Add recipeblock and mba_detector, improve ta4 pump and ta4 autocrafter

This commit is contained in:
Joachim Stolberg 2021-11-28 14:42:18 +01:00
parent a2d39706cf
commit fea1a6981c
20 changed files with 603 additions and 62 deletions

View File

@ -189,6 +189,17 @@ local function normalize(item_list)
return item_list return item_list
end 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) local function on_output_change(pos, inventory, stack)
if not stack then if not stack then
inventory:set_list("output", {}) inventory:set_list("output", {})
@ -212,6 +223,47 @@ local function on_output_change(pos, inventory, stack)
after_recipe_change(pos, inventory) after_recipe_change(pos, inventory)
end end
local function determine_recipe_items(pos, input)
if input and type(input) == "string" then
-- Test if "<node-number>.<recipe-number>" input
local num, idx = unpack(string.split(input, ".", false, 1))
if num and idx then
input = get_input_from_recipeblock(pos, num, idx)
end
if input 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
end
local function on_new_recipe(pos, input)
local items = determine_recipe_items(pos, input)
if items then
input = {
method = "normal",
width = 3,
items = items,
}
local output, _ = minetest.get_craft_result(input)
if output.item:get_name() ~= "" then
local inv = M(pos):get_inventory()
for i = 1, 9 do
inv:set_stack("recipe", i, input.items[i])
end
after_recipe_change(pos, inv)
end
else
local inv = M(pos):get_inventory()
inv:set_list("recipe", {})
after_recipe_change(pos, inv)
end
end
local function allow_metadata_inventory_put(pos, listname, index, stack, player) local function allow_metadata_inventory_put(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then if minetest.is_protected(pos, player:get_player_name()) then
@ -346,6 +398,8 @@ tiles.act = {
}, },
} }
local INFO = [[Commands: 'state', 'recipe']]
local tubing = { local tubing = {
on_inv_request = function(pos, in_dir, access_type) on_inv_request = function(pos, in_dir, access_type)
if access_type == "push" then if access_type == "push" then
@ -378,7 +432,20 @@ local tubing = {
end end
end, end,
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
return CRD(pos).State:on_receive_message(pos, topic, payload) if topic == "recipe" and CRD(pos).stage == 4 then
if payload and payload ~= "" then
local inv = M(pos):get_inventory()
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 == "info" and CRD(pos).stage == 4 then
return INFO
else
return CRD(pos).State:on_receive_message(pos, topic, payload)
end
end, end,
on_node_load = function(pos) on_node_load = function(pos)
CRD(pos).State:on_node_load(pos) CRD(pos).State:on_node_load(pos)
@ -410,7 +477,7 @@ local node_name_ta2, node_name_ta3, node_name_ta4 =
num_items = {0,1,2,4}, num_items = {0,1,2,4},
power_consumption = {0,4,6,9}, power_consumption = {0,4,6,9},
}, },
{false, true, true, false}) -- TA2/TA3 {false, true, true, true}) -- TA2/TA3/TA4
minetest.register_craft({ minetest.register_craft({
output = node_name_ta2, output = node_name_ta2,
@ -430,9 +497,18 @@ minetest.register_craft({
}, },
}) })
minetest.register_craft({
output = node_name_ta4,
recipe = {
{"", "default:diamond", ""},
{"", node_name_ta3, ""},
{"", "techage:ta4_wlanchip", ""},
},
})
local Cable = techage.ElectricCable local Cable = techage.ElectricCable
local power = networks.power local power = networks.power
techage.register_node_for_v1_transition({"techage:ta3_autocrafter_pas"}, function(pos, node) techage.register_node_for_v1_transition({"techage:ta3_autocrafter_pas", "techage:ta4_autocrafter_pas"}, function(pos, node)
power.update_network(pos, nil, Cable) power.update_network(pos, nil, Cable)
end) end)

View File

@ -0,0 +1,244 @@
--[[
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"},
},
})

View File

