From 553cedb06ba147b25383a77543f179470752b606 Mon Sep 17 00:00:00 2001 From: Joachim Stolberg Date: Sun, 13 Sep 2020 13:24:06 +0200 Subject: [PATCH] built on 13/09/2020 13:24:06 --- minecart/README.md | 3 +- minecart/depends.txt | 1 + minecart/init.lua | 3 +- minecart/lib.lua | 39 ++----- minecart/mods_support.lua | 131 ++++++++++++++++++++++ signs_bot/cmd_flowers.lua | 15 +-- signs_bot/interpreter.lua | 5 +- signs_bot/techage.lua | 5 +- techage/README.md | 15 +++ techage/basic_machines/consumer.lua | 1 + techage/basic_machines/distributor.lua | 11 +- techage/basic_machines/legacy_nodes.lua | 10 +- techage/basic_machines/mods_support.lua | 117 +++++++++++++++++++ techage/basic_machines/quarry.lua | 61 +++++----- techage/basis/assemble.lua | 2 +- techage/basis/fake_player.lua | 118 +++++++++++++++++++ techage/basis/firebox_lib.lua | 31 +++++ techage/basis/lib.lua | 39 ++++++- techage/basis/liquid_lib.lua | 4 + techage/basis/tubes.lua | 4 +- techage/basis/tubes_ta4.lua | 4 +- techage/coal_power_station/firebox.lua | 43 +++---- techage/coal_power_station/oilfirebox.lua | 47 ++++---- techage/digtron/battery.lua | 16 +-- techage/doc/manual_DE.lua | 11 +- techage/doc/manual_EN.lua | 17 ++- techage/icta_controller/battery.lua | 124 ++++++++++---------- techage/init.lua | 4 +- techage/items/hydrogen.lua | 1 + techage/items/lye.lua | 1 + techage/items/oil.lua | 2 +- techage/items/petroleum.lua | 5 + techage/lamps/growlight.lua | 15 +-- techage/liquids/node_api.lua | 11 ++ techage/liquids/pump.lua | 2 +- techage/liquids/silo.lua | 16 ++- techage/liquids/tank.lua | 12 ++ techage/locale/techage.de.tr | 4 +- techage/locale/template.txt | 3 +- techage/lua_controller/controller.lua | 14 ++- techage/lua_controller/sensorchest.lua | 19 +++- techage/manuals/manual_ta4_DE.md | 14 ++- techage/manuals/manual_ta4_EN.md | 19 +++- techage/manuals/ta4_lua_controller_EN.md | 3 +- techage/manuals/ta4_lua_controller_EN.pdf | Bin 352544 -> 353274 bytes techage/power/power_terminal2.lua | 2 +- techage/ta3_power/akkubox.lua | 17 +-- towercrane/control.lua | 2 +- 48 files changed, 775 insertions(+), 268 deletions(-) create mode 100644 minecart/mods_support.lua create mode 100644 techage/basic_machines/mods_support.lua create mode 100644 techage/basis/fake_player.lua diff --git a/minecart/README.md b/minecart/README.md index 800c0e0..b2f440b 100644 --- a/minecart/README.md +++ b/minecart/README.md @@ -116,4 +116,5 @@ History 2020-06-14 v1.06 API changed and chat command added 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 + diff --git a/minecart/depends.txt b/minecart/depends.txt index a8e9b3e..923877d 100644 --- a/minecart/depends.txt +++ b/minecart/depends.txt @@ -1,3 +1,4 @@ default carts +screwdriver doc? diff --git a/minecart/init.lua b/minecart/init.lua index a7f7ac4..94a36c2 100644 --- a/minecart/init.lua +++ b/minecart/init.lua @@ -13,7 +13,7 @@ minecart = {} -- Version for compatibility checks, see readme.md/history -minecart.version = 1.08 +minecart.version = 1.09 minecart.hopper_enabled = minetest.settings:get_bool("minecart_hopper_enabled") ~= false @@ -31,6 +31,7 @@ dofile(MP.."/protection.lua") if minecart.hopper_enabled then dofile(MP.."/hopper.lua") + dofile(MP.."/mods_support.lua") end dofile(MP.."/doc.lua") minetest.log("info", "[MOD] Minecart loaded") diff --git a/minecart/lib.lua b/minecart/lib.lua index da67ccc..d261e57 100644 --- a/minecart/lib.lua +++ b/minecart/lib.lua @@ -147,6 +147,8 @@ function minecart.take_items(pos, param2, num) if def and inv and def.take_listname and (not def.allow_take or def.allow_take(npos, nil, owner)) then return minecart.inv_take_items(inv, def.take_listname, num) + elseif def and def.take_item then + return def.take_item(npos, num, owner) else local ndef = minetest.registered_nodes[node.name] if ndef and ndef.minecart_hopper_takeitem then @@ -166,6 +168,8 @@ function minecart.put_items(pos, param2, stack) if leftover:get_count() > 0 then return leftover end + elseif def and def.put_item then + return def.put_item(npos, stack, owner) elseif is_air_like(node.name) or check_cart_for_loading(npos) then minetest.add_item(npos, stack) else @@ -191,8 +195,10 @@ function minecart.untake_items(pos, param2, stack) local def = RegisteredInventories[node.name] local inv = minetest.get_inventory({type="node", pos=npos}) - if def then - return inv and inv:add_item(def.put_listname, stack) + if def and inv and def.put_listname then + return inv:add_item(def.put_listname, stack) + elseif def and def.untake_item then + return def.untake_item(npos, stack) else local ndef = minetest.registered_nodes[node.name] if ndef and ndef.minecart_hopper_untakeitem then @@ -230,6 +236,9 @@ function minecart.register_inventory(node_names, def) put_listname = def.put and def.put.listname, allow_take = def.take and def.take.allow_inventory_take, take_listname = def.take and def.take.listname, + put_item = def.put and def.put.put_item, + take_item = def.take and def.take.take_item, + untake_item = def.take and def.take.untake_item, } end end @@ -272,32 +281,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) return false end) -minecart.register_inventory({"default:chest", "default:chest_open"}, { - put = { - listname = "main", - }, - take = { - listname = "main", - }, -}) - -minecart.register_inventory({"default:chest_locked", "default:chest_locked_open"}, { - put = { - allow_inventory_put = function(pos, stack, player_name) - local owner = M(pos):get_string("owner") - return owner == player_name - end, - listname = "main", - }, - take = { - allow_inventory_take = function(pos, stack, player_name) - local owner = M(pos):get_string("owner") - return owner == player_name - end, - listname = "main", - }, -}) - minecart.register_inventory({"minecart:hopper"}, { put = { allow_inventory_put = function(pos, stack, player_name) diff --git a/minecart/mods_support.lua b/minecart/mods_support.lua new file mode 100644 index 0000000..14aaaa7 --- /dev/null +++ b/minecart/mods_support.lua @@ -0,0 +1,131 @@ +--[[ + + Minecart + ======== + + Copyright (C) 2019-2020 Joachim Stolberg + + MIT + See license.txt for more information + + Wrapper functions to get hopper support for other mods + +]]-- + +-- for lazy programmers +local M = minetest.get_meta + +local CacheForFuelNodeNames = {} + +local function is_fuel(stack) + local name = stack:get_name() + if CacheForFuelNodeNames[name] then + return true + end + if minetest.get_craft_result({method="fuel", width=1, items={stack}}).time ~= 0 then + CacheForFuelNodeNames[name] = true + end + return CacheForFuelNodeNames[name] +end + +------------------------------------------------------------------------------ +-- default +------------------------------------------------------------------------------ + +minecart.register_inventory({"default:chest", "default:chest_open"}, { + put = { + listname = "main", + }, + take = { + listname = "main", + }, +}) + +minecart.register_inventory({"default:chest_locked", "default:chest_locked_open"}, { + put = { + allow_inventory_put = function(pos, stack, player_name) + local owner = M(pos):get_string("owner") + return owner == player_name + end, + listname = "main", + }, + take = { + allow_inventory_take = function(pos, stack, player_name) + local owner = M(pos):get_string("owner") + return owner == player_name + end, + listname = "main", + }, +}) + +minecart.register_inventory({"default:furnace", "default:furnace_active"}, { + put = { + -- distinguish between fuel and other items + put_item = function(pos, stack, player_name) + local inv = minetest.get_inventory({type="node", pos=pos}) + local listname = is_fuel(stack) and "fuel" or "src" + local leftover = inv:add_item(listname, stack) + minetest.get_node_timer(pos):start(1.0) + if leftover:get_count() > 0 then + return leftover + end + end, + }, + take = { + -- fuel can't be taken + listname = "dst", + }, +}) + +------------------------------------------------------------------------------ +-- digtron +------------------------------------------------------------------------------ + +minecart.register_inventory({"digtron:inventory"}, { + put = { + listname = "main", + }, + take = { + listname = "main", + }, +}) + +minecart.register_inventory({"digtron:fuelstore"}, { + put = { + listname = "fuel", + }, + take = { + listname = "fuel", + }, +}) + +minecart.register_inventory({"digtron:combined_storage"}, { + put = { + -- distinguish between fuel and other items + put_item = function(pos, stack, player_name) + local inv = minetest.get_inventory({type="node", pos=pos}) + local listname = is_fuel(stack) and "fuel" or "main" + local leftover = inv:add_item(listname, stack) + if leftover:get_count() > 0 then + return leftover + end + end, + }, + take = { + -- fuel can't be taken + listname = "main", + }, +}) + +------------------------------------------------------------------------------ +-- protector +------------------------------------------------------------------------------ + +minecart.register_inventory({"protector:chest"}, { + put = { + listname = "main", + }, + take = { + listname = "main", + }, +}) diff --git a/signs_bot/cmd_flowers.lua b/signs_bot/cmd_flowers.lua index e8003b6..3823311 100644 --- a/signs_bot/cmd_flowers.lua +++ b/signs_bot/cmd_flowers.lua @@ -32,18 +32,11 @@ function signs_bot.register_flower(name) end minetest.after(1, function() - for name,_ in pairs(minetest.registered_decorations) do - if type(name) == "string" then + for _,def in pairs(minetest.registered_decorations) do + local name = def.decoration + if name and type(name) == "string" then local mod = string.split(name, ":")[1] - if mod == "flowers" then - signs_bot.register_flower(name) - end - end - end - for name,ndef in pairs(minetest.registered_nodes) do - if type(name) == "string" then - local mod = string.split(name, ":")[1] - if mod == "flowers" then + if mod == "flowers" or mod == "bakedclay" then -- Bakedclay also registers flowers as decoration. signs_bot.register_flower(name) end end diff --git a/signs_bot/interpreter.lua b/signs_bot/interpreter.lua index 233afe6..bfd4c5a 100644 --- a/signs_bot/interpreter.lua +++ b/signs_bot/interpreter.lua @@ -147,12 +147,13 @@ end register_command("repeat", 1, function(base_pos, mem, cnt) - mem.Stack[#mem.Stack + 1] = cnt + mem.Stack[#mem.Stack + 1] = tonumber(cnt) mem.Stack[#mem.Stack + 1] = mem.pc + 1 return api.DONE end, function(cnt) - return cnt and cnt > 0 and cnt < 1000 + cnt = tonumber(cnt) or 0 + return cnt > 0 and cnt < 1000 end ) diff --git a/signs_bot/techage.lua b/signs_bot/techage.lua index 6aa7ee6..779f505 100644 --- a/signs_bot/techage.lua +++ b/signs_bot/techage.lua @@ -9,7 +9,8 @@ if minetest.get_modpath("techage") then local Cable = techage.ElectricCable local power = techage.power - signs_bot.register_inventory({"techage:chest_ta2", "techage:chest_ta3", "techage:chest_ta4"}, { + signs_bot.register_inventory({"techage:chest_ta2", "techage:chest_ta3", "techage:chest_ta4", + "techage:ta3_silo", "techage:ta4_silo"}, { allow_inventory_put = function(pos, stack, player_name) return not minetest.is_protected(pos, player_name) end, @@ -61,7 +62,7 @@ if minetest.get_modpath("techage") then and minetest.registered_nodes[node.name].on_ignite then minetest.registered_nodes[node.name].on_ignite(pos) end - return true + return signs_bot.DONE end, }) diff --git a/techage/README.md b/techage/README.md index 6bbdd8e..c99e3af 100644 --- a/techage/README.md +++ b/techage/README.md @@ -77,6 +77,21 @@ Available worlds will be converted to 'lsqlite3', but there is no way back, so: ### History +**2020-09-13 V0.23** +- Pull request #26: Digtron Battery: Fix duplication bug (from Thomas-S) +- Improve ta4 sensor box +- Firebox: Add check for free space when placing the node +- Lua controller: Add 'get_gametime' function +- Pull request #27: Liquid Tanks: Add protection support (from Thomas-S) +- Fix pump issue (silo source items can disappear) +- Pull request #28: Quarry: Improve digging behaviour (from Thomas-S) +- Pull request #28: Battery: Store battery load as metadata (from Thomas-S) +- Pull request #29: Distributor: Keep item metadata (from Thomas-S) + +**2020-08-08 V0.22** +- Pull request #25: Growlight: Improve flower registration (from Thomas-S) +- Add tube support for digtron chests and protector:chest + **2020-08-08 V0.21** - Pull request #18: Add a simple Digtron battery (from Thomas-S) - Pull request #23: Lua Controller: Fix $item_description() documentation and translation (from Thomas-S) diff --git a/techage/basic_machines/consumer.lua b/techage/basic_machines/consumer.lua index e7f1c95..e28937e 100644 --- a/techage/basic_machines/consumer.lua +++ b/techage/basic_machines/consumer.lua @@ -233,6 +233,7 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState on_rightclick = tNode.on_rightclick, after_place_node = after_place_node, after_dig_node = after_dig_node, + preserve_metadata = tNode.preserve_metadata, tubelib2_on_update2 = tubelib2_on_update2, allow_metadata_inventory_put = tNode.allow_metadata_inventory_put, allow_metadata_inventory_move = tNode.allow_metadata_inventory_move, diff --git a/techage/basic_machines/distributor.lua b/techage/basic_machines/distributor.lua index e4f9e27..ef06421 100644 --- a/techage/basic_machines/distributor.lua +++ b/techage/basic_machines/distributor.lua @@ -215,7 +215,7 @@ local function tubelib2_on_update2(pos, outdir, tlib2, node) end end -local function push_item(pos, filter, item_name, num_items, nvm) +local function push_item(pos, filter, itemstack, num_items, nvm) local idx = 1 local num_pushed = 0 local num_ports = #filter @@ -226,7 +226,7 @@ local function push_item(pos, filter, item_name, num_items, nvm) num_of_trials = num_of_trials + 1 local push_dir = filter[randidx[idx]] local num_to_push = math.min(amount, num_items - num_pushed) - if techage.push_items(pos, push_dir, ItemStack(item_name.." "..num_to_push)) then + if techage.push_items(pos, push_dir, itemstack:peek_item(num_to_push)) then num_pushed = num_pushed + num_to_push nvm.port_counter[push_dir] = (nvm.port_counter[push_dir] or 0) + num_to_push end @@ -255,18 +255,19 @@ local function distributing(pos, inv, crd, nvm) local item_name = stack:get_name() local num_items = stack:get_count() local num_to_push = math.min((nvm.num_items or crd.num_items) - sum_num_pushed, num_items) + local stack_to_push = stack:peek_item(num_to_push) num_pushed = 0 if item_filter[item_name] then -- Push items based on filter - num_pushed = push_item(pos, item_filter[item_name], item_name, num_to_push, nvm) + num_pushed = push_item(pos, item_filter[item_name], stack_to_push, num_to_push, nvm) elseif blocking_mode and #open_ports > 0 then -- Push items based on open ports - num_pushed = push_item(pos, open_ports, item_name, num_to_push, nvm) + num_pushed = push_item(pos, open_ports, stack_to_push, num_to_push, nvm) end if not blocking_mode and num_pushed == 0 and #open_ports > 0 then -- Push items based on open ports - num_pushed = push_item(pos, open_ports, item_name, num_to_push, nvm) + num_pushed = push_item(pos, open_ports, stack_to_push, num_to_push, nvm) end sum_num_pushed = sum_num_pushed + num_pushed diff --git a/techage/basic_machines/legacy_nodes.lua b/techage/basic_machines/legacy_nodes.lua index c2e3aa9..a949afd 100644 --- a/techage/basic_machines/legacy_nodes.lua +++ b/techage/basic_machines/legacy_nodes.lua @@ -1,16 +1,14 @@ --[[ - Tube Library - ============ + TechAge + ======= - Copyright (C) 2017 Joachim Stolberg + Copyright (C) 2019-2020 Joachim Stolberg GPL v3 See LICENSE.txt for more information - - legacy_nodes.lua: - Tubelib support for chests and furnace + Tube support for default chests and furnace ]]-- diff --git a/techage/basic_machines/mods_support.lua b/techage/basic_machines/mods_support.lua new file mode 100644 index 0000000..ede4e25 --- /dev/null +++ b/techage/basic_machines/mods_support.lua @@ -0,0 +1,117 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019-2020 Joachim Stolberg + + GPL v3 + See LICENSE.txt for more information + + Tube support for digtron and protector chests + +]]-- + + +-- for lazy programmers +local M = minetest.get_meta + +local CacheForFuelNodeNames = {} + +local function is_fuel(stack) + local name = stack:get_name() + if CacheForFuelNodeNames[name] then + return true + end + if minetest.get_craft_result({method="fuel", width=1, items={stack}}).time ~= 0 then + CacheForFuelNodeNames[name] = true + end + return CacheForFuelNodeNames[name] +end + +------------------------------------------------------------------------------ +-- digtron +------------------------------------------------------------------------------ + +techage.register_node({"digtron:inventory"}, { + on_pull_item = function(pos, in_dir, num) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return techage.get_items(pos, inv, "main", num) + end, + on_push_item = function(pos, in_dir, stack) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return techage.put_items(inv, "main", stack) + end, + on_unpull_item = function(pos, in_dir, stack) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return techage.put_items(inv, "main", stack) + end, +}) + +techage.register_node({"digtron:fuelstore"}, { + on_pull_item = function(pos, in_dir, num) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return techage.get_items(pos, inv, "fuel", num) + end, + on_push_item = function(pos, in_dir, stack) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return techage.put_items(inv, "fuel", stack) + end, + on_unpull_item = function(pos, in_dir, stack) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return techage.put_items(inv, "fuel", stack) + end, +}) + +techage.register_node({"digtron:combined_storage"}, { + on_pull_item = function(pos, in_dir, num) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return techage.get_items(pos, inv, "main", num) + end, + on_push_item = function(pos, side, stack) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + minetest.get_node_timer(pos):start(1.0) + if is_fuel(stack) then + return techage.put_items(inv, "fuel", stack) + else + return techage.put_items(inv, "main", stack) + end + end, + on_unpull_item = function(pos, side, stack) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return techage.put_items(inv, "main", stack) + end, +}) + +------------------------------------------------------------------------------ +-- protector +------------------------------------------------------------------------------ + +techage.register_node({"protector:chest"}, { + on_pull_item = function(pos, in_dir, num) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return techage.get_items(pos, inv, "main", num) + end, + on_push_item = function(pos, in_dir, stack) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return techage.put_items(inv, "main", stack) + end, + on_unpull_item = function(pos, in_dir, stack) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return techage.put_items(inv, "main", stack) + end, +}) + + diff --git a/techage/basic_machines/quarry.lua b/techage/basic_machines/quarry.lua index c7e6df1..ab938c7 100644 --- a/techage/basic_machines/quarry.lua +++ b/techage/basic_machines/quarry.lua @@ -157,23 +157,6 @@ local function mark_area(pos1, pos2, owner) pos1.y = pos1.y - 0.2 end -local function peek_node(qpos) - local node = techage.get_node_lvm(qpos) - local ndef = minetest.registered_nodes[node.name] - if techage.can_node_dig(node, ndef) then - return techage.dropped_node(node, ndef) - end -end - -local function add_to_inv(pos, item_name) - local inv = M(pos):get_inventory() - if inv:room_for_item("main", item_name) then - inv:add_item("main", item_name) - return true - end - return false -end - local function quarry_task(pos, crd, nvm) nvm.start_level = nvm.start_level or 0 nvm.quarry_depth = nvm.quarry_depth or 1 @@ -182,6 +165,30 @@ local function quarry_task(pos, crd, nvm) local y_last = y_first - nvm.quarry_depth + 1 local facedir = minetest.get_node(pos).param2 local owner = M(pos):get_string("owner") + local fake_player = techage.Fake_player:new() + fake_player.get_pos = function (...) + return pos + end + fake_player.get_inventory = function(...) + return M(pos):get_inventory() + end + + local add_to_inv = function(itemstacks) + local at_least_one_added = false + local inv = M(pos):get_inventory() + if #itemstacks == 0 then + return true + end + for _,stack in ipairs(itemstacks) do + if inv:room_for_item("main", stack) then + inv:add_item("main", stack) + at_least_one_added = true + elseif at_least_one_added then + minetest.add_item({x=pos.x,y=pos.y+1,z=pos.z}, stack) + end + end + return at_least_one_added + end local pos1, pos2 = get_corner_positions(pos, facedir, nvm.hole_diameter) nvm.level = 1 @@ -203,14 +210,13 @@ local function quarry_task(pos, crd, nvm) for zoffs = 1, nvm.hole_diameter do for xoffs = 1, nvm.hole_diameter do local qpos = get_quarry_pos(pos1, xoffs, zoffs) - local item_name = peek_node(qpos) - if item_name then - if add_to_inv(pos, item_name) then - minetest.remove_node(qpos) - crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS) - else - crd.State:blocked(pos, nvm, S("inventory full")) - end + local dig_state = techage.dig_like_player(qpos, fake_player, add_to_inv) + + if dig_state == techage.dig_states.INV_FULL then + crd.State:blocked(pos, nvm, S("inventory full")) + coroutine.yield() + elseif dig_state == techage.dig_states.DUG then + crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS) coroutine.yield() end end @@ -229,7 +235,10 @@ local function keep_running(pos, elapsed) local nvm = techage.get_nvm(pos) local crd = CRD(pos) - coroutine.resume(mem.co, pos, crd, nvm) + local _, err = coroutine.resume(mem.co, pos, crd, nvm) + if err then + minetest.log("error", "[TA4 Quarry Coroutine Error]" .. err) + end if techage.is_activeformspec(pos) then M(pos):set_string("formspec", formspec(crd.State, pos, nvm)) diff --git a/techage/basis/assemble.lua b/techage/basis/assemble.lua index 8a39207..45e09b4 100644 --- a/techage/basis/assemble.lua +++ b/techage/basis/assemble.lua @@ -81,7 +81,7 @@ local function check_space(pos, param2, AssemblyPlan, player_name) local node = techage.get_node_lvm(pos1) local ndef = minetest.registered_nodes[node.name] - if not ndef or ndef.walkable and node.name ~= node_name then + if not ndef or not ndef.buildable_to and node.name ~= node_name then minetest.chat_send_player(player_name, S("[TA] Not enough space!")) return false end diff --git a/techage/basis/fake_player.lua b/techage/basis/fake_player.lua new file mode 100644 index 0000000..e4a6f26 --- /dev/null +++ b/techage/basis/fake_player.lua @@ -0,0 +1,118 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019-2020 Joachim Stolberg + Copyright (C) 2020 Thomas S. + + GPL v3 + See LICENSE.txt for more information + + Fake Player + +]]-- + +-- Map method names to their return values +local methods = { + get_pos = { x = 0, y = 0, z = 0 }, + set_pos = nil, + moveto = nil, + punch = nil, + right_click = nil, + get_hp = 20, + set_hp = nil, + get_inventory = nil, + get_wield_list = "", + get_wield_index = 0, + get_wielded_item = ItemStack(), + set_wielded_item = true, + set_armor_groups = nil, + get_armor_groups = {}, + set_animation = nil, + get_animation = {}, + set_animation_frame_speed = nil, + set_attach = nil, + get_attach = nil, + set_detach = nil, + get_bone_position = {}, + set_properties = nil, + get_properties = {}, + is_player = false, + get_nametag_attributes = {}, + set_nametag_attributes = nil, + get_player_name = "", + get_player_velocity = nil, + add_player_velocity = nil, + get_look_dir = vector.new(0, 0, 1), + get_look_vertical = 0, + get_look_horizontal = 0, + set_look_vertical = nil, + set_look_horizontal = nil, + get_look_pitch = 0, + get_look_yaw = 0, + set_look_pitch = nil, + set_look_yaw = nil, + get_breath = 10, + set_breath = nil, + set_fov = nil, + get_fov = 0, + set_attribute = nil, + get_attribute = nil, + get_meta = nil, + set_inventory_formspec = nil, + get_inventory_formspec = "", + set_formspec_prepend = nil, + get_formspec_prepend = "", + get_player_control = {}, + get_player_control_bits = 0, + set_physics_override = nil, + get_physics_override = {}, + hud_add = 0, + hud_remove = nil, + hud_change = nil, + hud_get = {}, + hud_set_flags = nil, + hud_get_flags = {}, + hud_set_hotbar_itemcount = nil, + hud_get_hotbar_itemcount = 8, + hud_set_hotbar_image = nil, + hud_get_hotbar_image = "", + hud_set_hotbar_selected_image = nil, + hud_get_hotbar_selected_image = "", + set_sky = nil, + get_sky = {}, + get_sky_color = {}, + set_sun = nil, + get_sun = {}, + set_moon = nil, + get_moon = {}, + set_stars = nil, + get_stars = {}, + set_clouds = nil, + get_clouds = {}, + override_day_night_ratio = nil, + get_day_night_ratio = nil, + set_local_animation = nil, + get_local_animation = {}, + set_eye_offset = nil, + get_eye_offset = {}, + send_mapblock = nil, +} + +techage.Fake_player = {} +techage.Fake_player.__index = techage.Fake_player + +function techage.Fake_player:new() + local fake_player = {} + setmetatable(fake_player, techage.Fake_player) + return fake_player +end + + +for method_name, return_value in pairs(methods) do + techage.Fake_player[method_name] = function(self, ...) + return return_value + end +end + diff --git a/techage/basis/firebox_lib.lua b/techage/basis/firebox_lib.lua index a465807..294d2e6 100644 --- a/techage/basis/firebox_lib.lua +++ b/techage/basis/firebox_lib.lua @@ -118,3 +118,34 @@ function techage.firebox.has_fuel(pos) local items = inv:get_stack("fuel", 1) return items:get_count() > 0 end + +function techage.firebox.is_free_position(pos, player_name) + local pos2 = techage.get_pos(pos, 'F') + if minetest.is_protected(pos2, player_name) then + minetest.chat_send_player(player_name, S("[TA] Area is protected!")) + return false + end + local node = techage.get_node_lvm(pos2) + local ndef = minetest.registered_nodes[node.name] + if not ndef or not ndef.buildable_to then + minetest.chat_send_player(player_name, S("[TA] Not enough space!")) + return false + end + return true +end + +function techage.firebox.set_firehole(pos, on) + local param2 = techage.get_node_lvm(pos).param2 + local pos2 = techage.get_pos(pos, 'F') + if on == true then + minetest.swap_node(pos2, {name="techage:coalfirehole_on", param2 = param2}) + elseif on == false then + minetest.swap_node(pos2, {name="techage:coalfirehole", param2 = param2}) + else + local node = techage.get_node_lvm(pos2) + if node.name == "techage:coalfirehole" or node.name == "techage:coalfirehole_on" then + minetest.swap_node(pos2, {name="air"}) + end + end +end + diff --git a/techage/basis/lib.lua b/techage/basis/lib.lua index 4f50747..9d954c4 100644 --- a/techage/basis/lib.lua +++ b/techage/basis/lib.lua @@ -140,7 +140,44 @@ function techage.can_node_dig(node, ndef) -- add it to the white list RegisteredNodesToBeDug[node.name] = true return true -end +end + +techage.dig_states = { + NOT_DIGGABLE = 1, + INV_FULL = 2, + DUG = 3 +} + +-- Digs a node like a player would by utilizing a fake player object. +-- add_to_inv(itemstacks) is a method that should try to add the dropped stacks to an appropriate inventory. +-- The node will only be dug, if add_to_inv(itemstacks) returns true. +function techage.dig_like_player(pos, fake_player, add_to_inv) + local node = techage.get_node_lvm(pos) + local ndef = minetest.registered_nodes[node.name] + if not ndef or ndef.diggable == false or (ndef.can_dig and not ndef.can_dig(pos, fake_player)) then + return techage.dig_states.NOT_DIGGABLE + end + local drop_as_strings = minetest.get_node_drops(node) + local drop_as_stacks = {} + for _,itemstring in ipairs(drop_as_strings) do + drop_as_stacks[#drop_as_stacks+1] = ItemStack(itemstring) + end + local meta = M(pos) + if ndef.preserve_metadata then + ndef.preserve_metadata(pos, node, meta, drop_as_stacks) + end + + if add_to_inv(drop_as_stacks) then + local oldmeta = meta:to_table() + minetest.remove_node(pos) + + if ndef.after_dig_node then + ndef.after_dig_node(pos, node, oldmeta, fake_player) + end + return techage.dig_states.DUG + end + return techage.dig_states.INV_FULL +end local function handle_drop(drop) -- To keep it simple, return only the item with the lowest rarity diff --git a/techage/basis/liquid_lib.lua b/techage/basis/liquid_lib.lua index 1300857..6801070 100644 --- a/techage/basis/liquid_lib.lua +++ b/techage/basis/liquid_lib.lua @@ -203,6 +203,10 @@ 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 + return + end + local nvm = techage.get_nvm(pos) local mem = techage.get_mem(pos) mem.blocking_time = mem.blocking_time or 0 diff --git a/techage/basis/tubes.lua b/techage/basis/tubes.lua index d3848ff..a31ef48 100644 --- a/techage/basis/tubes.lua +++ b/techage/basis/tubes.lua @@ -90,7 +90,7 @@ minetest.register_node("techage:tubeS", { paramtype = "light", sunlight_propagates = true, is_ground_content = false, - groups = {choppy=2, cracky=3, stone=1}, + groups = {choppy=2, cracky=3}, sounds = default.node_sound_wood_defaults(), }) @@ -130,7 +130,7 @@ minetest.register_node("techage:tubeA", { paramtype = "light", sunlight_propagates = true, is_ground_content = false, - groups = {choppy=2, cracky=3, stone=1, not_in_creative_inventory=1}, + groups = {choppy=2, cracky=3, not_in_creative_inventory=1}, sounds = default.node_sound_wood_defaults(), drop = "techage:tubeS", }) diff --git a/techage/basis/tubes_ta4.lua b/techage/basis/tubes_ta4.lua index 14bb6f0..0178c8f 100644 --- a/techage/basis/tubes_ta4.lua +++ b/techage/basis/tubes_ta4.lua @@ -57,7 +57,7 @@ minetest.register_node("techage:ta4_tubeS", { paramtype = "light", sunlight_propagates = true, is_ground_content = false, - groups = {choppy=2, cracky=3, stone=1}, + groups = {choppy=2, cracky=3}, sounds = default.node_sound_wood_defaults(), }) @@ -97,7 +97,7 @@ minetest.register_node("techage:ta4_tubeA", { paramtype = "light", sunlight_propagates = true, is_ground_content = false, - groups = {choppy=2, cracky=3, stone=1, not_in_creative_inventory=1}, + groups = {choppy=2, cracky=3, not_in_creative_inventory=1}, sounds = default.node_sound_wood_defaults(), drop = "techage:ta4_tubeS", }) diff --git a/techage/coal_power_station/firebox.lua b/techage/coal_power_station/firebox.lua index 70547ac..467c05e 100644 --- a/techage/coal_power_station/firebox.lua +++ b/techage/coal_power_station/firebox.lua @@ -22,18 +22,6 @@ local firebox = techage.firebox local CYCLE_TIME = 2 local BURN_CYCLE_FACTOR = 0.5 -local function firehole(pos, on) - local param2 = techage.get_node_lvm(pos).param2 - local pos2 = techage.get_pos(pos, 'F') - if on == true then - minetest.swap_node(pos2, {name="techage:coalfirehole_on", param2 = param2}) - elseif on == false then - minetest.swap_node(pos2, {name="techage:coalfirehole", param2 = param2}) - else - minetest.swap_node(pos2, {name="air"}) - end -end - local function node_timer(pos, elapsed) local nvm = techage.get_nvm(pos) local power = techage.transfer( @@ -52,7 +40,7 @@ local function node_timer(pos, elapsed) nvm.burn_cycles_total = nvm.burn_cycles else nvm.running = false - firehole(pos, false) + firebox.set_firehole(pos, false) M(pos):set_string("formspec", firebox.formspec(nvm)) return false end @@ -67,7 +55,7 @@ local function start_firebox(pos, nvm) if not nvm.running then nvm.running = true node_timer(pos, 0) - firehole(pos, true) + firebox.set_firehole(pos, true) minetest.get_node_timer(pos):start(CYCLE_TIME) end end @@ -96,20 +84,25 @@ minetest.register_node("techage:coalfirebox", { allow_metadata_inventory_take = firebox.allow_metadata_inventory_take, on_rightclick = firebox.on_rightclick, - on_construct = function(pos) - techage.add_node(pos, "techage:coalfirebox") - local nvm = techage.get_nvm(pos) - nvm.running = false - nvm.burn_cycles = 0 - local meta = M(pos) - meta:set_string("formspec", firebox.formspec(nvm)) - local inv = meta:get_inventory() - inv:set_size('fuel', 1) - firehole(pos, false) + after_place_node = function(pos, placer) + if firebox.is_free_position(pos, placer:get_player_name()) then + techage.add_node(pos, "techage:coalfirebox") + local nvm = techage.get_nvm(pos) + nvm.running = false + nvm.burn_cycles = 0 + local meta = M(pos) + meta:set_string("formspec", firebox.formspec(nvm)) + local inv = meta:get_inventory() + inv:set_size('fuel', 1) + firebox.set_firehole(pos, false) + else + minetest.remove_node(pos) + return true + end end, on_destruct = function(pos) - firehole(pos, nil) + firebox.set_firehole(pos, nil) end, on_metadata_inventory_put = function(pos, listname, index, stack, player) diff --git a/techage/coal_power_station/oilfirebox.lua b/techage/coal_power_station/oilfirebox.lua index 6c45912..7de649b 100644 --- a/techage/coal_power_station/oilfirebox.lua +++ b/techage/coal_power_station/oilfirebox.lua @@ -25,18 +25,6 @@ local liquid = techage.liquid local CYCLE_TIME = 2 local BURN_CYCLE_FACTOR = 0.5 -local function firehole(pos, on) - local param2 = techage.get_node_lvm(pos).param2 - local pos2 = techage.get_pos(pos, 'F') - if on == true then - minetest.swap_node(pos2, {name="techage:coalfirehole_on", param2 = param2}) - elseif on == false then - minetest.swap_node(pos2, {name="techage:coalfirehole", param2 = param2}) - else - minetest.swap_node(pos2, {name="air"}) - end -end - local function node_timer(pos, elapsed) local nvm = techage.get_nvm(pos) local power = techage.transfer( @@ -55,7 +43,7 @@ local function node_timer(pos, elapsed) nvm.burn_cycles_total = nvm.burn_cycles else nvm.running = false - firehole(pos, false) + firebox.set_firehole(pos, false) M(pos):set_string("formspec", fuel.formspec(nvm)) return false end @@ -70,7 +58,7 @@ local function start_firebox(pos, nvm) if not nvm.running and fuel.has_fuel(nvm) then nvm.running = true node_timer(pos, 0) - firehole(pos, true) + firebox.set_firehole(pos, true) minetest.get_node_timer(pos):start(CYCLE_TIME) end end @@ -98,21 +86,26 @@ minetest.register_node("techage:oilfirebox", { on_rightclick = fuel.on_rightclick, on_receive_fields = fuel.on_receive_fields, - on_construct = function(pos) - techage.add_node(pos, "techage:oilfirebox") - local nvm = techage.get_nvm(pos) - nvm.running = false - nvm.burn_cycles = 0 - nvm.liquid = {} - nvm.liquid.amount = 0 - local meta = M(pos) - meta:set_string("formspec", fuel.formspec(nvm)) - local inv = meta:get_inventory() - firehole(pos, false) + after_place_node = function(pos, placer) + if firebox.is_free_position(pos, placer:get_player_name()) then + techage.add_node(pos, "techage:oilfirebox") + local nvm = techage.get_nvm(pos) + nvm.running = false + nvm.burn_cycles = 0 + nvm.liquid = {} + nvm.liquid.amount = 0 + local meta = M(pos) + meta:set_string("formspec", fuel.formspec(nvm)) + local inv = meta:get_inventory() + firebox.set_firehole(pos, false) + else + minetest.remove_node(pos) + return true + end end, - + on_destruct = function(pos) - firehole(pos, nil) + firebox.set_firehole(pos, nil) end, on_punch = function(pos, node, puncher, pointed_thing) diff --git a/techage/digtron/battery.lua b/techage/digtron/battery.lua index ba09deb..4763f5e 100644 --- a/techage/digtron/battery.lua +++ b/techage/digtron/battery.lua @@ -140,27 +140,21 @@ techage.register_consumer("digtron_battery", S("Digtron Battery"), { act = tiles end end end, - after_dig_node = function(pos, oldnode, oldmetadata, digger) - local node = ItemStack(oldnode.name) - if oldmetadata.inventory then - local total = count_coal(oldmetadata) - local meta = node:get_meta() + preserve_metadata = function(pos, oldnode, oldmetadata, drops) + local metadata = M(pos):to_table() + if metadata.inventory then + local total = count_coal(metadata) + local meta = drops[1]:get_meta() meta:set_int("coal", total) local text = S("Digtron Battery").." ("..math.floor(total/TOTAL_MAX * 100).." %)" meta:set_string("description", text) end - local inv = minetest.get_inventory({type="player", name=digger:get_player_name()}) - local left_over = inv:add_item("main", node) - if left_over:get_count() > 0 then - minetest.add_item(pos, node) - end end, on_rightclick = function(pos, node, clicker) techage.set_activeformspec(pos, clicker) local nvm = techage.get_nvm(pos) M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm)) end, - drop = "", node_timer = keep_running, on_receive_fields = on_receive_fields, allow_metadata_inventory_put = allow_metadata_inventory_put, diff --git a/techage/doc/manual_DE.lua b/techage/doc/manual_DE.lua index 016c02f..6039266 100644 --- a/techage/doc/manual_DE.lua +++ b/techage/doc/manual_DE.lua @@ -1340,7 +1340,16 @@ techage.manual_DE.aText = { "\n".. "\n".. "\n", - "Die TA4 Sensor Kiste dient zum Aufbau von Automatischen Lagern oder Verkaufsautomaten. Sie hat erweitere Kommandos zur Fernsteuerung.\n".. + "Die TA4 Sensor Kiste dient zum Aufbau von Automatischen Lagern oder Verkaufsautomaten in Verbindung mit dem Lua Controller.\n".. + "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 '$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".. "\n".. "\n".. "\n", diff --git a/techage/doc/manual_EN.lua b/techage/doc/manual_EN.lua index 81533c6..3473f67 100644 --- a/techage/doc/manual_EN.lua +++ b/techage/doc/manual_EN.lua @@ -1331,7 +1331,16 @@ techage.manual_EN.aText = { "\n".. "\n".. "\n", - "The TA4 sensor box is used to set up automatic warehouses or vending machines. It has additional commands for remote control.\n".. + "The TA4 sensor box is used to set up automatic warehouses or vending machines in conjunction with the Lua controller.\n".. + "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".. + " - 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".. "\n".. "\n".. "\n", @@ -1417,8 +1426,8 @@ techage.manual_EN.aText = { "\n".. "The TA4 pusher has two additional commands for the Lua controller:\n".. "\n".. - " - 'config' is used to configure the pusher\\, analogous to manual configuration via the menu.\nExample: '$ send_cmnd(1234\\, \"config\"\\, \"default: dirt\")'\n".. - " - 'pull' is used to send an order to the pusher:\nExample: '$ send_cmnd(1234\\, \"pull\"\\, \"default: dirt 8\")'\nValues ​​from 1 to 12 are permitted as numbers. Then the pusher goes back to 'stopped' mode and sends an\" off \"command back to the transmitter of the\" pull \"command.\n".. + " - 'config' is used to configure the pusher\\, analogous to manual configuration via the menu.\nExample: '$send_cmnd(1234\\, \"config\"\\, \"default: dirt\")'\n".. + " - 'pull' is used to send an order to the pusher:\nExample: '$send_cmnd(1234\\, \"pull\"\\, \"default: dirt 8\")'\nValues ​​from 1 to 12 are permitted as numbers. Then the pusher goes back to 'stopped' mode and sends an\" off \"command back to the transmitter of the\" pull \"command.\n".. "\n".. "\n".. "\n", @@ -1449,7 +1458,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: '$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".. "\n".. "\n".. "\n", diff --git a/techage/icta_controller/battery.lua b/techage/icta_controller/battery.lua index fa59f1d..7d3f262 100644 --- a/techage/icta_controller/battery.lua +++ b/techage/icta_controller/battery.lua @@ -15,7 +15,6 @@ -- for lazy programmers local M = minetest.get_meta local S = techage.S -local logic = techage.logic local BATTERY_CAPACITY = 10000000 local function calc_percent(content) @@ -36,73 +35,69 @@ local function on_timer(pos, elapsed) return true end -local function register_battery(ext, percent, nici) - minetest.register_node("techage:ta4_battery"..ext, { - description = S("Battery").." "..ext, - inventory_image = 'techage_battery_inventory.png', - wield_image = 'techage_battery_inventory.png', - tiles = { - -- up, down, right, left, back, front - "techage_smartline.png", - "techage_smartline.png", - "techage_smartline.png", - "techage_smartline.png", - "techage_smartline.png", - "techage_smartline.png^techage_battery_green.png", - }, +minetest.register_alias("techage:ta4_battery75", "techage:ta4_battery") +minetest.register_alias("techage:ta4_battery50", "techage:ta4_battery") +minetest.register_alias("techage:ta4_battery25", "techage:ta4_battery") - drawtype = "nodebox", - node_box = { - type = "fixed", - fixed = { - { -6/32, -6/32, 14/32, 6/32, 6/32, 16/32}, - }, +minetest.register_node("techage:ta4_battery", { + description = S("Battery"), + inventory_image = 'techage_battery_inventory.png', + wield_image = 'techage_battery_inventory.png', + tiles = { + -- up, down, right, left, back, front + "techage_smartline.png", + "techage_smartline.png", + "techage_smartline.png", + "techage_smartline.png", + "techage_smartline.png", + "techage_smartline.png^techage_battery_green.png", + }, + + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + { -6/32, -6/32, 14/32, 6/32, 6/32, 16/32}, }, - - after_place_node = function(pos, placer) - local meta = minetest.get_meta(pos) - meta:set_int("content", BATTERY_CAPACITY * percent) - local node = minetest.get_node(pos) - node.name = "techage:ta4_battery" - minetest.swap_node(pos, node) - on_timer(pos, 1) - minetest.get_node_timer(pos):start(30) - end, - - on_timer = on_timer, - - after_dig_node = function(pos, oldnode, oldmetadata, digger) - local percent = calc_percent(tonumber(oldmetadata.fields.content)) - local stack - if percent > 95 then - stack = ItemStack("techage:ta4_battery") - elseif percent > 75 then - stack = ItemStack("techage:ta4_battery75") - elseif percent > 50 then - stack = ItemStack("techage:ta4_battery50") - elseif percent > 25 then - stack = ItemStack("techage:ta4_battery25") - else - return + }, + + after_place_node = function(pos, placer, itemstack) + local content = BATTERY_CAPACITY + if itemstack then + local stack_meta = itemstack:get_meta() + if stack_meta then + -- This ensures that dug batteries of the old system are considered full. + local string_content = stack_meta:get_string("content") + if string_content ~= "" then + -- Batteries dug in the new system are handled correctly. + content = techage.in_range(stack_meta:get_int("content"), 0, BATTERY_CAPACITY) + end end - local inv = minetest.get_inventory({type="player", name=digger:get_player_name()}) - inv:add_item("main", stack) - end, + end + M(pos):set_int("content", content) + on_timer(pos, 1) + minetest.get_node_timer(pos):start(30) + end, - paramtype = "light", - sunlight_propagates = true, - paramtype2 = "facedir", - groups = {choppy=1, cracky=1, crumbly=1, not_in_creative_inventory=nici}, - drop = "", - is_ground_content = false, - sounds = default.node_sound_stone_defaults(), - }) -end + on_timer = on_timer, -register_battery("", 1.0, 0) -register_battery("75", 0.75, 1) -register_battery("50", 0.5, 1) -register_battery("25", 0.25, 1) + preserve_metadata = function(pos, oldnode, oldmetadata, drops) + local content = M(pos):get_int("content") + + local meta = drops[1]:get_meta() + meta:set_int("content", content) + local percent = calc_percent(content) + local text = S("Digtron Battery").." ("..percent.." %)" + meta:set_string("description", text) + end, + + paramtype = "light", + sunlight_propagates = true, + paramtype2 = "facedir", + groups = {choppy=1, cracky=1, crumbly=1}, + is_ground_content = false, + sounds = default.node_sound_stone_defaults(), +}) minetest.register_node("techage:ta4_battery_empty", { description = S("Battery"), @@ -159,8 +154,7 @@ else }) end -techage.register_node({"techage:ta4_battery", "techage:ta4_battery25", - "techage:ta4_battery50", "techage:ta4_battery75"}, +techage.register_node({"techage:ta4_battery"}, { on_node_load = function(pos) minetest.get_node_timer(pos):start(30) diff --git a/techage/init.lua b/techage/init.lua index ef8b2a1..f87a45e 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.21 +techage.version = 0.23 if minetest.global_exists("tubelib") then minetest.log("error", "[techage] Techage can't be used together with the mod tubelib!") @@ -66,6 +66,7 @@ end -- Basis features local MP = minetest.get_modpath("techage") dofile(MP.."/basis/lib.lua") -- helper functions +dofile(MP.."/basis/fake_player.lua") -- dummy player object dofile(MP.."/basis/node_store.lua") dofile(MP.."/basis/gravel_lib.lua") -- ore probability dofile(MP.."/basis/node_states.lua") -- state model @@ -144,6 +145,7 @@ dofile(MP.."/basic_machines/consumer.lua") -- consumer base model dofile(MP.."/basic_machines/source.lua") dofile(MP.."/basic_machines/pusher.lua") dofile(MP.."/basic_machines/legacy_nodes.lua") +dofile(MP.."/basic_machines/mods_support.lua") dofile(MP.."/basic_machines/grinder.lua") dofile(MP.."/basic_machines/distributor.lua") dofile(MP.."/basic_machines/gravelsieve.lua") diff --git a/techage/items/hydrogen.lua b/techage/items/hydrogen.lua index c64c4a6..160d61a 100644 --- a/techage/items/hydrogen.lua +++ b/techage/items/hydrogen.lua @@ -17,6 +17,7 @@ local S = techage.S minetest.register_craftitem("techage:hydrogen", { description = S("TA4 Hydrogen"), inventory_image = "techage_hydrogen_inv.png", + groups = {ta_liquid = 1}, }) minetest.register_craftitem("techage:cylinder_small_hydrogen", { diff --git a/techage/items/lye.lua b/techage/items/lye.lua index 50f2922..ec401ca 100644 --- a/techage/items/lye.lua +++ b/techage/items/lye.lua @@ -17,6 +17,7 @@ local S = techage.S minetest.register_craftitem("techage:lye", { description = S("Lye"), inventory_image = "techage_liquid2_inv.png^[colorize:#7fd44c:120^techage_liquid1_inv.png", + groups = {ta_liquid = 1}, }) minetest.register_craftitem("techage:barrel_lye", { diff --git a/techage/items/oil.lua b/techage/items/oil.lua index a36ff1a..1db905f 100644 --- a/techage/items/oil.lua +++ b/techage/items/oil.lua @@ -58,7 +58,7 @@ minetest.register_node("techage:oil_source", { liquid_range = 10, liquid_renewable = false, post_effect_color = {a = 200, r = 1, g = 1, b = 1}, - groups = {liquid = 5}, + groups = {liquid = 5, ta_liquid = 1}, }) minetest.register_node("techage:oil_flowing", { diff --git a/techage/items/petroleum.lua b/techage/items/petroleum.lua index 463bd78..2cb38a4 100644 --- a/techage/items/petroleum.lua +++ b/techage/items/petroleum.lua @@ -18,26 +18,31 @@ local S = techage.S minetest.register_craftitem("techage:bitumen", { description = S("TA3 Bitumen"), inventory_image = "techage_liquid2_inv.png^[colorize:#000000", + groups = {ta_liquid = 1}, }) minetest.register_craftitem("techage:fueloil", { description = S("TA3 Fuel Oil"), inventory_image = "techage_liquid2_inv.png^[colorize:#7E5D0A:180^techage_liquid1_inv.png", + groups = {ta_liquid = 1}, }) minetest.register_craftitem("techage:naphtha", { description = S("TA3 Naphtha"), inventory_image = "techage_liquid2_inv.png^[colorize:#AAA820:180^techage_liquid1_inv.png", + groups = {ta_liquid = 1}, }) minetest.register_craftitem("techage:gasoline", { description = S("TA3 Gasoline"), inventory_image = "techage_liquid2_inv.png^[colorize:#EEFC52:180^techage_liquid1_inv.png", + groups = {ta_liquid = 1}, }) minetest.register_craftitem("techage:gas", { description = S("TA3 Propane"), inventory_image = "techage_gas_inv.png", + groups = {ta_liquid = 1}, }) minetest.register_craftitem("techage:ta3_cylinder_small_gas", { diff --git a/techage/lamps/growlight.lua b/techage/lamps/growlight.lua index 8d35369..6938f99 100644 --- a/techage/lamps/growlight.lua +++ b/techage/lamps/growlight.lua @@ -138,10 +138,11 @@ function techage.register_plant(name) end minetest.after(1, function() - for name,_ in pairs(minetest.registered_decorations) do - if type(name) == "string" then + for _,def in pairs(minetest.registered_decorations) do + local name = def.decoration + if name and type(name) == "string" then local mod = string.split(name, ":")[1] - if mod == "flowers" then + if mod == "flowers" or mod == "bakedclay" then -- Bakedclay also registers flowers as decoration. techage.register_flower(name) end end @@ -149,12 +150,8 @@ minetest.after(1, function() for name,ndef in pairs(minetest.registered_nodes) do if type(name) == "string" then local mod = string.split(name, ":")[1] - if mod == "farming" then - if ndef.on_timer then -- probably a plant that still needs to grow - techage.register_plant(name) - end - elseif mod == "flowers" then - techage.register_flower(name) + if mod == "farming" and ndef.on_timer then -- probably a plant that still needs to grow + techage.register_plant(name) end end end diff --git a/techage/liquids/node_api.lua b/techage/liquids/node_api.lua index 1c4eb1c..7a6484c 100644 --- a/techage/liquids/node_api.lua +++ b/techage/liquids/node_api.lua @@ -162,6 +162,17 @@ function liquid.take(pos, outdir, name, amount, player_name) return taken, item_name end +function liquid.untake(pos, outdir, name, amount, player_name) + for _,item in ipairs(get_network_table(pos, outdir, "tank")) do + local liquid = LQD(item.pos) + if liquid and liquid.untake then + amount = liquid.untake(item.pos, item.indir, name, amount) + if not amount or amount == 0 then break end + end + end + return amount or 0 +end + -- -- Server local functions -- diff --git a/techage/liquids/pump.lua b/techage/liquids/pump.lua index e8081b7..a01c36e 100644 --- a/techage/liquids/pump.lua +++ b/techage/liquids/pump.lua @@ -70,7 +70,7 @@ local function pumping(pos, nvm, state, capa) if taken > 0 then local leftover = liquid.put(pos, outdir, name, taken, starter) if leftover and leftover == taken then - liquid.put(pos, Flip[outdir], name, leftover) + liquid.untake(pos, Flip[outdir], name, leftover) state:blocked(pos, nvm) return end diff --git a/techage/liquids/silo.lua b/techage/liquids/silo.lua index 7087050..617bbfe 100644 --- a/techage/liquids/silo.lua +++ b/techage/liquids/silo.lua @@ -26,9 +26,10 @@ local function allow_metadata_inventory_put(pos, listname, index, stack, player) if minetest.is_protected(pos, player:get_player_name()) then return 0 end - -- check if it is powder - local ndef = minetest.registered_craftitems[stack:get_name()] or {} - if ndef.groups and ndef.groups.powder == 1 then + -- check if it is powder or techage liquid item (migration function) + local ndef = minetest.registered_craftitems[stack:get_name()] or + minetest.registered_items[stack:get_name()] or {} + if ndef.groups and (ndef.groups.powder == 1 or ndef.groups.ta_liquid == 1) then local nvm = techage.get_nvm(pos) nvm.item_name = nil local inv = minetest.get_meta(pos):get_inventory() @@ -125,6 +126,15 @@ local tLiquid = { end return 0 end, + untake = function(pos, indir, name, amount) + local inv = M(pos):get_inventory() + local stack = ItemStack(name.." "..amount) + if inv:room_for_item("main", stack) then + inv:add_item("main", stack) + return 0 + end + return amount + end, } local tNetworks = { diff --git a/techage/liquids/tank.lua b/techage/liquids/tank.lua index 9663653..9144add 100644 --- a/techage/liquids/tank.lua +++ b/techage/liquids/tank.lua @@ -67,6 +67,15 @@ local function put_liquid(pos, indir, name, amount) return amount 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 networks_def = { pipe2 = { sides = techage.networks.AllSides, -- Pipe connection sides @@ -110,6 +119,7 @@ minetest.register_node("techage:ta3_tank", { peek = liquid.srv_peek, put = put_liquid, take = take_liquid, + untake = untake_liquid, }, networks = networks_def, on_rightclick = on_rightclick, @@ -168,6 +178,7 @@ minetest.register_node("techage:oiltank", { peek = liquid.srv_peek, put = put_liquid, take = take_liquid, + untake = untake_liquid, }, networks = networks_def, on_rightclick = on_rightclick, @@ -216,6 +227,7 @@ minetest.register_node("techage:ta4_tank", { peek = liquid.srv_peek, put = put_liquid, take = take_liquid, + untake = untake_liquid, }, networks = networks_def, on_rightclick = on_rightclick, diff --git a/techage/locale/techage.de.tr b/techage/locale/techage.de.tr index fce382b..21ae9dc 100644 --- a/techage/locale/techage.de.tr +++ b/techage/locale/techage.de.tr @@ -1,10 +1,10 @@ # textdomain: techage - ku is needed!)= ku wird benötigt!) #### 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 Aluminum=Aluminium Area already loaded or max. number of Forceload Blocks reached!=Bereich bereits geladen oder maximale Anzahl von Forceload Blöcken erreicht! @@ -429,6 +429,7 @@ 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 needs power=benötigt Strom @@ -453,3 +454,4 @@ water temperature=Wassertemperatur wrong catalyst=falscher Katalysator wrong storage diameter=Falscher Wärmespeicher-Durchmesser ##### not used anymore ##### + diff --git a/techage/locale/template.txt b/techage/locale/template.txt index a6aeb79..2d9530a 100644 --- a/techage/locale/template.txt +++ b/techage/locale/template.txt @@ -1,8 +1,8 @@ - ku is needed!)= #### 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= Aluminum= Area already loaded or max. number of Forceload Blocks reached!= @@ -427,6 +427,7 @@ inlet/pipe error= inventory full= item output blocked= keep assignment= +ku is needed= light= loaded= needs power= diff --git a/techage/lua_controller/controller.lua b/techage/lua_controller/controller.lua index c1f9b34..9673a3f 100644 --- a/techage/lua_controller/controller.lua +++ b/techage/lua_controller/controller.lua @@ -120,10 +120,18 @@ techage.lua_ctlr.register_function("get_ms_time", { cmnd = function(self) return math.floor(minetest.get_us_time() / 1000) end, - help = "$get_ms_time()\n".. + help = " ms = $get_ms_time()\n".. " returns time with millisecond precision." }) +techage.lua_ctlr.register_function("get_gametime", { + cmnd = function(self) + return minetest.get_gametime() + end, + help = " t = $get_gametime()\n".. + " returns the time, in seconds, since the world was created." +}) + techage.lua_ctlr.register_function("position", { cmnd = function(self, number) local info = techage.get_node_info(number) @@ -132,7 +140,7 @@ techage.lua_ctlr.register_function("position", { end return "(-,-,-)" end, - help = "$position(number)\n".. + help = " pos = $position(number)\n".. " returns the position '(x,y,z)' of the device\n with given number." }) @@ -144,7 +152,7 @@ techage.lua_ctlr.register_action("battery", { local val = (BATTERY_CAPA - math.min(batmeta:get_int("content") or 0, BATTERY_CAPA)) return 100 - math.floor((val * 100.0 / BATTERY_CAPA)) end, - help = " $battery()\n".. + help = " lvl = $battery()\n".. " Get charge level of battery connected to Controller.\n".. " Function returns percent number (0-100) where 100 means full.\n".. " example: battery_percent = $battery()" diff --git a/techage/lua_controller/sensorchest.lua b/techage/lua_controller/sensorchest.lua index aa04ddc..2a0858b 100644 --- a/techage/lua_controller/sensorchest.lua +++ b/techage/lua_controller/sensorchest.lua @@ -63,7 +63,7 @@ local function get_stacks(pos) end local function allow_metadata_inventory_put(pos, listname, index, stack, player) - if minetest.is_protected(pos, player:get_player_name()) then + if M(pos):get_string("public") ~= "true" and minetest.is_protected(pos, player:get_player_name()) then return 0 end store_action(pos, player, "put") @@ -72,7 +72,7 @@ local function allow_metadata_inventory_put(pos, listname, index, stack, player) end local function allow_metadata_inventory_take(pos, listname, index, stack, player) - if minetest.is_protected(pos, player:get_player_name()) then + if M(pos):get_string("public") ~= "true" and minetest.is_protected(pos, player:get_player_name()) then return 0 end store_action(pos, player, "take") @@ -93,12 +93,13 @@ local function after_dig_node(pos, oldnode, oldmetadata, digger) end local function formspec1() - return "size[6,4]".. + return "size[5.5,4]".. default.gui_bg.. default.gui_bg_img.. default.gui_slots.. "field[0.5,1;5,1;number;TA4 Lua Controller number:;]" .. - "button_exit[1.5,2.5;2,1;exit;Save]" + "checkbox[0.5,1.8;public;"..S("Allow public chest access")..";false]".. + "button_exit[1.7,2.8;2,1;exit;Save]" end local function formspec2(pos) @@ -147,7 +148,15 @@ minetest.register_node("techage:ta4_sensor_chest", { on_receive_fields = function(pos, formname, fields, player) local meta = M(pos) local nvm = techage.get_nvm(pos) - if fields.number and fields.number ~= "" then + + if meta:get_string("public") ~= "true" and minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + + if fields.public then + meta:set_string("public", fields.public) + end + if fields.quit == "true" and fields.number and fields.number ~= "" then local owner = meta:get_string("owner") if techage.check_numbers(fields.number, owner) then meta:set_string("number", fields.number) diff --git a/techage/manuals/manual_ta4_DE.md b/techage/manuals/manual_ta4_DE.md index 4807bbc..178c703 100644 --- a/techage/manuals/manual_ta4_DE.md +++ b/techage/manuals/manual_ta4_DE.md @@ -386,7 +386,17 @@ Der Server dient zur zentralen Speicherung von Daten von mehreren Lua Controller ### TA4 Sensor Kiste/Chest -Die TA4 Sensor Kiste dient zum Aufbau von Automatischen Lagern oder Verkaufsautomaten. Sie hat erweitere Kommandos zur Fernsteuerung. +Die TA4 Sensor Kiste dient zum Aufbau von Automatischen Lagern oder Verkaufsautomaten in Verbindung mit dem Lua Controller. +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 `$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. + [ta4_sensor_chest|image] @@ -602,4 +612,4 @@ Beim Weitergeben wird in der Zielmaschine pro Item nur eine Position im Inventar Die Verarbeitungsleistung beträgt bis zu 8 Items alle 3 Sekunden. -[ta4_injector|image] \ No newline at end of file +[ta4_injector|image] diff --git a/techage/manuals/manual_ta4_EN.md b/techage/manuals/manual_ta4_EN.md index 04acecd..665ca46 100644 --- a/techage/manuals/manual_ta4_EN.md +++ b/techage/manuals/manual_ta4_EN.md @@ -388,7 +388,16 @@ The server is used for the central storage of data from several Lua controllers. ### TA4 Sensor Box / Chest -The TA4 sensor box is used to set up automatic warehouses or vending machines. It has additional commands for remote control. +The TA4 sensor box is used to set up automatic warehouses or vending machines in conjunction with the Lua controller. +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 +- 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. [ta4_sensor_chest|image] @@ -513,9 +522,9 @@ The processing power is 12 items every 2 s, if TA4 tubes are used on both sides. The TA4 pusher has two additional commands for the Lua controller: - `config` is used to configure the pusher, analogous to manual configuration via the menu. - Example: `$ send_cmnd(1234, "config", "default: dirt")` + Example: `$send_cmnd(1234, "config", "default: dirt")` - `pull` is used to send an order to the pusher: - Example: `$ send_cmnd(1234, "pull", "default: dirt 8")` + Example: `$send_cmnd(1234, "pull", "default: dirt 8")` Values ​​from 1 to 12 are permitted as numbers. Then the pusher goes back to `stopped` mode and sends an" off "command back to the transmitter of the" pull "command. [ta4_pusher|image] @@ -552,8 +561,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: `$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) [ta4_8x2000_chest|image] diff --git a/techage/manuals/ta4_lua_controller_EN.md b/techage/manuals/ta4_lua_controller_EN.md index 297989c..0d21868 100644 --- a/techage/manuals/ta4_lua_controller_EN.md +++ b/techage/manuals/ta4_lua_controller_EN.md @@ -330,7 +330,8 @@ In addition to Lua standard function the Lua Controller provides the following f E.g.: `$print("Hello "..name)` - `$loopcycle(seconds)` - This function allows to change the call frequency of the controller loop() function, witch is per default one second. For more info, see "Cyclic Task" - `$events(bool)` - Enable/disable event handling. For more info, see "Events" -- `$get_ms_time()` - Returns time with millisecond precision +- `$get_ms_time()` - Returns the time with millisecond precision +- `get_gametime()` - Returns the time, in seconds, since the world was created - `$time_as_str()` - Read the time of day (ingame) as text string in 24h format, like "18:45" - `$time_as_num()` - Read the time of day (ingame) as integer number in 24h format, like 1845 - `$get_input(num)` - Read an input value provided by an external block with the given number _num_. The block has to be configured with the number of the controller to be able to send status messages (on/off commands) to the controller. _num_ is the number of the remote block, like "1234". diff --git a/techage/manuals/ta4_lua_controller_EN.pdf b/techage/manuals/ta4_lua_controller_EN.pdf index 1273eb1ab8af0b91b3b730b1093679cc2bd39326..eeb974ff2acff079c756f0f0c91f294bb04da710 100644 GIT binary patch delta 15913 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 delta 15142 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 (netw.available1 or 0) then - state = S("Probably too many consumers (")..needed..S(" ku is needed!)") + state = S("Probably too many consumers (")..needed.." "..S("ku is needed").."!)" elseif (netw.num_nodes or 0) < techage.networks.MAX_NUM_NODES then state = S("Number of power grid blocks")..": "..(netw.num_nodes or 0)..", "..S("Max. needed power")..": "..needed.. " ku" else diff --git a/techage/ta3_power/akkubox.lua b/techage/ta3_power/akkubox.lua index 84dfcae..53a60e6 100644 --- a/techage/ta3_power/akkubox.lua +++ b/techage/ta3_power/akkubox.lua @@ -120,19 +120,15 @@ local function get_capa(itemstack) return 0 end -local function set_capa(pos, oldnode, digger, capa) - local node = ItemStack(oldnode.name) - local meta = node:get_meta() +local function set_capa(pos, oldnode, oldmetadata, drops) + local nvm = techage.get_nvm(pos) + local capa = nvm.capa + local meta = drops[1]:get_meta() capa = techage.power.percent(PWR_CAPA, capa) capa = (math.floor((capa or 0) / 5)) * 5 meta:set_int("capa", capa) local text = S("TA3 Accu Box").." ("..capa.." %)" meta:set_string("description", text) - local inv = minetest.get_inventory({type="player", name=digger:get_player_name()}) - local left_over = inv:add_item("main", node) - if left_over:get_count() > 0 then - minetest.add_item(pos, node) - end end local function after_place_node(pos, placer, itemstack) @@ -149,9 +145,7 @@ local function after_place_node(pos, placer, itemstack) end local function after_dig_node(pos, oldnode, oldmetadata, digger) - local nvm = techage.get_nvm(pos) Cable:after_dig_node(pos) - set_capa(pos, oldnode, digger, nvm.capa) techage.del_mem(pos) end @@ -188,13 +182,12 @@ minetest.register_node("techage:ta3_akku", { after_dig_node = after_dig_node, tubelib2_on_update2 = tubelib2_on_update2, networks = net_def, - - drop = "", -- don't remove, item will be added via 'set_capa' paramtype2 = "facedir", groups = {cracky=2, crumbly=2, choppy=2}, on_rotate = screwdriver.disallow, is_ground_content = false, sounds = default.node_sound_wood_defaults(), + preserve_metadata = set_capa, }) Cable:add_secondary_node_names({"techage:ta3_akku"}) diff --git a/towercrane/control.lua b/towercrane/control.lua index e4b594c..1eebc25 100644 --- a/towercrane/control.lua +++ b/towercrane/control.lua @@ -281,8 +281,8 @@ minetest.register_node("towercrane:mast_ctrl_off", { -- switch the crane ON on_rightclick = function (pos, node, clicker) if is_my_crane(pos, clicker) and not is_operator(clicker) then - start_crane(pos, clicker) if set_operator_privs(clicker, pos) then + start_crane(pos, clicker) local pos1, pos2 = calc_construction_area(pos) -- control player every second minetest.after(1, control_player, pos, pos1, pos2, clicker:get_player_name())