mods that hopefully work for a TechAge-based pack
This commit is contained in:
@@ -0,0 +1,562 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2023 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
The autocrafter is derived from pipeworks:
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> WTFPL
|
||||
|
||||
TA2/TA3/TA4 Autocrafter
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S2P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
|
||||
local S = techage.S
|
||||
|
||||
local STANDBY_TICKS = 3
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 4
|
||||
|
||||
local UncraftableItems = {}
|
||||
|
||||
-- Add all nodes/items which should not be crafted with the autocrafter
|
||||
function techage.register_uncraftable_items(item_name)
|
||||
UncraftableItems[item_name] = true
|
||||
end
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
return "size[8,9.2]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;recipe;0,0;3,3;]"..
|
||||
"image[2.9,1;1,1;techage_form_arrow.png]"..
|
||||
"image[3.8,0;1,1;"..techage.get_power_image(pos, nvm).."]"..
|
||||
"list[context;output;3.8,1;1,1;]"..
|
||||
"image_button[3.8,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[3.8,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[context;src;0,3.2;8,2;]"..
|
||||
"list[context;dst;5,0;3,3;]"..
|
||||
"list[current_player;main;0,5.4;8,4;]" ..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]" ..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;dst]" ..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(0, 5.4)
|
||||
end
|
||||
|
||||
local function count_index(invlist)
|
||||
local index = {}
|
||||
for _, stack in pairs(invlist) do
|
||||
if not stack:is_empty() then
|
||||
local stack_name = stack:get_name()
|
||||
index[stack_name] = (index[stack_name] or 0) + stack:get_count()
|
||||
end
|
||||
end
|
||||
return index
|
||||
end
|
||||
|
||||
local function flush_input_inventory(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
if not inv:is_empty("src") then
|
||||
for idx = 1, 16 do
|
||||
local stack = inv:get_stack("src", idx)
|
||||
if not inv:room_for_item("dst", stack) then
|
||||
return false
|
||||
end
|
||||
inv:add_item("dst", stack)
|
||||
inv:set_stack("src", idx, nil)
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- caches some recipe data
|
||||
local autocrafterCache = {}
|
||||
|
||||
local function get_craft(pos, inventory, hash)
|
||||
hash = hash or minetest.hash_node_position(pos)
|
||||
local craft = autocrafterCache[hash]
|
||||
if not craft then
|
||||
local recipe = inventory:get_list("recipe")
|
||||
local output, decremented_input = minetest.get_craft_result(
|
||||
{method = "normal", width = 3, items = recipe})
|
||||
|
||||
-- check if registered item
|
||||
if UncraftableItems[output.item:get_name()] then
|
||||
output.item = ItemStack()
|
||||
end
|
||||
|
||||
craft = {recipe = recipe, consumption = count_index(recipe),
|
||||
output = output, decremented_input = decremented_input}
|
||||
autocrafterCache[hash] = craft
|
||||
end
|
||||
return craft
|
||||
end
|
||||
|
||||
local function autocraft(pos, crd, nvm, inv)
|
||||
local craft = get_craft(pos, inv)
|
||||
if not craft then
|
||||
crd.State:idle(pos, nvm)
|
||||
return
|
||||
end
|
||||
local output_item = craft.output.item
|
||||
if output_item:get_name() == "" then
|
||||
crd.State:idle(pos, nvm)
|
||||
return
|
||||
end
|
||||
|
||||
-- check if we have enough room in dst
|
||||
if not inv:room_for_item("dst", output_item) then
|
||||
crd.State:blocked(pos, nvm)
|
||||
return
|
||||
end
|
||||
local consumption = craft.consumption
|
||||
local inv_index = count_index(inv:get_list("src"))
|
||||
-- check if we have enough material available
|
||||
for itemname, number in pairs(consumption) do
|
||||
if (not inv_index[itemname]) or inv_index[itemname] < number then
|
||||
crd.State:idle(pos, nvm)
|
||||
return
|
||||
end
|
||||
end
|
||||
-- consume material
|
||||
for itemname, number in pairs(consumption) do
|
||||
for i = 1, number do -- We have to do that since remove_item does not work if count > stack_max
|
||||
inv:remove_item("src", ItemStack(itemname))
|
||||
end
|
||||
end
|
||||
|
||||
-- craft the result into the dst inventory and add any "replacements" as well
|
||||
inv:add_item("dst", output_item)
|
||||
for i = 1, 9 do
|
||||
inv:add_item("dst", craft.decremented_input.items[i])
|
||||
end
|
||||
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
end
|
||||
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
autocraft(pos, crd, nvm, inv)
|
||||
end
|
||||
|
||||
-- note, that this function assumes allready being updated to virtual items
|
||||
-- and doesn't handle recipes with stacksizes > 1
|
||||
local function after_recipe_change(pos, inventory)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
-- if we emptied the grid, there's no point in keeping it running or cached
|
||||
if inventory:is_empty("recipe") then
|
||||
autocrafterCache[minetest.hash_node_position(pos)] = nil
|
||||
inventory:set_stack("output", 1, "")
|
||||
crd.State:stop(pos, nvm)
|
||||
return
|
||||
end
|
||||
local recipe = inventory:get_list("recipe")
|
||||
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
local craft = autocrafterCache[hash]
|
||||
|
||||
if craft then
|
||||
-- check if it changed
|
||||
local cached_recipe = craft.recipe
|
||||
for i = 1, 9 do
|
||||
if recipe[i]:get_name() ~= cached_recipe[i]:get_name() then
|
||||
autocrafterCache[hash] = nil -- invalidate recipe
|
||||
craft = nil
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
craft = craft or get_craft(pos, inventory, hash)
|
||||
local output_item = craft.output.item
|
||||
inventory:set_stack("output", 1, output_item)
|
||||
crd.State:stop(pos, nvm)
|
||||
end
|
||||
|
||||
-- clean out unknown items and groups, which would be handled like unknown items in the crafting grid
|
||||
-- if minetest supports query by group one day, this might replace them
|
||||
-- with a canonical version instead
|
||||
local function normalize(item_list)
|
||||
for i = 1, #item_list do
|
||||
local name = item_list[i]
|
||||
if not minetest.registered_items[name] then
|
||||
item_list[i] = ""
|
||||
end
|
||||
end
|
||||
return item_list
|
||||
end
|
||||
|
||||
local function get_input_from_recipeblock(pos, number, idx)
|
||||
local own_num = M(pos):get_string("node_number")
|
||||
local owner = M(pos):get_string("owner")
|
||||
if techage.check_numbers(number, owner) then
|
||||
local input = techage.send_single(own_num, number, "input", idx)
|
||||
if input and type(input) == "string" then
|
||||
return input
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_output_change(pos, inventory, stack)
|
||||
if not stack then
|
||||
inventory:set_list("output", {})
|
||||
inventory:set_list("recipe", {})
|
||||
else
|
||||
local input = minetest.get_craft_recipe(stack:get_name())
|
||||
if not input.items or input.type ~= "normal" then return end
|
||||
local items, width = normalize(input.items), input.width
|
||||
local item_idx, width_idx = 1, 1
|
||||
for i = 1, 9 do
|
||||
if width_idx <= width then
|
||||
inventory:set_stack("recipe", i, items[item_idx])
|
||||
item_idx = item_idx + 1
|
||||
else
|
||||
inventory:set_stack("recipe", i, ItemStack(""))
|
||||
end
|
||||
width_idx = (width_idx < 3) and (width_idx + 1) or 1
|
||||
end
|
||||
-- we'll set the output slot in after_recipe_change to the actual result of the new recipe
|
||||
end
|
||||
after_recipe_change(pos, inventory)
|
||||
end
|
||||
|
||||
local function determine_recipe_items(pos, input)
|
||||
local num, idx
|
||||
|
||||
if input and type(input) == "string" then -- Lua controller
|
||||
-- Test if "<node-number>.<recipe-number>"
|
||||
if string.find(input, "%d+%.%d+") then
|
||||
num, idx = unpack(string.split(input, ".", false, 1))
|
||||
elseif input and type(input) == "table" then -- Beduino
|
||||
if input[3] == 0 then -- TA3 Terminal Basic
|
||||
num = tostring(input[1])
|
||||
idx = tostring(input[2])
|
||||
else -- 16 bit Beduino controller
|
||||
num = tostring(input[1] * 65536 + input[2])
|
||||
idx = tostring(input[3])
|
||||
end
|
||||
end
|
||||
if num and idx then
|
||||
input = get_input_from_recipeblock(pos, num, idx)
|
||||
end
|
||||
end
|
||||
if input and type(input) == "string" then
|
||||
-- "<item>,<item>,..." input
|
||||
local items = string.split(input, ",", true, 8)
|
||||
if items and type(items) == "table" and next(items) then
|
||||
return items
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_new_recipe(pos, input)
|
||||
local items = determine_recipe_items(pos, input)
|
||||
local inv = M(pos):get_inventory()
|
||||
if items then
|
||||
for i = 1, 9 do
|
||||
inv:set_stack("recipe", i, items[i])
|
||||
end
|
||||
else
|
||||
inv:set_list("recipe", {})
|
||||
end
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
autocrafterCache[hash] = nil
|
||||
local craft = get_craft(pos, inv, hash)
|
||||
if craft.output and craft.output.item then
|
||||
inv:set_stack("output", 1, craft.output.item)
|
||||
else
|
||||
inv:set_stack("output", 1, nil)
|
||||
end
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if listname == "output" then
|
||||
return 0
|
||||
end
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
if listname == "recipe" then
|
||||
stack:set_count(1)
|
||||
inv:set_stack(listname, index, stack)
|
||||
after_recipe_change(pos, inv)
|
||||
return 0
|
||||
elseif listname == "output" then
|
||||
on_output_change(pos, inv, stack)
|
||||
return 0
|
||||
elseif listname == "src" then
|
||||
CRD(pos).State:start_if_standby(pos)
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
if listname == "output" then
|
||||
return 0
|
||||
end
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
-- upgrade_autocrafter(pos)
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
if listname == "recipe" then
|
||||
inv:set_stack(listname, index, ItemStack(""))
|
||||
after_recipe_change(pos, inv)
|
||||
return 0
|
||||
elseif listname == "output" then
|
||||
on_output_change(pos, inv, nil)
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
if from_list == "output" or "to_list" == "output" then
|
||||
return 0
|
||||
end
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
|
||||
if to_list == "output" then
|
||||
on_output_change(pos, inv, stack)
|
||||
return 0
|
||||
elseif from_list == "output" then
|
||||
on_output_change(pos, inv, nil)
|
||||
if to_list ~= "recipe" then
|
||||
return 0
|
||||
end -- else fall through to recipe list handling
|
||||
end
|
||||
|
||||
if from_list == "recipe" or to_list == "recipe" then
|
||||
if from_list == "recipe" then
|
||||
inv:set_stack(from_list, from_index, ItemStack(""))
|
||||
end
|
||||
if to_list == "recipe" then
|
||||
stack:set_count(1)
|
||||
inv:set_stack(to_list, to_index, stack)
|
||||
end
|
||||
after_recipe_change(pos, inv)
|
||||
return 0
|
||||
end
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("dst") and inv:is_empty("src")
|
||||
end
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_appl_autocrafter.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_autocrafter.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_autocrafter.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
{
|
||||
name = "techage_filling4_ta#.png^techage_appl_autocrafter4.png^techage_frame4_ta#_top.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.5,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
{
|
||||
name = "techage_filling4_ta#.png^techage_appl_autocrafter4.png^techage_frame4_ta#.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.5,
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "techage_filling4_ta#.png^techage_appl_autocrafter4.png^techage_frame4_ta#.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.5,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
local INFO = [[Commands: 'state', 'recipe']]
|
||||
|
||||
local tubing = {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
if access_type == "push" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
return meta:get_inventory(), "src"
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "dst", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack, idx)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
local inv = M(pos):get_inventory()
|
||||
--CRD(pos).State:start_if_standby(pos) -- would need power!
|
||||
return techage.put_items(inv, "src", stack, idx)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "dst", stack)
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "recipe" and CRD(pos).stage == 4 then
|
||||
if payload and payload ~= "" then
|
||||
on_new_recipe(pos, payload)
|
||||
return true
|
||||
else
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:get_stack("output", 1):get_name()
|
||||
end
|
||||
elseif topic == "flush" and CRD(pos).stage == 4 then
|
||||
return flush_input_inventory(pos)
|
||||
elseif topic == "info" and CRD(pos).stage == 4 then
|
||||
return INFO
|
||||
else
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
if topic == 10 and CRD(pos).stage == 4 then
|
||||
on_new_recipe(pos, payload)
|
||||
return 1, ""
|
||||
elseif topic == 11 and CRD(pos).stage == 4 then
|
||||
if flush_input_inventory(pos) then
|
||||
return 1, ""
|
||||
else
|
||||
return 0, ""
|
||||
end
|
||||
end
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("autocrafter", S("Autocrafter"), tiles, {
|
||||
drawtype = "normal",
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size("src", 2*8)
|
||||
inv:set_size("recipe", 3*3)
|
||||
inv:set_size("dst", 3*3)
|
||||
inv:set_size("output", 1)
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,1,2,4},
|
||||
power_consumption = {0,4,6,9},
|
||||
},
|
||||
{false, true, true, true}) -- TA2/TA3/TA4
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2,
|
||||
recipe = {
|
||||
{"group:wood", "default:diamond", "group:wood"},
|
||||
{"techage:tubeS", "basic_materials:gear_steel", "techage:tubeS"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "default:diamond", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "default:diamond", ""},
|
||||
{"", node_name_ta3, ""},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
||||
|
||||
local Cable = techage.ElectricCable
|
||||
local power = networks.power
|
||||
|
||||
techage.register_node_for_v1_transition({"techage:ta3_autocrafter_pas", "techage:ta4_autocrafter_pas"}, function(pos, node)
|
||||
power.update_network(pos, nil, Cable)
|
||||
end)
|
||||
@@ -0,0 +1,89 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
All items and liquids disappear.
|
||||
|
||||
]]--
|
||||
|
||||
local S = techage.S
|
||||
local Pipe = techage.LiquidPipe
|
||||
local liquid = networks.liquid
|
||||
|
||||
local function take_liquid(pos, indir, name, amount)
|
||||
return 0, name
|
||||
end
|
||||
|
||||
local function put_liquid(pos, indir, name, amount)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function peek_liquid(pos, indir)
|
||||
return nil
|
||||
end
|
||||
|
||||
minetest.register_node("techage:blackhole", {
|
||||
description = S("TechAge Black Hole"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2_bottom.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_blackhole.png^techage_appl_hole_pipe.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_blackhole.png^techage_appl_inp.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_blackhole.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_blackhole.png",
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
meta:set_int("push_dir", techage.side_to_indir("L", node.param2))
|
||||
meta:set_string("infotext", S("TechAge Black Hole (let items and liquids disappear)"))
|
||||
Pipe:after_place_node(pos)
|
||||
end,
|
||||
after_dig_node = function(pos, oldnode)
|
||||
Pipe:after_dig_node(pos)
|
||||
end,
|
||||
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:blackhole",
|
||||
recipe = {
|
||||
{"group:wood", "", "group:wood"},
|
||||
{"techage:tubeS", "default:coal_lump", "techage:ta3_pipeS"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
techage.register_node({"techage:blackhole"}, {
|
||||
on_pull_item = nil, -- not needed
|
||||
on_unpull_item = nil, -- not needed
|
||||
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir then
|
||||
return true
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
liquid.register_nodes({"techage:blackhole"},
|
||||
Pipe, "tank", {"R"}, {
|
||||
capa = 9999999,
|
||||
peek = peek_liquid,
|
||||
put = put_liquid,
|
||||
take = take_liquid,
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,479 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2/TA3/TA4 Chest
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local TA4_INV_SIZE = 50
|
||||
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local mConf = dofile(MP.."/basis/conf_inv.lua")
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
return inv:is_empty("main")
|
||||
end
|
||||
|
||||
local function after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
techage.del_mem(pos)
|
||||
end
|
||||
|
||||
local function formspec2()
|
||||
return "size[9,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;main;0.5,0;8,4;]"..
|
||||
"list[current_player;main;0.5,4.3;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
minetest.register_node("techage:chest_ta2", {
|
||||
description = S("TA2 Protected Chest"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2_bottom.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_chest_back_ta3.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_chest_back_ta3.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_chest_back_ta3.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_chest_front_ta3.png",
|
||||
},
|
||||
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('main', 32)
|
||||
end,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
meta:set_string("formspec", formspec2())
|
||||
end,
|
||||
|
||||
techage_set_numbers = function(pos, numbers, player_name)
|
||||
return techage.logic.set_numbers(pos, numbers, player_name, S("TA2 Protected Chest"))
|
||||
end,
|
||||
|
||||
can_dig = can_dig,
|
||||
after_dig_node = after_dig_node,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
local function formspec3()
|
||||
return "size[10,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;main;0,0;10,4;]"..
|
||||
"list[current_player;main;1,4.3;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
minetest.register_node("techage:chest_ta3", {
|
||||
description = S("TA3 Protected Chest"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3_bottom.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_chest_back_ta3.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_chest_back_ta3.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_chest_back_ta3.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_chest_front_ta3.png",
|
||||
},
|
||||
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('main', 40)
|
||||
end,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local number = techage.add_node(pos, "techage:chest_ta3")
|
||||
meta:set_string("node_number", number)
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
meta:set_string("formspec", formspec3())
|
||||
meta:set_string("infotext", S("TA3 Protected Chest").." "..number)
|
||||
end,
|
||||
|
||||
techage_set_numbers = function(pos, numbers, player_name)
|
||||
return techage.logic.set_numbers(pos, numbers, player_name, S("TA3 Protected Chest"))
|
||||
end,
|
||||
|
||||
can_dig = can_dig,
|
||||
after_dig_node = after_dig_node,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
techage.register_node({"techage:chest_ta2", "techage:chest_ta3"}, {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return meta:get_inventory(), "main"
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num, item_name)
|
||||
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,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "state" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.get_inv_state(inv, "main")
|
||||
elseif topic == "count" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.check_inv_item(inv, "main", payload)
|
||||
else
|
||||
return "unsupported"
|
||||
end
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
if topic == 131 then
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return 0, {techage.get_inv_state_num(inv, "main")}
|
||||
elseif topic == 192 and payload and type(payload) == "string" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return 0, {techage.check_inv_item(inv, "main", payload)}
|
||||
else
|
||||
return 2, ""
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
local function formspec4(pos)
|
||||
return "size[10,9]"..
|
||||
"tabheader[0,0;tab;"..S("Inventory,Pre-Assignment,Config")..";1;;true]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;main;0,0;10,5;]"..
|
||||
mConf.preassigned_stacks(pos, 10, 5)..
|
||||
"list[current_player;main;1,5.3;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
local function formspec4_pre(pos)
|
||||
return "size[10,9]"..
|
||||
"tabheader[0,0;tab;"..S("Inventory,Pre-Assignment,Config")..";2;;true]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;conf;0,0;10,5;]"..
|
||||
"list[current_player;main;1,5.3;8,4;]"..
|
||||
"listring[context;conf]"..
|
||||
"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)
|
||||
local public = M(pos):get_int("public") == 1
|
||||
if not public and minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
if listname == "main" then
|
||||
return stack:get_count()
|
||||
else
|
||||
return mConf.allow_conf_inv_put(pos, listname, index, stack, player)
|
||||
end
|
||||
end
|
||||
|
||||
local function ta4_allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
local public = M(pos):get_int("public") == 1
|
||||
if not public and minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
if listname == "main" then
|
||||
return stack:get_count()
|
||||
else
|
||||
return mConf.allow_conf_inv_take(pos, listname, index, stack, player)
|
||||
end
|
||||
end
|
||||
|
||||
local function ta4_allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local public = M(pos):get_int("public") == 1
|
||||
if not public and minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
if from_list == "main" then
|
||||
return count
|
||||
else
|
||||
return mConf.allow_conf_inv_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("techage:chest_ta4", {
|
||||
description = S("TA4 Protected Chest"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta4.png^techage_frame_ta4_top.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4_bottom.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_front_ta4.png",
|
||||
},
|
||||
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('main', 50)
|
||||
inv:set_size('conf', 50)
|
||||
end,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local number = techage.add_node(pos, "techage:chest_ta4")
|
||||
meta:set_string("node_number", number)
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
meta:set_string("formspec", formspec4(pos))
|
||||
meta:set_string("infotext", S("TA4 Protected Chest").." "..number)
|
||||
end,
|
||||
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
if fields.tab == "1" then
|
||||
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)
|
||||
return techage.logic.set_numbers(pos, numbers, player_name, S("TA4 Protected Chest"))
|
||||
end,
|
||||
|
||||
can_dig = can_dig,
|
||||
after_dig_node = after_dig_node,
|
||||
allow_metadata_inventory_put = ta4_allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = ta4_allow_metadata_inventory_take,
|
||||
allow_metadata_inventory_move = ta4_allow_metadata_inventory_move,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
|
||||
techage.register_node({"techage:chest_ta4"}, {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return meta:get_inventory(), "main"
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num, item_name)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local mem = techage.get_mem(pos)
|
||||
|
||||
mem.filter = mem.filter or mConf.item_filter(pos, TA4_INV_SIZE)
|
||||
mem.chest_configured = mem.chest_configured or not inv:is_empty("conf")
|
||||
|
||||
if inv:is_empty("main") then
|
||||
return nil
|
||||
end
|
||||
|
||||
if item_name then
|
||||
if mem.filter[item_name] or not mem.chest_configured then
|
||||
local taken = inv:remove_item("main", {name = item_name, count = num})
|
||||
if taken:get_count() > 0 then
|
||||
return taken
|
||||
end
|
||||
end
|
||||
else -- no item given
|
||||
if mem.chest_configured then
|
||||
return mConf.take_item(pos, inv, "main", num, mem.filter["unconfigured"])
|
||||
else
|
||||
return techage.get_items(pos, inv, "main", num)
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, item, idx)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local mem = techage.get_mem(pos)
|
||||
|
||||
mem.filter = mem.filter or mConf.item_filter(pos, TA4_INV_SIZE)
|
||||
mem.chest_configured = mem.chest_configured or not inv:is_empty("conf")
|
||||
|
||||
if mem.chest_configured then
|
||||
local name = item:get_name()
|
||||
local stacks = mem.filter[name] or mem.filter["unconfigured"]
|
||||
return mConf.put_items(pos, inv, "main", item, stacks, idx)
|
||||
else
|
||||
return techage.put_items(inv, "main", item, idx)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, item)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local mem = techage.get_mem(pos)
|
||||
|
||||
mem.filter = mem.filter or mConf.item_filter(pos, TA4_INV_SIZE)
|
||||
mem.chest_configured = mem.chest_configured or not inv:is_empty("conf")
|
||||
|
||||
if mem.chest_configured then
|
||||
local name = item:get_name()
|
||||
local stacks = mem.filter[name] or mem.filter["unconfigured"]
|
||||
return mConf.put_items(pos, inv, "main", item, stacks)
|
||||
else
|
||||
return techage.put_items(inv, "main", item)
|
||||
end
|
||||
end,
|
||||
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "state" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.get_inv_state(inv, "main")
|
||||
elseif topic == "count" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.check_inv_item(inv, "main", payload)
|
||||
else
|
||||
return "unsupported"
|
||||
end
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
if topic == 131 then
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return 0, {techage.get_inv_state_num(inv, "main")}
|
||||
elseif topic == 192 and payload and type(payload) == "string" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return 0, {techage.check_inv_item(inv, "main", payload)}
|
||||
else
|
||||
return 2, ""
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:chest_ta2",
|
||||
recipe = {"default:chest", "techage:tubeS", "techage:iron_ingot"}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:chest_ta2",
|
||||
recipe = {"default:chest_locked", "techage:tubeS", "techage:iron_ingot"}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:chest_ta2",
|
||||
recipe = {"protector:chest", "techage:tubeS", "techage:iron_ingot"}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:chest_ta3",
|
||||
recipe = {"techage:chest_ta2", "default:chest"}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:chest_ta4",
|
||||
recipe = {"techage:chest_ta3", "default:chest"}
|
||||
})
|
||||
@@ -0,0 +1,154 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Tube Concentrator
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local Tube = techage.Tube
|
||||
|
||||
local size = 2/8
|
||||
local Boxes = {
|
||||
{{-size, -size, size, size, size, 0.5 }}, -- z+
|
||||
{{-size, -size, -size, 0.5, size, size}}, -- x+
|
||||
{{-size, -size, -0.5, size, size, size}}, -- z-
|
||||
{{-0.5, -size, -size, size, size, size}}, -- x-
|
||||
{{-size, -0.5, -size, size, size, size}}, -- y-
|
||||
{{-size, -size, -size, size, 0.5, size}}, -- y+
|
||||
}
|
||||
|
||||
local names = networks.register_junction("techage:concentrator", 2/8, Boxes, Tube, {
|
||||
description = S("Tube Concentrator"),
|
||||
tiles = {
|
||||
"techage_tube_junction.png^techage_appl_arrow2.png^[transformR270",
|
||||
"techage_tube_junction.png^techage_appl_arrow2.png^[transformR270",
|
||||
"techage_tube_junction.png^techage_tube_hole.png",
|
||||
"techage_tube_junction.png",
|
||||
"techage_tube_junction.png^techage_appl_arrow2.png^[transformR90",
|
||||
"techage_tube_junction.png^techage_appl_arrow2.png^[transformR270",
|
||||
},
|
||||
paramtype2 = "facedir", -- important!
|
||||
use_texture_alpha = techage.CLIP,
|
||||
groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 3, techage_trowel = 1},
|
||||
sounds = default.node_sound_defaults(),
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
local node = minetest.get_node(pos)
|
||||
local name = "techage:concentrator"..networks.junction_type(pos, Tube, "R", node.param2)
|
||||
minetest.swap_node(pos, {name = name, param2 = node.param2})
|
||||
M(pos):set_int("push_dir", techage.side_to_outdir("R", node.param2))
|
||||
Tube:after_place_node(pos)
|
||||
end,
|
||||
tubelib2_on_update2 = function(pos, dir1, tlib2, node)
|
||||
local name = "techage:concentrator"..networks.junction_type(pos, Tube, "R", node.param2)
|
||||
minetest.swap_node(pos, {name = name, param2 = node.param2})
|
||||
end,
|
||||
ta_rotate_node = function(pos, node, new_param2)
|
||||
Tube:after_dig_node(pos)
|
||||
minetest.swap_node(pos, {name = node.name, param2 = new_param2})
|
||||
Tube:after_place_node(pos)
|
||||
M(pos):set_int("push_dir", techage.side_to_outdir("R", new_param2))
|
||||
end,
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Tube:after_dig_node(pos)
|
||||
end,
|
||||
}, 27)
|
||||
|
||||
for _, name in ipairs(names) do
|
||||
Tube:set_valid_sides(name, {"B", "R", "F", "L", "D", "U"})
|
||||
end
|
||||
|
||||
techage.register_node(names, {
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local push_dir = M(pos):get_int("push_dir")
|
||||
if networks.Flip[push_dir] ~= in_dir then
|
||||
return techage.safe_push_items(pos, push_dir, stack)
|
||||
else
|
||||
return stack
|
||||
end
|
||||
end,
|
||||
is_pusher = true, -- is a pulling/pushing node
|
||||
})
|
||||
|
||||
names = networks.register_junction("techage:ta4_concentrator", 2/8, Boxes, Tube, {
|
||||
description = S("TA4 Tube Concentrator"),
|
||||
tiles = {
|
||||
"techage_tubeta4_junction.png^techage_appl_arrow2.png^[transformR270",
|
||||
"techage_tubeta4_junction.png^techage_appl_arrow2.png^[transformR270",
|
||||
"techage_tubeta4_junction.png^techage_tube_hole.png",
|
||||
"techage_tubeta4_junction.png",
|
||||
"techage_tubeta4_junction.png^techage_appl_arrow2.png^[transformR90",
|
||||
"techage_tubeta4_junction.png^techage_appl_arrow2.png^[transformR270",
|
||||
},
|
||||
paramtype2 = "facedir", -- important!
|
||||
use_texture_alpha = techage.CLIP,
|
||||
groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 3, techage_trowel = 1},
|
||||
sounds = default.node_sound_defaults(),
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
local node = minetest.get_node(pos)
|
||||
local name = "techage:ta4_concentrator"..networks.junction_type(pos, Tube, "R", node.param2)
|
||||
minetest.swap_node(pos, {name = name, param2 = node.param2})
|
||||
M(pos):set_int("push_dir", techage.side_to_outdir("R", node.param2))
|
||||
Tube:after_place_node(pos)
|
||||
end,
|
||||
tubelib2_on_update2 = function(pos, dir1, tlib2, node)
|
||||
local name = "techage:ta4_concentrator"..networks.junction_type(pos, Tube, "R", node.param2)
|
||||
minetest.swap_node(pos, {name = name, param2 = node.param2})
|
||||
end,
|
||||
ta_rotate_node = function(pos, node, new_param2)
|
||||
Tube:after_dig_node(pos)
|
||||
minetest.swap_node(pos, {name = node.name, param2 = new_param2})
|
||||
Tube:after_place_node(pos)
|
||||
M(pos):set_int("push_dir", techage.side_to_outdir("R", new_param2))
|
||||
end,
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Tube:after_dig_node(pos)
|
||||
end,
|
||||
}, 27)
|
||||
|
||||
for _, name in ipairs(names) do
|
||||
Tube:set_valid_sides(name, {"B", "R", "F", "L", "D", "U"})
|
||||
end
|
||||
|
||||
techage.register_node(names, {
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local push_dir = M(pos):get_int("push_dir")
|
||||
if networks.Flip[push_dir] ~= in_dir then
|
||||
return techage.safe_push_items(pos, push_dir, stack)
|
||||
else
|
||||
return stack
|
||||
end
|
||||
end,
|
||||
is_pusher = true, -- is a pulling/pushing node
|
||||
})
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:concentrator27",
|
||||
recipe = {
|
||||
{"", "techage:tubeS", ""},
|
||||
{"techage:tubeS", "", "techage:tubeS"},
|
||||
{"", "techage:tubeS", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:ta4_concentrator27",
|
||||
recipe = {
|
||||
{"", "techage:ta4_tubeS", ""},
|
||||
{"techage:ta4_tubeS", "", "techage:ta4_tubeS"},
|
||||
{"", "techage:ta4_tubeS", ""},
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,314 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Consumer node basis functionality.
|
||||
It handles:
|
||||
- up to 4 stages of nodes (TA2/TA3/TA4/TA5)
|
||||
- power consumption
|
||||
- node state handling
|
||||
- registration of passive and active nodes
|
||||
- Tube connections are on left and right side (from left to right)
|
||||
- Power connection are on front and back side (front or back)
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
local CRDN = function(node) return (minetest.registered_nodes[node.name] or {}).consumer end
|
||||
|
||||
local Tube = techage.Tube
|
||||
local power = networks.power
|
||||
local liquid = networks.liquid
|
||||
local CYCLE_TIME = 2
|
||||
|
||||
local function get_keys(tbl)
|
||||
local keys = {}
|
||||
for k,v in pairs(tbl) do
|
||||
keys[#keys + 1] = k
|
||||
end
|
||||
return keys
|
||||
end
|
||||
|
||||
local function has_power(pos, nvm, state)
|
||||
local crd = CRD(pos)
|
||||
return power.power_available(pos, crd.power_netw)
|
||||
end
|
||||
|
||||
local function start_node(pos, nvm, state)
|
||||
end
|
||||
|
||||
local function stop_node(pos, nvm, state)
|
||||
end
|
||||
|
||||
local function node_timer_pas(pos, elapsed)
|
||||
local crd = CRD(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
|
||||
-- handle power consumption
|
||||
if crd.power_netw and techage.needs_power(nvm) then
|
||||
local consumed = power.consume_power(pos, crd.power_netw, nil, crd.power_consumption)
|
||||
if consumed == crd.power_consumption then
|
||||
crd.State:start(pos, nvm)
|
||||
end
|
||||
end
|
||||
|
||||
-- call the node timer routine
|
||||
if techage.is_operational(nvm) then
|
||||
nvm.node_timer_call_cyle = (nvm.node_timer_call_cyle or 0) + 1
|
||||
if nvm.node_timer_call_cyle >= crd.call_cycle then
|
||||
crd.node_timer(pos, crd.cycle_time)
|
||||
nvm.node_timer_call_cyle = 0
|
||||
end
|
||||
end
|
||||
return crd.State:is_active(nvm)
|
||||
end
|
||||
|
||||
local function node_timer_act(pos, elapsed)
|
||||
local crd = CRD(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
|
||||
-- handle power consumption
|
||||
if crd.power_netw and techage.needs_power(nvm) then
|
||||
local consumed = power.consume_power(pos, crd.power_netw, nil, crd.power_consumption)
|
||||
if consumed < crd.power_consumption then
|
||||
crd.State:nopower(pos, nvm)
|
||||
end
|
||||
end
|
||||
|
||||
-- call the node timer routine
|
||||
if techage.is_operational(nvm) then
|
||||
nvm.node_timer_call_cyle = (nvm.node_timer_call_cyle or 0) + 1
|
||||
if nvm.node_timer_call_cyle >= crd.call_cycle then
|
||||
crd.node_timer(pos, crd.cycle_time)
|
||||
nvm.node_timer_call_cyle = 0
|
||||
end
|
||||
end
|
||||
return crd.State:is_active(nvm)
|
||||
end
|
||||
|
||||
local function prepare_tiles(tiles, stage, power_png)
|
||||
local tbl = {}
|
||||
for _,item in ipairs(tiles) do
|
||||
if type(item) == "string" then
|
||||
tbl[#tbl+1] = item:gsub("#", stage):gsub("{power}", power_png):gsub("@@", '#')
|
||||
else
|
||||
local temp = table.copy(item)
|
||||
temp.name = temp.name:gsub("#", stage):gsub("{power}", power_png):gsub("@@", '#')
|
||||
tbl[#tbl+1] = temp
|
||||
end
|
||||
end
|
||||
return tbl
|
||||
end
|
||||
|
||||
-- 'validStates' is optional and can be used to e.g. enable
|
||||
-- only one TA2 node {false, true, false, false}
|
||||
function techage.register_consumer(base_name, inv_name, tiles, tNode, validStates, node_name_prefix, inv_name_prefix)
|
||||
local names = {}
|
||||
validStates = validStates or {true, true, true, true}
|
||||
|
||||
node_name_prefix = node_name_prefix or "techage:ta"
|
||||
if inv_name_prefix then
|
||||
inv_name_prefix = inv_name_prefix.." "
|
||||
else
|
||||
inv_name_prefix = ""
|
||||
end
|
||||
|
||||
for stage = 2,5 do
|
||||
local name_pas = node_name_prefix..stage.."_"..base_name.."_pas"
|
||||
local name_act = node_name_prefix..stage.."_"..base_name.."_act"
|
||||
local name_inv = inv_name_prefix.."TA"..stage.." "..inv_name
|
||||
names[#names+1] = name_pas
|
||||
|
||||
if validStates[stage] then
|
||||
local power_network
|
||||
local power_png = 'techage_axle_clutch.png'
|
||||
local power_used = tNode.power_consumption ~= nil
|
||||
local sides
|
||||
-- power needed?
|
||||
if power_used then
|
||||
if stage > 2 then
|
||||
power_network = techage.ElectricCable
|
||||
power_png = 'techage_appl_hole_electric.png'
|
||||
sides = get_keys(tNode.power_sides or {F=1, B=1, U=1, D=1})
|
||||
else
|
||||
power_network = techage.Axle
|
||||
power_png = 'techage_axle_clutch.png'
|
||||
sides = get_keys(tNode.power_sides or {F=1, B=1, U=1, D=1})
|
||||
end
|
||||
end
|
||||
|
||||
local tState = techage.NodeStates:new({
|
||||
node_name_passive = name_pas,
|
||||
node_name_active = name_act,
|
||||
infotext_name = name_inv,
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = tNode.standby_ticks,
|
||||
formspec_func = tNode.formspec,
|
||||
on_state_change = tNode.on_state_change,
|
||||
can_start = tNode.can_start,
|
||||
quick_start = tNode.quick_start,
|
||||
has_power = tNode.has_power or power_used and has_power or nil,
|
||||
start_node = power_used and start_node or nil,
|
||||
stop_node = power_used and stop_node or nil,
|
||||
})
|
||||
|
||||
local tConsumer = {
|
||||
stage = stage,
|
||||
State = tState,
|
||||
-- number of items to be processed per cycle
|
||||
num_items = tNode.num_items and tNode.num_items[stage],
|
||||
power_consumption = power_used and
|
||||
tNode.power_consumption[stage] or 0,
|
||||
node_timer = tNode.node_timer,
|
||||
cycle_time = tNode.cycle_time,
|
||||
call_cycle = tNode.cycle_time / 2,
|
||||
power_netw = power_network,
|
||||
}
|
||||
|
||||
local after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
local crd = CRD(pos)
|
||||
local meta = M(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
meta:set_int("push_dir", techage.side_to_indir("L", node.param2))
|
||||
meta:set_int("pull_dir", techage.side_to_indir("R", node.param2))
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
-- Delete existing node number. Needed for Digtron compatibility.
|
||||
if (meta:contains("node_number")) then
|
||||
meta:set_string("node_number", "")
|
||||
end
|
||||
local number = techage.add_node(pos, name_pas, stage == 2)
|
||||
if crd.power_netw then
|
||||
crd.power_netw:after_place_node(pos)
|
||||
end
|
||||
if tNode.after_place_node then
|
||||
tNode.after_place_node(pos, placer, itemstack, pointed_thing)
|
||||
end
|
||||
crd.State:node_init(pos, nvm, number)
|
||||
end
|
||||
|
||||
local after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
if tNode.after_dig_node then
|
||||
tNode.after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||
end
|
||||
local crd = CRDN(oldnode)
|
||||
if crd.power_netw then
|
||||
crd.power_netw:after_dig_node(pos)
|
||||
end
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
techage.del_mem(pos)
|
||||
end
|
||||
|
||||
tNode.groups.not_in_creative_inventory = 0
|
||||
|
||||
local def_pas = {
|
||||
description = name_inv,
|
||||
tiles = prepare_tiles(tiles.pas, stage, power_png),
|
||||
consumer = tConsumer,
|
||||
drawtype = tNode.drawtype,
|
||||
node_box = tNode.node_box,
|
||||
selection_box = tNode.selection_box,
|
||||
|
||||
can_dig = tNode.can_dig,
|
||||
on_rotate = tNode.on_rotate or screwdriver.disallow,
|
||||
on_timer = node_timer_pas,
|
||||
on_receive_fields = tNode.on_receive_fields,
|
||||
on_rightclick = tNode.on_rightclick,
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
preserve_metadata = tNode.preserve_metadata,
|
||||
allow_metadata_inventory_put = tNode.allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = tNode.allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = tNode.allow_metadata_inventory_take,
|
||||
on_metadata_inventory_move = tNode.on_metadata_inventory_move,
|
||||
on_metadata_inventory_put = tNode.on_metadata_inventory_put,
|
||||
on_metadata_inventory_take = tNode.on_metadata_inventory_take,
|
||||
ta_rotate_node = tNode.ta_rotate_node,
|
||||
ta3_formspec = stage == 3 and tNode.ta3_formspec,
|
||||
ta4_formspec = stage == 4 and tNode.ta4_formspec,
|
||||
|
||||
paramtype = tNode.paramtype,
|
||||
paramtype2 = "facedir",
|
||||
drop = tNode.drop,
|
||||
groups = table.copy(tNode.groups),
|
||||
is_ground_content = false,
|
||||
sounds = tNode.sounds,
|
||||
}
|
||||
|
||||
-- Copy custom properties (starting with an underscore)
|
||||
for k,v in pairs(tNode) do
|
||||
if string.sub(k, 1, 1) == "_" then
|
||||
def_pas[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node(name_pas, def_pas)
|
||||
|
||||
tNode.groups.not_in_creative_inventory = 1
|
||||
|
||||
local def_act = {
|
||||
description = name_inv,
|
||||
tiles = prepare_tiles(tiles.act, stage, power_png),
|
||||
consumer = tConsumer,
|
||||
drawtype = tNode.drawtype,
|
||||
node_box = tNode.node_box,
|
||||
selection_box = tNode.selection_box,
|
||||
|
||||
on_rotate = tNode.on_rotate or screwdriver.disallow,
|
||||
on_timer = node_timer_act,
|
||||
on_receive_fields = tNode.on_receive_fields,
|
||||
on_rightclick = tNode.on_rightclick,
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
allow_metadata_inventory_put = tNode.allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = tNode.allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = tNode.allow_metadata_inventory_take,
|
||||
on_metadata_inventory_move = tNode.on_metadata_inventory_move,
|
||||
on_metadata_inventory_put = tNode.on_metadata_inventory_put,
|
||||
on_metadata_inventory_take = tNode.on_metadata_inventory_take,
|
||||
ta_rotate_node = tNode.ta_rotate_node,
|
||||
ta3_formspec = stage == 3 and tNode.ta3_formspec,
|
||||
ta4_formspec = stage == 4 and tNode.ta4_formspec,
|
||||
|
||||
paramtype = tNode.paramtype,
|
||||
paramtype2 = "facedir",
|
||||
drop = "",
|
||||
diggable = false,
|
||||
groups = table.copy(tNode.groups),
|
||||
is_ground_content = false,
|
||||
sounds = tNode.sounds,
|
||||
}
|
||||
|
||||
-- Copy custom properties (starting with an underscore)
|
||||
for k,v in pairs(tNode) do
|
||||
if string.sub(k, 1, 1) == "_" then
|
||||
def_act[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node(name_act, def_act)
|
||||
|
||||
if power_used then
|
||||
power.register_nodes({name_pas, name_act}, power_network, "con", sides)
|
||||
end
|
||||
techage.register_node({name_pas, name_act}, tNode.tubing)
|
||||
|
||||
if tNode.tube_sides then
|
||||
Tube:set_valid_sides(name_pas, get_keys(tNode.tube_sides))
|
||||
Tube:set_valid_sides(name_act, get_keys(tNode.tube_sides))
|
||||
end
|
||||
end
|
||||
end
|
||||
return names[1], names[2], names[3], names[4]
|
||||
end
|
||||
@@ -0,0 +1,684 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2/TA3/TA4 Distributor
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local N = minetest.get_node
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
local Tube = techage.Tube
|
||||
|
||||
local S = techage.S
|
||||
|
||||
local SRC_INV_SIZE = 8
|
||||
|
||||
local STANDBY_TICKS = 3
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 4
|
||||
local FILTER_ITEM_LIMIT_PER_STACK = 12
|
||||
local FILTER_ITEM_LIMIT = 36
|
||||
|
||||
local INFO = [[Turn port on/off or read its state: command = 'port', payload = red/green/blue/yellow{=on/off}]]
|
||||
|
||||
|
||||
--local Side2Color = {B="red", L="green", F="blue", R="yellow"}
|
||||
local SlotColors = {"red", "green", "blue", "yellow"}
|
||||
local SlotNumbers = {red = 1, green = 2, blue = 3, yellow = 4}
|
||||
local Num2Ascii = {"B", "L", "F", "R"}
|
||||
local FilterCache = {} -- local cache for filter settings
|
||||
|
||||
local function filter_settings(pos)
|
||||
local meta = M(pos)
|
||||
local param2 = techage.get_node_lvm(pos).param2
|
||||
local inv = meta:get_inventory()
|
||||
local filter = minetest.deserialize(meta:get_string("filter")) or {false,false,false,false}
|
||||
local ItemFilter = {} -- {<item:name> = {dir,...}]
|
||||
local OpenPorts = {} -- {dir, ...}
|
||||
local counter = 0 -- counts total item number in filter configuration
|
||||
|
||||
-- collect all filter settings
|
||||
for idx,slot in ipairs(SlotColors) do
|
||||
if filter[idx] == true then
|
||||
local side = Num2Ascii[idx]
|
||||
local out_dir = techage.side_to_outdir(side, param2)
|
||||
if inv:is_empty(slot) then
|
||||
table.insert(OpenPorts, out_dir)
|
||||
else
|
||||
for idx2,stack in ipairs(inv:get_list(slot)) do
|
||||
local name = stack:get_name()
|
||||
if name ~= "" then
|
||||
if not ItemFilter[name] then
|
||||
ItemFilter[name] = {}
|
||||
end
|
||||
for _ = 1, math.min(FILTER_ITEM_LIMIT_PER_STACK, stack:get_count()) do
|
||||
if counter > FILTER_ITEM_LIMIT then
|
||||
break
|
||||
end
|
||||
table.insert(ItemFilter[name], out_dir)
|
||||
counter = counter + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
FilterCache[minetest.hash_node_position(pos)] = {
|
||||
ItemFilter = ItemFilter,
|
||||
OpenPorts = OpenPorts,
|
||||
}
|
||||
end
|
||||
|
||||
-- Return filter table and list of open ports.
|
||||
-- (see test data)
|
||||
local function get_filter_settings(pos)
|
||||
-- local ItemFilter = {
|
||||
-- ["default:dirt"] = {1,2},
|
||||
-- ["default:cobble"] = {4},
|
||||
-- }
|
||||
-- local OpenPorts = {3}
|
||||
-- return ItemFilter, OpenPorts
|
||||
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
if FilterCache[hash] == nil then
|
||||
filter_settings(pos)
|
||||
end
|
||||
return FilterCache[hash].ItemFilter, FilterCache[hash].OpenPorts
|
||||
end
|
||||
|
||||
local function blocking_checkbox(pos, filter, is_hp)
|
||||
local cnt = 0
|
||||
local _, open_ports = get_filter_settings(pos)
|
||||
local fs_pos = is_hp and "0.25,5" or "3,3.9"
|
||||
for _,val in ipairs(filter) do
|
||||
if val then cnt = cnt + 1 end
|
||||
end
|
||||
if cnt > 1 and #open_ports > 0 then
|
||||
local blocking = M(pos):get_int("blocking") == 1 and "true" or "false"
|
||||
return "checkbox["..fs_pos..";blocking;"..S("blocking mode")..";"..blocking.."]"..
|
||||
"tooltip["..fs_pos..";1,1;"..S("Block configured items for open ports")..";#0C3D32;#FFFFFF]"
|
||||
else
|
||||
M(pos):set_int("blocking", 0) -- disable blocking
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
local filter = minetest.deserialize(M(pos):get_string("filter")) or {false,false,false,false}
|
||||
local is_hp = nvm.high_performance == true
|
||||
local blocking = blocking_checkbox(pos, filter, is_hp)
|
||||
|
||||
if is_hp then
|
||||
return "size[10.5,9.5]"..
|
||||
"box[0.25,-0.1;9.6,1.1;#005500]"..
|
||||
"label[0.6,0.2;"..S("Input").."]"..
|
||||
"list[context;src;1.75,0;8,1;]"..
|
||||
blocking..
|
||||
"image_button[0.25,5.8;1,1;"..self:get_state_button_image(nvm)..";state_button;]"..
|
||||
"tooltip[0.25,5.8;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"checkbox[0.25,1.2;filter1;On;"..dump(filter[1]).."]"..
|
||||
"checkbox[0.25,2.2;filter2;On;"..dump(filter[2]).."]"..
|
||||
"checkbox[0.25,3.2;filter3;On;"..dump(filter[3]).."]"..
|
||||
"checkbox[0.25,4.2;filter4;On;"..dump(filter[4]).."]"..
|
||||
"image[1.25,1.2;0.3,1;techage_inv_red.png]"..
|
||||
"image[1.25,2.2;0.3,1;techage_inv_green.png]"..
|
||||
"image[1.25,3.2;0.3,1;techage_inv_blue.png]"..
|
||||
"image[1.25,4.2;0.3,1;techage_inv_yellow.png]"..
|
||||
"list[context;red;1.75,1.2;8,1;]"..
|
||||
"list[context;green;1.75,2.2;8,1;]"..
|
||||
"list[context;blue;1.75,3.2;8,1;]"..
|
||||
"list[context;yellow;1.75,4.2;8,1;]"..
|
||||
"list[current_player;main;1.75,5.8;8,4;]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(1.75,5.8)
|
||||
else
|
||||
return "size[10.5,8.5]"..
|
||||
"list[context;src;0,0;2,4;]"..
|
||||
blocking..
|
||||
"image[2,1.5;1,1;techage_form_arrow.png]"..
|
||||
"image_button[0,4.8;1,1;"..self:get_state_button_image(nvm)..";state_button;]"..
|
||||
"tooltip[0,4.8;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"checkbox[3,0;filter1;On;"..dump(filter[1]).."]"..
|
||||
"checkbox[3,1;filter2;On;"..dump(filter[2]).."]"..
|
||||
"checkbox[3,2;filter3;On;"..dump(filter[3]).."]"..
|
||||
"checkbox[3,3;filter4;On;"..dump(filter[4]).."]"..
|
||||
"image[4,0;0.3,1;techage_inv_red.png]"..
|
||||
"image[4,1;0.3,1;techage_inv_green.png]"..
|
||||
"image[4,2;0.3,1;techage_inv_blue.png]"..
|
||||
"image[4,3;0.3,1;techage_inv_yellow.png]"..
|
||||
"list[context;red;4.5,0;6,1;]"..
|
||||
"list[context;green;4.5,1;6,1;]"..
|
||||
"list[context;blue;4.5,2;6,1;]"..
|
||||
"list[context;yellow;4.5,3;6,1;]"..
|
||||
"list[current_player;main;1.25,4.8;8,4;]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(1.25,4.8)
|
||||
end
|
||||
end
|
||||
|
||||
local function get_total_filter_items_number(pos, except_listname, except_index)
|
||||
local inv = M(pos):get_inventory()
|
||||
local total = 0
|
||||
for _, listname in ipairs(SlotColors) do
|
||||
local list = inv:get_list(listname)
|
||||
for idx, stack in ipairs(list) do
|
||||
if not (listname == except_listname and idx == except_index) then
|
||||
total = total + stack:get_count()
|
||||
end
|
||||
end
|
||||
end
|
||||
return total
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
local inv = M(pos):get_inventory()
|
||||
local list = inv:get_list(listname)
|
||||
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
if listname == "src" then
|
||||
CRD(pos).State:start_if_standby(pos)
|
||||
return stack:get_count()
|
||||
else
|
||||
stack:add_item(list[index])
|
||||
local max_items_to_limit = FILTER_ITEM_LIMIT - get_total_filter_items_number(pos, listname, index)
|
||||
stack:set_count(math.min(FILTER_ITEM_LIMIT_PER_STACK, stack:get_count(), max_items_to_limit))
|
||||
inv:set_stack(listname, index, stack)
|
||||
return 0
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
if listname == "src" then
|
||||
return stack:get_count()
|
||||
else
|
||||
local inv = M(pos):get_inventory()
|
||||
local list = inv:get_list(listname)
|
||||
list[index]:take_item(stack:get_count())
|
||||
inv:set_stack(listname, index, list[index])
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
local function 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
|
||||
return 0
|
||||
end
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
|
||||
if from_list == "src" and to_list ~= "src" then
|
||||
stack:add_item(inv:get_stack(to_list, to_index))
|
||||
local max_items_to_limit = FILTER_ITEM_LIMIT - get_total_filter_items_number(pos, to_list, to_index)
|
||||
stack:set_count(math.min(FILTER_ITEM_LIMIT_PER_STACK, stack:get_count(), max_items_to_limit))
|
||||
inv:set_stack(to_list, to_index, stack)
|
||||
return 0
|
||||
elseif from_list ~= "src" and to_list == "src" then
|
||||
inv:set_stack(from_list, from_index, nil)
|
||||
return 0
|
||||
elseif from_list ~= "src" and to_list ~= "src" then
|
||||
return math.min(stack:get_count(), FILTER_ITEM_LIMIT_PER_STACK - inv:get_stack(to_list, to_index):get_count())
|
||||
else
|
||||
return stack:get_count()
|
||||
end
|
||||
end
|
||||
|
||||
local function tubelib2_on_update2(pos, outdir, tlib2, node)
|
||||
local is_ta4_tube = true
|
||||
for dir = 1,4 do
|
||||
for i, pos, node in Tube:get_tube_line(pos, dir) do
|
||||
is_ta4_tube = is_ta4_tube and techage.TA4tubes[node.name]
|
||||
end
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
if CRD(pos).stage == 4 and not is_ta4_tube then
|
||||
nvm.num_items = crd.num_items / 2
|
||||
else
|
||||
nvm.num_items = crd.num_items
|
||||
end
|
||||
end
|
||||
|
||||
local function shuffle(list)
|
||||
for i = #list, 2, -1 do
|
||||
local j = math.random(i)
|
||||
list[i], list[j] = list[j], list[i]
|
||||
end
|
||||
return list
|
||||
end
|
||||
|
||||
local function push_item(pos, base_filter, itemstack, num_items, nvm)
|
||||
local filter = shuffle(table.copy(base_filter))
|
||||
local idx = 1
|
||||
local num_pushed = 0
|
||||
local num_ports = #filter
|
||||
local amount = math.floor(math.max((num_items + 1) / num_ports, 1))
|
||||
local num_of_trials = 0
|
||||
while num_pushed < num_items and num_of_trials <= 8 do
|
||||
num_of_trials = num_of_trials + 1
|
||||
local push_dir = filter[idx]
|
||||
local num_to_push = math.min(amount, num_items - num_pushed)
|
||||
local leftover = techage.push_items(pos, push_dir, itemstack:peek_item(num_to_push))
|
||||
local pushed
|
||||
if not leftover then
|
||||
pushed = 0
|
||||
elseif leftover ~= true then
|
||||
pushed = num_to_push - leftover:get_count()
|
||||
else -- leftover == true
|
||||
pushed = num_to_push
|
||||
end
|
||||
num_pushed = num_pushed + pushed
|
||||
nvm.port_counter[push_dir] = (nvm.port_counter[push_dir] or 0) + pushed
|
||||
-- filter start offset
|
||||
idx = idx + 1
|
||||
if idx > num_ports then
|
||||
idx = 1
|
||||
end
|
||||
end
|
||||
return num_pushed
|
||||
end
|
||||
|
||||
-- move items to output slots
|
||||
local function distributing(pos, inv, crd, nvm)
|
||||
local item_filter, open_ports = get_filter_settings(pos)
|
||||
local sum_num_pushed = 0
|
||||
local num_pushed = 0
|
||||
local blocking_mode = M(pos):get_int("blocking") == 1
|
||||
|
||||
-- start searching after last position
|
||||
local offs = nvm.last_index or 1
|
||||
|
||||
for i = 1, SRC_INV_SIZE do
|
||||
local idx = ((i + offs - 1) % 8) + 1
|
||||
local stack = inv:get_stack("src", idx)
|
||||
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)
|
||||
local filter = item_filter[item_name]
|
||||
num_pushed = 0
|
||||
|
||||
if filter and #filter > 0 then
|
||||
-- Push items based on filter
|
||||
num_pushed = push_item(pos, filter, 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, 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, stack_to_push, num_to_push, nvm)
|
||||
end
|
||||
|
||||
sum_num_pushed = sum_num_pushed + num_pushed
|
||||
stack:take_item(num_pushed)
|
||||
inv:set_stack("src", idx, stack)
|
||||
if sum_num_pushed >= (nvm.num_items or crd.num_items) then
|
||||
nvm.last_index = idx
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if sum_num_pushed == 0 then
|
||||
crd.State:blocked(pos, nvm)
|
||||
else
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
end
|
||||
end
|
||||
|
||||
-- move items to the output slots
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.port_counter = nvm.port_counter or {}
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
if not inv:is_empty("src") then
|
||||
distributing(pos, inv, crd, nvm)
|
||||
else
|
||||
crd.State:idle(pos, nvm)
|
||||
end
|
||||
return crd.State:is_active(nvm)
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local meta = M(pos)
|
||||
local crd = CRD(pos)
|
||||
local filter = minetest.deserialize(meta:get_string("filter")) or {false,false,false,false}
|
||||
if fields.filter1 ~= nil then
|
||||
filter[1] = fields.filter1 == "true"
|
||||
elseif fields.filter2 ~= nil then
|
||||
filter[2] = fields.filter2 == "true"
|
||||
elseif fields.filter3 ~= nil then
|
||||
filter[3] = fields.filter3 == "true"
|
||||
elseif fields.filter4 ~= nil then
|
||||
filter[4] = fields.filter4 == "true"
|
||||
elseif fields.blocking ~= nil then
|
||||
meta:set_int("blocking", fields.blocking == "true" and 1 or 0)
|
||||
end
|
||||
meta:set_string("filter", minetest.serialize(filter))
|
||||
|
||||
filter_settings(pos)
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if fields.state_button ~= nil then
|
||||
crd.State:state_button_event(pos, nvm, fields)
|
||||
else
|
||||
meta:set_string("formspec", formspec(crd.State, pos, nvm))
|
||||
end
|
||||
end
|
||||
|
||||
-- techage command to turn on/off filter channels
|
||||
local function change_filter_settings(pos, slot, val)
|
||||
local meta = M(pos)
|
||||
local filter = minetest.deserialize(meta:get_string("filter")) or {false,false,false,false}
|
||||
local num = SlotNumbers[slot] or 1
|
||||
if num >= 1 and num <= 4 then
|
||||
filter[num] = val == "on"
|
||||
end
|
||||
meta:set_string("filter", minetest.serialize(filter))
|
||||
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
FilterCache[hash] = nil
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
meta:set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
return true
|
||||
end
|
||||
|
||||
-- techage command to read filter channel status (on/off)
|
||||
local function read_filter_settings(pos, slot)
|
||||
local filter = minetest.deserialize(M(pos):get_string("filter")) or {false,false,false,false}
|
||||
return filter[SlotNumbers[slot]] and "on" or "off"
|
||||
end
|
||||
|
||||
local function get_payload_values(payload)
|
||||
local color
|
||||
local idx = 0
|
||||
local items = {ItemStack(""), ItemStack(""), ItemStack(""), ItemStack(""), ItemStack(""), ItemStack("")}
|
||||
for s in payload:gmatch("[^%s]+") do --- white spaces
|
||||
if not color then
|
||||
if SlotNumbers[s] then
|
||||
color = s
|
||||
else
|
||||
return "red", {}
|
||||
end
|
||||
else
|
||||
idx = idx + 1
|
||||
if idx <= 6 then
|
||||
items[idx] = ItemStack(s)
|
||||
end
|
||||
end
|
||||
end
|
||||
return color, items
|
||||
end
|
||||
|
||||
local function str_of_inv_items(pos, color)
|
||||
color = SlotColors[color] or color
|
||||
if SlotNumbers[color] then
|
||||
local inv = M(pos):get_inventory()
|
||||
local t = {}
|
||||
for idx = 1, 6 do
|
||||
local item = inv:get_stack(color, idx)
|
||||
if item:get_count() > 0 then
|
||||
t[#t + 1] = item:get_name()
|
||||
end
|
||||
end
|
||||
return table.concat(t, " ")
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("src")
|
||||
end
|
||||
|
||||
local get_tiles = function(is_hp)
|
||||
local variant = is_hp and "_hp" or ""
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_appl_distri.png^techage_frame_ta#_top"..variant..".png^techage_appl_color_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top"..variant..".png^(techage_appl_color_top.png^[transformFY)",
|
||||
"techage_filling_ta#.png^techage_frame_ta#"..variant..".png^techage_appl_distri_yellow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#"..variant..".png^techage_appl_distri_green.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#"..variant..".png^techage_appl_distri_red.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#"..variant..".png^techage_appl_distri_blue.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
{
|
||||
name = "techage_filling4_ta#.png^techage_appl_distri4.png^techage_frame4_ta#_top"..variant..".png^techage_appl_color_top4.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 1.0,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top"..variant..".png^(techage_appl_color_top.png^[transformFY)",
|
||||
"techage_filling_ta#.png^techage_frame_ta#"..variant..".png^techage_appl_distri_yellow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#"..variant..".png^techage_appl_distri_green.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#"..variant..".png^techage_appl_distri_red.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#"..variant..".png^techage_appl_distri_blue.png",
|
||||
}
|
||||
return tiles
|
||||
end
|
||||
|
||||
local tubing = {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "src", num)
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
CRD(pos).State:start_if_standby(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "src", stack)
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "src", stack)
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "info" then
|
||||
return INFO
|
||||
elseif topic == "port" then
|
||||
-- "red"/"green"/"blue"/"yellow" = "on"/"off"
|
||||
local slot, val = techage.ident_value(payload)
|
||||
if val == "" then
|
||||
return read_filter_settings(pos, slot)
|
||||
else
|
||||
return change_filter_settings(pos, slot, val)
|
||||
end
|
||||
elseif topic == "config" then
|
||||
local color, items = get_payload_values(payload)
|
||||
local inv = M(pos):get_inventory()
|
||||
for idx,item in ipairs(items) do
|
||||
inv:set_stack(color, idx, item)
|
||||
end
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
FilterCache[hash] = nil
|
||||
return true
|
||||
elseif topic == "get" then
|
||||
return str_of_inv_items(pos, payload)
|
||||
else
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
if topic == 4 then
|
||||
local slot = SlotColors[payload[1]]
|
||||
local state = payload[2] == 1 and "on" or "off"
|
||||
change_filter_settings(pos, slot, state)
|
||||
return 0
|
||||
elseif topic == 67 then
|
||||
local color, items = get_payload_values(payload)
|
||||
local inv = M(pos):get_inventory()
|
||||
for idx,item in ipairs(items) do
|
||||
inv:set_stack(color, idx, item)
|
||||
end
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
FilterCache[hash] = nil
|
||||
return 0
|
||||
else
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
if topic == 148 then
|
||||
return 0, str_of_inv_items(pos, payload[1])
|
||||
else
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local def = {
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = M(pos)
|
||||
local filter = {false,false,false,false}
|
||||
meta:set_string("filter", minetest.serialize(filter))
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('src', 8)
|
||||
inv:set_size('yellow', 6)
|
||||
inv:set_size('green', 6)
|
||||
inv:set_size('red', 6)
|
||||
inv:set_size('blue', 6)
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
tubelib2_on_update2 = tubelib2_on_update2,
|
||||
|
||||
on_metadata_inventory_move = function(pos, from_list, from_index, to_list)
|
||||
if from_list ~= "src" or to_list ~= "src" then
|
||||
filter_settings(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
end,
|
||||
on_metadata_inventory_put = function(pos, listname)
|
||||
if listname ~= "src" then
|
||||
filter_settings(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
end,
|
||||
on_metadata_inventory_take = function(pos, listname)
|
||||
if listname ~= "src" then
|
||||
filter_settings(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
end,
|
||||
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,4,12,24},
|
||||
tube_sides = {B=1, R=1, F=1, L=1, D=1, U=1}
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 = techage.register_consumer(
|
||||
"distributor",
|
||||
S("Distributor"),
|
||||
get_tiles(false),
|
||||
def
|
||||
)
|
||||
|
||||
local hp_def = table.copy(def)
|
||||
|
||||
hp_def.after_place_node = function(pos, placer)
|
||||
local meta = M(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.high_performance = true
|
||||
local filter = {false,false,false,false}
|
||||
meta:set_string("filter", minetest.serialize(filter))
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('src', 8)
|
||||
inv:set_size('yellow', 8)
|
||||
inv:set_size('green', 8)
|
||||
inv:set_size('red', 8)
|
||||
inv:set_size('blue', 8)
|
||||
end
|
||||
hp_def.num_items = {0,0,0,36}
|
||||
|
||||
local _, _, node_name_ta4_hp = techage.register_consumer(
|
||||
"high_performance_distributor", S("High Performance Distributor"),
|
||||
get_tiles(true),
|
||||
hp_def,
|
||||
{false, false, false, true}
|
||||
)
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2.." 2",
|
||||
recipe = {
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
{"techage:tubeS", "default:mese_crystal", "techage:tubeS"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "techage:iron_ingot", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "techage:iron_ingot", ""},
|
||||
{"", node_name_ta3, ""},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4_hp,
|
||||
recipe = {
|
||||
{node_name_ta4, "default:copper_ingot"},
|
||||
{"default:mese_crystal_fragment", node_name_ta4},
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,314 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2/TA3/TA4 Electronic Fab
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
|
||||
local S = techage.S
|
||||
local STANDBY_TICKS = 3
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 6
|
||||
|
||||
local recipes = techage.recipes
|
||||
|
||||
local RecipeType = {
|
||||
[2] = "ta2_electronic_fab",
|
||||
[3] = "ta3_electronic_fab",
|
||||
[4] = "ta4_electronic_fab",
|
||||
}
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
local rtype = RecipeType[CRD(pos).stage]
|
||||
local owner = M(pos):get_string("owner")
|
||||
return "size[8.4,8.4]"..
|
||||
"list[context;src;0,0;2,4;]"..
|
||||
recipes.formspec(2.2, 0, rtype, nvm, owner)..
|
||||
"list[context;dst;6.4,0;2,4;]"..
|
||||
"image_button[3.7,3.3;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[3.7,3.3;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[current_player;main;0.2,4.5;8,4;]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(0.2, 4.5)
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
local crd = CRD(pos)
|
||||
if listname == "src" then
|
||||
crd.State:start_if_standby(pos)
|
||||
return stack:get_count()
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
return allow_metadata_inventory_put(pos, to_list, to_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
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function get_original_waste(inv, waste)
|
||||
-- Waste has meta data, so we need to find the original waste item
|
||||
for i = 1, 8 do
|
||||
local stack = inv:get_stack("src", i)
|
||||
if stack:get_count() == 1 then
|
||||
if stack:get_name() == waste:get_name() then
|
||||
return stack
|
||||
end
|
||||
end
|
||||
end
|
||||
return waste
|
||||
end
|
||||
|
||||
local function making(pos, crd, nvm, inv)
|
||||
local owner = M(pos):get_string("owner")
|
||||
local rtype = RecipeType[crd.stage]
|
||||
local recipe = recipes.get(nvm, rtype, owner)
|
||||
local output = ItemStack(recipe.output.name .. " " .. recipe.output.num)
|
||||
local waste = recipe.waste and ItemStack(recipe.waste.name .. " " .. recipe.waste.num)
|
||||
if inv:room_for_item("dst", output) and (not waste or inv:room_for_item("dst", waste)) then
|
||||
for _,item in ipairs(recipe.input) do
|
||||
local input = ItemStack(item.name.." "..item.num)
|
||||
if not inv:contains_item("src", input) then
|
||||
crd.State:idle(pos, nvm)
|
||||
return
|
||||
end
|
||||
end
|
||||
-- For some recipes, an item customized via metadata is used as a copy template.
|
||||
-- This allows specially programmed items such as ROM chips to be produced.
|
||||
-- The metadata of the copy template must be passed to the on_production function.
|
||||
-- At the same time, the metadata of the copy template must not be lost when moving
|
||||
-- as 'waste' to the output inventory.
|
||||
local idef = minetest.registered_items[recipe.output.name]
|
||||
if waste and idef and idef.on_production then
|
||||
waste = get_original_waste(inv, waste)
|
||||
local metadata = waste:get_meta():to_table().fields or {}
|
||||
output = idef.on_production(output, metadata)
|
||||
end
|
||||
for _,item in ipairs(recipe.input) do
|
||||
local input = ItemStack(item.name.." "..item.num)
|
||||
inv:remove_item("src", input)
|
||||
end
|
||||
inv:add_item("dst", output)
|
||||
if waste then
|
||||
inv:add_item("dst", waste)
|
||||
end
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
return
|
||||
end
|
||||
crd.State:idle(pos, nvm)
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
if inv then
|
||||
making(pos, crd, nvm, inv)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
|
||||
if not nvm.running then
|
||||
recipes.on_receive_fields(pos, formname, fields, player)
|
||||
end
|
||||
|
||||
crd.State:state_button_event(pos, nvm, fields)
|
||||
M(pos):set_string("formspec", formspec(crd.State, pos, nvm))
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("dst") and inv:is_empty("src")
|
||||
end
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_electronic_fab.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_electronic_fab.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
{
|
||||
name = "techage_filling4_ta#.png^techage_appl_electronic_fab4.png^techage_frame4_ta#.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.5,
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "techage_filling4_ta#.png^techage_appl_electronic_fab4.png^techage_frame4_ta#.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.5,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
if access_type == "push" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
return meta:get_inventory(), "src"
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "dst", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack, idx)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
local inv = M(pos):get_inventory()
|
||||
--CRD(pos).State:start_if_standby(pos) -- would need power!
|
||||
return techage.put_items(inv, "src", stack, idx)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "dst", stack)
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("electronic_fab", S("Electronic Fab"), tiles, {
|
||||
drawtype = "normal",
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size("src", 8)
|
||||
inv:set_size("dst", 8)
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,1,1,1},
|
||||
power_consumption = {0,8,12,12},
|
||||
},
|
||||
{false, true, true, true}) -- TA2/TA3/TA4
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2,
|
||||
recipe = {
|
||||
{"group:wood", "default:diamond", "group:wood"},
|
||||
{"techage:tubeS", "basic_materials:gear_steel", "techage:tubeS"},
|
||||
{"group:wood", "default:steel_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "default:diamond", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "default:diamond", ""},
|
||||
{"", node_name_ta3, ""},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
||||
|
||||
techage.recipes.register_craft_type("ta2_electronic_fab", {
|
||||
description = S("TA2 Ele Fab"),
|
||||
icon = 'techage_filling_ta2.png^techage_appl_electronic_fab.png^techage_frame_ta2.png',
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
||||
techage.recipes.register_craft_type("ta3_electronic_fab", {
|
||||
description = S("TA3 Ele Fab"),
|
||||
icon = 'techage_filling_ta3.png^techage_appl_electronic_fab.png^techage_frame_ta3.png',
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
||||
techage.recipes.register_craft_type("ta4_electronic_fab", {
|
||||
description = S("TA4 Ele Fab"),
|
||||
icon = 'techage_filling_ta4.png^techage_appl_electronic_fab.png^techage_frame_ta4.png',
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
||||
@@ -0,0 +1,445 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Forceload block
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S = techage.S
|
||||
|
||||
-- Global registry so admins can see all forceload blocks, even for offline players
|
||||
-- Keys use "flb_<pos>" prefix on techage.storage to avoid collisions with
|
||||
-- other users of the shared mod_storage (numbers, nodedata, etc.)
|
||||
local function registry_add(pos, owner)
|
||||
techage.storage:set_string("flb_" .. P2S(pos), owner)
|
||||
end
|
||||
|
||||
local function registry_remove(pos)
|
||||
techage.storage:set_string("flb_" .. P2S(pos), "")
|
||||
end
|
||||
|
||||
local function registry_get_all()
|
||||
local entries = {}
|
||||
for key, val in pairs(techage.storage:to_table().fields) do
|
||||
if val ~= "" and key:sub(1, 4) == "flb_" then
|
||||
local pos = minetest.string_to_pos(key:sub(5))
|
||||
if pos then
|
||||
entries[#entries+1] = {pos = pos, owner = val}
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(entries, function(a, b)
|
||||
if a.owner ~= b.owner then return a.owner < b.owner end
|
||||
return P2S(a.pos) < P2S(b.pos)
|
||||
end)
|
||||
return entries
|
||||
end
|
||||
|
||||
local function calc_area(pos)
|
||||
local xpos = (math.floor(pos.x / 16) * 16)
|
||||
local ypos = (math.floor(pos.y / 16) * 16)
|
||||
local zpos = (math.floor(pos.z / 16) * 16)
|
||||
local pos1 = {x=xpos, y=ypos, z=zpos}
|
||||
local pos2 = {x=xpos+15, y=ypos+15, z=zpos+15}
|
||||
return pos1, pos2
|
||||
end
|
||||
|
||||
local function in_list(list, x)
|
||||
local pos1 = calc_area(x)
|
||||
for _,v in ipairs(list) do
|
||||
local pos2 = calc_area(v)
|
||||
if vector.equals(pos1, pos2) then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function remove_list_elem(list, x)
|
||||
local n = nil
|
||||
for idx, v in ipairs(list) do
|
||||
if vector.equals(v, x) then
|
||||
n = idx
|
||||
break
|
||||
end
|
||||
end
|
||||
if n then
|
||||
table.remove(list, n)
|
||||
end
|
||||
return list
|
||||
end
|
||||
|
||||
local function chat(player, text)
|
||||
minetest.chat_send_player(player:get_player_name(), "[Techage] "..text)
|
||||
end
|
||||
|
||||
local function postload_area(pos)
|
||||
minetest.log("warning", "[FLB] area "..P2S(pos).." not loaded!")
|
||||
if not minetest.forceload_block(pos, true) then
|
||||
minetest.after(60, postload_area, pos)
|
||||
end
|
||||
end
|
||||
|
||||
local function add_pos(pos, player)
|
||||
local meta = player:get_meta()
|
||||
local lPos = minetest.deserialize(meta:get_string("techage_forceload_blocks")) or {}
|
||||
if not in_list(lPos, pos) and (#lPos < techage.max_num_forceload_blocks or
|
||||
minetest.global_exists("creative") and creative.is_enabled_for and
|
||||
creative.is_enabled_for(player:get_player_name())) then
|
||||
lPos[#lPos+1] = pos
|
||||
local meta = player:get_meta()
|
||||
meta:set_string("techage_forceload_blocks", minetest.serialize(lPos))
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function del_pos(pos, player)
|
||||
local meta = player:get_meta()
|
||||
local lPos = minetest.deserialize(meta:get_string("techage_forceload_blocks")) or {}
|
||||
lPos = remove_list_elem(lPos, pos)
|
||||
if next(lPos) then
|
||||
meta:set_string("techage_forceload_blocks", minetest.serialize(lPos))
|
||||
else
|
||||
meta:set_string("techage_forceload_blocks", "")
|
||||
end
|
||||
end
|
||||
|
||||
local function get_pos_list(player)
|
||||
local meta = player:get_meta()
|
||||
return minetest.deserialize(meta:get_string("techage_forceload_blocks")) or {}
|
||||
end
|
||||
|
||||
local function set_pos_list(player, lPos)
|
||||
local meta = player:get_meta()
|
||||
if next(lPos) then
|
||||
meta:set_string("techage_forceload_blocks", minetest.serialize(lPos))
|
||||
else
|
||||
meta:set_string("techage_forceload_blocks", "")
|
||||
end
|
||||
end
|
||||
|
||||
local function show_flbs(pos, name, range)
|
||||
local pos1 = {x=pos.x-range, y=pos.y-range, z=pos.z-range}
|
||||
local pos2 = {x=pos.x+range, y=pos.y+range, z=pos.z+range}
|
||||
for _,npos in ipairs(minetest.find_nodes_in_area(pos1, pos2, {"techage:forceload", "techage:forceloadtile"})) do
|
||||
local _pos1, _pos2 = calc_area(npos)
|
||||
local owner = M(npos):get_string("owner")
|
||||
techage.mark_region(name, _pos1, _pos2, owner .. " " .. P2S(npos))
|
||||
end
|
||||
end
|
||||
|
||||
local function get_data(pos, player)
|
||||
local pos1, pos2 = calc_area(pos)
|
||||
local meta = player:get_meta()
|
||||
local num = #minetest.deserialize(meta:get_string("techage_forceload_blocks")) or 0
|
||||
local max = techage.max_num_forceload_blocks
|
||||
return pos1, pos2, num, max
|
||||
end
|
||||
|
||||
local function formspec(name)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
local lPos = get_pos_list(player)
|
||||
local tRes = {}
|
||||
tRes[#tRes+1] = "#"
|
||||
tRes[#tRes+1] = S("Block at pos")
|
||||
tRes[#tRes+1] = S("Area from")
|
||||
tRes[#tRes+1] = S("Area to")
|
||||
tRes[#tRes+1] = S("Status")
|
||||
for idx,pos in ipairs(lPos) do
|
||||
local pos1, pos2 = calc_area(pos)
|
||||
tRes[#tRes+1] = idx
|
||||
tRes[#tRes+1] = minetest.formspec_escape(P2S(pos))
|
||||
tRes[#tRes+1] = minetest.formspec_escape(P2S(pos1))
|
||||
tRes[#tRes+1] = minetest.formspec_escape(P2S(pos2))
|
||||
tRes[#tRes+1] = minetest.forceload_block(pos, true) and 'Loaded' or 'Unloaded'
|
||||
end
|
||||
return "size[9,9]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"label[0,0;"..S("List of your Forceload Blocks:").."]"..
|
||||
"tablecolumns[text,width=1.8;text,width=12;text,width=12;text,width=12;text,width=12]"..
|
||||
"table[0,0.6;8.8,8.4;output;"..table.concat(tRes, ",")..";1]"
|
||||
end
|
||||
end
|
||||
|
||||
local function on_place(itemstack, placer, pointed_thing)
|
||||
if pointed_thing.type ~= "node" then
|
||||
return itemstack
|
||||
end
|
||||
return minetest.rotate_and_place(itemstack, placer, pointed_thing)
|
||||
end
|
||||
|
||||
local function after_place_node(pos, placer, itemstack)
|
||||
if add_pos(pos, placer) then
|
||||
minetest.forceload_block(pos, true)
|
||||
local pos1, pos2, num, max = get_data(pos, placer)
|
||||
M(pos):set_string("infotext", "Area "..P2S(pos1).." to "..P2S(pos2).." "..S("loaded").."!\n"..
|
||||
S("Punch the block to make the area visible."))
|
||||
chat(placer, "Area ("..num.."/"..max..") "..P2S(pos1).." to "..P2S(pos2).." "..S("loaded").."!")
|
||||
techage.mark_region(placer:get_player_name(), pos1, pos2)
|
||||
M(pos):set_string("owner", placer:get_player_name())
|
||||
registry_add(pos, placer:get_player_name())
|
||||
else
|
||||
chat(placer, S("Area already loaded or max. number of Forceload Blocks reached!"))
|
||||
minetest.remove_node(pos)
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
|
||||
local function after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||
local player = minetest.get_player_by_name(oldmetadata.fields.owner)
|
||||
if player then
|
||||
del_pos(pos, player)
|
||||
end
|
||||
minetest.forceload_free_block(pos, true)
|
||||
techage.unmark_region(oldmetadata.fields.owner)
|
||||
registry_remove(pos)
|
||||
end
|
||||
|
||||
local function on_rightclick(pos, node, clicker, itemstack, pointed_thing)
|
||||
local owner = M(pos):get_string("owner")
|
||||
local name = clicker:get_player_name()
|
||||
if name == owner or minetest.check_player_privs(name, "server") then
|
||||
local s = formspec(owner)
|
||||
if s then
|
||||
minetest.show_formspec(name, "techage:forceload", s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_punch(pos, node, puncher, pointed_thing)
|
||||
local pos1, pos2 = calc_area(pos)
|
||||
techage.switch_region(puncher:get_player_name(), pos1, pos2)
|
||||
end
|
||||
|
||||
minetest.register_node("techage:forceload", {
|
||||
description = S("Techage Forceload Block"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
'techage_filling_ta2.png^techage_frame_ta2_top.png',
|
||||
'techage_filling_ta2.png^techage_frame_ta2_top.png',
|
||||
{
|
||||
name = "techage_filling_ta2.png^techage_frame_ta2_top.png^techage_appl_forceload.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.5,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
on_rightclick = on_rightclick,
|
||||
on_punch = on_punch,
|
||||
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
use_texture_alpha = techage.CLIP,
|
||||
groups = {choppy=2, cracky=2, crumbly=2,
|
||||
digtron_protected = 1,
|
||||
not_in_creative_inventory = techage.max_num_forceload_blocks == 0 and 1 or 0},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("techage:forceloadtile", {
|
||||
description = S("Techage Forceload Tile"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
{
|
||||
name = "techage_filling_ta2.png^techage_frame_ta2_top.png^techage_appl_forceload.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.5,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
--{-5/16, -7/16, -5/16, 5/16, -5/16, 5/16},
|
||||
{-4/16, -8/16, -4/16, 4/16, -15/32, 4/16},
|
||||
},
|
||||
},
|
||||
|
||||
on_place = on_place,
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
on_rightclick = on_rightclick,
|
||||
on_punch = on_punch,
|
||||
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
sunlight_propagates = true,
|
||||
groups = {choppy=2, cracky=2, crumbly=2,
|
||||
not_in_creative_inventory = techage.max_num_forceload_blocks == 0 and 1 or 0},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
if techage.max_num_forceload_blocks > 0 then
|
||||
minetest.register_craft({
|
||||
output = "techage:forceload",
|
||||
recipe = {
|
||||
{"group:wood", "", "group:wood"},
|
||||
{"default:mese_crystal_fragment", "techage:usmium_nuggets", "default:mese_crystal_fragment"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:forceloadtile",
|
||||
recipe = {"techage:forceload"},
|
||||
})
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:forceload",
|
||||
recipe = {"techage:forceloadtile"},
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local lPos = {}
|
||||
local name = player:get_player_name()
|
||||
for _,pos in ipairs(get_pos_list(player)) do
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if node.name == "techage:forceload" or node.name == "techage:forceloadtile" then
|
||||
if not minetest.forceload_block(pos, true) then
|
||||
minetest.after(60, postload_area, pos)
|
||||
end
|
||||
lPos[#lPos+1] = pos
|
||||
-- Populate registry for blocks placed before the registry existed
|
||||
if techage.storage:get_string("flb_" .. P2S(pos)) == "" then
|
||||
registry_add(pos, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
set_pos_list(player, lPos)
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
for _,pos in ipairs(get_pos_list(player)) do
|
||||
minetest.forceload_free_block(pos, true)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
local function admin_formspec()
|
||||
local entries = registry_get_all()
|
||||
local engine_limit = tonumber(minetest.settings:get("max_forceloaded_blocks")) or 16
|
||||
local per_player = techage.max_num_forceload_blocks
|
||||
local total = #entries
|
||||
|
||||
local warn
|
||||
if total >= engine_limit then
|
||||
warn = "label[0,0.5;\27(c@#FF4444)WARNING: Engine limit reached (" ..
|
||||
total .. "/" .. engine_limit .. ")! No new forceload blocks can be placed!]"
|
||||
elseif total >= math.floor(engine_limit * 0.8) then
|
||||
warn = "label[0,0.5;\27(c@#FFA500)Notice: " ..
|
||||
total .. " of " .. engine_limit .. " engine-level slots in use (80 %+ full).]"
|
||||
else
|
||||
warn = "label[0,0.5;Engine limit: " .. engine_limit ..
|
||||
" Per-player limit: " .. per_player .. "]"
|
||||
end
|
||||
|
||||
local tRes = {}
|
||||
tRes[#tRes+1] = "#"
|
||||
tRes[#tRes+1] = "Owner"
|
||||
tRes[#tRes+1] = "Position"
|
||||
tRes[#tRes+1] = "Online"
|
||||
for idx, e in ipairs(entries) do
|
||||
local online = minetest.get_player_by_name(e.owner) ~= nil
|
||||
tRes[#tRes+1] = idx
|
||||
tRes[#tRes+1] = minetest.formspec_escape(e.owner)
|
||||
tRes[#tRes+1] = minetest.formspec_escape(P2S(e.pos))
|
||||
tRes[#tRes+1] = online and "yes" or "no"
|
||||
end
|
||||
return "size[9,9.5]" ..
|
||||
default.gui_bg ..
|
||||
default.gui_bg_img ..
|
||||
default.gui_slots ..
|
||||
"label[0,0;Forceload Blocks: " .. total .. " total | Engine limit: " .. engine_limit ..
|
||||
" | Per-player limit: " .. per_player .. "]" ..
|
||||
warn ..
|
||||
"tablecolumns[text,width=1.8;text,width=10;text,width=10;text,width=5]" ..
|
||||
"table[0,1.1;8.8,8.4;flb_admin;" .. table.concat(tRes, ",") .. ";1]"
|
||||
end
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname ~= "techage:forceload_admin" then return end
|
||||
if fields.flb_admin then
|
||||
local event = minetest.explode_table_event(fields.flb_admin)
|
||||
if event.type == "DCL" then
|
||||
local idx = event.row - 1 -- row 1 is the header
|
||||
if idx >= 1 and minetest.check_player_privs(player:get_player_name(), "server") then
|
||||
local entries = registry_get_all()
|
||||
local entry = entries[idx]
|
||||
if entry then
|
||||
player:set_pos(entry.pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_chatcommand("forceload_admin", {
|
||||
params = "",
|
||||
description = "[Admin] Show all forceload blocks on the server; double-click to teleport",
|
||||
privs = {server = true},
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
minetest.show_formspec(name, "techage:forceload_admin", admin_formspec())
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("forceload", {
|
||||
params = "",
|
||||
description = S("Show all forceload blocks in a 64x64x64 range"),
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
local pos = player:get_pos()
|
||||
pos = vector.round(pos)
|
||||
show_flbs(pos, name, 64)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("forceload_verify", {
|
||||
params = "",
|
||||
description = "Checks each forceload block and returns a count of active/placed blocks",
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
local loaded = {}
|
||||
local wanted = get_pos_list(player)
|
||||
for _,pos in ipairs(wanted) do
|
||||
if minetest.forceload_block(pos, true) then
|
||||
loaded[#loaded+1] = pos
|
||||
end
|
||||
end
|
||||
minetest.chat_send_player(name, "Found "..#loaded.." out of ".. #wanted .. " force loads")
|
||||
end
|
||||
end,
|
||||
})
|
||||
@@ -0,0 +1,129 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Tube support for default chests and furnace
|
||||
|
||||
]]--
|
||||
|
||||
local OwnerCache = {
|
||||
}
|
||||
|
||||
-- Check if the chest is in the protected area of the owner
|
||||
local function is_owner(pos, meta)
|
||||
local owner = meta:get_string("owner")
|
||||
local key = minetest.hash_node_position(pos)
|
||||
-- If successfull, store info in cache
|
||||
if OwnerCache[key] ~= owner then
|
||||
if not minetest.is_protected(pos, owner) then
|
||||
OwnerCache[key] = owner
|
||||
end
|
||||
end
|
||||
return OwnerCache[key] == owner
|
||||
end
|
||||
|
||||
|
||||
techage.register_node({"default:chest", "default:chest_open"}, {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return meta:get_inventory(), "main"
|
||||
end,
|
||||
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({"default:chest_locked", "default:chest_locked_open"}, {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if is_owner(pos, meta) then
|
||||
return meta:get_inventory(), "main"
|
||||
end
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if is_owner(pos, meta) then
|
||||
local inv = meta:get_inventory()
|
||||
return techage.get_items(pos, inv, "main", num)
|
||||
end
|
||||
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({"default:furnace", "default:furnace_active"}, {
|
||||
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, "dst", num)
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
minetest.get_node_timer(pos):start(1.0)
|
||||
if in_dir == 5 then
|
||||
return techage.put_items(inv, "src", stack)
|
||||
elseif minetest.get_craft_result({method="fuel", width=1, items={stack}}).time ~= 0 then
|
||||
return techage.put_items(inv, "fuel", stack)
|
||||
else
|
||||
return techage.put_items(inv, "src", stack)
|
||||
end
|
||||
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, "dst", stack)
|
||||
end,
|
||||
})
|
||||
|
||||
techage.register_node({"mobs:beehive"}, {
|
||||
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, "beehive", num)
|
||||
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, "beehive", stack)
|
||||
end,
|
||||
})
|
||||
|
||||
techage.register_node({"xdecor:hive"}, {
|
||||
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, "honey", num)
|
||||
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, "honey", stack)
|
||||
end,
|
||||
})
|
||||
@@ -0,0 +1,341 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2 Gravel Rinser, washing sieved gravel to find more ores
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
|
||||
local STANDBY_TICKS = 3
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 4
|
||||
|
||||
local Probability = {}
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
return "size[8,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;src;0,0;3,3;]"..
|
||||
"item_image[0,0;1,1;default:gravel]"..
|
||||
"image[0,0;1,1;techage_form_mask.png]"..
|
||||
"image[3.5,0;1,1;"..techage.get_power_image(pos, nvm).."]"..
|
||||
"image[3.5,1;1,1;techage_form_arrow.png]"..
|
||||
"image_button[3.5,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[3.5,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[context;dst;5,0;3,3;]"..
|
||||
"list[current_player;main;0,4;8,4;]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(0, 4)
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
if listname == "src" then
|
||||
CRD(pos).State:start_if_standby(pos)
|
||||
return stack:get_count()
|
||||
elseif listname == "dst" then
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
return allow_metadata_inventory_put(pos, to_list, to_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
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
|
||||
local function get_water_level(pos)
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if minetest.get_item_group(node.name, "water") > 0 then
|
||||
local ndef = minetest.registered_nodes[node.name]
|
||||
if ndef and ndef.liquidtype == "flowing" then
|
||||
return node.param2
|
||||
end
|
||||
end
|
||||
return 99
|
||||
end
|
||||
|
||||
local function determine_water_dir(pos)
|
||||
local lvl = get_water_level(pos)
|
||||
if lvl > get_water_level({x=pos.x+1, y=pos.y, z=pos.z}) then
|
||||
return 2
|
||||
end
|
||||
if lvl > get_water_level({x=pos.x-1, y=pos.y, z=pos.z}) then
|
||||
return 4
|
||||
end
|
||||
if lvl > get_water_level({x=pos.x, y=pos.y, z=pos.z+1}) then
|
||||
return 1
|
||||
end
|
||||
if lvl > get_water_level({x=pos.x, y=pos.y, z=pos.z-1}) then
|
||||
return 3
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
local function set_velocity(obj, pos, vel)
|
||||
if obj then
|
||||
obj:set_acceleration({x = 0, y = 0, z = 0})
|
||||
local p = obj:get_pos()
|
||||
if p then
|
||||
obj:set_pos({x=p.x, y=p.y-0.3, z=p.z})
|
||||
obj:set_velocity(vel)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function add_object(pos, name)
|
||||
local dir = determine_water_dir(pos)
|
||||
if dir > 0 then
|
||||
local obj = minetest.add_item(pos, ItemStack(name))
|
||||
local vel = vector.multiply(tubelib2.Dir6dToVector[dir], 0.3)
|
||||
minetest.after(0.3, set_velocity, obj, pos, vel)
|
||||
end
|
||||
end
|
||||
|
||||
local function get_random_gravel_ore()
|
||||
for ore, probability in pairs(Probability) do
|
||||
if math.random(probability) == 1 then
|
||||
return ore
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function remove_objects(pos)
|
||||
for _, object in pairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||
local lua_entity = object:get_luaentity()
|
||||
if not object:is_player() and lua_entity and lua_entity.name == "__builtin:item" then
|
||||
object:remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function washing(pos, crd, nvm, inv)
|
||||
-- for testing purposes
|
||||
if inv:contains_item("src", ItemStack("default:stick")) then
|
||||
add_object({x=pos.x, y=pos.y+1, z=pos.z}, "default:stick")
|
||||
inv:remove_item("src", ItemStack("default:stick"))
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
return
|
||||
end
|
||||
|
||||
local src = ItemStack("techage:sieved_gravel")
|
||||
local dst = ItemStack("default:sand")
|
||||
if inv:contains_item("src", src) then
|
||||
if not inv:room_for_item("dst", dst) then
|
||||
crd.State:blocked(pos, nvm)
|
||||
return
|
||||
end
|
||||
local ore = get_random_gravel_ore()
|
||||
if ore then
|
||||
add_object({x=pos.x, y=pos.y+1, z=pos.z}, ore)
|
||||
end
|
||||
inv:add_item("dst", dst)
|
||||
inv:remove_item("src", src)
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
return
|
||||
else
|
||||
crd.State:idle(pos, nvm)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
washing(pos, crd, nvm, inv)
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("dst") and inv:is_empty("src")
|
||||
end
|
||||
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_appl_rinser_top.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_rinser.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_rinser.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
{
|
||||
name = "techage_appl_rinser4_top.png^techage_frame4_ta#_top.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_rinser.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_rinser.png^techage_frame_ta#.png",
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "dst", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
local inv = M(pos):get_inventory()
|
||||
-- CRD(pos).State:start_if_standby(pos) -- would need power!
|
||||
return techage.put_items(inv, "src", stack)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "dst", stack)
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
remove_objects({x=pos.x, y=pos.y+1, z=pos.z})
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("rinser", S("Gravel Rinser"), tiles, {
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-8/16, -8/16, -8/16, 8/16, 8/16, -6/16},
|
||||
{-8/16, -8/16, 6/16, 8/16, 8/16, 8/16},
|
||||
{-8/16, -8/16, -8/16, -6/16, 8/16, 8/16},
|
||||
{ 6/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-6/16, -8/16, -6/16, 6/16, 6/16, 6/16},
|
||||
{-6/16, 6/16, -1/16, 6/16, 8/16, 1/16},
|
||||
{-1/16, 6/16, -6/16, 1/16, 8/16, 6/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('src', 9)
|
||||
inv:set_size('dst', 9)
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,1,1,1},
|
||||
power_consumption = {0,3,3,3},
|
||||
tube_sides = {L=1, R=1, U=1},
|
||||
},
|
||||
{false, true, true, false}) -- TA2/TA3
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2,
|
||||
recipe = {
|
||||
{"group:wood", "default:mese_crystal", "group:wood"},
|
||||
{"techage:tubeS", "techage:sieve", "techage:tubeS"},
|
||||
{"group:wood", "default:tin_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
techage.recipes.register_craft_type("rinsing", {
|
||||
description = S("Rinsing"),
|
||||
icon = "techage_appl_rinser_top.png^techage_frame_ta2_top.png",
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
||||
|
||||
function techage.add_rinser_recipe(recipe)
|
||||
Probability[recipe.output] = recipe.probability
|
||||
recipe.items = {recipe.input}
|
||||
recipe.type = "rinsing"
|
||||
techage.recipes.register_craft(recipe)
|
||||
end
|
||||
|
||||
techage.add_rinser_recipe({input="techage:sieved_gravel", output="techage:usmium_nuggets", probability=30})
|
||||
techage.add_rinser_recipe({input="techage:sieved_gravel", output="default:copper_lump", probability=15})
|
||||
@@ -0,0 +1,298 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2/TA3/TA4 Gravel Sieve, sieving gravel to find ores
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
|
||||
local STANDBY_TICKS = 3
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 4
|
||||
|
||||
local get_random_gravel_ore = techage.gravelsieve_get_random_gravel_ore
|
||||
local get_random_basalt_ore = techage.gravelsieve_get_random_basalt_ore
|
||||
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
return "size[8,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;src;0,0;3,3;]"..
|
||||
"item_image[0,0;1,1;default:gravel]"..
|
||||
"image[0,0;1,1;techage_form_mask.png]"..
|
||||
"image[3.5,0;1,1;"..techage.get_power_image(pos, nvm).."]"..
|
||||
"image[3.5,1;1,1;techage_form_arrow.png]"..
|
||||
"image_button[3.5,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[3.5,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[context;dst;5,0;3,3;]"..
|
||||
"list[current_player;main;0,4;8,4;]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(0, 4)
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
if listname == "src" then
|
||||
CRD(pos).State:start_if_standby(pos)
|
||||
return stack:get_count()
|
||||
elseif listname == "dst" then
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local inv = M(pos):get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
return allow_metadata_inventory_put(pos, to_list, to_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
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local sieving_recipes = {}
|
||||
|
||||
function techage.register_sieving_recipe(material, get_ore_func)
|
||||
sieving_recipes[ItemStack(material)] = get_ore_func
|
||||
end
|
||||
|
||||
techage.register_sieving_recipe("techage:basalt_gravel", get_random_basalt_ore)
|
||||
techage.register_sieving_recipe("default:gravel", get_random_gravel_ore)
|
||||
|
||||
local function sieving(pos, crd, nvm, inv)
|
||||
for i = 1, crd.num_items do
|
||||
local src, dst
|
||||
for input_material, get_ore_func in pairs(sieving_recipes) do
|
||||
if inv:contains_item("src", ItemStack(input_material)) then
|
||||
dst, src = get_ore_func(), ItemStack(input_material)
|
||||
break
|
||||
end
|
||||
end
|
||||
if dst == nil then
|
||||
crd.State:idle(pos, nvm)
|
||||
return
|
||||
end
|
||||
if not inv:room_for_item("dst", dst) then
|
||||
crd.State:idle(pos, nvm)
|
||||
return
|
||||
end
|
||||
inv:add_item("dst", dst)
|
||||
inv:remove_item("src", src)
|
||||
end
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
sieving(pos, crd, nvm, inv)
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("dst") and inv:is_empty("src")
|
||||
end
|
||||
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_appl_sieve_top.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_sieve.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_sieve.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
{
|
||||
name = "techage_appl_sieve4_top.png^techage_frame4_ta#_top.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_sieve.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_sieve.png^techage_frame_ta#.png",
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "dst", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "src", stack)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "dst", stack)
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("gravelsieve", S("Gravel Sieve"), tiles, {
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-8/16, -8/16, -8/16, 8/16, 8/16, -6/16},
|
||||
{-8/16, -8/16, 6/16, 8/16, 8/16, 8/16},
|
||||
{-8/16, -8/16, -8/16, -6/16, 8/16, 8/16},
|
||||
{ 6/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-6/16, -8/16, -6/16, 6/16, 4/16, 6/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('src', 9)
|
||||
inv:set_size('dst', 9)
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,1,2,4},
|
||||
power_consumption = {0,3,4,5},
|
||||
tube_sides = {L=1, R=1, U=1},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2,
|
||||
recipe = {
|
||||
{"group:wood", "default:mese_crystal", "group:wood"},
|
||||
{"techage:tubeS", "techage:sieve", "techage:tubeS"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", node_name_ta3, ""},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
||||
|
||||
techage.recipes.register_craft_type("ta2_gravelsieve", {
|
||||
description = S("TA2 Gravel Sieve"),
|
||||
icon = 'techage_sieve_sieve_ta1.png',
|
||||
width = 1,
|
||||
height = 1,
|
||||
})
|
||||
techage.recipes.register_craft_type("ta3_gravelsieve", {
|
||||
description = S("TA3 Gravel Sieve"),
|
||||
icon = 'techage_filling_ta3.png^techage_appl_sieve.png^techage_frame_ta3.png',
|
||||
width = 1,
|
||||
height = 1,
|
||||
})
|
||||
techage.recipes.register_craft_type("ta4_gravelsieve", {
|
||||
description = S("TA4 Gravel Sieve"),
|
||||
icon = 'techage_filling_ta4.png^techage_appl_sieve.png^techage_frame_ta4.png',
|
||||
width = 1,
|
||||
height = 1,
|
||||
})
|
||||
techage.recipes.register_craft({
|
||||
output = "techage:sieved_basalt_gravel",
|
||||
items = {"techage:basalt_gravel"},
|
||||
type = "ta2_gravelsieve",
|
||||
})
|
||||
techage.recipes.register_craft({
|
||||
output = "techage:sieved_basalt_gravel",
|
||||
items = {"techage:basalt_gravel"},
|
||||
type = "ta3_gravelsieve",
|
||||
})
|
||||
techage.recipes.register_craft({
|
||||
output = "techage:sieved_basalt_gravel",
|
||||
items = {"techage:basalt_gravel"},
|
||||
type = "ta4_gravelsieve",
|
||||
})
|
||||
@@ -0,0 +1,435 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2/TA3/TA4 Grinder, grinding Cobble/Basalt to Gravel
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer or {} end
|
||||
|
||||
local STANDBY_TICKS = 3
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 4
|
||||
|
||||
-- Grinder recipes TA1
|
||||
local RecipesTa1 = {}
|
||||
-- Grinder recipes TA2 - TA4
|
||||
local Recipes = {}
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
return "size[8,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;src;0,0;3,3;]"..
|
||||
"item_image[0,0;1,1;default:cobble]"..
|
||||
"image[0,0;1,1;techage_form_mask.png]"..
|
||||
"image[3.5,0;1,1;"..techage.get_power_image(pos, nvm).."]"..
|
||||
"image[3.5,1;1,1;techage_form_arrow.png]"..
|
||||
"image_button[3.5,2;1,1;"..self:get_state_button_image(nvm)..";state_button;]"..
|
||||
"tooltip[3.5,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[context;dst;5,0;3,3;]"..
|
||||
"item_image[5,0;1,1;default:gravel]"..
|
||||
"image[5,0;1,1;techage_form_mask.png]"..
|
||||
"list[current_player;main;0,4;8,4;]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(0, 4)
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
if listname == "src" then
|
||||
local state = CRD(pos).State
|
||||
if state then
|
||||
state:start_if_standby(pos)
|
||||
end
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local inv = M(pos):get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
return allow_metadata_inventory_put(pos, to_list, to_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
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
-- Grinder normaly handles 'num_items' per cycle. 'num_items' is node stage dependent.
|
||||
-- But if 'inp_num' > 1 (wheat recipes), use 'inp_num' and produce one output item.
|
||||
local function src_to_dst(src_stack, idx, src_name, num_items, inp_num, inv, dst_name)
|
||||
if inp_num > 1 then
|
||||
local input = ItemStack(src_name)
|
||||
input:set_count(inp_num)
|
||||
local output = ItemStack(dst_name)
|
||||
if inv:contains_item("src", input) and inv:room_for_item("dst", output) then
|
||||
inv:remove_item("src", input)
|
||||
inv:add_item("dst", output)
|
||||
return true
|
||||
end
|
||||
else
|
||||
local taken = src_stack:take_item(num_items)
|
||||
local output = ItemStack(dst_name)
|
||||
output:set_count(output:get_count() * taken:get_count())
|
||||
if inv:room_for_item("dst", output) then
|
||||
inv:set_stack("src", idx, src_stack)
|
||||
inv:add_item("dst", output)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function grinding(pos, crd, nvm, inv)
|
||||
local blocked = false -- idle
|
||||
for idx,stack in ipairs(inv:get_list("src")) do
|
||||
if not stack:is_empty() then
|
||||
local name = stack:get_name()
|
||||
if Recipes[name] then
|
||||
local recipe = Recipes[name]
|
||||
if src_to_dst(stack, idx, name, crd.num_items, recipe.inp_num, inv, recipe.output) then
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
return
|
||||
else
|
||||
blocked = true
|
||||
end
|
||||
else
|
||||
crd.State:fault(pos, nvm)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
if blocked then
|
||||
crd.State:blocked(pos, nvm)
|
||||
else
|
||||
crd.State:idle(pos, nvm)
|
||||
end
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
grinding(pos, crd, nvm, inv)
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("dst") and inv:is_empty("src")
|
||||
end
|
||||
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_appl_grinder.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_grinder2.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_grinder2.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
{
|
||||
name = "techage_appl_grinder4.png^techage_frame4_ta#_top.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 1.0,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_grinder2.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_grinder2.png^techage_frame_ta#.png",
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "dst", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
local inv = M(pos):get_inventory()
|
||||
--CRD(pos).State:start_if_standby(pos) -- would need power!
|
||||
return techage.put_items(inv, "src", stack)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "dst", stack)
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("grinder", S("Grinder"), tiles, {
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-8/16, -8/16, -8/16, 8/16, 8/16, -6/16},
|
||||
{-8/16, -8/16, 6/16, 8/16, 8/16, 8/16},
|
||||
{-8/16, -8/16, -8/16, -6/16, 8/16, 8/16},
|
||||
{ 6/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-6/16, -8/16, -6/16, 6/16, 6/16, 6/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('src', 9)
|
||||
inv:set_size('dst', 9)
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,1,2,4},
|
||||
power_consumption = {0,4,6,9},
|
||||
tube_sides = {L=1, R=1, U=1},
|
||||
})
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- TA1 Mill (watermill)
|
||||
-------------------------------------------------------------------------------
|
||||
local formspecStr = "size[8,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;src;1,1;1,1;]"..
|
||||
"item_image[1,1;1,1;farming:wheat]"..
|
||||
"image[1,1;1,1;techage_form_mask.png]"..
|
||||
"image[3.5,1;1,1;techage_form_arrow.png]"..
|
||||
"list[context;dst;6,1;1,1;]"..
|
||||
"item_image[6,1;1,1;farming:flour]"..
|
||||
"image[6,1;1,1;techage_form_mask.png]"..
|
||||
"list[current_player;main;0,4;8,4;]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(0, 4)
|
||||
|
||||
local function node_timer(pos, elapsed)
|
||||
if techage.ta1_mill_has_power(pos, 2) then
|
||||
local inv = M(pos):get_inventory()
|
||||
local stack = inv:get_stack("src", 1)
|
||||
if not stack:is_empty() then
|
||||
local name = stack:get_name()
|
||||
if RecipesTa1[name] then
|
||||
local recipe = RecipesTa1[name]
|
||||
src_to_dst(stack, 1, name, 1, recipe.inp_num, inv, recipe.output)
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
minetest.register_node("techage:ta1_mill_base", {
|
||||
description = S("TA1 Mill Base"),
|
||||
tiles = {
|
||||
"techage_mill_base.png",
|
||||
"default_stone_brick.png",
|
||||
},
|
||||
after_place_node = function(pos, placer)
|
||||
M(pos):set_string("formspec", formspecStr)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('src', 1)
|
||||
inv:set_size('dst', 1)
|
||||
minetest.get_node_timer(pos):start(4)
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
on_timer = node_timer,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_take,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
is_ground_content = false,
|
||||
groups = {cracky = 2, crumbly = 2, choppy = 2},
|
||||
})
|
||||
|
||||
techage.register_node({"techage:ta1_mill_base"}, {
|
||||
on_node_load = function(pos, node)
|
||||
minetest.get_node_timer(pos):start(4)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:ta1_mill_base",
|
||||
recipe = {
|
||||
{"default:stonebrick", "", "default:stonebrick"},
|
||||
{"", "techage:iron_ingot", ""},
|
||||
{"default:stonebrick", "", "default:stonebrick"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2,
|
||||
recipe = {
|
||||
{"group:wood", "default:mese_crystal", "group:wood"},
|
||||
{"techage:tubeS", "techage:hammer_steel", "techage:tubeS"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", node_name_ta3, ""},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
||||
|
||||
techage.recipes.register_craft_type("grinding", {
|
||||
description = S("Grinding"),
|
||||
icon = 'techage_appl_grinder.png',
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
||||
techage.recipes.register_craft_type("milling", {
|
||||
description = S("Milling"),
|
||||
icon = 'techage_mill_inv.png',
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
||||
|
||||
function techage.add_grinder_recipe(recipe, ta1_permitted)
|
||||
local name, num = unpack(string.split(recipe.input, " ", false, 1))
|
||||
if minetest.registered_items[name] then
|
||||
if ta1_permitted then
|
||||
RecipesTa1[name] = {input = name,inp_num = tonumber(num) or 1, output = recipe.output}
|
||||
|
||||
recipe.items = {recipe.input}
|
||||
recipe.type = "milling"
|
||||
techage.recipes.register_craft(table.copy(recipe))
|
||||
end
|
||||
|
||||
Recipes[name] = {input = name,inp_num = tonumber(num) or 1, output = recipe.output}
|
||||
|
||||
recipe.items = {recipe.input}
|
||||
recipe.type = "grinding"
|
||||
techage.recipes.register_craft(recipe)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
techage.add_grinder_recipe({input="default:cobble", output="default:gravel"})
|
||||
techage.add_grinder_recipe({input="default:desert_cobble", output="default:gravel"})
|
||||
techage.add_grinder_recipe({input="default:mossycobble", output="default:gravel"})
|
||||
techage.add_grinder_recipe({input="default:gravel", output="default:sand"})
|
||||
techage.add_grinder_recipe({input="techage:sieved_gravel", output="default:sand"})
|
||||
techage.add_grinder_recipe({input="default:coral_skeleton", output="default:silver_sand"})
|
||||
|
||||
if minetest.global_exists("skytest") then
|
||||
techage.add_grinder_recipe({input="default:desert_sand", output="skytest:dust"})
|
||||
techage.add_grinder_recipe({input="default:silver_sand", output="skytest:dust"})
|
||||
techage.add_grinder_recipe({input="default:sand", output="skytest:dust"})
|
||||
else
|
||||
techage.add_grinder_recipe({input="default:desert_sand", output="default:clay"})
|
||||
techage.add_grinder_recipe({input="default:silver_sand", output="default:clay"})
|
||||
techage.add_grinder_recipe({input="default:sand", output="default:clay"})
|
||||
end
|
||||
|
||||
techage.add_grinder_recipe({input="default:sandstone", output="default:sand 4"})
|
||||
techage.add_grinder_recipe({input="default:desert_sandstone", output="default:desert_sand 4"})
|
||||
techage.add_grinder_recipe({input="default:silver_sandstone", output="default:silver_sand 4"})
|
||||
|
||||
techage.add_grinder_recipe({input="default:tree", output="default:leaves 8"})
|
||||
techage.add_grinder_recipe({input="default:jungletree", output="default:jungleleaves 8"})
|
||||
techage.add_grinder_recipe({input="default:pine_tree", output="default:pine_needles 8"})
|
||||
techage.add_grinder_recipe({input="default:acacia_tree", output="default:acacia_leaves 8"})
|
||||
techage.add_grinder_recipe({input="default:aspen_tree", output="default:aspen_leaves 8"})
|
||||
|
||||
if minetest.global_exists("farming") then
|
||||
techage.add_grinder_recipe({input="farming:wheat 3", output="farming:flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:seed_wheat 6", output="farming:flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:barley 3", output="farming:flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:seed_barley 6", output="farming:flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:rye 3", output="farming:flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:seed_rye 6", output="farming:flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:rice 3", output="farming:rice_flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:seed_rice 6", output="farming:rice_flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:oat 3", output="farming:flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:seed_oat 6", output="farming:flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:seed_cotton 3", output="basic_materials:oil_extract"}, true)
|
||||
end
|
||||
@@ -0,0 +1,106 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Item Source Block
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local CYCLE_TIME = 30
|
||||
|
||||
local function formspec()
|
||||
return "size[8,7.2]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;main;3.5,0.8;1,1;]"..
|
||||
"list[current_player;main;0,3.5;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
minetest.register_node("techage:itemsource", {
|
||||
description = "Techage Item Source",
|
||||
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_frame_ta3.png^techage_appl_outp.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_appl_nodedetector.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_appl_nodedetector.png^techage_frame_ta3.png",
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = M(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
meta:set_int("push_dir", techage.side_to_outdir("R", node.param2))
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('main', 1)
|
||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||
meta:set_string("infotext", "Techage Item Source")
|
||||
meta:set_string("formspec", formspec())
|
||||
end,
|
||||
|
||||
on_timer = function(pos, elapsed)
|
||||
local meta = M(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local stack = inv:get_stack('main', 1)
|
||||
if stack:get_count() > 0 then
|
||||
local push_dir = meta:get_int("push_dir")
|
||||
local leftover = techage.push_items(pos, push_dir, stack)
|
||||
local pushed
|
||||
if not leftover then
|
||||
pushed = 0
|
||||
elseif leftover ~= true then
|
||||
pushed = stack:get_count() - leftover:get_count()
|
||||
else -- leftover == true
|
||||
pushed = stack:get_count()
|
||||
end
|
||||
meta:set_int("counter", pushed)
|
||||
meta:set_string("infotext", "Techage Item Source: "..pushed)
|
||||
end
|
||||
return true
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
|
||||
paramtype2 = "facedir", -- important!
|
||||
on_rotate = screwdriver.disallow, -- important!
|
||||
is_ground_content = false,
|
||||
drop = "",
|
||||
groups = {crumbly = 3, cracky = 3, snappy = 3},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
})
|
||||
|
||||
techage.register_node({"techage:itemsource"}, {
|
||||
on_node_load = function(pos)
|
||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||
end,
|
||||
})
|
||||
@@ -0,0 +1,228 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2/TA3 Bucket based Liquid Sampler
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
|
||||
local S = techage.S
|
||||
|
||||
local STANDBY_TICKS = 2
|
||||
local COUNTDOWN_TICKS = 3
|
||||
local CYCLE_TIME = 8
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
return "size[9,8.5]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;src;0,0;1,4;]"..
|
||||
"image[0,0;1,1;bucket.png]"..
|
||||
"image[1,0;1,1;"..techage.get_power_image(pos, nvm).."]"..
|
||||
"image[1,1.5;1,1;techage_form_arrow.png]"..
|
||||
"image_button[1,3;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[1,3;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[context;dst;2,0;7,4;]"..
|
||||
"list[current_player;main;0.5,4.5;8,4;]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]" ..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;dst]" ..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
if listname == "src" then
|
||||
CRD(pos).State:start_if_standby(pos)
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local inv = M(pos):get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
return allow_metadata_inventory_put(pos, to_list, to_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
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function is_water(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
local liquiddef = bucket.liquids[node.name]
|
||||
if liquiddef ~= nil and liquiddef.itemname ~= nil and node.name == liquiddef.source then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function can_start(pos, nvm, state)
|
||||
local water_pos = minetest.string_to_pos(M(pos):get_string("water_pos"))
|
||||
if not is_water(water_pos) then
|
||||
return S("no usable water")
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function sample_liquid(pos, crd, nvm, inv)
|
||||
if inv:room_for_item("dst", {name = "bucket:bucket_water"}) and
|
||||
inv:contains_item("src", {name = "bucket:bucket_empty"}) then
|
||||
inv:remove_item("src", {name = "bucket:bucket_empty"})
|
||||
inv:add_item("dst", {name = "bucket:bucket_water"})
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
else
|
||||
crd.State:idle(pos, nvm)
|
||||
end
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
--if tubelib.data_not_corrupted(pos) then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
sample_liquid(pos, crd, nvm, inv)
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("dst") and inv:is_empty("src")
|
||||
end
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^{power}^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_liquidsampler.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_liquidsampler.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^{power}^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
{
|
||||
name = "techage_filling4_ta#.png^techage_liquidsampler4.png^techage_frame4_ta#.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 1.0,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_appl_liquidsampler.png^techage_frame_ta#.png",
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "dst", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "src", stack)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "dst", stack)
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, _ =
|
||||
techage.register_consumer("liquidsampler", S("Liquid Sampler"), tiles, {
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
can_start = can_start,
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size("src", 4)
|
||||
inv:set_size("dst", 28)
|
||||
local water_pos = techage.get_pos(pos, "B")
|
||||
M(pos):set_string("water_pos", minetest.pos_to_string(water_pos))
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,1,2,4},
|
||||
power_consumption = {0,3,5,8},
|
||||
power_sides = {U=1},
|
||||
},
|
||||
{false, true, true, false}) -- TA2/A3
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2,
|
||||
recipe = {
|
||||
{"group:wood", "default:mese_crystal", "group:wood"},
|
||||
{"techage:tubeS", "bucket:bucket_empty", "techage:tubeS"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,131 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL 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_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return meta:get_inventory(), "main"
|
||||
end,
|
||||
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_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return meta:get_inventory(), "fuel"
|
||||
end,
|
||||
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_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return meta:get_inventory(), "main"
|
||||
end,
|
||||
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_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return meta:get_inventory(), "main"
|
||||
end,
|
||||
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,
|
||||
})
|
||||
@@ -0,0 +1,438 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2/TA3/TA4 Pusher
|
||||
Nodes for push/pull operation of StackItems from chests or other
|
||||
inventory/server nodes to tubes or other inventory/server nodes.
|
||||
|
||||
+--------+
|
||||
/ /|
|
||||
+--------+ |
|
||||
IN (L) -->| |X--> OUT (R)
|
||||
| PUSHER | +
|
||||
| |/
|
||||
+--------+
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
local Tube = techage.Tube
|
||||
|
||||
local STANDBY_TICKS = 2
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 2
|
||||
|
||||
local WRENCH_MENU = {
|
||||
{
|
||||
type = "number",
|
||||
name = "limit",
|
||||
label = S("Number of items"),
|
||||
tooltip = S("Number of items that are allowed to be pushed"),
|
||||
default = "0",
|
||||
},
|
||||
}
|
||||
|
||||
local function ta4_formspec(self, pos, nvm)
|
||||
if CRD(pos).stage == 4 then -- TA4 node?
|
||||
return "size[8,7.2]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;7.8,0.5;#c6e8ff]"..
|
||||
"label[3,-0.1;"..minetest.colorize("#000000", S("Pusher")).."]"..
|
||||
techage.question_mark_help(7.5, S("Optionally configure\nthe pusher with one item"))..
|
||||
techage.wrench_image(7.4, -0.05) ..
|
||||
"list[context;main;3.5,0.8;1,1;]"..
|
||||
"image_button[3.5,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[3.5,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[current_player;main;0,3.5;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if CRD(pos).State:get_state(nvm) ~= techage.STOPPED then
|
||||
return 0
|
||||
end
|
||||
|
||||
local inv = M(pos):get_inventory()
|
||||
local list = inv:get_list(listname)
|
||||
if list[index]:get_count() == 0 then
|
||||
stack:set_count(1)
|
||||
inv:set_stack(listname, index, stack)
|
||||
return 0
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if CRD(pos).State:get_state(nvm) ~= techage.STOPPED then
|
||||
return 0
|
||||
end
|
||||
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_stack(listname, index, nil)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function set_limit(pos, nvm, val)
|
||||
val = tonumber(val) or 0
|
||||
if val > 0 then
|
||||
nvm.limit = val
|
||||
nvm.num_items = 0
|
||||
M(pos):set_int("limit", val)
|
||||
else
|
||||
nvm.limit = nil
|
||||
nvm.num_items = nil
|
||||
M(pos):set_string("limit", "")
|
||||
end
|
||||
end
|
||||
|
||||
-- Function returns the number of pushed items
|
||||
local function push(pos, crd, meta, nvm, pull_dir, push_dir, num)
|
||||
local items = techage.pull_items(pos, pull_dir, num, nvm.item_name)
|
||||
if items ~= nil then
|
||||
local taken = items:get_count()
|
||||
local leftover = techage.push_items(pos, push_dir, items)
|
||||
if not leftover then
|
||||
-- place item back
|
||||
techage.unpull_items(pos, pull_dir, items)
|
||||
crd.State:blocked(pos, nvm)
|
||||
return 0
|
||||
elseif leftover ~= true then
|
||||
-- place item back
|
||||
taken = taken - leftover:get_count()
|
||||
techage.unpull_items(pos, pull_dir, leftover)
|
||||
crd.State:blocked(pos, nvm)
|
||||
return taken
|
||||
end
|
||||
return taken
|
||||
end
|
||||
crd.State:idle(pos, nvm)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function pushing(pos, crd, meta, nvm)
|
||||
local pull_dir = meta:get_int("pull_dir")
|
||||
local push_dir = meta:get_int("push_dir")
|
||||
|
||||
if not nvm.limit then
|
||||
local num = nvm.item_count or nvm.num_items or crd.num_items
|
||||
num = push(pos, crd, meta, nvm, pull_dir, push_dir, num)
|
||||
if num > 0 then
|
||||
if nvm.item_count then
|
||||
nvm.item_count = nvm.item_count - num
|
||||
if nvm.item_count <= 0 then
|
||||
crd.State:stop(pos, nvm)
|
||||
nvm.item_count = nil
|
||||
end
|
||||
end
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
end
|
||||
elseif nvm.num_items < nvm.limit then
|
||||
local num = math.min(crd.num_items, nvm.limit - nvm.num_items)
|
||||
num = push(pos, crd, meta, nvm, pull_dir, push_dir, num)
|
||||
if num > 0 then
|
||||
nvm.num_items = nvm.num_items + num
|
||||
if nvm.num_items >= nvm.limit then
|
||||
crd.State:stop(pos, nvm)
|
||||
else
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
pushing(pos, crd, M(pos), nvm)
|
||||
crd.State:is_active(nvm)
|
||||
end
|
||||
|
||||
local function on_rightclick(pos, node, clicker)
|
||||
if CRD(pos).stage ~= 4 then -- Not TA4 node?
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if not minetest.is_protected(pos, clicker:get_player_name()) then
|
||||
if CRD(pos).State:get_state(nvm) == techage.STOPPED then
|
||||
CRD(pos).State:start(pos, nvm)
|
||||
else
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if CRD(pos).stage == 4 then -- TA4 node?
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
M(pos):set_string("formspec", ta4_formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
end
|
||||
|
||||
local function tubelib2_on_update2(pos, outdir, tlib2, node)
|
||||
local pull_dir = M(pos):get_int("pull_dir")
|
||||
local push_dir = M(pos):get_int("push_dir")
|
||||
local is_ta4_tube = true
|
||||
|
||||
for i, pos, node in Tube:get_tube_line(pos, pull_dir) do
|
||||
is_ta4_tube = is_ta4_tube and techage.TA4tubes[node.name]
|
||||
end
|
||||
for i, pos, node in Tube:get_tube_line(pos, push_dir) do
|
||||
is_ta4_tube = is_ta4_tube and techage.TA4tubes[node.name]
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
if CRD(pos).stage == 4 and not is_ta4_tube then
|
||||
nvm.num_items = crd.num_items / 2
|
||||
else
|
||||
nvm.num_items = crd.num_items
|
||||
end
|
||||
end
|
||||
|
||||
local function can_start(pos, nvm, state)
|
||||
if CRD(pos).stage == 4 then -- TA4 node?
|
||||
local inv = M(pos):get_inventory()
|
||||
local name = inv:get_stack("main", 1):get_name()
|
||||
if name ~= "" then
|
||||
nvm.item_name = name
|
||||
else
|
||||
nvm.item_name = nil
|
||||
end
|
||||
else
|
||||
nvm.item_name = nil
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function ta_after_formspec(pos, fields, playername)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
set_limit(pos, nvm, fields.limit)
|
||||
end
|
||||
|
||||
local function on_state_change(pos, old_state, new_state)
|
||||
if old_state == techage.STOPPED and new_state == techage.RUNNING then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
set_limit(pos, nvm, M(pos):get_int("limit"))
|
||||
end
|
||||
end
|
||||
|
||||
local function config_item(pos, payload)
|
||||
if type(payload) == "string" then
|
||||
if payload == "" then
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_stack("main", 1, nil)
|
||||
return 0
|
||||
else
|
||||
local name, count = unpack(payload:split(" "))
|
||||
if name and (minetest.registered_nodes[name] or minetest.registered_items[name]
|
||||
or minetest.registered_craftitems[name]) then
|
||||
count = tonumber(count) or 1
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_stack("main", 1, {name = name, count = 1})
|
||||
return count
|
||||
end
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_appl_pusher.png^[transformR180]^techage_frame_ta#.png",
|
||||
"techage_appl_pusher.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
{
|
||||
name = "techage_appl_pusher14.png^[transformR180]^techage_frame14_ta#.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "techage_appl_pusher14.png^techage_frame14_ta#.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
-- push item through the pusher in opposit direction
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
return in_dir == M(pos):get_int("pull_dir") and techage.safe_push_items(pos, in_dir, stack)
|
||||
end,
|
||||
is_pusher = true, -- is a pulling/pushing node
|
||||
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "pull" then -- Deprecated command, use config/limit/start instead
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
nvm.item_count = math.min(config_item(pos, payload), 12)
|
||||
nvm.rmt_num = src
|
||||
CRD(pos).State:start(pos, nvm)
|
||||
return true
|
||||
elseif topic == "config" then -- Set item type
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
config_item(pos, payload)
|
||||
return true
|
||||
elseif topic == "limit" then -- Set push limit
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
set_limit(pos, nvm, payload)
|
||||
return true
|
||||
elseif topic == "count" then -- Get number of push items
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return nvm.num_items or 0
|
||||
else
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
if topic == 65 then -- Set item type
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
config_item(pos, payload)
|
||||
return 0
|
||||
elseif topic == 68 or topic == 20 then -- Set push limit
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
set_limit(pos, nvm, payload[1])
|
||||
return 0
|
||||
else
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if nvm.limit then
|
||||
nvm.num_items = 0
|
||||
end
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
if topic == 150 then -- Get number of pushed items
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return 0, {nvm.num_items or 0}
|
||||
else
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("pusher", S("Pusher"), tiles, {
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = ta4_formspec,
|
||||
tubing = tubing,
|
||||
can_start = can_start,
|
||||
on_state_change = on_state_change,
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = M(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
meta:set_int("pull_dir", techage.side_to_outdir("L", node.param2))
|
||||
meta:set_int("push_dir", techage.side_to_outdir("R", node.param2))
|
||||
if CRD(pos).stage == 4 then -- TA4 node?
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('main', 1)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", ta4_formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
end,
|
||||
ta_rotate_node = function(pos, node, new_param2)
|
||||
Tube:after_dig_node(pos)
|
||||
minetest.swap_node(pos, {name = node.name, param2 = new_param2})
|
||||
Tube:after_place_node(pos)
|
||||
local meta = M(pos)
|
||||
meta:set_int("pull_dir", techage.side_to_outdir("L", new_param2))
|
||||
meta:set_int("push_dir", techage.side_to_outdir("R", new_param2))
|
||||
end,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
on_rightclick = on_rightclick,
|
||||
on_receive_fields = on_receive_fields,
|
||||
node_timer = keep_running,
|
||||
on_rotate = screwdriver.disallow,
|
||||
tubelib2_on_update2 = tubelib2_on_update2,
|
||||
ta4_formspec = WRENCH_MENU,
|
||||
ta_after_formspec = ta_after_formspec,
|
||||
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,2,6,12},
|
||||
tube_sides = {L=1, R=1},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2.." 2",
|
||||
recipe = {
|
||||
{"group:wood", "wool:dark_green", "group:wood"},
|
||||
{"techage:tubeS", "default:mese_crystal", "techage:tubeS"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "techage:iron_ingot", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "techage:iron_ingot", ""},
|
||||
{"", node_name_ta3, ""},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,517 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2023 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Quarry machine to dig stones and other ground blocks.
|
||||
|
||||
The Quarry digs a hole (default) 5x5 blocks large and up to 80 blocks deep.
|
||||
It starts at the given level (0 is same level as the quarry block,
|
||||
1 is one level higher and so on)) and goes down to the given depth number.
|
||||
It digs one block every 4 seconds.
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S2P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
|
||||
local S = techage.S
|
||||
|
||||
-- Per-player active quarry registry (mod_storage key: "q_<pos>" → owner)
|
||||
-- Uses the shared techage.storage with "q_" prefix to avoid collisions
|
||||
local function quarry_reg_add(pos, owner)
|
||||
techage.storage:set_string("q_" .. P2S(pos), owner)
|
||||
end
|
||||
|
||||
local function quarry_reg_remove(pos)
|
||||
techage.storage:set_string("q_" .. P2S(pos), "")
|
||||
end
|
||||
|
||||
local function quarry_count_running(owner)
|
||||
local count = 0
|
||||
for key, val in pairs(techage.storage:to_table().fields) do
|
||||
if val == owner and key:sub(1, 2) == "q_" then
|
||||
local pos = minetest.string_to_pos(key:sub(3))
|
||||
if pos then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if nvm.techage_state == techage.RUNNING then
|
||||
count = count + 1
|
||||
else
|
||||
-- Stale entry (e.g. after server restart), clean up
|
||||
techage.storage:set_string(key, "")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
local CYCLE_TIME = 4
|
||||
local STANDBY_TICKS = 4
|
||||
local COUNTDOWN_TICKS = 4
|
||||
|
||||
local Side2Facedir = {F=0, R=1, B=2, L=3, D=4, U=5}
|
||||
local Depth2Idx = {[1]=1 ,[2]=2, [3]=3, [5]=4, [7]=5, [10]=6, [15]=7, [20]=8, [25]=9, [40]=10, [60]=11, [80]=12}
|
||||
local Holesize2Idx = {["3x3"] = 1, ["5x5"] = 2, ["7x7"] = 3, ["9x9"] = 4, ["11x11"] = 5}
|
||||
local Holesize2Diameter = {["3x3"] = 3, ["5x5"] = 5, ["7x7"] = 7, ["9x9"] = 9, ["11x11"] = 11}
|
||||
local Level2Idx = {[2]=1, [1]=2, [0]=3, [-1]=4, [-2]=5, [-3]=6,
|
||||
[-5]=7, [-10]=8, [-15]=9, [-20]=10}
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
local tooltip = S("Start level = 0\nmeans the same level\nas the quarry is placed")
|
||||
local level_idx = Level2Idx[nvm.start_level or 1] or 2
|
||||
local depth_idx = Depth2Idx[nvm.quarry_depth or 1] or 1
|
||||
local hsize_idx = Holesize2Idx[nvm.hole_size or "5x5"] or 2
|
||||
local level = nvm.level or "-"
|
||||
local hsize_list = "5x5"
|
||||
if CRD(pos).stage == 4 then
|
||||
hsize_list = "3x3,5x5,7x7,9x9,11x11"
|
||||
elseif CRD(pos).stage == 3 then
|
||||
hsize_list = "3x3,5x5,7x7"
|
||||
end
|
||||
local depth_list = "1,2,3,5,7,10,15,20,25,40,60,80"
|
||||
if CRD(pos).stage == 3 then
|
||||
depth_list = "1,2,3,5,7,10,15,20,25,40"
|
||||
elseif CRD(pos).stage == 2 then
|
||||
depth_list = "1,2,3,5,7,10,15,20"
|
||||
end
|
||||
|
||||
return "size[8,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;7.8,0.5;#c6e8ff]"..
|
||||
"label[3.5,-0.1;"..minetest.colorize( "#000000", S("Quarry")).."]"..
|
||||
techage.question_mark_help(8, tooltip)..
|
||||
"dropdown[0,0.8;1.5;level;2,1,0,-1,-2,-3,-5,-10,-15,-20;"..level_idx.."]"..
|
||||
"label[1.6,0.9;"..S("Start level").."]"..
|
||||
"dropdown[0,1.8;1.5;depth;"..depth_list..";"..depth_idx.."]"..
|
||||
"label[1.6,1.9;"..S("Digging depth").." ("..level..")]"..
|
||||
"dropdown[0,2.8;1.5;hole_size;"..hsize_list..";"..hsize_idx.."]"..
|
||||
"label[1.6,2.9;"..S("Hole size").."]"..
|
||||
"list[context;main;5,0.8;3,3;]"..
|
||||
"image[4,0.8;1,1;"..techage.get_power_image(pos, nvm).."]"..
|
||||
"image_button[4,2.8;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[4,2.8;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[current_player;main;0,4.3;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
local function play_sound(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
-- Stop any lingering handle first, so newly arrived clients get the fresh sound
|
||||
if mem.handle then
|
||||
minetest.sound_stop(mem.handle)
|
||||
mem.handle = nil
|
||||
end
|
||||
mem.handle = minetest.sound_play("techage_quarry", {
|
||||
pos = pos,
|
||||
gain = 1.5,
|
||||
max_hear_distance = 15,
|
||||
loop = true})
|
||||
if mem.handle == -1 then
|
||||
mem.handle = nil
|
||||
minetest.after(1, play_sound, pos)
|
||||
end
|
||||
end
|
||||
|
||||
local function stop_sound(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
if mem.handle then
|
||||
minetest.sound_stop(mem.handle)
|
||||
-- Keep handle: on_node_load can re-send stop to clients that came back in range
|
||||
end
|
||||
end
|
||||
|
||||
local function on_node_state_change(pos, old_state, new_state)
|
||||
local mem = techage.get_mem(pos)
|
||||
local owner = M(pos):get_string("owner")
|
||||
mem.co = nil
|
||||
techage.unmark_position(owner)
|
||||
if new_state == techage.RUNNING then
|
||||
play_sound(pos)
|
||||
quarry_reg_add(pos, owner)
|
||||
else
|
||||
stop_sound(pos)
|
||||
quarry_reg_remove(pos)
|
||||
end
|
||||
end
|
||||
|
||||
local function get_pos(pos, facedir, side, steps)
|
||||
facedir = (facedir + Side2Facedir[side]) % 4
|
||||
local dir = vector.multiply(minetest.facedir_to_dir(facedir), steps or 1)
|
||||
return vector.add(pos, dir)
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
|
||||
local function get_quarry_pos(pos, xoffs, zoffs)
|
||||
return {x = pos.x + xoffs - 1, y = pos.y, z = pos.z + zoffs - 1}
|
||||
end
|
||||
|
||||
-- pos is the quarry pos
|
||||
local function get_corner_positions(pos, facedir, hole_diameter)
|
||||
local _pos = get_pos(pos, facedir, "L")
|
||||
local pos1 = get_pos(_pos, facedir, "F", math.floor((hole_diameter - 1) / 2))
|
||||
local pos2 = get_pos(_pos, facedir, "B", math.floor((hole_diameter - 1) / 2))
|
||||
pos2 = get_pos(pos2, facedir, "L", hole_diameter - 1)
|
||||
if pos1.x > pos2.x then pos1.x, pos2.x = pos2.x, pos1.x end
|
||||
if pos1.y > pos2.y then pos1.y, pos2.y = pos2.y, pos1.y end
|
||||
if pos1.z > pos2.z then pos1.z, pos2.z = pos2.z, pos1.z end
|
||||
return pos1, pos2
|
||||
end
|
||||
|
||||
local function is_air_level(pos1, pos2, hole_diameter)
|
||||
return #minetest.find_nodes_in_area(pos1, pos2, {"air"}) == hole_diameter * hole_diameter
|
||||
end
|
||||
|
||||
local function mark_area(pos1, pos2, owner)
|
||||
pos1.y = pos1.y + 0.2
|
||||
techage.mark_cube(owner, pos1, pos2, "quarry", "#FF0000", 20)
|
||||
pos1.y = pos1.y - 0.2
|
||||
end
|
||||
|
||||
local function quarry_task(pos, crd, nvm)
|
||||
nvm.start_level = nvm.start_level or 0
|
||||
nvm.quarry_depth = nvm.quarry_depth or 1
|
||||
nvm.hole_diameter = nvm.hole_diameter or 5
|
||||
local y_first = pos.y + nvm.start_level
|
||||
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
|
||||
for y_curr = y_first, y_last, -1 do
|
||||
pos1.y = y_curr
|
||||
pos2.y = y_curr
|
||||
|
||||
-- Restarting the server can detach the coroutine data.
|
||||
-- Therefore, read nvm again.
|
||||
nvm = techage.get_nvm(pos)
|
||||
nvm.level = y_first - y_curr
|
||||
|
||||
if minetest.is_area_protected(pos1, pos2, owner, 5) then
|
||||
crd.State:fault(pos, nvm, S("area is protected"))
|
||||
return
|
||||
end
|
||||
|
||||
if not is_air_level(pos1, pos2, nvm.hole_diameter) then
|
||||
mark_area(pos1, pos2, owner)
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
coroutine.yield()
|
||||
|
||||
for zoffs = 1, nvm.hole_diameter do
|
||||
for xoffs = 1, nvm.hole_diameter do
|
||||
local qpos = get_quarry_pos(pos1, xoffs, zoffs)
|
||||
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
|
||||
end
|
||||
techage.unmark_position(owner)
|
||||
end
|
||||
end
|
||||
crd.State:stop(pos, nvm, S("finished"))
|
||||
stop_sound(pos)
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local mem = techage.get_mem(pos)
|
||||
if not mem.co then
|
||||
mem.co = coroutine.create(quarry_task)
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local _, err = coroutine.resume(mem.co, pos, crd, nvm)
|
||||
if err then
|
||||
minetest.log("error", "[TA4 Quarry Coroutine Error] at pos " .. minetest.pos_to_string(pos) .. " " .. err)
|
||||
end
|
||||
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", formspec(crd.State, pos, nvm))
|
||||
end
|
||||
if nvm.techage_state ~= techage.RUNNING then
|
||||
stop_sound(pos)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_rightclick(pos, node, clicker)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
techage.set_activeformspec(pos, clicker)
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("main")
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
|
||||
if fields.depth then
|
||||
if tonumber(fields.depth) ~= nvm.quarry_depth then
|
||||
nvm.quarry_depth = tonumber(fields.depth)
|
||||
if CRD(pos).stage == 2 then
|
||||
nvm.quarry_depth = math.min(nvm.quarry_depth, 20)
|
||||
elseif CRD(pos).stage == 3 then
|
||||
nvm.quarry_depth = math.min(nvm.quarry_depth, 40)
|
||||
end
|
||||
mem.co = nil
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
end
|
||||
end
|
||||
|
||||
if fields.level then
|
||||
if tonumber(fields.level) ~= nvm.start_level then
|
||||
nvm.start_level = tonumber(fields.level)
|
||||
mem.co = nil
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
end
|
||||
end
|
||||
|
||||
if fields.hole_size then
|
||||
if CRD(pos).stage == 4 then
|
||||
if fields.hole_size ~= nvm.hole_size then
|
||||
nvm.hole_size = fields.hole_size
|
||||
nvm.hole_diameter = Holesize2Diameter[fields.hole_size or "5x5"] or 5
|
||||
mem.co = nil
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
end
|
||||
elseif CRD(pos).stage == 3 then
|
||||
if fields.hole_size ~= nvm.hole_size then
|
||||
nvm.hole_size = fields.hole_size
|
||||
nvm.hole_diameter = Holesize2Diameter[fields.hole_size or "7x7"] or 7
|
||||
mem.co = nil
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
end
|
||||
else
|
||||
nvm.hole_size = "5x5"
|
||||
nvm.hole_diameter = 5
|
||||
end
|
||||
end
|
||||
|
||||
-- Per-player active quarry limit check (only on start attempts)
|
||||
if fields.state_button ~= nil and techage.max_active_quarries > 0 then
|
||||
local state = nvm.techage_state or techage.STOPPED
|
||||
if state == techage.STOPPED or state == techage.STANDBY or state == techage.BLOCKED then
|
||||
local owner = M(pos):get_string("owner")
|
||||
if quarry_count_running(owner) >= techage.max_active_quarries then
|
||||
minetest.chat_send_player(player:get_player_name(),
|
||||
"[Techage] " .. S("Max. number of active quarries reached!") ..
|
||||
" (" .. techage.max_active_quarries .. ")")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_quarry_left.png",
|
||||
"techage_filling_ta#.png^techage_appl_quarry.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_quarry.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
{
|
||||
name = "techage_frame14_ta#.png^techage_quarry_left14.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_appl_quarry.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_quarry.png^techage_frame_ta#.png",
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "main", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
local inv = M(pos):get_inventory()
|
||||
--CRD(pos).State:start_if_standby(pos) -- would need power!
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "depth" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return nvm.level or 0
|
||||
elseif topic == "on" and techage.max_active_quarries > 0 then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local state = nvm.techage_state or techage.STOPPED
|
||||
if state ~= techage.RUNNING then
|
||||
local owner = M(pos):get_string("owner")
|
||||
if quarry_count_running(owner) >= techage.max_active_quarries then
|
||||
return "limit"
|
||||
end
|
||||
end
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
else
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
if topic == 133 then -- Quarry Depth
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return 0, {nvm.level or 0}
|
||||
else
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if nvm.techage_state == techage.RUNNING then
|
||||
play_sound(pos) -- stops lingering handle and restarts fresh
|
||||
else
|
||||
stop_sound(pos) -- re-send stop to clients that came back in range
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("quarry", S("Quarry"), tiles, {
|
||||
drawtype = "normal",
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
on_state_change = on_node_state_change,
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
local nvm = techage.get_nvm(pos)
|
||||
inv:set_size('main', 9)
|
||||
M(pos):set_string("owner", placer:get_player_name())
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
on_rightclick = on_rightclick,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,1,1,1},
|
||||
power_consumption = {0,10,12,14},
|
||||
}
|
||||
)
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2,
|
||||
recipe = {
|
||||
{"group:wood", "default:mese_crystal", "group:wood"},
|
||||
{"techage:tubeS", "default:pick_diamond", "techage:iron_ingot"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", node_name_ta3, ""},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,243 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2021 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA4 Recipe Block for the TA4 Autocrafter
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S2P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local MAX_RECIPE = 10
|
||||
|
||||
local function recipes_formspec(x, y, idx)
|
||||
return "container[" .. x .. "," .. y .. "]" ..
|
||||
"background[0,0;8,3.2;techage_form_grey.png]" ..
|
||||
"list[context;input;0.1,0.1;3,3;]" ..
|
||||
"image[3,1.1;1,1;techage_form_arrow.png]" ..
|
||||
"list[context;output;3.9,1.1;1,1;]" ..
|
||||
"button[5.5,1.1;1,1;priv;<<]" ..
|
||||
"button[6.5,1.1;1,1;next;>>]" ..
|
||||
"label[5.5,0.5;"..S("Recipe") .. ": " .. idx .. "/" .. MAX_RECIPE .. "]" ..
|
||||
"container_end[]"
|
||||
end
|
||||
|
||||
local function formspec(pos, nvm)
|
||||
return "size[8,7.4]"..
|
||||
recipes_formspec(0, 0, nvm.recipe_idx or 1) ..
|
||||
"list[current_player;main;0,3.6;8,4;]" ..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]" ..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;dst]" ..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
local function determine_new_input(pos, inv)
|
||||
local output = inv:get_stack("output", 1):get_name()
|
||||
if output and output ~= "" then
|
||||
local recipe = minetest.get_craft_recipe(output)
|
||||
if recipe.items and recipe.type == "normal" then
|
||||
for i = 1, 9 do
|
||||
local name = recipe.items[i]
|
||||
if name then
|
||||
if minetest.registered_items[name] then
|
||||
inv:set_stack("input", i, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
inv:set_stack("output", 1, recipe.output)
|
||||
end
|
||||
else
|
||||
for i = 1, 9 do
|
||||
inv:set_stack("input", i, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function determine_new_output(pos, inv)
|
||||
local items = {}
|
||||
for i = 1, 9 do
|
||||
items[i] = inv:get_stack("input", i):get_name()
|
||||
end
|
||||
local input = {
|
||||
method = "normal",
|
||||
width = 3,
|
||||
items = items,
|
||||
}
|
||||
local output, _ = minetest.get_craft_result(input)
|
||||
inv:set_stack("output", 1, output.item)
|
||||
end
|
||||
|
||||
local function get_recipe(inv)
|
||||
local items = {}
|
||||
local last_idx = 0
|
||||
for i = 1, 9 do
|
||||
local name = inv:get_stack("input", i):get_name()
|
||||
if name ~= "" then
|
||||
last_idx = i
|
||||
end
|
||||
items[i] = name
|
||||
end
|
||||
local input = table.concat(items, ",", 1, last_idx)
|
||||
local stack = inv:get_stack("output", 1)
|
||||
return {
|
||||
input = input,
|
||||
output = stack:get_name() .. " " .. stack:get_count()
|
||||
}
|
||||
end
|
||||
|
||||
local function after_recipe_change(pos, inv, listname)
|
||||
if listname == "input" then
|
||||
determine_new_output(pos, inv)
|
||||
else
|
||||
determine_new_input(pos, inv)
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.recipes = nvm.recipes or {}
|
||||
nvm.recipes[nvm.recipe_idx or 1] = get_recipe(inv)
|
||||
end
|
||||
|
||||
local function update_inventor(pos, inv, idx)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.recipes = nvm.recipes or {}
|
||||
local recipe = nvm.recipes[idx]
|
||||
if recipe then
|
||||
local items = string.split(recipe.input, ",", true)
|
||||
for i = 1, 9 do
|
||||
inv:set_stack("input", i, items[i] or "")
|
||||
end
|
||||
inv:set_stack("output", 1, recipe.output)
|
||||
else
|
||||
for i = 1, 9 do
|
||||
inv:set_stack("input", i, nil)
|
||||
end
|
||||
inv:set_stack("output", 1, nil)
|
||||
end
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
local inv = M(pos):get_inventory()
|
||||
local list = inv:get_list(listname)
|
||||
stack:set_count(1)
|
||||
inv:set_stack(listname, index, stack)
|
||||
after_recipe_change(pos, inv, listname)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_stack(listname, index, nil)
|
||||
after_recipe_change(pos, inv, listname)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function 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
|
||||
return 0
|
||||
end
|
||||
|
||||
local inv = M(pos):get_inventory()
|
||||
if from_list == to_list then
|
||||
minetest.after(0.1, after_recipe_change, pos, inv, from_list)
|
||||
return 1
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
minetest.register_node("techage:ta4_recipeblock", {
|
||||
description = S("TA4 Recipe Block"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta4.png^techage_frame_ta4_top.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4_top.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_recipeblock.png",
|
||||
},
|
||||
|
||||
on_construct = function(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('input', 9)
|
||||
inv:set_size('output', 1)
|
||||
end,
|
||||
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local number = techage.add_node(pos, "techage:ta4_chest")
|
||||
M(pos):set_string("owner", placer:get_player_name())
|
||||
M(pos):set_string("node_number", number)
|
||||
M(pos):set_string("formspec", formspec(pos, nvm))
|
||||
M(pos):set_string("infotext", S("TA4 Recipe Block") .. " " .. number)
|
||||
end,
|
||||
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.recipe_idx = nvm.recipe_idx or 1
|
||||
if fields.next == ">>" then
|
||||
nvm.recipe_idx = techage.in_range(nvm.recipe_idx + 1, 1, MAX_RECIPE)
|
||||
elseif fields.priv == "<<" then
|
||||
nvm.recipe_idx = techage.in_range(nvm.recipe_idx - 1, 1, MAX_RECIPE)
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
update_inventor(pos, inv, nvm.recipe_idx or 1)
|
||||
M(pos):set_string("formspec", formspec(pos, nvm))
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
techage.del_mem(pos)
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
techage.register_node({"techage:ta4_recipeblock"}, {
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if topic == "input" and payload and payload ~= "" then
|
||||
nvm.recipes = nvm.recipes or {}
|
||||
local recipe = nvm.recipes[tonumber(payload) or 1]
|
||||
if recipe then
|
||||
return recipe.input
|
||||
end
|
||||
else
|
||||
return "unsupported"
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:ta4_recipeblock",
|
||||
recipe = {
|
||||
{"techage:ta4_carbon_fiber", "dye:blue", "techage:aluminum"},
|
||||
{"", "basic_materials:ic", ""},
|
||||
{"default:steel_ingot", "techage:ta4_wlanchip", "default:steel_ingot"},
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,358 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA4 Recycler, recycling techage machines
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
|
||||
local STANDBY_TICKS = 3
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 8
|
||||
|
||||
local Recipes = {}
|
||||
|
||||
local SpecialItems = {
|
||||
["techage:sieved_gravel"] = "default:sand",
|
||||
["basic_materials:heating_element"] = "default:copper_ingot",
|
||||
["techage:ta4_wlanchip"] = "",
|
||||
["techage:basalt_cobble"] = "default:sand",
|
||||
["default:stone"] = "techage:sieved_gravel",
|
||||
["default:wood"] = "default:stick 5",
|
||||
["basic_materials:concrete_block"] = "techage:sieved_gravel",
|
||||
["dye:green"] = "",
|
||||
["dye:red"] = "",
|
||||
["dye:white"] = "",
|
||||
["dye:blue"] = "",
|
||||
["dye:brown"] = "",
|
||||
["dye:cyan"] = "",
|
||||
["dye:yellow"] = "",
|
||||
["dye:grey"] = "",
|
||||
["dye:orange"] = "",
|
||||
["dye:black"] = "",
|
||||
["techage:basalt_glass_thin"] = "",
|
||||
["group:stone"] = "techage:sieved_gravel",
|
||||
--["basic_materials:plastic_sheet"] = "",
|
||||
["group:wood"] = "default:stick 5",
|
||||
["techage:basalt_glass"] = "",
|
||||
["default:junglewood"] = "default:stick 5",
|
||||
["techage:ta4_silicon_wafer"] = "",
|
||||
["default:cobble"] = "techage:sieved_gravel",
|
||||
["default:pick_diamond"] = "default:stick",
|
||||
["techage:hammer_steel"] = "default:stick",
|
||||
["default:paper"] = "",
|
||||
["stairs:slab_basalt_glass2"] = "",
|
||||
["techage:basalt_stone"] = "techage:sieved_gravel",
|
||||
["techage:ta4_ramchip"] = "",
|
||||
["protector:chest"] = "default:chest",
|
||||
["techage:ta4_rotor_blade"] = "",
|
||||
["techage:ta4_carbon_fiber"] = "",
|
||||
["techage:ta4_round_ceramic"] = "",
|
||||
["techage:ta4_furnace_ceramic"] = "",
|
||||
["techage:ta5_aichip"] = "",
|
||||
["techage:ta4_leds"] = "",
|
||||
}
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
return "size[8,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;src;0,0;3,3;]"..
|
||||
--"item_image[0,0;1,1;default:cobble]"..
|
||||
"image[0,0;1,1;techage_form_mask.png]"..
|
||||
"image[3.5,0;1,1;"..techage.get_power_image(pos, nvm).."]"..
|
||||
"image[3.5,1;1,1;techage_form_arrow.png]"..
|
||||
"image_button[3.5,2;1,1;"..self:get_state_button_image(nvm)..";state_button;]"..
|
||||
"tooltip[3.5,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[context;dst;5,0;3,3;]"..
|
||||
--"item_image[5,0;1,1;default:gravel]"..
|
||||
"image[5,0;1,1;techage_form_mask.png]"..
|
||||
"list[current_player;main;0,4;8,4;]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(0, 4)
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
if listname == "src" then
|
||||
CRD(pos).State:start_if_standby(pos)
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local inv = M(pos):get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
return allow_metadata_inventory_put(pos, to_list, to_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
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function cook_reverse(stack, inv, idx, recipe)
|
||||
-- check space
|
||||
for _,item in ipairs(recipe.items) do
|
||||
if not inv:room_for_item("dst", item) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
-- take item
|
||||
inv:remove_item("src", ItemStack(recipe.output))
|
||||
-- add items
|
||||
for _,item in ipairs(recipe.items) do
|
||||
inv:add_item("dst", item)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function get_recipe(stack)
|
||||
local name = stack:get_name()
|
||||
local recipe = Recipes[name]
|
||||
if recipe then
|
||||
if stack:get_count() >= ItemStack(recipe.output):get_count() then
|
||||
return recipe
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function recycling(pos, crd, nvm, inv)
|
||||
for idx,stack in ipairs(inv:get_list("src")) do
|
||||
local recipe = not stack:is_empty() and get_recipe(stack)
|
||||
if recipe then
|
||||
if cook_reverse(stack, inv, idx, recipe) then
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
else
|
||||
crd.State:blocked(pos, nvm)
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
crd.State:idle(pos, nvm)
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
recycling(pos, crd, nvm, inv)
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("dst") and inv:is_empty("src")
|
||||
end
|
||||
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_appl_grinder.png^[colorize:@@000000:100^techage_frame_ta#_top.png",
|
||||
--"techage_appl_grinder.png^techage_frame_ta#_top.png^[multiply:#FF0000",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_recycler.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_recycler.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
{
|
||||
name = "techage_appl_grinder4.png^[colorize:@@000000:100^techage_frame4_ta#_top.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 1.0,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_recycler.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_recycler.png^techage_frame_ta#.png",
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "dst", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
local inv = M(pos):get_inventory()
|
||||
--CRD(pos).State:start_if_standby(pos) -- would need power!
|
||||
return techage.put_items(inv, "src", stack)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "dst", stack)
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local _, _, node_name_ta4 =
|
||||
techage.register_consumer("recycler", S("Recycler"), tiles, {
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-8/16, -8/16, -8/16, 8/16, 8/16, -6/16},
|
||||
{-8/16, -8/16, 6/16, 8/16, 8/16, 8/16},
|
||||
{-8/16, -8/16, -8/16, -6/16, 8/16, 8/16},
|
||||
{ 6/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-6/16, -8/16, -6/16, 6/16, 6/16, 6/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('src', 9)
|
||||
inv:set_size('dst', 9)
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,0,0,1},
|
||||
power_consumption = {0,0,0,16},
|
||||
},
|
||||
{false, false, false, true}) -- TA4 only
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", "techage:ta4_grinder_pas", ""},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Prepare recipes
|
||||
-------------------------------------------------------------------------------
|
||||
-- Nodes from mods that can be recycled
|
||||
local ModNames = {
|
||||
techage = true,
|
||||
hyperloop = true,
|
||||
}
|
||||
|
||||
local function get_item_list(inputs)
|
||||
local lst = {}
|
||||
for _,input in pairs(inputs or {}) do
|
||||
if SpecialItems[input] then
|
||||
input = SpecialItems[input]
|
||||
end
|
||||
if input and input ~= "" then
|
||||
if minetest.registered_nodes[input] or minetest.registered_items[input] then
|
||||
table.insert(lst, input)
|
||||
end
|
||||
end
|
||||
end
|
||||
return lst
|
||||
end
|
||||
|
||||
local function get_special_recipe(name)
|
||||
if SpecialItems[name] then
|
||||
return {
|
||||
output = name,
|
||||
items = {SpecialItems[name]}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local function collect_recipes()
|
||||
local add = function(name, ndef)
|
||||
local _, _, mod, _ = string.find(name, "([%w_]+):([%w_]+)")
|
||||
local recipe = get_special_recipe(name) or
|
||||
techage.recipes.get_recipe(name) or
|
||||
minetest.get_craft_recipe(name)
|
||||
local items = get_item_list(recipe.items)
|
||||
|
||||
if ModNames[mod]
|
||||
and ndef.groups.not_in_creative_inventory ~= 1
|
||||
and not ndef.tool_capabilities
|
||||
and recipe.output
|
||||
and next(items) then
|
||||
local s = table.concat(items, ", ")
|
||||
--print(string.format("%-36s {%s}", recipe.output, s))
|
||||
Recipes[name] = {output = recipe.output, items = items}
|
||||
end
|
||||
end
|
||||
|
||||
for name, ndef in pairs(minetest.registered_nodes) do
|
||||
add(name, ndef)
|
||||
end
|
||||
for name, ndef in pairs(minetest.registered_items) do
|
||||
add(name, ndef)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.after(2, collect_recipes)
|
||||
@@ -0,0 +1,715 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2023 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA4 8x2000 Chest
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local M = minetest.get_meta
|
||||
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}
|
||||
return inv[idx]
|
||||
end
|
||||
|
||||
local function gen_inv(nvm)
|
||||
nvm.inventory = {}
|
||||
for i = 1,8 do
|
||||
gen_stack(nvm.inventory, i)
|
||||
end
|
||||
return nvm.inventory
|
||||
end
|
||||
|
||||
local function repair_inv(nvm)
|
||||
nvm.inventory = nvm.inventory or {}
|
||||
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 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 {}
|
||||
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
|
||||
return nvm.inventory[idx] and nvm.inventory[idx].count or 0
|
||||
else
|
||||
local count = 0
|
||||
for _,item in ipairs(nvm.inventory) do
|
||||
count = count + item.count or 0
|
||||
end
|
||||
return count
|
||||
end
|
||||
end
|
||||
|
||||
local function get_itemstring(nvm, idx)
|
||||
if idx and idx > 0 then
|
||||
nvm.inventory = nvm.inventory or {}
|
||||
return nvm.inventory[idx] and nvm.inventory[idx].name or ""
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
local function inv_empty(nvm)
|
||||
for _,item in ipairs(nvm.inventory or {}) do
|
||||
if item.count and item.count > 0 then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function inv_state(nvm)
|
||||
local num = 0
|
||||
for _,item in ipairs(nvm.inventory or {}) do
|
||||
if item.count and item.count > 0 then
|
||||
num = num + 1
|
||||
end
|
||||
end
|
||||
if num == 0 then return "empty" end
|
||||
if num == 8 then return "full" end
|
||||
return "loaded"
|
||||
end
|
||||
|
||||
local function inv_state_num(nvm)
|
||||
local num = 0
|
||||
for _,item in ipairs(nvm.inventory or {}) do
|
||||
if item.count and item.count > 0 then
|
||||
num = num + 1
|
||||
end
|
||||
end
|
||||
if num == 0 then return 0 end
|
||||
if num == 8 then return 2 end
|
||||
return 1
|
||||
end
|
||||
|
||||
local function max_stacksize(item_name)
|
||||
-- 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)
|
||||
local size = M(pos):get_int("stacksize")
|
||||
if size == 0 then
|
||||
return STACK_SIZE
|
||||
end
|
||||
return size
|
||||
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
|
||||
if nvmstack.name and nvmstack.name ~= "" and nvmstack.name ~= itemstack:get_name() then
|
||||
return false, "Mismatching names"
|
||||
end
|
||||
|
||||
-- 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 or ""))
|
||||
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
|
||||
|
||||
|
||||
-- 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 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) - output_stack:get_count())
|
||||
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 or ""))
|
||||
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 {}
|
||||
|
||||
for idx = 1,8 do
|
||||
input_stack:take_item(add_to_chest(pos, input_stack, idx))
|
||||
end
|
||||
|
||||
if input_stack:get_count() > 0 then
|
||||
return input_stack -- Not all items were added to chest
|
||||
else
|
||||
return true -- All items were added
|
||||
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
|
||||
|
||||
local function formspec_container(x, y, nvm, inv)
|
||||
local tbl = {"container["..x..","..y.."]"}
|
||||
for i = 1,8 do
|
||||
local xpos = i - 1
|
||||
tbl[#tbl+1] = "box["..(xpos - 0.03)..",0;0.86,0.9;#808080]"
|
||||
local stack = get_stack(nvm, i)
|
||||
if stack.name ~= "" then
|
||||
local itemstack = ItemStack({
|
||||
name = stack.name,
|
||||
count = stack.count,
|
||||
wear = stack.wear,
|
||||
})
|
||||
local stack_meta_table = (minetest.deserialize(stack.meta) or {}).fields or {}
|
||||
for _, key in ipairs({"description", "short_description", "color", "palette_index"}) do
|
||||
if stack_meta_table[key] then
|
||||
itemstack:get_meta():set_string(key, stack_meta_table[key]:gsub("%[", "("):gsub("%]", ")"))
|
||||
end
|
||||
end
|
||||
local itemname = itemstack:to_string()
|
||||
--tbl[#tbl+1] = "item_image["..xpos..",1;1,1;"..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..";]"
|
||||
else
|
||||
tbl[#tbl+1] = "image_button["..xpos..",1;1,1;techage_form_add_arrow.png;add"..i..";]"
|
||||
end
|
||||
end
|
||||
tbl[#tbl+1] = "list[context;main;0,2;8,1;]"
|
||||
tbl[#tbl+1] = "container_end[]"
|
||||
return table.concat(tbl, "")
|
||||
end
|
||||
|
||||
local function formspec(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
local size = get_stacksize(pos)
|
||||
local assignment = M(pos):get_int("assignment") == 1 and "true" or "false"
|
||||
local priority = M(pos):get_int("priority") == 1 and "true" or "false"
|
||||
return "size[8,8.3]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
formspec_container(0, 0, nvm, inv)..
|
||||
"button[0,3.5;3,1;unlock;"..S("Unlock").."]"..
|
||||
"tooltip[0,3.5;3,1;"..S("Unlock connected chest\nif all slots are below 2000")..";#0C3D32;#FFFFFF]"..
|
||||
"label[0,3;"..S("Size")..": 8x"..size.."]"..
|
||||
"checkbox[4,3;assignment;"..S("keep assignment")..";"..assignment.."]"..
|
||||
"tooltip[4,3;2,0.6;"..S("Never completely empty the slots\nwith the pusher to keep the item assignment")..";#0C3D32;#FFFFFF]"..
|
||||
"checkbox[4,3.6;priority;"..S("right to left")..";"..priority.."]"..
|
||||
"tooltip[4,3.6;2,0.6;"..S("Empty the slots always \nfrom right to left")..";#0C3D32;#FFFFFF]"..
|
||||
"list[current_player;main;0,4.6;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
local function count_number_of_chests(pos)
|
||||
local node = techage.get_node_lvm(pos)
|
||||
local dir = techage.side_to_outdir("B", node.param2)
|
||||
local pos1 = tubelib2.get_pos(pos, dir)
|
||||
local param2 = node.param2
|
||||
local cnt = 1
|
||||
while cnt < 50 do
|
||||
node = techage.get_node_lvm(pos1)
|
||||
if node.name ~= "techage:ta4_chest_dummy" then
|
||||
break
|
||||
end
|
||||
local meta = M(pos1)
|
||||
if meta:contains("param2") and meta:get_int("param2") ~= param2 then
|
||||
break
|
||||
end
|
||||
pos1 = tubelib2.get_pos(pos1, dir)
|
||||
cnt = cnt + 1
|
||||
end
|
||||
M(pos):set_int("stacksize", STACK_SIZE * cnt)
|
||||
end
|
||||
|
||||
local function dummy_chest_behind(pos, node)
|
||||
local dir = techage.side_to_outdir("B", node.param2)
|
||||
local pos1 = tubelib2.get_pos(pos, dir)
|
||||
node = techage.get_node_lvm(pos1)
|
||||
return node.name == "techage:ta4_chest_dummy"
|
||||
end
|
||||
|
||||
local function part_of_a_chain(pos, node)
|
||||
local dir = techage.side_to_outdir("F", node.param2)
|
||||
local pos1 = tubelib2.get_pos(pos, dir)
|
||||
node = techage.get_node_lvm(pos1)
|
||||
return node.name == "techage:ta4_chest_dummy" or node.name == "techage:ta4_chest"
|
||||
end
|
||||
|
||||
local function search_chest_in_front(pos, node)
|
||||
local dir = techage.side_to_outdir("F", node.param2)
|
||||
local pos1 = tubelib2.get_pos(pos, dir)
|
||||
local param2 = node.param2
|
||||
local cnt = 1
|
||||
while cnt < 50 do
|
||||
node = techage.get_node_lvm(pos1)
|
||||
if node.name ~= "techage:ta4_chest_dummy" then
|
||||
break
|
||||
end
|
||||
local meta = M(pos1)
|
||||
if meta:contains("param2") and meta:get_int("param2") ~= param2 then
|
||||
break
|
||||
end
|
||||
pos1 = tubelib2.get_pos(pos1, dir)
|
||||
cnt = cnt + 1
|
||||
end
|
||||
if node.name == "techage:ta4_chest" and node.param2 == param2 then
|
||||
minetest.after(1, count_number_of_chests, pos1)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.front_chest_pos = pos1
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function get_front_chest_pos(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if nvm.front_chest_pos then
|
||||
return nvm.front_chest_pos
|
||||
end
|
||||
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if search_chest_in_front(pos, node) then
|
||||
return nvm.front_chest_pos
|
||||
end
|
||||
|
||||
return pos
|
||||
end
|
||||
|
||||
local function convert_to_chest_again(pos, node, player)
|
||||
local dir = techage.side_to_outdir("B", node.param2)
|
||||
local pos1 = tubelib2.get_pos(pos, dir)
|
||||
local node1 = techage.get_node_lvm(pos1)
|
||||
if minetest.is_protected(pos1, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
if node1.name == "techage:ta4_chest_dummy" then
|
||||
node1.name = "techage:ta4_chest"
|
||||
minetest.swap_node(pos1, node1)
|
||||
--M(pos1):set_int("disabled", 1)
|
||||
local nvm = techage.get_nvm(pos1)
|
||||
gen_inv(nvm)
|
||||
local number = techage.add_node(pos1, "techage:ta4_chest")
|
||||
M(pos1):set_string("owner", player:get_player_name())
|
||||
M(pos1):set_string("formspec", formspec(pos1))
|
||||
M(pos1):set_string("infotext", DESCRIPTION.." "..number)
|
||||
end
|
||||
end
|
||||
|
||||
local function unlock_chests(pos, player)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
for idx = 1,8 do
|
||||
if get_count(nvm, idx) > STACK_SIZE then return end
|
||||
end
|
||||
local node = techage.get_node_lvm(pos)
|
||||
convert_to_chest_again(pos, node, player)
|
||||
M(pos):set_int("stacksize", STACK_SIZE)
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function 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
|
||||
return 0
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
local function on_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
techage.set_activeformspec(pos, player)
|
||||
end
|
||||
|
||||
local function on_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
techage.set_activeformspec(pos, player)
|
||||
end
|
||||
|
||||
local function on_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
techage.set_activeformspec(pos, player)
|
||||
end
|
||||
|
||||
local function on_rightclick(pos, node, clicker)
|
||||
if M(pos):get_int("disabled") ~= 1 then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
repair_inv(nvm)
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
techage.set_activeformspec(pos, clicker)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
for i = 1,8 do
|
||||
if fields["get"..i] ~= nil then
|
||||
inv_take_from_chest(pos, i)
|
||||
break
|
||||
elseif fields["add"..i] ~= nil then
|
||||
inv_add_to_chest(pos, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
if fields.unlock then
|
||||
unlock_chests(pos, player)
|
||||
end
|
||||
if fields.assignment then
|
||||
M(pos):set_int("assignment", fields.assignment == "true" and 1 or 0)
|
||||
end
|
||||
if fields.priority then
|
||||
M(pos):set_int("priority", fields.priority == "true" and 1 or 0)
|
||||
end
|
||||
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return inv:is_empty("main") and inv_empty(nvm)
|
||||
end
|
||||
|
||||
local function on_rotate(pos, node, user, mode, new_param2)
|
||||
if get_stacksize(pos) == STACK_SIZE then
|
||||
return screwdriver.rotate_simple(pos, node, user, mode, new_param2)
|
||||
else
|
||||
return screwdriver.disallow(pos, node, user, mode, new_param2)
|
||||
end
|
||||
end
|
||||
|
||||
local function after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
convert_to_chest_again(pos, oldnode, digger)
|
||||
end
|
||||
|
||||
minetest.register_node("techage:ta4_chest", {
|
||||
description = DESCRIPTION,
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta4.png^techage_frame_ta4_top.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_front_ta4.png^techage_appl_warehouse.png",
|
||||
},
|
||||
|
||||
on_construct = function(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('main', 8)
|
||||
end,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local node = minetest.get_node(pos)
|
||||
if dummy_chest_behind(pos, node) then
|
||||
minetest.remove_node(pos)
|
||||
return true
|
||||
end
|
||||
if search_chest_in_front(pos, node) then
|
||||
node.name = "techage:ta4_chest_dummy"
|
||||
minetest.swap_node(pos, node)
|
||||
M(pos):set_int("param2", node.param2)
|
||||
else
|
||||
local nvm = techage.get_nvm(pos)
|
||||
gen_inv(nvm)
|
||||
local number = techage.add_node(pos, "techage:ta4_chest")
|
||||
M(pos):set_string("owner", placer:get_player_name())
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
M(pos):set_string("infotext", DESCRIPTION.." "..number)
|
||||
end
|
||||
end,
|
||||
|
||||
techage_set_numbers = function(pos, numbers, player_name)
|
||||
return techage.logic.set_numbers(pos, numbers, player_name, DESCRIPTION)
|
||||
end,
|
||||
|
||||
on_rotate = on_rotate,
|
||||
on_rightclick = on_rightclick,
|
||||
on_receive_fields = on_receive_fields,
|
||||
can_dig = can_dig,
|
||||
after_dig_node = after_dig_node,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
|
||||
on_metadata_inventory_put = on_metadata_inventory_put,
|
||||
on_metadata_inventory_move = on_metadata_inventory_move,
|
||||
on_metadata_inventory_take = on_metadata_inventory_take,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("techage:ta4_chest_dummy", {
|
||||
description = DESCRIPTION,
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta4.png^techage_frame_ta4_top.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_front_ta4.png^techage_appl_warehouse.png",
|
||||
},
|
||||
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
end,
|
||||
paramtype2 = "facedir",
|
||||
diggable = false,
|
||||
groups = {not_in_creative_inventory = 1},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
|
||||
techage.register_node({"techage:ta4_chest"}, {
|
||||
on_pull_item = function(pos, in_dir, num, item_name)
|
||||
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 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 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_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "count" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return get_count(nvm, tonumber(payload or 0) or 0)
|
||||
elseif topic == "itemstring" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return get_itemstring(nvm, tonumber(payload or 0) or 0)
|
||||
elseif topic == "storesize" then
|
||||
return get_stacksize(pos)
|
||||
elseif topic == "state" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return inv_state(nvm)
|
||||
else
|
||||
return "unsupported"
|
||||
end
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
if topic == 140 and payload[1] == 1 then -- Inventory Item Count
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return 0, {get_count(nvm, tonumber(payload[2] or 0) or 0)}
|
||||
elseif topic == 140 and payload[1] == 2 then -- Inventory Item Name
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return 0, get_itemstring(nvm, tonumber(payload[2] or 0) or 0)
|
||||
elseif topic == 140 and payload[1] == 3 then -- storesize
|
||||
return 0, {get_stacksize(pos)}
|
||||
elseif topic == 131 then -- Chest State
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return 0, {inv_state_num(nvm)}
|
||||
else
|
||||
return 2, ""
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
techage.register_node({"techage:ta4_chest_dummy"}, {
|
||||
on_pull_item = function(pos, in_dir, num, item_name)
|
||||
local fc_pos = get_front_chest_pos(pos)
|
||||
local res = tube_take_from_chest(fc_pos, item_name, num)
|
||||
if techage.is_activeformspec(fc_pos) then
|
||||
M(fc_pos):set_string("formspec", formspec(fc_pos))
|
||||
end
|
||||
return res
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local fc_pos = get_front_chest_pos(pos)
|
||||
local res = tube_add_to_chest(fc_pos, stack)
|
||||
if techage.is_activeformspec(fc_pos) then
|
||||
M(fc_pos):set_string("formspec", formspec(fc_pos))
|
||||
end
|
||||
return res
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local fc_pos = get_front_chest_pos(pos)
|
||||
local res = tube_add_to_chest(fc_pos, stack)
|
||||
if techage.is_activeformspec(fc_pos) then
|
||||
M(fc_pos):set_string("formspec", formspec(fc_pos))
|
||||
end
|
||||
return res
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_lbm({
|
||||
label = "Repair Dummy Chests",
|
||||
name = "techage:chest_dummy",
|
||||
nodenames = {"techage:ta4_chest_dummy"},
|
||||
run_at_every_load = true,
|
||||
action = function(pos, node)
|
||||
if not part_of_a_chain(pos, node) then
|
||||
minetest.swap_node(pos, {name = "techage:ta4_chest", param2 = node.param2})
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:ta4_chest",
|
||||
recipe = {"techage:chest_ta4"}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:chest_ta4",
|
||||
recipe = {"techage:ta4_chest"}
|
||||
})
|
||||
@@ -0,0 +1,334 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA4 Injector
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
local tooltip = S("Switch to pull mode \nto pull items out of inventory slots \naccording the injector configuration")
|
||||
local Tube = techage.Tube
|
||||
|
||||
local STANDBY_TICKS = 2
|
||||
local COUNTDOWN_TICKS = 3
|
||||
local CYCLE_TIME = 4
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
local pull_mode = dump(nvm.pull_mode or false)
|
||||
return "size[8,7.2]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;7.8,0.5;#c6e8ff]"..
|
||||
"label[3,-0.1;"..minetest.colorize("#000000", S("Injector")).."]"..
|
||||
techage.question_mark_help(8, S("Configure up to 8 items \nto be pushed by the injector"))..
|
||||
"list[context;filter;0,0.8;8,1;]"..
|
||||
"image_button[2,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[2,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"checkbox[3.5,1.9;pull_mode;"..S("pull mode")..";"..pull_mode.."]"..
|
||||
"tooltip[3.5,1.9;2,0.8;"..tooltip..";#0C3D32;#FFFFFF]"..
|
||||
"list[current_player;main;0,3.5;8,4;]"..
|
||||
"listring[context;filter]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if CRD(pos).State:get_state(nvm) ~= techage.STOPPED then
|
||||
return 0
|
||||
end
|
||||
|
||||
local inv = M(pos):get_inventory()
|
||||
local list = inv:get_list(listname)
|
||||
local cdr = CRD(pos)
|
||||
if list[index]:get_count() < cdr.num_items then
|
||||
local num = math.min(cdr.num_items - list[index]:get_count(), stack:get_count()) + list[index]:get_count()
|
||||
stack:set_count(num)
|
||||
inv:set_stack(listname, index, stack)
|
||||
return 0
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if CRD(pos).State:get_state(nvm) ~= techage.STOPPED then
|
||||
return 0
|
||||
end
|
||||
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_stack(listname, index, nil)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function pull_items(pos, out_dir, idx, name, num)
|
||||
local inv, listname = techage.get_inv_access(pos, out_dir, "pull")
|
||||
if inv and listname then
|
||||
if idx and idx ~= 0 then
|
||||
local stack = inv:get_stack(listname, idx)
|
||||
if stack and not stack:is_empty() and stack:get_name() == name then
|
||||
local taken = stack:take_item(num)
|
||||
inv:set_stack(listname, idx, stack)
|
||||
return (taken:get_count() > 0) and taken or nil
|
||||
end
|
||||
else
|
||||
local taken = inv:remove_item(listname, {name = name, count = num})
|
||||
return (taken:get_count() > 0) and taken or nil
|
||||
end
|
||||
else
|
||||
return techage.pull_items(pos, out_dir, num, name)
|
||||
end
|
||||
end
|
||||
|
||||
local function push_items(pos, out_dir, idx, items)
|
||||
local inv, listname, callafter, dpos = techage.get_inv_access(pos, out_dir, "push")
|
||||
if inv and listname then
|
||||
if idx and idx ~= 0 then
|
||||
if idx > inv:get_size(listname) then
|
||||
return false
|
||||
end
|
||||
local stack = inv:get_stack(listname, idx)
|
||||
if stack:item_fits(items) then
|
||||
stack:add_item(items)
|
||||
inv:set_stack(listname, idx, stack)
|
||||
if callafter then
|
||||
callafter(dpos)
|
||||
end
|
||||
return true
|
||||
end
|
||||
else
|
||||
if inv:room_for_item(listname, items) then
|
||||
inv:add_item(listname, items)
|
||||
if callafter then
|
||||
callafter(dpos)
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
else
|
||||
local taken = items:get_count()
|
||||
local leftover = techage.push_items(pos, out_dir, items, idx)
|
||||
if not leftover or leftover == false then
|
||||
return false -- No items placed
|
||||
elseif leftover ~= true then
|
||||
-- One or more items placed?
|
||||
if leftover:get_count() < taken then
|
||||
-- place the rest back
|
||||
local pull_dir = M(pos):get_int("pull_dir")
|
||||
techage.unpull_items(pos, pull_dir, leftover)
|
||||
return true -- Some items placed
|
||||
end
|
||||
return false -- No items placed
|
||||
end
|
||||
return true -- All items placed
|
||||
end
|
||||
end
|
||||
|
||||
local function unpull_items(pos, out_dir, idx, items)
|
||||
local inv, listname = techage.get_inv_access(pos, out_dir, "unpull")
|
||||
if inv and listname then
|
||||
if idx and idx ~= 0 then
|
||||
local stack = inv:get_stack(listname, idx)
|
||||
stack:add_item(items)
|
||||
inv:set_stack(listname, idx, stack)
|
||||
else
|
||||
inv:add_item(listname, items)
|
||||
end
|
||||
else
|
||||
techage.unpull_items(pos, out_dir, items)
|
||||
end
|
||||
end
|
||||
|
||||
local function pushing(pos, crd, meta, nvm)
|
||||
local pull_dir = meta:get_int("pull_dir")
|
||||
local push_dir = meta:get_int("push_dir")
|
||||
local inv = M(pos):get_inventory()
|
||||
local filter = inv:get_list("filter")
|
||||
local pushed = false
|
||||
local pulled = false
|
||||
|
||||
for idx, item in ipairs(filter) do
|
||||
local name = item:get_name()
|
||||
local num = math.min(item:get_count(), crd.num_items)
|
||||
if name ~= "" and num > 0 then
|
||||
local items = pull_items(pos, pull_dir, nvm.pull_mode and idx, name, num)
|
||||
if items ~= nil then
|
||||
pulled = true
|
||||
if push_items(pos, push_dir, not nvm.pull_mode and idx, items) then
|
||||
pushed = true
|
||||
else
|
||||
-- place item back - destination is full or unreachable
|
||||
unpull_items(pos, pull_dir, nvm.pull_mode and idx, items)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not pulled then
|
||||
crd.State:idle(pos, nvm)
|
||||
elseif not pushed then
|
||||
crd.State:blocked(pos, nvm)
|
||||
else
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
end
|
||||
end
|
||||
|
||||
local function node_timer(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
pushing(pos, crd, M(pos), nvm)
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if fields.pull_mode then
|
||||
nvm.pull_mode = fields.pull_mode == "true"
|
||||
end
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_appl_pusher.png^[transformR180]^techage_frame_ta#.png^techage_appl_injector.png",
|
||||
"techage_appl_pusher.png^techage_frame_ta#.png^techage_appl_injector.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
{
|
||||
name = "techage_appl_pusher14.png^[transformR180]^techage_frame14_ta#.png^techage_appl_injector14.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "techage_appl_pusher14.png^techage_frame14_ta#.png^techage_appl_injector14.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
-- push item through the injector in opposit direction
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
return in_dir == M(pos):get_int("pull_dir") and techage.safe_push_items(pos, in_dir, stack)
|
||||
end,
|
||||
is_pusher = true, -- is a pulling/pushing node
|
||||
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local _, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("injector", S("Injector"), tiles, {
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
quick_start = node_timer,
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = M(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
meta:set_int("pull_dir", techage.side_to_outdir("L", node.param2))
|
||||
meta:set_int("push_dir", techage.side_to_outdir("R", node.param2))
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('filter', 8)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end,
|
||||
ta_rotate_node = function(pos, node, new_param2)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if CRD(pos).State:get_state(nvm) == techage.STOPPED then
|
||||
Tube:after_dig_node(pos)
|
||||
minetest.swap_node(pos, {name = node.name, param2 = new_param2})
|
||||
Tube:after_place_node(pos)
|
||||
local meta = M(pos)
|
||||
meta:set_int("pull_dir", techage.side_to_outdir("L", new_param2))
|
||||
meta:set_int("push_dir", techage.side_to_outdir("R", new_param2))
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
allow_metadata_inventory_move = function() return 0 end,
|
||||
on_receive_fields = on_receive_fields,
|
||||
node_timer = node_timer,
|
||||
on_rotate = screwdriver.disallow,
|
||||
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,0,1,4},
|
||||
}, {false, false, true, true})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "default:steel_ingot", ""},
|
||||
{"", "techage:ta3_pusher_pas", ""},
|
||||
{"", "basic_materials:ic", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "techage:aluminum", ""},
|
||||
{"", "techage:ta4_pusher_pas", ""},
|
||||
{"", "basic_materials:ic", ""},
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,264 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2023 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA5 Hyperloop Chest
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local S2P = minetest.string_to_pos
|
||||
local P2S = minetest.pos_to_string
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local TA4_INV_SIZE = 32
|
||||
local EX_POINTS = 15
|
||||
|
||||
local hyperloop = techage.hyperloop
|
||||
local remote_pos = techage.hyperloop.remote_pos
|
||||
local shared_inv = techage.shared_inv
|
||||
local menu = techage.menu
|
||||
|
||||
local function formspec(pos)
|
||||
local ndef = minetest.registered_nodes["techage:ta5_hl_chest"]
|
||||
local status = M(pos):get_string("conn_status")
|
||||
if hyperloop.is_server(pos) then
|
||||
local title = ndef.description .. " " .. status
|
||||
return "size[8,9]"..
|
||||
"box[0,-0.1;7.8,0.5;#c6e8ff]" ..
|
||||
"label[0.2,-0.1;" .. minetest.colorize( "#000000", title) .. "]" ..
|
||||
"list[context;main;0,1;8,4;]"..
|
||||
"list[current_player;main;0,5.3;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
elseif hyperloop.is_client(pos) then
|
||||
local title = ndef.description .. " " .. status
|
||||
return "size[8,9]"..
|
||||
"box[0,-0.1;7.8,0.5;#c6e8ff]" ..
|
||||
"label[0.2,-0.1;" .. minetest.colorize( "#000000", title) .. "]" ..
|
||||
"label[0.2,2;Inventory access on this node is disabled\ndue to minetest engine issues!]" ..
|
||||
"list[current_player;main;0,5.3;8,4;]"
|
||||
else
|
||||
return menu.generate_formspec(pos, ndef, hyperloop.SUBMENU)
|
||||
end
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
if techage.hyperloop.is_client(pos) then
|
||||
return 0
|
||||
end
|
||||
shared_inv.before_inv_access(pos, listname)
|
||||
local inv = minetest.get_inventory({type="node", pos=pos})
|
||||
if inv and inv:room_for_item(listname, stack) then
|
||||
return stack:get_count()
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
if techage.hyperloop.is_client(pos) then
|
||||
return 0
|
||||
end
|
||||
shared_inv.before_inv_access(pos, listname)
|
||||
local inv = minetest.get_inventory({type="node", pos=pos})
|
||||
if inv and inv:contains_item(listname, stack) then
|
||||
return stack:get_count()
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
if shared_inv.before_inv_access(pos, "main") then
|
||||
return 0
|
||||
end
|
||||
if techage.hyperloop.is_client(pos) then
|
||||
return 0
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
minetest.register_node("techage:ta5_hl_chest", {
|
||||
description = S("TA5 Hyperloop Chest"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta4.png^techage_frame_ta5_top.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta5.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_chest_front_ta4.png",
|
||||
},
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('main', 32)
|
||||
local number = techage.add_node(pos, "techage:ta5_hl_chest")
|
||||
meta:set_string("node_number", number)
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
meta:set_string("formspec", formspec(pos))
|
||||
meta:set_string("infotext", S("TA5 Hyperloop Chest").." "..number)
|
||||
hyperloop.after_place_node(pos, placer, "chest")
|
||||
end,
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
if techage.get_expoints(player) >= EX_POINTS then
|
||||
if techage.menu.eval_input(pos, hyperloop.SUBMENU, fields) then
|
||||
hyperloop.after_formspec(pos, fields)
|
||||
shared_inv.on_rightclick(pos, player, "main")
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_timer = shared_inv.node_timer,
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
shared_inv.on_rightclick(pos, clicker, "main")
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
end,
|
||||
can_dig = function(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
shared_inv.before_inv_access(pos, "main")
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
return inv:is_empty("main")
|
||||
end,
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
hyperloop.after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||
techage.del_mem(pos)
|
||||
end,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
on_metadata_inventory_put = shared_inv.after_inv_access,
|
||||
on_metadata_inventory_take = shared_inv.after_inv_access,
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
|
||||
techage.register_node({"techage:ta5_hl_chest"}, {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
pos = remote_pos(pos)
|
||||
if pos then
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta then
|
||||
return meta:get_inventory(), "main"
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num, item_name)
|
||||
pos = remote_pos(pos)
|
||||
if pos then
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta then
|
||||
local inv = meta:get_inventory()
|
||||
if inv then
|
||||
return techage.get_items(pos, inv, "main", num)
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
if techage.hyperloop.is_paired(pos) then
|
||||
pos = remote_pos(pos)
|
||||
if pos then
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta then
|
||||
local inv = meta:get_inventory()
|
||||
if inv then
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
pos = remote_pos(pos)
|
||||
if pos then
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta then
|
||||
local inv = meta:get_inventory()
|
||||
if inv then
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "state" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta then
|
||||
local inv = meta:get_inventory()
|
||||
if inv then
|
||||
return techage.get_inv_state(inv, "main")
|
||||
end
|
||||
end
|
||||
return "error"
|
||||
elseif topic == "count" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta then
|
||||
local inv = meta:get_inventory()
|
||||
if inv then
|
||||
return techage.check_inv_item(inv, "main", payload)
|
||||
end
|
||||
end
|
||||
else
|
||||
return "unsupported"
|
||||
end
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
if topic == 131 then -- Chest State
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta then
|
||||
local inv = meta:get_inventory()
|
||||
if inv then
|
||||
return 0, {techage.get_inv_state_num(inv, "main")}
|
||||
end
|
||||
end
|
||||
elseif topic == 192 and payload and type(payload) == "string" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta then
|
||||
local inv = meta:get_inventory()
|
||||
if inv then
|
||||
return 0, {techage.check_inv_item(inv, "main", payload)}
|
||||
end
|
||||
end
|
||||
else
|
||||
return 2, ""
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:ta5_hl_chest",
|
||||
recipe = {"techage:chest_ta4", "techage:ta5_aichip"}
|
||||
})
|
||||
|
||||
minetest.register_on_mods_loaded(function()
|
||||
if not minetest.global_exists("hyperloop") then
|
||||
minetest.clear_craft({output = "techage:ta5_hl_chest"})
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,351 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2025 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Water Remover
|
||||
|
||||
The Water Remover removes water from an area of up to 21 x 21 x 80 m.
|
||||
It is mainly used to drain caves. The water remover is placed at the highest
|
||||
point of the cave and removes the water from the cave to the lowest point.
|
||||
It digs one water block every two seconds.
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S2P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
local NDEF = function(pos) return minetest.registered_nodes[techage.get_node_lvm(pos).name] or {} end
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
|
||||
local S = techage.S
|
||||
local Pipe = techage.LiquidPipe
|
||||
local liquid = networks.liquid
|
||||
local menu = techage.menu
|
||||
|
||||
local TITLE = S("Water Remover")
|
||||
local CYCLE_TIME = 2
|
||||
local STANDBY_TICKS = 4
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local Side2Facedir = {F=0, R=1, B=2, L=3, D=4, U=5}
|
||||
|
||||
local MENU = {
|
||||
{
|
||||
type = "dropdown",
|
||||
choices = "9x9,11x11,13x13,15x15,17x17,19x19,21x21",
|
||||
name = "area_size",
|
||||
label = S("Area size"),
|
||||
tooltip = S("Area where the water is to be removed"),
|
||||
default = "9",
|
||||
values = {9,11,13,15,17,19,21},
|
||||
},
|
||||
{
|
||||
type = "numbers",
|
||||
name = "area_depth",
|
||||
label = S("Area depth"),
|
||||
tooltip = S("Depth of the area where the water is to be removed (1-80)"),
|
||||
default = "10",
|
||||
check = function(value, player_name) return tonumber(value) >= 1 and tonumber(value) <= 80 end,
|
||||
},
|
||||
{
|
||||
type = "output",
|
||||
name = "curr_depth",
|
||||
label = S("Current depth"),
|
||||
tooltip = S("Current working depth of the water remover"),
|
||||
},
|
||||
}
|
||||
|
||||
local WaterNodes = {
|
||||
"default:water_source",
|
||||
"default:river_water_source",
|
||||
-- Add more water nodes here
|
||||
}
|
||||
|
||||
core.register_node("techage:air", {
|
||||
description = "Techage Air",
|
||||
inventory_image = "air.png",
|
||||
wield_image = "air.png",
|
||||
drawtype = "airlike",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
walkable = false,
|
||||
pointable = false,
|
||||
diggable = false,
|
||||
buildable_to = true,
|
||||
floodable = false, -- This is important!
|
||||
air_equivalent = true,
|
||||
drop = "",
|
||||
groups = {not_in_creative_inventory=1},
|
||||
})
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
return "size[8,4.4]" ..
|
||||
"box[0,-0.1;7.8,0.5;#c6e8ff]" ..
|
||||
"label[3.0,-0.1;" .. minetest.colorize( "#000000", TITLE) .. "]" ..
|
||||
"image[6.4,0.8;1,1;" .. techage.get_power_image(pos, nvm) .. "]" ..
|
||||
"image_button[6.4,2.2;1,1;".. self:get_state_button_image(nvm) .. ";state_button;]" ..
|
||||
"tooltip[6.4,2.2;1,1;" .. self:get_state_tooltip(nvm) .. "]" ..
|
||||
menu.generate_formspec_container(pos, NDEF(pos), MENU, 0.0, 5.8)
|
||||
end
|
||||
|
||||
local function play_sound(pos)
|
||||
minetest.sound_play("techage_scoopwater", {
|
||||
pos = pos,
|
||||
gain = 1.5,
|
||||
max_hear_distance = 15})
|
||||
end
|
||||
|
||||
local function on_node_state_change(pos, old_state, new_state)
|
||||
local mem = techage.get_mem(pos)
|
||||
local owner = M(pos):get_string("owner")
|
||||
mem.co = nil
|
||||
techage.unmark_position(owner)
|
||||
end
|
||||
|
||||
local function get_pos(pos, facedir, side, steps)
|
||||
facedir = (facedir + Side2Facedir[side]) % 4
|
||||
local dir = vector.multiply(minetest.facedir_to_dir(facedir), steps or 1)
|
||||
return vector.add(pos, dir)
|
||||
end
|
||||
|
||||
local function get_dig_pos(pos, xoffs, zoffs)
|
||||
return {x = pos.x + xoffs - 1, y = pos.y, z = pos.z + zoffs - 1}
|
||||
end
|
||||
|
||||
-- pos is the quarry pos
|
||||
local function get_corner_positions(pos, facedir, hole_diameter)
|
||||
local _pos = get_pos(pos, facedir, "L")
|
||||
local pos1 = get_pos(_pos, facedir, "F", math.floor((hole_diameter - 1) / 2))
|
||||
local pos2 = get_pos(_pos, facedir, "B", math.floor((hole_diameter - 1) / 2))
|
||||
pos2 = get_pos(pos2, facedir, "L", hole_diameter - 1)
|
||||
if pos1.x > pos2.x then pos1.x, pos2.x = pos2.x, pos1.x end
|
||||
if pos1.y > pos2.y then pos1.y, pos2.y = pos2.y, pos1.y end
|
||||
if pos1.z > pos2.z then pos1.z, pos2.z = pos2.z, pos1.z end
|
||||
return pos1, pos2
|
||||
end
|
||||
|
||||
local function is_water(pos1, pos2)
|
||||
return #minetest.find_nodes_in_area(pos1, pos2, WaterNodes) > 0
|
||||
end
|
||||
|
||||
local function mark_area(pos1, pos2, owner)
|
||||
pos1.y = pos1.y + 0.2
|
||||
techage.mark_cube(owner, pos1, pos2, TITLE, "#FF0000", 40)
|
||||
pos1.y = pos1.y - 0.2
|
||||
end
|
||||
|
||||
local function dig_water_node(mypos, dig_pos)
|
||||
local outdir = M(mypos):get_int("outdir")
|
||||
local node = techage.get_node_lvm(dig_pos)
|
||||
if node.name == "default:water_source" then
|
||||
minetest.swap_node(dig_pos, {name = "techage:air", param2 = 0})
|
||||
local leftover = liquid.put(mypos, Pipe, outdir, "techage:water", 1)
|
||||
if leftover and leftover > 0 then
|
||||
return "tank full"
|
||||
end
|
||||
return "ok"
|
||||
end
|
||||
return "no_water"
|
||||
end
|
||||
|
||||
local function drain_task(pos, crd, nvm)
|
||||
nvm.area_depth = M(pos):get_int("area_depth")
|
||||
nvm.area_size = M(pos):get_int("area_size")
|
||||
local y_first = pos.y
|
||||
local y_last = y_first - nvm.area_depth + 1
|
||||
local facedir = minetest.get_node(pos).param2
|
||||
local owner = M(pos):get_string("owner")
|
||||
local cnt = 0
|
||||
|
||||
local pos1, pos2 = get_corner_positions(pos, facedir, nvm.area_size)
|
||||
nvm.level = 1
|
||||
--print("drain_task", nvm.area_depth, nvm.area_size, y_first, y_last, M(pos):get_int("area_depth"))
|
||||
for y_curr = y_first, y_last, -1 do
|
||||
pos1.y = y_curr
|
||||
pos2.y = y_curr
|
||||
|
||||
-- Restarting the server can detach the coroutine data.
|
||||
-- Therefore, read nvm again.
|
||||
nvm = techage.get_nvm(pos)
|
||||
nvm.level = y_first - y_curr + 1
|
||||
|
||||
if minetest.is_area_protected(pos1, pos2, owner, 5) then
|
||||
crd.State:fault(pos, nvm, S("area is protected"))
|
||||
return
|
||||
end
|
||||
|
||||
if is_water(pos1, pos2) then
|
||||
mark_area(pos1, pos2, owner)
|
||||
M(pos):set_string("curr_depth", nvm.level)
|
||||
coroutine.yield()
|
||||
|
||||
for zoffs = 1, nvm.area_size do
|
||||
for xoffs = 1, nvm.area_size do
|
||||
local qpos = get_dig_pos(pos1, xoffs, zoffs)
|
||||
while true do
|
||||
local res = dig_water_node(pos, qpos)
|
||||
if res == "tank full" then
|
||||
crd.State:blocked(pos, nvm, S("tank full"))
|
||||
techage.unmark_position(owner)
|
||||
coroutine.yield()
|
||||
elseif res == "no_water" then
|
||||
break
|
||||
else
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
if cnt % 4 == 0 then
|
||||
play_sound(pos)
|
||||
end
|
||||
cnt = cnt + 1
|
||||
coroutine.yield()
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
coroutine.yield()
|
||||
end
|
||||
techage.unmark_position(owner)
|
||||
end
|
||||
end
|
||||
M(pos):set_string("curr_depth", nvm.level)
|
||||
crd.State:stop(pos, nvm, S("finished"))
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local mem = techage.get_mem(pos)
|
||||
if not mem.co then
|
||||
mem.co = coroutine.create(drain_task)
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local _, err = coroutine.resume(mem.co, pos, crd, nvm)
|
||||
if err then
|
||||
minetest.log("error", "[" .. TITLE .. "] at pos " .. minetest.pos_to_string(pos) .. " " .. err)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_rightclick(pos, node, clicker)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
techage.set_activeformspec(pos, clicker)
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if menu.eval_input(pos, MENU, fields) then
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
else
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
end
|
||||
|
||||
local function after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||
Pipe:after_dig_node(pos)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
techage.del_mem(pos)
|
||||
end
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_hole_pipe.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_quarry_left.png",
|
||||
"techage_filling_ta#.png^techage_appl_liquidsampler.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_liquidsampler.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_hole_pipe.png",
|
||||
{
|
||||
name = "techage_frame14_ta#.png^techage_quarry_left14.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_appl_liquidsampler.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_liquidsampler.png^techage_frame_ta#.png",
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "depth" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return nvm.level or 0
|
||||
else
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
if topic == 153 then -- Current Depth
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return 0, {nvm.level or 0}
|
||||
else
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local _, _, node_name_ta4 =
|
||||
techage.register_consumer("waterremover", TITLE, tiles, {
|
||||
drawtype = "normal",
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
on_state_change = on_node_state_change,
|
||||
after_place_node = function(pos, placer)
|
||||
M(pos):set_string("owner", placer:get_player_name())
|
||||
M(pos):set_int("outdir", networks.side_to_outdir(pos, "R"))
|
||||
M(pos):set_int("area_depth", 10)
|
||||
M(pos):set_int("area_size", 9)
|
||||
Pipe:after_place_node(pos)
|
||||
end,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
on_rightclick = on_rightclick,
|
||||
after_dig_node = after_dig_node,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,0,0,1},
|
||||
power_consumption = {0,0,0,10},
|
||||
}, {false, false, false, true}
|
||||
)
|
||||
|
||||
liquid.register_nodes({
|
||||
"techage:ta4_waterremover_pas", "techage:ta4_waterremover_act",
|
||||
}, Pipe, "pump", {"R"}, {})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", "techage:ta3_liquidsampler_pas", ""},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user