From 67ba0cde5b003a2e39f60d5c6759ba665121ac48 Mon Sep 17 00:00:00 2001 From: Joachim Stolberg Date: Fri, 11 Dec 2020 18:07:29 +0100 Subject: [PATCH] built on 11/12/2020 18:07:29 --- autobahn/init.lua | 25 +- basic_materials/locale/basic_materials.de.tr | 26 +- minecart/README.md | 2 +- minecart/buffer.lua | 12 +- minecart/cart_lib1.lua | 415 +++--- minecart/cart_lib3.lua | 3 +- minecart/init.lua | 6 +- minecart/lib.lua | 25 + minecart/monitoring.lua | 23 +- ta4_jetpack/README.md | 2 +- ta4_jetpack/init.lua | 26 +- ta4_jetpack/locale/ta4_jetpack.de.tr | 9 +- ta4_jetpack/locale/template.txt | 10 +- ta4_jetpack/manual_DE.lua | 2 +- ta4_jetpack/manual_DE.md | 2 +- ta4_jetpack/manual_EN.lua | 2 +- ta4_jetpack/manual_EN.md | 2 +- ta4_jetpack/settingtypes.txt | 2 +- techage/COPYING.txt | 28 - techage/README.md | 8 + techage/basic_machines/chest.lua | 44 +- techage/basic_machines/consumer.lua | 5 +- techage/basic_machines/source.lua | 2 +- techage/basic_machines/ta4_chest.lua | 345 ++--- techage/basis/command.lua | 31 +- techage/basis/lib.lua | 18 +- techage/basis/liquid_lib.lua | 33 +- techage/basis/mark.lua | 3 + techage/basis/mark2.lua | 2 +- techage/basis/networks.lua | 2 +- techage/basis/windturbine_lib.lua | 5 +- techage/carts/tank_cart.lua | 10 + techage/chemistry/ta4_doser.lua | 4 +- techage/coal_power_station/generator.lua | 2 +- techage/digtron/battery.lua | 2 +- techage/doc/items.lua | 2 + techage/doc/manual_DE.lua | 53 +- techage/doc/manual_EN.lua | 44 +- techage/doc/plans.lua | 2 +- techage/energy_storage/generator.lua | 2 +- techage/energy_storage/heatexchanger2.lua | 4 +- techage/furnace/cooking.lua | 2 +- techage/furnace/furnace_top.lua | 7 +- techage/hydrogen/electrolyzer.lua | 21 +- techage/hydrogen/fuelcell.lua | 2 +- techage/i18n.py | 483 +++++- techage/icta_controller/controller.lua | 10 +- techage/icta_controller/display.lua | 48 +- techage/init.lua | 4 +- techage/iron_age/coalburner.lua | 4 + techage/items/cracking.lua | 6 +- techage/lamps/growlight.lua | 9 +- techage/liquids/tank.lua | 8 + techage/locale/techage.de.tr | 1305 ++++++++++++----- techage/locale/template.txt | 1303 +++++++++++----- techage/logic/sequencer.lua | 15 +- techage/logic/terminal.lua | 100 +- techage/lua_controller/controller.lua | 12 +- techage/lua_controller/server.lua | 7 +- techage/lua_controller/terminal.lua | 21 +- techage/manuals/manual_ta2_DE.md | 13 + techage/manuals/manual_ta2_EN.md | 14 + techage/manuals/manual_ta3_DE.md | 23 +- techage/manuals/manual_ta3_EN.md | 16 +- techage/manuals/manual_ta4_DE.md | 17 +- techage/manuals/manual_ta4_EN.md | 19 +- techage/manuals/markdown2formspec.py | 2 +- techage/manuals/ta4_lua_controller_EN.md | 49 +- techage/manuals/ta4_lua_controller_EN.pdf | Bin 356709 -> 354267 bytes techage/manuals/toc_DE.md | 29 +- techage/manuals/toc_EN.md | 2 + techage/power/distribution.lua | 8 +- techage/power/formspecs.lua | 17 +- techage/power/node_api.lua | 30 + techage/power/power_terminal.lua | 8 +- techage/power/power_terminal2.lua | 2 + techage/solar/inverter.lua | 4 +- techage/steam_engine/flywheel.lua | 2 +- techage/ta3_power/akkubox.lua | 2 +- techage/ta3_power/axle2power.lua | 236 +++ techage/ta3_power/power2axle.lua | 245 ++++ techage/ta3_power/tiny_generator.lua | 2 +- .../textures/techage_appl_generator_red.png | Bin 0 -> 2673 bytes .../textures/techage_appl_generator_red4.png | Bin 0 -> 5430 bytes techage/tools/repairkit.lua | 5 + techage/wind_turbine/rotor.lua | 41 +- tubelib2/tube_api.lua | 2 +- 87 files changed, 3820 insertions(+), 1580 deletions(-) delete mode 100644 techage/COPYING.txt create mode 100644 techage/ta3_power/axle2power.lua create mode 100644 techage/ta3_power/power2axle.lua create mode 100644 techage/textures/techage_appl_generator_red.png create mode 100644 techage/textures/techage_appl_generator_red4.png diff --git a/autobahn/init.lua b/autobahn/init.lua index 9378b57..5083365 100644 --- a/autobahn/init.lua +++ b/autobahn/init.lua @@ -92,24 +92,24 @@ minetest.register_on_respawnplayer(function(player) end end) -local function control_player(player) - local player_name = player:get_player_name() +local function control_player(player_name) if Currently_left_the_game[player_name] then Currently_left_the_game[player_name] = nil return end + local player = minetest.get_player_by_name(player_name) if player then local pos = player:get_pos() if pos then --pos.y = math.floor(pos.y) local node = minetest.get_node(pos) if string.sub(node.name,1,13) == "autobahn:node" then - minetest.after(0.5, control_player, player) + minetest.after(0.5, control_player, player_name) else pos.y = pos.y - 1 node = minetest.get_node(pos) if string.sub(node.name,1,13) == "autobahn:node" then - minetest.after(0.5, control_player, player) + minetest.after(0.5, control_player, player_name) else reset_player_privs(player) end @@ -125,11 +125,13 @@ local NodeTbl1 = { ["autobahn:node3"] = true, ["autobahn:node4"] = true, ["autobahn:node5"] = true, + ["autobahn:node6"] = true, ["autobahn:node12"] = true, ["autobahn:node22"] = true, ["autobahn:node32"] = true, ["autobahn:node42"] = true, ["autobahn:node52"] = true, + ["autobahn:node62"] = true, } local NodeTbl2 = { ["autobahn:node11"] = true, @@ -137,6 +139,7 @@ local NodeTbl2 = { ["autobahn:node31"] = true, ["autobahn:node41"] = true, ["autobahn:node51"] = true, + ["autobahn:node61"] = true, } local NodeTbl3 = { ["autobahn:node1"] = true, @@ -144,6 +147,7 @@ local NodeTbl3 = { ["autobahn:node3"] = true, ["autobahn:node4"] = true, ["autobahn:node5"] = true, + ["autobahn:node6"] = true, } -- 1) _o_ @@ -227,7 +231,9 @@ local function register_node(name, tiles, drawtype, mesh, box, drop) sunlight_propagates = true, sounds = default.node_sound_stone_defaults(), is_ground_content = false, - groups = {cracky=2, crumbly=2, not_in_creative_inventory=(mesh==nil) and 0 or 1}, + groups = {cracky=2, crumbly=2, + fall_damage_add_percent = -80, + not_in_creative_inventory=(mesh==nil) and 0 or 1}, drop = "autobahn:"..drop, after_place_node = function(pos, placer, itemstack, pointed_thing) @@ -239,7 +245,8 @@ local function register_node(name, tiles, drawtype, mesh, box, drop) reset_player_privs(clicker) else set_player_privs(clicker) - minetest.after(0.5, control_player, clicker) + local player_name = clicker:get_player_name() + minetest.after(0.5, control_player, player_name) end end, }) @@ -277,12 +284,14 @@ local Nodes = { {name="node31", tiles={"autobahn3.png","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp1.obj", box=sb1, drop="node3"}, {name="node41", tiles={"autobahn2.png^[transformR180]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp1.obj", box=sb1, drop="node4"}, {name="node51", tiles={"autobahn4.png^[transformR90]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp1.obj", box=sb1, drop="node5"}, + {name="node61", tiles={"autobahn5.png^[transformR90]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp1.obj", box=sb1, drop="node6"}, {name="node12", tiles={"autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node1"}, {name="node22", tiles={"autobahn2.png","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node2"}, {name="node32", tiles={"autobahn3.png","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node3"}, {name="node42", tiles={"autobahn2.png^[transformR180]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node4"}, {name="node52", tiles={"autobahn4.png^[transformR90]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node5"}, + {name="node62", tiles={"autobahn5.png^[transformR90]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node6"}, } for _,item in ipairs(Nodes) do @@ -405,10 +414,14 @@ if minetest.global_exists("minecart") then minecart.register_protected_node("autobahn:node21") minecart.register_protected_node("autobahn:node31") minecart.register_protected_node("autobahn:node41") + minecart.register_protected_node("autobahn:node51") + minecart.register_protected_node("autobahn:node61") minecart.register_protected_node("autobahn:node12") minecart.register_protected_node("autobahn:node22") minecart.register_protected_node("autobahn:node32") minecart.register_protected_node("autobahn:node42") + minecart.register_protected_node("autobahn:node52") + minecart.register_protected_node("autobahn:node62") end diff --git a/basic_materials/locale/basic_materials.de.tr b/basic_materials/locale/basic_materials.de.tr index e661fcd..8fddd8a 100644 --- a/basic_materials/locale/basic_materials.de.tr +++ b/basic_materials/locale/basic_materials.de.tr @@ -1,9 +1,9 @@ # textdomain: basic_materials -Silicon lump=Silikonklumpen -Simple Integrated Circuit=einfacher Integrierter Schaltkreis -Simple Motor=einfacher Motor +Silicon lump=Siliziumklumpen +Simple Integrated Circuit=Einfacher Integrierter Schaltkreis +Simple Motor=Einfacher Motor Heating element=Heizelement -Simple energy crystal=einfacher Energiekristall +Simple energy crystal=Einfacher Energiekristall Spool of steel wire=Spule mit Stahldraht Spool of copper wire=Spule mit Kupferdraht @@ -12,22 +12,22 @@ Spool of gold wire=Spule mit Golddraht Steel Strip=Stahlstreifen Copper Strip=Kupferstreifen Steel Bar=Stahlstab -Chainlinks (brass)=Messing-Kettenglieder -Chainlinks (steel)=Stahl-Kettenglieder +Chainlinks (brass)=Messingkettenglieder +Chainlinks (steel)=Stahlkettenglieder Brass Ingot=Messingbarren Steel gear=Stahlzahnrad Padlock=Vorhängeschloss -Chain (steel, hanging)=Stahlkette -Chain (brass, hanging)=Messingkette +Chain (steel, hanging)=Hängende Stahlkette +Chain (brass, hanging)=Hängende Messingkette Brass Block=Messingblock -Oil extract=raffiniertes Öl -Unprocessed paraffin=unbearbeitetes Paraffin -Uncooked Terracotta Base=ungebranntes Terrakotta -Wet Cement=nasser Zement +Oil extract=Ölextrakt +Unprocessed paraffin=Unverarbeitetes Paraffin +Uncooked Terracotta Base=Ungebranntes Terrakotta +Wet Cement=Nasser Zement Cement=Zement Concrete Block=Betonblock Plastic sheet=Kunststoffplatte Plastic strips=Kunststoffstreifen -Empty wire spool=leere Drahtspule +Empty wire spool=Leere Drahtspule diff --git a/minecart/README.md b/minecart/README.md index b2f440b..27a267c 100644 --- a/minecart/README.md +++ b/minecart/README.md @@ -117,4 +117,4 @@ History 2020-06-27 v1.07 Route storage and cart command bugfixes 2020-07-24 V1.08 Adapted to new techage ICTA style 2020-08-14 V1.09 Hopper support for digtron, protector:chest and default:furnace added - +2020-11-12 V1.10 Make carts more robust against server lag diff --git a/minecart/buffer.lua b/minecart/buffer.lua index 536114b..89e642b 100644 --- a/minecart/buffer.lua +++ b/minecart/buffer.lua @@ -53,8 +53,18 @@ local function on_punch(pos, node, puncher) if not minecart.teleport_enabled then return end local route = minecart.get_route(P2S(pos)) if route and route.dest_pos and puncher and puncher:is_player() then + + -- only teleport if the user is not pressing shift if not puncher:get_player_control()['sneak'] then - puncher:set_pos(S2P(route.dest_pos)) + local playername = puncher:get_player_name() + local pos = S2P(route.dest_pos) + + local teleport = function() + -- Make sure the player object still exists + local player = minetest.get_player_by_name(playername) + if player and pos then player:set_pos(pos) end + end + minetest.after(0.25, teleport) end end end diff --git a/minecart/cart_lib1.lua b/minecart/cart_lib1.lua index 92f3c76..afde093 100644 --- a/minecart/cart_lib1.lua +++ b/minecart/cart_lib1.lua @@ -17,6 +17,12 @@ -- 2) Only the owner can start the recording -- 3) But any player can act as cargo, cart punched by owner or buffer +local SLOPE_ACCELERATION = 3 +local MAX_SPEED = 7 +local PUNCH_SPEED = 3 +local SLOWDOWN = 0.4 +local RAILTYPE = minetest.get_item_group("carts:rail", "connect_to_raillike") +local Y_OFFS_ON_SLOPES = 0.5 -- for lazy programmers local M = minetest.get_meta @@ -24,6 +30,83 @@ local S = minecart.S local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end local S2P = minetest.string_to_pos local MP = minetest.get_modpath("minecart") +local D = function(pos) return minetest.pos_to_string(vector.round(pos)) end + +local tRails = { + ["carts:rail"] = true, + ["carts:powerrail"] = true, + ["carts:brakerail"] = true, +} + +local lRails = {"carts:rail", "carts:powerrail", "carts:brakerail"} + +local function get_rail_node(pos) + local rail_pos = vector.round(pos) + local node = minecart.get_node_lvm(rail_pos) + if tRails[node.name] then + return rail_pos, node + end +end + +local function find_rail_node(pos) + local rail_pos = vector.round(pos) + local node = get_rail_node(rail_pos) + if node then + return rail_pos, node + end + local pos1 = {x=rail_pos.x-1, y=rail_pos.y-1, z=rail_pos.z-1} + local pos2 = {x=rail_pos.x+1, y=rail_pos.y+1, z=rail_pos.z+1} + for _,pos3 in ipairs(minetest.find_nodes_in_area(pos1, pos2, lRails)) do + --print("invalid position1", D(pos), D(pos3)) + return pos3, minecart.get_node_lvm(pos3) + end + --print("invalid position2", D(pos)) +end + +local function get_pitch(dir) + local pitch = 0 + if dir.y == -1 then + pitch = -math.pi/4 + elseif dir.y == 1 then + pitch = math.pi/4 + end + return pitch * (dir.z == 0 and -1 or 1) +end + +local function get_yaw(dir) + local yaw = 0 + if dir.x < 0 then + yaw = math.pi/2*3 + elseif dir.x > 0 then + yaw = math.pi/2 + elseif dir.z < 0 then + yaw = math.pi + end + return yaw +end + +local function push_cart(self, pos, punch_dir, puncher) + local vel = self.object:get_velocity() + punch_dir = punch_dir or carts:velocity_to_dir(puncher:get_look_dir()) + punch_dir.y = 0 + local cart_dir = carts:get_rail_direction(pos, punch_dir, nil, nil, RAILTYPE) + + -- Always start in horizontal direction + cart_dir.y = 0 + + if vector.equals(cart_dir, {x=0, y=0, z=0}) then return end + + local speed = vector.multiply(cart_dir, PUNCH_SPEED) + local new_vel = vector.add(vel, speed) + local yaw = get_yaw(cart_dir) + local pitch = get_pitch(cart_dir) + + self.object:set_rotation({x = pitch, y = yaw, z = 0}) + self.object:set_velocity(new_vel) + + self.old_pos = vector.round(pos) + self.stopped = false +end local api = {} @@ -94,31 +177,20 @@ function api:on_punch(puncher, time_from_last_punch, tool_capabilities, directio return end - -- running carts can't be punched or removed from external - if not stopped then - return - end - -- Punched by non-authorized player if puncher_name and not puncher_is_owner then minetest.chat_send_player(puncher_name, S("[minecart] Cart is protected by ")..(self.owner or "")) return end - if not self.railtype then - local node = minetest.get_node(pos).name - self.railtype = minetest.get_item_group(node, "connect_to_raillike") - end - -- Punched by non-player if not puncher_name then - local cart_dir = carts:get_rail_direction(pos, direction, nil, nil, self.railtype) + local cart_dir = carts:get_rail_direction(pos, direction, nil, nil, RAILTYPE) if vector.equals(cart_dir, {x=0, y=0, z=0}) then return end - self.velocity = vector.multiply(cart_dir, 2) - self.punched = true api.load_cargo(self, pos) + push_cart(self, pos, cart_dir) minecart.start_cart(pos, self.myID) return end @@ -131,7 +203,7 @@ function api:on_punch(puncher, time_from_last_punch, tool_capabilities, directio end -- detach driver if self.driver then - carts:manage_attachment(puncher_name, nil) + carts:manage_attachment(puncher, nil) end -- Pick up cart api.remove_cart(self, pos, puncher) @@ -147,23 +219,7 @@ function api:on_punch(puncher, time_from_last_punch, tool_capabilities, directio api.load_cargo(self, pos) - -- Normal punch by owner to start the cart - local punch_dir = carts:velocity_to_dir(puncher:get_look_dir()) - punch_dir.y = 0 - local cart_dir = carts:get_rail_direction(pos, punch_dir, nil, nil, self.railtype) - if vector.equals(cart_dir, {x=0, y=0, z=0}) then - return - end - - self.velocity = vector.multiply(cart_dir, 2) - self.old_dir = cart_dir - self.punched = true -end - -local function rail_on_step_event(handler, obj, dtime) - if handler then - handler(obj, dtime) - end + push_cart(self, pos, nil, puncher) end -- sound refresh interval = 1.0sec @@ -193,224 +249,149 @@ local function rail_sound(self, dtime) end end -local function get_railparams(pos) - local node = minetest.get_node(pos) - return carts.railparams[node.name] or {} -end - -local v3_len = vector.length -local function rail_on_step(self, dtime) - local vel = self.object:get_velocity() +local function rail_on_step(self) + -- Check if same position as before local pos = self.object:get_pos() local rot = self.object:get_rotation() - local stopped = minecart.stopped(vel) and rot.x == 0 + local on_slope = rot.x ~= 0 + --print("rail_on_step_new", P2S(pos), rot.x) + + -- cart position correction on slopes + if on_slope then + pos.y = pos.y - Y_OFFS_ON_SLOPES + end + + -- Used as fallback position + self.old_pos = self.old_pos or pos + local pos_rounded = vector.round(pos) + -- Same pos as before + if vector.equals(pos_rounded, self.old_pos) then + return -- nothing todo + end + + -- Check if stopped + local vel = self.object:get_velocity() + local stopped = not on_slope and minecart.stopped(vel) local is_minecart = self.node_name == nil local recording = is_minecart and self.driver == self.owner - -- cart position correction on slopes - if rot.x ~= 0 then - pos.y = pos.y - 0.5 + if stopped then + if not self.stopped then + local param2 = minetest.dir_to_facedir(self.old_dir) + api.stop_cart(pos, self, self.node_name or "minecart:cart", param2) + if recording then + minecart.stop_recording(self, pos_rounded, vel, self.driver) + end + api.unload_cargo(self, pos) + self.stopped = true + end + self.old_pos = pos_rounded + return -- nothing todo end - if self.punched then - vel = vector.add(vel, self.velocity) - self.object:set_velocity(vel) - self.old_dir.y = 0 - self.stopped = false - elseif stopped and not self.stopped then - local param2 = minetest.dir_to_facedir(self.old_dir) - api.stop_cart(pos, self, self.node_name or "minecart:cart", param2) - if recording then - minecart.stop_recording(self, pos, vel, self.driver) + -- Check if invalid position (not on rail anymore) + local rail_pos, node = get_rail_node(pos) + if not node then + rail_pos, node = find_rail_node(self.old_pos) + if rail_pos then + pos_rounded = rail_pos + if on_slope then + self.object:set_pos({x=rail_pos.x, y=rail_pos.y + Y_OFFS_ON_SLOPES, z=rail_pos.z}) + else + self.object:set_pos(rail_pos) + end + else + self.object:set_pos(pos) + minetest.log("error", "[minecart] No valid position "..(P2S(pos) or "nil")) + return -- no valid position end - api.unload_cargo(self, pos) - self.stopped = true - self.object:set_velocity({x=0, y=0, z=0}) - self.object:set_acceleration({x=0, y=0, z=0}) - return - elseif stopped then - return end - if recording then - minecart.store_next_waypoint(self, pos, vel) + -- Calc speed (value) + local speed = math.sqrt((vel.x+vel.z)^2 + vel.y^2) + -- Check if slope position + if pos_rounded.y > self.old_pos.y then + speed = speed - SLOPE_ACCELERATION + elseif pos_rounded.y < self.old_pos.y then + speed = speed + SLOPE_ACCELERATION + else + speed = speed - SLOWDOWN end - - local cart_dir = carts:velocity_to_dir(vel) - local same_dir = vector.equals(cart_dir, self.old_dir) - local update = {} - - if self.old_pos and not self.punched and same_dir then - local flo_pos = vector.round(pos) - local flo_old = vector.round(self.old_pos) - if vector.equals(flo_pos, flo_old) then - -- Do not check one node multiple times - return + -- Add power/brake rail acceleration + local acc = (carts.railparams[node.name] or {}).acceleration or 0 + speed = speed + acc + + -- Determine new direction + local dir = carts:velocity_to_dir(vel) + if speed < 0 then + if on_slope then + dir = vector.multiply(dir, -1) + -- start with a value > 0 + speed = 0.5 + else + speed = 0 end end - - local ctrl, player - + -- Get player controls + local ctrl, player if recording then player = minetest.get_player_by_name(self.driver) if player then ctrl = player:get_player_control() end - end - - local railparams + end + + -- new_dir: New moving direction of the cart + -- keys: Currently pressed L/R key, used to ignore the key on the next rail node + local new_dir, keys = carts:get_rail_direction(rail_pos, dir, ctrl, self.old_keys, RAILTYPE) - -- dir: New moving direction of the cart - -- switch_keys: Currently pressed L/R key, used to ignore the key on the next rail node - local dir, switch_keys = carts:get_rail_direction( - pos, cart_dir, ctrl, self.old_switch, self.railtype - ) - -- handle junctions - if switch_keys then -- recording - minecart.set_junction(self, pos, dir, switch_keys) + if recording and keys then + minecart.set_junction(self, rail_pos, new_dir, keys) else -- normal run - dir, switch_keys = minecart.get_junction(self, pos, dir) + new_dir, keys = minecart.get_junction(self, rail_pos, new_dir) end + self.old_keys = keys - local dir_changed = not vector.equals(dir, self.old_dir) - - local new_acc = {x=0, y=0, z=0} - if vector.equals(dir, {x=0, y=0, z=0}) then - vel = {x = 0, y = 0, z = 0} - local pos_r = vector.round(pos) - if not carts:is_rail(pos_r, self.railtype) - and self.old_pos then - pos = self.old_pos - else - pos = pos_r - end - update.pos = true - update.vel = true - else - -- Direction change detected - if dir_changed then - vel = vector.multiply(dir, math.abs(vel.x + vel.z)) - update.vel = true - if dir.y ~= self.old_dir.y then - pos = vector.round(pos) - update.pos = true - end - end - -- Center on the rail - if dir.z ~= 0 and math.floor(pos.x + 0.5) ~= pos.x then - pos.x = math.floor(pos.x + 0.5) - update.pos = true - end - if dir.x ~= 0 and math.floor(pos.z + 0.5) ~= pos.z then - pos.z = math.floor(pos.z + 0.5) - update.pos = true - end - - -- Slow down or speed up.. - local acc = dir.y * -1.5 - - -- Get rail for corrected position - railparams = get_railparams(pos) - - -- no need to check for railparams == nil since we always make it exist. - local speed_mod = railparams.acceleration - if speed_mod and speed_mod ~= 0 then - -- Try to make it similar to the original carts mod - acc = acc + speed_mod - else - acc = acc - 0.4 - end - - new_acc = vector.multiply(dir, acc) - end - - -- Limits - local max_vel = carts.speed_max - for _, v in pairs({"x","y","z"}) do - if math.abs(vel[v]) > max_vel then - vel[v] = carts:get_sign(vel[v]) * max_vel - new_acc[v] = 0 - update.vel = true - end - end - - self.object:set_acceleration(new_acc) - self.old_pos = vector.round(pos) - if not vector.equals(dir, {x=0, y=0, z=0}) then - self.old_dir = vector.new(dir) - end - self.old_switch = switch_keys - - if self.punched then - self.punched = false - update.vel = true - end - - railparams = railparams or get_railparams(pos) - - if not (update.vel or update.pos) then - rail_on_step_event(railparams.on_step, self, dtime) + -- Detect U-turn + if (dir.x ~= 0 and dir.x == -new_dir.x) or (dir.z ~= 0 and dir.z == -new_dir.z) then + -- Stop the cart + self.object:set_velocity({x=0, y=0, z=0}) + self.object:move_to(pos_rounded) return - end - - local yaw = 0 - if self.old_dir.x < 0 then - yaw = math.pi/2*3 - elseif self.old_dir.x > 0 then - yaw = math.pi/2 - elseif self.old_dir.z < 0 then - yaw = math.pi - end - --self.object:set_yaw(yaw * math.pi) - - local pitch = 0 - if self.old_dir.z ~= 0 then - if dir.y == -1 then - pitch = -math.pi/4 - elseif dir.y == 1 then - pitch = math.pi/4 - end - else - if dir.y == -1 then - pitch = math.pi/4 - elseif dir.y == 1 then - pitch = -math.pi/4 - end - end - self.object:set_rotation({x = pitch, y = yaw, z = 0}) - - -- cart position correction on slopes - if pitch ~= 0 then - pos.y = pos.y + 0.5 - update.pos = true - vel = vector.divide(vel, 2) - update.vel = true - elseif self.old_pitch ~= 0 then - vel = vector.multiply(vel, 2) - update.vel = true - end - self.old_pitch = pitch - - if update.vel then - self.object:set_velocity(vel) - end - if update.pos then - if dir_changed then - self.object:set_pos(pos) + -- New direction + elseif not vector.equals(dir, new_dir) then + if new_dir.y ~= 0 then + self.object:set_pos({x=pos_rounded.x, y=pos_rounded.y + Y_OFFS_ON_SLOPES, z=pos_rounded.z}) else - self.object:move_to(pos) + self.object:set_pos(pos_rounded) end end + + -- Set velocity and rotation + local new_vel = vector.multiply(new_dir, math.min(speed, MAX_SPEED)) + local yaw = get_yaw(new_dir) + local pitch = get_pitch(new_dir) - -- call event handler - rail_on_step_event(railparams.on_step, self, dtime) + self.object:set_rotation({x = pitch, y = yaw, z = 0}) + self.object:set_velocity(new_vel) + + + if recording then + minecart.store_next_waypoint(self, rail_pos, vel) + end + + self.old_pos = pos_rounded end function api:on_step(dtime) - rail_on_step(self, dtime) - rail_sound(self, dtime) + self.delay = (self.delay or 0) + dtime + if self.delay > 0.09 then + rail_on_step(self) + rail_sound(self, self.delay) + self.delay = 0 + end end return api diff --git a/minecart/cart_lib3.lua b/minecart/cart_lib3.lua index d1686e0..6cecc9c 100644 --- a/minecart/cart_lib3.lua +++ b/minecart/cart_lib3.lua @@ -49,7 +49,7 @@ function api.get_station_name(pos) end end -function api.load_cart(pos, vel, item) +function api.load_cart(pos, vel, pitch, yaw, item) -- Add cart to map local obj = minetest.add_entity(pos, item.entity_name or "minecart:cart", nil) -- Determine ID @@ -67,6 +67,7 @@ function api.load_cart(pos, vel, item) item.cargo = nil -- Start cart obj:set_velocity(vel) + obj:set_rotation({x = pitch or 0, y = yaw or 0, z = 0}) return myID else print("Entity has no ID") diff --git a/minecart/init.lua b/minecart/init.lua index eda148b..c484085 100644 --- a/minecart/init.lua +++ b/minecart/init.lua @@ -13,12 +13,10 @@ minecart = {} -- Version for compatibility checks, see readme.md/history -minecart.version = 1.09 +minecart.version = 1.10 minecart.hopper_enabled = minetest.settings:get_bool("minecart_hopper_enabled") ~= false -minecart.teleport_enabled = minetest.settings:get_bool("minecart_teleport_enabled") ~= false - -print("minecart_hopper_enabled", dump(minetest.settings:get_bool("minecart_hopper_enabled"))) +minecart.teleport_enabled = minetest.settings:get_bool("minecart_teleport_enabled") == true minecart.S = minetest.get_translator("minecart") local MP = minetest.get_modpath("minecart") diff --git a/minecart/lib.lua b/minecart/lib.lua index d261e57..9d78e51 100644 --- a/minecart/lib.lua +++ b/minecart/lib.lua @@ -51,6 +51,24 @@ function minecart.register_cart_names(cart_name_stopped, cart_name_running) end end +function minecart.get_node_lvm(pos) + local node = minetest.get_node_or_nil(pos) + if node then + return node + end + local vm = minetest.get_voxel_manip() + local MinEdge, MaxEdge = vm:read_from_map(pos, pos) + local data = vm:get_data() + local param2_data = vm:get_param2_data() + local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge}) + local idx = area:indexp(pos) + node = { + name = minetest.get_name_from_content_id(data[idx]), + param2 = param2_data[idx] + } + return node +end + function minecart.stopped(vel, tolerance) tolerance = tolerance or 0.05 return math.abs(vel.x) < tolerance and math.abs(vel.z) < tolerance @@ -64,6 +82,13 @@ local function is_air_like(name) return false end +function minecart.range(val, min, max) + val = tonumber(val) + if val < min then return min end + if val > max then return max end + return val +end + function minecart.get_next_node(pos, param2) local pos2 = param2 and vector.add(pos, param2_to_dir[param2]) or pos local node = minetest.get_node(pos2) diff --git a/minecart/monitoring.lua b/minecart/monitoring.lua index 5f6f3fd..daeb2e4 100644 --- a/minecart/monitoring.lua +++ b/minecart/monitoring.lua @@ -33,26 +33,26 @@ local NodesAtStation = {} -- -- Helper functions -- -local function calc_pos_and_vel(item) +local function get_pos_vel_pitch_yaw(item) if item.start_time and item.start_key then -- cart on recorded route local run_time = minetest.get_gametime() - item.start_time local waypoints = get_route(item.start_key).waypoints local waypoint = waypoints[run_time] if waypoint then - return S2P(waypoint[1]), S2P(waypoint[2]) + return S2P(waypoint[1]), S2P(waypoint[2]), 0, 0 end end if item.last_pos then item.last_pos = vector.round(item.last_pos) if carts:is_rail(item.last_pos, minetest.raillike_group("rail")) then - return item.last_pos, item.last_vel + return item.last_pos, item.last_vel, item.last_pitch or 0, item.last_yaw or 0 end item.last_pos.y = item.last_pos.y - 1 if carts:is_rail(item.last_pos, minetest.raillike_group("rail")) then - return item.last_pos, item.last_vel + return item.last_pos, item.last_vel, item.last_pitch or 0, item.last_yaw or 0 end end - return item.start_pos, {x=0, y=0, z=0} + return item.start_pos, {x=0, y=0, z=0}, 0, 0 end -- @@ -132,24 +132,29 @@ local function monitoring() if entity then -- cart entity running local pos = entity.object:get_pos() local vel = entity.object:get_velocity() + local rot = entity.object:get_rotation() if not minetest.get_node_or_nil(pos) then -- unloaded area lib.unload_cart(pos, vel, entity, item) item.stopped = minecart.stopped(vel) end -- store last pos from cart - item.last_pos, item.last_vel = pos, vel + item.last_pos, item.last_vel, item.last_pitch, item.last_yaw = pos, vel, rot.x, rot.y + else -- no cart running - local pos, vel = calc_pos_and_vel(item) + local pos, vel, pitch, yaw = get_pos_vel_pitch_yaw(item) if pos and vel then if minetest.get_node_or_nil(pos) then -- loaded area - local myID = lib.load_cart(pos, vel, item) + if pitch > 0 then + pos.y = pos.y + 0.5 + end + local myID = lib.load_cart(pos, vel, pitch, yaw, item) if myID then item.stopped = minecart.stopped(vel) to_be_added[myID] = table.copy(item) CartsOnRail[key] = nil -- invalid old ID end end - item.last_pos, item.last_vel = pos, vel + item.last_pos, item.last_vel, item.last_pitch, item.last_yaw = pos, vel, pitch, yaw else -- should never happen minetest.log("error", "[minecart] Cart of owner "..(item.owner or "nil").." got lost") diff --git a/ta4_jetpack/README.md b/ta4_jetpack/README.md index ecfc630..6ebee88 100644 --- a/ta4_jetpack/README.md +++ b/ta4_jetpack/README.md @@ -19,7 +19,7 @@ Instructions: Important to know: - 12 units of hydrogen are sufficient for a flight of 6 minutes -- Maximum 5 items stacks in your inventory are allowed including the controller. +- Maximum of 99 items in your inventory are allowed including the controller. Otherwise you would be too heavy :-) - The Jetpack also wears out and can be used for approximately 10 flights - Always hold the controller tight during the flight, otherwise it will switch off :) diff --git a/ta4_jetpack/init.lua b/ta4_jetpack/init.lua index bd265c3..4d4d3c3 100644 --- a/ta4_jetpack/init.lua +++ b/ta4_jetpack/init.lua @@ -13,13 +13,16 @@ -- Load support for I18n. local S = minetest.get_translator("ta4_jetpack") +local ta4_jetpack = {} + local Players = {} local Jetpacks = {} +local ItemsBlocklist = {} local MAX_HEIGHT = tonumber(minetest.settings:get("ta4_jetpack_max_height")) or 500 local MAX_VSPEED = tonumber(minetest.settings:get("ta4_jetpack_max_vertical_speed")) or 20 local MAX_HSPEED = (tonumber(minetest.settings:get("ta4_jetpack_max_horizontal_speed")) or 12) / 4 -local MAX_NUM_INV_ITEMS = tonumber(minetest.settings:get("ta4_jetpack_max_num_inv_items")) or 5 +local MAX_NUM_INV_ITEMS = tonumber(minetest.settings:get("ta4_jetpack_max_num_inv_items")) or 99 -- Flight time maximum 6 min or 360 s or 3600 steps. -- 12 units hydrogen for 3600 steps means 0.0033 units hydrogen / step. @@ -31,6 +34,11 @@ local STEPS_TO_FUEL = 0.0033 local WEAR_VALUE = 180 -- roughly 10 flys, 6 min each +-- API function to register items that are forbidden in inventory during flight. +ta4_jetpack.register_forbidden_item = function(itemname) + ItemsBlocklist[itemname] = true +end + local function store_player_physics(player) local meta = player:get_meta() -- Check access conflicts with other mods @@ -143,19 +151,22 @@ local function check_player_load(player) local bags_meta = meta:get_string("unified_inventory:bags") if bags_meta then if next(minetest.deserialize(bags_meta) or {}) then - return S("check your bags!") + return S("You are too heavy: Check your bags!") end end for _, stack in ipairs(inv:get_list("craft") or {}) do if not stack:is_empty() then - return S("check your carfting menu!") + return S("You are too heavy: Check your crafting menu!") end end local count = 0 for _, stack in ipairs(inv:get_list("main") or {}) do - count = count + (stack:is_empty() and 0 or 1) + count = count + stack:get_count() if count > MAX_NUM_INV_ITEMS then - return S("check your inventory!") + return S("You are too heavy: Check your inventory!") + end + if ItemsBlocklist[stack:get_name()] then + return S("You may not transport @1 with a jetpack!", stack:get_description()) end end end @@ -349,7 +360,7 @@ local function turn_controller_on_off(itemstack, user) -- check inventory load local res = check_player_load(user) if res then - minetest.chat_send_player(name, S("[Jetpack] You are too heavy: ")..res) + minetest.chat_send_player(name, S("[Jetpack]").." "..res) return itemstack end -- check fuel @@ -533,3 +544,6 @@ techage.add_manual_items({ ta4_jetpack = "ta4_jetpack.png", ta4_jetpack_controller = 'ta4_jetpack_controller_inv.png'}) +ta4_jetpack.register_forbidden_item("techage:cylinder_large_hydrogen") +ta4_jetpack.register_forbidden_item("techage:cylinder_small_hydrogen") +ta4_jetpack.register_forbidden_item("techage:hydrogen") diff --git a/ta4_jetpack/locale/ta4_jetpack.de.tr b/ta4_jetpack/locale/ta4_jetpack.de.tr index 7a5b4f3..b3ba944 100644 --- a/ta4_jetpack/locale/ta4_jetpack.de.tr +++ b/ta4_jetpack/locale/ta4_jetpack.de.tr @@ -5,10 +5,11 @@ TA4 Jetpack=TA4 Jetpac TA4 Jetpack Controller Off=TA4 Jetpack Controller Aus TA4 Jetpack Controller On=TA4 Jetpack Controller An Use the controller (left click) to fill the tank with hydrogen=Benutze den Controller (linksklick) um den Tank mit Wasserstoff zu füllen -[Jetpack] You are too heavy: =[Jetpack] Du bist zu schwer: +You are too heavy: Check your bags!=Du bist zu schwer: Prüfe deine Rucksäcke! +You are too heavy: Check your crafting menu!=Du bist zu schwer: Prüfe dein Crafting Menü! +You are too heavy: Check your inventory!=Du bist zu schwer: Prüfe dein Inventar! +You may not transport @1 with a jetpack!=Du darfst @1 nicht mit dem Jetpack transportieren! +[Jetpack]=[Jetpack] [Jetpack] You don't have your jetpack on your back!=[Jetpack] Du hast dein Jetpack nicht auf dem Rücken! [Jetpack] Your tank is empty!=[Jetpack] Dein Tank ist leer! -check your bags!=Prüfe deine Rucksäcke! -check your carfting menu!=Prüfe dein Crafting Menü! -check your inventory!=Prüfe dein Inventar! ##### not used anymore ##### \ No newline at end of file diff --git a/ta4_jetpack/locale/template.txt b/ta4_jetpack/locale/template.txt index 7e34064..fce8a80 100644 --- a/ta4_jetpack/locale/template.txt +++ b/ta4_jetpack/locale/template.txt @@ -3,9 +3,11 @@ TA4 Jetpack= TA4 Jetpack Controller Off= TA4 Jetpack Controller On= Use the controller (left click) to fill the tank with hydrogen= -[Jetpack] You are too heavy: = +You are too heavy: Check your bags!= +You are too heavy: Check your crafting menu!= +You are too heavy: Check your inventory!= +You may not transport @1 with a jetpack!= +[Jetpack]= [Jetpack] You don't have your jetpack on your back!= [Jetpack] Your tank is empty!= -check your bags!= -check your carfting menu!= -check your inventory!= \ No newline at end of file +##### not used anymore ##### \ No newline at end of file diff --git a/ta4_jetpack/manual_DE.lua b/ta4_jetpack/manual_DE.lua index 1b2126e..806a1e0 100644 --- a/ta4_jetpack/manual_DE.lua +++ b/ta4_jetpack/manual_DE.lua @@ -17,7 +17,7 @@ techage.add_to_manual('DE', { "\n".. "\n", " - 12 Einheiten Wasserstoff reichen für einen Flug von 6 Minuten\n".. - " - Maximal 5 Stapel von Gegenständen im Spieler-Inventar sind zulässig\\, einschließlich des Controllers\n(Sonst wärst du zu schwer :-)\n".. + " - Maximal 99 Gegenstände im Spieler-Inventar sind zulässig\\, einschließlich des Controllers\n(Sonst wärst du zu schwer :-)\n".. " - Das Jetpack nutzt sich ab und kann für ca. 10 Flüge verwendet werden\n".. " - Halte den Controller während des Fluges immer fest\\, sonst schaltet er sich aus :)\n".. "\n".. diff --git a/ta4_jetpack/manual_DE.md b/ta4_jetpack/manual_DE.md index b2b4ea5..7236eaa 100644 --- a/ta4_jetpack/manual_DE.md +++ b/ta4_jetpack/manual_DE.md @@ -21,7 +21,7 @@ Das Jetpack ist inspiriert vom Jetpack von spirit689 (https://github.com/spirit6 ## Was du wissen solltest - 12 Einheiten Wasserstoff reichen für einen Flug von 6 Minuten -- Maximal 5 Stapel von Gegenständen im Spieler-Inventar sind zulässig, einschließlich des Controllers +- Maximal 99 Gegenstände im Spieler-Inventar sind zulässig, einschließlich des Controllers (Sonst wärst du zu schwer :-) - Das Jetpack nutzt sich ab und kann für ca. 10 Flüge verwendet werden - Halte den Controller während des Fluges immer fest, sonst schaltet er sich aus :) diff --git a/ta4_jetpack/manual_EN.lua b/ta4_jetpack/manual_EN.lua index 19222ed..f0e1a54 100644 --- a/ta4_jetpack/manual_EN.lua +++ b/ta4_jetpack/manual_EN.lua @@ -18,7 +18,7 @@ techage.add_to_manual('EN', { "\n".. "\n", " - 12 units of hydrogen are sufficient for a flight of 6 minutes\n".. - " - Maximum 5 items stacks in your inventory are allowed including the controller.\nOtherwise you would be too heavy :-)\n".. + " - Maximum 99 items in your inventory are allowed including the controller.\nOtherwise you would be too heavy :-)\n".. " - The Jetpack also wears out and can be used for approximately 10 flights\n".. " - Always hold the controller tight during the flight\\, otherwise it will switch off :)\n".. "\n".. diff --git a/ta4_jetpack/manual_EN.md b/ta4_jetpack/manual_EN.md index 82cf6c8..d6dd57c 100644 --- a/ta4_jetpack/manual_EN.md +++ b/ta4_jetpack/manual_EN.md @@ -22,7 +22,7 @@ and by the historical game Lunar Lander. ## Important to know - 12 units of hydrogen are sufficient for a flight of 6 minutes -- Maximum 5 items stacks in your inventory are allowed including the controller. +- Maximum 99 items in your inventory are allowed including the controller. Otherwise you would be too heavy :-) - The Jetpack also wears out and can be used for approximately 10 flights - Always hold the controller tight during the flight, otherwise it will switch off :) diff --git a/ta4_jetpack/settingtypes.txt b/ta4_jetpack/settingtypes.txt index c1e8f15..cf2d42c 100644 --- a/ta4_jetpack/settingtypes.txt +++ b/ta4_jetpack/settingtypes.txt @@ -8,7 +8,7 @@ ta4_jetpack_max_vertical_speed (maximum vertical speed) int 20 ta4_jetpack_max_horizontal_speed (maximum horizontal speed) int 12 # Maximum number of inventory items a player can take -ta4_jetpack_max_num_inv_items (maximum number of inventory items) int 5 +ta4_jetpack_max_num_inv_items (maximum number of inventory items) int 99 diff --git a/techage/COPYING.txt b/techage/COPYING.txt deleted file mode 100644 index d3a4dba..0000000 --- a/techage/COPYING.txt +++ /dev/null @@ -1,28 +0,0 @@ -The Techage mod for Minetest is - -Copyright (C) 2019-2020 Joachim Stolberg - -License of source code ----------------------- - -This mod is free software; you can redistribute and/or -modify it under the terms of the GNU General Public License version 3 or later -published by the Free Software Foundation. - -This mod is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public -License along with this mod; if not, write to the -Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -Boston, MA 02110-1301, USA. - - -License of media (textures, sounds and documentation) ------------------------------------------------------ - -All textures, sounds and documentation files are licensed under the -Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) -http://creativecommons.org/licenses/by-sa/3.0/ diff --git a/techage/README.md b/techage/README.md index 84f3202..bcd12ac 100644 --- a/techage/README.md +++ b/techage/README.md @@ -77,6 +77,14 @@ Available worlds will be converted to 'lsqlite3', but there is no way back, so: ### History +**2020-11-01 V0.25** +- Pull request #37: Trowel: Add protection support (from Thomas-S) +- Pull request #38: Charcoal Pile: Ignore "ignore" nodes (from Thomas-S) +- Autocrafter: Add register function for uncraftable items +- Fix bug: Tubes do not recognize when TA2 nodes are added/removed +- TA4 chest/tank: Add 'public' checkbox to allow public access +- Add nodes TA2 Power Generator and TA3 Electric Motor + **2020-10-20 V0.24** - Pull request #27: Liquid Tanks: Add protection support (from Thomas-S) - Pull request #28: Quarry: Improve digging behaviour (from Thomas-S) diff --git a/techage/basic_machines/chest.lua b/techage/basic_machines/chest.lua index 11840ec..6d5837f 100644 --- a/techage/basic_machines/chest.lua +++ b/techage/basic_machines/chest.lua @@ -178,7 +178,7 @@ techage.register_node({"techage:chest_ta2", "techage:chest_ta3"}, { local function formspec4(pos) return "size[10,9]".. - "tabheader[0,0;tab;"..S("Inventory,Configuration")..";1;;true]".. + "tabheader[0,0;tab;"..S("Inventory,Pre-Assignment,Config")..";1;;true]".. default.gui_bg.. default.gui_bg_img.. default.gui_slots.. @@ -189,9 +189,9 @@ local function formspec4(pos) "listring[current_player;main]" end -local function formspec4_cfg(pos) +local function formspec4_pre(pos) return "size[10,9]".. - "tabheader[0,0;tab;"..S("Inventory,Configuration")..";2;;true]".. + "tabheader[0,0;tab;"..S("Inventory,Pre-Assignment,Config")..";2;;true]".. default.gui_bg.. default.gui_bg_img.. default.gui_slots.. @@ -201,8 +201,23 @@ local function formspec4_cfg(pos) "listring[current_player;main]" end +local function formspec4_cfg(pos) + local meta = minetest.get_meta(pos) + local label = meta:get_string("label") or "" + local public = dump((meta:get_int("public") or 0) == 1) + return "size[10,5]".. + "tabheader[0,0;tab;"..S("Inventory,Pre-Assignment,Config")..";3;;true]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "field[0.5,1;9,1;label;"..S("Node label:")..";"..label.."]" .. + "checkbox[1,2;public;"..S("Allow public access to the chest")..";"..public.."]".. + "button_exit[3.5,4;3,1;exit;"..S("Save").."]" +end + local function ta4_allow_metadata_inventory_put(pos, listname, index, stack, player) - if minetest.is_protected(pos, player:get_player_name()) then + local public = M(pos):get_int("public") == 1 + if not public and minetest.is_protected(pos, player:get_player_name()) then return 0 end @@ -214,7 +229,8 @@ local function ta4_allow_metadata_inventory_put(pos, listname, index, stack, pla end local function ta4_allow_metadata_inventory_take(pos, listname, index, stack, player) - if minetest.is_protected(pos, player:get_player_name()) then + local public = M(pos):get_int("public") == 1 + if not public and minetest.is_protected(pos, player:get_player_name()) then return 0 end @@ -226,7 +242,8 @@ local function ta4_allow_metadata_inventory_take(pos, listname, index, stack, pl end local function ta4_allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player) - if minetest.is_protected(pos, player:get_player_name()) then + local public = M(pos):get_int("public") == 1 + if not public and minetest.is_protected(pos, player:get_player_name()) then return 0 end @@ -276,10 +293,25 @@ minetest.register_node("techage:chest_ta4", { mem.filter = nil meta:set_string("formspec", formspec4(pos)) elseif fields.tab == "2" then + meta:set_string("formspec", formspec4_pre(pos)) + elseif fields.tab == "3" then meta:set_string("formspec", formspec4_cfg(pos)) elseif fields.quit == "true" then mem.filter = nil end + if fields.public then + meta:set_int("public", fields.public == "true" and 1 or 0) + end + if fields.exit then + local number = meta:get_string("node_number") + if fields.label ~= "" then + meta:set_string("infotext", minetest.formspec_escape(fields.label).." #"..number) + else + meta:set_string("infotext", S("TA4 Protected Chest").." "..number) + end + meta:set_string("label", fields.label) + meta:set_string("formspec", formspec4_cfg(pos)) + end end, techage_set_numbers = function(pos, numbers, player_name) diff --git a/techage/basic_machines/consumer.lua b/techage/basic_machines/consumer.lua index 70ad1ad..ff32904 100644 --- a/techage/basic_machines/consumer.lua +++ b/techage/basic_machines/consumer.lua @@ -180,10 +180,7 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState if (meta:contains("node_number")) then meta:set_string("node_number", "") end - local number = "-" - if stage > 2 then - number = techage.add_node(pos, name_pas) - end + local number = techage.add_node(pos, name_pas, stage == 2) if crd.power_netw then crd.power_netw:after_place_node(pos) end diff --git a/techage/basic_machines/source.lua b/techage/basic_machines/source.lua index 48164b2..5056980 100644 --- a/techage/basic_machines/source.lua +++ b/techage/basic_machines/source.lua @@ -35,7 +35,7 @@ local function formspec(self, pos, nvm) default.gui_bg.. default.gui_bg_img.. default.gui_slots.. - power.formspec_label_bar(0, 0.8, S("power"), PWR_CAPA, nvm.provided).. + power.formspec_label_bar(pos, 0, 0.8, S("power"), PWR_CAPA, nvm.provided).. "image_button[2.8,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]".. "tooltip[2.8,2;1,1;"..self:get_state_tooltip(nvm).."]" end diff --git a/techage/basic_machines/ta4_chest.lua b/techage/basic_machines/ta4_chest.lua index ce565ac..3eacd0e 100644 --- a/techage/basic_machines/ta4_chest.lua +++ b/techage/basic_machines/ta4_chest.lua @@ -20,11 +20,16 @@ local S = techage.S local DESCRIPTION = S("TA4 8x2000 Chest") local STACK_SIZE = 2000 +local function gen_stack(inv, idx) + inv[idx] = {name = "", count = 0} +end + local function gen_inv(nvm) nvm.inventory = {} for i = 1,8 do - nvm.inventory[i] = {name = "", count = 0} + gen_stack(nvm.inventory, i) end + return nvm.inventory end local function repair_inv(nvm) @@ -32,33 +37,26 @@ local function repair_inv(nvm) for i = 1,8 do local item = nvm.inventory[i] if not item or type(item) ~= "table" - or not item.name or type(item.name) ~= "string" - or not item.count or type(item.count) ~= "number" then - nvm.inventory[i] = {name = "", count = 0} + or not item.name or type(item.name) ~= "string" or item.name == "" + or not item.count or type(item.count) ~= "number" or item.count < 1 + then + gen_stack(nvm.inventory, i) end end end local function get_stack(nvm, idx) nvm.inventory = nvm.inventory or {} - if nvm.inventory[idx] then - return nvm.inventory[idx] - end - nvm.inventory[idx] = {name = "", count = 0} - return nvm.inventory[idx] + return nvm.inventory[idx] or gen_stack(nvm.inventory, idx) end local function get_count(nvm, idx) + nvm.inventory = nvm.inventory or {} if idx and idx > 0 then - nvm.inventory = nvm.inventory or {} - if nvm.inventory[idx] then - return nvm.inventory[idx].count or 0 - else - return 0 - end + return nvm.inventory[idx] and nvm.inventory[idx].count or 0 else local count = 0 - for _,item in ipairs(nvm.inventory or {}) do + for _,item in ipairs(nvm.inventory) do count = count + item.count or 0 end return count @@ -68,9 +66,7 @@ end local function get_itemstring(nvm, idx) if idx and idx > 0 then nvm.inventory = nvm.inventory or {} - if nvm.inventory[idx] then - return nvm.inventory[idx].name or "" - end + return nvm.inventory[idx] and nvm.inventory[idx].name or "" end return "" end @@ -97,11 +93,11 @@ local function inv_state(nvm) end local function max_stacksize(item_name) - local ndef = minetest.registered_nodes[item_name] or minetest.registered_items[item_name] or minetest.registered_craftitems[item_name] - if ndef then - return ndef.stack_max - end - return 0 + -- It is sufficient to use minetest.registered_items as all registration + -- functions (node, craftitems, tools) add the definitions there. + local ndef = minetest.registered_items[item_name] + -- Return 1 as fallback so that slots with unknown items can be emptied. + return ndef and ndef.stack_max or 1 end local function get_stacksize(pos) @@ -112,102 +108,159 @@ local function get_stacksize(pos) return size end --- Sort the items into the nvm inventory -local function sort_in(pos, nvm, stack) - local old_counts = {} - local orig_count = stack:get_count() - for idx,item in ipairs(nvm.inventory or {}) do - if item.name and (item.name == "" or item.name == stack:get_name()) then - local count = math.min(stack:get_count(), get_stacksize(pos) - item.count) - old_counts[idx] = item.count -- store old value - item.count = item.count + count - item.name = stack:get_name() - stack:set_count(stack:get_count() - count) - if stack:get_count() == 0 then - return true - end - end +-- Returns a boolean that indicates if an itemstack and nvmstack can be combined. +-- The second return value is a string describing the reason. +-- This function guarantees not to modify any of both stacks. +local function doesItemStackMatchNvmStack(itemstack, nvmstack) + if itemstack:get_count() == 0 or nvmstack.count == 0 then + return true, "Empty stack" end - -- restore old values - for idx,cnt in pairs(old_counts) do - nvm.inventory[idx].count = cnt + if nvmstack.name and nvmstack.name ~= "" and nvmstack.name ~= itemstack:get_name() then + return false, "Mismatching names" end - stack:set_count(orig_count) - return false + + -- The following seems to be the most reliable approach to compare meta. + local nvm_meta = ItemStack():get_meta() + nvm_meta:from_table(minetest.deserialize(nvmstack.meta)) + if not nvm_meta:equals(itemstack:get_meta()) then + return false, "Mismatching meta" + end + if (nvmstack.wear or 0) ~= itemstack:get_wear() then + return false, "Mismatching wear" + end + return true, "Stacks match" end -local function move_items_to_stack(item, stack, num) - item.count = item.count - num - stack.count = stack.count + num - if stack.count > 0 then - stack.name = item.name - end - if item.count == 0 then - item.name = "" -- empty - end - return stack -end -local function get_item(pos, nvm, item_name, count) - local stack = {count = 0} - nvm.inventory = nvm.inventory or {} - - if item_name then - -- Take specified items from the chest - for _,item in ipairs(nvm.inventory) do - if item.name == item_name then - local num = math.min(item.count, count - stack.count, max_stacksize(item.name)) - if M(pos):get_int("assignment") == 1 and num == item.count then - -- never take the last item - num = num - 1 - end - stack = move_items_to_stack(item, stack, num) - if stack.count == count then - return ItemStack(stack) - end - end - end - elseif M(pos):get_int("priority") == 1 then - -- Take any items. The position within the inventory is from right to left - for idx = 8,1,-1 do - local item = nvm.inventory[idx] - if item.name ~= "" and (stack.name == nil or stack.name == item.name) then - local num = math.min(item.count, count - stack.count, max_stacksize(item.name)) - if M(pos):get_int("assignment") == 1 and num == item.count then - -- never take the last item - num = num - 1 - end - stack = move_items_to_stack(item, stack, num) - if stack.count == count then - return ItemStack(stack) - end - end - end - else - -- Take any items. The position within the inventory - -- is incremented each time so that different item stacks will be considered. - local mem = techage.get_mem(pos) - mem.startpos = mem.startpos or 1 - for idx = mem.startpos, mem.startpos + 8 do - idx = (idx % 8) + 1 - local item = nvm.inventory[idx] - if item.name ~= "" and (stack.name == nil or stack.name == item.name) then - local num = math.min(item.count, count - stack.count, max_stacksize(item.name)) - if M(pos):get_int("assignment") == 1 and num == item.count then - -- never take the last item - num = num - 1 - end - stack = move_items_to_stack(item, stack, num) - if stack.count == count then - mem.startpos = idx - return ItemStack(stack) - end - end - mem.startpos = idx - end +-- Generic function for adding items to the 8x2000 Chest +-- This function guarantees not to modify the itemstack. +-- The number of items that were added to the chest is returned. +local function add_to_chest(pos, input_stack, idx) + local nvm = techage.get_nvm(pos) + local nvm_stack = get_stack(nvm, idx) + if input_stack:get_count() == 0 then + return 0 end - if stack.count > 0 then - return ItemStack(stack) + if not doesItemStackMatchNvmStack(input_stack, nvm_stack) then + return 0 + end + local count = math.min(input_stack:get_count(), get_stacksize(pos) - (nvm_stack.count or 0)) + if nvm_stack.count == 0 then + nvm_stack.name = input_stack:get_name() + nvm_stack.meta = minetest.serialize(input_stack:get_meta():to_table()) + nvm_stack.wear = input_stack:get_wear() + end + nvm_stack.count = nvm_stack.count + count + return count +end + +local function stackOrNil(stack) + if stack and stack.get_count and stack:get_count() > 0 then + return stack + end + return nil +end + +-- Generic function for taking items from the 8x2000 Chest +-- output_stack is directly modified; but nil can also be supplied. +-- The resulting output_stack is returned from the function. +-- keep_assignment indicates if the meta information for this function should be considered (manual vs. tubes). +local function take_from_chest(pos, idx, output_stack, max_total_count, keep_assignment) + local nvm = techage.get_nvm(pos) + local nvm_stack = get_stack(nvm, idx) + output_stack = output_stack or ItemStack() + local assignment_count = keep_assignment and M(pos):get_int("assignment") == 1 and 1 or 0 + local count = math.min(nvm_stack.count - assignment_count, max_stacksize(nvm_stack.name)) + if max_total_count then + count = math.min(count, max_total_count - output_stack:get_count()) + end + if count < 1 then + return stackOrNil(output_stack) + end + if not doesItemStackMatchNvmStack(output_stack, nvm_stack) then + return stackOrNil(output_stack) + end + output_stack:add_item(ItemStack({ + name = nvm_stack.name, + count = count, + wear = nvm_stack.wear, + })) + output_stack:get_meta():from_table(minetest.deserialize(nvm_stack.meta)) + nvm_stack.count = nvm_stack.count - count + if nvm_stack.count == 0 then + gen_stack(nvm.inventory or {}, idx) + end + return stackOrNil(output_stack) +end + +-- Function for adding items to the 8x2000 Chest via automation, e.g. pushers +local function tube_add_to_chest(pos, input_stack) + local nvm = techage.get_nvm(pos) + nvm.inventory = nvm.inventory or {} + + -- Backup some values needed for restoring the old + -- state if items can't fully be added to chest. + local orig_count = input_stack:get_count() + local backup = table.copy(nvm.inventory) + + for idx = 1,8 do + input_stack:take_item(add_to_chest(pos, input_stack, idx)) + end + + if input_stack:get_count() > 0 then + nvm.inventory = backup -- Restore old nvm inventory + input_stack:set_count(orig_count) -- Restore input_stack + return false -- No items were added to chest + else + return true -- Items were added successfully + end +end + +-- Function for taking items from the 8x2000 Chest via automation, e.g. pushers +local function tube_take_from_chest(pos, item_name, count) + local nvm = techage.get_nvm(pos) + local mem = techage.get_mem(pos) + nvm.inventory = nvm.inventory or {} + mem.startpos = mem.startpos or 1 + local prio = M(pos):get_int("priority") == 1 + local startpos = prio and 8 or mem.startpos + local endpos = prio and 1 or mem.startpos + 8 + local step = prio and -1 or 1 + local itemstack = ItemStack() + for idx = startpos,endpos,step do + idx = ((idx - 1) % 8) + 1 + local nvmstack = get_stack(nvm, idx) + if not item_name or item_name == nvmstack.name then + take_from_chest(pos, idx, itemstack, count - itemstack:get_count(), true) + if itemstack:get_count() == count then + mem.startpos = idx + 1 + return itemstack + end + end + mem.startpos = idx + 1 + end + return stackOrNil(itemstack) +end + +-- Function for manually adding items to the 8x2000 Chest via the formspec +local function inv_add_to_chest(pos, idx) + local inv = M(pos):get_inventory() + local inv_stack = inv:get_stack("main", idx) + local count = add_to_chest(pos, inv_stack, idx) + inv_stack:set_count(inv_stack:get_count() - count) + inv:set_stack("main", idx, inv_stack) +end + +-- Function for manually taking items from the 8x2000 Chest via the formspec +local function inv_take_from_chest(pos, idx) + local inv = M(pos):get_inventory() + local inv_stack = inv:get_stack("main", idx) + if inv_stack:get_count() > 0 then + return + end + local output_stack = take_from_chest(pos, idx) + if output_stack then + inv:set_stack("main", idx, output_stack) end end @@ -218,9 +271,15 @@ local function formspec_container(x, y, nvm, inv) tbl[#tbl+1] = "box["..(xpos - 0.03)..",0;0.86,0.9;#808080]" local stack = get_stack(nvm, i) if stack.name ~= "" then - local itemname = stack.name.." "..stack.count + local itemstack = ItemStack({ + name = stack.name, + count = stack.count, + wear = stack.wear, + }) + itemstack:get_meta():from_table(minetest.deserialize(stack.meta)) + local itemname = itemstack:to_string() --tbl[#tbl+1] = "item_image["..xpos..",1;1,1;"..itemname.."]" - tbl[#tbl+1] = techage.item_image(xpos, 0, itemname) + tbl[#tbl+1] = techage.item_image(xpos, 0, itemname, stack.count) end if inv:get_stack("main", i):get_count() == 0 then tbl[#tbl+1] = "image_button["..xpos..",1;1,1;techage_form_get_arrow.png;get"..i..";]" @@ -366,47 +425,6 @@ local function on_rightclick(pos, node, clicker) end end --- take items from chest -local function move_from_nvm_to_inv(pos, idx) - local nvm = techage.get_nvm(pos) - local inv = M(pos):get_inventory() - local inv_stack = inv:get_stack("main", idx) - local nvm_stack = get_stack(nvm, idx) - - if nvm_stack.count > 0 and inv_stack:get_count() == 0 then - local count = math.min(nvm_stack.count, max_stacksize(nvm_stack.name)) - nvm_stack.count = nvm_stack.count - count - inv:set_stack("main", idx, {name = nvm_stack.name, count = count}) - if nvm_stack.count == 0 then - nvm_stack.name = "" - end - end -end - --- add items to chest -local function move_from_inv_to_nvm(pos, idx) - local nvm = techage.get_nvm(pos) - local inv = M(pos):get_inventory() - local inv_stack = inv:get_stack("main", idx) - local nvm_stack = get_stack(nvm, idx) - - if inv_stack:get_count() > 0 then - -- Don't handle items with meta or wear information because it would get lost. - local meta_table = inv_stack:get_meta():to_table() - if meta_table ~= nil and next(meta_table.fields) ~= nil or inv_stack:get_wear() ~= 0 then - return - end - - if nvm_stack.count == 0 or nvm_stack.name == inv_stack:get_name() then - local count = math.min(inv_stack:get_count(), get_stacksize(pos) - nvm_stack.count) - nvm_stack.count = nvm_stack.count + count - nvm_stack.name = inv_stack:get_name() - inv_stack:set_count(inv_stack:get_count() - count) - inv:set_stack("main", idx, inv_stack) - end - end -end - local function on_receive_fields(pos, formname, fields, player) if minetest.is_protected(pos, player:get_player_name()) then return @@ -414,10 +432,10 @@ local function on_receive_fields(pos, formname, fields, player) for i = 1,8 do if fields["get"..i] ~= nil then - move_from_nvm_to_inv(pos, i) + inv_take_from_chest(pos, i) break elseif fields["add"..i] ~= nil then - move_from_inv_to_nvm(pos, i) + inv_add_to_chest(pos, i) break end end @@ -534,24 +552,21 @@ minetest.register_node("techage:ta4_chest_dummy", { techage.register_node({"techage:ta4_chest"}, { on_pull_item = function(pos, in_dir, num, item_name) - local nvm = techage.get_nvm(pos) - local res = get_item(pos, nvm, item_name, num) + local res = tube_take_from_chest(pos, item_name, num) if techage.is_activeformspec(pos) then M(pos):set_string("formspec", formspec(pos)) end return res end, on_push_item = function(pos, in_dir, stack) - local nvm = techage.get_nvm(pos) - local res = sort_in(pos, nvm, stack) + local res = tube_add_to_chest(pos, stack) if techage.is_activeformspec(pos) then M(pos):set_string("formspec", formspec(pos)) end return res end, on_unpull_item = function(pos, in_dir, stack) - local nvm = techage.get_nvm(pos) - local res = sort_in(pos, nvm, stack) + local res = tube_add_to_chest(pos, stack) if techage.is_activeformspec(pos) then M(pos):set_string("formspec", formspec(pos)) end diff --git a/techage/basis/command.lua b/techage/basis/command.lua index e8b87b8..4ebea9d 100644 --- a/techage/basis/command.lua +++ b/techage/basis/command.lua @@ -207,28 +207,39 @@ end -- Add node to the techage lists. -- Function determines and returns the node position number, -- needed for message communication. -function techage.add_node(pos, name) +-- If TA2 node, return '-' instead of a real number, because +-- TA2 nodes should not support number based commands. +function techage.add_node(pos, name, is_ta2) if item_handling_node(name) then Tube:after_place_node(pos) end + if is_ta2 then + return "-" + end local key = minetest.hash_node_position(pos) - return NumbersToBeRecycled[key] or get_number(pos, true) + local num = NumbersToBeRecycled[key] + if num then + backend.set_nodepos(num, pos) + NumbersToBeRecycled[key] = nil + return num + end + return get_number(pos, true) end -- Function removes the node from the techage lists. function techage.remove_node(pos, oldnode, oldmetadata) - local number = oldmetadata and oldmetadata.fields and oldmetadata.fields.node_number + local number = oldmetadata and oldmetadata.fields and oldmetadata.fields.node_number or oldmetadata.fields.number + print("number1", dump(oldmetadata)) number = number or get_number(pos) + print("number2", number) if number and tonumber(number) then local key = minetest.hash_node_position(pos) NumbersToBeRecycled[key] = number - local ninfo = NodeInfoCache[number] or update_nodeinfo(number) - if ninfo then - NodeInfoCache[number] = nil - if item_handling_node(ninfo.name) then - Tube:after_dig_node(pos) - end - end + NodeInfoCache[number] = nil + print("number3", number) + end + if oldnode and item_handling_node(oldnode.name) then + Tube:after_dig_node(pos) end end diff --git a/techage/basis/lib.lua b/techage/basis/lib.lua index 4f6dee2..ffec3a4 100644 --- a/techage/basis/lib.lua +++ b/techage/basis/lib.lua @@ -240,19 +240,15 @@ function techage.is_ocean(pos) return true end -function techage.item_image(x, y, itemname) +function techage.item_image(x, y, itemname, count) local name, size = unpack(string.split(itemname, " ")) + size = count and count or size + size = tonumber(size) or 1 local label = "" - local tooltip = "" - local ndef = minetest.registered_nodes[name] or minetest.registered_items[name] or minetest.registered_craftitems[name] - - if ndef and ndef.description then - local text = minetest.formspec_escape(ndef.description) - tooltip = "tooltip["..x..","..y..";1,1;"..text..";#0C3D32;#FFFFFF]" - end - - if ndef and ndef.stack_max == 1 then - size = tonumber(size) + local text = minetest.formspec_escape(ItemStack(itemname):get_description()) + local tooltip = "tooltip["..x..","..y..";1,1;"..text..";#0C3D32;#FFFFFF]" + + if minetest.registered_tools[name] and size > 1 then local offs = 0 if size < 10 then offs = 0.65 diff --git a/techage/basis/liquid_lib.lua b/techage/basis/liquid_lib.lua index a21ffc4..cb9c044 100644 --- a/techage/basis/liquid_lib.lua +++ b/techage/basis/liquid_lib.lua @@ -36,14 +36,28 @@ function techage.liquid.formspec(pos, nvm) if nvm.liquid and nvm.liquid.amount and nvm.liquid.amount > 0 and nvm.liquid.name then itemname = nvm.liquid.name.." "..nvm.liquid.amount end - return "size[4,2]".. - default.gui_bg.. - default.gui_bg_img.. - default.gui_slots.. - "box[0,-0.1;3.8,0.5;#c6e8ff]".. - "label[1,-0.1;"..minetest.colorize("#000000", title).."]".. - help(3.4, -0.1).. - techage.item_image(1.5, 1, itemname) + local name = minetest.get_node(pos).name + if name == "techage:ta4_tank" then + local public = dump((M(pos):get_int("public") or 0) == 1) + return "size[5,3]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "box[0,-0.1;4.8,0.5;#c6e8ff]".. + "label[1.5,-0.1;"..minetest.colorize("#000000", title).."]".. + help(4.4, -0.1).. + techage.item_image(2, 1, itemname).. + "checkbox[0.1,2.5;public;"..S("Allow public access to the tank")..";"..public.."]" + else + return "size[4,2]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "box[0,-0.1;3.8,0.5;#c6e8ff]".. + "label[1,-0.1;"..minetest.colorize("#000000", title).."]".. + help(3.4, -0.1).. + techage.item_image(1.5, 1, itemname) + end end function techage.liquid.is_empty(pos) @@ -205,7 +219,8 @@ local function empty_on_punch(pos, nvm, full_container, item_count) end function techage.liquid.on_punch(pos, node, puncher, pointed_thing) - if minetest.is_protected(pos, puncher:get_player_name()) then + local public = M(pos):get_int("public") == 1 + if not public and minetest.is_protected(pos, puncher:get_player_name()) then return end diff --git a/techage/basis/mark.lua b/techage/basis/mark.lua index 4b76773..538bae7 100644 --- a/techage/basis/mark.lua +++ b/techage/basis/mark.lua @@ -26,6 +26,8 @@ end function techage.mark_region(name, pos1, pos2, owner, secs) + if not name or not pos1 or not pos2 then return end + techage.unmark_region(name) local thickness = 0.2 @@ -82,6 +84,7 @@ minetest.register_entity(":techage:region_cube", { textures = {"techage_cube_mark.png"}, use_texture_alpha = true, physical = false, + glow = 12, }, on_step = function(self, dtime) if marker_region[self.player_name] == nil then diff --git a/techage/basis/mark2.lua b/techage/basis/mark2.lua index 90dea04..99ac668 100644 --- a/techage/basis/mark2.lua +++ b/techage/basis/mark2.lua @@ -114,7 +114,7 @@ minetest.register_entity(":techage:position_side", { physical = false, visual_size = {x = 1.1, y = 1.1, z = 1.1}, collisionbox = {-0.55,-0.55,-0.55, 0.55,0.55,0.55}, - glow = 8, + glow = 12, }, on_step = function(self, dtime) if marker_region[self.player_name] == nil then diff --git a/techage/basis/networks.lua b/techage/basis/networks.lua index 29ff735..ddc16b4 100644 --- a/techage/basis/networks.lua +++ b/techage/basis/networks.lua @@ -243,7 +243,7 @@ local function collect_network_nodes(pos, outdir, tlib2) end for _,ntype in ipairs(ntypes) do if not netw[ntype] then netw[ntype] = {} end - netw[ntype][#netw[ntype] + 1] = {pos = pos, indir = indir, nominal = ndef.nominal or 0} + netw[ntype][#netw[ntype] + 1] = {pos = pos, indir = indir, nominal = ndef.nominal} end end) netw.best_before = minetest.get_gametime() + BEST_BEFORE diff --git a/techage/basis/windturbine_lib.lua b/techage/basis/windturbine_lib.lua index 2c2a290..31a30b6 100644 --- a/techage/basis/windturbine_lib.lua +++ b/techage/basis/windturbine_lib.lua @@ -41,7 +41,7 @@ function techage.valid_place_for_windturbine(pos, player_name, num_turbines) if data then local name = minetest.get_biome_name(data.biome) if not string.find(name, "ocean") then - chat_message(player_name, S("This is a "..name.." biome and no ocean!")) + chat_message(player_name, S("This is a").." "..name.." "..S("biome and no ocean!")) return false end end @@ -60,7 +60,7 @@ function techage.valid_place_for_windturbine(pos, player_name, num_turbines) pos2 = {x=pos.x+20, y=1, z=pos.z+20} num = #minetest.find_nodes_in_area(pos1, pos2, {"default:water_source", "default:water_flowing", "ignore"}) - print(num, (41 * 41 * 0.9)) + if num < (41*41 * 0.8) then techage.mark_region(player_name, pos1, pos2, "") chat_message(player_name, S("Here is not enough water (41x41 m)!")) @@ -69,6 +69,7 @@ function techage.valid_place_for_windturbine(pos, player_name, num_turbines) -- Check for next wind turbine pos1 = {x=pos.x-13, y=2, z=pos.z-13} pos2 = {x=pos.x+13, y=22, z=pos.z+13} + num = #minetest.find_nodes_in_area(pos1, pos2, {"techage:ta4_wind_turbine"}) if num > num_turbines then techage.mark_region(player_name, pos1, pos2, "") diff --git a/techage/carts/tank_cart.lua b/techage/carts/tank_cart.lua index c036c68..6749a76 100644 --- a/techage/carts/tank_cart.lua +++ b/techage/carts/tank_cart.lua @@ -59,6 +59,15 @@ local function take_liquid(pos, indir, name, amount) return amount, name end +local function untake_liquid(pos, indir, name, amount) + local leftover = liquid.srv_put(pos, indir, name, amount) + if techage.is_activeformspec(pos) then + local nvm = techage.get_nvm(pos) + M(pos):set_string("formspec", liquid.formspec(pos, nvm)) + end + return leftover +end + local function put_liquid(pos, indir, name, amount) -- check if it is not powder local ndef = minetest.registered_craftitems[name] or {} @@ -153,6 +162,7 @@ minetest.register_node("techage:tank_cart", { peek = liquid.srv_peek, put = put_liquid, take = take_liquid, + untake = untake_liquid, }, networks = networks_def, on_rightclick = on_rightclick, diff --git a/techage/chemistry/ta4_doser.lua b/techage/chemistry/ta4_doser.lua index 0888542..09fb175 100644 --- a/techage/chemistry/ta4_doser.lua +++ b/techage/chemistry/ta4_doser.lua @@ -157,7 +157,9 @@ local function untake(recipe, pos, liquids) for _,item in pairs(recipe.input) do if item.name ~= "" then local outdir = liquids[item.name] or reload_liquids(pos)[item.name] - liquid.untake(pos, outdir, item.name, item.num) + if outdir then + liquid.untake(pos, outdir, item.name, item.num) + end end end end diff --git a/techage/coal_power_station/generator.lua b/techage/coal_power_station/generator.lua index 5a44f2d..e8c6e8c 100644 --- a/techage/coal_power_station/generator.lua +++ b/techage/coal_power_station/generator.lua @@ -32,7 +32,7 @@ local function formspec(self, pos, nvm) default.gui_bg.. default.gui_bg_img.. default.gui_slots.. - power.formspec_label_bar(0, 0.8, S("power"), PWR_CAPA, nvm.provided).. + power.formspec_label_bar(pos, 0, 0.8, S("power"), PWR_CAPA, nvm.provided).. "image_button[2.8,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]".. "tooltip[2.8,2;1,1;"..self:get_state_tooltip(nvm).."]" end diff --git a/techage/digtron/battery.lua b/techage/digtron/battery.lua index 239d983..021b955 100644 --- a/techage/digtron/battery.lua +++ b/techage/digtron/battery.lua @@ -49,7 +49,7 @@ local function formspec(self, pos, nvm) default.gui_slots.. "box[0,-0.1;4.8,0.5;#c6e8ff]".. "label[1,-0.1;"..minetest.colorize("#000000", S("Digtron Battery")).."]".. - power.formspec_label_bar(0, 0.8, S("Load"), TOTAL_MAX, total, S("Coal Equivalents")).. + power.formspec_label_bar(pos, 0, 0.8, S("Load"), TOTAL_MAX, total, S("Coal Equivalents")).. "image_button[2.6,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]".. "tooltip[2.6,2;1,1;"..self:get_state_tooltip(nvm).."]".. "image[3.75,2;1,1;"..techage.get_power_image(pos, nvm).."]" diff --git a/techage/doc/items.lua b/techage/doc/items.lua index 784ffa4..0a3db3e 100644 --- a/techage/doc/items.lua +++ b/techage/doc/items.lua @@ -48,6 +48,7 @@ techage.Items = { ta2_chest = "techage:chest_ta2", ta2_forceload = "techage:forceload", ta2_driveaxle = "techage:axle", + ta2_generator = "techage:ta2_generator_off", --------------------- techage_ta3 = "techage_ta3.png", techage_ta31 = "techage_ta3b.png", @@ -114,6 +115,7 @@ techage.Items = { ta3_pipe_wall_entry = "techage:ta3_pipe_wall_entry", ta3_mesecons_converter = "techage:ta3_mesecons_converter", ta3_valve = "techage:ta3_valve_closed", + ta3_motor = "techage:ta3_motor_off", ---------------------------- techage_ta4 = "techage_ta4.png", ta4_windturbine = "techage:ta4_wind_turbine", diff --git a/techage/doc/manual_DE.lua b/techage/doc/manual_DE.lua index 9ff6fb0..a57960e 100644 --- a/techage/doc/manual_DE.lua +++ b/techage/doc/manual_DE.lua @@ -28,6 +28,7 @@ techage.manual_DE.aTitel = { "3,TA2 Schwungrad / Flywheel", "3,TA2 Dampfleitungen / Steam Pipe", "3,TA2 Antriebsachsen / TA2 Drive Axle", + "3,TA2 Stromgenerator / TA2 Power Generator", "2,Items schieben und sortieren", "3,Röhren / TechAge Tube", "3,TA2 Schieber / Pusher", @@ -66,6 +67,8 @@ techage.manual_DE.aTitel = { "3,TA3 Kleiner Stromgenerator / Tiny Power Generator", "3,TA3 Akku Block / Akku Box", "3,TA3 Strom Terminal / Power Terminal", + "3,TA3 Elektromotor / TA3 Electric Motor", + "3,TA3 Strom Terminal / Power Terminal", "2,TA3 Industrieofen", "3,TA3 Ofen-Ölbrenner / Furnace Oil Burner", "3,TA3 Ofenoberteil / Furnace Top", @@ -399,6 +402,14 @@ techage.manual_DE.aText = { "\n".. "\n".. "\n", + "Um Lampen oder andere Stromverbraucher an einer Dampfmaschine betreiben zu können\\, wird der TA2 Stromgenerator benötigt. Der TA2 Stromgenerator muss auf einer Seite mit Antriebsachsen verbunden werden und liefert dann auf der anderen Seite elektrischen Strom.\n".. + "\n".. + "Wird der Stromgenerator nicht mit ausreichend Kraft versorgt\\, geht er in einen Fehlerzustand und muss über einen Rechtsklick wieder aktiviert werden.\n".. + "\n".. + "Das Stromgenerator nimmt primär max. 25 ku an Achsenkraft auf und gibt sekundär max. 24 ku als Strom wieder ab. Er verbraucht also ein ku für die Umwandlung.\n".. + "\n".. + "\n".. + "\n", "Um Gegenstände (Items) von einer Verarbeitungsstation zur nächsten weiter zu transportieren\\, werden Schieber und Röhren verwendet. Siehe Plan.\n".. "\n".. "\n".. @@ -424,6 +435,8 @@ techage.manual_DE.aText = { "\n".. "Der Verteiler besitzt dazu ein Menü mit 4 Filter mit unterschiedlichen Farben\\, entsprechend den 4 Ausgängen. Soll ein Ausgang genutzt werden\\, so muss der entsprechende Filter über die \"on\" Checkbox aktiviert werden. Alle Items\\, die für diesen Filter konfiguriert sind\\, werden über den zugeordneten Ausgang ausgegeben. Wird ein Filter aktiviert\\, ohne das Items konfiguriert werden\\, so sprechen wir hier von einem \"nicht-konfigurierten\"\\, offenen Ausgang.\n".. "\n".. + "*Achtung: Der Verteiler ist an seinen Ausgängen gleichzeitig ein Schieber. Daher niemals die Gegenstände mit einem Schieber aus dem Verteiler ziehen!*\n".. + "\n".. "Für einen nicht-konfigurierten Ausgang gibt es zwei Betriebsarten:\n".. "\n".. "1) Alle Items ausgeben\\, die an keine anderen Ausgängen ausgegeben werden können\\, auch wenn diese blockiert sind.\n".. @@ -649,6 +662,21 @@ techage.manual_DE.aText = { "\n".. "\n".. "\n", + "Um TA2 Maschinen über das Stromnetz betreiben zu können\\, wird der TA3 Elektromotor benötigt. Dieser wandelt Strom in Achsenkraft um.\n".. + "Wird der Elektromotor nicht mit ausreichend Strom versorgt\\, geht er in einen Fehlerzustand und muss über einen Rechtsklick wieder aktiviert werden.\n".. + "\n".. + "Das Elektromotor nimmt primär max. 40 ku an Strom auf und gibt sekundär max. 39 ku als Achsenkraft wieder ab. Er verbraucht also ein ku für die Umwandlung.\n".. + "\n".. + "\n".. + "\n", + "Das Strom-Terminal muss mit dem Stromnetz verbunden werden. Es zeigt Daten aus dem Stromnetz an.\n".. + "\n".. + "In der oberen Hälfte werden nur die Daten eines ausgewählten Typs ausgegeben. Wird als Typ bspw. \"Kraftwerk\" gewählt\\, so werden nur die Daten von Öl- und Kohlekraftwerken gesammelt und ausgegeben. Links werden die Daten von Generatoren (Stromabgabe) und rechts die Daten von Energiespeichern (Stromaufnahme) ausgegeben. Beim Akkublocks bspw. wird beides ausgegeben\\, da der Akku Strom aufnehmen und abgeben kann.\n".. + "\n".. + "In der unteren Hälfte werden die Daten aller Generatoren und Speichersystemen des ganzen Stromnetzen zusammengefasst ausgegeben.\n".. + "\n".. + "\n".. + "\n", "Der TA3 Industrieofen dient als Ergänzung zu normalen Ofen (furnace). Damit können alle Waren mit \"Koch\" Rezepten\\, auch im Industrieofen hergestellt werden. Es gibt aber auch spezielle Rezepte\\, die nur im Industrieofen hergestellt werden können.\n".. "Der Industrieofen hat sein eigenes Menü zur Rezeptauswahl. Abhängig von den Waren im Industrieofen Inventar links kann rechts das Ausgangsprodukt gewählt werden.\n".. "\n".. @@ -935,7 +963,7 @@ techage.manual_DE.aText = { " - 'pub' schalte in den öffentlichen Modus um\n".. " - 'priv' schalte in den privaten Modus um\n".. "\n".. - "Im privaten Modul kann nur der Besitzer selbst Kommandos eingeben oder Tasten nutzen.\n".. + "Im privaten Modus (private) kann das Terminal nur von Spielern verwendet werden\\, die an diesem Ort bauen können\\, also Protection Rechte besitzen. Im öffentlichen Modus (public) können alle Spieler die vorkonfigurierten Tasten verwenden.\n".. "\n".. "\n".. "\n", @@ -1070,10 +1098,11 @@ techage.manual_DE.aText = { "\n".. "\n".. "\n", - "Eine Windkraftanlagen liefern immer dann Strom\\, wenn Wind vorhanden ist. Im Spiel gibt es keinen Wind\\, aber die Mod simuliert dies dadurch\\, dass sich nur morgens (5:00 - 9:00) und abends (17:00 - 21:00) die Windräder drehen und damit Strom liefern\\, sofern diese an geeigneten Stellen errichtet werden.\n".. + "Eine Windkraftanlage liefern immer dann Strom\\, wenn Wind vorhanden ist. Im Spiel gibt es keinen Wind\\, aber die Mod simuliert dies dadurch\\, dass sich nur morgens (5:00 - 9:00) und abends (17:00 - 21:00) die Windräder drehen. Eine Windkraftanlage liefert nur dann Strom\\, wenn sie an einer geeigneten Stelle aufgestellt ist.\n".. "\n".. - "Die TA Windkraftanlagen sind reine Offshore Anlagen\\, das heißt\\, die müssen im Meer (Wasser) errichtet werden. Dies bedeutet\\, dass um den Mast herum mit einem Abstand von 20 Blöcken nur Wasser sein darf und das mindestens 2 Blöcke tief.\n".. - "Der Rotor muss in einer Höhe (Y-Koordinate) von 12 bis maximal 20 m platziert werden. Der Abstand zu weiteren Windkraftanlagen muss mindestens 14 m betragen.\n".. + "Die TA Windkraftanlagen sind reine Offshore Anlagen\\, das heißt\\, die müssen im Meer errichtet werden. Dies bedeutet\\, dass Windkraftanlagen nur in einem Meer (occean) Biom errichtet werden können und dass um den Mast herum ausreichend Wasser und freie Sicht vorhanden sein müssen.\n".. + "\n".. + "Um eine geeignete Stelle zu finden\\, musst du mit dem Schraubenschlüssel (TechAge Info Werkzeug) auf das Wasser klicken. Ob diese Stelle für den Mast der Windkraftanlage geeignet ist\\, wird dir als Chat Nachricht angezeigt.\n".. "\n".. "Der Strom muss vom Rotor-Block durch den Mast nach unten geführt werden. Dazu zuerst die Stromleitung nach oben ziehen und das Stromkabel dann mit TA4 Säulenblöcke \"verputzen\". Unten kann eine Arbeitsplattform errichtet werden. Der Plan rechts zeigt den Aufbau im oberen Teil.\n".. "\n".. @@ -1160,7 +1189,7 @@ techage.manual_DE.aText = { " - Hülle mit 7x7x7 Concrete Blocks\\, gefüllt mit 125 Gravel\\, Speicherkapazität: 2\\,5 Tage bei 60 ku\n".. " - Hülle mit 9x9x9 Concrete Blocks\\, gefüllt mit 343 Gravel\\, Speicherkapazität: 6\\,5 Tage bei 60 ku\n".. "\n".. - "In der Betonhülle darf ein Fenster aus einem Obsidian Glas Block sein. Dieses muss ziemlich in der Mitte der Wand platziert werden. Durch dieses Fenster sieht man\\, ob der Speicher mehr als 80 % geladen ist. Im Plan rechts sieht man den Aufbau aus TA4 Wärmetauscher bestehend aus 3 Blöcken\\, der TA4 Turbine und dem TA4 Generator. Beim Wärmetauscher ist auf die Ausrichtung achten (der Pfeil bei Block 1 muss zur Turbine zeigen).\n".. + "In der Betonhülle darf ein Fenster aus einem Obsidian Glas Block sein. Dieses muss ziemlich in der Mitte der Wand platziert werden. Durch dieses Fenster sieht man\\, ob der Speicher mehr als 80 % geladen ist. Im Plan rechts sieht man den Aufbau aus TA4 Wärmetauscher bestehend aus 3 Blöcken\\, der TA4 Turbine und dem TA4 Generator. Beim Wärmetauscher ist auf die Ausrichtung zu achten (der Pfeil bei Block 1 muss zur Turbine zeigen).\n".. "\n".. "Entgegen dem Plan rechts müssen die Anschlüsse am Speicherblock auf gleicher Ebene sein (horizontal angeordnet\\, also nicht unten und oben). Die Rohrzuläufe (TA4 Pipe Inlet) müssen genau in der Mitte der Wand sein und stehen sich damit gegenüber. Als Röhren kommen die gelbel TA4 Röhren zum Einsatz. Die TA3 Dampfrohre können hier nicht verwendet werden.\n".. "Sowohl der Generator als auch der Wärmetauscher haben einen Stromanschluss und müssen mit dem Stromnetz verbunden werden.\n".. @@ -1349,9 +1378,9 @@ techage.manual_DE.aText = { "Wird etwas in die Kiste gelegt\\, oder entnommen\\, oder eine der Tasten \"F1\"/\"F2\" gedrückt\\, so wird ein Event-Signal an den Lua Controller gesendet.\n".. "Die Sensor Kiste unterstützt folgende Kommandos:\n".. "\n".. - " - Über 'state = $read_data(\\, \"state\")' kann der Status der Kiste abgefragt werden. Mögliche Antworten sind: \"empty\"\\, \"loaded\"\\, \"full\"\n".. - " - Über 'name\\, action = $read_data(\\, \"action\")' kann die letzte Spieleraktion abgefragt werden. 'name' ist der Spielername\\, Als 'action' wird zurückgeliefert: \"put\"\\, \"take\"\\, \"f1\"\\, \"f2\".\n".. - " - Über 'stacks = $read_data(\\, \"stacks\")' kann der Inhalt der Kiste ausgelesen werden. Siehe dazu: https://github.com/joe7575/techage/blob/master/manuals/ta4_lua_controller_EN.md#sensor-chest\n".. + " - Über 'state = $send_cmnd(\\, \"state\")' kann der Status der Kiste abgefragt werden. Mögliche Antworten sind: \"empty\"\\, \"loaded\"\\, \"full\"\n".. + " - Über 'name\\, action = $send_cmnd(\\, \"action\")' kann die letzte Spieleraktion abgefragt werden. 'name' ist der Spielername\\, Als 'action' wird zurückgeliefert: \"put\"\\, \"take\"\\, \"f1\"\\, \"f2\".\n".. + " - Über 'stacks = $send_cmnd(\\, \"stacks\")' kann der Inhalt der Kiste ausgelesen werden. Siehe dazu: https://github.com/joe7575/techage/blob/master/manuals/ta4_lua_controller_EN.md#sensor-chest\n".. " - Über '$send_cmnd(\\, \"text\"\\, \"press both buttons andnput something into the chest\")' kann der Text im Menü der Sensor Kiste gesetzt werden.\n".. "\n".. "Über die Checkbox \"Erlaube öffentlichen Zugriff\" kann eingestellt werden\\, ob die Kiste von jedem genutzt werden darf\\, oder nur von Spielern die hier Zugriffsrechte haben.\n".. @@ -1497,7 +1526,7 @@ techage.manual_DE.aText = { "\n".. "Der Kiste besitzt ein zusätzliches Kommandos für den Lua Controller:\n".. "\n".. - " - 'count' dient zur Anfrage\\, wie viele Items in der Kiste sind.\nBeispiel 1: '$read_data(CHEST\\, \"count\")' --> Summe der Items über alle 8 Speicher\nBeispiel 2: '$read_data(CHEST\\, \"count\"\\, 2)' --> Anzahl der Items in Speicher 2 (zweiter von links)\n".. + " - 'count' dient zur Anfrage\\, wie viele Items in der Kiste sind.\nBeispiel 1: '$send_cmnd(CHEST\\, \"count\")' --> Summe der Items über alle 8 Speicher\nBeispiel 2: '$send_cmnd(CHEST\\, \"count\"\\, 2)' --> Anzahl der Items in Speicher 2 (zweiter von links)\n".. "\n".. "\n".. "\n", @@ -1572,6 +1601,7 @@ techage.manual_DE.aItemName = { "ta2_flywheel", "ta2_steampipe", "ta2_driveaxle", + "ta2_generator", "", "tube", "ta2_pusher", @@ -1610,6 +1640,8 @@ techage.manual_DE.aItemName = { "ta3_tinygenerator", "ta3_akkublock", "ta3_powerterminal", + "ta3_motor", + "ta3_powerterminal", "", "ta3_furnacefirebox", "ta3_furnace", @@ -1764,6 +1796,7 @@ techage.manual_DE.aPlanTable = { "", "", "", + "", "itemtransport", "", "", @@ -1802,6 +1835,8 @@ techage.manual_DE.aPlanTable = { "", "", "", + "", + "", "ta3_furnace", "", "", diff --git a/techage/doc/manual_EN.lua b/techage/doc/manual_EN.lua index 84060c1..792bd32 100644 --- a/techage/doc/manual_EN.lua +++ b/techage/doc/manual_EN.lua @@ -28,6 +28,7 @@ techage.manual_EN.aTitel = { "3,TA2 Flywheel", "3,TA2 Steam Pipes", "3,TA2 Drive Axle / TA2 Gearbox", + "3,TA2 Power Generator", "2,Push and sort items", "3,TechAge Tube", "3,TA2 Pusher", @@ -66,6 +67,7 @@ techage.manual_EN.aTitel = { "3,TA3 Small Power Generator", "3,TA3 Battery Block", "3,TA3 Power Terminal", + "3,TA3 Electric Motor", "2,TA3 Industrial Furnace", "3,TA3 Furnace Oil Burner", "3,TA3 Furnace Top", @@ -399,6 +401,14 @@ techage.manual_EN.aText = { "\n".. "\n".. "\n", + "The TA2 Power Generator is required to operate lamps or other power consumers on a steam engine. The TA2 Power Generator has to be connected to drive axles on one side and then supplies electricity on the other side.\n".. + "\n".. + "If the Power Generator is not supplied with sufficient power\\, it goes into an error state and must be reactivated with a right-click.\n".. + "\n".. + "The Power Generator takes max. 25 ku of axle power and provides on the other side max. 24 ku as electricity. So he consumes one ku for the conversion.\n".. + "\n".. + "\n".. + "\n", "In order to transport objects from one processing station to the next\\, pushers and tubes are used. See plan.\n".. "\n".. "\n".. @@ -424,6 +434,8 @@ techage.manual_EN.aText = { "\n".. "The distributor has a menu with 4 filters with different colors\\, corresponding to the 4 outputs. If an output is to be used\\, the corresponding filter must be activated via the \"on\" checkbox. All items that are configured for this filter are output via the assigned output. If a filter is activated without items being configured\\, we are talking about an \"unconfigured\"\\, open output.\n".. "\n".. + "*Attention: The distributor is also a pusher at its output sides. Therefore\\, never pull items out of the distributor with a pusher!*\n".. + "\n".. "There are two operating modes for a non-configured output:\n".. "\n".. "1) Output all items that cannot be output to any other exit\\, even if they are blocked.\n".. @@ -649,6 +661,13 @@ techage.manual_EN.aText = { "\n".. "\n".. "\n", + "The TA3 Electric Motor is required in order to be able to operate TA2 machines via the power grid. The TA3 Electric Motor converts electricity into axle power.\n".. + "If the electric motor is not supplied with sufficient power\\, it goes into an fault state and must be reactivated with a right-click.\n".. + "\n".. + "The electric motor takes max. 40 ku of electricity and provides on the other side max. 39 ku as axle power. So he consumes one ku for the conversion.\n".. + "\n".. + "\n".. + "\n", "The TA3 industrial furnace serves as a supplement to normal furnaces. This means that all goods can be produced with \"cooking\" recipes\\, even in an industrial furnace. But there are also special recipes that can only be made in an industrial furnace.\n".. "The industrial furnace has its own menu for recipe selection. Depending on the goods in the industrial furnace inventory on the left\\, the output product can be selected on the right.\n".. "\n".. @@ -933,7 +952,9 @@ techage.manual_EN.aText = { " - 'pub' switch to public mode\n".. " - 'priv' switch to private mode\n".. "\n".. - "In the private mode\\, only the owner can enter commands himself or use keys.\n".. + "In private mode\\, the terminal can only be used by players who can build at this location\\, i.e. who have protection rights.\n".. + "\n".. + "In public mode\\, all players can use the preconfigured keys.\n".. "\n".. "\n".. "\n", @@ -1060,10 +1081,11 @@ techage.manual_EN.aText = { "\n".. "\n".. "\n", - "A wind turbine always delivers electricity when there is wind. There is no wind in the game\\, but the mod simulates this by only turning the wind turbines in the morning (5:00 a.m. - 9:00 a.m.) and in the evening (5:00 p.m. - 9:00 p.m.) and thus supplying electricity\\, provided they are positioned appropriately.\n".. + "A wind turbine always supplies electricity when there is wind. There is no wind in the game\\, but the mod simulates this by turning the wind turbines only in the morning (5:00 - 9:00) and in the evening (17:00 - 21:00). A wind turbine only supplies electricity if it is set up in a suitable location.\n".. "\n".. - "The TA wind turbines are pure offshore plants\\, which means that they have to be installed in the sea (water). This means that there must be in the minimum 20 blocks of water around the mast and at least 2 blocks deep.\n".. - "The rotor must be placed at a height (Y coordinate) of 12 to a maximum of 20 m. The distance to other wind turbines must be at least 14 m.\n".. + "The TA wind power plants are pure offshore plants\\, which means that they have to be built in the sea. This means that wind turbines can only be build in a sea (occean) biome and that there must be sufficient water and a clear view around the mast.\n".. + "\n".. + "To find a suitable spot\\, click on the water with the wrench (TechAge Info Tool). A chat message will show you whether this position is suitable for the mast of the wind turbine.\n".. "\n".. "The current must be led from the rotor block down through the mast. First pull the power line up and then \"plaster\" the power cable with TA4 pillar blocks. A work platform can be built below. The plan on the right shows the structure in the upper part.\n".. "\n".. @@ -1340,9 +1362,9 @@ techage.manual_EN.aText = { "If something is put into the box or removed\\, or one of the \"F1\" / \"F2\" keys is pressed\\, an event signal is sent to the Lua controller.\n".. "The sensor box supports the following commands:\n".. "\n".. - " - The status of the box can be queried via 'state = $read_data(\\, \"state\")'. Possible answers are: \"empty\"\\, \"loaded\"\\, \"full\"\n".. - " - The last player action can be queried via 'name\\, action = $read_data(\\, \"action\")'. 'name' is the player name. One of the following is returned as 'action': \"put\"\\, \"take\"\\, \"f1\"\\, \"f2\".\n".. - " - The contents of the box can be read out via 'stacks = $read_data(\\, \"stacks\")'. See: https://github.com/joe7575/techage/blob/master/manuals/ta4_lua_controller_EN.md#sensor-chest\n".. + " - The status of the box can be queried via 'state = $send_cmnd(\\, \"state\")'. Possible answers are: \"empty\"\\, \"loaded\"\\, \"full\"\n".. + " - The last player action can be queried via 'name\\, action = $send_cmnd(\\, \"action\")'. 'name' is the player name. One of the following is returned as 'action': \"put\"\\, \"take\"\\, \"f1\"\\, \"f2\".\n".. + " - The contents of the box can be read out via 'stacks = $send_cmnd(\\, \"stacks\")'. See: https://github.com/joe7575/techage/blob/master/manuals/ta4_lua_controller_EN.md#sensor-chest\n".. " - Via '$send_cmnd(\\, \"text\"\\, \"press both buttons andnput something into the chest\")' the text can be set in the menu of the sensor box.\n".. "\n".. "The checkbox \"Allow public chest access\" can be used to set whether the box can be used by everyone or only by players who have access/protection rights here.\n".. @@ -1471,7 +1493,7 @@ techage.manual_EN.aText = { "\n".. "If the chest is filled with a pusher\\, all stores fill from left to right. If all 8 stores are full and no further items can be added\\, further items are rejected.\n".. "\n".. - "* Row function *\n".. + "*Row function*\n".. "\n".. "Several TA4 8x2000 chests can be connected to a large chest with more content. To do this\\, the chests must be placed in a row one after the other.\n".. "\n".. @@ -1488,7 +1510,7 @@ techage.manual_EN.aText = { "\n".. "The chest has an additional command for the Lua controller:\n".. "\n".. - " - 'count' is used to request how many items are in the chest.\nExample 1: '$read_data(CHEST\\, \"count\")' -> Sum of items across all 8 stores\nExample 2: '$read_data(CHEST\\, \"count\"\\, 2)' -> number of items in store 2 (second from left)\n".. + " - 'count' is used to request how many items are in the chest.\nExample 1: '$send_cmnd(CHEST\\, \"count\")' -> Sum of items across all 8 stores\nExample 2: '$send_cmnd(CHEST\\, \"count\"\\, 2)' -> number of items in store 2 (second from left)\n".. "\n".. "\n".. "\n", @@ -1563,6 +1585,7 @@ techage.manual_EN.aItemName = { "ta2_flywheel", "ta2_steampipe", "ta2_driveaxle", + "ta2_generator", "", "tube", "ta2_pusher", @@ -1601,6 +1624,7 @@ techage.manual_EN.aItemName = { "ta3_tinygenerator", "ta3_akkublock", "ta3_powerterminal", + "ta3_motor", "", "ta3_furnacefirebox", "ta3_furnace", @@ -1755,6 +1779,7 @@ techage.manual_EN.aPlanTable = { "", "", "", + "", "itemtransport", "", "", @@ -1793,6 +1818,7 @@ techage.manual_EN.aPlanTable = { "", "", "", + "", "ta3_furnace", "", "", diff --git a/techage/doc/plans.lua b/techage/doc/plans.lua index 3feba0d..2060825 100644 --- a/techage/doc/plans.lua +++ b/techage/doc/plans.lua @@ -185,7 +185,7 @@ local PN270 = {"techage_gaspipe_knee.png^[transformR270", "techage:ta4_pipeS"} techage.ConstructionPlans["ta3_tank"] = { {false, false, false, false, false, false, false, false, false, false}, {false, Tubes, PushR, Tubes, Fillr, Tubes, PushR, Tubes, false, false}, - {false, false, false, false, TANK3, PIPEH, PIPEH, Pump, PIPEH, Tank}, + {false, false, false, false, TANK3, PIPEH, PIPEH, Pump, PIPEH, false}, {false, false, false, false, false, false, false, false, false, false}, } diff --git a/techage/energy_storage/generator.lua b/techage/energy_storage/generator.lua index 78f172b..cd36b3a 100644 --- a/techage/energy_storage/generator.lua +++ b/techage/energy_storage/generator.lua @@ -32,7 +32,7 @@ local function formspec(self, pos, nvm) default.gui_bg.. default.gui_bg_img.. default.gui_slots.. - power.formspec_label_bar(0, 0.8, S("Electricity"), PWR_CAPA, nvm.provided).. + power.formspec_label_bar(pos, 0, 0.8, S("Electricity"), PWR_CAPA, nvm.provided).. "image_button[2.8,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]".. "tooltip[2.8,2;1,1;"..self:get_state_tooltip(nvm).."]" end diff --git a/techage/energy_storage/heatexchanger2.lua b/techage/energy_storage/heatexchanger2.lua index 6069e14..55fcf86 100644 --- a/techage/energy_storage/heatexchanger2.lua +++ b/techage/energy_storage/heatexchanger2.lua @@ -44,8 +44,8 @@ local function formspec(self, pos, nvm) default.gui_slots.. "box[0,-0.1;5.8,0.5;#c6e8ff]".. "label[2,-0.1;"..minetest.colorize( "#000000", S("Heat Exchanger")).."]".. - power.formspec_label_bar(0, 0.8, S("Electricity"), needed_max, needed).. - power.formspec_label_bar(3.5, 0.8, S("Thermal"), capa_max, capa, "").. + power.formspec_label_bar(pos, 0, 0.8, S("Electricity"), needed_max, needed).. + power.formspec_label_bar(pos, 3.5, 0.8, S("Thermal"), capa_max, capa, "").. arrow.. "image_button[2.5,3;1,1;".. self:get_state_button_image(nvm) ..";state_button;]".. "tooltip[2.5,3;1,1;"..self:get_state_tooltip(nvm).."]" diff --git a/techage/furnace/cooking.lua b/techage/furnace/cooking.lua index 2f188aa..4583407 100644 --- a/techage/furnace/cooking.lua +++ b/techage/furnace/cooking.lua @@ -111,7 +111,7 @@ local function process(inv, recipe, output) if recipe.waste then local leftover = inv:add_item("dst", ItemStack(recipe.waste)) if leftover:get_count() > 0 then - inv:set_list("src", leftover) + inv:add_item("src", leftover) return techage.BLOCKED end end diff --git a/techage/furnace/furnace_top.lua b/techage/furnace/furnace_top.lua index 1b70eee..6e0dafc 100644 --- a/techage/furnace/furnace_top.lua +++ b/techage/furnace/furnace_top.lua @@ -242,7 +242,12 @@ local tubing = { end end, on_recv_message = function(pos, src, topic, payload) - return CRD(pos).State:on_receive_message(pos, topic, payload) + if topic == "output" then + local nvm = techage.get_nvm(pos) + return string.split(nvm.output or "unknown", " ")[1] + else + return CRD(pos).State:on_receive_message(pos, topic, payload) + end end, } diff --git a/techage/hydrogen/electrolyzer.lua b/techage/hydrogen/electrolyzer.lua index b83d4eb..13890c5 100644 --- a/techage/hydrogen/electrolyzer.lua +++ b/techage/hydrogen/electrolyzer.lua @@ -44,7 +44,7 @@ local function formspec(self, pos, nvm) default.gui_slots.. "box[0,-0.1;5.8,0.5;#c6e8ff]".. "label[2.5,-0.1;"..minetest.colorize( "#000000", S("Electrolyzer")).."]".. - techage.power.formspec_label_bar(0.1, 0.8, S("Electricity"), PWR_NEEDED, nvm.taken).. + techage.power.formspec_label_bar(pos, 0.1, 0.8, S("Electricity"), PWR_NEEDED, nvm.taken).. arrow.. "image_button[3,2.5;1,1;".. self:get_state_button_image(nvm) ..";state_button;]".. "tooltip[3,2.5;1,1;"..self:get_state_tooltip(nvm).."]".. @@ -156,6 +156,15 @@ local function after_dig_node(pos, oldnode, oldmetadata, digger) Cable:after_dig_node(pos) end +local function put(pos, indir, name, amount) + local leftover = liquid.srv_put(pos, indir, name, amount) + if techage.is_activeformspec(pos) then + local nvm = techage.get_nvm(pos) + M(pos):set_string("formspec", formspec(State, pos, nvm)) + end + return leftover +end + local function tubelib2_on_update2(pos, outdir, tlib2, node) if tlib2.tube_type == "pipe2" then liquid.update_network(pos, outdir, tlib2) @@ -182,14 +191,8 @@ local netw_def = { local liquid_def = { capa = CAPACITY, peek = liquid.srv_peek, - put = function(pos, indir, name, amount) - local leftover = liquid.srv_put(pos, indir, name, amount) - if techage.is_activeformspec(pos) then - local nvm = techage.get_nvm(pos) - M(pos):set_string("formspec", formspec(State, pos, nvm)) - end - return leftover - end, + put = put, + untake = put, take = function(pos, indir, name, amount) amount, name = liquid.srv_take(pos, indir, name, amount) if techage.is_activeformspec(pos) then diff --git a/techage/hydrogen/fuelcell.lua b/techage/hydrogen/fuelcell.lua index 2c7e32a..1c1e040 100644 --- a/techage/hydrogen/fuelcell.lua +++ b/techage/hydrogen/fuelcell.lua @@ -48,7 +48,7 @@ local function formspec(self, pos, nvm) arrow.. "image_button[2,2.5;1,1;".. self:get_state_button_image(nvm) ..";state_button;]".. "tooltip[2,2.5;1,1;"..self:get_state_tooltip(nvm).."]".. - techage.power.formspec_label_bar(3.5, 0.8, S("Electricity"), PWR_CAPA, nvm.given) + techage.power.formspec_label_bar(pos, 3.5, 0.8, S("Electricity"), PWR_CAPA, nvm.given) end local function start_node(pos, nvm, state) diff --git a/techage/i18n.py b/techage/i18n.py index bc46fb5..335716f 100755 --- a/techage/i18n.py +++ b/techage/i18n.py @@ -1,79 +1,448 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # Script to generate the template file and update the translation files. +# Copy the script into the mod or modpack root folder and run it there. # -# Copyright (C) 2019 Joachim Stolberg +# Copyright (C) 2019 Joachim Stolberg, 2020 FaceDeer, 2020 Louis Royer # LGPLv2.1+ -# -# Copy the script into the mod root folder and adapt the last code lines to you needs. +# +# See https://github.com/minetest-tools/update_translations for +# potential future updates to this script. from __future__ import print_function -import os, fnmatch, re, shutil +import os, fnmatch, re, shutil, errno +from sys import argv as _argv +from sys import stderr as _stderr -pattern_lua = re.compile(r'[ \.=^\t]S\("(.+?)"\)', re.DOTALL) -pattern_tr = re.compile(r'(.+?[^@])=(.+)') +# Running params +params = {"recursive": False, + "help": False, + "mods": False, + "verbose": False, + "folders": [], + "no-old-file": False +} +# Available CLI options +options = {"recursive": ['--recursive', '-r'], + "help": ['--help', '-h'], + "mods": ['--installed-mods'], + "verbose": ['--verbose', '-v'], + "no-old-file": ['--no-old-file'] +} -def gen_template(templ_file, lkeyStrings): - lOut = [] - lkeyStrings.sort() - for s in lkeyStrings: - lOut.append("%s=" % s) - open(templ_file, "wt").write("\n".join(lOut)) +# Strings longer than this will have extra space added between +# them in the translation files to make it easier to distinguish their +# beginnings and endings at a glance +doublespace_threshold = 60 +def set_params_folders(tab: list): + '''Initialize params["folders"] from CLI arguments.''' + # Discarding argument 0 (tool name) + for param in tab[1:]: + stop_param = False + for option in options: + if param in options[option]: + stop_param = True + break + if not stop_param: + params["folders"].append(os.path.abspath(param)) + +def set_params(tab: list): + '''Initialize params from CLI arguments.''' + for option in options: + for option_name in options[option]: + if option_name in tab: + params[option] = True + break + +def print_help(name): + '''Prints some help message.''' + print(f'''SYNOPSIS + {name} [OPTIONS] [PATHS...] +DESCRIPTION + {', '.join(options["help"])} + prints this help message + {', '.join(options["recursive"])} + run on all subfolders of paths given + {', '.join(options["mods"])} + run on locally installed modules + {', '.join(options["no-old-file"])} + do not create *.old files + {', '.join(options["verbose"])} + add output information +''') + + +def main(): + '''Main function''' + set_params(_argv) + set_params_folders(_argv) + if params["help"]: + print_help(_argv[0]) + elif params["recursive"] and params["mods"]: + print("Option --installed-mods is incompatible with --recursive") + else: + # Add recursivity message + print("Running ", end='') + if params["recursive"]: + print("recursively ", end='') + # Running + if params["mods"]: + print(f"on all locally installed modules in {os.path.abspath('~/.minetest/mods/')}") + run_all_subfolders("~/.minetest/mods") + elif len(params["folders"]) >= 2: + print("on folder list:", params["folders"]) + for f in params["folders"]: + if params["recursive"]: + run_all_subfolders(f) + else: + update_folder(f) + elif len(params["folders"]) == 1: + print("on folder", params["folders"][0]) + if params["recursive"]: + run_all_subfolders(params["folders"][0]) + else: + update_folder(params["folders"][0]) + else: + print("on folder", os.path.abspath("./")) + if params["recursive"]: + run_all_subfolders(os.path.abspath("./")) + else: + update_folder(os.path.abspath("./")) + +#group 2 will be the string, groups 1 and 3 will be the delimiters (" or ') +#See https://stackoverflow.com/questions/46967465/regex-match-text-in-either-single-or-double-quote +pattern_lua_s = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*(["\'])((?:\\\1|(?:(?!\1)).)*)(\1)[\s,\)]', re.DOTALL) +pattern_lua_fs = re.compile(r'[\.=^\t,{\(\s]N?FS\(\s*(["\'])((?:\\\1|(?:(?!\1)).)*)(\1)[\s,\)]', re.DOTALL) +pattern_lua_bracketed_s = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*\[\[(.*?)\]\][\s,\)]', re.DOTALL) +pattern_lua_bracketed_fs = re.compile(r'[\.=^\t,{\(\s]N?FS\(\s*\[\[(.*?)\]\][\s,\)]', re.DOTALL) + +# Handles "concatenation" .. " of strings" +pattern_concat = re.compile(r'["\'][\s]*\.\.[\s]*["\']', re.DOTALL) + +pattern_tr = re.compile(r'(.*?[^@])=(.*)') +pattern_name = re.compile(r'^name[ ]*=[ ]*([^ \n]*)') +pattern_tr_filename = re.compile(r'\.tr$') +pattern_po_language_code = re.compile(r'(.*)\.po$') + +#attempt to read the mod's name from the mod.conf file. Returns None on failure +def get_modname(folder): + try: + with open(os.path.join(folder, "mod.conf"), "r", encoding='utf-8') as mod_conf: + for line in mod_conf: + match = pattern_name.match(line) + if match: + return match.group(1) + except FileNotFoundError: + pass + return None + +#If there are already .tr files in /locale, returns a list of their names +def get_existing_tr_files(folder): + out = [] + for root, dirs, files in os.walk(os.path.join(folder, 'locale/')): + for name in files: + if pattern_tr_filename.search(name): + out.append(name) + return out + +# A series of search and replaces that massage a .po file's contents into +# a .tr file's equivalent +def process_po_file(text): + # The first three items are for unused matches + text = re.sub(r'#~ msgid "', "", text) + text = re.sub(r'"\n#~ msgstr ""\n"', "=", text) + text = re.sub(r'"\n#~ msgstr "', "=", text) + # comment lines + text = re.sub(r'#.*\n', "", text) + # converting msg pairs into "=" pairs + text = re.sub(r'msgid "', "", text) + text = re.sub(r'"\nmsgstr ""\n"', "=", text) + text = re.sub(r'"\nmsgstr "', "=", text) + # various line breaks and escape codes + text = re.sub(r'"\n"', "", text) + text = re.sub(r'"\n', "\n", text) + text = re.sub(r'\\"', '"', text) + text = re.sub(r'\\n', '@n', text) + # remove header text + text = re.sub(r'=Project-Id-Version:.*\n', "", text) + # remove double-spaced lines + text = re.sub(r'\n\n', '\n', text) + return text + +# Go through existing .po files and, if a .tr file for that language +# *doesn't* exist, convert it and create it. +# The .tr file that results will subsequently be reprocessed so +# any "no longer used" strings will be preserved. +# Note that "fuzzy" tags will be lost in this process. +def process_po_files(folder, modname): + for root, dirs, files in os.walk(os.path.join(folder, 'locale/')): + for name in files: + code_match = pattern_po_language_code.match(name) + if code_match == None: + continue + language_code = code_match.group(1) + tr_name = modname + "." + language_code + ".tr" + tr_file = os.path.join(root, tr_name) + if os.path.exists(tr_file): + if params["verbose"]: + print(f"{tr_name} already exists, ignoring {name}") + continue + fname = os.path.join(root, name) + with open(fname, "r", encoding='utf-8') as po_file: + if params["verbose"]: + print(f"Importing translations from {name}") + text = process_po_file(po_file.read()) + with open(tr_file, "wt", encoding='utf-8') as tr_out: + tr_out.write(text) + +# from https://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python/600612#600612 +# Creates a directory if it doesn't exist, silently does +# nothing if it already exists +def mkdir_p(path): + try: + os.makedirs(path) + except OSError as exc: # Python >2.5 + if exc.errno == errno.EEXIST and os.path.isdir(path): + pass + else: raise + +# Converts the template dictionary to a text to be written as a file +# dKeyStrings is a dictionary of localized string to source file sets +# dOld is a dictionary of existing translations and comments from +# the previous version of this text +def strings_to_text(dkeyStrings, dOld, mod_name, header_comments): + lOut = [f"# textdomain: {mod_name}\n"] + if header_comments is not None: + lOut.append(header_comments) + + dGroupedBySource = {} + + for key in dkeyStrings: + sourceList = list(dkeyStrings[key]) + sourceList.sort() + sourceString = "\n".join(sourceList) + listForSource = dGroupedBySource.get(sourceString, []) + listForSource.append(key) + dGroupedBySource[sourceString] = listForSource + + lSourceKeys = list(dGroupedBySource.keys()) + lSourceKeys.sort() + for source in lSourceKeys: + localizedStrings = dGroupedBySource[source] + localizedStrings.sort() + lOut.append("") + lOut.append(source) + lOut.append("") + for localizedString in localizedStrings: + val = dOld.get(localizedString, {}) + translation = val.get("translation", "") + comment = val.get("comment") + if len(localizedString) > doublespace_threshold and not lOut[-1] == "": + lOut.append("") + if comment != None: + lOut.append(comment) + lOut.append(f"{localizedString}={translation}") + if len(localizedString) > doublespace_threshold: + lOut.append("") + + + unusedExist = False + for key in dOld: + if key not in dkeyStrings: + val = dOld[key] + translation = val.get("translation") + comment = val.get("comment") + # only keep an unused translation if there was translated + # text or a comment associated with it + if translation != None and (translation != "" or comment): + if not unusedExist: + unusedExist = True + lOut.append("\n\n##### not used anymore #####\n") + if len(key) > doublespace_threshold and not lOut[-1] == "": + lOut.append("") + if comment != None: + lOut.append(comment) + lOut.append(f"{key}={translation}") + if len(key) > doublespace_threshold: + lOut.append("") + return "\n".join(lOut) + '\n' + +# Writes a template.txt file +# dkeyStrings is the dictionary returned by generate_template +def write_template(templ_file, dkeyStrings, mod_name): + # read existing template file to preserve comments + existing_template = import_tr_file(templ_file) + + text = strings_to_text(dkeyStrings, existing_template[0], mod_name, existing_template[2]) + mkdir_p(os.path.dirname(templ_file)) + with open(templ_file, "wt", encoding='utf-8') as template_file: + template_file.write(text) + + +# Gets all translatable strings from a lua file def read_lua_file_strings(lua_file): lOut = [] - text = open(lua_file).read() - for s in pattern_lua.findall(text): - s = re.sub(r'"\.\.\s+"', "", s) - s = re.sub("@[^@=n]", "@@", s) - s = s.replace("\n", "@n") - s = s.replace("\\n", "@n") - s = s.replace("=", "@=") - lOut.append(s) + with open(lua_file, encoding='utf-8') as text_file: + text = text_file.read() + #TODO remove comments here + + text = re.sub(pattern_concat, "", text) + + strings = [] + for s in pattern_lua_s.findall(text): + strings.append(s[1]) + for s in pattern_lua_bracketed_s.findall(text): + strings.append(s) + for s in pattern_lua_fs.findall(text): + strings.append(s[1]) + for s in pattern_lua_bracketed_fs.findall(text): + strings.append(s) + + for s in strings: + s = re.sub(r'"\.\.\s+"', "", s) + s = re.sub("@[^@=0-9]", "@@", s) + s = s.replace('\\"', '"') + s = s.replace("\\'", "'") + s = s.replace("\n", "@n") + s = s.replace("\\n", "@n") + s = s.replace("=", "@=") + lOut.append(s) return lOut -def inport_tr_file(tr_file): +# Gets strings from an existing translation file +# returns both a dictionary of translations +# and the full original source text so that the new text +# can be compared to it for changes. +# Returns also header comments in the third return value. +def import_tr_file(tr_file): dOut = {} + text = None + header_comment = None if os.path.exists(tr_file): - for line in open(tr_file, "r").readlines(): - s = line.strip() - if s == "" or s[0] == "#": - continue - match = pattern_tr.match(s) - if match: - dOut[match.group(1)] = match.group(2) - return dOut + with open(tr_file, "r", encoding='utf-8') as existing_file : + # save the full text to allow for comparison + # of the old version with the new output + text = existing_file.read() + existing_file.seek(0) + # a running record of the current comment block + # we're inside, to allow preceeding multi-line comments + # to be retained for a translation line + latest_comment_block = None + for line in existing_file.readlines(): + line = line.rstrip('\n') + if line[:3] == "###": + if header_comment is None: + # Save header comments + header_comment = latest_comment_block or "" + # Stip textdomain line + tmp_h_c = "" + for l in header_comment.split('\n'): + if not l.startswith("# textdomain:"): + tmp_h_c += l + '\n' + header_comment = tmp_h_c -def generate_template(templ_file): - lOut = [] - for root, dirs, files in os.walk('./'): + # Reset comment block if we hit a header + latest_comment_block = None + continue + if line[:1] == "#": + # Save the comment we're inside + if not latest_comment_block: + latest_comment_block = line + else: + latest_comment_block = latest_comment_block + "\n" + line + continue + match = pattern_tr.match(line) + if match: + # this line is a translated line + outval = {} + outval["translation"] = match.group(2) + if latest_comment_block: + # if there was a comment, record that. + outval["comment"] = latest_comment_block + latest_comment_block = None + dOut[match.group(1)] = outval + return (dOut, text, header_comment) + +# Walks all lua files in the mod folder, collects translatable strings, +# and writes it to a template.txt file +# Returns a dictionary of localized strings to source file sets +# that can be used with the strings_to_text function. +def generate_template(folder, mod_name): + dOut = {} + for root, dirs, files in os.walk(folder): for name in files: if fnmatch.fnmatch(name, "*.lua"): fname = os.path.join(root, name) found = read_lua_file_strings(fname) - print(fname, len(found)) - lOut.extend(found) - lOut = list(set(lOut)) - lOut.sort() - gen_template(templ_file, lOut) - return lOut + if params["verbose"]: + print(f"{fname}: {str(len(found))} translatable strings") -def update_tr_file(lNew, mod_name, tr_file): - lOut = ["# textdomain: %s\n" % mod_name] - if os.path.exists(tr_file): - shutil.copyfile(tr_file, tr_file+".old") - dOld = inport_tr_file(tr_file) - for key in lNew: - val = dOld.get(key, "") - lOut.append("%s=%s" % (key, val)) - lOut.append("##### not used anymore #####") - for key in dOld: - if key not in lNew: - lOut.append("%s=%s" % (key, dOld[key])) - open(tr_file, "w").write("\n".join(lOut)) - -data = generate_template("./locale/template.txt") -update_tr_file(data, "techage", "./locale/techage.de.tr") -#update_tr_file(data, "techage", "./locale/techage.fr.tr") -print("Done.\n") + for s in found: + sources = dOut.get(s, set()) + sources.add(f"### {os.path.basename(fname)} ###") + dOut[s] = sources + + if len(dOut) == 0: + return None + templ_file = os.path.join(folder, "locale/template.txt") + write_template(templ_file, dOut, mod_name) + return dOut + +# Updates an existing .tr file, copying the old one to a ".old" file +# if any changes have happened +# dNew is the data used to generate the template, it has all the +# currently-existing localized strings +def update_tr_file(dNew, mod_name, tr_file): + if params["verbose"]: + print(f"updating {tr_file}") + + tr_import = import_tr_file(tr_file) + dOld = tr_import[0] + textOld = tr_import[1] + + textNew = strings_to_text(dNew, dOld, mod_name, tr_import[2]) + + if textOld and textOld != textNew: + print(f"{tr_file} has changed.") + if not params["no-old-file"]: + shutil.copyfile(tr_file, f"{tr_file}.old") + + with open(tr_file, "w", encoding='utf-8') as new_tr_file: + new_tr_file.write(textNew) + +# Updates translation files for the mod in the given folder +def update_mod(folder): + modname = get_modname(folder) + if modname is not None: + process_po_files(folder, modname) + print(f"Updating translations for {modname}") + data = generate_template(folder, modname) + if data == None: + print(f"No translatable strings found in {modname}") + else: + for tr_file in get_existing_tr_files(folder): + update_tr_file(data, modname, os.path.join(folder, "locale/", tr_file)) + else: + print(f"\033[31mUnable to find modname in folder {folder}.\033[0m", file=_stderr) + exit(1) + +# Determines if the folder being pointed to is a mod or a mod pack +# and then runs update_mod accordingly +def update_folder(folder): + is_modpack = os.path.exists(os.path.join(folder, "modpack.txt")) or os.path.exists(os.path.join(folder, "modpack.conf")) + if is_modpack: + subfolders = [f.path for f in os.scandir(folder) if f.is_dir()] + for subfolder in subfolders: + update_mod(subfolder + "/") + else: + update_mod(folder) + print("Done.") + +def run_all_subfolders(folder): + for modfolder in [f.path for f in os.scandir(folder) if f.is_dir()]: + update_folder(modfolder + "/") + + +main() diff --git a/techage/icta_controller/controller.lua b/techage/icta_controller/controller.lua index a41d1c1..a1e6253 100644 --- a/techage/icta_controller/controller.lua +++ b/techage/icta_controller/controller.lua @@ -385,13 +385,9 @@ minetest.register_node("techage:ta4_icta_controller", { on_receive_fields = on_receive_fields, - on_dig = function(pos, node, puncher, pointed_thing) - if minetest.is_protected(pos, puncher:get_player_name()) then - return - end - - techage.remove_node(pos) - minetest.node_dig(pos, node, puncher, pointed_thing) + after_dig_node = function(pos, oldnode, oldmetadata) + techage.remove_node(pos, oldnode, oldmetadata) + techage.del_mem(pos) end, on_timer = on_timer, diff --git a/techage/icta_controller/display.lua b/techage/icta_controller/display.lua index 01208f2..ad8efc6 100644 --- a/techage/icta_controller/display.lua +++ b/techage/icta_controller/display.lua @@ -14,6 +14,8 @@ local S = techage.S +techage.display = {} + local NUM_ROWS = 5 local RADIUS = 6 local Param2ToFacedir = {[0] = 0, 0, 3, 1, 2, 0} @@ -33,7 +35,7 @@ local function lcdlib_bugfix(text_tbl) return "" end -local function display_update(pos, objref) +function techage.display.display_update(pos, objref) pos = vector.round(pos) local nvm = techage.get_nvm(pos) local text = lcdlib_bugfix(nvm.text) @@ -44,7 +46,7 @@ local function display_update(pos, objref) visual_size = {x=0.94, y=0.94} }) end -local function display_updateXL(pos, objref) +function techage.display.display_updateXL(pos, objref) pos = vector.round(pos) local nvm = techage.get_nvm(pos) local text = lcdlib_bugfix(nvm.text) @@ -55,7 +57,7 @@ local function display_updateXL(pos, objref) visual_size = {x=0.94*1.9, y=0.94} }) end -local function on_timer(pos) +function techage.display.on_timer(pos) local mem = techage.get_mem(pos) mem.ticks = mem.ticks or 0 @@ -77,7 +79,7 @@ local function on_timer(pos) return true end -local lcd_box = { +techage.display.lcd_box = { type = "wallmounted", wall_top = {-8/16, 15/32, -8/16, 8/16, 8/16, 8/16} } @@ -90,13 +92,13 @@ minetest.register_node("techage:ta4_display", { paramtype = "light", sunlight_propagates = true, paramtype2 = "wallmounted", - node_box = lcd_box, - selection_box = lcd_box, + node_box = techage.display.lcd_box, + selection_box = techage.display.lcd_box, light_source = 6, display_entities = { ["techage:display_entity"] = { depth = 0.42, - on_display_update = display_update}, + on_display_update = techage.display.display_update}, }, after_place_node = function(pos, placer) @@ -114,7 +116,7 @@ minetest.register_node("techage:ta4_display", { techage.remove_node(pos, oldnode, oldmetadata) end, - on_timer = on_timer, + on_timer = techage.display.on_timer, on_place = lcdlib.on_place, on_construct = lcdlib.on_construct, on_destruct = lcdlib.on_destruct, @@ -124,7 +126,7 @@ minetest.register_node("techage:ta4_display", { sounds = default.node_sound_glass_defaults(), }) -local lcd_boxXL = { +techage.display.lcd_boxXL = { type = "fixed", fixed = {-0.9, -8/16, -8/16, 0.9, -15/32, 8/16} } @@ -137,13 +139,13 @@ minetest.register_node("techage:ta4_displayXL", { paramtype = "light", sunlight_propagates = true, paramtype2 = "wallmounted", - node_box = lcd_boxXL, - selection_box = lcd_boxXL, + node_box = techage.display.lcd_boxXL, + selection_box = techage.display.lcd_boxXL, light_source = 6, display_entities = { ["techage:display_entityXL"] = { depth = 0.42, - on_display_update = display_updateXL}, + on_display_update = techage.display.display_updateXL}, }, after_place_node = function(pos, placer) @@ -161,7 +163,7 @@ minetest.register_node("techage:ta4_displayXL", { techage.remove_node(pos, oldnode, oldmetadata) end, - on_timer = on_timer, + on_timer = techage.display.on_timer, on_place = lcdlib.on_place, on_construct = lcdlib.on_construct, on_destruct = lcdlib.on_destruct, @@ -189,7 +191,7 @@ minetest.register_craft({ }, }) -local function add_line(pos, payload, cycle_time) +function techage.display.add_line(pos, payload, cycle_time) local nvm = techage.get_nvm(pos) local mem = techage.get_mem(pos) nvm.text = nvm.text or {} @@ -206,7 +208,7 @@ local function add_line(pos, payload, cycle_time) table.insert(nvm.text, payload) end -local function write_row(pos, payload, cycle_time) +function techage.display.write_row(pos, payload, cycle_time) local nvm = techage.get_nvm(pos) local mem = techage.get_mem(pos) nvm.text = nvm.text or {} @@ -227,7 +229,7 @@ local function write_row(pos, payload, cycle_time) nvm.text[row] = str end -local function clear_screen(pos, cycle_time) +function techage.display.clear_screen(pos, cycle_time) local nvm = techage.get_nvm(pos) local mem = techage.get_mem(pos) mem.ticks = mem.ticks or 0 @@ -242,11 +244,11 @@ end techage.register_node({"techage:ta4_display"}, { on_recv_message = function(pos, src, topic, payload) if topic == "add" then -- add one line and scroll if necessary - add_line(pos, payload, 1) + techage.display.add_line(pos, payload, 1) elseif topic == "set" then -- overwrite the given row - write_row(pos, payload, 1) + techage.display.write_row(pos, payload, 1) elseif topic == "clear" then -- clear the screen - clear_screen(pos, 1) + techage.display.clear_screen(pos, 1) end end, }) @@ -254,14 +256,14 @@ techage.register_node({"techage:ta4_display"}, { techage.register_node({"techage:ta4_displayXL"}, { on_recv_message = function(pos, src, topic, payload) if topic == "add" then -- add one line and scroll if necessary - add_line(pos, payload, 2) + techage.display.add_line(pos, payload, 2) elseif topic == "set" then -- overwrite the given row - write_row(pos, payload, 2) + techage.display.write_row(pos, payload, 2) elseif topic == "clear" then -- clear the screen - clear_screen(pos, 2) + techage.display.clear_screen(pos, 2) end end, -}) +}) lcdlib.register_display_entity("techage:display_entity") lcdlib.register_display_entity("techage:display_entityXL") diff --git a/techage/init.lua b/techage/init.lua index 5eea301..ee8d76a 100644 --- a/techage/init.lua +++ b/techage/init.lua @@ -13,7 +13,7 @@ techage = {} -- Version for compatibility checks, see readme.md/history -techage.version = 0.23 +techage.version = 0.25 if minetest.global_exists("tubelib") then minetest.log("error", "[techage] Techage can't be used together with the mod tubelib!") @@ -217,6 +217,8 @@ dofile(MP.."/oil/reboiler.lua") -- TA3 power based dofile(MP.."/ta3_power/tiny_generator.lua") dofile(MP.."/ta3_power/akkubox.lua") +dofile(MP.."/ta3_power/axle2power.lua") +dofile(MP.."/ta3_power/power2axle.lua") -- Digtron if minetest.global_exists("digtron") then diff --git a/techage/iron_age/coalburner.lua b/techage/iron_age/coalburner.lua index 55d658e..18ea0e2 100644 --- a/techage/iron_age/coalburner.lua +++ b/techage/iron_age/coalburner.lua @@ -97,6 +97,7 @@ end local function flame(pos, height, heat, first_time) local idx + local playername = minetest.get_meta(pos):get_string("playername") pos = {x=pos.x, y=pos.y+height, z=pos.z} for idx=heat,1,-1 do pos = {x=pos.x, y=pos.y+1, z=pos.z} @@ -113,6 +114,9 @@ local function flame(pos, height, heat, first_time) end return end + if minetest.is_protected(pos, playername) then + return + end minetest.add_node(pos, {name = "techage:flame"..math.min(idx,7)}) local meta = minetest.get_meta(pos) meta:set_int("heat", idx) diff --git a/techage/items/cracking.lua b/techage/items/cracking.lua index 6651bfe..0773d3f 100644 --- a/techage/items/cracking.lua +++ b/techage/items/cracking.lua @@ -46,7 +46,7 @@ techage.recipes.add("ta4_doser", { -- Hydrogenate techage.recipes.add("ta4_doser", { - output = "techage:bitumen 2", + output = "techage:bitumen 1", input = { "techage:fueloil 1", "techage:hydrogen 1", @@ -55,7 +55,7 @@ techage.recipes.add("ta4_doser", { }) techage.recipes.add("ta4_doser", { - output = "techage:fueloil 2", + output = "techage:fueloil 1", input = { "techage:naphtha 1", "techage:hydrogen 1", @@ -64,7 +64,7 @@ techage.recipes.add("ta4_doser", { }) techage.recipes.add("ta4_doser", { - output = "techage:naphtha 2", + output = "techage:naphtha 1", input = { "techage:gasoline 1", "techage:hydrogen 1", diff --git a/techage/lamps/growlight.lua b/techage/lamps/growlight.lua index 5c5c98a..ffbb4b4 100644 --- a/techage/lamps/growlight.lua +++ b/techage/lamps/growlight.lua @@ -20,6 +20,7 @@ local Cable = techage.ElectricCable local power = techage.power local Flowers = {} local Plants = {} +local Ignore = { ["flowers:waterlily_waving"] = true } -- 9 plant positions below the light local Positions = { {x = 0, y =-1, z = 0}, @@ -143,7 +144,9 @@ minetest.after(1, function() if name and type(name) == "string" then local mod = string.split(name, ":")[1] if mod == "flowers" or mod == "bakedclay" then -- Bakedclay also registers flowers as decoration. - techage.register_flower(name) + if not Ignore[name] then + techage.register_flower(name) + end end end end @@ -151,7 +154,9 @@ minetest.after(1, function() if type(name) == "string" then local mod = string.split(name, ":")[1] if mod == "farming" and ndef.on_timer then -- probably a plant that still needs to grow - techage.register_plant(name) + if not Ignore[name] then + techage.register_plant(name) + end end end end diff --git a/techage/liquids/tank.lua b/techage/liquids/tank.lua index 37db737..b2e522e 100644 --- a/techage/liquids/tank.lua +++ b/techage/liquids/tank.lua @@ -217,6 +217,14 @@ minetest.register_node("techage:ta4_tank", { tubelib2_on_update2 = function(pos, outdir, tlib2, node) liquid.update_network(pos, outdir) end, + on_receive_fields = function(pos, formname, fields, player) + if minetest.is_protected(pos, player:get_player_name()) then + return + end + if fields.public then + M(pos):set_int("public", fields.public == "true" and 1 or 0) + end + end, on_timer = node_timer, on_punch = liquid.on_punch, after_dig_node = function(pos, oldnode, oldmetadata, digger) diff --git a/techage/locale/techage.de.tr b/techage/locale/techage.de.tr index fd5419f..f33a388 100644 --- a/techage/locale/techage.de.tr +++ b/techage/locale/techage.de.tr @@ -1,19 +1,70 @@ # textdomain: techage -#### TA3 Terminal ####@n@nSend commands to your machines@nand output text messages from your@nmachines to the Terminal.@n@nCommand syntax:@n cmd @n@nexample: cmd 181 on@n is the number of the node to which the command is sent@n'on' is the command to turn machines/nodes on@nFurther commands can be retrieved by clicking on@nmachines/nodes with the Techage Info Tool.@n@nLocal commands:@n- clear @= clear screen@n- help @= this message@n- pub @= switch to public use@n- priv @= switch to private use@nTo program a user button with a command:@n set @ne.g. 'set 1 ON cmd 123 on'@n= -Accu Box=Akkublock -Active:=Aktiv: -All nodes:=Alle Blöcke: -Allow public chest access=Erlaube öffentlichen Zugriff -Allow to dig/place Techage power lines nearby power poles=Erlaubt TODO + + +### akkubox.lua ### + +TA3 Accu Box=Akkublock +TA3 Akku Box=TA3 Akku Block + +### akkubox.lua ### +### battery.lua ### + +Load=Ladung + +### akkubox.lua ### +### electrolyzer.lua ### +### fuelcell.lua ### +### generator.lua ### +### heatexchanger2.lua ### +### tiny_generator.lua ### + +Electricity=Strom + +### aluminium.lua ### + Aluminum=Aluminium -Area already loaded or max. number of Forceload Blocks reached!=Bereich bereits geladen oder maximale Anzahl von Forceload Blöcken erreicht! -Ash=Asche +Gibbsite Powder=Gibbsit Pulver +Red Mud=Rotschlamm +Red Mud Barrel=Rotschlamm Fass +Red Mud Canister=Rotschlamm Kanister + +### assemble.lua ### +### firebox_lib.lua ### + +[TA] Area is protected!=[TA] Bereich ist geschützt +[TA] Not enough space!=[TA] Nicht ausreichend Platz! + +### autocrafter.lua ### + Autocrafter=Autocrafter -Axle Power Source=Achsenkraftquelle + +### axle2power.lua ### + +TA2 Power Generator=TA2 Stromgenerator + +TA2 Power Generator: Overload fault?@n(restart with right-click)=TA2 Stromgenerator: Überlastfehler?@n(Neustart mit Rechtsklick) + + +### baborium.lua ### + Baborium Ingot=Baboriumbarren Baborium Lump=Baboriumklumpen Baborium Ore=Baboriumerz + +### barrel.lua ### + +Gas Cylinder Large=Gasflasche groß +Gas Cylinder Small=Gasflasche klein +River Water Barrel=Flusswasserfass +TA Empty Barrel=TA leeres Fass +TA3 Canister=TA3 Kanister +Water=Wasser +Water Barrel=Wasserfass +empty=leer + +### basalt.lua ### + Basalt Cobble=Basaltpflaster Basalt Glass=Basaltglas Basalt Glass 2=Basaltglas 2 @@ -25,390 +76,646 @@ Basalt Gravel=Basaltkies Basalt Stone=Basaltgestein Basalt Stone Block=Basaltsteinblock Basalt Stone Brick=Basaltsteinziegel +Sieved Basalt Gravel=Basaltkies gesiebt + +### battery.lua ### + Battery=Batterie +Coal Equivalents=Kohleeinheiten +Digtron Battery=Digtron Akku + +### bauxit.lua ### + Bauxite Cobblestone=Bauxit Kopfsteinpflaster Bauxite Gravel=Bauxit Kies Bauxite Powder=Bauxit Pulver Bauxite Stone=Bauxit -Biome=Biom -Block configured items for open ports=Blockiere konfigurierte Gegenstände für offene Ausgänge -Build derrick=Errichte Ölturm -Catalyst=Katalysator + +### blackhole.lua ### + +TechAge Black Hole=TechAge Schwarzes Loch +TechAge Black Hole (let items and liquids disappear)=TechAge Schwarzes Loch (Gegenstände und Flüssigkeiten verschwinden) + +### boiler.lua ### + +TA2 Boiler Base=TA2 Boiler unten +TA2 Boiler Top=TA2 Boiler oben + +### boiler_base.lua ### + +TA3 Boiler Base=TA3 Boiler unten + +### boiler_lib.lua ### + +To add water punch@nthe boiler@nwith a water bucket=Um Wasser nachzufüllen,@nschlage mit einem Wassereimer@nauf den Block +Water Boiler=Wasserboiler +water temperature=Wassertemperatur + +### boiler_top.lua ### + +TA3 Boiler Top=TA3 Boiler oben + +### booster.lua ### + +TA3 Booster=TA3 Gebläse + +### button.lua ### + +TA3 Button/Switch=TA3 Taster/Schalter +TA4 Button/Switch=TA4 Schalter/Taster + +### button.lua ### +### cart_detector.lua ### +### detector.lua ### +### lua_logic.lua ### +### mesecons_converter.lua ### +### node_detector.lua ### +### player_detector.lua ### +### repeater.lua ### + +Insert destination node number(s)=Gebe Zielnummer(n) ein + +### button.lua ### +### chest.lua ### +### detector.lua ### +### doorcontroller.lua ### +### mesecons_converter.lua ### +### repeater.lua ### + +Save=Speichern + +### cart_detector.lua ### + +TA3 Cart Detector=TA3 Wagen Detektor + +### cart_detector.lua ### +### node_detector.lua ### + +accept=akzeptieren + +### cart_detector.lua ### +### player_detector.lua ### + +TA3 Player Detector=TA3 Spieler Detektor + +### ceilinglamp.lua ### + +TA Ceiling Lamp=TA Deckenlampe + +### cement.lua ### + Cement Block=Zement Block Cement Powder=Zement Pulver -Coal Equivalents=Kohleeinheiten -Compressed Gravel=Komprimiertes Kies -Configure up to 8 items @nto be pushed by the injector=Konfiguriere bis zu 8 Gegenstände \n die vom Injektor weitergegeben werden sollen -Consum. 1=Konsum. 1 -Consum. 2=Konsum. 2 -Current power:=Strom aktuell: -Depth=Tiefe -Digging depth=Grabungstiefe -Digtron Battery=Digtron Akku + +### charcoalpile.lua ### + Dirt with Ash=Erde mit Asche +TA1 Charcoal=TA1 Holzkohle + +### chest.lua ### + +Allow public access to the chest=Erlaube öffentlichen Zugriff auf die Kiste +Inventory,Pre-Assignment,Config=Inventar,Vorbelegung,Konfiguration +Node label:= Blockbeschriftung: +TA2 Protected Chest=TA2 Gesicherte Kiste +TA3 Protected Chest=TA3 Gesicherte Kiste +TA4 Protected Chest=TA4 Gesicherte Kiste + +### chest_cart.lua ### + +TA Chest Cart=TA Kistenwagen + +### coalburner.lua ### + +Ash=Asche + +### collector.lua ### + +Node number to send the events to=Knotennummer zum Senden der Events +Node numbers to read the states from=Knotennummern zum Lesen der Zustände +Send an event if state is equal or larger than=Senden ein Event wenn Status größer oder gleich als +TA4 State Collector=TA4 Zuständesammler + +### cooking.lua ### + +TA3 Melting=TA3 Schmelzen + +### cooler.lua ### + +TA3 Cooler=TA3 Kühler + +### cylinder.lua ### + +TA2 Cylinder=TA2 Zylinder + +### detector.lua ### + +TA3 Detector=TA3 Detektor +TA4 Detector=TA4 Detektor + +### display.lua ### + Display no: = Display Nr. +TA4 Display=TA4 Display +TA4 Display XL=TA4 Display XL + +### distiller.lua ### + +TA3 Distillation Tower 1=TA3 Destillationsturm 1 +TA3 Distillation Tower 2=TA3 Destillationsturm 2 +TA3 Distillation Tower 3=TA3 Destillationsturm 3 +TA3 Distillation Tower 4=TA3 Destillationsturm 4 +TA3 Distillation Tower Base=TA3 Destillationsturm Basis + +### distributor.lua ### + +Block configured items for open ports=Blockiere konfigurierte Gegenstände für offene Ausgänge Distributor=Verteiler -Doser=Dosierer +High Performance Distributor=Hochleistungs-Verteiler +Input=Einspeisung +blocking mode=Blockiert + +### doorblock.lua ### + +TechAge Door Block=TechAge Türblock + +### doorcontroller.lua ### + +Insert door/gate block number(s)=Gebe Tür-/Tornummer(n) ein +TA3 Door Controller=TA3 Tür Controller + +### doorcontroller.lua ### +### repeater.lua ### + +TA3 Repeater=TA3 Wiederholer + +### drillbox.lua ### + +Build derrick=Errichte Ölturm +Depth=Tiefe Drill Bit=Bohrstange Drill area is protected=Bohrbereich ist geschützt Drill bits missing=Bohrgestänge fehlt -Ele Power Source=Ele Kraftquelle -Electricity=Strom +Oil Drill Box=Ölbohrkiste +Remove derrick=Entferne Ölturm +item output blocked=Ausgang blockiert + +### drive_axle.lua ### + +TA2 Drive Axle=TA2 Antriebsachse + +### electric_cable.lua ### + +TA Electric Cable=TA Stromkabel + +### electrolyzer.lua ### + +TA4 Electrolyzer=TA4 Elektrolyseur +full=voll + +### electrolyzer.lua ### +### power_terminal2.lua ### + Electrolyzer=Eletrolyseur + +### electronic.lua ### + +TA3 Vacuum Tube=TA3 Vakuumröhre +TA4 LEDs=TA4 LEDs +TA4 RAM Chip=RAM Chip +TA4 WLAN Chip=TA4 WLAN Chip +WLAN Chip=WLAN Chip + +### electronic_fab.lua ### + Electronic Fab=Elektronikfabrik -Empty the slots always @nfrom right to left=Speicherplätze von rechts nach links leeren -Energy storage=Engergiespeicher -Energy stored:=Energie gespeichert -Enter=Eingeben +TA2 Ele Fab=TA2 E-Fabrik +TA3 Ele Fab=TA3 E-Fabrik +TA4 Ele Fab=TA4 E-Fabrik + +### epoxy.lua ### + Epoxide Resin=Epoxidharz Epoxide Resin Barrel=Epoxidharz Fass Epoxide Resin Canister=Epoxidharz Kanister -Error=Fehler + +### explore.lua ### + +Oil=Öl +TA3 Oil Explorer=TA3 Ölexplorer +TA3 Oil Storage=TA3 Öl Speicher +depth=Tiefe + +### filler.lua ### + +Liquid Filler=Einfülltrichter +TA Liquid Filler=TA Einfülltrichter + +### firebox.lua ### + +TA2 Firebox=TA2 Feuerkiste +TA3 Coal Power Station Firebox=TA3 Kohlekraftwerks-Feuerbox +TA3 Furnace Oil Burner=TA3 Ofen-Ölbrenner +TA3 Power Station Firebox=TA3 Kraftwerks-Feuerbox + +### firebox_lib.lua ### + Firebox=Feuerkasten -Flint and Iron=Flint and Iron -Flowing Oil=Fließendes Öl + +### flywheel.lua ### + Flywheel=Schwungrad -Fuel Cell=Brennstoffzelle +TA2 Flywheel=TA2 Schwungrad + +### flywheel.lua ### +### generator.lua ### +### solarcell.lua ### +### source.lua ### + +power=Energie + +### forceload.lua ### + +Area already loaded or max. number of Forceload Blocks reached!=Bereich bereits geladen oder maximale Anzahl von Forceload Blöcken erreicht! + +List of your Forceload Blocks:=Liste der Forceload Blöcke +Priv missing=Rechte fehlen +Punch the block to make the area visible.=Schlage auf den Bock um den Bereich anzuzeigen. +Show all forceload blocks in a 64x64x64 range=Zeige alle Forceload Blöcke im Umkreis von 64x64x64 Blöcken +Techage Forceload Block=Techage Forceload Block +Techage Forceload Tile=Techage Forceload Kachel +loaded=geladen + +### fuel_lib.lua ### + Fuel Menu=Brennstoff Menü -Fuel cell=Brennstoffzelle +To add fuel punch@nthis block@nwith a fuel container=Um Brennstoff nachzufüllen,@nschlage mit einem Kraftstoffbehälter@nauf den Block + +### fuelcell.lua ### + +Fuel Cell=Brennstoffzelle +TA4 Fuel Cell=TA4 Brennstoffzelle + +### fuelcellstack.lua ### + +TA4 Fuel Cell Stack=Brennstoffzellenstapel + +### furnace_top.lua ### + Furnace Top=Ofenoberteil -Gas Cylinder Large=Gasflasche groß -Gas Cylinder Small=Gasflasche klein -Genera. 1=Genera. 1 -Genera. 2=Genera. 2 +Outp=Ergeb. +no fuel or no power=kein Strom oder Brennstoff + +### gateblock.lua ### + +TechAge Gate Block=TechAge Torblock + +### gearbox.lua ### + +TA2 Gearbox=TA2 Getriebeblock + +### generator.lua ### + Generator=Generator -Generators=Generatoren -Gibbsite Powder=Gibbsit Pulver +TA3 Generator=TA3 Generator +TA4 Generator=TA4 Generator +storage empty?=Speicher leer? + +### gravelrinser.lua ### + Gravel Rinser=Kiesspüler +Rinsing=Waschen + +### gravelsieve.lua ### + +Compressed Gravel=Komprimiertes Kies Gravel Sieve=Kiessieb +Sieved Gravel=Gesiebtes Kies +TA1 Gravel Sieve=TA1 Kiessieb +TA2 Gravel Sieve=TA2 Kiessieb +TA3 Gravel Sieve=TA3 Kiessieb +TA4 Gravel Sieve=TA4 Kiessieb + +### grinder.lua ### + Grinder=Mühle Grinding=Mahlen -Heat=Hitze + +### growlight.lua ### + +TA4 LED Grow Light=TA4 LED Pflanzenlampe + +### guide.lua ### + +No plan available=Kein Plan verfügar +Plan=Plan + +### hammer.lua ### + +TA1 Bronze Hammer (smash stone to gravel)=TA1 Bronzehammer (zerschlage Stein zu Kies) +TA1 Diamond Hammer (smash stone to gravel)=TA1 Diamanthammer (zerschlage Stein zu Kies) +TA1 Meridium Hammer (smash stone to gravel)=TA1 Meridiumhammer (zerschlage Stein zu Kies) +TA1 Mese Hammer (smash stone to gravel)=TA1 Mesehammer (zerschlage Stein zu Kies) +TA1 Steel Hammer (smash stone to gravel)=TA1 Stahlhammer (zerschlage Stein zu Kies) +TA1 Stone Hammer (smash stone to gravel)=TA1 Steinhammer (zerschlage Stein zu Kies) + +### heater.lua ### + +TA4 Furnace Heater=TA4 Ofenheizung + +### heatexchanger1.lua ### + +TA4 Heat Exchanger 1=TA4 Wärmetauscher 1 +inlet/pipe error=Einlass/Röhrenfehler +wrong storage diameter=Falscher Wärmespeicher-Durchmesser + +### heatexchanger1.lua ### +### heatexchanger2.lua ### + +did you check the plan?=hast du den Plan geprüft? + +### heatexchanger2.lua ### + Heat Exchanger=Wärmetauscher -High Performance Distributor=Hochleistungs-Verteiler -Hole size=Lochgröße +TA4 Heat Exchanger=TA4 Wärmetauscher +TA4 Heat Exchanger 2=TA4 Wärmetauscher 2 +Thermal=Wärme + +### heatexchanger3.lua ### + +TA4 Heat Exchanger 3=TA4 Wärmetauscher 3 + +### hydrogen.lua ### + Hydrogen Cylinder Large=Wasserstoffflasche groß Hydrogen Cylinder Small=Wasserstoffflasche klein -In use:=In Benutzung: -Injector=Injektor -Input=Einspeisung -Insert destination node number(s)=Gebe Zielnummer(n) ein -Insert door/gate block number(s)=Gebe Tür-/Tornummer(n) ein -Intake=Stromaufnahme -Inventory,Configuration=Inventar,Konfiguration +TA4 Hydrogen=TA4 Wasserstoff + +### industriallamp1.lua ### + +TA Industrial Lamp 1=TA Industrielampe 1 + +### industriallamp2.lua ### + +TA Industrial Lamp 2=TA Industrielampe 2 + +### industriallamp3.lua ### + +TA Industrial Lamp 3=TA Industrielampe 3 + +### industriallamp4.lua ### + +TA4 LED Industrial Lamp=TA4 LED Industrielampe + +### inlet.lua ### + +TA4 Pipe Inlet=TA4 Rohrzulauf + +### inverter.lua ### + Inverter=Wechselrichter -Iron Powder=Eisen Pulver -Leave Powder=Laub Pulver -Liquid Filler=Einfülltrichter -Liquid Sampler=Flüssigkeitensammler -Liquid Tank=Flüssigkeitstank -List of your Forceload Blocks:=Liste der Forceload Blöcke -Load=Ladung -Lye=Lauge -Lye Barrel=Lauge Fass -Lye Canister=Lauge Kanister -Max. needed power=Max. benötigter Strom -Maximum power:=Maximalstrom: -Melting Guide=Schmelzführer -Melting Pot active (heat@==Schmelztiegel aktiv (Hitze@= -Melting Pot inactive (heat@==Schmelztiegel inaktiv (Hitze@= -Melting Pot inactive (heat@=0)=Schmelztiegel inaktiv (Hitze@=0) -Menu=Menü -Menu,Recipes=Menü,Rezepte -Meridium Axe=Meridium Axt -Meridium Pickaxe=Meridium Pickel -Meridium Shovel=Meridium Schaufel -Meridium Sword=Meridium Schwert -More water expected (2 m deep)!=Mehr Wasser erwartet (2 m tief) -Nacelle is missing=Die Gondel fehlt -Needle Powder=Nadel Pulver -Network Data=Netzwerkdaten -Never completely empty the slots@nwith the pusher to keep the item assignment=Speicherplätze mit dem Schieber nie ganz@nleeren, um die Item-Zuordnung beizubehalten -No network or active generator available!=Kein Stromnetz oder aktiver Generator verfügbar -No plan available=Kein Plan verfügar -No power grid or running generator!=Kein Stromnetz oder Generator verfügbar! -No wind at this altitude!=Kein Wind auf dieser Höhe -Node number to send the events to=Knotennummer zum Senden der Events -Node numbers to read the states from=Knotennummern zum Lesen der Zustände -Node owner=Blockbesitzer -Number blocks:=Anzahl Blöcke: -Number of all nodes=Anzahl aller Blöcke -Number of power grid blocks=Anzahl der Stromnetz Blöcke -Oil=Öl -Oil Drill Box=Ölbohrkiste -Oil Pumpjack=Ölpumpe -Oil Source=Erdöl -Oil Tank=Öltank -Oil amount=Ölmenge -Optionally configure@nthe pusher with one item=Der Schieber kann optional@nmit einem Gegenstand@nkonfiguriert werden -Outp=Ergeb. -Output=Stromabgabe -Plan=Plan -Plastic Granules=Plastikgranulat -Position=Position -Position temperature=Positionstemperatur Power AC=Wechselstrom Power DC=Gleichstrom -Power Source=Stromquelle -Power grid total=Stromnetz gesammt -Power station=Kraftwerk -Priv missing=Rechte fehlen -Probably too many consumers (=Vermutlich zu viele Verbraucher ( -Propane Cylinder Large=Propangasflasche groß -Propane Cylinder Small=Propangasflasche klein -Pumpjack=Ölpumpe -Punch the block to make the area visible.=Schlage auf den Bock um den Bereich anzuzeigen. -Pusher=Schieber -Quarry=Steinbrecher -Recipe=Rezept -Red Mud=Rotschlamm -Red Mud Barrel=Rotschlamm Fass -Red Mud Canister=Rotschlamm Kanister -Red Stone=Rotstein -Red Stone Block=Rotsteinblock -Red Stone Brick=Rotsteinziegel -Remove derrick=Entferne Ölturm -Rinsing=Waschen -River Water Barrel=Flusswasserfass -Save=Speichern -Select type=Wähle Typ -Send an event if state is equal or larger than=Senden ein Event wenn Status größer oder gleich als -Send signal if nodes have been:=Sende ein Signal falls Blöcke: -Show all forceload blocks in a 64x64x64 range=Zeige alle Forceload Blöcke im Umkreis von 64x64x64 Blöcken -Sieved Basalt Gravel=Basaltkies gesiebt -Sieved Gravel=Gesiebtes Kies -Size=Größe -Solar system=Solaranlage -Start level=Startebene -Start level @= 0@nmeans the same level@nas the quarry is placed=Startebene @= 0@nbedeutet gleiche Ebene@nwie der Steinbrecher -Steam Power Source=Dampfenergiequelle -Storage systems=Speichersysteme -Store=Speichern -Switched to private use!=Zur privaten Nutzung umgeschaltet -Switched to public use!=Zur öffentlichen Nutzung umgeschaltet -Syntax error, try help=Syntax Fehler, nutze help -TA Ceiling Lamp=TA Deckenlampe -TA Chest Cart=TA Kistenwagen -TA Electric Cable=TA Stromkabel +TA4 Solar Inverter=TA4 Solar Wechselrichter + +### junctionbox.lua ### + TA Electric Junction Box=TA Verteilerdose -TA Empty Barrel=TA leeres Fass -TA Industrial Lamp 1=TA Industrielampe 1 -TA Industrial Lamp 2=TA Industrielampe 2 -TA Industrial Lamp 3=TA Industrielampe 3 -TA Junction Pipe=TA Leitungskupplung -TA Lamp=TA Lampe + +### lampholder.lua ### + TA Lamp Holder Acacia=TA Lampenhalter Akazie TA Lamp Holder Apple=TA Lampenhalter Apfel TA Lamp Holder Aspen=TA Lampenhalter Espe TA Lamp Holder Copper=TA Lampenhalter Kupfer TA Lamp Holder Gold=TA Lampenhalter Gold TA Lamp Holder White=TA Lampenhalter Weiß -TA Liquid Filler=TA Einfülltrichter + +### lib.lua ### +### sensorchest.lua ### + +connected with=verbunden mit + +### lighter.lua ### + +TA1 Lighter=TA1 Anzünder + +### liquid_lib.lua ### + +Allow public access to the tank=Erlaube öffentlichen Zugriff auf den Tank +Liquid Tank=Flüssigkeitstank +To add liquids punch@nthe tank@nwith a liquid container=Um Flüssigkeit nachzufüllen,@nschlage mit einem Flüssigkeitsbehälter@nauf den Block + +### liquid_pipe.lua ### + +TA Junction Pipe=TA Leitungskupplung TA Pipe=TA Leitung (Flüssigkeiten) + +### liquidsampler.lua ### + +Liquid Sampler=Flüssigkeitensammler + +### liquidsampler.lua ### +### waterpump.lua ### + +no usable water=Kein brauchbares Wasser + +### lua_logic.lua ### + +TA3 Logic Block=TA3 Logikblock +Update=Update + +### lua_logic.lua ### +### power_terminal2.lua ### + +Store=Speichern + +### lye.lua ### + +Lye=Lauge +Lye Barrel=Lauge Fass +Lye Canister=Lauge Kanister + +### meltingpot.lua ### + +Heat=Hitze +Melting Guide=Schmelzführer +Melting Pot active (heat@==Schmelztiegel aktiv (Hitze@= +Melting Pot inactive (heat@==Schmelztiegel inaktiv (Hitze@= +Melting Pot inactive (heat@=0)=Schmelztiegel inaktiv (Hitze@=0) +Menu=Menü +Menu,Recipes=Menü,Rezepte +TA1 Burning=TA1 Brennen +TA1 Melting=TA1 Schmelzen +TA1 Melting Pot=TA1 Schmelztiegel + +### meltingpot.lua ### +### repairkit.lua ### + +Time=Zeit + +### meridium.lua ### + +Meridium Axe=Meridium Axt +Meridium Pickaxe=Meridium Pickel +Meridium Shovel=Meridium Schaufel +Meridium Sword=Meridium Schwert + +### mesecons_converter.lua ### + +TA3 Mesecons Converter=TA3 Mesecons Konverter + +### minicell.lua ### + +TA4 Streetlamp Solar Cell=TA4 Straßenlampen-Solarzelle + +### node_detector.lua ### + +Send signal if nodes have been:=Sende ein Signal falls Blöcke: +TA3 Node Detector=TA3 Block Detektor +added=hinzugefügt wird +added or removed=hinzugefügt oder entfernt wird +removed=entfernt + +### nodes.lua ### + +TechAge Gravel=TechAge Kies + +### oil.lua ### + +Flowing Oil=Fließendes Öl +Oil Source=Erdöl +TA3 Oil Barrel=TA3 Ölfass +TA3 Oil Canister=TA3 Erdölkanister + +### oilfirebox.lua ### + +TA3 Power Station Oil Burner=TA3 Kraftwerks-Ölbrenner + +### petroleum.lua ### + +Propane Cylinder Large=Propangasflasche groß +Propane Cylinder Small=Propangasflasche klein +TA3 Bitumen=TA3 Bitumen +TA3 Bitumen Barrel=TA3 Bitumenfass +TA3 Bitumen Canister=TA3 Bitumenkanister +TA3 Fuel Oil=TA3 Schweröl +TA3 Fuel Oil Barrel=TA3 Schwerölfass +TA3 Fuel Oil Canister=TA3 Schwerölkanister +TA3 Gasoline=TA3 Benzin +TA3 Gasoline Barrel=TA3 Benzinfass +TA3 Gasoline Canister=TA3 Benzinkanister +TA3 Naphtha=TA3 Naphtha +TA3 Naphtha Barrel=TA3 Naphtha-Fass +TA3 Naphtha Canister=TA3 Naphtha-Kanister +TA3 Propane=TA3 Propan + +### pillar.lua ### + +TA4 Pillar=TA4 Säule + +### pipe_wall_entry.lua ### + +TA3 Pipe Wall Entry=TA3 Rohr/Wanddurchbruch + +### pipe_wrench.lua ### + +TA3 Drill Pipe Wrench=TA3 Bohrgestängezange + +### plastic.lua ### + +Plastic Granules=Plastikgranulat + +### player_detector.lua ### + +TA4 Player Detector=TA4 Spieler Detektor + +### powder.lua ### + +Iron Powder=Eisen Pulver +Leave Powder=Laub Pulver +Needle Powder=Nadel Pulver + +### power2axle.lua ### + +TA3 Electric Motor=TA3 Elektromotor + +TA3 Electric Motor: Overload fault?@n(restart with right-click)=TA3 Elektromotor: Überlastfehler?@n(Neustart mit Rechtsklick) + + +### power_line.lua ### + TA Power Line=TA Stromleitung TA Power Pole=TA Strommast TA Power Pole Top (for up to 6 connections)=TA Strommastkopf (für bis zu 6 Verbindungen) TA Power Pole Top 2 (for landlines)=TA Strommastkopf 2 (für Überlandleitungen) -TA Power Switch=TA Stromschalter -TA Power Switch Box=TA Stromschalterbox -TA Power Switch Small=TA Stromschalter klein -TA Street Lamp=TA Straßenlampe -TA Tank Cart=TA Tankwagen -TA Valve=TA Ventil -TA1 Bronze Hammer (smash stone to gravel)=TA1 Bronzehammer (zerschlage Stein zu Kies) -TA1 Burning=TA1 Brennen -TA1 Charcoal=TA1 Holzkohle -TA1 Diamond Hammer (smash stone to gravel)=TA1 Diamanthammer (zerschlage Stein zu Kies) -TA1 Gravel Sieve=TA1 Kiessieb -TA1 Iron Ingot=TA1 Eisenbarren -TA1 Lighter=TA1 Anzünder -TA1 Melting=TA1 Schmelzen -TA1 Melting Pot=TA1 Schmelztiegel -TA1 Meridium Hammer (smash stone to gravel)=TA1 Meridiumhammer (zerschlage Stein zu Kies) -TA1 Mese Hammer (smash stone to gravel)=TA1 Mesehammer (zerschlage Stein zu Kies) -TA1 Steel Hammer (smash stone to gravel)=TA1 Stahlhammer (zerschlage Stein zu Kies) -TA1 Stone Hammer (smash stone to gravel)=TA1 Steinhammer (zerschlage Stein zu Kies) -TA2 Boiler Base=TA2 Boiler unten -TA2 Boiler Top=TA2 Boiler oben -TA2 Cylinder=TA2 Zylinder -TA2 Drive Axle=TA2 Antriebsachse -TA2 Ele Fab=TA2 E-Fabrik -TA2 Firebox=TA2 Feuerkiste -TA2 Flywheel=TA2 Schwungrad -TA2 Gearbox=TA2 Getriebeblock -TA2 Gravel Sieve=TA2 Kiessieb -TA2 Protected Chest=TA2 Gesicherte Kiste -TA2 Steam Pipe=TA2 Dampfleitung -TA3 Accu Box=Akkublock -TA3 Akku Box=TA3 Akku Block -TA3 Bitumen=TA3 Bitumen -TA3 Bitumen Barrel=TA3 Bitumenfass -TA3 Bitumen Canister=TA3 Bitumenkanister -TA3 Boiler Base=TA3 Boiler unten -TA3 Boiler Top=TA3 Boiler oben -TA3 Booster=TA3 Gebläse -TA3 Button/Switch=TA3 Taster/Schalter -TA3 Canister=TA3 Kanister -TA3 Cart Detector=TA3 Wagen Detektor -TA3 Coal Power Station Firebox=TA3 Kohlekraftwerks-Feuerbox -TA3 Cooler=TA3 Kühler -TA3 Derrick=TA3 Bohrturm -TA3 Detector=TA3 Detektor -TA3 Distillation Tower 1=TA3 Destillationsturm 1 -TA3 Distillation Tower 2=TA3 Destillationsturm 2 -TA3 Distillation Tower 3=TA3 Destillationsturm 3 -TA3 Distillation Tower 4=TA3 Destillationsturm 4 -TA3 Distillation Tower Base=TA3 Destillationsturm Basis -TA3 Door Controller=TA3 Tür Controller -TA3 Drill Pipe=TA3 Bohrgestänge -TA3 Drill Pipe Wrench=TA3 Bohrgestängezange -TA3 Ele Fab=TA3 E-Fabrik -TA3 Fuel Oil=TA3 Schweröl -TA3 Fuel Oil Barrel=TA3 Schwerölfass -TA3 Fuel Oil Canister=TA3 Schwerölkanister -TA3 Furnace Oil Burner=TA3 Ofen-Ölbrenner -TA3 Gasoline=TA3 Benzin -TA3 Gasoline Barrel=TA3 Benzinfass -TA3 Gasoline Canister=TA3 Benzinkanister -TA3 Generator=TA3 Generator -TA3 Gravel Sieve=TA3 Kiessieb -TA3 Logic Block=TA3 Logikblock -TA3 Melting=TA3 Schmelzen -TA3 Mesecons Converter=TA3 Mesecons Konverter -TA3 Naphtha=TA3 Naphtha -TA3 Naphtha Barrel=TA3 Naphtha-Fass -TA3 Naphtha Canister=TA3 Naphtha-Kanister -TA3 Node Detector=TA3 Block Detektor -TA3 Oil Barrel=TA3 Ölfass -TA3 Oil Canister=TA3 Erdölkanister -TA3 Oil Explorer=TA3 Ölexplorer -TA3 Oil Reboiler=TA3 Aufkocher -TA3 Oil Reboiler: blocked=TA3 Aufkocher: blockiert -TA3 Oil Storage=TA3 Öl Speicher -TA3 Pipe Wall Entry=TA3 Rohr/Wanddurchbruch -TA3 Player Detector=TA3 Spieler Detektor -TA3 Power Station Firebox=TA3 Kraftwerks-Feuerbox -TA3 Power Station Oil Burner=TA3 Kraftwerks-Ölbrenner -TA3 Power Terminal=TA3 Strom Terminal + +### power_terminal.lua ### + +Active:=Aktiv: +All nodes:=Alle Blöcke: +Consum. 1=Konsum. 1 +Consum. 2=Konsum. 2 +Genera. 1=Genera. 1 +Genera. 2=Genera. 2 +In use:=In Benutzung: +No network or active generator available!=Kein Stromnetz oder aktiver Generator verfügbar +Number of all nodes=Anzahl aller Blöcke TA3 Power Terminal Old=TA3 Strom Terminal Alt -TA3 Propane=TA3 Propan -TA3 Protected Chest=TA3 Gesicherte Kiste -TA3 Pump=TA3 Pumpe -TA3 Repeater=TA3 Wiederholer -TA3 Sequencer=TA3 Sequenzer -TA3 Silo=TA3 Silo -TA3 Tank=TA3 Tank -TA3 Terminal=TA3 Terminal -TA3 Timer=TA3 Timer -TA3 Tiny Power Generator=TA3 Kleiner Stromgenerator -TA3 Turbine=TA3 Turbine -TA3 Vacuum Tube=TA3 Vakuumröhre -TA3 Valve closed=TA3 Ventil zu -TA3 Valve open=TA3 Ventil offen -TA4 8x2000 Chest=TA4 8x2000 Kiste -TA4 Button/Switch=TA4 Schalter/Taster -TA4 Carbon Fiber=TA4 Kohlefaser -TA4 Derrick=TA4 Bohrturm -TA4 Detector=TA4 Detektor -TA4 Display=TA4 Display -TA4 Display XL=TA4 Display XL -TA4 Doser=TA4 Dosierer -TA4 Ele Fab=TA4 E-Fabrik -TA4 Electrolyzer=TA4 Elektrolyseur -TA4 Fuel Cell=TA4 Brennstoffzelle -TA4 Fuel Cell Stack=Brennstoffzellenstapel -TA4 Furnace Heater=TA4 Ofenheizung -TA4 Generator=TA4 Generator -TA4 Gravel Sieve=TA4 Kiessieb -TA4 Heat Exchanger=TA4 Wärmetauscher -TA4 Heat Exchanger 1=TA4 Wärmetauscher 1 -TA4 Heat Exchanger 2=TA4 Wärmetauscher 2 -TA4 Heat Exchanger 3=TA4 Wärmetauscher 3 -TA4 Hydrogen=TA4 Wasserstoff -TA4 LED Grow Light=TA4 LED Pflanzenlampe -TA4 LED Industrial Lamp=TA4 LED Industrielampe -TA4 LED Street Lamp=TA4 LED Straßenlampe -TA4 LED Street Lamp Arm=TA4 LED Lampenarm -TA4 LED Street Lamp Pole=TA4 LED Lampenmast -TA4 LEDs=TA4 LEDs -TA4 Liquid Filter Filler=TA4 Flüssigkeitsfilter Einfüllstutzen -TA4 Liquid Filter Sink=TA4 Flüssigkeitsfilter Abfluss -TA4 Low Power Box=TA4 Niederspannungsverteilerbox -TA4 Low Power Cable=TA4 Niederspannungskabel -TA4 Pillar=TA4 Säule -TA4 Pipe Inlet=TA4 Rohrzulauf -TA4 Player Detector=TA4 Spieler Detektor -TA4 Protected Chest=TA4 Gesicherte Kiste -TA4 Pump=TA4 Pumpe -TA4 RAM Chip=RAM Chip -TA4 Reactor=TA4 Reaktor -TA4 Reactor Base=TA4 Reaktor Sockel -TA4 Reactor Filler Pipe=TA4 Reaktor Einfüllstutzen -TA4 Reactor Stand=TA4 Reaktor Ständer -TA4 Rotor Blade=TA4 Rotorblatt -TA4 Sensor Chest=Sensorkiste -TA4 Silicon Wafer=TA4 Silizium-Wafer -TA4 Silo=Silo -TA4 Solar Carrier Module=TA4 Solar Trägermodul -TA4 Solar Carrier Module B=TA4 Solar Trägermodul U -TA4 Solar Carrier Module T=TA4 Solar Trägermodul O -TA4 Solar Inverter=TA4 Solar Wechselrichter -TA4 Solar Module=TA4 Solarmodul -TA4 State Collector=TA4 Zuständesammler -TA4 Streetlamp Solar Cell=TA4 Straßenlampen-Solarzelle -TA4 Tank=TA4 Tank -TA4 Turbine=TA4 Turbine -TA4 WLAN Chip=TA4 WLAN Chip -TA4 Water Pump=Wasserpumpe -TA4 Wind Turbine=TA4 Windkraftanlage -TA4 Wind Turbine Nacelle=TA4 Windkraftanlagengondel -TA4 Wind Turbine Signal Lamp=TA4 Windkraftanlagenlampe -TechAge Black Hole=TechAge Schwarzes Loch -TechAge Black Hole (let items and liquids disappear)=TechAge Schwarzes Loch (Gegenstände und Flüssigkeiten verschwinden) -TechAge Door Block=TechAge Türblock -TechAge Gate Block=TechAge Torblock -TechAge Gravel=TechAge Kies -TechAge Info Tool (use @= read status info)=TechAge Info Werkzeug -TechAge Programmer (right @= read number, left @= write numbers)=TechAge Programmer (rechts @= lese Nummer, links @= schreibe Nummern) -TechAge Repair Kit=TechAge Reparaturset -TechAge Signal Lamp=TechAge Signallampe -TechAge Signal Lamp (can be colored)=TechAge Signallampe (kann gefärbt werden) -TechAge Steel Mat=TechAge Stahlmatte -TechAge Trowel=TechAge Kelle -Techage Forceload Block=Techage Forceload Block -Techage Forceload Tile=Techage Forceload Kachel The network is overloaded!=Das Stromnetz ist überlastet! The network load is almost at the limit!=Das Stromnetz ist ziemlich am Limit! -The wind turbines are too close together!=Die Windkraftanlagen stehen zu eng beisammen! -Thermal=Wärme -Time=Zeit -Tiny Generator=Kleingenerator -Tiny generator=Kleingenerator -To add fuel punch@nthis block@nwith a fuel container=Um Brennstoff nachzufüllen,@nschlage mit einem Kraftstoffbehälter@nauf den Block -To add liquids punch@nthe tank@nwith a liquid container=Um Flüssigkeit nachzufüllen,@nschlage mit einem Flüssigkeitsbehälter@nauf den Block -To add water punch@nthe boiler@nwith a water bucket=Um Wasser nachzufüllen,@nschlage mit einem Wassereimer@nauf den Block -To many blocks in the power grid!=Zu viele Blöcke im Stromnetz! -Tube Wall Entry=Tube Wanddurchbruch Turned on:=Eingeschaltet: + +With %u of a maximum of %u blocks you are almost at the limit!=Mit %u von maximal %u Blöcken bist du fast am Limit! + + +### power_terminal.lua ### +### power_terminal2.lua ### + +Network Data=Netzwerkdaten + +### power_terminal2.lua ### + +Accu Box=Akkublock +Current power:=Strom aktuell: +Energy storage=Engergiespeicher +Energy stored:=Energie gespeichert +Fuel cell=Brennstoffzelle +Generators=Generatoren +Intake=Stromaufnahme +Max. needed power=Max. benötigter Strom +Maximum power:=Maximalstrom: +No power grid or running generator!=Kein Stromnetz oder Generator verfügbar! +Number blocks:=Anzahl Blöcke: +Number of power grid blocks=Anzahl der Stromnetz Blöcke +Output=Stromabgabe +Power grid total=Stromnetz gesammt +Power station=Kraftwerk +Probably too many consumers (=Vermutlich zu viele Verbraucher ( +Select type=Wähle Typ +Solar system=Solaranlage +Storage systems=Speichersysteme +TA2 Generator=TA2 Generator +TA3 Power Terminal=TA3 Strom Terminal +Tiny generator=Kleingenerator +To many blocks in the power grid!=Zu viele Blöcke im Stromnetz! Type=Typ -Unlock=Entsperren -Unlock connected chest@nif all slots are below 2000=Nachfolgende Kiste entsperren,@nsofern alle Speicherplätze <= 2000 -Update=Update -Use a trowel to remove the node.=Verwende eine Kelle, um den Block zu entfernen. -Usmium Nuggets=Usmium Nuggets -Usmium Powder=Usmium Pulver -WLAN Chip=WLAN Chip -Water=Wasser -Water Barrel=Wasserfass -Water Boiler=Wasserboiler -Water Pump=Wasserpumpe Wind turbine=Windkraftanlage -[Bucket] Lava can only be placed below sea level!=Lava kann nur unterhalb der Meerehöhe platziert werden! -[TA4 Wind Turbine]=[TA4 Windkraftanlage] -[TA] Area is protected!=[TA] Bereich ist geschützt -[TA] Derrick is being built!=[TA] Bohrturm wird errichtet -[TA] Derrick is being removed!=[TA] Bohrturm wird abgebaut -[TA] Not enough space!=[TA] Nicht ausreichend Platz! +ku is needed=ku wird benötigt + +### powerswitch.lua ### + +TA Power Switch=TA Stromschalter +TA Power Switch Small=TA Stromschalter klein + +### powerswitchbox.lua ### + +TA Power Switch Box=TA Stromschalterbox + +### programmer.lua ### + +TechAge Programmer (right @= read number, left @= write numbers)=TechAge Programmer (rechts @= lese Nummer, links @= schreibe Nummern) + [TechAge Programmer] Error: invalid numbers!=[TechAge Programmer] Fehler: ungültige Nummern! [TechAge Programmer] Error: programmer not supported!=[TechAge Programmer] Fehler: Programmer wird nicht unterstützt! [TechAge Programmer] Unknown node on=[TechAge Programmer] Unbekannter Block bei @@ -416,45 +723,289 @@ Wind turbine=Windkraftanlage [TechAge Programmer] node programmed!=[TechAge Programmer] Nummer(n) programmiert! [TechAge Programmer] number=[TechAge Programmer] Nummer [TechAge Programmer] programmer reset=[TechAge Programmer] Programmer zurück gesetzt -accept=akzeptieren -added=hinzugefügt wird -added or removed=hinzugefügt oder entfernt wird -area is protected=Bereich ist geschützt -blocking mode=Blockiert -catalyst missing=Katalysator fehlt -commands like: help=Kommandos wie: help -connected with=verbunden mit -depth=Tiefe -did you check the plan?=hast du den Plan geprüft? -empty=leer -finished=fertig -full=voll -inlet/pipe error=Einlass/Röhrenfehler -inventory full=Inventar ist voll -item output blocked=Ausgang blockiert -keep assignment=Zuordnung beibehalten -ku is needed=ku wird benötigt -light=Licht -loaded=geladen + +### protection.lua ### + +Allow to dig/place Techage power lines nearby power poles=Erlaubt TODO + +### pump.lua ### + +TA3 Pump=TA3 Pumpe +TA4 Pump=TA4 Pumpe + +### pumpjack.lua ### + +Oil Pumpjack=Ölpumpe +Oil amount=Ölmenge +Pumpjack=Ölpumpe needs power=benötigt Strom -no fuel=kein Kraftstoff -no fuel or no power=kein Strom oder Brennstoff no oil=Kein Öl -no power=kein Strom -no usable water=Kein brauchbares Wasser + +### pusher.lua ### + +Optionally configure@nthe pusher with one item=Der Schieber kann optional@nmit einem Gegenstand@nkonfiguriert werden +Pusher=Schieber + +### quarry.lua ### + +Digging depth=Grabungstiefe +Hole size=Lochgröße +Quarry=Steinbrecher +Start level=Startebene + +Start level @= 0@nmeans the same level@nas the quarry is placed=Startebene @= 0@nbedeutet gleiche Ebene@nwie der Steinbrecher + +area is protected=Bereich ist geschützt +finished=fertig +inventory full=Inventar ist voll + +### reboiler.lua ### + +TA3 Oil Reboiler=TA3 Aufkocher +TA3 Oil Reboiler: blocked=TA3 Aufkocher: blockiert + +### recipe_lib.lua ### + +Recipe=Rezept + +### recipe_lib.lua ### +### ta4_reactor.lua ### + +Catalyst=Katalysator + +### recipes.lua ### + +Flint and Iron=Flint and Iron +TA1 Iron Ingot=TA1 Eisenbarren +[Bucket] Lava can only be placed below sea level!=Lava kann nur unterhalb der Meerehöhe platziert werden! + +### redstone.lua ### + +Red Stone=Rotstein +Red Stone Block=Rotsteinblock +Red Stone Brick=Rotsteinziegel + +### repairkit.lua ### + +Biome=Biom +Node owner=Blockbesitzer +Position=Position +Position temperature=Positionstemperatur +TechAge Info Tool (use @= read status info)=TechAge Info Werkzeug +TechAge Repair Kit=TechAge Reparaturset +repaired=repariert + +### rotor.lua ### + +Nacelle is missing=Die Gondel fehlt +Not suitable position!=Ungeeignete Position! +TA4 Carbon Fiber=TA4 Kohlefaser +TA4 Rotor Blade=TA4 Rotorblatt +TA4 Wind Turbine=TA4 Windkraftanlage +TA4 Wind Turbine Nacelle=TA4 Windkraftanlagengondel + +### sensorchest.lua ### + +Allow public chest access=Erlaube öffentlichen Zugriff +TA4 Sensor Chest=Sensorkiste not connected=nicht verbunden -off=aus -on=an -power=Energie + +### sequencer.lua ### + +TA3 Sequencer=TA3 Sequenzer +stopped=gestoppt + +### signallamp.lua ### + +TA4 Wind Turbine Signal Lamp=TA4 Windkraftanlagenlampe +TechAge Signal Lamp=TechAge Signallampe +TechAge Signal Lamp (can be colored)=TechAge Signallampe (kann gefärbt werden) + +### silicon.lua ### + +TA4 Silicon Wafer=TA4 Silizium-Wafer + +### silo.lua ### + +TA3 Silo=TA3 Silo +TA4 Silo=Silo + +### simplelamp.lua ### + +TA Lamp=TA Lampe + +### solarcell.lua ### + +TA4 Solar Carrier Module=TA4 Solar Trägermodul +TA4 Solar Carrier Module B=TA4 Solar Trägermodul U +TA4 Solar Carrier Module T=TA4 Solar Trägermodul O +TA4 Solar Module=TA4 Solarmodul +light=Licht + +### source.lua ### + +Axle Power Source=Achsenkraftquelle +Ele Power Source=Ele Kraftquelle +Power Source=Stromquelle +Steam Power Source=Dampfenergiequelle + +### steam_pipe.lua ### + +TA2 Steam Pipe=TA2 Dampfleitung + +### steelmat.lua ### + +TechAge Steel Mat=TechAge Stahlmatte + +### streetlamp.lua ### + +TA Street Lamp=TA Straßenlampe + +### streetlamp2.lua ### + +TA4 LED Street Lamp=TA4 LED Straßenlampe +TA4 LED Street Lamp Arm=TA4 LED Lampenarm +TA4 LED Street Lamp Pole=TA4 LED Lampenmast + +### ta4_cable.lua ### + +TA4 Low Power Box=TA4 Niederspannungsverteilerbox +TA4 Low Power Cable=TA4 Niederspannungskabel + +### ta4_chest.lua ### + +Empty the slots always @nfrom right to left=Speicherplätze von rechts nach links leeren + +Never completely empty the slots@nwith the pusher to keep the item assignment=Speicherplätze mit dem Schieber nie ganz@nleeren, um die Item-Zuordnung beizubehalten + +Size=Größe +TA4 8x2000 Chest=TA4 8x2000 Kiste +Unlock=Entsperren +Unlock connected chest@nif all slots are below 2000=Nachfolgende Kiste entsperren,@nsofern alle Speicherplätze <= 2000 +keep assignment=Zuordnung beibehalten +right to left=von rechts nach links + +### ta4_doser.lua ### + +Doser=Dosierer +TA4 Doser=TA4 Dosierer +catalyst missing=Katalysator fehlt reactor defect=Reaktor defekt reactor defect or no power=Reaktor defekt oder kein Strom reactor has no power=Reaktor hat keinen Strom -removed=entfernt -repaired=repariert -right to left=von rechts nach links -stopped=gestoppt -storage empty?=Speicher leer? -water temperature=Wassertemperatur wrong catalyst=falscher Katalysator -wrong storage diameter=Falscher Wärmespeicher-Durchmesser -##### not used anymore ##### \ No newline at end of file + +### ta4_doser.lua ### +### ta4_reactor.lua ### + +TA4 Reactor=TA4 Reaktor + +### ta4_injector.lua ### + +Configure up to 8 items @nto be pushed by the injector=Konfiguriere bis zu 8 Gegenstände \n die vom Injektor weitergegeben werden sollen +Injector=Injektor + +### ta4_liquid_filter.lua ### + +TA4 Liquid Filter Filler=TA4 Flüssigkeitsfilter Einfüllstutzen +TA4 Liquid Filter Sink=TA4 Flüssigkeitsfilter Abfluss + +### ta4_reactor.lua ### + +TA4 Reactor Filler Pipe=TA4 Reaktor Einfüllstutzen + +### ta4_stand.lua ### + +TA4 Reactor Base=TA4 Reaktor Sockel +TA4 Reactor Stand=TA4 Reaktor Ständer +off=aus +on=an + +### ta4_stand.lua ### +### waterpump.lua ### + +no power=kein Strom + +### tank.lua ### + +Oil Tank=Öltank +TA3 Tank=TA3 Tank +TA4 Tank=TA4 Tank + +### tank_cart.lua ### + +TA Tank Cart=TA Tankwagen + +### terminal.lua ### + +Enter=Eingeben +Switched to private use!=Zur privaten Nutzung umgeschaltet +Switched to public use!=Zur öffentlichen Nutzung umgeschaltet +Syntax error, try help=Syntax Fehler, nutze help +TA3 Terminal=TA3 Terminal +commands like: help=Kommandos wie: help + +### timer.lua ### + +TA3 Timer=TA3 Timer + +### tiny_generator.lua ### + +TA3 Tiny Power Generator=TA3 Kleiner Stromgenerator +Tiny Generator=Kleingenerator +no fuel=kein Kraftstoff + +### tower.lua ### + +TA3 Derrick=TA3 Bohrturm +TA3 Drill Pipe=TA3 Bohrgestänge +TA4 Derrick=TA4 Bohrturm +[TA] Derrick is being built!=[TA] Bohrturm wird errichtet +[TA] Derrick is being removed!=[TA] Bohrturm wird abgebaut + +### trowel.lua ### + +TechAge Trowel=TechAge Kelle +Use a trowel to remove the node.=Verwende eine Kelle, um den Block zu entfernen. + +### tube_wall_entry.lua ### + +Tube Wall Entry=Tube Wanddurchbruch + +### turbine.lua ### + +TA3 Turbine=TA3 Turbine +TA4 Turbine=TA4 Turbine + +### usmium.lua ### + +Usmium Nuggets=Usmium Nuggets +Usmium Powder=Usmium Pulver + +### valve.lua ### + +TA Valve=TA Ventil +TA3 Valve closed=TA3 Ventil zu +TA3 Valve open=TA3 Ventil offen + +### waterpump.lua ### + +TA4 Water Pump=Wasserpumpe +Water Pump=Wasserpumpe + +### windturbine_lib.lua ### + +Here is not enough water (41x41 m)!=Hier ist nicht genug Wasser (41x41 m)! + +Here is not enough wind (A free air space of 41x41x21 m is necessary)!=Hier ist nicht genug Wind (Ein freier Luftraum von 41x41x21 m ist notwendig)! + +The next wind turbines is too close!= Die nächste Windkraftanlagen iat zu nahe! +This is a=Dies ist ein +This is no ocean water!= Dies ist kein Meerwasser! +This is not the surface of the ocean!=Das ist nicht die Meeresoberfläche! +[TA4 Wind Turbine]=[TA4 Windkraftanlage] +biome and no ocean!=Biom und keine Meer (ocean)! +is a suitable place for a wind turbine!=ist ein geeigneter Ort für eine Windkraftanlage! + + +##### not used anymore ##### diff --git a/techage/locale/template.txt b/techage/locale/template.txt index 024cbf0..65cba57 100644 --- a/techage/locale/template.txt +++ b/techage/locale/template.txt @@ -1,17 +1,70 @@ -#### TA3 Terminal ####@n@nSend commands to your machines@nand output text messages from your@nmachines to the Terminal.@n@nCommand syntax:@n cmd @n@nexample: cmd 181 on@n is the number of the node to which the command is sent@n'on' is the command to turn machines/nodes on@nFurther commands can be retrieved by clicking on@nmachines/nodes with the Techage Info Tool.@n@nLocal commands:@n- clear @= clear screen@n- help @= this message@n- pub @= switch to public use@n- priv @= switch to private use@nTo program a user button with a command:@n set @ne.g. 'set 1 ON cmd 123 on'@n= -Accu Box= -Active:= -All nodes:= -Allow public chest access= -Allow to dig/place Techage power lines nearby power poles= +# textdomain: techage + + + +### akkubox.lua ### + +TA3 Accu Box= +TA3 Akku Box= + +### akkubox.lua ### +### battery.lua ### + +Load= + +### akkubox.lua ### +### electrolyzer.lua ### +### fuelcell.lua ### +### generator.lua ### +### heatexchanger2.lua ### +### tiny_generator.lua ### + +Electricity= + +### aluminium.lua ### + Aluminum= -Area already loaded or max. number of Forceload Blocks reached!= -Ash= +Gibbsite Powder= +Red Mud= +Red Mud Barrel= +Red Mud Canister= + +### assemble.lua ### +### firebox_lib.lua ### + +[TA] Area is protected!= +[TA] Not enough space!= + +### autocrafter.lua ### + Autocrafter= -Axle Power Source= + +### axle2power.lua ### + +TA2 Power Generator= + +TA2 Power Generator: Overload fault?@n(restart with right-click)= + + +### baborium.lua ### + Baborium Ingot= Baborium Lump= Baborium Ore= + +### barrel.lua ### + +Gas Cylinder Large= +Gas Cylinder Small= +River Water Barrel= +TA Empty Barrel= +TA3 Canister= +Water= +Water Barrel= +empty= + +### basalt.lua ### + Basalt Cobble= Basalt Glass= Basalt Glass 2= @@ -23,390 +76,646 @@ Basalt Gravel= Basalt Stone= Basalt Stone Block= Basalt Stone Brick= +Sieved Basalt Gravel= + +### battery.lua ### + Battery= +Coal Equivalents= +Digtron Battery= + +### bauxit.lua ### + Bauxite Cobblestone= Bauxite Gravel= Bauxite Powder= Bauxite Stone= -Biome= -Block configured items for open ports= -Build derrick= -Catalyst= + +### blackhole.lua ### + +TechAge Black Hole= +TechAge Black Hole (let items and liquids disappear)= + +### boiler.lua ### + +TA2 Boiler Base= +TA2 Boiler Top= + +### boiler_base.lua ### + +TA3 Boiler Base= + +### boiler_lib.lua ### + +To add water punch@nthe boiler@nwith a water bucket= +Water Boiler= +water temperature= + +### boiler_top.lua ### + +TA3 Boiler Top= + +### booster.lua ### + +TA3 Booster= + +### button.lua ### + +TA3 Button/Switch= +TA4 Button/Switch= + +### button.lua ### +### cart_detector.lua ### +### detector.lua ### +### lua_logic.lua ### +### mesecons_converter.lua ### +### node_detector.lua ### +### player_detector.lua ### +### repeater.lua ### + +Insert destination node number(s)= + +### button.lua ### +### chest.lua ### +### detector.lua ### +### doorcontroller.lua ### +### mesecons_converter.lua ### +### repeater.lua ### + +Save= + +### cart_detector.lua ### + +TA3 Cart Detector= + +### cart_detector.lua ### +### node_detector.lua ### + +accept= + +### cart_detector.lua ### +### player_detector.lua ### + +TA3 Player Detector= + +### ceilinglamp.lua ### + +TA Ceiling Lamp= + +### cement.lua ### + Cement Block= Cement Powder= -Coal Equivalents= -Compressed Gravel= -Configure up to 8 items @nto be pushed by the injector= -Consum. 1= -Consum. 2= -Current power:= -Depth= -Digging depth= -Digtron Battery= + +### charcoalpile.lua ### + Dirt with Ash= +TA1 Charcoal= + +### chest.lua ### + +Allow public access to the chest= +Inventory,Pre-Assignment,Config= +Node label:= +TA2 Protected Chest= +TA3 Protected Chest= +TA4 Protected Chest= + +### chest_cart.lua ### + +TA Chest Cart= + +### coalburner.lua ### + +Ash= + +### collector.lua ### + +Node number to send the events to= +Node numbers to read the states from= +Send an event if state is equal or larger than= +TA4 State Collector= + +### cooking.lua ### + +TA3 Melting= + +### cooler.lua ### + +TA3 Cooler= + +### cylinder.lua ### + +TA2 Cylinder= + +### detector.lua ### + +TA3 Detector= +TA4 Detector= + +### display.lua ### + Display no: = +TA4 Display= +TA4 Display XL= + +### distiller.lua ### + +TA3 Distillation Tower 1= +TA3 Distillation Tower 2= +TA3 Distillation Tower 3= +TA3 Distillation Tower 4= +TA3 Distillation Tower Base= + +### distributor.lua ### + +Block configured items for open ports= Distributor= -Doser= +High Performance Distributor= +Input= +blocking mode= + +### doorblock.lua ### + +TechAge Door Block= + +### doorcontroller.lua ### + +Insert door/gate block number(s)= +TA3 Door Controller= + +### doorcontroller.lua ### +### repeater.lua ### + +TA3 Repeater= + +### drillbox.lua ### + +Build derrick= +Depth= Drill Bit= Drill area is protected= Drill bits missing= -Ele Power Source= -Electricity= +Oil Drill Box= +Remove derrick= +item output blocked= + +### drive_axle.lua ### + +TA2 Drive Axle= + +### electric_cable.lua ### + +TA Electric Cable= + +### electrolyzer.lua ### + +TA4 Electrolyzer= +full= + +### electrolyzer.lua ### +### power_terminal2.lua ### + Electrolyzer= + +### electronic.lua ### + +TA3 Vacuum Tube= +TA4 LEDs= +TA4 RAM Chip= +TA4 WLAN Chip= +WLAN Chip= + +### electronic_fab.lua ### + Electronic Fab= -Empty the slots always @nfrom right to left= -Energy storage= -Energy stored:= -Enter= +TA2 Ele Fab= +TA3 Ele Fab= +TA4 Ele Fab= + +### epoxy.lua ### + Epoxide Resin= Epoxide Resin Barrel= Epoxide Resin Canister= -Error= + +### explore.lua ### + +Oil= +TA3 Oil Explorer= +TA3 Oil Storage= +depth= + +### filler.lua ### + +Liquid Filler= +TA Liquid Filler= + +### firebox.lua ### + +TA2 Firebox= +TA3 Coal Power Station Firebox= +TA3 Furnace Oil Burner= +TA3 Power Station Firebox= + +### firebox_lib.lua ### + Firebox= -Flint and Iron= -Flowing Oil= + +### flywheel.lua ### + Flywheel= -Fuel Cell= +TA2 Flywheel= + +### flywheel.lua ### +### generator.lua ### +### solarcell.lua ### +### source.lua ### + +power= + +### forceload.lua ### + +Area already loaded or max. number of Forceload Blocks reached!= + +List of your Forceload Blocks:= +Priv missing= +Punch the block to make the area visible.= +Show all forceload blocks in a 64x64x64 range= +Techage Forceload Block= +Techage Forceload Tile= +loaded= + +### fuel_lib.lua ### + Fuel Menu= -Fuel cell= +To add fuel punch@nthis block@nwith a fuel container= + +### fuelcell.lua ### + +Fuel Cell= +TA4 Fuel Cell= + +### fuelcellstack.lua ### + +TA4 Fuel Cell Stack= + +### furnace_top.lua ### + Furnace Top= -Gas Cylinder Large= -Gas Cylinder Small= -Genera. 1= -Genera. 2= +Outp= +no fuel or no power= + +### gateblock.lua ### + +TechAge Gate Block= + +### gearbox.lua ### + +TA2 Gearbox= + +### generator.lua ### + Generator= -Generators= -Gibbsite Powder= +TA3 Generator= +TA4 Generator= +storage empty?= + +### gravelrinser.lua ### + Gravel Rinser= +Rinsing= + +### gravelsieve.lua ### + +Compressed Gravel= Gravel Sieve= +Sieved Gravel= +TA1 Gravel Sieve= +TA2 Gravel Sieve= +TA3 Gravel Sieve= +TA4 Gravel Sieve= + +### grinder.lua ### + Grinder= Grinding= -Heat= + +### growlight.lua ### + +TA4 LED Grow Light= + +### guide.lua ### + +No plan available= +Plan= + +### hammer.lua ### + +TA1 Bronze Hammer (smash stone to gravel)= +TA1 Diamond Hammer (smash stone to gravel)= +TA1 Meridium Hammer (smash stone to gravel)= +TA1 Mese Hammer (smash stone to gravel)= +TA1 Steel Hammer (smash stone to gravel)= +TA1 Stone Hammer (smash stone to gravel)= + +### heater.lua ### + +TA4 Furnace Heater= + +### heatexchanger1.lua ### + +TA4 Heat Exchanger 1= +inlet/pipe error= +wrong storage diameter= + +### heatexchanger1.lua ### +### heatexchanger2.lua ### + +did you check the plan?= + +### heatexchanger2.lua ### + Heat Exchanger= -High Performance Distributor= -Hole size= +TA4 Heat Exchanger= +TA4 Heat Exchanger 2= +Thermal= + +### heatexchanger3.lua ### + +TA4 Heat Exchanger 3= + +### hydrogen.lua ### + Hydrogen Cylinder Large= Hydrogen Cylinder Small= -In use:= -Injector= -Input= -Insert destination node number(s)= -Insert door/gate block number(s)= -Intake= -Inventory,Configuration= +TA4 Hydrogen= + +### industriallamp1.lua ### + +TA Industrial Lamp 1= + +### industriallamp2.lua ### + +TA Industrial Lamp 2= + +### industriallamp3.lua ### + +TA Industrial Lamp 3= + +### industriallamp4.lua ### + +TA4 LED Industrial Lamp= + +### inlet.lua ### + +TA4 Pipe Inlet= + +### inverter.lua ### + Inverter= -Iron Powder= -Leave Powder= -Liquid Filler= -Liquid Sampler= -Liquid Tank= -List of your Forceload Blocks:= -Load= -Lye= -Lye Barrel= -Lye Canister= -Max. needed power= -Maximum power:= -Melting Guide= -Melting Pot active (heat@== -Melting Pot inactive (heat@== -Melting Pot inactive (heat@=0)= -Menu= -Menu,Recipes= -Meridium Axe= -Meridium Pickaxe= -Meridium Shovel= -Meridium Sword= -More water expected (2 m deep)!= -Nacelle is missing= -Needle Powder= -Network Data= -Never completely empty the slots@nwith the pusher to keep the item assignment= -No network or active generator available!= -No plan available= -No power grid or running generator!= -No wind at this altitude!= -Node number to send the events to= -Node numbers to read the states from= -Node owner= -Number blocks:= -Number of all nodes= -Number of power grid blocks= -Oil= -Oil Drill Box= -Oil Pumpjack= -Oil Source= -Oil Tank= -Oil amount= -Optionally configure@nthe pusher with one item= -Outp= -Output= -Plan= -Plastic Granules= -Position= -Position temperature= Power AC= Power DC= -Power Source= -Power grid total= -Power station= -Priv missing= -Probably too many consumers (= -Propane Cylinder Large= -Propane Cylinder Small= -Pumpjack= -Punch the block to make the area visible.= -Pusher= -Quarry= -Recipe= -Red Mud= -Red Mud Barrel= -Red Mud Canister= -Red Stone= -Red Stone Block= -Red Stone Brick= -Remove derrick= -Rinsing= -River Water Barrel= -Save= -Select type= -Send an event if state is equal or larger than= -Send signal if nodes have been:= -Show all forceload blocks in a 64x64x64 range= -Sieved Basalt Gravel= -Sieved Gravel= -Size= -Solar system= -Start level= -Start level @= 0@nmeans the same level@nas the quarry is placed= -Steam Power Source= -Storage systems= -Store= -Switched to private use!= -Switched to public use!= -Syntax error, try help= -TA Ceiling Lamp= -TA Chest Cart= -TA Electric Cable= +TA4 Solar Inverter= + +### junctionbox.lua ### + TA Electric Junction Box= -TA Empty Barrel= -TA Industrial Lamp 1= -TA Industrial Lamp 2= -TA Industrial Lamp 3= -TA Junction Pipe= -TA Lamp= + +### lampholder.lua ### + TA Lamp Holder Acacia= TA Lamp Holder Apple= TA Lamp Holder Aspen= TA Lamp Holder Copper= TA Lamp Holder Gold= TA Lamp Holder White= -TA Liquid Filler= + +### lib.lua ### +### sensorchest.lua ### + +connected with= + +### lighter.lua ### + +TA1 Lighter= + +### liquid_lib.lua ### + +Allow public access to the tank= +Liquid Tank= +To add liquids punch@nthe tank@nwith a liquid container= + +### liquid_pipe.lua ### + +TA Junction Pipe= TA Pipe= + +### liquidsampler.lua ### + +Liquid Sampler= + +### liquidsampler.lua ### +### waterpump.lua ### + +no usable water= + +### lua_logic.lua ### + +TA3 Logic Block= +Update= + +### lua_logic.lua ### +### power_terminal2.lua ### + +Store= + +### lye.lua ### + +Lye= +Lye Barrel= +Lye Canister= + +### meltingpot.lua ### + +Heat= +Melting Guide= +Melting Pot active (heat@== +Melting Pot inactive (heat@== +Melting Pot inactive (heat@=0)= +Menu= +Menu,Recipes= +TA1 Burning= +TA1 Melting= +TA1 Melting Pot= + +### meltingpot.lua ### +### repairkit.lua ### + +Time= + +### meridium.lua ### + +Meridium Axe= +Meridium Pickaxe= +Meridium Shovel= +Meridium Sword= + +### mesecons_converter.lua ### + +TA3 Mesecons Converter= + +### minicell.lua ### + +TA4 Streetlamp Solar Cell= + +### node_detector.lua ### + +Send signal if nodes have been:= +TA3 Node Detector= +added= +added or removed= +removed= + +### nodes.lua ### + +TechAge Gravel= + +### oil.lua ### + +Flowing Oil= +Oil Source= +TA3 Oil Barrel= +TA3 Oil Canister= + +### oilfirebox.lua ### + +TA3 Power Station Oil Burner= + +### petroleum.lua ### + +Propane Cylinder Large= +Propane Cylinder Small= +TA3 Bitumen= +TA3 Bitumen Barrel= +TA3 Bitumen Canister= +TA3 Fuel Oil= +TA3 Fuel Oil Barrel= +TA3 Fuel Oil Canister= +TA3 Gasoline= +TA3 Gasoline Barrel= +TA3 Gasoline Canister= +TA3 Naphtha= +TA3 Naphtha Barrel= +TA3 Naphtha Canister= +TA3 Propane= + +### pillar.lua ### + +TA4 Pillar= + +### pipe_wall_entry.lua ### + +TA3 Pipe Wall Entry= + +### pipe_wrench.lua ### + +TA3 Drill Pipe Wrench= + +### plastic.lua ### + +Plastic Granules= + +### player_detector.lua ### + +TA4 Player Detector= + +### powder.lua ### + +Iron Powder= +Leave Powder= +Needle Powder= + +### power2axle.lua ### + +TA3 Electric Motor= + +TA3 Electric Motor: Overload fault?@n(restart with right-click)= + + +### power_line.lua ### + TA Power Line= TA Power Pole= TA Power Pole Top (for up to 6 connections)= TA Power Pole Top 2 (for landlines)= -TA Power Switch= -TA Power Switch Box= -TA Power Switch Small= -TA Street Lamp= -TA Tank Cart= -TA Valve= -TA1 Bronze Hammer (smash stone to gravel)= -TA1 Burning= -TA1 Charcoal= -TA1 Diamond Hammer (smash stone to gravel)= -TA1 Gravel Sieve= -TA1 Iron Ingot= -TA1 Lighter= -TA1 Melting= -TA1 Melting Pot= -TA1 Meridium Hammer (smash stone to gravel)= -TA1 Mese Hammer (smash stone to gravel)= -TA1 Steel Hammer (smash stone to gravel)= -TA1 Stone Hammer (smash stone to gravel)= -TA2 Boiler Base= -TA2 Boiler Top= -TA2 Cylinder= -TA2 Drive Axle= -TA2 Ele Fab= -TA2 Firebox= -TA2 Flywheel= -TA2 Gearbox= -TA2 Gravel Sieve= -TA2 Protected Chest= -TA2 Steam Pipe= -TA3 Accu Box= -TA3 Akku Box= -TA3 Bitumen= -TA3 Bitumen Barrel= -TA3 Bitumen Canister= -TA3 Boiler Base= -TA3 Boiler Top= -TA3 Booster= -TA3 Button/Switch= -TA3 Canister= -TA3 Cart Detector= -TA3 Coal Power Station Firebox= -TA3 Cooler= -TA3 Derrick= -TA3 Detector= -TA3 Distillation Tower 1= -TA3 Distillation Tower 2= -TA3 Distillation Tower 3= -TA3 Distillation Tower 4= -TA3 Distillation Tower Base= -TA3 Door Controller= -TA3 Drill Pipe= -TA3 Drill Pipe Wrench= -TA3 Ele Fab= -TA3 Fuel Oil= -TA3 Fuel Oil Barrel= -TA3 Fuel Oil Canister= -TA3 Furnace Oil Burner= -TA3 Gasoline= -TA3 Gasoline Barrel= -TA3 Gasoline Canister= -TA3 Generator= -TA3 Gravel Sieve= -TA3 Logic Block= -TA3 Melting= -TA3 Mesecons Converter= -TA3 Naphtha= -TA3 Naphtha Barrel= -TA3 Naphtha Canister= -TA3 Node Detector= -TA3 Oil Barrel= -TA3 Oil Canister= -TA3 Oil Explorer= -TA3 Oil Reboiler= -TA3 Oil Reboiler: blocked= -TA3 Oil Storage= -TA3 Pipe Wall Entry= -TA3 Player Detector= -TA3 Power Station Firebox= -TA3 Power Station Oil Burner= -TA3 Power Terminal= + +### power_terminal.lua ### + +Active:= +All nodes:= +Consum. 1= +Consum. 2= +Genera. 1= +Genera. 2= +In use:= +No network or active generator available!= +Number of all nodes= TA3 Power Terminal Old= -TA3 Propane= -TA3 Protected Chest= -TA3 Pump= -TA3 Repeater= -TA3 Sequencer= -TA3 Silo= -TA3 Tank= -TA3 Terminal= -TA3 Timer= -TA3 Tiny Power Generator= -TA3 Turbine= -TA3 Vacuum Tube= -TA3 Valve closed= -TA3 Valve open= -TA4 8x2000 Chest= -TA4 Button/Switch= -TA4 Carbon Fiber= -TA4 Derrick= -TA4 Detector= -TA4 Display= -TA4 Display XL= -TA4 Doser= -TA4 Ele Fab= -TA4 Electrolyzer= -TA4 Fuel Cell= -TA4 Fuel Cell Stack= -TA4 Furnace Heater= -TA4 Generator= -TA4 Gravel Sieve= -TA4 Heat Exchanger= -TA4 Heat Exchanger 1= -TA4 Heat Exchanger 2= -TA4 Heat Exchanger 3= -TA4 Hydrogen= -TA4 LED Grow Light= -TA4 LED Industrial Lamp= -TA4 LED Street Lamp= -TA4 LED Street Lamp Arm= -TA4 LED Street Lamp Pole= -TA4 LEDs= -TA4 Liquid Filter Filler= -TA4 Liquid Filter Sink= -TA4 Low Power Box= -TA4 Low Power Cable= -TA4 Pillar= -TA4 Pipe Inlet= -TA4 Player Detector= -TA4 Protected Chest= -TA4 Pump= -TA4 RAM Chip= -TA4 Reactor= -TA4 Reactor Base= -TA4 Reactor Filler Pipe= -TA4 Reactor Stand= -TA4 Rotor Blade= -TA4 Sensor Chest= -TA4 Silicon Wafer= -TA4 Silo= -TA4 Solar Carrier Module= -TA4 Solar Carrier Module B= -TA4 Solar Carrier Module T= -TA4 Solar Inverter= -TA4 Solar Module= -TA4 State Collector= -TA4 Streetlamp Solar Cell= -TA4 Tank= -TA4 Turbine= -TA4 WLAN Chip= -TA4 Water Pump= -TA4 Wind Turbine= -TA4 Wind Turbine Nacelle= -TA4 Wind Turbine Signal Lamp= -TechAge Black Hole= -TechAge Black Hole (let items and liquids disappear)= -TechAge Door Block= -TechAge Gate Block= -TechAge Gravel= -TechAge Info Tool (use @= read status info)= -TechAge Programmer (right @= read number, left @= write numbers)= -TechAge Repair Kit= -TechAge Signal Lamp= -TechAge Signal Lamp (can be colored)= -TechAge Steel Mat= -TechAge Trowel= -Techage Forceload Block= -Techage Forceload Tile= The network is overloaded!= The network load is almost at the limit!= -The wind turbines are too close together!= -Thermal= -Time= -Tiny Generator= -Tiny generator= -To add fuel punch@nthis block@nwith a fuel container= -To add liquids punch@nthe tank@nwith a liquid container= -To add water punch@nthe boiler@nwith a water bucket= -To many blocks in the power grid!= -Tube Wall Entry= Turned on:= + +With %u of a maximum of %u blocks you are almost at the limit!= + + +### power_terminal.lua ### +### power_terminal2.lua ### + +Network Data= + +### power_terminal2.lua ### + +Accu Box= +Current power:= +Energy storage= +Energy stored:= +Fuel cell= +Generators= +Intake= +Max. needed power= +Maximum power:= +No power grid or running generator!= +Number blocks:= +Number of power grid blocks= +Output= +Power grid total= +Power station= +Probably too many consumers (= +Select type= +Solar system= +Storage systems= +TA2 Generator= +TA3 Power Terminal= +Tiny generator= +To many blocks in the power grid!= Type= -Unlock= -Unlock connected chest@nif all slots are below 2000= -Update= -Use a trowel to remove the node.= -Usmium Nuggets= -Usmium Powder= -WLAN Chip= -Water= -Water Barrel= -Water Boiler= -Water Pump= Wind turbine= -[Bucket] Lava can only be placed below sea level!= -[TA4 Wind Turbine]= -[TA] Area is protected!= -[TA] Derrick is being built!= -[TA] Derrick is being removed!= -[TA] Not enough space!= +ku is needed= + +### powerswitch.lua ### + +TA Power Switch= +TA Power Switch Small= + +### powerswitchbox.lua ### + +TA Power Switch Box= + +### programmer.lua ### + +TechAge Programmer (right @= read number, left @= write numbers)= + [TechAge Programmer] Error: invalid numbers!= [TechAge Programmer] Error: programmer not supported!= [TechAge Programmer] Unknown node on= @@ -414,44 +723,286 @@ Wind turbine= [TechAge Programmer] node programmed!= [TechAge Programmer] number= [TechAge Programmer] programmer reset= -accept= -added= -added or removed= -area is protected= -blocking mode= -catalyst missing= -commands like: help= -connected with= -depth= -did you check the plan?= -empty= -finished= -full= -inlet/pipe error= -inventory full= -item output blocked= -keep assignment= -ku is needed= -light= -loaded= + +### protection.lua ### + +Allow to dig/place Techage power lines nearby power poles= + +### pump.lua ### + +TA3 Pump= +TA4 Pump= + +### pumpjack.lua ### + +Oil Pumpjack= +Oil amount= +Pumpjack= needs power= -no fuel= -no fuel or no power= no oil= -no power= -no usable water= + +### pusher.lua ### + +Optionally configure@nthe pusher with one item= +Pusher= + +### quarry.lua ### + +Digging depth= +Hole size= +Quarry= +Start level= + +Start level @= 0@nmeans the same level@nas the quarry is placed= + +area is protected= +finished= +inventory full= + +### reboiler.lua ### + +TA3 Oil Reboiler= +TA3 Oil Reboiler: blocked= + +### recipe_lib.lua ### + +Recipe= + +### recipe_lib.lua ### +### ta4_reactor.lua ### + +Catalyst= + +### recipes.lua ### + +Flint and Iron= +TA1 Iron Ingot= +[Bucket] Lava can only be placed below sea level!= + +### redstone.lua ### + +Red Stone= +Red Stone Block= +Red Stone Brick= + +### repairkit.lua ### + +Biome= +Node owner= +Position= +Position temperature= +TechAge Info Tool (use @= read status info)= +TechAge Repair Kit= +repaired= + +### rotor.lua ### + +Nacelle is missing= +Not suitable position!= +TA4 Carbon Fiber= +TA4 Rotor Blade= +TA4 Wind Turbine= +TA4 Wind Turbine Nacelle= + +### sensorchest.lua ### + +Allow public chest access= +TA4 Sensor Chest= not connected= -off= -on= -power= + +### sequencer.lua ### + +TA3 Sequencer= +stopped= + +### signallamp.lua ### + +TA4 Wind Turbine Signal Lamp= +TechAge Signal Lamp= +TechAge Signal Lamp (can be colored)= + +### silicon.lua ### + +TA4 Silicon Wafer= + +### silo.lua ### + +TA3 Silo= +TA4 Silo= + +### simplelamp.lua ### + +TA Lamp= + +### solarcell.lua ### + +TA4 Solar Carrier Module= +TA4 Solar Carrier Module B= +TA4 Solar Carrier Module T= +TA4 Solar Module= +light= + +### source.lua ### + +Axle Power Source= +Ele Power Source= +Power Source= +Steam Power Source= + +### steam_pipe.lua ### + +TA2 Steam Pipe= + +### steelmat.lua ### + +TechAge Steel Mat= + +### streetlamp.lua ### + +TA Street Lamp= + +### streetlamp2.lua ### + +TA4 LED Street Lamp= +TA4 LED Street Lamp Arm= +TA4 LED Street Lamp Pole= + +### ta4_cable.lua ### + +TA4 Low Power Box= +TA4 Low Power Cable= + +### ta4_chest.lua ### + +Empty the slots always @nfrom right to left= + +Never completely empty the slots@nwith the pusher to keep the item assignment= + +Size= +TA4 8x2000 Chest= +Unlock= +Unlock connected chest@nif all slots are below 2000= +keep assignment= +right to left= + +### ta4_doser.lua ### + +Doser= +TA4 Doser= +catalyst missing= reactor defect= reactor defect or no power= reactor has no power= -removed= -repaired= -right to left= -stopped= -storage empty?= -water temperature= wrong catalyst= -wrong storage diameter= \ No newline at end of file + +### ta4_doser.lua ### +### ta4_reactor.lua ### + +TA4 Reactor= + +### ta4_injector.lua ### + +Configure up to 8 items @nto be pushed by the injector= +Injector= + +### ta4_liquid_filter.lua ### + +TA4 Liquid Filter Filler= +TA4 Liquid Filter Sink= + +### ta4_reactor.lua ### + +TA4 Reactor Filler Pipe= + +### ta4_stand.lua ### + +TA4 Reactor Base= +TA4 Reactor Stand= +off= +on= + +### ta4_stand.lua ### +### waterpump.lua ### + +no power= + +### tank.lua ### + +Oil Tank= +TA3 Tank= +TA4 Tank= + +### tank_cart.lua ### + +TA Tank Cart= + +### terminal.lua ### + +Enter= +Switched to private use!= +Switched to public use!= +Syntax error, try help= +TA3 Terminal= +commands like: help= + +### timer.lua ### + +TA3 Timer= + +### tiny_generator.lua ### + +TA3 Tiny Power Generator= +Tiny Generator= +no fuel= + +### tower.lua ### + +TA3 Derrick= +TA3 Drill Pipe= +TA4 Derrick= +[TA] Derrick is being built!= +[TA] Derrick is being removed!= + +### trowel.lua ### + +TechAge Trowel= +Use a trowel to remove the node.= + +### tube_wall_entry.lua ### + +Tube Wall Entry= + +### turbine.lua ### + +TA3 Turbine= +TA4 Turbine= + +### usmium.lua ### + +Usmium Nuggets= +Usmium Powder= + +### valve.lua ### + +TA Valve= +TA3 Valve closed= +TA3 Valve open= + +### waterpump.lua ### + +TA4 Water Pump= +Water Pump= + +### windturbine_lib.lua ### + +Here is not enough water (41x41 m)!= + +Here is not enough wind (A free air space of 41x41x21 m is necessary)!= + +The next wind turbines is too close!= +This is a= +This is no ocean water!= +This is not the surface of the ocean!= +[TA4 Wind Turbine]= +biome and no ocean!= +is a suitable place for a wind turbine!= diff --git a/techage/logic/sequencer.lua b/techage/logic/sequencer.lua index 10360a4..f62706b 100644 --- a/techage/logic/sequencer.lua +++ b/techage/logic/sequencer.lua @@ -222,16 +222,17 @@ minetest.register_node("techage:ta3_sequencer", { on_receive_fields = on_receive_fields, - on_dig = function(pos, node, puncher, pointed_thing) + can_dig = function(pos, puncher) if minetest.is_protected(pos, puncher:get_player_name()) then - return + return false end local nvm = techage.get_nvm(pos) - if not nvm.running then - techage.remove_node(pos) - minetest.node_dig(pos, node, puncher, pointed_thing) - techage.del_mem(pos) - end + return not nvm.running + end, + + after_dig_node = function(pos, oldnode, oldmetadata) + techage.remove_node(pos, oldnode, oldmetadata) + techage.del_mem(pos) end, on_timer = check_rules, diff --git a/techage/logic/terminal.lua b/techage/logic/terminal.lua index 718c1bb..436eb7b 100644 --- a/techage/logic/terminal.lua +++ b/techage/logic/terminal.lua @@ -15,41 +15,23 @@ local M = minetest.get_meta local S = techage.S -local HELP_TA3 = S("#### TA3 Terminal ####@n".. -"@n".. -"Send commands to your machines@n".. -"and output text messages from your@n".. -"machines to the Terminal.@n".. -"@n".. -"Command syntax:@n".. -" cmd @n".. -"@n".. -"example: cmd 181 on@n".. -" is the number of the node to which the command is sent@n".. -"'on' is the command to turn machines/nodes on@n".. -"Further commands can be retrieved by clicking on@n".. -"machines/nodes with the Techage Info Tool.@n".. -"@n".. -"Local commands:@n".. -"- clear = clear screen@n".. -"- help = this message@n".. -"- pub = switch to public use@n".. -"- priv = switch to private use@n".. -"To program a user button with a command:@n".. -" set @n".. -"e.g. 'set 1 ON cmd 123 on'@n") +local HELP_TA3 = "Syntax:\n".. +" cmd \n".. +"\n".. +"like: cmd 181 on\n".. +"or: cmd 4573 state\n".. +"\n".. +"Local commands:\n".. +"- clear = clear screen\n".. +"- help = this message\n".. +"- pub = switch to public use of buttons\n".. +"- priv = switch to private use of buttons\n".. +"To program a user button with a command:\n".. +" set \n".. +"e.g.: set 1 ON cmd 123 on" local CMNDS_TA3 = S("Syntax error, try help") ---local function formspec1() --- return "size[6,4]".. --- default.gui_bg.. --- default.gui_bg_img.. --- default.gui_slots.. --- "field[0.5,1;5,1;number;Techage Controller number:;]" .. --- "button_exit[1.5,2.5;2,1;exit;Save]" ---end - local function get_string(meta, num, default) local s = meta:get_string("bttn_text"..num) if not s or s == "" then @@ -106,6 +88,7 @@ end local function command(pos, command, player) local meta = minetest.get_meta(pos) local owner = meta:get_string("owner") or "" + if command then command = command:sub(1,80) command = string.trim(command) @@ -117,16 +100,15 @@ local function command(pos, command, player) local meta = minetest.get_meta(pos) meta:set_string("output", HELP_TA3) meta:set_string("formspec", formspec2(meta)) - elseif command == "pub" and owner == player then + elseif command == "pub" then meta:set_int("public", 1) output(pos, player..":$ "..command) output(pos, S("Switched to public use!")) - elseif command == "priv" and owner == player then + elseif command == "priv" then meta:set_int("public", 0) output(pos, player..":$ "..command) output(pos, S("Switched to private use!")) - elseif meta:get_int("public") == 1 or owner == player or - minetest.check_player_privs(player, "server") then + else output(pos, "$ "..command) local own_num = meta:get_string("node_number") local num, cmnd, payload = command:match('^cmd%s+([0-9]+)%s+(%w+)%s*(.*)$') @@ -206,24 +188,34 @@ local function register_terminal(num, tiles, node_box, selection_box) on_receive_fields = function(pos, formname, fields, player) local meta = minetest.get_meta(pos) - local evt = minetest.explode_table_event(fields.output) - if evt.type == "DCL" then - local s = get_line_text(pos, evt.row) - meta:set_string("command", s) - meta:set_string("formspec", formspec2(meta)) - elseif (fields.key_enter == "true" or fields.ok) and fields.cmnd ~= "" then - command(pos, fields.cmnd, player:get_player_name()) - meta:set_string("command", "") - meta:set_string("formspec", formspec2(meta)) - elseif fields.bttn1 then send_cmnd(pos, meta, 1) - elseif fields.bttn2 then send_cmnd(pos, meta, 2) - elseif fields.bttn3 then send_cmnd(pos, meta, 3) - elseif fields.bttn4 then send_cmnd(pos, meta, 4) - elseif fields.bttn5 then send_cmnd(pos, meta, 5) - elseif fields.bttn6 then send_cmnd(pos, meta, 6) - elseif fields.bttn7 then send_cmnd(pos, meta, 7) - elseif fields.bttn8 then send_cmnd(pos, meta, 8) - elseif fields.bttn9 then send_cmnd(pos, meta, 9) + local public = meta:get_int("public") == 1 + local protected = minetest.is_protected(pos, player:get_player_name()) + + if not protected then + local evt = minetest.explode_table_event(fields.output) + if evt.type == "DCL" then + local s = get_line_text(pos, evt.row) + meta:set_string("command", s) + meta:set_string("formspec", formspec2(meta)) + return + elseif (fields.key_enter == "true" or fields.ok) and fields.cmnd ~= "" then + command(pos, fields.cmnd, player:get_player_name()) + meta:set_string("command", "") + meta:set_string("formspec", formspec2(meta)) + return + end + end + if public or not protected then + if fields.bttn1 then send_cmnd(pos, meta, 1) + elseif fields.bttn2 then send_cmnd(pos, meta, 2) + elseif fields.bttn3 then send_cmnd(pos, meta, 3) + elseif fields.bttn4 then send_cmnd(pos, meta, 4) + elseif fields.bttn5 then send_cmnd(pos, meta, 5) + elseif fields.bttn6 then send_cmnd(pos, meta, 6) + elseif fields.bttn7 then send_cmnd(pos, meta, 7) + elseif fields.bttn8 then send_cmnd(pos, meta, 8) + elseif fields.bttn9 then send_cmnd(pos, meta, 9) + end end end, diff --git a/techage/lua_controller/controller.lua b/techage/lua_controller/controller.lua index 2154212..92d3c4d 100644 --- a/techage/lua_controller/controller.lua +++ b/techage/lua_controller/controller.lua @@ -541,13 +541,9 @@ minetest.register_node("techage:ta4_lua_controller", { end end, - on_dig = function(pos, node, puncher, pointed_thing) - if minetest.is_protected(pos, puncher:get_player_name()) then - return - end - - techage.remove_node(pos) - minetest.node_dig(pos, node, puncher, pointed_thing) + after_dig_node = function(pos, oldnode, oldmetadata) + techage.remove_node(pos, oldnode, oldmetadata) + techage.del_mem(pos) end, on_timer = on_timer, @@ -631,7 +627,7 @@ techage.register_node({"techage:ta4_lua_controller"}, { elseif topic == "term" then set_input(pos, number, "term", payload) elseif topic == "msg" then - set_input(pos, number, "msg", payload) + set_input(pos, number, "msg", {src = src, data = payload}) elseif topic == "state" then local running = meta:get_int("running") or STATE_STOPPED return techage.StateStrings[running] or "stopped" diff --git a/techage/lua_controller/server.lua b/techage/lua_controller/server.lua index 7c1d467..62cea21 100644 --- a/techage/lua_controller/server.lua +++ b/techage/lua_controller/server.lua @@ -86,11 +86,14 @@ minetest.register_node("techage:ta4_server", { return end techage.del_mem(pos) - techage.remove_node(pos) minetest.node_dig(pos, node, puncher, pointed_thing) end, - on_timer = function(pos, elasped) + after_dig_node = function(pos, oldnode, oldmetadata) + techage.remove_node(pos, oldnode, oldmetadata) + end, + +on_timer = function(pos, elasped) local meta = M(pos) local nvm = techage.get_nvm(pos) nvm.size = nvm.size or 0 diff --git a/techage/lua_controller/terminal.lua b/techage/lua_controller/terminal.lua index 8361ccf..c2ffef0 100644 --- a/techage/lua_controller/terminal.lua +++ b/techage/lua_controller/terminal.lua @@ -108,7 +108,7 @@ local function command(pos, cmnd, player) if techage.lua_ctlr.not_protected(owner, num) then --output(pos, player..":$ msg "..num.." "..text) output(pos, "> msg "..num.." "..text) - techage.send_single(own_number, num, "msg", {src=own_number, text=text}) + techage.send_single(own_number, num, "msg", text) return end end @@ -230,26 +230,31 @@ techage.lua_ctlr.register_action("put_term", { }) techage.lua_ctlr.register_function("get_msg", { - cmnd = function(self) + cmnd = function(self, raw) local msg = techage.lua_ctlr.get_msg(self.meta.number) if msg then - return msg.src, msg.text + local data = msg.data + if not raw then + data = tostring(data or "") + end + return msg.src, data end end, - help = ' $get_msg() --> number and text string or nil\n'.. + help = ' $get_msg([raw]) --> number and any value or nil\n'.. + ' If the optional `raw` parameter is not set or false,\n'.. + ' the second return value is guaranteed to be a string.\n'.. ' Read a received messages. Number is the node\n'.. ' number of the sender.\n'.. ' example: num,msg = $get_msg().' }) techage.lua_ctlr.register_action("send_msg", { - cmnd = function(self, num, text) - local msg = {src = self.meta.number, text = tostring(text or "")} + cmnd = function(self, num, data) if techage.lua_ctlr.not_protected(self.meta.owner, num) then - techage.send_single(self.meta.number, num, "msg", msg) + techage.send_single(self.meta.number, num, "msg", data) end end, - help = " $send_msg(num, text)\n".. + help = " $send_msg(num, data)\n".. ' Send a message to the controller with number "num".\n'.. ' example: $send_msg("0123", "test")' }) diff --git a/techage/manuals/manual_ta2_DE.md b/techage/manuals/manual_ta2_DE.md index 6b718d9..39bc18c 100644 --- a/techage/manuals/manual_ta2_DE.md +++ b/techage/manuals/manual_ta2_DE.md @@ -70,6 +70,17 @@ Die Antriebsachsen dienen zur Kraftübertragung von der Dampfmaschine zu anderen [ta2_driveaxle|image] +### TA2 Stromgenerator / TA2 Power Generator + +Um Lampen oder andere Stromverbraucher an einer Dampfmaschine betreiben zu können, wird der TA2 Stromgenerator benötigt. Der TA2 Stromgenerator muss auf einer Seite mit Antriebsachsen verbunden werden und liefert dann auf der anderen Seite elektrischen Strom. + +Wird der Stromgenerator nicht mit ausreichend Kraft versorgt, geht er in einen Fehlerzustand und muss über einen Rechtsklick wieder aktiviert werden. + +Das Stromgenerator nimmt primär max. 25 ku an Achsenkraft auf und gibt sekundär max. 24 ku als Strom wieder ab. Er verbraucht also ein ku für die Umwandlung. + +[ta2_generator|image] + + ## Items schieben und sortieren @@ -107,6 +118,8 @@ Der Verteiler ist in der Lage, die Items aus seinem Inventar sortiert in bis zu Der Verteiler besitzt dazu ein Menü mit 4 Filter mit unterschiedlichen Farben, entsprechend den 4 Ausgängen. Soll ein Ausgang genutzt werden, so muss der entsprechende Filter über die "on" Checkbox aktiviert werden. Alle Items, die für diesen Filter konfiguriert sind, werden über den zugeordneten Ausgang ausgegeben. Wird ein Filter aktiviert, ohne das Items konfiguriert werden, so sprechen wir hier von einem "nicht-konfigurierten", offenen Ausgang. +**Achtung: Der Verteiler ist an seinen Ausgängen gleichzeitig ein Schieber. Daher niemals die Gegenstände mit einem Schieber aus dem Verteiler ziehen!** + Für einen nicht-konfigurierten Ausgang gibt es zwei Betriebsarten: 1) Alle Items ausgeben, die an keine anderen Ausgängen ausgegeben werden können, auch wenn diese blockiert sind. diff --git a/techage/manuals/manual_ta2_EN.md b/techage/manuals/manual_ta2_EN.md index 63d0db8..c607ddd 100644 --- a/techage/manuals/manual_ta2_EN.md +++ b/techage/manuals/manual_ta2_EN.md @@ -71,6 +71,18 @@ The drive axles are used to transmit power from the steam engine to other machin [ta2_driveaxle|image] + +### TA2 Power Generator + +The TA2 Power Generator is required to operate lamps or other power consumers on a steam engine. The TA2 Power Generator has to be connected to drive axles on one side and then supplies electricity on the other side. + +If the Power Generator is not supplied with sufficient power, it goes into an error state and must be reactivated with a right-click. + +The Power Generator takes max. 25 ku of axle power and provides on the other side max. 24 ku as electricity. So he consumes one ku for the conversion. + +[ta2_generator|image] + + ## Push and sort items In order to transport objects from one processing station to the next, pushers and tubes are used. See plan. @@ -107,6 +119,8 @@ The distributor is able to transport the items from his inventory sorted in up t The distributor has a menu with 4 filters with different colors, corresponding to the 4 outputs. If an output is to be used, the corresponding filter must be activated via the "on" checkbox. All items that are configured for this filter are output via the assigned output. If a filter is activated without items being configured, we are talking about an "unconfigured", open output. +**Attention: The distributor is also a pusher at its output sides. Therefore, never pull items out of the distributor with a pusher!** + There are two operating modes for a non-configured output: 1) Output all items that cannot be output to any other exit, even if they are blocked. diff --git a/techage/manuals/manual_ta3_DE.md b/techage/manuals/manual_ta3_DE.md index a10211d..0c80684 100644 --- a/techage/manuals/manual_ta3_DE.md +++ b/techage/manuals/manual_ta3_DE.md @@ -198,6 +198,27 @@ In der unteren Hälfte werden die Daten aller Generatoren und Speichersystemen d [ta3_powerterminal|image] +### TA3 Elektromotor / TA3 Electric Motor + +Um TA2 Maschinen über das Stromnetz betreiben zu können, wird der TA3 Elektromotor benötigt. Dieser wandelt Strom in Achsenkraft um. +Wird der Elektromotor nicht mit ausreichend Strom versorgt, geht er in einen Fehlerzustand und muss über einen Rechtsklick wieder aktiviert werden. + +Das Elektromotor nimmt primär max. 40 ku an Strom auf und gibt sekundär max. 39 ku als Achsenkraft wieder ab. Er verbraucht also ein ku für die Umwandlung. + +[ta3_motor|image] + + +### TA3 Strom Terminal / Power Terminal + +Das Strom-Terminal muss mit dem Stromnetz verbunden werden. Es zeigt Daten aus dem Stromnetz an. + +In der oberen Hälfte werden nur die Daten eines ausgewählten Typs ausgegeben. Wird als Typ bspw. "Kraftwerk" gewählt, so werden nur die Daten von Öl- und Kohlekraftwerken gesammelt und ausgegeben. Links werden die Daten von Generatoren (Stromabgabe) und rechts die Daten von Energiespeichern (Stromaufnahme) ausgegeben. Beim Akkublocks bspw. wird beides ausgegeben, da der Akku Strom aufnehmen und abgeben kann. + +In der unteren Hälfte werden die Daten aller Generatoren und Speichersystemen des ganzen Stromnetzen zusammengefasst ausgegeben. + +[ta3_powerterminal|image] + + ## TA3 Industrieofen Der TA3 Industrieofen dient als Ergänzung zu normalen Ofen (furnace). Damit können alle Waren mit "Koch" Rezepten, auch im Industrieofen hergestellt werden. Es gibt aber auch spezielle Rezepte, die nur im Industrieofen hergestellt werden können. @@ -569,7 +590,7 @@ Das Terminal besitzt folgende, lokalen Kommandos: - `pub` schalte in den öffentlichen Modus um - `priv` schalte in den privaten Modus um -Im privaten Modul kann nur der Besitzer selbst Kommandos eingeben oder Tasten nutzen. +Im privaten Modus (private) kann das Terminal nur von Spielern verwendet werden, die an diesem Ort bauen können, also Protection Rechte besitzen. Im öffentlichen Modus (public) können alle Spieler die vorkonfigurierten Tasten verwenden. [ta3_terminal|image] diff --git a/techage/manuals/manual_ta3_EN.md b/techage/manuals/manual_ta3_EN.md index e3a224a..240bd84 100644 --- a/techage/manuals/manual_ta3_EN.md +++ b/techage/manuals/manual_ta3_EN.md @@ -198,6 +198,18 @@ In the lower half, the data of all generators and storage systems of the entire [ta3_powerterminal|image] +### TA3 Electric Motor + +The TA3 Electric Motor is required in order to be able to operate TA2 machines via the power grid. The TA3 Electric Motor converts electricity into axle power. +If the electric motor is not supplied with sufficient power, it goes into an fault state and must be reactivated with a right-click. + +The electric motor takes max. 40 ku of electricity and provides on the other side max. 39 ku as axle power. So he consumes one ku for the conversion. + +[ta3_motor|image] + + + + ## TA3 Industrial Furnace The TA3 industrial furnace serves as a supplement to normal furnaces. This means that all goods can be produced with "cooking" recipes, even in an industrial furnace. But there are also special recipes that can only be made in an industrial furnace. @@ -567,7 +579,9 @@ The terminal has the following local commands: - `pub` switch to public mode - `priv` switch to private mode -In the private mode, only the owner can enter commands himself or use keys. +In private mode, the terminal can only be used by players who can build at this location, i.e. who have protection rights. + +In public mode, all players can use the preconfigured keys. [ta3_terminal|image] diff --git a/techage/manuals/manual_ta4_DE.md b/techage/manuals/manual_ta4_DE.md index 1eadb54..377bbd8 100644 --- a/techage/manuals/manual_ta4_DE.md +++ b/techage/manuals/manual_ta4_DE.md @@ -7,10 +7,11 @@ Regenerative Energiequellen wie Wind, Sonne und Biokraft helfen dir, das Ölzeit ## Windkraftanlage -Eine Windkraftanlagen liefern immer dann Strom, wenn Wind vorhanden ist. Im Spiel gibt es keinen Wind, aber die Mod simuliert dies dadurch, dass sich nur morgens (5:00 - 9:00) und abends (17:00 - 21:00) die Windräder drehen und damit Strom liefern, sofern diese an geeigneten Stellen errichtet werden. +Eine Windkraftanlage liefern immer dann Strom, wenn Wind vorhanden ist. Im Spiel gibt es keinen Wind, aber die Mod simuliert dies dadurch, dass sich nur morgens (5:00 - 9:00) und abends (17:00 - 21:00) die Windräder drehen. Eine Windkraftanlage liefert nur dann Strom, wenn sie an einer geeigneten Stelle aufgestellt ist. -Die TA Windkraftanlagen sind reine Offshore Anlagen, das heißt, die müssen im Meer (Wasser) errichtet werden. Dies bedeutet, dass um den Mast herum mit einem Abstand von 20 Blöcken nur Wasser sein darf und das mindestens 2 Blöcke tief. -Der Rotor muss in einer Höhe (Y-Koordinate) von 12 bis maximal 20 m platziert werden. Der Abstand zu weiteren Windkraftanlagen muss mindestens 14 m betragen. +Die TA Windkraftanlagen sind reine Offshore Anlagen, das heißt, die müssen im Meer errichtet werden. Dies bedeutet, dass Windkraftanlagen nur in einem Meer (occean) Biom errichtet werden können und dass um den Mast herum ausreichend Wasser und freie Sicht vorhanden sein müssen. + +Um eine geeignete Stelle zu finden, musst du mit dem Schraubenschlüssel (TechAge Info Werkzeug) auf das Wasser klicken. Ob diese Stelle für den Mast der Windkraftanlage geeignet ist, wird dir als Chat Nachricht angezeigt. Der Strom muss vom Rotor-Block durch den Mast nach unten geführt werden. Dazu zuerst die Stromleitung nach oben ziehen und das Stromkabel dann mit TA4 Säulenblöcke "verputzen". Unten kann eine Arbeitsplattform errichtet werden. Der Plan rechts zeigt den Aufbau im oberen Teil. @@ -390,9 +391,9 @@ Die TA4 Sensor Kiste dient zum Aufbau von Automatischen Lagern oder Verkaufsauto Wird etwas in die Kiste gelegt, oder entnommen, oder eine der Tasten "F1"/"F2" gedrückt, so wird ein Event-Signal an den Lua Controller gesendet. Die Sensor Kiste unterstützt folgende Kommandos: -- Über `state = $read_data(, "state")` kann der Status der Kiste abgefragt werden. Mögliche Antworten sind: "empty", "loaded", "full" -- Über `name, action = $read_data(, "action")` kann die letzte Spieleraktion abgefragt werden. `name` ist der Spielername, Als `action` wird zurückgeliefert: "put", "take", "f1", "f2". -- Über `stacks = $read_data(, "stacks")` kann der Inhalt der Kiste ausgelesen werden. Siehe dazu: https://github.com/joe7575/techage/blob/master/manuals/ta4_lua_controller_EN.md#sensor-chest +- Über `state = $send_cmnd(, "state")` kann der Status der Kiste abgefragt werden. Mögliche Antworten sind: "empty", "loaded", "full" +- Über `name, action = $send_cmnd(, "action")` kann die letzte Spieleraktion abgefragt werden. `name` ist der Spielername, Als `action` wird zurückgeliefert: "put", "take", "f1", "f2". +- Über `stacks = $send_cmnd(, "stacks")` kann der Inhalt der Kiste ausgelesen werden. Siehe dazu: https://github.com/joe7575/techage/blob/master/manuals/ta4_lua_controller_EN.md#sensor-chest - Über `$send_cmnd(, "text", "press both buttons and\nput something into the chest")` kann der Text im Menü der Sensor Kiste gesetzt werden. Über die Checkbox "Erlaube öffentlichen Zugriff" kann eingestellt werden, ob die Kiste von jedem genutzt werden darf, oder nur von Spielern die hier Zugriffsrechte haben. @@ -596,8 +597,8 @@ Die Kiste kann nur von den Spielern genutzt werden, die an diesem Ort auch bauen Der Kiste besitzt ein zusätzliches Kommandos für den Lua Controller: - `count` dient zur Anfrage, wie viele Items in der Kiste sind. - Beispiel 1: `$read_data(CHEST, "count")` --> Summe der Items über alle 8 Speicher - Beispiel 2: `$read_data(CHEST, "count", 2)` --> Anzahl der Items in Speicher 2 (zweiter von links) + Beispiel 1: `$send_cmnd(CHEST, "count")` --> Summe der Items über alle 8 Speicher + Beispiel 2: `$send_cmnd(CHEST, "count", 2)` --> Anzahl der Items in Speicher 2 (zweiter von links) [ta4_8x2000_chest|image] diff --git a/techage/manuals/manual_ta4_EN.md b/techage/manuals/manual_ta4_EN.md index 595f71c..6024efa 100644 --- a/techage/manuals/manual_ta4_EN.md +++ b/techage/manuals/manual_ta4_EN.md @@ -7,10 +7,11 @@ Renewable energy sources such as wind, sun and biofuels help you to leave the oi ## Wind Turbine -A wind turbine always delivers electricity when there is wind. There is no wind in the game, but the mod simulates this by only turning the wind turbines in the morning (5:00 a.m. - 9:00 a.m.) and in the evening (5:00 p.m. - 9:00 p.m.) and thus supplying electricity, provided they are positioned appropriately. +A wind turbine always supplies electricity when there is wind. There is no wind in the game, but the mod simulates this by turning the wind turbines only in the morning (5:00 - 9:00) and in the evening (17:00 - 21:00). A wind turbine only supplies electricity if it is set up in a suitable location. -The TA wind turbines are pure offshore plants, which means that they have to be installed in the sea (water). This means that there must be in the minimum 20 blocks of water around the mast and at least 2 blocks deep. -The rotor must be placed at a height (Y coordinate) of 12 to a maximum of 20 m. The distance to other wind turbines must be at least 14 m. +The TA wind power plants are pure offshore plants, which means that they have to be built in the sea. This means that wind turbines can only be build in a sea (occean) biome and that there must be sufficient water and a clear view around the mast. + +To find a suitable spot, click on the water with the wrench (TechAge Info Tool). A chat message will show you whether this position is suitable for the mast of the wind turbine. The current must be led from the rotor block down through the mast. First pull the power line up and then "plaster" the power cable with TA4 pillar blocks. A work platform can be built below. The plan on the right shows the structure in the upper part. @@ -392,9 +393,9 @@ The TA4 sensor box is used to set up automatic warehouses or vending machines in If something is put into the box or removed, or one of the "F1" / "F2" keys is pressed, an event signal is sent to the Lua controller. The sensor box supports the following commands: -- The status of the box can be queried via `state = $read_data(, "state")`. Possible answers are: "empty", "loaded", "full" -- The last player action can be queried via `name, action = $read_data(, "action")`. `name` is the player name. One of the following is returned as `action`: "put", "take", "f1", "f2". -- The contents of the box can be read out via `stacks = $read_data(, "stacks")`. See: https://github.com/joe7575/techage/blob/master/manuals/ta4_lua_controller_EN.md#sensor-chest +- The status of the box can be queried via `state = $send_cmnd(, "state")`. Possible answers are: "empty", "loaded", "full" +- The last player action can be queried via `name, action = $send_cmnd(, "action")`. `name` is the player name. One of the following is returned as `action`: "put", "take", "f1", "f2". +- The contents of the box can be read out via `stacks = $send_cmnd(, "stacks")`. See: https://github.com/joe7575/techage/blob/master/manuals/ta4_lua_controller_EN.md#sensor-chest - Via `$send_cmnd(, "text", "press both buttons and\nput something into the chest")` the text can be set in the menu of the sensor box. The checkbox "Allow public chest access" can be used to set whether the box can be used by everyone or only by players who have access/protection rights here. @@ -579,7 +580,7 @@ The TA4 8x2000 chest does not have a normal inventory like other chest, but has If the chest is filled with a pusher, all stores fill from left to right. If all 8 stores are full and no further items can be added, further items are rejected. -** Row function ** +**Row function** Several TA4 8x2000 chests can be connected to a large chest with more content. To do this, the chests must be placed in a row one after the other. @@ -597,8 +598,8 @@ The chest can only be used by players who can build at this location, i.e. who h The chest has an additional command for the Lua controller: - `count` is used to request how many items are in the chest. - Example 1: `$read_data(CHEST, "count")` -> Sum of items across all 8 stores - Example 2: `$read_data(CHEST, "count", 2)` -> number of items in store 2 (second from left) + Example 1: `$send_cmnd(CHEST, "count")` -> Sum of items across all 8 stores + Example 2: `$send_cmnd(CHEST, "count", 2)` -> number of items in store 2 (second from left) [ta4_8x2000_chest|image] diff --git a/techage/manuals/markdown2formspec.py b/techage/manuals/markdown2formspec.py index 72df37b..76c7cb4 100644 --- a/techage/manuals/markdown2formspec.py +++ b/techage/manuals/markdown2formspec.py @@ -106,7 +106,7 @@ class MyRenderer(mistune.Renderer): ## def block_code(self, code, lang): text = formspec_escape(code.strip()) - lines = text.split("\n") + lines = text.split("\\n") lines = [" " + item for item in lines] self.TextChunck.extend(lines) self.TextChunck.append("") diff --git a/techage/manuals/ta4_lua_controller_EN.md b/techage/manuals/ta4_lua_controller_EN.md index 34f0f34..52a247b 100644 --- a/techage/manuals/ta4_lua_controller_EN.md +++ b/techage/manuals/ta4_lua_controller_EN.md @@ -346,10 +346,16 @@ In addition to Lua standard function the Lua Controller provides the following f ### Techage Command Functions -* `$read_data(num, ident, add_data)` - Read any kind of data from another block with the given number _num_. - _ident_ specifies the data to be read. - _add_data_ is for additional data and normally not needed. - The result is block dependent (see table below): +With the `$send_cmnd(num, ident, add_data)` function, you can send commands to and retrieve data from another block with the given number _num_. +The possible commands can be classified in two groups: Commands for reading data and commands for triggering an action. +Please note, that this is not a technical distinction, only a logical. + +**Reading data** + +- _ident_ specifies the data to be read. +- _add_data_ is for additional data and normally not needed. +- The result is block dependent (see table below) + | ident | returned data | comment | | ------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | @@ -358,18 +364,22 @@ In addition to Lua standard function the Lua Controller provides the following f | "state" | one of: "empty", "loaded", "full" | State of a chest or Sensor Chest | | "fuel" | number | fuel value of a fuel consuming block | | "depth" | number | Read the current depth value of a quarry block (1..80) | -| "load" | number | Read the load value in percent (0..100) of a tank, silo, accu, or battery block, or from the Signs Bot Box. Silo and tank return two values: The percentage value and the absolute value in units.
Example: percent, absolute = $read_data("223", "load") | +| "load" | number | Read the load value in percent (0..100) of a tank, silo, accu, or battery block, or from the Signs Bot Box. Silo and tank return two values: The percentage value and the absolute value in units.
Example: percent, absolute = $send_cmnd("223", "load") | | "delivered" | number | Read the current delivered power value of a generator block. A power consuming block (accu) provides a negative value | -| "action" | player-name, action-string | only for Sensor Chests | -| "stacks" | Array with up to 4 Stores with the inventory content (see example) | only for Sensor Chests | +| "action" | player-name, action-string | Only for Sensor Chests | +| "stacks" | Array with up to 4 Stores with the inventory content (see example) | Only for Sensor Chests | | "count" | number | Read the item counter of the TA4 Item Detector block | | "count" | number of items | Read the total amount of TA4 chest items. An optional number as `add_data` is used to address only one inventory slot (1..8, from left to right). | -| "itemstring" | item string of the given slot | Specific command for the TA4 8x2000 Chest to read the item type (technical name) of one chest slot, specified via `add_data` (1..8).
Example: s = $read_data("223", "itemstring", 1) | +| "itemstring" | item string of the given slot | Specific command for the TA4 8x2000 Chest to read the item type (technical name) of one chest slot, specified via `add_data` (1..8).
Example: s = $send_cmnd("223", "itemstring", 1) | +| "output" | recipe output string,
e.g.: "default:glass" | Only for the Industrial Furnace. If no recipe is active, the command returns "unknown" | +**Trigger an action** -* `$send_cmnd(num, cmnd, data)` - Send a command to another block. _num_ is the number of the remote block, like "1234". _cmnd_ is the command, _data_ is additional data (see table below): +- _num_ is the number of the remote block, like "1234" +- _cmnd_ is the command +- _data_ is additional data (see table below) | cmnd | data | comment | | -------------------------------- | ------------ | ------------------------------------------------------------ | @@ -406,11 +416,10 @@ In contrast the Controller can send text strings to the terminal. ### Further Functions -Messages are used to transport data between Controllers. Messages are text strings or any other data. Incoming messages are stored in order (up to 10) and can be read one after the other. -* `$get_msg()` - Read a received message. The function returns the sender number and the message. (see example "Emails") +Messages are used to transport data between Controllers. Messages can contain arbitrary data. Incoming messages are stored in order (up to 10) and can be read one after the other. +* `$get_msg([raw])` - Read a received message. The function returns the sender number and the message. (see example "Emails"). If the _raw_ parameter is not set or false, the message is guaranteed to be a string. * `$send_msg(num, msg)` - Send a message to another Controller. _num_ is the destination number. (see example "Emails") - * `$chat(text)` - Send yourself a chat message. _text_ is a text string. * `$door(pos, text)` - Open/Close a door at position "pos". @@ -419,7 +428,7 @@ Messages are used to transport data between Controllers. Messages are text strin * `$item_description("default:apple")` Get the description (item name) for a specified itemstring, e. g. determined via the TA4 8x2000 Chest command `itemstring`: - `str = $read_data("223", "itemstring", 1)` + `str = $send_cmnd("223", "itemstring", 1)` `descr = $item_description(str)` @@ -504,15 +513,15 @@ if ticks % 60 == 0 then $display(DISPLAY, 1, min.." min") -- Cactus chest overrun - sts = $read_data("1034", "state") -- read pusher status + sts = $send_cmnd("1034", "state") -- read pusher status if sts == "blocked" then $display(DISPLAY, 2, "Cactus full") end -- Tree chest overrun - sts = $read_data("1065", "state") -- read pusher status + sts = $send_cmnd("1065", "state") -- read pusher status if sts == "blocked" then $display(DISPLAY, 3, "Tree full") end -- Furnace fuel empty - sts = $read_data("1544", "state") -- read pusher status + sts = $send_cmnd("1544", "state") -- read pusher status if sts == "standby" then $display(DISPLAY, 4, "Furnace fuel") end end ``` @@ -570,7 +579,7 @@ loop() code: ```lua if event then - name = $read_data(SENSOR, "name") + name = $send_cmnd(SENSOR, "name") if name == "" then -- no player arround $clear_screen(DISPLAY) else @@ -602,13 +611,13 @@ loop() code: ```lua if event and $get_input(SENSOR) == "on" then -- read inventory state - state = $read_data(SENSOR, "state") + state = $send_cmnd(SENSOR, "state") $print("state: "..state) -- read player name and action - name, action = $read_data(SENSOR, "action") + name, action = $send_cmnd(SENSOR, "action") $print("action"..": "..name.." "..action) -- read inventory content - stacks = $read_data(SENSOR, "stacks") + stacks = $send_cmnd(SENSOR, "stacks") for i,stack in stacks.next() do $print("stack: "..stack.get("name").." "..stack.get("count")) end diff --git a/techage/manuals/ta4_lua_controller_EN.pdf b/techage/manuals/ta4_lua_controller_EN.pdf index 7469d82f9ff31a4ac073d35657ddb6dc638d9f84..0f9e6fdb6592d9f62b13ed28c5eaf37ed7c10ee0 100644 GIT binary patch delta 94370 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 W7BtnbVqeIV79+z=qTH2?toJ{HJy!_; delta 96499 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∋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≺D}GdM84 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 rJvmEZ9FbmpH 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 diff --git a/techage/manuals/toc_DE.md b/techage/manuals/toc_DE.md index c018a99..eb3164c 100644 --- a/techage/manuals/toc_DE.md +++ b/techage/manuals/toc_DE.md @@ -27,6 +27,7 @@ - [TA2 Schwungrad / Flywheel](./manual_ta2_DE.md#ta2-schwungrad--flywheel) - [TA2 Dampfleitungen / Steam Pipe](./manual_ta2_DE.md#ta2-dampfleitungen--steam-pipe) - [TA2 Antriebsachsen / TA2 Drive Axle](./manual_ta2_DE.md#ta2-antriebsachsen--ta2-drive-axle) + - [TA2 Stromgenerator / TA2 Power Generator](./manual_ta2_DE.md#ta2-stromgenerator--ta2-power-generator) - [Items schieben und sortieren](./manual_ta2_DE.md#items-schieben-und-sortieren) - [Röhren / TechAge Tube](./manual_ta2_DE.md#röhren--techage-tube) - [TA2 Schieber / Pusher](./manual_ta2_DE.md#ta2-schieber--pusher) @@ -44,10 +45,10 @@ - [TA2 Flüssigkeitensammler / Liquid Sampler](./manual_ta2_DE.md#ta2-flüssigkeitensammler--liquid-sampler) - [TA2 Gesicherte Kiste / Protected Chest](./manual_ta2_DE.md#ta2-gesicherte-kiste--protected-chest) - [Techage Forceload Block](./manual_ta2_DE.md#techage-forceload-block) -- [TA3: Ölzeitalter](./manual_ta3_DE.md#ta3:-ölzeitalter) - - [Kohlekraftwerk / Ölkraftwerk](./manual_ta3_DE.md#kohlekraftwerk--ölkraftwerk) +- [TA3: Ölzeitalter](./manual_ta3_DE.md#ta3:-Ölzeitalter) + - [Kohlekraftwerk / Ölkraftwerk](./manual_ta3_DE.md#kohlekraftwerk--Ölkraftwerk) - [TA3 Kraftwerks-Feuerbox / Power Station Firebox](./manual_ta3_DE.md#ta3-kraftwerks-feuerbox--power-station-firebox) - - [TA3 Kraftwerks-Ölbrenner / TA3 Power Station Oil Burner](./manual_ta3_DE.md#ta3-kraftwerks-ölbrenner--ta3-power-station-oil-burner) + - [TA3 Kraftwerks-Ölbrenner / TA3 Power Station Oil Burner](./manual_ta3_DE.md#ta3-kraftwerks-Ölbrenner--ta3-power-station-oil-burner) - [TA3 Boiler unten/oben](./manual_ta3_DE.md#ta3-boiler-untenoben) - [TA3 Turbine](./manual_ta3_DE.md#ta3-turbine) - [TA3 Generator](./manual_ta3_DE.md#ta3-generator) @@ -65,8 +66,10 @@ - [TA3 Kleiner Stromgenerator / Tiny Power Generator](./manual_ta3_DE.md#ta3-kleiner-stromgenerator--tiny-power-generator) - [TA3 Akku Block / Akku Box](./manual_ta3_DE.md#ta3-akku-block---akku-box) - [TA3 Strom Terminal / Power Terminal](./manual_ta3_DE.md#ta3-strom-terminal--power-terminal) + - [TA3 Elektromotor / TA3 Electric Motor](./manual_ta3_DE.md#ta3-elektromotor--ta3-electric-motor) + - [TA3 Strom Terminal / Power Terminal](./manual_ta3_DE.md#ta3-strom-terminal--power-terminal) - [TA3 Industrieofen](./manual_ta3_DE.md#ta3-industrieofen) - - [TA3 Ofen-Ölbrenner / Furnace Oil Burner](./manual_ta3_DE.md#ta3-ofen-ölbrenner--furnace-oil-burner) + - [TA3 Ofen-Ölbrenner / Furnace Oil Burner](./manual_ta3_DE.md#ta3-ofen-Ölbrenner--furnace-oil-burner) - [TA3 Ofenoberteil / Furnace Top](./manual_ta3_DE.md#ta3-ofenoberteil--furnace-top) - [TA3 Gebläse / Booster](./manual_ta3_DE.md#ta3-gebläse--booster) - [Flüssigkeiten](./manual_ta3_DE.md#flüssigkeiten) @@ -76,18 +79,18 @@ - [TA4 Röhre / Pipe](./manual_ta3_DE.md#ta4-röhre--pipe) - [TA3 Rohr/Wanddurchbruch / TA3 Pipe Wall Entry Blöcke](./manual_ta3_DE.md#ta3-rohrwanddurchbruch--ta3-pipe-wall-entry-blöcke) - [TA Ventil / TA Valve](./manual_ta3_DE.md#ta-ventil--ta-valve) - - [Öl-Förderung](./manual_ta3_DE.md#öl-förderung) - - [TA3 Ölexplorer / Oil Explorer](./manual_ta3_DE.md#ta3-ölexplorer--oil-explorer) - - [TA3 Ölbohrkiste / Oil Drill Box](./manual_ta3_DE.md#ta3-ölbohrkiste--oil-drill-box) - - [TA3 Ölpumpe / Oil Pumpjack](./manual_ta3_DE.md#ta3-ölpumpe--oil-pumpjack) + - [Öl-Förderung](./manual_ta3_DE.md#Öl-förderung) + - [TA3 Ölexplorer / Oil Explorer](./manual_ta3_DE.md#ta3-Ölexplorer--oil-explorer) + - [TA3 Ölbohrkiste / Oil Drill Box](./manual_ta3_DE.md#ta3-Ölbohrkiste--oil-drill-box) + - [TA3 Ölpumpe / Oil Pumpjack](./manual_ta3_DE.md#ta3-Ölpumpe--oil-pumpjack) - [TA3 Bohrgestänge / Drill Pipe](./manual_ta3_DE.md#ta3-bohrgestänge--drill-pipe) - - [Öltank / Oil Tank](./manual_ta3_DE.md#öltank--oil-tank) - - [Öl-Transport](./manual_ta3_DE.md#öl-transport) - - [Öl-Transport mit dem Tankwagen](./manual_ta3_DE.md#öl-transport-mit-dem-tankwagen) - - [Öl-Transport mit Fässern über Minecarts](./manual_ta3_DE.md#öl-transport-mit-fässern-über-minecarts) + - [Öltank / Oil Tank](./manual_ta3_DE.md#Öltank--oil-tank) + - [Öl-Transport](./manual_ta3_DE.md#Öl-transport) + - [Öl-Transport mit dem Tankwagen](./manual_ta3_DE.md#Öl-transport-mit-dem-tankwagen) + - [Öl-Transport mit Fässern über Minecarts](./manual_ta3_DE.md#Öl-transport-mit-fässern-über-minecarts) - [Tankwagen / Tank Cart](./manual_ta3_DE.md#tankwagen--tank-cart) - [Kistenwagen / Chest Cart](./manual_ta3_DE.md#kistenwagen--chest-cart) - - [Öl-Verarbeitung](./manual_ta3_DE.md#öl-verarbeitung) + - [Öl-Verarbeitung](./manual_ta3_DE.md#Öl-verarbeitung) - [Destillationsturm / distiller tower](./manual_ta3_DE.md#destillationsturm--distiller-tower) - [Aufkocher / reboiler)](./manual_ta3_DE.md#aufkocher--reboiler)) - [Logik-/Schalt-Blöcke](./manual_ta3_DE.md#logik-schalt-blöcke) diff --git a/techage/manuals/toc_EN.md b/techage/manuals/toc_EN.md index f22bfad..dcc1e79 100644 --- a/techage/manuals/toc_EN.md +++ b/techage/manuals/toc_EN.md @@ -27,6 +27,7 @@ - [TA2 Flywheel](./manual_ta2_EN.md#ta2-flywheel) - [TA2 Steam Pipes](./manual_ta2_EN.md#ta2-steam-pipes) - [TA2 Drive Axle / TA2 Gearbox](./manual_ta2_EN.md#ta2-drive-axle--ta2-gearbox) + - [TA2 Power Generator](./manual_ta2_EN.md#ta2-power-generator) - [Push and sort items](./manual_ta2_EN.md#push-and-sort-items) - [TechAge Tube](./manual_ta2_EN.md#techage-tube) - [TA2 Pusher](./manual_ta2_EN.md#ta2-pusher) @@ -65,6 +66,7 @@ - [TA3 Small Power Generator](./manual_ta3_EN.md#ta3-small-power-generator) - [TA3 Battery Block](./manual_ta3_EN.md#ta3-battery-block) - [TA3 Power Terminal](./manual_ta3_EN.md#ta3-power-terminal) + - [TA3 Electric Motor](./manual_ta3_EN.md#ta3-electric-motor) - [TA3 Industrial Furnace](./manual_ta3_EN.md#ta3-industrial-furnace) - [TA3 Furnace Oil Burner](./manual_ta3_EN.md#ta3-furnace-oil-burner) - [TA3 Furnace Top](./manual_ta3_EN.md#ta3-furnace-top) diff --git a/techage/power/distribution.lua b/techage/power/distribution.lua index 2e1a079..60a4c20 100644 --- a/techage/power/distribution.lua +++ b/techage/power/distribution.lua @@ -27,7 +27,7 @@ local function start_consumer(tbl, tlib_type) if def and def["cstate"] == NOPOWER and (def["calive"] or 0) > 0 then local ndef = net_def(v.pos, tlib_type) def["cstate"] = RUNNING - def["taken"] = v.nominal or 0 + def["taken"] = v.nominal or def.curr_power or 0 if ndef.on_power then ndef.on_power(v.pos, tlib_type) end @@ -73,10 +73,10 @@ local function get_consumer_sum(tbl, tlib_type, cycle_time) if def and def["cstate"] ~= STOPPED then def["calive"] = (def["calive"] or 1) - cycle_time/2 if def["calive"] >= 0 then - sum = sum + v.nominal + sum = sum + (v.nominal or def.curr_power or 0) end end - --print(N(v.pos), P2S(v.pos), def["cstate"], def["calive"]) + --print(N(v.pos), P2S(v.pos), def["cstate"], def["calive"], sum) end return sum end @@ -155,7 +155,7 @@ function techage.power.get_con1_sum(network, tlib_type) local nvm = techage.get_nvm(v.pos) local def = nvm[tlib_type] -- power related network data if def and def["cstate"] ~= STOPPED then - sum = sum + v.nominal + sum = sum + (v.nominal or def.curr_power or 0) end end return sum diff --git a/techage/power/formspecs.lua b/techage/power/formspecs.lua index c82f500..d8c0e2e 100644 --- a/techage/power/formspecs.lua +++ b/techage/power/formspecs.lua @@ -48,11 +48,24 @@ function techage.power.formspec_power_bar(max_power, current_power) return "techage_form_level_bg.png^[lowpart:"..percent..":techage_form_level_fg.png" end -function techage.power.formspec_label_bar(x, y, label, max_power, current_power, unit) +function techage.power.formspec_label_bar(pos, x, y, label, max_power, current_power, unit) local percent, ypos - current_power = current_power or 0 + max_power = max_power or 1 unit = unit or "ku" + + if current_power == 0 then + -- check if power network is overloaded + if techage.power.network_overloaded(pos, techage.ElectricCable) then + return "container["..x..","..y.."]".. + "box[0,0;2.3,3.3;#395c74]".. + "label[0.2,0;"..label.."]".. + "label[0.7,0.4;"..max_power.." "..unit.."]".. + "image[0,0.5;1,3;techage_form_level_red_fg.png]".. + "container_end[]" + end + end + current_power = current_power or 0 if current_power == 0 then percent = 0 ypos = 2.8 diff --git a/techage/power/node_api.lua b/techage/power/node_api.lua index 2bc99be..1c4cc39 100644 --- a/techage/power/node_api.lua +++ b/techage/power/node_api.lua @@ -148,6 +148,17 @@ function techage.power.power_available(pos, Cable) return netw and netw.on and netw.alive and netw.alive > 0 end +function techage.power.network_overloaded(pos, Cable) + local nvm = techage.get_nvm(pos) + local tlib_type = Cable.tube_type + local netID = nvm[Cable.tube_type] and nvm[Cable.tube_type]["netID"] + local netw = networks.has_network(tlib_type, netID) + if netw then + local sum = (netw.available1 or 0) + (netw.available2 or 0) + return sum > 0 and sum < (netw.needed1 or 0) + end +end + -- this is more a try to start, the start will be performed by on_power() function techage.power.consumer_start(pos, Cable, cycle_time) local nvm = techage.get_nvm(pos) @@ -228,5 +239,24 @@ function techage.power.generator_alive(pos, Cable, cycle_time, outdir, curr_powe return 0 end +-- Calculate the needed power over all con1 consumers +function techage.power.needed_power(pos, Cable, outdir) + local sum = 0 + networks.connection_walk(pos, outdir, Cable, function(pos, indir, node) + local net = net_def(pos, Cable.tube_type) -- network definition + if net.ntype == "con1" then + local nvm = techage.get_nvm(pos) + local def = nvm[Cable.tube_type] -- power related data + + if def and def["cstate"] ~= STOPPED then + if def["calive"] >= 0 then + sum = sum + (net.nominal or def.curr_power or 0) + end + end + end + end) + return sum +end + -- function delete_netID(pos, outdir, Cable) techage.power.delete_netID = delete_netID diff --git a/techage/power/power_terminal.lua b/techage/power/power_terminal.lua index ccf1988..a20852c 100644 --- a/techage/power/power_terminal.lua +++ b/techage/power/power_terminal.lua @@ -129,10 +129,10 @@ local function formspec(pos, nvm) "box[0,-0.1;9.8,0.5;#c6e8ff]".. "label[4,-0.1;"..minetest.colorize( "#000000", S("Network Data")).."]".. "label[9.5,-0.1;"..minetest.colorize( "#000000", star).."]".. - power.formspec_label_bar(0, 0.7, S("Genera. 1"), gen1.pow_act, gen1.pow_used).. - power.formspec_label_bar(2.5, 0.7, S("Genera. 2"), gen2.pow_act, gen2.pow_used).. - power.formspec_label_bar(5, 0.7, S("Consum. 2"), con2.pow_act, con2.pow_used).. - power.formspec_label_bar(7.5, 0.7, S("Consum. 1"), con1.pow_act, con1.pow_used).. + power.formspec_label_bar(pos, 0, 0.7, S("Genera. 1"), gen1.pow_act, gen1.pow_used).. + power.formspec_label_bar(pos, 2.5, 0.7, S("Genera. 2"), gen2.pow_act, gen2.pow_used).. + power.formspec_label_bar(pos, 5, 0.7, S("Consum. 2"), con2.pow_act, con2.pow_used).. + power.formspec_label_bar(pos, 7.5, 0.7, S("Consum. 1"), con1.pow_act, con1.pow_used).. "box[0,4.3;9.8,0.4;#c6e8ff]".. "box[0,4.85;9.8,0.4;#395c74]".. "box[0,5.35;9.8,0.4;#395c74]".. diff --git a/techage/power/power_terminal2.lua b/techage/power/power_terminal2.lua index 240f237..2c5d691 100644 --- a/techage/power/power_terminal2.lua +++ b/techage/power/power_terminal2.lua @@ -37,6 +37,7 @@ local Generators = { S("Energy storage"), S("Fuel cell"), S("Electrolyzer"), + S("TA2 Generator"), } local Storage = { @@ -55,6 +56,7 @@ local GeneratorPerformances = { 60, -- S("Energy storage") 25, -- S("Fuel cell") 30, -- S("Electrolyzer") + 24, -- S("TA2 Generator") } -- diff --git a/techage/solar/inverter.lua b/techage/solar/inverter.lua index b5ea96c..9b877f8 100644 --- a/techage/solar/inverter.lua +++ b/techage/solar/inverter.lua @@ -67,8 +67,8 @@ local function formspec(self, pos, nvm) default.gui_slots.. "box[0,-0.1;5.8,0.5;#c6e8ff]".. "label[2.5,-0.1;"..minetest.colorize( "#000000", S("Inverter")).."]".. - power.formspec_label_bar(0, 0.8, S("Power DC"), PWR_PERF, max_power).. - power.formspec_label_bar(3.5, 0.8, S("Power AC"), max_power, delivered).. + power.formspec_label_bar(pos, 0, 0.8, S("Power DC"), PWR_PERF, max_power).. + power.formspec_label_bar(pos, 3.5, 0.8, S("Power AC"), max_power, delivered).. arrow.. "image_button[2.5,3;1,1;".. self:get_state_button_image(nvm) ..";state_button;]".. "tooltip[2.5,3;1,1;"..self:get_state_tooltip(nvm).."]" diff --git a/techage/steam_engine/flywheel.lua b/techage/steam_engine/flywheel.lua index 6d5bf1c..189a3bd 100644 --- a/techage/steam_engine/flywheel.lua +++ b/techage/steam_engine/flywheel.lua @@ -38,7 +38,7 @@ local function formspec(self, pos, nvm) default.gui_bg.. default.gui_bg_img.. default.gui_slots.. - power.formspec_label_bar(0, 0.8, S("power"), PWR_CAPA, nvm.provided).. + power.formspec_label_bar(pos, 0, 0.8, S("power"), PWR_CAPA, nvm.provided).. "image_button[2.8,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]".. "tooltip[2.8,2;1,1;"..self:get_state_tooltip(nvm).."]" end diff --git a/techage/ta3_power/akkubox.lua b/techage/ta3_power/akkubox.lua index 17421a0..f5efc7a 100644 --- a/techage/ta3_power/akkubox.lua +++ b/techage/ta3_power/akkubox.lua @@ -36,7 +36,7 @@ local function formspec(self, pos, nvm) default.gui_slots.. "box[0,-0.1;4.8,0.5;#c6e8ff]".. "label[1,-0.1;"..minetest.colorize( "#000000", S("TA3 Akku Box")).."]".. - power.formspec_label_bar(0, 0.8, S("Load"), PWR_CAPA, capa).. + power.formspec_label_bar(pos, 0, 0.8, S("Load"), PWR_CAPA, capa).. "image_button[2.6,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]".. "tooltip[3,2;1,1;"..self:get_state_tooltip(nvm).."]".. "label[3.7,1.2;"..S("Electricity").."]".. diff --git a/techage/ta3_power/axle2power.lua b/techage/ta3_power/axle2power.lua new file mode 100644 index 0000000..cc06dfd --- /dev/null +++ b/techage/ta3_power/axle2power.lua @@ -0,0 +1,236 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019-2020 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA2 Power Generator + +]]-- + +-- for lazy programmers +local M = minetest.get_meta +local S = techage.S +local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end +local S2P = minetest.string_to_pos + +local Cable = techage.ElectricCable +local Axle = techage.Axle +local power = techage.power +local networks = techage.networks + +local CYCLE_TIME = 2 +local PWR_PERF = 24 + +local function swap_node(pos, name) + local node = techage.get_node_lvm(pos) + if node.name == name then + return + end + node.name = name + minetest.swap_node(pos, node) +end + +local function on_power(pos) + local nvm = techage.get_nvm(pos) + nvm.axle = nvm.axle or {} + nvm.consumer_powered = true + M(pos):set_string("infotext", S("TA2 Power Generator")) + swap_node(pos, "techage:ta2_generator_on") + nvm.ticks = 0 + local outdir = M(pos):get_int("outdir") + nvm.axle.curr_power = techage.power.needed_power(pos, Cable, outdir) +end + +local function on_nopower(pos) + local nvm = techage.get_nvm(pos) + nvm.consumer_powered = false + if (nvm.ticks or 0) < 4 then + M(pos):set_string("infotext", S("TA2 Power Generator: Overload fault?\n(restart with right-click)")) + end + nvm.ticks = 0 +end + +local function node_timer(pos, elapsed) + local nvm = techage.get_nvm(pos) + nvm.axle = nvm.axle or {} + + -- trigger network on consumer side + nvm.ticks = (nvm.ticks or 0) + 1 + if nvm.ticks % 2 then + power.consumer_alive(pos, Axle, CYCLE_TIME) + end + + -- handle generator side delayed + if nvm.ticks > 3 then + local outdir = M(pos):get_int("outdir") + + if nvm.consumer_powered and not nvm.running_as_generator then + nvm.running_as_generator = true + power.generator_start(pos, Cable, CYCLE_TIME, outdir, nvm.max_power) + elseif not nvm.consumer_powered and nvm.running_as_generator then + nvm.running_as_generator = false + power.generator_stop(pos, Cable, outdir) + end + + if nvm.running_as_generator then + nvm.axle.curr_power = power.generator_alive(pos, Cable, CYCLE_TIME, outdir, PWR_PERF) + 1 + else + swap_node(pos, "techage:ta2_generator_off") + end + end + return true +end + +local function tubelib2_on_update2(pos, outdir, tlib2, node) + local nvm = techage.get_nvm(pos) + nvm.axle = nvm.axle or {} + nvm.axle.curr_power = 1 + power.update_network(pos, outdir, tlib2) +end + +minetest.register_node("techage:ta2_generator_off", { + description = S("TA2 Power Generator"), + tiles = { + -- up, down, right, left, back, front + "techage_filling_ta2.png^techage_frame_ta2_top.png^techage_appl_arrow.png", + "techage_filling_ta2.png^techage_frame_ta2.png", + "techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_hole_electric.png", + "techage_filling_ta2.png^techage_axle_clutch.png^techage_frame_ta2.png", + "techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_generator_red.png", + "techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_generator_red.png^[transformFX]", + }, + paramtype2 = "facedir", + groups = {cracky=2, crumbly=2, choppy=2}, + on_rotate = screwdriver.disallow, + is_ground_content = false, + + after_place_node = function(pos) + local nvm = techage.get_nvm(pos) + nvm.axle = nvm.axle or {} + nvm.axle.curr_power = 1 + nvm.consumer_powered = false + nvm.running_as_generator = false + M(pos):set_int("outdir", networks.side_to_outdir(pos, "R")) + M(pos):set_int("leftdir", networks.side_to_outdir(pos, "L")) + Cable:after_place_node(pos) + Axle:after_place_node(pos) + minetest.get_node_timer(pos):start(CYCLE_TIME) + power.consumer_start(pos, Axle, CYCLE_TIME*2) + M(pos):set_string("infotext", S("TA2 Power Generator")) + end, + + on_rightclick = function(pos, node, clicker) + local nvm = techage.get_nvm(pos) + nvm.axle = nvm.axle or {} + nvm.axle.curr_power = 1 + M(pos):set_string("infotext", S("TA2 Power Generator")) + end, + + after_dig_node = function(pos, oldnode) + Cable:after_dig_node(pos) + Axle:after_dig_node(pos) + techage.del_mem(pos) + end, + + tubelib2_on_update2 = tubelib2_on_update2, + on_timer = node_timer, + networks = { + ele1 = { + sides = {R = 1}, + ntype = "gen1", + nominal = PWR_PERF, + }, + axle = { + sides = {L = 1}, + ntype = "con1", + on_power = on_power, + on_nopower = on_nopower, + }, + } +}) + +minetest.register_node("techage:ta2_generator_on", { + description = S("TA2 Power Generator"), + tiles = { + -- up, down, right, left, back, front + "techage_filling_ta2.png^techage_frame_ta2_top.png^techage_appl_arrow.png", + "techage_filling_ta2.png^techage_frame_ta2.png", + "techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_hole_electric.png", + { + image = "techage_filling4_ta2.png^techage_axle_clutch4.png^techage_frame4_ta2.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 0.6, + }, + }, + { + image = "techage_filling4_ta2.png^techage_appl_generator_red4.png^techage_frame4_ta2.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 0.3, + }, + }, + { + image = "techage_filling4_ta2.png^techage_appl_generator_red4.png^[transformFX]^techage_frame4_ta2.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 0.3, + }, + }, + }, + paramtype2 = "facedir", + on_rotate = screwdriver.disallow, + is_ground_content = false, + drop = "", + groups = {not_in_creative_inventory=1}, + diggable = false, + + tubelib2_on_update2 = tubelib2_on_update2, + on_timer = node_timer, + networks = { + ele1 = { + sides = {R = 1}, + ntype = "gen1", + nominal = PWR_PERF, + }, + axle = { + sides = {L = 1}, + ntype = "con1", + on_power = on_power, + on_nopower = on_nopower, + }, + } +}) + +techage.register_node({"techage:ta2_generator_off", "techage:ta2_generator_on"}, { + on_node_load = function(pos, node) + minetest.get_node_timer(pos):start(CYCLE_TIME) + end, +}) + +Cable:add_secondary_node_names({"techage:ta2_generator_off", "techage:ta2_generator_on"}) +Axle:add_secondary_node_names({"techage:ta2_generator_off", "techage:ta2_generator_on"}) + +minetest.register_craft({ + output = "techage:ta2_generator_off", + recipe = { + {"basic_materials:steel_bar", "dye:red", "default:wood"}, + {'techage:axle', 'basic_materials:gear_steel', 'techage:electric_cableS'}, + {"default:wood", "techage:iron_ingot", "basic_materials:steel_bar"}, + }, +}) + diff --git a/techage/ta3_power/power2axle.lua b/techage/ta3_power/power2axle.lua new file mode 100644 index 0000000..3e37294 --- /dev/null +++ b/techage/ta3_power/power2axle.lua @@ -0,0 +1,245 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019-2020 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA3 Electric Motor + +]]-- + +-- for lazy programmers +local M = minetest.get_meta +local S = techage.S +local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end +local S2P = minetest.string_to_pos + +local Cable = techage.ElectricCable +local Axle = techage.Axle +local power = techage.power +local networks = techage.networks + +local CYCLE_TIME = 2 +local PWR_PERF = 40 + +-- Axles texture animation +local function switch_axles(pos, on) + for _,outdir in ipairs(networks.get_node_connections(pos, "axle")) do + Axle:switch_tube_line(pos, outdir, on and "on" or "off") + end +end + +local function swap_node(pos, name) + local node = techage.get_node_lvm(pos) + if node.name == name then + return + end + node.name = name + minetest.swap_node(pos, node) +end + +local function on_power(pos) + local nvm = techage.get_nvm(pos) + nvm.ele1 = nvm.ele1 or {} + nvm.consumer_powered = true + M(pos):set_string("infotext", S("TA3 Electric Motor")) + swap_node(pos, "techage:ta3_motor_on") + nvm.ticks = 0 + local outdir = M(pos):get_int("outdir") + nvm.ele1.curr_power = techage.power.needed_power(pos, Axle, outdir) +end + +local function on_nopower(pos) + local nvm = techage.get_nvm(pos) + nvm.consumer_powered = false + if (nvm.ticks or 0) < 4 then + M(pos):set_string("infotext", S("TA3 Electric Motor: Overload fault?\n(restart with right-click)")) + end + nvm.ticks = 0 +end + +local function node_timer(pos, elapsed) + local nvm = techage.get_nvm(pos) + nvm.ele1 = nvm.ele1 or {} + + -- trigger network on consumer side + nvm.ticks = (nvm.ticks or 0) + 1 + if nvm.ticks % 2 then + power.consumer_alive(pos, Cable, CYCLE_TIME) + end + + -- handle generator side delayed + if nvm.ticks > 3 then + local outdir = M(pos):get_int("outdir") + + if nvm.consumer_powered and not nvm.running_as_generator then + nvm.running_as_generator = true + power.generator_start(pos, Axle, CYCLE_TIME, outdir, nvm.max_power) + switch_axles(pos, true) + elseif not nvm.consumer_powered and nvm.running_as_generator then + nvm.running_as_generator = false + power.generator_stop(pos, Axle, outdir) + switch_axles(pos, false) + end + + if nvm.running_as_generator then + nvm.ele1.curr_power = power.generator_alive(pos, Axle, CYCLE_TIME, outdir, PWR_PERF) + 1 + else + swap_node(pos, "techage:ta3_motor_off") + end + end + return true +end + +local function tubelib2_on_update2(pos, outdir, tlib2, node) + local nvm = techage.get_nvm(pos) + nvm.ele1 = nvm.ele1 or {} + nvm.ele1.curr_power = 1 + power.update_network(pos, outdir, tlib2) +end + +minetest.register_node("techage:ta3_motor_off", { + description = S("TA3 Electric Motor"), + tiles = { + -- up, down, right, left, back, front + "techage_filling_ta3.png^techage_frame_ta3_top.png^techage_appl_arrow.png", + "techage_filling_ta3.png^techage_frame_ta3.png", + "techage_filling_ta3.png^techage_axle_clutch.png^techage_frame_ta3.png", + "techage_filling_ta3.png^techage_appl_hole_electric.png^techage_frame_ta3.png", + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_generator_red.png^[transformFX]", + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_generator_red.png", + }, + paramtype2 = "facedir", + groups = {cracky=2, crumbly=2, choppy=2}, + on_rotate = screwdriver.disallow, + is_ground_content = false, + + after_place_node = function(pos) + local nvm = techage.get_nvm(pos) + nvm.ele1 = nvm.ele1 or {} + nvm.ele1.curr_power = 1 + nvm.consumer_powered = false + nvm.running_as_generator = false + M(pos):set_int("outdir", networks.side_to_outdir(pos, "R")) + M(pos):set_int("leftdir", networks.side_to_outdir(pos, "L")) + Cable:after_place_node(pos) + Axle:after_place_node(pos) + minetest.get_node_timer(pos):start(CYCLE_TIME) + power.consumer_start(pos, Cable, CYCLE_TIME*2) + M(pos):set_string("infotext", S("TA3 Electric Motor")) + end, + + on_rightclick = function(pos, node, clicker) + local nvm = techage.get_nvm(pos) + nvm.ele1 = nvm.ele1 or {} + nvm.ele1.curr_power = 1 + M(pos):set_string("infotext", S("TA3 Electric Motor")) + end, + + after_dig_node = function(pos, oldnode) + Cable:after_dig_node(pos) + Axle:after_dig_node(pos) + techage.del_mem(pos) + end, + + tubelib2_on_update2 = tubelib2_on_update2, + on_timer = node_timer, + networks = { + axle = { + sides = {R = 1}, + ntype = "gen1", + nominal = PWR_PERF, + }, + ele1 = { + sides = {L = 1}, + ntype = "con1", + on_power = on_power, + on_nopower = on_nopower, + }, + } +}) + +minetest.register_node("techage:ta3_motor_on", { + description = S("TA3 Electric Motor"), + tiles = { + -- up, down, right, left, back, front + "techage_filling_ta3.png^techage_frame_ta3_top.png^techage_appl_arrow.png", + "techage_filling_ta3.png^techage_frame_ta3.png", + { + image = "techage_filling4_ta3.png^techage_axle_clutch4.png^techage_frame4_ta3.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 0.6, + }, + }, + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_hole_electric.png", + { + image = "techage_filling4_ta3.png^techage_appl_generator_red4.png^[transformFX]^techage_frame4_ta3.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 0.3, + }, + }, + { + image = "techage_filling4_ta3.png^techage_appl_generator_red4.png^techage_frame4_ta3.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 0.3, + }, + }, + }, + paramtype2 = "facedir", + on_rotate = screwdriver.disallow, + is_ground_content = false, + drop = "", + groups = {not_in_creative_inventory=1}, + diggable = false, + + tubelib2_on_update2 = tubelib2_on_update2, + on_timer = node_timer, + networks = { + axle = { + sides = {R = 1}, + ntype = "gen1", + nominal = PWR_PERF, + }, + ele1 = { + sides = {L = 1}, + ntype = "con1", + on_power = on_power, + on_nopower = on_nopower, + }, + } +}) + +techage.register_node({"techage:ta3_motor_off", "techage:ta3_motor_on"}, { + on_node_load = function(pos, node) + minetest.get_node_timer(pos):start(CYCLE_TIME) + end, +}) + +Cable:add_secondary_node_names({"techage:ta3_motor_off", "techage:ta3_motor_on"}) +Axle:add_secondary_node_names({"techage:ta3_motor_off", "techage:ta3_motor_on"}) + +minetest.register_craft({ + output = "techage:ta3_motor_off", + recipe = { + {"basic_materials:steel_bar", "dye:red", "default:wood"}, + {'techage:electric_cableS', 'basic_materials:gear_steel', 'techage:axle'}, + {"default:wood", "techage:iron_ingot", "basic_materials:steel_bar"}, + }, +}) + diff --git a/techage/ta3_power/tiny_generator.lua b/techage/ta3_power/tiny_generator.lua index ffd3ff0..3d27862 100644 --- a/techage/ta3_power/tiny_generator.lua +++ b/techage/ta3_power/tiny_generator.lua @@ -39,7 +39,7 @@ local function formspec(self, pos, nvm) "image[1.4,1.6;1,1;techage_form_arrow_bg.png^[transformR270]".. "image_button[1.4,3.2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]".. "tooltip[1.5,3;1,1;"..self:get_state_tooltip(nvm).."]".. - power.formspec_label_bar(2.5, 0.8, S("Electricity"), PWR_CAPA, nvm.provided) + power.formspec_label_bar(pos, 2.5, 0.8, S("Electricity"), PWR_CAPA, nvm.provided) end local function play_sound(pos) diff --git a/techage/textures/techage_appl_generator_red.png b/techage/textures/techage_appl_generator_red.png new file mode 100644 index 0000000000000000000000000000000000000000..427c45100bf6ed7ba72717dd05442cd5a8c707c4 GIT binary patch literal 2673 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 g{6Ojtr050z1u2>E@rr5c8vp 1 then - if player_name then - techage.mark_region(player_name, pos1, pos2, "") - minetest.chat_send_player(player_name, S("[TA4 Wind Turbine]").. - " "..S("The wind turbines are too close together!")) - end - M(pos):set_string("infotext", S("TA4 Wind Turbine").." "..S("Error")) - nvm.error = true - return - end - - -- Check for water surface (occean) - pos1 = {x=pos.x-20, y=0, z=pos.z-20} - pos2 = {x=pos.x+20, y=1, z=pos.z+20} - local num = #minetest.find_nodes_in_area(pos1, pos2, {"default:water_source", "default:water_flowing", "ignore"}) - if num < (41*41*2-MAX_NUM_FOREIGN_NODES) then - if player_name then - techage.mark_region(player_name, pos1, pos2, "") - minetest.chat_send_player(player_name, S("[TA4 Wind Turbine]").. - " "..S("More water expected (2 m deep)!")) - end - M(pos):set_string("infotext", S("TA4 Wind Turbine").." "..S("Error")) - nvm.error = true - return - end - - if pos.y < 12 or pos.y > 20 then - if player_name then - pos1 = {x=pos.x-13, y=12, z=pos.z-13} - pos2 = {x=pos.x+13, y=20, z=pos.z+13} - techage.mark_region(player_name, pos1, pos2, "") - minetest.chat_send_player(player_name, S("[TA4 Wind Turbine]").. - " "..S("No wind at this altitude!")) - end - M(pos):set_string("infotext", S("TA4 Wind Turbine").." "..S("Error")) + if not techage.valid_place_for_windturbine(pos, nil, 1) then nvm.error = true + M(pos):set_string("infotext", S("TA4 Wind Turbine")..": "..S("Not suitable position!")) return end diff --git a/tubelib2/tube_api.lua b/tubelib2/tube_api.lua index 8a78ba9..5c3d690 100644 --- a/tubelib2/tube_api.lua +++ b/tubelib2/tube_api.lua @@ -58,7 +58,7 @@ function tubelib2.get_node_lvm(pos) local data = vm:get_data() local param2_data = vm:get_param2_data() local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge}) - local idx = area:index(pos.x, pos.y, pos.z) + local idx = area:indexp(pos) node = { name = minetest.get_name_from_content_id(data[idx]), param2 = param2_data[idx]