@ -547,7 +547,7 @@ end
minetest.register_chatcommand("ta_send", { minetest.register_chatcommand("ta_send", {
description = minetest.formspec_escape( description = minetest.formspec_escape(
"Send a techage command to the block with the number given: /ta_send <number> <topic> [<data>]"), "Send a techage command to the block with the number given: /ta_send <number> <command> [<data>]"),
func = function(name, param) func = function(name, param)
local num, cmnd, payload = param:match('^([0-9]+)%s+(%w+)%s*(.*)$') local num, cmnd, payload = param:match('^([0-9]+)%s+(%w+)%s*(.*)$')
@ -563,6 +563,43 @@ minetest.register_chatcommand("ta_send", {
return false, "Destination block is protected" return false, "Destination block is protected"
end end
end end
return false, "Syntax: /ta_send <number> <topic> [<data>]" return false, "Syntax: /ta_send <number> <command> [<data>]"
end
})
minetest.register_chatcommand("expoints", {
privs = {
server = true
},
func = function(name, param)
local player_name, points = param:match("^(%S+)%s*(%d*)$")
if player_name then
local player = minetest.get_player_by_name(player_name)
if player then
if points and points ~= "" then
if techage.set_expoints(player, tonumber(points)) then
return true, "The player "..player_name.." now has "..points.." experience points."
end
else
points = techage.get_expoints(player)
return true, "The player "..player_name.." has "..points.." experience points."
end
else
return false, "Unknown player "..player_name
end
end
return false, "Syntax error! Syntax: /expoints <name> [<points>]"
end
})
minetest.register_chatcommand("my_expoints", {
func = function(name, param)
local player = minetest.get_player_by_name(name)
if player then
local points = techage.get_expoints(player)
if points then
return true, "You have "..points.." experience points."
end
end
end end
}) })

View File

@ -20,6 +20,36 @@ local S = techage.S
local flylib = {} local flylib = {}
local function lvect_add_vec(lvect1, offs)
if not lvect1 or not offs then return end
local lvect2 = {}
for _, v in ipairs(lvect1) do
lvect2[#lvect2 + 1] = vector.add(v, offs)
end
return lvect2
end
local function lvect_add(lvect1, lvect2)
if not lvect1 or not lvect2 then return end
local lvect3 = {}
for i, v in ipairs(lvect1) do
lvect3[#lvect3 + 1] = vector.add(v, lvect2[i])
end
return lvect3
end
local function lvect_subtract(lvect1, lvect2)
if not lvect1 or not lvect2 then return end
local lvect3 = {}
for i, v in ipairs(lvect1) do
lvect3[#lvect3 + 1] = vector.subtract(v, lvect2[i])
end
return lvect3
end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- to_path function for the fly/move path -- to_path function for the fly/move path
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -294,7 +324,10 @@ end
local function determine_dir(pos1, pos2) local function determine_dir(pos1, pos2)
local vdist = vector.subtract(pos2, pos1) local vdist = vector.subtract(pos2, pos1)
local ndist = vector.length(vdist) local ndist = vector.length(vdist)
return vector.divide(vdist, ndist) if ndist > 0 then
return vector.divide(vdist, ndist)
end
return {x=0, y=0, z=0}
end end
local function move_entity(obj, dest_pos, dir, is_corner) local function move_entity(obj, dest_pos, dir, is_corner)
@ -413,12 +446,14 @@ minetest.register_entity("techage:move_item", {
on_step = function(self, dtime, moveresult) on_step = function(self, dtime, moveresult)
local stop_obj = function(obj, self) local stop_obj = function(obj, self)
local dest_pos = self.dest_pos
obj:move_to(self.dest_pos, true) obj:move_to(self.dest_pos, true)
obj:set_acceleration({x=0, y=0, z=0}) obj:set_acceleration({x=0, y=0, z=0})
obj:set_velocity({x=0, y=0, z=0}) obj:set_velocity({x=0, y=0, z=0})
self.dest_pos = nil self.dest_pos = nil
self.old_dist = nil self.old_dist = nil
self.ttl = 2 self.ttl = 2
return dest_pos
end end
if self.dest_pos then if self.dest_pos then
@ -431,24 +466,21 @@ minetest.register_entity("techage:move_item", {
-- Landing -- Landing
if self.lpath and self.lpath[self.path_idx] then if self.lpath and self.lpath[self.path_idx] then
if dist < 1 or dist > self.old_dist then if dist < 1 or dist > self.old_dist then
local dest_pos = self.dest_pos local dest_pos = stop_obj(obj, self)
stop_obj(obj, self)
if not moveon_entity(obj, self, dest_pos) then if not moveon_entity(obj, self, dest_pos) then
minetest.after(0.5, entity_to_node, dest_pos, obj) minetest.after(0.5, entity_to_node, dest_pos, obj)
end end
return return
end end
elseif self.handover and dist < 0.2 or dist > self.old_dist then elseif self.handover and dist < 0.2 or dist > self.old_dist then
local dest_pos = self.dest_pos local dest_pos = stop_obj(obj, self)
stop_obj(obj, self)
if not handover_to(obj, self, dest_pos) then if not handover_to(obj, self, dest_pos) then
minetest.after(0.5, entity_to_node, dest_pos, obj) minetest.after(0.5, entity_to_node, dest_pos, obj)
end end
return return
else else
if dist < 0.05 or dist > self.old_dist then if dist < 0.05 or dist > self.old_dist then
local dest_pos = self.dest_pos local dest_pos = stop_obj(obj, self)
stop_obj(obj, self)
minetest.after(0.5, entity_to_node, dest_pos, obj) minetest.after(0.5, entity_to_node, dest_pos, obj)
return return
end end
@ -513,17 +545,7 @@ local function is_simple_node(pos)
return true return true
end end
local function table_add(tbl, offs) local function move_node(pos, pos1_idx, start_pos, lpath, max_speed, height, move2to1, handover, cpos)
if not tbl or not offs then return end
local tbl2 = {}
for _, v in ipairs(tbl) do
tbl2[#tbl2 + 1] = vector.add(v, offs)
end
return tbl2
end
local function move_node(pos, pos1_idx, start_pos, lpath, max_speed, height, move2to1, handover)
local pos2 = next_path_pos(start_pos, lpath, 1) local pos2 = next_path_pos(start_pos, lpath, 1)
--print("move_node", P2S(pos), P2S(start_pos), lpath, max_speed, height, move2to1, P2S(pos2)) --print("move_node", P2S(pos), P2S(start_pos), lpath, max_speed, height, move2to1, P2S(pos2))
if pos2 then if pos2 then
@ -547,7 +569,7 @@ local function move_node(pos, pos1_idx, start_pos, lpath, max_speed, height, mov
self.base_pos = pos self.base_pos = pos
self.move2to1 = move2to1 self.move2to1 = move2to1
self.handover = handover self.handover = handover
print("move_node", P2S(start_pos), P2S(pos2), P2S(dir), P2S(pos)) --print("move_node", P2S(start_pos), P2S(pos2), P2S(dir), P2S(pos))
move_entity(obj, pos2, dir) move_entity(obj, pos2, dir)
end end
end end
@ -598,13 +620,14 @@ function flylib.move_to_other_pos(pos, move2to1)
local handover local handover
height = techage.in_range(height, 0, 1) height = techage.in_range(height, 0, 1)
max_speed = techage.in_range(max_speed, MIN_SPEED, MAX_SPEED) max_speed = techage.in_range(max_speed, MIN_SPEED, MAX_SPEED)
nvm.lpos1 = nvm.lpos1 or {}
local offs = dest_offset(lpath) local offs = dest_offset(lpath)
if move2to1 then if move2to1 then
lpath = reverse_path(lpath) lpath = reverse_path(lpath)
end end
nvm.lpos1 = nvm.lpos1 or {} -- calc destination positions
nvm.lpos2 = table_add(nvm.lpos1, offs) nvm.lpos2 = lvect_add_vec(nvm.lpos1, offs)
if move2to1 then if move2to1 then
handover = meta:contains("handoverA") and meta:get_string("handoverA") handover = meta:contains("handoverA") and meta:get_string("handoverA")

View File

@ -84,31 +84,33 @@ end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- Rotate nodes around the center -- Rotate nodes around the center
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
local function center(nodes) function techage.positions_center(lpos)
local c = {x=0, y=0, z=0} local c = {x=0, y=0, z=0}
for _,v in ipairs(nodes) do for _,v in ipairs(lpos) do
c = vector.add(c, v) c = vector.add(c, v)
end end
c = vector.divide(c, #nodes) c = vector.divide(c, #lpos)
c = vector.round(c) c = vector.round(c)
c.y = 0 c.y = 0
return c return c
end end
local function rotate_around_axis(v, c, rot) function techage.rotate_around_axis(v, c, turn)
local dx, dz = v.x - c.x, v.z - c.z local dx, dz = v.x - c.x, v.z - c.z
if rot == "l" then if turn == "l" then
return { return {
x = c.x - dz, x = c.x - dz,
y = v.y, y = v.y,
z = c.z + dx, z = c.z + dx,
} }
elseif rot == "r" then elseif turn == "r" then
return { return {
x = c.x + dz, x = c.x + dz,
y = v.y, y = v.y,
z = c.z - dx, z = c.z - dx,
} }
elseif turn == "" then
return v
else -- turn 180 degree else -- turn 180 degree
return { return {
x = c.x - dx, x = c.x - dx,
@ -119,13 +121,13 @@ local function rotate_around_axis(v, c, rot)
end end
-- Function returns a list ẃith the new node positions -- Function returns a list ẃith the new node positions
-- rot is one of "l", "r", "2l", "2r" -- turn is one of "l", "r", "2l", "2r"
-- cpos is the center pos (optional) -- cpos is the center pos (optional)
function techage.rotate_around_center(nodes1, rot, cpos) function techage.rotate_around_center(nodes1, turn, cpos)
cpos = cpos or center(nodes1) cpos = cpos or techage.positions_center(nodes1)
local nodes2 = {} local nodes2 = {}
for _,pos in ipairs(nodes1) do for _,pos in ipairs(nodes1) do
nodes2[#nodes2 + 1] = rotate_around_axis(pos, cpos, rot) nodes2[#nodes2 + 1] = techage.rotate_around_axis(pos, cpos, turn)
end end
return nodes2 return nodes2
end end
@ -471,6 +473,7 @@ function techage.add_expoint(player)
local meta = player:get_meta() local meta = player:get_meta()
if meta then if meta then
meta:set_int("techage_ex_points", meta:get_int("techage_ex_points") + 1) meta:set_int("techage_ex_points", meta:get_int("techage_ex_points") + 1)
return true
end end
end end
end end
@ -480,6 +483,7 @@ function techage.set_expoints(player, ex_points)
local meta = player:get_meta() local meta = player:get_meta()
if meta then if meta then
meta:set_int("techage_ex_points", ex_points) meta:set_int("techage_ex_points", ex_points)
return true
end end
end end
end end

View File

@ -22,6 +22,19 @@ local range = techage.in_range
techage.recipes = {} techage.recipes = {}
local GROUP_ITEMS = {
stone = "default:cobble",
wood = "default:wood",
book = "default:book",
sand = "default:sand",
leaves = "default:leaves",
stick = "default:stick",
tree = "default:tree",
vessel = "vessels:glass_bottle",
wool = "wool:white",
}
local RECIPE = { local RECIPE = {
output = {name = "", num = 0}, output = {name = "", num = 0},
waste = {name = "", num = 0}, waste = {name = "", num = 0},
@ -137,3 +150,17 @@ function techage.recipes.get_recipe(name)
return NormalizedRecipes[name] return NormalizedRecipes[name]
end end
function techage.recipes.get_default_group_item_name(item_name)
if item_name and item_name:sub(1, 6) == "group:" then
local default_name = GROUP_ITEMS[item_name:sub(7)]
if default_name then
return default_name
end
end
return item_name
end
function techage.recipes.add_group_item(group, default_item_name)
GROUP_ITEMS[group] = default_item_name
end

View File

@ -1729,7 +1729,7 @@ techage.manual_DE.aText = {
"\n", "\n",
"Siehe TA3 Pumpe.\n".. "Siehe TA3 Pumpe.\n"..
"\n".. "\n"..
"Die TA4 Pumpe pumpt 8 Einheiten Flüssigkeit alle zwei Sekunden.\n".. "Die TA4 Pumpe pumpt 8 Einheiten Flüssigkeit alle zwei Sekunden. Zusätzlich unterstützt die Pumpe das Kommando 'flowrate'. Damit kann die Gesamtdurchflussmenge durch die Pumpe abgefragt werden.\n"..
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",

View File

@ -1725,7 +1725,7 @@ techage.manual_EN.aText = {
"\n", "\n",
"See TA3 pump.\n".. "See TA3 pump.\n"..
"\n".. "\n"..
"The TA4 pump pumps 8 units of liquid every two seconds.\n".. "The TA4 pump pumps 8 units of liquid every two seconds. The pump also supports the 'flowrate' command. This means that the total flow rate through the pump can be queried. \n"..
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",

View File

@ -33,8 +33,8 @@ elseif minetest.global_exists("minecart") and minecart.version < 1.08 then
elseif minetest.global_exists("lcdlib") and lcdlib.version < 1.01 then elseif minetest.global_exists("lcdlib") and lcdlib.version < 1.01 then
minetest.log("error", "[techage] Techage requires lcdlib version 1.01 or newer!") minetest.log("error", "[techage] Techage requires lcdlib version 1.01 or newer!")
return return
elseif minetest.global_exists("safer_lua") and safer_lua.version < 1.0 then elseif minetest.global_exists("safer_lua") and safer_lua.version < 1.01 then
minetest.log("error", "[techage] Techage requires safer_lua version 1.0 or newer!") minetest.log("error", "[techage] Techage requires safer_lua version 1.01 or newer!")
return return
elseif minetest.global_exists("networks") and networks.version < 0.10 then elseif minetest.global_exists("networks") and networks.version < 0.10 then
minetest.log("error", "[techage] Techage requires networks version 0.10 or newer!") minetest.log("error", "[techage] Techage requires networks version 0.10 or newer!")
@ -187,6 +187,7 @@ dofile(MP.."/basic_machines/ta4_injector.lua")
dofile(MP.."/basic_machines/itemsource.lua") dofile(MP.."/basic_machines/itemsource.lua")
dofile(MP.."/basic_machines/recycler.lua") dofile(MP.."/basic_machines/recycler.lua")
dofile(MP.."/basic_machines/concentrator.lua") dofile(MP.."/basic_machines/concentrator.lua")
dofile(MP.."/basic_machines/recipeblock.lua")
-- Liquids II -- Liquids II
dofile(MP.."/liquids/tank.lua") dofile(MP.."/liquids/tank.lua")
@ -274,6 +275,7 @@ dofile(MP.."/logic/lua_logic.lua") -- old
dofile(MP.."/logic/logic_block.lua") -- new dofile(MP.."/logic/logic_block.lua") -- new
dofile(MP.."/logic/node_detector.lua") dofile(MP.."/logic/node_detector.lua")
dofile(MP.."/logic/player_detector.lua") dofile(MP.."/logic/player_detector.lua")
dofile(MP.."/logic/mba_detector.lua")
dofile(MP.."/logic/cart_detector.lua") dofile(MP.."/logic/cart_detector.lua")
dofile(MP.."/logic/collector.lua") dofile(MP.."/logic/collector.lua")
dofile(MP.."/logic/button_2x.lua") dofile(MP.."/logic/button_2x.lua")

View File

@ -25,6 +25,13 @@ local COUNTDOWN_TICKS = 4
local CYCLE_TIME = 2 local CYCLE_TIME = 2
local CAPA = 4 local CAPA = 4
local WRENCH_MENU = {{
type = "output",
name = "flowrate",
label = S("Total flow rate"),
tooltip = S("Total flow rate in liquid units"),
}}
local State3 = techage.NodeStates:new({ local State3 = techage.NodeStates:new({
node_name_passive = "techage:t3_pump", node_name_passive = "techage:t3_pump",
node_name_active = "techage:t3_pump_on", node_name_active = "techage:t3_pump_on",
@ -52,13 +59,15 @@ local function pumping(pos, nvm, state, capa)
liquid.untake(pos, Pipe, Flip[outdir], name, leftover) liquid.untake(pos, Pipe, Flip[outdir], name, leftover)
if leftover == taken then if leftover == taken then
state:blocked(pos, nvm) state:blocked(pos, nvm)
return return 0
end end
return taken - leftover
end end
state:keep_running(pos, nvm, COUNTDOWN_TICKS) state:keep_running(pos, nvm, COUNTDOWN_TICKS)
return return taken
end end
state:idle(pos, nvm) state:idle(pos, nvm)
return 0
end end
local function after_place_node3(pos, placer) local function after_place_node3(pos, placer)
@ -85,7 +94,7 @@ end
local function node_timer4(pos, elapsed) local function node_timer4(pos, elapsed)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
pumping(pos, nvm, State4, CAPA * 2) nvm.flowrate = (nvm.flowrate or 0) + pumping(pos, nvm, State4, CAPA * 2)
return State4:is_active(nvm) return State4:is_active(nvm)
end end
@ -235,6 +244,7 @@ minetest.register_node("techage:t4_pump", {
groups = {cracky=2}, groups = {cracky=2},
is_ground_content = false, is_ground_content = false,
sounds = default.node_sound_metal_defaults(), sounds = default.node_sound_metal_defaults(),
ta4_formspec = WRENCH_MENU,
}) })
minetest.register_node("techage:t4_pump_on", { minetest.register_node("techage:t4_pump_on", {
@ -261,7 +271,12 @@ techage.register_node({"techage:t3_pump", "techage:t3_pump_on"}, {
techage.register_node({"techage:t4_pump", "techage:t4_pump_on"}, { techage.register_node({"techage:t4_pump", "techage:t4_pump_on"}, {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
return State4:on_receive_message(pos, topic, payload) if topic == "flowrate" then
local nvm = techage.get_nvm(pos)
return nvm.flowrate or 0
else
return State4:on_receive_message(pos, topic, payload)
end
end, end,
}) })

100
logic/mba_detector.lua Normal file
View File

@ -0,0 +1,100 @@
--[[
TechAge
=======
Copyright (C) 2017-2020 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
TA4 Mapblock Active Detector
]]--
-- for lazy programmers
local M = minetest.get_meta
local S = techage.S
local logic = techage.logic
minetest.register_node("techage:ta4_mbadetector", {
description = "TA4 Mapblock Active Detector",
inventory_image = 'techage_smartline_mba_detector_inv.png',
tiles = {
-- up, down, right, left, back, front
"techage_smartline.png",
"techage_smartline.png",
"techage_smartline.png",
"techage_smartline.png",
"techage_smartline.png",
"techage_smartline.png^techage_smartline_mba_detector.png",
},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{ -6/32, -6/32, 14/32, 6/32, 6/32, 16/32},
},
},
after_place_node = function(pos, placer)
local meta = M(pos)
logic.after_place_node(pos, placer, "techage:ta4_mbadetector", S("TA4 Mapblock Active Detector"))
logic.infotext(meta, S("TA4 Mapblock Active Detector"))
minetest.get_node_timer(pos):start(1)
end,
on_timer = function(pos, elapsed)
local mem = techage.get_mem(pos)
mem.gametime = minetest.get_gametime()
return true
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
techage.remove_node(pos, oldnode, oldmetadata)
techage.del_mem(pos)
end,
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
groups = {choppy=2, cracky=2, crumbly=2},
is_ground_content = false,
sounds = default.node_sound_metal_defaults(),
})
minetest.register_craft({
output = "techage:ta4_mbadetector",
recipe = {
{"", "group:wood", "default:mese_crystal"},
{"", "techage:vacuum_tube", "default:copper_ingot"},
{"", "group:wood", ""},
},
})
techage.register_node({"techage:ta4_mbadetector"}, {
on_recv_message = function(pos, src, topic, payload)
if topic == "state" then
if minetest.compare_block_status then
if minetest.compare_block_status(pos, "active") then
return "on"
else
return "off"
end
else
local mem = techage.get_mem(pos)
local res = mem.gametime and mem.gametime > (minetest.get_gametime() - 2)
return res and "on" or "off"
end
else
return "unsupported"
end
end,
on_node_load = function(pos)
minetest.get_node_timer(pos):start(1)
end,
}
)

View File

@ -689,7 +689,7 @@ In einen TA4 Tank passen 2000 Einheiten oder 200 Fässer einer Flüssigkeit.
Siehe TA3 Pumpe. Siehe TA3 Pumpe.
Die TA4 Pumpe pumpt 8 Einheiten Flüssigkeit alle zwei Sekunden. Die TA4 Pumpe pumpt 8 Einheiten Flüssigkeit alle zwei Sekunden. Zusätzlich unterstützt die Pumpe das Kommando `flowrate`. Damit kann die Gesamtdurchflussmenge durch die Pumpe abgefragt werden.
[ta4_pump|image] [ta4_pump|image]

View File

@ -681,7 +681,7 @@ A TA4 tank can hold 2000 units or 200 barrels of liquid.
See TA3 pump. See TA3 pump.
The TA4 pump pumps 8 units of liquid every two seconds. The TA4 pump pumps 8 units of liquid every two seconds. The pump also supports the `flowrate` command. This means that the total flow rate through the pump can be queried.
[ta4_pump|image] [ta4_pump|image]

View File

@ -134,7 +134,8 @@ SaferLua directly supports the following standard functions:
- string.rep - string.rep
- string.sub - string.sub
- string.upper - string.upper
- string.split - string.split (result is an Array)
- string.split2 (result are multiple returns like the Lua function unpack)
- string.trim - string.trim
For own function definitions, the menu tab 'func' can be used. Here you write your functions like: For own function definitions, the menu tab 'func' can be used. Here you write your functions like:
@ -366,12 +367,14 @@ Please note, that this is not a technical distinction, only a logical.
| "depth" | number | Read the current depth value of a quarry block (1..80) | | "depth" | number | Read the current depth value of a quarry block (1..80) |
| "load" | number | Read the load value in percent (0..100) of a tank, silo, accu, or battery block, or from the Signs Bot Box. Silo and tank return two values: The percentage value and the absolute value in units.<br /> Example: percent, absolute = $send_cmnd("223", "load") | | "load" | number | Read the load value in percent (0..100) of a tank, silo, accu, or battery block, or from the Signs Bot Box. Silo and tank return two values: The percentage value and the absolute value in units.<br /> Example: percent, absolute = $send_cmnd("223", "load") |
| "delivered" | number | Read the current delivered power value of a generator block. A power consuming block (accu) provides a negative value | | "delivered" | number | Read the current delivered power value of a generator block. A power consuming block (accu) provides a negative value |
| "flowrate" | Total flow rate in liquid units | Only for TA4 Pumps |
| "action" | player-name, action-string | Only for Sensor Chests | | "action" | player-name, action-string | Only for Sensor Chests |
| "stacks" | Array with up to 4 Stores with the inventory content (see example) | Only for Sensor Chests | | "stacks" | Array with up to 4 Stores with the inventory content (see example) | Only for Sensor Chests |
| "count" | number | Read the item counter of the TA4 Item Detector block | | "count" | number | Read the item counter of the TA4 Item Detector block |
| "count" | number of items | Read the total amount of TA4 chest items. An optional number as `add_data` is used to address only one inventory slot (1..8, from left to right). | | "count" | number of items | Read the total amount of TA4 chest items. An optional number as `add_data` is used to address only one inventory slot (1..8, from left to right). |
| "itemstring" | item string of the given slot | Specific command for the TA4 8x2000 Chest to read the item type (technical name) of one chest slot, specified via `add_data` (1..8).<br />Example: s = $send_cmnd("223", "itemstring", 1) | | "itemstring" | item string of the given slot | Specific command for the TA4 8x2000 Chest to read the item type (technical name) of one chest slot, specified via `add_data` (1..8).<br />Example: s = $send_cmnd("223", "itemstring", 1) |
| "output" | recipe output string, <br />e.g.: "default:glass" | Only for the Industrial Furnace. If no recipe is active, the command returns "unknown" | | "output" | recipe output string, <br />e.g.: "default:glass" | Only for the Industrial Furnace. If no recipe is active, the command returns "unknown" |
| "input" | `<index>` | Read a recipe from the TA4 Recipe Block. `<index>` is the number of the recipe. The block return a list of recipe items. |
@ -385,18 +388,23 @@ Please note, that this is not a technical distinction, only a logical.
| -------------------------------- | ------------ | ------------------------------------------------------------ | | -------------------------------- | ------------ | ------------------------------------------------------------ |
| "on", "off" | nil | turn a node on/off (machine, lamp,...) | | "on", "off" | nil | turn a node on/off (machine, lamp,...) |
| "red, "amber", "green", "off" | nil | set Signal Tower color | | "red, "amber", "green", "off" | nil | set Signal Tower color |
| "red, "amber", "green", "off" | lamp number (1..4) | Set the signal lamp color. Valid for "TA4 2x Signal Lamp" and "TA4 4x Signal Lamp" |
| "port" | `<color>=on/off` | Enable/disable a Distributor filter slot..<br />Example: `yellow=on`<br />colors: "red", "green", "blue", "yellow" | | "port" | `<color>=on/off` | Enable/disable a Distributor filter slot..<br />Example: `yellow=on`<br />colors: "red", "green", "blue", "yellow" |
| "text" | text string | Text to be used for the Sensor Chest menu | | "text" | text string | Text to be used for the Sensor Chest menu |
| "reset" | nil | Reset the item counter of the TA4 Item Detector block | | "reset" | nil | Reset the item counter of the TA4 Item Detector block |
| "pull" | item string | Start the TA4 pusher to pull/push items.<br /> Example: `default:dirt 8` | | "pull" | item string | Start the TA4 pusher to pull/push items.<br /> Example: `default:dirt 8` |
| "config" | item string | Configure the TA4 pusher.<br />Example: `wool:blue` | | "config" | item string | Configure the TA4 pusher.<br />Example: `wool:blue` |
| "exchange" | inventory slot number | place/remove/exchange an block by means of the TA3 Door Controller II (techage:ta3_doorcontroller2) | | "exchange" | inventory slot number | place/remove/exchange an block by means of the TA3 Door Controller II (techage:ta3_doorcontroller2) |
| "a2b" | nil | TA4 Move Controller command to move the block(s) from position A to B |
| "b2a" | nil | TA4 Move Controller command to move the block(s) from position B to A |
| "move" | nil | TA4 Move Controller command to move the block(s) to the opposite position |
* `$display(num, row, text)` Send a text string to the display with number _num_. _row_ is the display row, a value from 1 to 5, or 0 to add the text string at the bottom (scroll screen mode). _text_ is the string to be displayed. If the first char of the string is a blank, the text will be horizontally centered. | "left" | nil | TA4 Turn Controller command to turn the block(s) to the left |
* `$clear_screen(num)` Clear the screen of the display with number _num_. | "right" | nil | TA4 Turn Controller command to turn the block(s) to the right |
* `$position(num)` Returns the position as string "'(x,y,z)" of the device with the given _num_. | "uturn" | nil | TA4 Turn Controller command to turn the block(s) 180 degrees |
| "recipe" | `<item_name>,<item_name>,...` | Set the TA4 Autocrafter recipe. <br />Example for the torch recipe: `default:coal_lump,,,default:stick` <br />Hint: Empty fields may only be left out at the end of the item list! |
| "recipe" | `<number>.<index>` | Set the TA4 Autocrafter recipe with a recipe from a TA4 Recipe Block.<br />`<number>` is the TA4 Recipe Block number<br />`<index>` is the number of the recipe in the TA4 Recipe Block |
| "goto" | `<slot>` | Start command for the TA4 Sequencer. `<slot>` is the time slot like `[1]` where the execution starts. |
| "stop" | nil | Stop command for the TA4 Sequencer. |
### Server and Terminal Functions ### Server and Terminal Functions
@ -414,25 +422,27 @@ In contrast the Controller can send text strings to the terminal.
- `$get_term()` - Read a text command received from the Terminal - `$get_term()` - Read a text command received from the Terminal
- `$put_term(num, text)` - Send a text string to the Terminal. _num_ is the number of the Terminal. - `$put_term(num, text)` - Send a text string to the Terminal. _num_ is the number of the Terminal.
### Communication between Lua Controllers
### Further Functions
Messages are used to transport data between Controllers. Messages can contain arbitrary data. Incoming messages are stored in order (up to 10) and can be read one after the other. Messages are used to transport data between Controllers. Messages can contain arbitrary data. Incoming messages are stored in order (up to 10) and can be read one after the other.
* `$get_msg([raw])` - Read a received message. The function returns the sender number and the message. (see example "Emails"). If the _raw_ parameter is not set or false, the message is guaranteed to be a string. * `$get_msg([raw])` - Read a received message. The function returns the sender number and the message. (see example "Emails"). If the _raw_ parameter is not set or false, the message is guaranteed to be a string.
* `$send_msg(num, msg)` - Send a message to another Controller. _num_ is the destination number. (see example "Emails") * `$send_msg(num, msg)` - Send a message to another Controller. _num_ is the destination number. (see example "Emails")
* `$chat(text)` - Send yourself a chat message. _text_ is a text string. ### Further Functions
* `$chat(text)` - Send yourself a chat message. _text_ is a text string.
* `$door(pos, text)` - Open/Close a door at position "pos". * `$door(pos, text)` - Open/Close a door at position "pos".
Example: `$door("123,7,-1200", "close")`. Example: `$door("123,7,-1200", "close")`.
Hint: Use the Techage Info Tool to determine the door position. Hint: Use the Techage Info Tool to determine the door position.
* `$item_description("default:apple")` * `$item_description("default:apple")`
Get the description (item name) for a specified itemstring, e. g. determined via the TA4 8x2000 Chest command `itemstring`: Get the description (item name) for a specified itemstring, e. g. determined via the TA4 8x2000 Chest command `itemstring`:
`str = $send_cmnd("223", "itemstring", 1)` `str = $send_cmnd("223", "itemstring", 1)`
`descr = $item_description(str)` `descr = $item_description(str)`
* `$display(num, row, text)` Send a text string to the display with number _num_. _row_ is the display row, a value from 1 to 5, or 0 to add the text string at the bottom (scroll screen mode). _text_ is the string to be displayed. If the first char of the string is a blank, the text will be horizontally centered.
* `$clear_screen(num)` Clear the screen of the display with number _num_.
* `$position(num)` Returns the position as string "'(x,y,z)" of the device with the given _num_.
## Example Scripts ## Example Scripts
@ -662,7 +672,7 @@ loop() code:
-- read from Terminal and send the message -- read from Terminal and send the message
s = $get_term() s = $get_term()
if s then if s then
name,text = unpack(string.split(s, ":", false, 1)) name,text = string.split2(s, ":", false, 1)
num = $server_read(SERVER, name) num = $server_read(SERVER, name)
if num then if num then
$send_msg(num, text) $send_msg(num, text)

Binary file not shown.

View File

@ -97,7 +97,6 @@ minetest.register_node("techage:ta4_turncontroller", {
nvm.lpos = new_posses nvm.lpos = new_posses
local name = player:get_player_name() local name = player:get_player_name()
mark.stop(name) mark.stop(name)
print("new_posses", #new_posses)
end end
meta:set_string("formspec", formspec(nvm, meta)) meta:set_string("formspec", formspec(nvm, meta))
elseif fields.right then elseif fields.right then
@ -107,7 +106,6 @@ minetest.register_node("techage:ta4_turncontroller", {
nvm.lpos = new_posses nvm.lpos = new_posses
local name = player:get_player_name() local name = player:get_player_name()
mark.stop(name) mark.stop(name)
print("new_posses", #new_posses)
end end
meta:set_string("formspec", formspec(nvm, meta)) meta:set_string("formspec", formspec(nvm, meta))
end end

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 669 B

View File

@ -109,6 +109,11 @@ local function read_state(itemstack, user, pointed_thing)
consumption = dump(consumption) consumption = dump(consumption)
minetest.chat_send_player(user:get_player_name(), ndef.description.." "..number..": consumption = "..consumption.." kud ") minetest.chat_send_player(user:get_player_name(), ndef.description.." "..number..": consumption = "..consumption.." kud ")
end end
local flowrate = techage.send_single("0", number, "flowrate", nil)
if flowrate and flowrate ~= "" and flowrate ~= "unsupported" then
flowrate = dump(flowrate)
minetest.chat_send_player(user:get_player_name(), ndef.description.." "..number..": flowrate = "..flowrate.." ")
end
local owner = M(pos):get_string("owner") or "" local owner = M(pos):get_string("owner") or ""
if owner ~= "" then if owner ~= "" then
minetest.chat_send_player(user:get_player_name(), S("Node owner")..": "..owner.." ") minetest.chat_send_player(user:get_player_name(), S("Node owner")..": "..owner.." ")