built on 31/12/2022 10:51:49
This commit is contained in:
parent
8321aff4c7
commit
d734800e13
@ -323,6 +323,11 @@ local function door_command(floor_pos, facedir, cmnd, sound)
|
||||
-- one step up
|
||||
local door_pos1 = hyperloop.new_pos(floor_pos, facedir, "1B", 0)
|
||||
local door_pos2 = hyperloop.new_pos(floor_pos, facedir, "1B", 1)
|
||||
local meta = M(floor_pos)
|
||||
local owner = meta:contains("owner") and meta:get_string("owner")
|
||||
if owner and (minetest.is_protected(door_pos1, owner) or minetest.is_protected(door_pos2, owner)) then
|
||||
return
|
||||
end
|
||||
local node1 = minetest.get_node(door_pos1)
|
||||
local node2 = minetest.get_node(door_pos2)
|
||||
|
||||
@ -455,6 +460,7 @@ minetest.register_node("hyperloop:elevator_bottom", {
|
||||
"field[0.5,1.5;5,1;floor;"..S("Floor name")..";"..S("Base").."]" ..
|
||||
"button_exit[2,3;2,1;exit;"..S("Save").."]"
|
||||
meta:set_string("formspec", formspec)
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
|
||||
-- add upper part of the car
|
||||
pos = Shaft:get_pos(pos, 6)
|
||||
|
@ -266,7 +266,7 @@ local function collect_network_nodes(pos, tlib2, outdir)
|
||||
-- outdir corresponds to the indir coming from
|
||||
connection_walk(pos, outdir, Flip[outdir], node, tlib2, function(pos, indir, node)
|
||||
local ndef = net_def2(pos, node.name, netw_type)
|
||||
if ndef then
|
||||
if ndef and ndef.ntype then
|
||||
local ntype = ndef.ntype
|
||||
if not netw[ntype] then netw[ntype] = {} end
|
||||
netw[ntype][#netw[ntype] + 1] = {pos = pos, indir = indir}
|
||||
|
@ -102,7 +102,7 @@ local function format_error_str(str, label)
|
||||
if s:find("function 'xpcall'") then
|
||||
break
|
||||
elseif s:find(".-%.lua:%d+:(.+)") then
|
||||
local err = s:gsub(".-%.lua:%d+:%s*(.+)", "extern: %1")
|
||||
local err = s:gsub(".-%.lua:%d+:%s*(.+)", "%1")
|
||||
table.insert(tbl, err)
|
||||
elseif s:find('%[string ".-"%]') then
|
||||
local line, err = s:match('^%[string ".-"%]:(%d+): (.+)$')
|
||||
@ -134,6 +134,24 @@ local function compile(pos, text, label, err_clbk)
|
||||
end
|
||||
end
|
||||
|
||||
local function runtime_delimiter(code)
|
||||
local time = minetest.get_us_time()
|
||||
local timeout = function ()
|
||||
if minetest.get_us_time() - time > safer_lua.MaxExeTime then
|
||||
debug.sethook()
|
||||
error("Runtime limit exceeded")
|
||||
end
|
||||
end
|
||||
debug.sethook(timeout, "c")
|
||||
code()
|
||||
debug.sethook()
|
||||
end
|
||||
|
||||
local function error_handler(...)
|
||||
debug.sethook()
|
||||
return debug.traceback(...)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Standard init/loop controller
|
||||
-------------------------------------------------------------------------------
|
||||
@ -148,7 +166,7 @@ function safer_lua.init(pos, init, loop, environ, err_clbk)
|
||||
env.S = {}
|
||||
env.S = map(env.S, environ)
|
||||
setfenv(code, env)
|
||||
local res, err = xpcall(code, debug.traceback)
|
||||
local res, err = xpcall(runtime_delimiter, error_handler, code)
|
||||
if not res then
|
||||
err_clbk(pos, format_error(err, "init"))
|
||||
else
|
||||
@ -171,7 +189,7 @@ function safer_lua.run_loop(pos, elapsed, code, err_clbk)
|
||||
env.event = false
|
||||
env.ticks = env.ticks + 1
|
||||
end
|
||||
local res, err = xpcall(code, debug.traceback)
|
||||
local res, err = xpcall(runtime_delimiter, error_handler, code)
|
||||
if calc_used_mem_size(env) > safer_lua.MaxTableSize then
|
||||
err_clbk(pos, "Error: Data memory limit exceeded")
|
||||
return false
|
||||
@ -188,7 +206,7 @@ end
|
||||
-------------------------------------------------------------------------------
|
||||
local function thread(pos, code, err_clbk)
|
||||
while true do
|
||||
local res, err = xpcall(code, debug.traceback)
|
||||
local res, err = xpcall(runtime_delimiter, error_handler, code)
|
||||
if not res then
|
||||
err_clbk(pos, format_error(err, "loop"))
|
||||
return false
|
||||
|
@ -8,7 +8,7 @@ A subset of the language Lua for safe and secure Lua sandboxes with:
|
||||
- limited posibilities to call functions
|
||||
|
||||
### License
|
||||
Copyright (C) 2018-2021 Joachim Stolberg
|
||||
Copyright (C) 2018-2022 Joachim Stolberg
|
||||
Code: Licensed under the GNU LGPL version 2.1 or later. See LICENSE.txt
|
||||
|
||||
|
||||
@ -19,3 +19,4 @@ none
|
||||
- 2018-06-24 v0.01 * first draft
|
||||
- 2020-03-14 v1.00 * extracted from TechPack and released
|
||||
- 2021-11-28 v1.01 * function `string.split2` added, `unpack` removed
|
||||
- 2022-12-22 v1.02 * Limit code execution time for recursive function calls (#3 by Thomas--S)
|
||||
|
@ -48,6 +48,7 @@ function signs_bot.move_robot(mem)
|
||||
if node4.name == "signs_bot:robot_foot" then
|
||||
minetest.swap_node(pos4, mem.stored_node or {name = "air"})
|
||||
end
|
||||
minetest.swap_node(pos3, {name = "air"})
|
||||
minetest.remove_node(pos)
|
||||
else
|
||||
minetest.swap_node(pos, mem.stored_node or {name = "air"})
|
||||
@ -319,7 +320,7 @@ signs_bot.register_botcommand("stop", {
|
||||
if mem.capa then
|
||||
mem.capa = mem.capa + 2
|
||||
end
|
||||
return signs_bot.DONE
|
||||
return signs_bot.BUSY
|
||||
end,
|
||||
})
|
||||
|
||||
|
@ -168,6 +168,7 @@ signs_bot.register_botcommand("place_below", {
|
||||
end,
|
||||
cmnd = function(base_pos, mem, slot)
|
||||
slot = tonumber(slot) or 0
|
||||
mem.stored_node = {name = "air"}
|
||||
return place_item_below(base_pos, mem.robot_pos, mem.robot_param2, slot)
|
||||
end,
|
||||
})
|
||||
|
@ -129,6 +129,7 @@ end
|
||||
|
||||
local function gen_string_cmnd(code, pc, num_param, script)
|
||||
local tokens = tokenizer(script)
|
||||
pc = math.min(pc, #tokens)
|
||||
if num_param == 0 then
|
||||
return tokens[pc]
|
||||
elseif num_param == 1 then
|
||||
|
@ -109,17 +109,19 @@ techage.register_node({"default:furnace", "default:furnace_active"}, {
|
||||
local inv = meta:get_inventory()
|
||||
return techage.get_items(pos, inv, "dst", num)
|
||||
end,
|
||||
on_push_item = function(pos, side, stack)
|
||||
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 minetest.get_craft_result({method="fuel", width=1, items={stack}}).time ~= 0 then
|
||||
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, side, stack)
|
||||
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)
|
||||
|
@ -431,4 +431,5 @@ if minetest.global_exists("farming") then
|
||||
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
|
||||
|
@ -26,7 +26,7 @@ local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm
|
||||
|
||||
local S = techage.S
|
||||
|
||||
local CYCLE_TIME = 3
|
||||
local CYCLE_TIME = 4
|
||||
local STANDBY_TICKS = 4
|
||||
local COUNTDOWN_TICKS = 4
|
||||
|
||||
@ -205,6 +205,7 @@ local function quarry_task(pos, crd, nvm)
|
||||
|
||||
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
|
||||
|
@ -613,10 +613,10 @@ techage.register_node({"techage:ta4_chest"}, {
|
||||
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 1) or 1)
|
||||
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 1) or 1)
|
||||
return get_itemstring(nvm, tonumber(payload or 0) or 0)
|
||||
elseif topic == "state" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return inv_state(nvm)
|
||||
@ -627,10 +627,10 @@ techage.register_node({"techage:ta4_chest"}, {
|
||||
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 1) or 1)}
|
||||
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 1) or 1)
|
||||
return 0, get_itemstring(nvm, tonumber(payload[2] or 0) or 0)
|
||||
elseif topic == 131 then -- Chest State
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return 0, {inv_state_num(nvm)}
|
||||
|
@ -16,6 +16,7 @@
|
||||
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
|
||||
local has_mesecons = minetest.global_exists("mesecon")
|
||||
|
||||
local NodeInfoCache = {}
|
||||
local NumbersToBeRecycled = {}
|
||||
@ -171,7 +172,7 @@ end)
|
||||
techage.dug_node = {}
|
||||
minetest.register_on_dignode(function(pos, oldnode, digger)
|
||||
if not digger then return end
|
||||
-- store pos for tools without own 'register_on_dignode'
|
||||
-- store the position of the dug block for tools like the TA1 hammer
|
||||
techage.dug_node[digger:get_player_name()] = pos
|
||||
end)
|
||||
|
||||
@ -317,6 +318,13 @@ function techage.register_node(names, node_definition)
|
||||
if node_definition.on_node_load then
|
||||
register_lbm(names[1], names)
|
||||
end
|
||||
|
||||
-- register mvps stopper
|
||||
if has_mesecons then
|
||||
for _, name in ipairs(names) do
|
||||
mesecon.register_mvps_stopper(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
@ -331,6 +339,19 @@ function techage.not_protected(number, placer_name, clicker_name)
|
||||
return false
|
||||
end
|
||||
|
||||
-- Check the given number value.
|
||||
-- Returns true if the number is valid, point to real node and
|
||||
-- and the node is not protected for the given player_name.
|
||||
function techage.check_number(number, placer_name)
|
||||
if number then
|
||||
if not techage.not_protected(number, placer_name, nil) then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Check the given list of numbers.
|
||||
-- Returns true if number(s) is/are valid, point to real nodes and
|
||||
-- and the nodes are not protected for the given player_name.
|
||||
|
@ -3,7 +3,7 @@
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2020-2021 Joachim Stolberg
|
||||
Copyright (C) 2020-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
@ -57,6 +57,96 @@ local function rotate(v, yaw)
|
||||
return {x = v.x * cosyaw - v.z * sinyaw, y = v.y, z = v.x * sinyaw + v.z * cosyaw}
|
||||
end
|
||||
|
||||
local function set_node(item)
|
||||
local dest_pos = item.dest_pos
|
||||
local name = item.name or "air"
|
||||
local param2 = item.param2 or 0
|
||||
local metadata = item.metadata or {}
|
||||
local nvm = techage.get_nvm(item.base_pos)
|
||||
local node = techage.get_node_lvm(dest_pos)
|
||||
local ndef1 = minetest.registered_nodes[name]
|
||||
local ndef2 = minetest.registered_nodes[node.name]
|
||||
|
||||
nvm.running = false
|
||||
M(item.base_pos):set_string("status", S("Stopped"))
|
||||
if ndef1 and ndef2 then
|
||||
if ndef2.buildable_to then
|
||||
local meta = M(dest_pos)
|
||||
minetest.set_node(dest_pos, {name=name, param2=param2})
|
||||
meta:from_table(item.metadata or {})
|
||||
meta:set_string("ta_move_block", "")
|
||||
meta:set_int("ta_door_locked", 1)
|
||||
return
|
||||
end
|
||||
local meta = M(dest_pos)
|
||||
if not meta:contains("ta_move_block") then
|
||||
meta:set_string("ta_move_block", minetest.serialize({name=name, param2=param2}))
|
||||
return
|
||||
end
|
||||
elseif ndef1 then
|
||||
minetest.add_item(dest_pos, ItemStack(name))
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Entity monitoring
|
||||
-------------------------------------------------------------------------------
|
||||
local queue = {}
|
||||
local first = 0
|
||||
local last = -1
|
||||
|
||||
local function push(item)
|
||||
last = last + 1
|
||||
queue[last] = item
|
||||
end
|
||||
|
||||
local function pop(nvm, time)
|
||||
if first > last then return end
|
||||
local item = queue[first]
|
||||
queue[first] = nil -- to allow garbage collection
|
||||
first = first + 1
|
||||
return item
|
||||
end
|
||||
|
||||
local function monitoring()
|
||||
local num = last - first + 1
|
||||
for _ = 1, num do
|
||||
local item = pop()
|
||||
if item.ttl >= techage.SystemTime then
|
||||
-- still valud
|
||||
push(item)
|
||||
elseif item.ttl ~= 0 then
|
||||
set_node(item)
|
||||
end
|
||||
end
|
||||
minetest.after(1, monitoring)
|
||||
end
|
||||
minetest.after(1, monitoring)
|
||||
|
||||
minetest.register_on_shutdown(function()
|
||||
local num = last - first + 1
|
||||
for _ = 1, num do
|
||||
local item = pop()
|
||||
if item.ttl ~= 0 then
|
||||
set_node(item)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local function monitoring_add_entity(item)
|
||||
item.ttl = techage.SystemTime + 1
|
||||
push(item)
|
||||
end
|
||||
|
||||
local function monitoring_del_entity(item)
|
||||
-- Mark as timed out
|
||||
item.ttl = 0
|
||||
end
|
||||
|
||||
local function monitoring_trigger_entity(item)
|
||||
item.ttl = techage.SystemTime + 1
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- to_path function for the fly/move path
|
||||
-------------------------------------------------------------------------------
|
||||
@ -310,41 +400,15 @@ end
|
||||
|
||||
local function entity_to_node(pos, obj)
|
||||
local self = obj:get_luaentity()
|
||||
if self then
|
||||
local name = self.item_name or "air"
|
||||
local param2 = self.param2 or 0
|
||||
local metadata = self.metadata or {}
|
||||
if self and self.item then
|
||||
detach_objects(pos, self)
|
||||
if self.base_pos then
|
||||
local nvm = techage.get_nvm(self.base_pos)
|
||||
nvm.running = nil
|
||||
end
|
||||
monitoring_del_entity(self.item)
|
||||
minetest.after(0.1, obj.remove, obj)
|
||||
local node = minetest.get_node(pos)
|
||||
local ndef1 = minetest.registered_nodes[name]
|
||||
local ndef2 = minetest.registered_nodes[node.name]
|
||||
if ndef1 and ndef2 then
|
||||
if ndef2.buildable_to then
|
||||
local meta = M(pos)
|
||||
minetest.set_node(pos, {name=name, param2=param2})
|
||||
meta:from_table(metadata)
|
||||
meta:set_string("ta_move_block", "")
|
||||
meta:set_int("ta_door_locked", 1)
|
||||
return
|
||||
end
|
||||
local meta = M(pos)
|
||||
if not meta:contains("ta_move_block") then
|
||||
meta:set_string("ta_move_block", minetest.serialize({name=name, param2=param2}))
|
||||
return
|
||||
end
|
||||
--minetest.add_item(pos, ItemStack(name))
|
||||
elseif ndef1 then
|
||||
minetest.add_item(pos, ItemStack(name))
|
||||
end
|
||||
set_node(self.item)
|
||||
end
|
||||
end
|
||||
|
||||
local function node_to_entity(start_pos)
|
||||
local function node_to_entity(base_pos, start_pos, dest_pos)
|
||||
local meta = M(start_pos)
|
||||
local node, metadata
|
||||
|
||||
@ -356,7 +420,7 @@ local function node_to_entity(start_pos)
|
||||
meta:set_string("ta_block_locked", "true")
|
||||
elseif not meta:contains("ta_block_locked") then
|
||||
-- Block with other metadata
|
||||
node = minetest.get_node(start_pos)
|
||||
node = techage.get_node_lvm(start_pos)
|
||||
metadata = meta:to_table()
|
||||
minetest.after(0.1, minetest.remove_node, start_pos)
|
||||
else
|
||||
@ -371,9 +435,15 @@ local function node_to_entity(start_pos)
|
||||
obj:set_armor_groups({immortal=1})
|
||||
|
||||
-- To be able to revert to node
|
||||
self.item_name = node.name
|
||||
self.param2 = node.param2
|
||||
self.metadata = metadata or {}
|
||||
self.item = {
|
||||
name = node.name,
|
||||
param2 = node.param2,
|
||||
metadata = metadata or {},
|
||||
dest_pos = dest_pos,
|
||||
base_pos = base_pos,
|
||||
}
|
||||
monitoring_add_entity(self.item)
|
||||
|
||||
-- Prepare for attachments
|
||||
self.players = {}
|
||||
@ -436,7 +506,6 @@ local function handover_to(obj, self, pos1)
|
||||
end
|
||||
local pos2 = next_path_pos(pos1, self.lpath, 1)
|
||||
local dir = determine_dir(pos1, pos2)
|
||||
--print("handover_to", P2S(pos1), P2S(pos2), P2S(dir), P2S(info.pos), meta:get_string("path"))
|
||||
if not self.handover then
|
||||
local nvm = techage.get_nvm(info.pos)
|
||||
nvm.lpos1 = nvm.lpos1 or {}
|
||||
@ -458,7 +527,7 @@ minetest.register_entity("techage:move_item", {
|
||||
initial_properties = {
|
||||
pointable = true,
|
||||
makes_footstep_sound = true,
|
||||
static_save = true,
|
||||
static_save = false,
|
||||
collide_with_objects = false,
|
||||
physical = false,
|
||||
visual = "wielditem",
|
||||
@ -467,49 +536,6 @@ minetest.register_entity("techage:move_item", {
|
||||
selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||
},
|
||||
|
||||
get_staticdata = function(self)
|
||||
return minetest.serialize({
|
||||
item_name = self.item_name,
|
||||
param2 = self.param2,
|
||||
metadata = self.metadata,
|
||||
move2to1 = self.move2to1,
|
||||
handover = self.handover,
|
||||
path_idx = self.path_idx,
|
||||
pos1_idx = self.pos1_idx,
|
||||
lpath = self.lpath,
|
||||
start_pos = self.start_pos,
|
||||
base_pos = self.base_pos,
|
||||
max_speed = self.max_speed,
|
||||
dest_pos = self.dest_pos,
|
||||
dir = self.dir,
|
||||
respawn = true,
|
||||
})
|
||||
end,
|
||||
|
||||
on_activate = function(self, staticdata)
|
||||
if staticdata then
|
||||
local tbl = minetest.deserialize(staticdata) or {}
|
||||
self.item_name = tbl.item_name or "air"
|
||||
self.param2 = tbl.param2 or 0
|
||||
self.metadata = tbl.metadata or {}
|
||||
self.move2to1 = tbl.move2to1 or false
|
||||
self.handover = tbl.handover
|
||||
self.path_idx = tbl.path_idx or 1
|
||||
self.pos1_idx = tbl.pos1_idx or 1
|
||||
self.lpath = tbl.lpath or {}
|
||||
self.max_speed = tbl.max_speed or MAX_SPEED
|
||||
self.dest_pos = tbl.dest_pos or self.object:get_pos()
|
||||
self.start_pos = tbl.start_pos or self.object:get_pos()
|
||||
self.base_pos = tbl.base_pos
|
||||
self.dir = tbl.dir or {x=0, y=0, z=0}
|
||||
self.object:set_properties({wield_item = self.item})
|
||||
--print("tbl.respawn", tbl.respawn)
|
||||
if tbl.respawn then
|
||||
entity_to_node(self.dest_pos, self.object)
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
on_step = function(self, dtime, moveresult)
|
||||
local stop_obj = function(obj, self)
|
||||
local dest_pos = self.dest_pos
|
||||
@ -518,7 +544,6 @@ minetest.register_entity("techage:move_item", {
|
||||
obj:set_velocity({x=0, y=0, z=0})
|
||||
self.dest_pos = nil
|
||||
self.old_dist = nil
|
||||
self.ttl = 2
|
||||
return dest_pos
|
||||
end
|
||||
|
||||
@ -571,19 +596,13 @@ minetest.register_entity("techage:move_item", {
|
||||
end
|
||||
end
|
||||
|
||||
elseif self.ttl then
|
||||
self.ttl = self.ttl - dtime
|
||||
if self.ttl < 0 then
|
||||
local obj = self.object
|
||||
local pos = obj:get_pos()
|
||||
entity_to_node(pos, obj)
|
||||
end
|
||||
monitoring_trigger_entity(self.item)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
local function is_valid_dest(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if techage.is_air_like(node.name) then
|
||||
return true
|
||||
end
|
||||
@ -594,20 +613,19 @@ local function is_valid_dest(pos)
|
||||
end
|
||||
|
||||
local function is_simple_node(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
local node =techage.get_node_lvm(pos)
|
||||
local ndef = minetest.registered_nodes[node.name]
|
||||
return not techage.is_air_like(node.name) and techage.can_dig_node(node.name, ndef)
|
||||
end
|
||||
|
||||
local function move_node(pos, pos1_idx, start_pos, lpath, max_speed, height, move2to1, handover, cpos)
|
||||
local pos2 = next_path_pos(start_pos, lpath, 1)
|
||||
--print("move_node", P2S(pos), P2S(start_pos), lpath, max_speed, height, move2to1, P2S(pos2))
|
||||
-- optional for non-player objects
|
||||
local yoffs = M(pos):get_float("offset")
|
||||
|
||||
if pos2 then
|
||||
local dir = determine_dir(start_pos, pos2)
|
||||
local obj = node_to_entity(start_pos)
|
||||
local obj = node_to_entity(pos, start_pos, pos2)
|
||||
|
||||
if obj then
|
||||
local offs = {x=0, y=height or 1, z=0}
|
||||
@ -622,40 +640,43 @@ local function move_node(pos, pos1_idx, start_pos, lpath, max_speed, height, mov
|
||||
self.pos1_idx = pos1_idx
|
||||
self.lpath = lpath
|
||||
self.max_speed = max_speed
|
||||
self.start_pos = start_pos
|
||||
self.base_pos = pos
|
||||
self.move2to1 = move2to1
|
||||
self.handover = handover
|
||||
self.yoffs = yoffs
|
||||
--print("move_node", P2S(start_pos), P2S(pos2), P2S(dir), P2S(pos))
|
||||
move_entity(obj, pos2, dir)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function move_nodes(pos, meta, nvm, lpath, max_speed, height, move2to1, handover)
|
||||
--print("move_nodes", dump(nvm), dump(lpath), max_speed, height, move2to1, handover)
|
||||
local owner = meta:get_string("owner")
|
||||
techage.counting_add(owner, #nvm.lpos1 * #lpath)
|
||||
techage.counting_add(owner, #lpath, #nvm.lpos1 * #lpath)
|
||||
|
||||
for idx = 1, #nvm.lpos1 do
|
||||
local pos1 = nvm.lpos1[idx]
|
||||
local pos2 = nvm.lpos2[idx]
|
||||
--print("move_nodes", idx, P2S(pos1), P2S(pos2))
|
||||
|
||||
if move2to1 then
|
||||
pos1, pos2 = pos2, pos1
|
||||
end
|
||||
|
||||
--print("move_nodes", P2S(pos1), P2S(pos2))
|
||||
if not minetest.is_protected(pos1, owner) and not minetest.is_protected(pos2, owner) then
|
||||
if is_simple_node(pos1) and is_valid_dest(pos2) then
|
||||
move_node(pos, idx, pos1, lpath, max_speed, height, move2to1, handover)
|
||||
if move_node(pos, idx, pos1, lpath, max_speed, height, move2to1, handover) == false then
|
||||
meta:set_string("status", S("No valid node at the start position"))
|
||||
return false
|
||||
end
|
||||
else
|
||||
if not is_simple_node(pos1) then
|
||||
meta:set_string("status", S("No valid node at the start position"))
|
||||
else
|
||||
meta:set_string("status", S("No valid destination position"))
|
||||
end
|
||||
return false
|
||||
end
|
||||
else
|
||||
if minetest.is_protected(pos1, owner) then
|
||||
@ -666,12 +687,12 @@ local function move_nodes(pos, meta, nvm, lpath, max_speed, height, move2to1, ha
|
||||
return false
|
||||
end
|
||||
end
|
||||
meta:set_string("status", S("Running"))
|
||||
return true
|
||||
end
|
||||
|
||||
-- Move nodes from lpos1 by the given x/y/z 'line'
|
||||
local function move_nodes2(pos, meta, lpos1, line, max_speed, height)
|
||||
--print("move_nodes2", dump(lpos1), dump(line), max_speed, height)
|
||||
local owner = meta:get_string("owner")
|
||||
techage.counting_add(owner, #lpos1)
|
||||
|
||||
@ -691,6 +712,7 @@ local function move_nodes2(pos, meta, lpos1, line, max_speed, height)
|
||||
else
|
||||
meta:set_string("status", S("No valid destination position"))
|
||||
end
|
||||
return false, lpos1
|
||||
end
|
||||
else
|
||||
if minetest.is_protected(pos1, owner) then
|
||||
@ -702,7 +724,7 @@ local function move_nodes2(pos, meta, lpos1, line, max_speed, height)
|
||||
end
|
||||
end
|
||||
|
||||
meta:set_string("status", "")
|
||||
meta:set_string("status", S("Running"))
|
||||
return true, lpos2
|
||||
end
|
||||
|
||||
@ -714,7 +736,7 @@ function flylib.move_to_other_pos(pos, move2to1)
|
||||
local height = meta:contains("height") and meta:get_float("height") or 1
|
||||
local handover
|
||||
|
||||
if err then return false end
|
||||
if err or nvm.running then return false end
|
||||
|
||||
height = techage.in_range(height, 0, 1)
|
||||
max_speed = techage.in_range(max_speed, MIN_SPEED, MAX_SPEED)
|
||||
@ -732,7 +754,9 @@ function flylib.move_to_other_pos(pos, move2to1)
|
||||
else
|
||||
handover = meta:contains("handoverB") and meta:get_string("handoverB") or nil
|
||||
end
|
||||
return move_nodes(pos, meta, nvm, lpath, max_speed, height, move2to1, handover)
|
||||
nvm.running = move_nodes(pos, meta, nvm, lpath, max_speed, height, move2to1, handover)
|
||||
nvm.moveBA = nvm.running and not move2to1
|
||||
return nvm.running
|
||||
end
|
||||
|
||||
function flylib.move_to(pos, line)
|
||||
@ -742,8 +766,10 @@ function flylib.move_to(pos, line)
|
||||
local max_speed = meta:contains("max_speed") and meta:get_int("max_speed") or MAX_SPEED
|
||||
local resp
|
||||
|
||||
resp, nvm.lastpos = move_nodes2(pos, meta, nvm.lastpos or nvm.lpos1, line, max_speed, height)
|
||||
return resp
|
||||
if nvm.running then return false end
|
||||
|
||||
nvm.running, nvm.lastpos = move_nodes2(pos, meta, nvm.lastpos or nvm.lpos1, line, max_speed, height)
|
||||
return nvm.running
|
||||
end
|
||||
|
||||
function flylib.reset_move(pos)
|
||||
@ -751,11 +777,17 @@ function flylib.reset_move(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local height = techage.in_range(meta:contains("height") and meta:get_float("height") or 1, 0, 1)
|
||||
local max_speed = meta:contains("max_speed") and meta:get_int("max_speed") or MAX_SPEED
|
||||
|
||||
if nvm.running then return false end
|
||||
|
||||
if nvm.lpos1 and nvm.lpos1[1] then
|
||||
local move = vector.subtract(nvm.lpos1[1], (nvm.lastpos or nvm.lpos1)[1])
|
||||
local resp
|
||||
|
||||
resp, nvm.lastpos = move_nodes2(pos, meta, nvm.lastpos or nvm.lpos1, move, max_speed, height)
|
||||
return resp
|
||||
nvm.running, nvm.lastpos = move_nodes2(pos, meta, nvm.lastpos or nvm.lpos1, move, max_speed, height)
|
||||
return nvm.running
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- rot is one of "l", "r", "2l", "2r"
|
||||
@ -842,4 +874,4 @@ minetest.register_on_dieplayer(function(player)
|
||||
end
|
||||
end)
|
||||
|
||||
return flylib
|
||||
techage.flylib = flylib
|
||||
|
@ -72,8 +72,11 @@ end
|
||||
local api = {}
|
||||
|
||||
function api.store_mapblock_data(key, mapblock_data)
|
||||
if use_marshal then
|
||||
set_block(key, marshal.encode(mapblock_data))
|
||||
if use_marshal and mapblock_data then
|
||||
local data = marshal.encode(mapblock_data)
|
||||
if data then
|
||||
set_block(key, data)
|
||||
end
|
||||
else
|
||||
set_block(key, minetest.serialize(mapblock_data))
|
||||
end
|
||||
|
@ -1,208 +0,0 @@
|
||||
--[[
|
||||
|
||||
Techage
|
||||
=======
|
||||
|
||||
Copyright (C) 2020-2021 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA4 Terminal
|
||||
|
||||
]]--
|
||||
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local STR_LEN = 80
|
||||
local HELP = [[#### TA4 Terminal ####
|
||||
|
||||
Send commands to the connected machine
|
||||
and output text messages from the
|
||||
machine.
|
||||
|
||||
Commands can have up to 80 characters.
|
||||
Local commands:
|
||||
- clear = clear screen
|
||||
- help = this message
|
||||
- pub = switch to public use
|
||||
- priv = switch to private use
|
||||
- connect <num> = connect the machine
|
||||
|
||||
All other commands are machine dependent.
|
||||
]]
|
||||
|
||||
local function get_string(meta, num, default)
|
||||
local s = meta:get_string("bttn_text"..num)
|
||||
if not s or s == "" then
|
||||
return default
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
local function formspec2(mem)
|
||||
mem.command = mem.command or ""
|
||||
mem.output = mem.output or ""
|
||||
local output = minetest.formspec_escape(mem.output)
|
||||
output = output:gsub("\n", ",")
|
||||
local command = minetest.formspec_escape(mem.command)
|
||||
local bttn_text1 = get_string(meta, 1, "User1")
|
||||
local bttn_text2 = get_string(meta, 2, "User2")
|
||||
local bttn_text3 = get_string(meta, 3, "User3")
|
||||
local bttn_text4 = get_string(meta, 4, "User4")
|
||||
local bttn_text5 = get_string(meta, 5, "User5")
|
||||
local bttn_text6 = get_string(meta, 6, "User6")
|
||||
local bttn_text7 = get_string(meta, 7, "User7")
|
||||
local bttn_text8 = get_string(meta, 8, "User8")
|
||||
local bttn_text9 = get_string(meta, 9, "User9")
|
||||
return "size[10,8]"..
|
||||
"style_type[table,field;font=mono]"..
|
||||
"button[0,0;3.3,1;bttn1;"..bttn_text1.."]button[3.3,0;3.3,1;bttn2;"..bttn_text2.."]button[6.6,0;3.3,1;bttn3;"..bttn_text3.."]"..
|
||||
"button[0,0.8;3.3,1;bttn4;"..bttn_text4.."]button[3.3,0.8;3.3,1;bttn5;"..bttn_text5.."]button[6.6,0.8;3.3,1;bttn6;"..bttn_text6.."]"..
|
||||
"button[0,1.6;3.3,1;bttn7;"..bttn_text7.."]button[3.3,1.6;3.3,1;bttn8;"..bttn_text8.."]button[6.6,1.6;3.3,1;bttn9;"..bttn_text9.."]"..
|
||||
"table[0,2.5;9.8,4.7;output;"..output..";200]"..
|
||||
"field[0.4,7.7;7.6,1;cmnd;;"..mem.command.."]" ..
|
||||
"field_close_on_enter[cmnd;false]"..
|
||||
"button[7.9,7.4;2,1;enter;"..S("Enter").."]"
|
||||
end
|
||||
|
||||
local function output(pos, text)
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.output = mem.output .. "\n" .. (text or "")
|
||||
mem.output = mem.output:sub(-500,-1)
|
||||
M(pos):set_string("formspec", formspec2(mem))
|
||||
end
|
||||
|
||||
local function command(pos, mem, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local owner = meta:get_string("owner")
|
||||
|
||||
if mem.command == "clear" then
|
||||
mem.output = ""
|
||||
mem.command = ""
|
||||
meta:set_string("formspec", formspec2(mem))
|
||||
elseif mem.command == "" then
|
||||
output(pos, ">")
|
||||
mem.command = ""
|
||||
meta:set_string("formspec", formspec2(mem))
|
||||
elseif mem.command == "help" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
mem.output = HELP
|
||||
mem.command = ""
|
||||
meta:set_string("formspec", formspec2(mem))
|
||||
elseif mem.command == "pub" and owner == player then
|
||||
meta:set_int("public", 1)
|
||||
output(pos, "> "..mem.command)
|
||||
mem.command = ""
|
||||
output(pos, "Switched to public use!")
|
||||
elseif mem.command == "priv" and owner == player then
|
||||
meta:set_int("public", 0)
|
||||
output(pos, "> "..mem.command)
|
||||
mem.command = ""
|
||||
output(pos, "Switched to private use!")
|
||||
elseif meta:get_int("public") == 1 or owner == player then
|
||||
if mem.command == "clear" then
|
||||
mem.output =
|
||||
mem.command = ""
|
||||
meta:set_string("formspec", formspec2(mem))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("techage:ta4_terminal", {
|
||||
description = "TA4 Collider Terminal",
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
'techage_terminal1_top.png',
|
||||
'techage_terminal1_bottom.png',
|
||||
'techage_terminal1_side.png',
|
||||
'techage_terminal1_side.png',
|
||||
'techage_terminal1_bottom.png',
|
||||
"techage_terminal1_front.png",
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-12/32, -16/32, -8/32, 12/32, -14/32, 12/32},
|
||||
{-12/32, -14/32, 12/32, 12/32, 6/32, 14/32},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-12/32, -16/32, -8/32, 12/32, -14/32, 12/32},
|
||||
{-12/32, -14/32, 12/32, 12/32, 6/32, 14/32},
|
||||
},
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local number = techage.add_node(pos, minetest.get_node(pos).name)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("formspec", formspec1())
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
meta:set_string("infotext", S("TA4 Collider Terminal") .. ": " .. S("not connected")
|
||||
end,
|
||||
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
if fields.number and fields.number ~= "" then
|
||||
local owner = meta:get_string("owner")
|
||||
if techage.check_numbers(fields.number, owner) then
|
||||
local own_number = meta:get_string("own_number")
|
||||
if techage.send_single(own_number, fields.number, "connect") == true then
|
||||
meta:set_string("number", fields.number)
|
||||
meta:set_string("infotext", S("TA4 Collider Terminal") .. ": " .. S("connected with") .. " " .. fields.number)
|
||||
meta:set_string("formspec", formspec2(mem))
|
||||
end
|
||||
end
|
||||
elseif (fields.enter or fields.key_enter_field) and fields.cmnd then
|
||||
mem.command = string.sub(fields.cmnd, 1, STR_LEN)
|
||||
command(pos, mem, player:get_player_name())
|
||||
elseif fields.key_up then
|
||||
mem.command = pdp13.historybuffer_priv(pos)
|
||||
meta:set_string("formspec", formspec2(mem))
|
||||
elseif fields.key_down then
|
||||
mem.command = pdp13.historybuffer_next(pos)
|
||||
meta:set_string("formspec", formspec2(mem))
|
||||
end
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
end,
|
||||
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
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_terminal",
|
||||
recipe = {
|
||||
{"", "techage:ta4_display", ""},
|
||||
{"dye:black", "techage:ta4_wlanchip", "default:copper_ingot"},
|
||||
{"", "techage:aluminum", ""},
|
||||
},
|
||||
})
|
||||
|
||||
techage.register_node({"techage:ta4_terminal"}, {
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "term" then
|
||||
output(pos, payload)
|
||||
return true
|
||||
elseif topic == "clear" then
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.output = ""
|
||||
mem.command = ""
|
||||
M(pos):set_string("formspec", formspec2(mem))
|
||||
return true
|
||||
end
|
||||
end,
|
||||
})
|
@ -208,6 +208,7 @@ techage.Items = {
|
||||
techage_ta5 = "techage:ta5_fr_nucleus",
|
||||
ta5_flycontroller = "techage:ta5_flycontroller",
|
||||
ta5_aichip = "techage:ta5_aichip",
|
||||
ta5_aichip2 = "techage:ta5_aichip2",
|
||||
ta5_tele_pipe = "techage:ta5_tele_pipe",
|
||||
ta5_tele_tube = "techage:ta5_tele_tube",
|
||||
ta5_chest = "techage:ta5_hl_chest",
|
||||
|
@ -254,6 +254,7 @@ techage.manual_DE.aTitel = {
|
||||
"2,Weitere TA5 Blöcke/Items",
|
||||
"3,TA5 Container (geplant)",
|
||||
"3,TA5 KI Chip / TA5 AI Chip",
|
||||
"3,TA5 KI Chip II / TA5 AI Chip II",
|
||||
}
|
||||
|
||||
techage.manual_DE.aText = {
|
||||
@ -360,13 +361,20 @@ techage.manual_DE.aText = {
|
||||
"\n",
|
||||
"Den Köhler brauchst du\\, um Holzkohle herzustellen. Holzkohle wird für den Brenner\\, aber auch bspw. in TA2 für die Dampfmaschine benötigt.\n"..
|
||||
"\n"..
|
||||
"Für den Köhler brauchst du:\n"..
|
||||
"\n"..
|
||||
" - einen Anzünderblock ('techage:lighter')\n"..
|
||||
" - 26 Hölzblöcke (wood)\\, die zu einem Würfen aufgeschichtet werden. Die Holzsorte spielt keine Rolle\n"..
|
||||
" - Erde (dirt) um den Holzhaufen abzudecken\n"..
|
||||
" - Flint and Iron (technischer Name: 'fire:flint_and_steel') um den Anzünderblock anzuzünden\n"..
|
||||
"\n"..
|
||||
"Bauanleitung (siehe auch Plan):\n"..
|
||||
"\n"..
|
||||
" - Baue eine 5x5 große Fläche aus Erde (dirt)\n"..
|
||||
" - Platziere in die Mitte einen Anzünder (lighter)\n"..
|
||||
" - Baue aus Holz (wood) einen 3x3x3 großen Würfel darüber\n"..
|
||||
" - Überdecke alles mit einer Schicht Erde zu einem 5x5x5 großen Würfel\n"..
|
||||
" - Lasse ein Loch zum Anzünder\n"..
|
||||
" - Platziere rund um den Anzünder 7 Holz (wood)\\, aber lasse ein Loch zum Anzünder frei\n"..
|
||||
" - Baue weitere 2 Schichten Holz darüber\\, so dass ein 3x3x3 großen Holzwürfel entsteht\n"..
|
||||
" - Überdecke alles mit einer Schicht Erde zu einem 5x5x5 großen Würfel\\, aber lasse das Loch zum Anzünder frei\n"..
|
||||
" - Zünde den Anzünder an und verschließe das Loch sofort mit jeweils einem Block Holz und Erde\n"..
|
||||
" - Wenn du alles richtig gemacht hast\\, beginnt der Köhler nach wenigen Sekunden an zu rauchen\n"..
|
||||
" - Öffne den Köhler erst\\, wenn der Rauch verschwunden ist (ca. 20 min)\n"..
|
||||
@ -1479,6 +1487,8 @@ techage.manual_DE.aText = {
|
||||
"\n"..
|
||||
"Der Elektrolyseur besitzt ein Schraubenschlüssel-Menü zur Einstellung der Stromaufnahme und des Abschaltpunkts.\n"..
|
||||
"\n"..
|
||||
"Unterschreitet die im Stromnetz gespeicherte Leistung den angegebenen Wert des Abschaltpunkts\\, so schaltet sich der Elektrolyseur automatisch ab. Damit kann ein Leerlaufen der Speichersysteme verhindert werden.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Die Brennstoffzelle wandelt Wasserstoff in Strom um.\n"..
|
||||
@ -1494,16 +1504,18 @@ techage.manual_DE.aText = {
|
||||
"\n",
|
||||
"Der Reaktor dient dazu\\, die über den Destillationsturm oder aus anderen Rezepten gewonnenen Zutaten zu neuen Produkten weiter zu verarbeiten. Der Plan links zeigt nur eine mögliche Variante\\, da die Anordnung der Silos und Tanks rezeptabhängig ist.\n"..
|
||||
"\n"..
|
||||
"Das primäre Ausgabeprodukt wird immer an der Seite des Reaktorständers ausgegeben\\, unabhängig davon\\, ob es sich um ein Pulver oder eine Flüssigkeit handelt. Das (sekundäre) Abfallprodukt wird immer unten am Reaktorständers ausgegeben.\n"..
|
||||
"\n"..
|
||||
"Ein Reaktor besteht aus:\n"..
|
||||
"\n"..
|
||||
" - div. Tanks und Silos mit den Zutaten\\, die über Leitungen mit dem Dosierer verbunden sind\n"..
|
||||
" - optional einem Reaktorsockel\\, welcher die Abfälle aus dem Reaktor ableitet (nur bei Rezepten mit zwei Ausgangsstoffen notwendig)\n"..
|
||||
" - optional einem Reaktorsockel\\, welcher die Abfälle aus dem Reaktor ableitet (nur bei Rezepten mit zwei Ausgabestoffen notwendig)\n"..
|
||||
" - dem Reaktorständer\\, der auf den Sockel gesetzt werden muss (sofern vorhanden). Der Ständer hat einen Stromanschluss und zieht bei Betrieb 8 ku.\n"..
|
||||
" - dem eigentlichen Reaktorbehälter\\, der auf den Reaktorständer gesetzt werden muss\n"..
|
||||
" - dem Einfüllstutzen der auf den Reaktorbehälter gesetzt werden muss\n"..
|
||||
" - dem Dosierer\\, welcher über Leitungen mit den Tanks oder Silos sowie dem Einfüllstutzen verbunden werden muss\n"..
|
||||
"\n"..
|
||||
"Hinweis 1: Flüssigkeiten werden nur in Tanks gelagert\\, feste Stoffe und Stoffe in Pulverform nur in Silos. Dies gilt für Zutaten und Ausgangsstoffe.\n"..
|
||||
"Hinweis 1: Flüssigkeiten werden nur in Tanks gelagert\\, feste Stoffe und Stoffe in Pulverform nur in Silos. Dies gilt für Zutaten und Ausgabestoffe.\n"..
|
||||
"\n"..
|
||||
"Hinweis 2: Tanks oder Silos mit verschiedenen Inhalten dürfen nicht zu einem Leitungssystem verbunden werden. Mehrere Tanks oder Silos mit gleichem Inhalt dürfen dagegen parallel an einer Leitung hängen.\n"..
|
||||
"\n"..
|
||||
@ -1524,7 +1536,7 @@ techage.manual_DE.aText = {
|
||||
"Wie auch bei anderen Maschinen:\n"..
|
||||
"\n"..
|
||||
" - geht der Dosierer in den standby Zustand\\, so fehlen ein oder mehrere Zutaten\n"..
|
||||
" - geht der Dosierer in den blocked Zustand\\, so ist Ausgangstank oder Silo voll\\, defekt oder falsch angeschlossen\n"..
|
||||
" - geht der Dosierer in den blocked Zustand\\, so ist Ausgabetank oder Silo voll\\, defekt oder falsch angeschlossen\n"..
|
||||
"\n"..
|
||||
"Der Dosierer benötigt keinen Strom. Alle 10 s wird ein Rezept abgearbeitet.\n"..
|
||||
"\n"..
|
||||
@ -1541,7 +1553,7 @@ techage.manual_DE.aText = {
|
||||
"\n",
|
||||
"Teil des Chemischen Reaktors. Hier ist auch der Stromanschluss für den Reaktor. Der Reaktor benötigt 8 ku Strom.\n"..
|
||||
"\n"..
|
||||
"Der Ständer hat zwei Leitungsanschlüsse\\, nach rechst für das Ausgangsprodukt und nach unten für den Abfall\\, wie bspw. Rotschlamm bei der Aluminiumherstellung.\n"..
|
||||
"Der Ständer hat zwei Leitungsanschlüsse\\, nach rechst für das primäre Ausgabeprodukt und nach unten für den Abfall\\, wie bspw. Rotschlamm bei der Aluminiumherstellung.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
@ -1722,6 +1734,11 @@ techage.manual_DE.aText = {
|
||||
" - 'b2a' Bewege Block von B nach A\n"..
|
||||
" - 'move' Bewege Block auf die andere Seite\n"..
|
||||
"\n"..
|
||||
"Über das Schraubenschlüssel-Menü kann auf die Betriebsart 'move xyz' umgeschaltet werden. Nach der Umschaltung werden folgende techage Kommandos unterstützt:\n"..
|
||||
"\n"..
|
||||
" - 'move2' Beim Kommando muss zusätzlich die Flugstrecke als x\\,y\\,z Vektor angegeben werden.\nBeispiel Lua Controller: '$send_cmnd(MOVE_CTLR\\, \"move2\"\\, \"0\\,12\\,0\")'\n"..
|
||||
" - 'reset' Block/Blöcke zurück in Startposition bewegen\n"..
|
||||
"\n"..
|
||||
"*Wichtige Hinweise:*\n"..
|
||||
"\n"..
|
||||
" - Sofern mehrere Blöcke bewegt werden sollen\\, muss der Block\\, der die Spieler/Mobs mitnehmen soll\\, beim Antrainieren als erstes angeklickt werden.\n"..
|
||||
@ -2146,6 +2163,10 @@ techage.manual_DE.aText = {
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Der TA5 KI Chip II wird zur Herstellung des TA5 Fusionsreaktors benötigt. Der TA5 KI Chip II kann nur auf der TA4 Elektronik Fab hergestellt werden. Dazu werden 50 Erfahrungspunkte benötigt.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
}
|
||||
|
||||
techage.manual_DE.aItemName = {
|
||||
@ -2402,6 +2423,7 @@ techage.manual_DE.aItemName = {
|
||||
"",
|
||||
"",
|
||||
"ta5_aichip",
|
||||
"ta5_aichip2",
|
||||
}
|
||||
|
||||
techage.manual_DE.aPlanTable = {
|
||||
@ -2658,5 +2680,6 @@ techage.manual_DE.aPlanTable = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
}
|
||||
|
||||
|
@ -254,6 +254,7 @@ techage.manual_EN.aTitel = {
|
||||
"2,More TA5 Blocks/Items",
|
||||
"3,TA5 Container (planned)",
|
||||
"3,TA5 AI Chip",
|
||||
"3,TA5 AI Chip II",
|
||||
}
|
||||
|
||||
techage.manual_EN.aText = {
|
||||
@ -368,13 +369,19 @@ techage.manual_EN.aText = {
|
||||
"\n",
|
||||
"You need the Charcoal Pile to make charcoal. Charcoal is required for the melting furnace\\, but also\\, for example\\, in TA2 for the steam engine.\n"..
|
||||
"\n"..
|
||||
"For the charcoal burner you need:\n"..
|
||||
"\n"..
|
||||
" - a lighter block ('techage:lighter')\n"..
|
||||
" - 26 wooden blocks that are stacked into a pile of wood. The type of wood is irrelevant\n"..
|
||||
" - Dirt to cover the pile of wood\n"..
|
||||
" - Flint and Iron (technical name: 'fire:flint_and_steel') to light the lighter block\n"..
|
||||
"\n"..
|
||||
"Building instructions (see also plan):\n"..
|
||||
"\n"..
|
||||
" - Build a 5x5 area of dirt\n"..
|
||||
" - Place a lighter in the middle\n"..
|
||||
" - Build a 3x3x3 cube above it out of wood\n"..
|
||||
" - Cover everything with a layer of dirt to form a 5x5x5 cube\n"..
|
||||
" - Leave a hole to the lighter\n"..
|
||||
" - Build a 5x5 area of dirt\n"..
|
||||
" - Place 7 wood around the lighter but leave a hole to the lighter\n"..
|
||||
" - Build another 2 layers of wood on top\\, making a 3x3x3 wooden cube\n"..
|
||||
" - Cover everything with a layer of dirt into a 5x5x5 cube\\, but keep the hole to the lighter open\n"..
|
||||
" - Light the lighter and immediately close the hole with a block of wood and dirt\n"..
|
||||
" - If you have done everything correctly\\, the coal burner will start smoking after a few seconds\n"..
|
||||
" - Only open the charcoal burner when the smoke has disappeared (approx. 20 min)\n"..
|
||||
@ -1486,6 +1493,8 @@ techage.manual_EN.aText = {
|
||||
"\n"..
|
||||
"The electrolyzer has a wrench menu for setting the current consumption and the switch-off point.\n"..
|
||||
"\n"..
|
||||
"If the power stored in the power grid falls below the specified value of the switch-off point\\, the electrolyzer switches off automatically. This prevents the storage systems from running empty.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"The fuel cell converts hydrogen into electricity.\n"..
|
||||
@ -1501,16 +1510,18 @@ techage.manual_EN.aText = {
|
||||
"The reactor is used to process the ingredients obtained from the distillation tower or from other recipes into new products.\n"..
|
||||
"The plan on the left shows only one possible variant\\, since the arrangement of the silos and tanks depends on the recipe.\n"..
|
||||
"\n"..
|
||||
"The primary output product is always output to the side of the reactor stand\\, regardless of whether it is a powder or a liquid. The (secondary) waste product is always discharged at the bottom of the reactor stand.\n"..
|
||||
"\n"..
|
||||
"A reactor consists of:\n"..
|
||||
"\n"..
|
||||
" - Various tanks and silos with the ingredients that are connected to the doser via pipes\n"..
|
||||
" - optionally a reactor base\\, which discharges the waste from the reactor (only necessary for recipes with two starting materials)\n"..
|
||||
" - optionally a reactor base\\, which discharges the waste from the reactor (only necessary for recipes with two output products)\n"..
|
||||
" - the reactor stand\\, which must be placed on the base (if available). The stand has a power connection and draws 8 ku during operation.\n"..
|
||||
" - The reactor vessel that has to be placed on the reactor stand\n"..
|
||||
" - The filler pipe that must be placed on the reactor vessel\n"..
|
||||
" - The dosing device\\, which has to be connected to the tanks or silos and the filler pipe via pipes\n"..
|
||||
"\n"..
|
||||
"Note 1: Liquids are only stored in tanks\\, solids and substances in powder form only in silos. This applies to ingredients and raw materials.\n"..
|
||||
"Note 1: Liquids are only stored in tanks\\, solids and substances in powder form only in silos. This applies to ingredients and output products.\n"..
|
||||
"\n"..
|
||||
"Note 2: Tanks or silos with different contents must not be connected to a pipe system. In contrast\\, several tanks or silos with the same content may hang in parallel on one line.\n"..
|
||||
"\n"..
|
||||
@ -1531,7 +1542,7 @@ techage.manual_EN.aText = {
|
||||
"As with other machines:\n"..
|
||||
"\n"..
|
||||
" - if the doser is in standby mode\\, one or more ingredients are missing\n"..
|
||||
" - if the doser is in the blocked state\\, the outlet tank or silo is full\\, defective or incorrectly connected\n"..
|
||||
" - if the doser is in the blocked state\\, the output tank or silo is full\\, defective or incorrectly connected\n"..
|
||||
"\n"..
|
||||
"The doser does not need any electricity. A recipe is processed every 10 s.\n"..
|
||||
"\n"..
|
||||
@ -1728,6 +1739,11 @@ techage.manual_EN.aText = {
|
||||
" - 'b2a' Move block from B to A.\n"..
|
||||
" - 'move' Move block to the other side\n"..
|
||||
"\n"..
|
||||
"You can switch to the 'move xyz' operating mode via the wrench menu. After switching\\, the following techage commands are supported: \n"..
|
||||
"\n"..
|
||||
" - 'move2' With the command\\, the flight route must also be specified as an x\\,y\\,z vector.\nExample Lua Controller: '$send_cmnd(MOVE_CTLR\\, \"move2\"\\, \"0\\,12\\,0\")'\n"..
|
||||
" - 'reset' move block(s) back to start position\n"..
|
||||
"\n"..
|
||||
"*Important instructions:*\n"..
|
||||
"\n"..
|
||||
" - If several blocks are to be moved\\, the block that is to take the players/mobs must be clicked first when training.\n"..
|
||||
@ -2151,6 +2167,10 @@ techage.manual_EN.aText = {
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"The TA5 AI Chip II is required to build the TA5 Fusion Reactor. The TA5 AI Chip II can only be manufactured at the TA4 Electronics Fab. This requires 50 experience points.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
}
|
||||
|
||||
techage.manual_EN.aItemName = {
|
||||
@ -2407,6 +2427,7 @@ techage.manual_EN.aItemName = {
|
||||
"",
|
||||
"",
|
||||
"ta5_aichip",
|
||||
"ta5_aichip2",
|
||||
}
|
||||
|
||||
techage.manual_EN.aPlanTable = {
|
||||
@ -2663,5 +2684,6 @@ techage.manual_EN.aPlanTable = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
}
|
||||
|
||||
|
@ -346,7 +346,8 @@ local STAND = {"techage_reactor_stand_side.png", "techage:ta4_reactor_stand"}
|
||||
local REACT = {"techage_reactor_plan.png", "techage:ta4_reactor"}
|
||||
local FILLR = {"techage_reactor_filler_plan.png", "techage:ta4_reactor_fillerpipe"}
|
||||
local DOSER = {"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_pump_up.png", "techage:ta4_doser"}
|
||||
local SILO = {"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_silo.png", "techage:ta3_silo"}
|
||||
local SILO4 = {"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_silo.png", "techage:ta4_silo"}
|
||||
local TANK4 = {"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_tank.png", "techage:ta4_tank"}
|
||||
|
||||
techage.ConstructionPlans["ta4_reactor"] = {
|
||||
{false, false, false, false, false, false, SIDEV, false, false, false, false},
|
||||
@ -354,9 +355,9 @@ techage.ConstructionPlans["ta4_reactor"] = {
|
||||
{false, false, false, false, PN000, PIPEH, PIPEH, PN270, false, false, false},
|
||||
{false, false, false, false, PIPEV, false, false, FILLR, false, false, false},
|
||||
{false, false, false, false, PIPEV, false, false, REACT, false, false, false},
|
||||
{false, false, false, false, PIPEV, false, false, STAND, PIPEH, PIPEH, SILO},
|
||||
{false, TANK3, PIPEH, PIPEH, DOSER, PN270, false, RBASE, PIPEH, PIPEH, TANK3},
|
||||
{false, SILO, PIPEH, PIPEH, PIPEH, PN180, false, false, false, false, false},
|
||||
{false, false, false, false, PIPEV, false, false, STAND, PIPEH, PIPEH, SILO4},
|
||||
{false, TANK4, PIPEH, PIPEH, DOSER, PN270, false, RBASE, PIPEH, PIPEH, TANK4},
|
||||
{false, SILO4, PIPEH, PIPEH, PIPEH, PN180, false, false, false, false, false},
|
||||
}
|
||||
|
||||
--
|
||||
|
@ -30,7 +30,7 @@ minetest.register_node("techage:glow_gravel", {
|
||||
}},
|
||||
paramtype = "light",
|
||||
light_source = 8,
|
||||
groups = {crumbly = 2, falling_node = 1},
|
||||
groups = {crumbly = 2, falling_node = 1, not_in_creative_inventory = 1},
|
||||
sounds = default.node_sound_gravel_defaults(),
|
||||
drop = "",
|
||||
})
|
||||
|
@ -200,7 +200,7 @@ local tool_config = {
|
||||
choices = "0%,20%,40%,60%,80%,98%",
|
||||
name = "turnoff",
|
||||
label = S("Turnoff point"),
|
||||
tooltip = S("If the charge of the storage\nsystem exceeds the configured value,\nthe block switches off"),
|
||||
tooltip = S("If the charge of the storage\nsystem falls below the configured value,\nthe block switches off"),
|
||||
default = "98%",
|
||||
},
|
||||
}
|
||||
|
@ -105,6 +105,7 @@ dofile(MP.."/basis/submenu.lua")
|
||||
dofile(MP.."/basis/shared_inv.lua")
|
||||
dofile(MP.."/basis/shared_tank.lua")
|
||||
dofile(MP.."/basis/teleport.lua")
|
||||
dofile(MP.."/basis/fly_lib.lua")
|
||||
|
||||
-- Main doc
|
||||
dofile(MP.."/doc/manual_DE.lua")
|
||||
|
@ -14,9 +14,29 @@
|
||||
|
||||
local S = techage.S
|
||||
|
||||
local Stone2Gravel = {
|
||||
["default:stone"] = "default:gravel",
|
||||
["default:cobble"] = "default:gravel",
|
||||
["default:desert_stone"] = "default:gravel",
|
||||
["techage:basalt_stone"] = "techage:basalt_gravel",
|
||||
["techage:basalt_cobble"] = "techage:basalt_gravel",
|
||||
["techage:bauxite_stone"] = "techage:bauxite_gravel",
|
||||
["techage:bauxite_cobble"] = "techage:bauxite_gravel",
|
||||
}
|
||||
|
||||
function techage.register_stone_gravel_pair(stone_name, gravel_name)
|
||||
Stone2Gravel[stone_name] = gravel_name
|
||||
end
|
||||
|
||||
-- Pipeworks uses a fakeplayer based on the owner of the nodebraker.
|
||||
local function is_real_player(player)
|
||||
return minetest.is_player(player) and not player.is_fake_player
|
||||
end
|
||||
|
||||
local function handler(player_name, node, itemstack, digparams)
|
||||
local pos = techage.dug_node[player_name]
|
||||
if not pos then return end
|
||||
techage.dug_node[player_name] = nil
|
||||
|
||||
if minetest.is_protected(pos, player_name) then
|
||||
minetest.record_protection_violation(pos, player_name)
|
||||
@ -30,6 +50,7 @@ local function handler(player_name, node, itemstack, digparams)
|
||||
local item = ItemStack(ndef.drop or node.name)
|
||||
local inv = minetest.get_inventory({type="player", name=player_name})
|
||||
if inv and inv:room_for_item("main", item) then
|
||||
-- item should have been added and can therefore be removed again
|
||||
local taken = inv:remove_item("main", item)
|
||||
else
|
||||
for _,obj in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||
@ -38,8 +59,8 @@ local function handler(player_name, node, itemstack, digparams)
|
||||
end
|
||||
end
|
||||
end
|
||||
if node.name == "techage:basalt_stone" or node.name == "techage:basalt_cobble" then
|
||||
node.name = "techage:basalt_gravel"
|
||||
if Stone2Gravel[node.name] then
|
||||
node.name = Stone2Gravel[node.name]
|
||||
else
|
||||
node.name = "default:gravel"
|
||||
end
|
||||
@ -61,7 +82,9 @@ minetest.register_tool("techage:hammer_stone", {
|
||||
},
|
||||
sound = {breaks = "default_tool_breaks"},
|
||||
after_use = function(itemstack, user, node, digparams)
|
||||
if is_real_player(user) then
|
||||
minetest.after(0.01, handler, user:get_player_name(), node)
|
||||
end
|
||||
itemstack:add_wear(digparams.wear)
|
||||
return itemstack
|
||||
end,
|
||||
@ -80,7 +103,9 @@ minetest.register_tool("techage:hammer_bronze", {
|
||||
},
|
||||
sound = {breaks = "default_tool_breaks"},
|
||||
after_use = function(itemstack, user, node, digparams)
|
||||
if is_real_player(user) then
|
||||
minetest.after(0.01, handler, user:get_player_name(), node)
|
||||
end
|
||||
itemstack:add_wear(digparams.wear)
|
||||
return itemstack
|
||||
end,
|
||||
@ -99,7 +124,9 @@ minetest.register_tool("techage:hammer_steel", {
|
||||
},
|
||||
sound = {breaks = "default_tool_breaks"},
|
||||
after_use = function(itemstack, user, node, digparams)
|
||||
if is_real_player(user) then
|
||||
minetest.after(0.01, handler, user:get_player_name(), node)
|
||||
end
|
||||
itemstack:add_wear(digparams.wear)
|
||||
return itemstack
|
||||
end,
|
||||
@ -118,7 +145,9 @@ minetest.register_tool("techage:hammer_mese", {
|
||||
},
|
||||
sound = {breaks = "default_tool_breaks"},
|
||||
after_use = function(itemstack, user, node, digparams)
|
||||
if is_real_player(user) then
|
||||
minetest.after(0.01, handler, user:get_player_name(), node)
|
||||
end
|
||||
itemstack:add_wear(digparams.wear)
|
||||
return itemstack
|
||||
end,
|
||||
@ -137,7 +166,9 @@ minetest.register_tool("techage:hammer_diamond", {
|
||||
},
|
||||
sound = {breaks = "default_tool_breaks"},
|
||||
after_use = function(itemstack, user, node, digparams)
|
||||
if is_real_player(user) then
|
||||
minetest.after(0.01, handler, user:get_player_name(), node)
|
||||
end
|
||||
itemstack:add_wear(digparams.wear)
|
||||
return itemstack
|
||||
end,
|
||||
|
@ -10,7 +10,8 @@
|
||||
|
||||
Cracking breaks long chains of hydrocarbons into short chains using a catalyst.
|
||||
Gibbsite powder serves as a catalyst (is not consumed).
|
||||
It can be used to convert bitumen into fueloil, fueloil into naphtha and naphtha into gasoline.
|
||||
It can be used to convert bitumen into fueloil, fueloil into naphtha, naphtha into gasoline,
|
||||
and gasoline into gas.
|
||||
|
||||
In hydrogenation, pairs of hydrogen atoms are added to a molecule to convert short-chain
|
||||
hydrocarbons into long ones.
|
||||
@ -45,6 +46,22 @@ techage.recipes.add("ta4_doser", {
|
||||
catalyst = "techage:gibbsite_powder",
|
||||
})
|
||||
|
||||
techage.recipes.add("ta4_doser", {
|
||||
output = "techage:isobutane 1",
|
||||
input = {
|
||||
"techage:gasoline 1",
|
||||
},
|
||||
catalyst = "techage:gibbsite_powder",
|
||||
})
|
||||
|
||||
techage.recipes.add("ta4_doser", {
|
||||
output = "techage:gas 1",
|
||||
input = {
|
||||
"techage:isobutane 1",
|
||||
},
|
||||
catalyst = "techage:gibbsite_powder",
|
||||
})
|
||||
|
||||
-- Hydrogenate
|
||||
techage.recipes.add("ta4_doser", {
|
||||
output = "techage:isobutane 1",
|
||||
|
@ -70,3 +70,21 @@ techage.add_grinder_recipe({input="techage:aluminum", output="techage:aluminum_p
|
||||
techage.add_grinder_recipe({input="default:silver_sandstone", output="techage:silver_sandstone_powder"})
|
||||
techage.add_grinder_recipe({input="default:coal_lump", output="techage:graphite_powder"})
|
||||
|
||||
if minetest.get_modpath("ethereal") then
|
||||
techage.add_grinder_recipe({input="ethereal:bush", output="techage:leave_powder"})
|
||||
techage.add_grinder_recipe({input="ethereal:bush2", output="techage:leave_powder"})
|
||||
techage.add_grinder_recipe({input="ethereal:bush3", output="techage:leave_powder"})
|
||||
techage.add_grinder_recipe({input="ethereal:bamboo_leaves", output="techage:leave_powder"})
|
||||
techage.add_grinder_recipe({input="ethereal:bananaleaves", output="techage:leave_powder"})
|
||||
techage.add_grinder_recipe({input="ethereal:birch_leaves", output="techage:leave_powder"})
|
||||
techage.add_grinder_recipe({input="ethereal:frost_leaves", output="techage:leave_powder"})
|
||||
techage.add_grinder_recipe({input="ethereal:lemon_leaves", output="techage:leave_powder"})
|
||||
techage.add_grinder_recipe({input="ethereal:olive_leaves", output="techage:leave_powder"})
|
||||
techage.add_grinder_recipe({input="ethereal:orange_leaves", output="techage:leave_powder"})
|
||||
techage.add_grinder_recipe({input="ethereal:palmleaves", output="techage:leave_powder"})
|
||||
techage.add_grinder_recipe({input="ethereal:redwood_leaves", output="techage:leave_powder"})
|
||||
techage.add_grinder_recipe({input="ethereal:sakura_leaves", output="techage:leave_powder"})
|
||||
techage.add_grinder_recipe({input="ethereal:ethereal:sakura_leaves2", output="techage:leave_powder"})
|
||||
techage.add_grinder_recipe({input="ethereal:willow_twig", output="techage:leave_powder"})
|
||||
techage.add_grinder_recipe({input="ethereal:yellowleaves", output="techage:leave_powder"})
|
||||
end
|
||||
|
@ -58,11 +58,13 @@ minetest.register_craft({
|
||||
})
|
||||
|
||||
techage.furnace.register_recipe({
|
||||
output = "techage:red_stone",
|
||||
output = "techage:red_stone 3",
|
||||
recipe = {
|
||||
"techage:canister_redmud",
|
||||
"default:sand",
|
||||
"default:sand",
|
||||
"default:sand",
|
||||
},
|
||||
waste = "techage:ta3_canister_empty",
|
||||
time = 4,
|
||||
time = 10,
|
||||
})
|
||||
|
@ -19,7 +19,19 @@ minetest.register_craftitem("techage:ta4_silicon_wafer", {
|
||||
inventory_image = "techage_silicon_wafer.png",
|
||||
})
|
||||
|
||||
techage.furnace.register_recipe({
|
||||
if minetest.global_exists("mesecon") then
|
||||
techage.furnace.register_recipe({
|
||||
output = "techage:ta4_silicon_wafer 16",
|
||||
recipe = {
|
||||
"mesecons_materials:silicon",
|
||||
"mesecons_materials:silicon",
|
||||
"mesecons_materials:silicon",
|
||||
"techage:baborium_ingot"
|
||||
},
|
||||
time = 6,
|
||||
})
|
||||
else
|
||||
techage.furnace.register_recipe({
|
||||
output = "techage:ta4_silicon_wafer 16",
|
||||
recipe = {
|
||||
"basic_materials:silicon",
|
||||
@ -28,4 +40,6 @@ techage.furnace.register_recipe({
|
||||
"techage:baborium_ingot"
|
||||
},
|
||||
time = 6,
|
||||
})
|
||||
})
|
||||
end
|
||||
|
||||
|
@ -60,7 +60,7 @@ local State4 = techage.NodeStates:new({
|
||||
-- Function returns the number of pumped units
|
||||
local function pump(pos, mem, nvm, state, outdir, units)
|
||||
local taken, name = liquid.take(pos, Pipe, Flip[outdir], nil, units, mem.dbg_cycles > 0)
|
||||
if taken > 0 then
|
||||
if taken > 0 and name then
|
||||
local leftover = liquid.put(pos, Pipe, outdir, name, taken, mem.dbg_cycles > 0)
|
||||
if leftover and leftover > 0 then
|
||||
-- air needs no tank
|
||||
|
@ -128,9 +128,15 @@ TA4 Button/Switch=TA4 Schalter/Taster
|
||||
|
||||
Access=Zugriff
|
||||
Button protection=Tastenschutz
|
||||
Type=Typ
|
||||
|
||||
### button.lua ###
|
||||
### button_2x.lua ###
|
||||
### button_4x.lua ###
|
||||
### player_detector.lua ###
|
||||
|
||||
Command=Kommando
|
||||
Number=Nummer
|
||||
Type=Typ
|
||||
|
||||
### button.lua ###
|
||||
### cart_detector.lua ###
|
||||
@ -163,10 +169,15 @@ TA4 2x Button=TA4 2x Taster
|
||||
### button_4x.lua ###
|
||||
|
||||
Command to be sent (ignored for switches)=Zu sendender Befehl (wird für Schalter ignoriert)
|
||||
Destination block number=Zielblocknummer
|
||||
Label for the button=Beschriftung für die Taste
|
||||
Momentary button or on/off switch=Taster oder Ein-/Ausschalter
|
||||
|
||||
### button_2x.lua ###
|
||||
### button_4x.lua ###
|
||||
### player_detector.lua ###
|
||||
|
||||
Destination block number=Zielblocknummer
|
||||
|
||||
### button_2x.lua ###
|
||||
### button_4x.lua ###
|
||||
### signallamp_2x.lua ###
|
||||
@ -387,7 +398,7 @@ Power=Strom
|
||||
Configurable value@nfor the current limit=Konfigurierbarer Wert@nfür die Strombegrenzung
|
||||
Current limitation=Strombegrenzung
|
||||
Electrolyzer=Eletrolyseur
|
||||
If the charge of the storage@nsystem exceeds the configured value,@nthe block switches off=Überschreitet die Ladung des@nSpeichersystems den konfigurierten@nWert, schaltet sich der Block ab
|
||||
If the charge of the storage@nsystem falls below the configured value,@nthe block switches off=unterschreitet die Ladung des@nSpeichersystems den konfigurierten@nWert, schaltet sich der Block ab
|
||||
Maximum possible@ncurrent consumption=Maximal mögliche Stromaufnahme
|
||||
Maximum power consumption [ku]=maximale Stromaufnahme
|
||||
Storage full=Speicher voll
|
||||
@ -453,7 +464,9 @@ Destination position is protected=Zielposition ist geschützt
|
||||
Error: Max. length of the flight route exceeded by @1 blocks !!=Fehler: max. Länge der Flugstrecke um @1 Blöcke überschritten !!
|
||||
No valid destination position=Keine gültige Zielposition
|
||||
No valid node at the start position=Kein gültiger Block an der Startposition
|
||||
Running=In Betrieb
|
||||
Start position is protected=Startposition ist geschützt
|
||||
Stopped=Gestoppt
|
||||
|
||||
### fly_lib.lua ###
|
||||
### flycontroller.lua ###
|
||||
@ -959,6 +972,10 @@ Plastic Granules=Plastikgranulat
|
||||
|
||||
### player_detector.lua ###
|
||||
|
||||
Command to send when player is detected=Befehl zum Senden, wenn ein Spieler erkannt wird
|
||||
Command to send when player moves away=Befehl zum Senden, wenn sich der Spieler wegbewegt
|
||||
Radius=Radius
|
||||
Search radius=Suchradius
|
||||
TA4 Player Detector=TA4 Spieler Detektor
|
||||
|
||||
### powder.lua ###
|
||||
@ -1151,12 +1168,14 @@ stopped=gestoppt
|
||||
<num> is a number from 1 to 50000 and is@n=<num> ist eine Nummer von 1 bis 50000 und ist@n
|
||||
@n=@n
|
||||
Commands=Kommandos
|
||||
Cycle time=Zykluszeit
|
||||
Example:@n=Beispiel:
|
||||
Invalid command!=Ungültiges Kommando!
|
||||
Start=Start
|
||||
Stop=Stopp
|
||||
Syntax:@n=Syntax:@n
|
||||
TA4 Sequencer=TA4 Sequenzer
|
||||
Timer cycle time (default: 100 ms)=Zykluszeit (normal: 100 ms)
|
||||
running=läuft
|
||||
the timeslot when the command is executed.@n=der Zeitpunkt, wenn der Befehl ausgeführt wird.@n
|
||||
|
||||
|
@ -115,7 +115,7 @@ TA3 Booster=
|
||||
|
||||
Access:=
|
||||
Button or switch=
|
||||
Change the node name (infotext)=
|
||||
Change the block name (infotext)=
|
||||
Command to be sent=
|
||||
Destination block number(s)=
|
||||
Infotext=
|
||||
@ -128,9 +128,15 @@ TA4 Button/Switch=
|
||||
|
||||
Access=
|
||||
Button protection=
|
||||
Type=
|
||||
|
||||
### button.lua ###
|
||||
### button_2x.lua ###
|
||||
### button_4x.lua ###
|
||||
### player_detector.lua ###
|
||||
|
||||
Command=
|
||||
Number=
|
||||
Type=
|
||||
|
||||
### button.lua ###
|
||||
### cart_detector.lua ###
|
||||
@ -163,10 +169,15 @@ TA4 2x Button=
|
||||
### button_4x.lua ###
|
||||
|
||||
Command to be sent (ignored for switches)=
|
||||
Destination block number=
|
||||
Label for the button=
|
||||
Momentary button or on/off switch=
|
||||
|
||||
### button_2x.lua ###
|
||||
### button_4x.lua ###
|
||||
### player_detector.lua ###
|
||||
|
||||
Destination block number=
|
||||
|
||||
### button_2x.lua ###
|
||||
### button_4x.lua ###
|
||||
### signallamp_2x.lua ###
|
||||
@ -387,7 +398,7 @@ Power=
|
||||
Configurable value@nfor the current limit=
|
||||
Current limitation=
|
||||
Electrolyzer=
|
||||
If the charge of the storage@nsystem exceeds the configured value,@nthe block switches off=
|
||||
If the charge of the storage@nsystem falls below the configured value,@nthe block switches off=
|
||||
Maximum possible@ncurrent consumption=
|
||||
Maximum power consumption [ku]=
|
||||
Storage full=
|
||||
@ -453,7 +464,9 @@ Destination position is protected=
|
||||
Error: Max. length of the flight route exceeded by @1 blocks !!=
|
||||
No valid destination position=
|
||||
No valid node at the start position=
|
||||
Running=
|
||||
Start position is protected=
|
||||
Stopped=
|
||||
|
||||
### fly_lib.lua ###
|
||||
### flycontroller.lua ###
|
||||
@ -959,6 +972,10 @@ Plastic Granules=
|
||||
|
||||
### player_detector.lua ###
|
||||
|
||||
Command to send when player is detected=
|
||||
Command to send when player moves away=
|
||||
Radius=
|
||||
Search radius=
|
||||
TA4 Player Detector=
|
||||
|
||||
### powder.lua ###
|
||||
@ -1151,12 +1168,14 @@ stopped=
|
||||
<num> is a number from 1 to 50000 and is@n=
|
||||
@n=
|
||||
Commands=
|
||||
Cycle time=
|
||||
Example:@n=
|
||||
Invalid command!=
|
||||
Start=
|
||||
Stop=
|
||||
Syntax:@n=
|
||||
TA4 Sequencer=
|
||||
Timer cycle time (default: 100 ms)=
|
||||
running=
|
||||
the timeslot when the command is executed.@n=
|
||||
|
||||
|
@ -68,10 +68,7 @@ local function switch_on(pos)
|
||||
elseif name == "techage:ta4_button_off" then
|
||||
logic.swap_node(pos, "techage:ta4_button_on")
|
||||
end
|
||||
local meta = M(pos)
|
||||
local s = meta:contains("command") and meta:get_string("command") or "on"
|
||||
local command, payload = unpack(string.split(s, " ", false, 1))
|
||||
logic.send_cmnd(pos, M(pos), command, payload, cycle_time)
|
||||
logic.send_cmnd(pos, "command", "on", cycle_time)
|
||||
minetest.sound_play("techage_button", {
|
||||
pos = pos,
|
||||
gain = 0.5,
|
||||
|
@ -67,13 +67,16 @@ function techage.logic.send_on(pos, meta, time)
|
||||
return own_num == numbers
|
||||
end
|
||||
|
||||
function techage.logic.send_cmnd(pos, meta, cmnd, payload, time)
|
||||
function techage.logic.send_cmnd(pos, ident, default, time)
|
||||
local meta = M(pos)
|
||||
local s = meta:contains(ident) and meta:get_string(ident) or default
|
||||
local command, payload = unpack(string.split(s, " ", false, 1))
|
||||
local own_num = meta:get_string("node_number") or ""
|
||||
local numbers = meta:get_string("numbers") or ""
|
||||
if time and time > 0 then
|
||||
minetest.get_node_timer(pos):start(time)
|
||||
end
|
||||
techage.send_multi(own_num, numbers, cmnd, payload)
|
||||
techage.send_multi(own_num, numbers, command, payload)
|
||||
end
|
||||
|
||||
function techage.logic.send_off(pos, meta)
|
||||
|
@ -20,15 +20,48 @@ local NDEF = function(pos) return (minetest.registered_nodes[techage.get_node_lv
|
||||
local logic = techage.logic
|
||||
local CYCLE_TIME = 1
|
||||
|
||||
local WRENCH_MENU = {
|
||||
{
|
||||
type = "dropdown",
|
||||
choices = "1,2,3,4,5,6,7,8",
|
||||
name = "radius",
|
||||
label = S("Radius"),
|
||||
tooltip = S("Search radius"),
|
||||
default = "4",
|
||||
},
|
||||
{
|
||||
type = "numbers",
|
||||
name = "numbers",
|
||||
label = S("Number"),
|
||||
tooltip = S("Destination block number"),
|
||||
default = "",
|
||||
check = techage.check_numbers,
|
||||
},
|
||||
{
|
||||
type = "ascii",
|
||||
name = "command1",
|
||||
label = "On " .. S("Command"),
|
||||
tooltip = S("Command to send when player is detected"),
|
||||
default = "on",
|
||||
},
|
||||
{
|
||||
type = "ascii",
|
||||
name = "command2",
|
||||
label = "Off " .. S("Command"),
|
||||
tooltip = S("Command to send when player moves away"),
|
||||
default = "off",
|
||||
},
|
||||
}
|
||||
|
||||
local function switch_on(pos, stage)
|
||||
if logic.swap_node(pos, "techage:ta"..stage.."_playerdetector_on") then
|
||||
logic.send_on(pos, M(pos))
|
||||
logic.send_cmnd(pos, "command1", "on")
|
||||
end
|
||||
end
|
||||
|
||||
local function switch_off(pos, stage)
|
||||
if logic.swap_node(pos, "techage:ta"..stage.."_playerdetector_off") then
|
||||
logic.send_off(pos, M(pos))
|
||||
logic.send_cmnd(pos, "command2", "off")
|
||||
end
|
||||
end
|
||||
|
||||
@ -36,7 +69,8 @@ local function scan_for_player(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local names = meta:get_string("names") or ""
|
||||
for _, object in pairs(minetest.get_objects_inside_radius(pos, 4)) do
|
||||
local radius = meta:contains("radius") and meta:get_int("radius") or 4
|
||||
for _, object in pairs(minetest.get_objects_inside_radius(pos, radius)) do
|
||||
if object:is_player() then
|
||||
if names == "" then
|
||||
nvm.player_name = object:get_player_name()
|
||||
@ -228,6 +262,7 @@ minetest.register_node("techage:ta4_playerdetector_off", {
|
||||
techage.del_mem(pos)
|
||||
end,
|
||||
|
||||
ta4_formspec = WRENCH_MENU,
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
paramtype2 = "facedir",
|
||||
@ -277,6 +312,7 @@ minetest.register_node("techage:ta4_playerdetector_on", {
|
||||
techage.del_mem(pos)
|
||||
end,
|
||||
|
||||
ta4_formspec = WRENCH_MENU,
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
paramtype2 = "facedir",
|
||||
|
@ -17,13 +17,22 @@ Die Haltbarkeit/Härte bspw. für eine Axt ist:
|
||||
|
||||
Den Köhler brauchst du, um Holzkohle herzustellen. Holzkohle wird für den Brenner, aber auch bspw. in TA2 für die Dampfmaschine benötigt.
|
||||
|
||||
Für den Köhler brauchst du:
|
||||
|
||||
- einen Anzünderblock (`techage:lighter`)
|
||||
- 26 Hölzblöcke (wood), die zu einem Würfen aufgeschichtet werden. Die Holzsorte spielt keine Rolle
|
||||
- Erde (dirt) um den Holzhaufen abzudecken
|
||||
- Flint and Iron (technischer Name: `fire:flint_and_steel`) um den Anzünderblock anzuzünden
|
||||
|
||||
|
||||
|
||||
Bauanleitung (siehe auch Plan):
|
||||
|
||||
- Baue eine 5x5 große Fläche aus Erde (dirt)
|
||||
- Platziere in die Mitte einen Anzünder (lighter)
|
||||
- Baue aus Holz (wood) einen 3x3x3 großen Würfel darüber
|
||||
- Überdecke alles mit einer Schicht Erde zu einem 5x5x5 großen Würfel
|
||||
- Lasse ein Loch zum Anzünder
|
||||
- Platziere rund um den Anzünder 7 Holz (wood), aber lasse ein Loch zum Anzünder frei
|
||||
- Baue weitere 2 Schichten Holz darüber, so dass ein 3x3x3 großen Holzwürfel entsteht
|
||||
- Überdecke alles mit einer Schicht Erde zu einem 5x5x5 großen Würfel, aber lasse das Loch zum Anzünder frei
|
||||
- Zünde den Anzünder an und verschließe das Loch sofort mit jeweils einem Block Holz und Erde
|
||||
- Wenn du alles richtig gemacht hast, beginnt der Köhler nach wenigen Sekunden an zu rauchen
|
||||
- Öffne den Köhler erst, wenn der Rauch verschwunden ist (ca. 20 min)
|
||||
|
@ -17,13 +17,21 @@ The durability / hardness for an axe, for example:
|
||||
|
||||
You need the Charcoal Pile to make charcoal. Charcoal is required for the melting furnace, but also, for example, in TA2 for the steam engine.
|
||||
|
||||
For the charcoal burner you need:
|
||||
|
||||
- a lighter block (`techage:lighter`)
|
||||
- 26 wooden blocks that are stacked into a pile of wood. The type of wood is irrelevant
|
||||
- Dirt to cover the pile of wood
|
||||
- Flint and Iron (technical name: `fire:flint_and_steel`) to light the lighter block
|
||||
|
||||
|
||||
|
||||
Building instructions (see also plan):
|
||||
|
||||
- Build a 5x5 area of dirt
|
||||
- Place a lighter in the middle
|
||||
- Build a 3x3x3 cube above it out of wood
|
||||
- Cover everything with a layer of dirt to form a 5x5x5 cube
|
||||
- Leave a hole to the lighter
|
||||
- Build a 5x5 area of dirt
|
||||
- Place 7 wood around the lighter but leave a hole to the lighter
|
||||
- Build another 2 layers of wood on top, making a 3x3x3 wooden cube
|
||||
- Cover everything with a layer of dirt into a 5x5x5 cube, but keep the hole to the lighter open
|
||||
- Light the lighter and immediately close the hole with a block of wood and dirt
|
||||
- If you have done everything correctly, the coal burner will start smoking after a few seconds
|
||||
- Only open the charcoal burner when the smoke has disappeared (approx. 20 min)
|
||||
|
@ -258,6 +258,8 @@ In den Elektrolyseur passen 200 Einheiten Wasserstoff.
|
||||
|
||||
Der Elektrolyseur besitzt ein Schraubenschlüssel-Menü zur Einstellung der Stromaufnahme und des Abschaltpunkts.
|
||||
|
||||
Unterschreitet die im Stromnetz gespeicherte Leistung den angegebenen Wert des Abschaltpunkts, so schaltet sich der Elektrolyseur automatisch ab. Damit kann ein Leerlaufen der Speichersysteme verhindert werden.
|
||||
|
||||
[ta4_electrolyzer|image]
|
||||
|
||||
|
||||
@ -279,15 +281,17 @@ In diesem Fall können keine anderen Blöcke der Kategorie 2 wie der Akku-Block
|
||||
|
||||
Der Reaktor dient dazu, die über den Destillationsturm oder aus anderen Rezepten gewonnenen Zutaten zu neuen Produkten weiter zu verarbeiten. Der Plan links zeigt nur eine mögliche Variante, da die Anordnung der Silos und Tanks rezeptabhängig ist.
|
||||
|
||||
Das primäre Ausgabeprodukt wird immer an der Seite des Reaktorständers ausgegeben, unabhängig davon, ob es sich um ein Pulver oder eine Flüssigkeit handelt. Das (sekundäre) Abfallprodukt wird immer unten am Reaktorständers ausgegeben.
|
||||
|
||||
Ein Reaktor besteht aus:
|
||||
- div. Tanks und Silos mit den Zutaten, die über Leitungen mit dem Dosierer verbunden sind
|
||||
- optional einem Reaktorsockel, welcher die Abfälle aus dem Reaktor ableitet (nur bei Rezepten mit zwei Ausgangsstoffen notwendig)
|
||||
- optional einem Reaktorsockel, welcher die Abfälle aus dem Reaktor ableitet (nur bei Rezepten mit zwei Ausgabestoffen notwendig)
|
||||
- dem Reaktorständer, der auf den Sockel gesetzt werden muss (sofern vorhanden). Der Ständer hat einen Stromanschluss und zieht bei Betrieb 8 ku.
|
||||
- dem eigentlichen Reaktorbehälter, der auf den Reaktorständer gesetzt werden muss
|
||||
- dem Einfüllstutzen der auf den Reaktorbehälter gesetzt werden muss
|
||||
- dem Dosierer, welcher über Leitungen mit den Tanks oder Silos sowie dem Einfüllstutzen verbunden werden muss
|
||||
|
||||
Hinweis 1: Flüssigkeiten werden nur in Tanks gelagert, feste Stoffe und Stoffe in Pulverform nur in Silos. Dies gilt für Zutaten und Ausgangsstoffe.
|
||||
Hinweis 1: Flüssigkeiten werden nur in Tanks gelagert, feste Stoffe und Stoffe in Pulverform nur in Silos. Dies gilt für Zutaten und Ausgabestoffe.
|
||||
|
||||
Hinweis 2: Tanks oder Silos mit verschiedenen Inhalten dürfen nicht zu einem Leitungssystem verbunden werden. Mehrere Tanks oder Silos mit gleichem Inhalt dürfen dagegen parallel an einer Leitung hängen.
|
||||
|
||||
@ -310,7 +314,7 @@ Auf allen 4 Seiten der Dosierers können Leitungen für Eingangsmaterialien ange
|
||||
|
||||
Wie auch bei anderen Maschinen:
|
||||
- geht der Dosierer in den standby Zustand, so fehlen ein oder mehrere Zutaten
|
||||
- geht der Dosierer in den blocked Zustand, so ist Ausgangstank oder Silo voll, defekt oder falsch angeschlossen
|
||||
- geht der Dosierer in den blocked Zustand, so ist Ausgabetank oder Silo voll, defekt oder falsch angeschlossen
|
||||
|
||||
Der Dosierer benötigt keinen Strom. Alle 10 s wird ein Rezept abgearbeitet.
|
||||
|
||||
@ -335,7 +339,7 @@ Teil des Chemischen Reaktors. Muss auf den Reaktor gesetzt werden. Wenn dies nic
|
||||
|
||||
Teil des Chemischen Reaktors. Hier ist auch der Stromanschluss für den Reaktor. Der Reaktor benötigt 8 ku Strom.
|
||||
|
||||
Der Ständer hat zwei Leitungsanschlüsse, nach rechst für das Ausgangsprodukt und nach unten für den Abfall, wie bspw. Rotschlamm bei der Aluminiumherstellung.
|
||||
Der Ständer hat zwei Leitungsanschlüsse, nach rechst für das primäre Ausgabeprodukt und nach unten für den Abfall, wie bspw. Rotschlamm bei der Aluminiumherstellung.
|
||||
|
||||
[ta4_reactorstand|image]
|
||||
|
||||
@ -583,6 +587,12 @@ Der Move Controller unterstützt folgende techage Kommandos:
|
||||
- `b2a` Bewege Block von B nach A
|
||||
- `move` Bewege Block auf die andere Seite
|
||||
|
||||
Über das Schraubenschlüssel-Menü kann auf die Betriebsart `move xyz` umgeschaltet werden. Nach der Umschaltung werden folgende techage Kommandos unterstützt:
|
||||
|
||||
- `move2` Beim Kommando muss zusätzlich die Flugstrecke als x,y,z Vektor angegeben werden.
|
||||
Beispiel Lua Controller: `$send_cmnd(MOVE_CTLR, "move2", "0,12,0")`
|
||||
- `reset` Block/Blöcke zurück in Startposition bewegen
|
||||
|
||||
**Wichtige Hinweise:**
|
||||
|
||||
- Sofern mehrere Blöcke bewegt werden sollen, muss der Block, der die Spieler/Mobs mitnehmen soll, beim Antrainieren als erstes angeklickt werden.
|
||||
|
@ -251,6 +251,8 @@ The electrolyzer can draw up to 35 ku of electricity and then generates a hydrog
|
||||
|
||||
The electrolyzer has a wrench menu for setting the current consumption and the switch-off point.
|
||||
|
||||
If the power stored in the power grid falls below the specified value of the switch-off point, the electrolyzer switches off automatically. This prevents the storage systems from running empty.
|
||||
|
||||
[ta4_electrolyzer|image]
|
||||
|
||||
|
||||
@ -272,15 +274,17 @@ In this case, no other category 2 blocks such as the battery block can be charge
|
||||
The reactor is used to process the ingredients obtained from the distillation tower or from other recipes into new products.
|
||||
The plan on the left shows only one possible variant, since the arrangement of the silos and tanks depends on the recipe.
|
||||
|
||||
The primary output product is always output to the side of the reactor stand, regardless of whether it is a powder or a liquid. The (secondary) waste product is always discharged at the bottom of the reactor stand.
|
||||
|
||||
A reactor consists of:
|
||||
- Various tanks and silos with the ingredients that are connected to the doser via pipes
|
||||
- optionally a reactor base, which discharges the waste from the reactor (only necessary for recipes with two starting materials)
|
||||
- optionally a reactor base, which discharges the waste from the reactor (only necessary for recipes with two output products)
|
||||
- the reactor stand, which must be placed on the base (if available). The stand has a power connection and draws 8 ku during operation.
|
||||
- The reactor vessel that has to be placed on the reactor stand
|
||||
- The filler pipe that must be placed on the reactor vessel
|
||||
- The dosing device, which has to be connected to the tanks or silos and the filler pipe via pipes
|
||||
|
||||
Note 1: Liquids are only stored in tanks, solids and substances in powder form only in silos. This applies to ingredients and raw materials.
|
||||
Note 1: Liquids are only stored in tanks, solids and substances in powder form only in silos. This applies to ingredients and output products.
|
||||
|
||||
Note 2: Tanks or silos with different contents must not be connected to a pipe system. In contrast, several tanks or silos with the same content may hang in parallel on one line.
|
||||
|
||||
@ -304,7 +308,7 @@ The recipe can be set and the reactor started via the doser.
|
||||
|
||||
As with other machines:
|
||||
- if the doser is in standby mode, one or more ingredients are missing
|
||||
- if the doser is in the blocked state, the outlet tank or silo is full, defective or incorrectly connected
|
||||
- if the doser is in the blocked state, the output tank or silo is full, defective or incorrectly connected
|
||||
|
||||
The doser does not need any electricity. A recipe is processed every 10 s.
|
||||
|
||||
@ -574,6 +578,12 @@ The Move Controller supports the following techage commands:
|
||||
- `b2a` Move block from B to A.
|
||||
- `move` Move block to the other side
|
||||
|
||||
You can switch to the `move xyz` operating mode via the wrench menu. After switching, the following techage commands are supported:
|
||||
|
||||
- `move2` With the command, the flight route must also be specified as an x,y,z vector.
|
||||
Example Lua Controller: `$send_cmnd(MOVE_CTLR, "move2", "0,12,0")`
|
||||
- `reset` move block(s) back to start position
|
||||
|
||||
**Important instructions:**
|
||||
|
||||
- If several blocks are to be moved, the block that is to take the players/mobs must be clicked first when training.
|
||||
|
@ -159,3 +159,9 @@ Für die Nutzung des TA5 Containers werden 80 Erfahrungspunkte benötigt.
|
||||
Der TA5 KI Chip wird teilweise zur Herstellung von TA5 Blöcken benötigt. Der TA5 KI Chip kann nur auf der TA4 Elektronik Fab hergestellt werden. Dazu werden 10 Erfahrungspunkte benötigt.
|
||||
|
||||
[ta5_aichip|image]
|
||||
|
||||
### TA5 KI Chip II / TA5 AI Chip II
|
||||
|
||||
Der TA5 KI Chip II wird zur Herstellung des TA5 Fusionsreaktors benötigt. Der TA5 KI Chip II kann nur auf der TA4 Elektronik Fab hergestellt werden. Dazu werden 50 Erfahrungspunkte benötigt.
|
||||
|
||||
[ta5_aichip2|image]
|
@ -159,3 +159,9 @@ The TA5 container allows Techage systems to be packed and unpacked at another lo
|
||||
The TA5 AI Chip is partly required for the production of TA5 blocks. The TA5 AI Chip can only be manufactured at the TA4 Electronics Fab. This requires 10 experience points.
|
||||
|
||||
[ta5_aichip|image]
|
||||
|
||||
### TA5 AI Chip II
|
||||
|
||||
The TA5 AI Chip II is required to build the TA5 Fusion Reactor. The TA5 AI Chip II can only be manufactured at the TA4 Electronics Fab. This requires 50 experience points.
|
||||
|
||||
[ta5_aichip2|image]
|
||||
|
@ -5,7 +5,7 @@
|
||||
import re
|
||||
import sys
|
||||
import pprint
|
||||
import mistune # must be v0.8.4
|
||||
import mistune # must be v0.8.4, install with 'sudo pip install mistune==0.8.4'
|
||||
|
||||
def formspec_escape(text):
|
||||
text = text.replace("\\", "")
|
||||
|
@ -406,7 +406,7 @@ Please note, that this is not a technical distinction, only a logical.
|
||||
| "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 |
|
||||
| "move2" | x,y,z | TA4 Move Controller command to move the block(s) by the given<br /> x/y/z-distance. Valid ranges for x, y, and z are -100 to 100. |
|
||||
| "move2" | x,y,z | TA4 Move Controller command to move the block(s) by the given<br /> x/y/z-distance. Valid ranges for x, y, and z are -100 to 100.<br />Example: `$send_cmnd("1674", "move2", "0,4,0")` |
|
||||
| "reset" | nil | Reset TA4 Move Controller (move block(s) to start position) |
|
||||
| "left" | nil | TA4 Turn Controller command to turn the block(s) to the left |
|
||||
| "right" | nil | TA4 Turn Controller command to turn the block(s) to the right |
|
||||
|
@ -253,3 +253,4 @@
|
||||
- [Weitere TA5 Blöcke/Items](./manual_ta5_DE.md#weitere-ta5-blöckeitems)
|
||||
- [TA5 Container (geplant)](./manual_ta5_DE.md#ta5-container-(geplant))
|
||||
- [TA5 KI Chip / TA5 AI Chip](./manual_ta5_DE.md#ta5-ki-chip--ta5-ai-chip)
|
||||
- [TA5 KI Chip II / TA5 AI Chip II](./manual_ta5_DE.md#ta5-ki-chip-ii--ta5-ai-chip-ii)
|
@ -253,3 +253,4 @@
|
||||
- [More TA5 Blocks/Items](./manual_ta5_EN.md#more-ta5-blocksitems)
|
||||
- [TA5 Container (planned)](./manual_ta5_EN.md#ta5-container-(planned))
|
||||
- [TA5 AI Chip](./manual_ta5_EN.md#ta5-ai-chip)
|
||||
- [TA5 AI Chip II](./manual_ta5_EN.md#ta5-ai-chip-ii)
|
@ -1,4 +1,4 @@
|
||||
name = techage
|
||||
depends = default,doors,flowers,tubelib2,networks,basic_materials,bucket,stairs,screwdriver,minecart,lcdlib,safer_lua
|
||||
optional_depends = unified_inventory,wielded_light,unifieddyes,moreores,ethereal,mesecons,digtron,bakedclay,moreblocks,i3,creative,craftguide
|
||||
optional_depends = unified_inventory,wielded_light,unifieddyes,moreores,ethereal,mesecons,mesecons_materials,mesecons_mvps,digtron,bakedclay,moreblocks,i3,creative,craftguide
|
||||
description = Techage, go through 5 tech ages in search of wealth and power!
|
||||
|
@ -17,9 +17,8 @@ local M = minetest.get_meta
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S = techage.S
|
||||
|
||||
local MP = minetest.get_modpath("techage")
|
||||
local flylib = dofile(MP .. "/basis/fly_lib.lua")
|
||||
local logic = techage.logic
|
||||
local fly = techage.flylib
|
||||
|
||||
local MarkedNodes = {} -- t[player] = {{entity, pos},...}
|
||||
local CurrentPos -- to mark punched entities
|
||||
@ -141,9 +140,9 @@ local function exchange_node(pos, item, param2)
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
if node and is_simple_node(node.name) then
|
||||
if item and item:get_name() ~= "" and minetest.registered_nodes[item:get_name()] then
|
||||
flylib.exchange_node(pos, item:get_name(), param2)
|
||||
fly.exchange_node(pos, item:get_name(), param2)
|
||||
else
|
||||
flylib.remove_node(pos)
|
||||
fly.remove_node(pos)
|
||||
end
|
||||
if not techage.is_air_like(node.name) then
|
||||
return ItemStack(node.name), node.param2
|
||||
@ -439,7 +438,7 @@ local Doors = {
|
||||
for _, name in ipairs(Doors) do
|
||||
for _, postfix in ipairs({"a", "b", "c", "d"}) do
|
||||
techage.register_simple_nodes({name .. "_" .. postfix}, true)
|
||||
flylib.protect_door_from_being_opened(name .. "_" .. postfix)
|
||||
fly.protect_door_from_being_opened(name .. "_" .. postfix)
|
||||
end
|
||||
end
|
||||
|
||||
@ -453,6 +452,6 @@ local ProtectorDoors = {
|
||||
for _, name in ipairs(ProtectorDoors) do
|
||||
for _, postfix in ipairs({"b_1", "b_2", "t_1", "t_2"}) do
|
||||
techage.register_simple_nodes({name .. "_" .. postfix}, true)
|
||||
flylib.protect_door_from_being_opened(name .. "_" .. postfix)
|
||||
fly.protect_door_from_being_opened(name .. "_" .. postfix)
|
||||
end
|
||||
end
|
||||
|
@ -19,8 +19,8 @@ local S2P = minetest.string_to_pos
|
||||
local S = techage.S
|
||||
|
||||
local MP = minetest.get_modpath("techage")
|
||||
local fly = dofile(MP .. "/basis/fly_lib.lua")
|
||||
local mark = dofile(MP .. "/basis/mark_lib.lua")
|
||||
local fly = techage.flylib
|
||||
|
||||
local MAX_DIST = 500
|
||||
local MAX_BLOCKS = 16
|
||||
|
@ -19,8 +19,8 @@ local S2P = minetest.string_to_pos
|
||||
local S = techage.S
|
||||
|
||||
local MP = minetest.get_modpath("techage")
|
||||
local fly = dofile(MP .. "/basis/fly_lib.lua")
|
||||
local mark = dofile(MP .. "/basis/mark_lib.lua")
|
||||
local fly = techage.flylib
|
||||
|
||||
local MAX_DIST = 200
|
||||
local MAX_BLOCKS = 16
|
||||
@ -40,7 +40,7 @@ local WRENCH_MENU = {
|
||||
label = S("Handover to B"),
|
||||
tooltip = S("Number of the next movecontroller"),
|
||||
default = "",
|
||||
check = techage.check_numbers,
|
||||
check = techage.check_number,
|
||||
},
|
||||
{
|
||||
type = "number",
|
||||
@ -48,7 +48,7 @@ local WRENCH_MENU = {
|
||||
label = S("Handover to A"),
|
||||
tooltip = S("Number of the previous movecontroller"),
|
||||
default = "",
|
||||
check = techage.check_numbers,
|
||||
check = techage.check_number,
|
||||
},
|
||||
{
|
||||
type = "float",
|
||||
@ -131,6 +131,7 @@ minetest.register_node("techage:ta4_movecontroller", {
|
||||
nvm.lpos2 = {}
|
||||
nvm.moveBA = false
|
||||
nvm.running = nil
|
||||
nvm.lastpos = nil
|
||||
meta:set_string("status", S("Recording..."))
|
||||
local name = player:get_player_name()
|
||||
minetest.chat_send_player(name, S("Click on all blocks that shall be moved"))
|
||||
@ -144,6 +145,7 @@ minetest.register_node("techage:ta4_movecontroller", {
|
||||
end
|
||||
local text = #pos_list.." "..S("block positions are stored.")
|
||||
nvm.running = nil
|
||||
nvm.lastpos = nil
|
||||
meta:set_string("status", text)
|
||||
nvm.lpos1 = pos_list
|
||||
mark.unmark_all(name)
|
||||
@ -161,11 +163,10 @@ minetest.register_node("techage:ta4_movecontroller", {
|
||||
mark.stop(name)
|
||||
nvm.moveBA = false
|
||||
nvm.running = nil
|
||||
nvm.lastpos = nil
|
||||
elseif fields.moveAB then
|
||||
meta:set_string("status", "")
|
||||
if fly.move_to_other_pos(pos, false) then
|
||||
nvm.moveBA = true
|
||||
nvm.running = true
|
||||
meta:set_string("formspec", formspec(nvm, meta))
|
||||
local name = player:get_player_name()
|
||||
mark.stop(name)
|
||||
@ -174,8 +175,6 @@ minetest.register_node("techage:ta4_movecontroller", {
|
||||
elseif fields.moveBA then
|
||||
meta:set_string("status", "")
|
||||
if fly.move_to_other_pos(pos, true) then
|
||||
nvm.moveBA = false
|
||||
nvm.running = true
|
||||
meta:set_string("formspec", formspec(nvm, meta))
|
||||
local name = player:get_player_name()
|
||||
mark.stop(name)
|
||||
@ -187,11 +186,9 @@ minetest.register_node("techage:ta4_movecontroller", {
|
||||
end
|
||||
local line = fly.to_vector(meta:get_string("path"), MAX_DIST)
|
||||
if line then
|
||||
nvm.running = true
|
||||
fly.move_to(pos, line)
|
||||
end
|
||||
elseif fields.reset then
|
||||
nvm.running = true
|
||||
fly.reset_move(pos)
|
||||
end
|
||||
end,
|
||||
@ -230,28 +227,18 @@ techage.register_node({"techage:ta4_movecontroller"}, {
|
||||
elseif topic == "state" then
|
||||
return nvm.running and "running" or "stopped"
|
||||
elseif not move_xyz and topic == "a2b" then
|
||||
nvm.moveBA = true
|
||||
nvm.running = true
|
||||
return fly.move_to_other_pos(pos, false)
|
||||
elseif not move_xyz and topic == "b2a" then
|
||||
nvm.moveBA = false
|
||||
nvm.running = true
|
||||
return fly.move_to_other_pos(pos, true)
|
||||
elseif not move_xyz and topic == "move" then
|
||||
nvm.moveBA = nvm.moveBA == false
|
||||
nvm.running = true
|
||||
return fly.move_to_other_pos(pos, nvm.moveBA == false)
|
||||
elseif move_xyz and topic == "move2" then
|
||||
local line = fly.to_vector(payload, MAX_DIST)
|
||||
if line then
|
||||
nvm.running = true
|
||||
nvm.controller_mode = true
|
||||
return fly.move_to(pos, line)
|
||||
end
|
||||
return false
|
||||
elseif topic == "reset" then
|
||||
nvm.running = true
|
||||
nvm.controller_mode = true
|
||||
return fly.reset_move(pos)
|
||||
end
|
||||
return false
|
||||
@ -262,16 +249,10 @@ techage.register_node({"techage:ta4_movecontroller"}, {
|
||||
--print("on_beduino_receive_cmnd", P2S(pos), move_xyz, topic, payload[1])
|
||||
if not move_xyz and topic == 11 then
|
||||
if payload[1] == 1 then
|
||||
nvm.moveBA = true
|
||||
nvm.running = true
|
||||
return fly.move_to_other_pos(pos, false) and 0 or 3
|
||||
elseif payload[1] == 2 then
|
||||
nvm.moveBA = false
|
||||
nvm.running = true
|
||||
return fly.move_to_other_pos(pos, true) and 0 or 3
|
||||
elseif payload[1] == 3 then
|
||||
nvm.moveBA = nvm.moveBA == false
|
||||
nvm.running = true
|
||||
return fly.move_to_other_pos(pos, nvm.moveBA == false) and 0 or 3
|
||||
end
|
||||
elseif move_xyz and topic == 18 then -- move xyz
|
||||
@ -280,12 +261,8 @@ techage.register_node({"techage:ta4_movecontroller"}, {
|
||||
y = techage.in_range(techage.beduino_signed_var(payload[2]), -100, 100),
|
||||
z = techage.in_range(techage.beduino_signed_var(payload[3]), -100, 100),
|
||||
}
|
||||
nvm.running = true
|
||||
nvm.controller_mode = true
|
||||
return fly.move_to(pos, line) and 0 or 3
|
||||
elseif move_xyz and topic == 19 then -- reset
|
||||
nvm.running = true
|
||||
nvm.controller_mode = true
|
||||
return fly.reset_move(pos) and 0 or 3
|
||||
else
|
||||
return 2
|
||||
@ -298,6 +275,10 @@ techage.register_node({"techage:ta4_movecontroller"}, {
|
||||
end
|
||||
return 2, ""
|
||||
end,
|
||||
on_node_load = function(pos, node)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.running = false
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
|
@ -19,8 +19,8 @@ local S2P = minetest.string_to_pos
|
||||
local S = techage.S
|
||||
|
||||
local MP = minetest.get_modpath("techage")
|
||||
local fly = dofile(MP .. "/basis/fly_lib.lua")
|
||||
local mark = dofile(MP .. "/basis/mark_lib.lua")
|
||||
local fly = techage.flylib
|
||||
|
||||
local MAX_BLOCKS = 16
|
||||
|
||||
|
@ -229,7 +229,7 @@ local function build_crane_up(pos, owner, height, width)
|
||||
", "..S("Crane size")..": "..height..","..width)
|
||||
meta:set_string("formspec", formspec(height, width))
|
||||
else
|
||||
chat(owner, S("Area is protected or too less space for the crane!"))
|
||||
chat(owner, S("Area is protected or not enough space for the crane!"))
|
||||
end
|
||||
end
|
||||
else
|
||||
|
16
towercrane/locale/template.txt
Normal file
16
towercrane/locale/template.txt
Normal file
@ -0,0 +1,16 @@
|
||||
# textdomain: towercrane
|
||||
Area is protected.=
|
||||
Tower Crane Mast Ctrl On=
|
||||
Switch crane on/off=
|
||||
Tower Crane Mast Ctrl Off=
|
||||
Construction area size=
|
||||
Build=
|
||||
Owner=
|
||||
Crane size=
|
||||
Area is protected or too less space for the crane!=
|
||||
Invalid input!=
|
||||
Tower Crane Base=
|
||||
Tower Crane Balance=
|
||||
Tower Crane Mast=
|
||||
Tower Crane Arm=
|
||||
Tower Crane Arm2=
|
16
towercrane/locale/towercrane.eo.tr
Normal file
16
towercrane/locale/towercrane.eo.tr
Normal file
@ -0,0 +1,16 @@
|
||||
# textdomain: towercrane
|
||||
Area is protected.=Areo estas protektita.
|
||||
Tower Crane Mast Ctrl On=Turgruomasta Kontrolo Enŝaltita
|
||||
Switch crane on/off=Ŝaltu/malŝaltu gruon
|
||||
Tower Crane Mast Ctrl Off=Turgruomasta Kontrolo Malŝaltita
|
||||
Construction area size=Konstrua area grandeco
|
||||
Build=Konstruita
|
||||
Owner=Posedanto
|
||||
Crane size=Gruo grandeco
|
||||
Area is protected or not enough space for the crane!=Areo estas protektita aŭ ne sufice da spaco por la gruo!
|
||||
Invalid input!=Nevalida enigo!
|
||||
Tower Crane Base=Bazo de Turgruo
|
||||
Tower Crane Balance=Ekvilibro de Turgruo
|
||||
Tower Crane Mast=Masto de Turgruo
|
||||
Tower Crane Arm=Brako de Turgruo
|
||||
Tower Crane Arm2=Brako2 de Turgruo
|
@ -249,7 +249,7 @@ function Tube:determine_tube_dirs(pos, preferred_pos, fdir)
|
||||
if friendly then
|
||||
local v = vector.direction(pos, preferred_pos)
|
||||
local dir1 = self:vector_to_dir(v)
|
||||
local dir2 = Turn180Deg[fdir]
|
||||
local dir2 = fdir < 5 and Turn180Deg[fdir] or fdir
|
||||
return dir1, dir2, 1
|
||||
end
|
||||
end
|
||||
|
@ -1,7 +1,7 @@
|
||||
# textdomain: tubelib2
|
||||
Not connected!=Nicht verbunden!
|
||||
Paired with @1=Gepaart mit @1
|
||||
Connected to @1=erbunden mit @1
|
||||
Connected to @1=Verbunden mit @1
|
||||
Maximum length reached!=Maximale Länge erreicht!
|
||||
Pairing is missing=Das Pairing fehlt
|
||||
Connection to a tube is missing!=Eine Verbindung zu einer Röhre fehlt!
|
||||
|
8
tubelib2/locale/tubelib2.zh_CN.tr
Normal file
8
tubelib2/locale/tubelib2.zh_CN.tr
Normal file
@ -0,0 +1,8 @@
|
||||
# textdomain: tubelib2
|
||||
Not connected!=未连接!
|
||||
Paired with @1=与@1配对
|
||||
Connected to @1=已连接到 @1
|
||||
Maximum length reached!=已达到最大长度!
|
||||
Pairing is missing=配对缺失
|
||||
Connection to a tube is missing!=管道连接缺失!
|
||||
Pairing is missing (@1)=配对缺失 (@1)
|
8
tubelib2/locale/tubelib2.zh_TW.tr
Normal file
8
tubelib2/locale/tubelib2.zh_TW.tr
Normal file
@ -0,0 +1,8 @@
|
||||
# textdomain: tubelib2
|
||||
Not connected!=未連接!
|
||||
Paired with @1=與@1配對
|
||||
Connected to @1=已連接到 @1
|
||||
Maximum length reached!=已達到最大長度!
|
||||
Pairing is missing=配對缺失
|
||||
Connection to a tube is missing!=管道連接缺失!
|
||||
Pairing is missing (@1)=配對缺失 (@1)
|
@ -2,48 +2,59 @@ local S = minetest.get_translator("unified_inventory")
|
||||
local F = minetest.formspec_escape
|
||||
local ui = unified_inventory
|
||||
|
||||
local function is_recipe_craftable(recipe)
|
||||
-- Ensure the ingedients exist
|
||||
for _, itemname in pairs(recipe.items) do
|
||||
local groups = string.find(itemname, "group:")
|
||||
if groups then
|
||||
if not ui.get_group_item(string.sub(groups, 8)).item then
|
||||
return false
|
||||
end
|
||||
else
|
||||
-- Possibly an item
|
||||
if not minetest.registered_items[itemname]
|
||||
or minetest.get_item_group(itemname, "not_in_craft_guide") ~= 0 then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Create detached creative inventory after loading all mods
|
||||
minetest.after(0.01, function()
|
||||
local rev_aliases = {}
|
||||
for source, target in pairs(minetest.registered_aliases) do
|
||||
if not rev_aliases[target] then rev_aliases[target] = {} end
|
||||
table.insert(rev_aliases[target], source)
|
||||
for original, newname in pairs(minetest.registered_aliases) do
|
||||
if not rev_aliases[newname] then
|
||||
rev_aliases[newname] = {}
|
||||
end
|
||||
table.insert(rev_aliases[newname], original)
|
||||
end
|
||||
|
||||
-- Filtered item list
|
||||
ui.items_list = {}
|
||||
for name, def in pairs(minetest.registered_items) do
|
||||
if (not def.groups.not_in_creative_inventory or
|
||||
def.groups.not_in_creative_inventory == 0) and
|
||||
def.description and def.description ~= "" then
|
||||
if ui.is_itemdef_listable(def) then
|
||||
table.insert(ui.items_list, name)
|
||||
|
||||
-- Alias processing: Find recipes that belong to the current item name
|
||||
local all_names = rev_aliases[name] or {}
|
||||
table.insert(all_names, name)
|
||||
for _, player_name in ipairs(all_names) do
|
||||
local recipes = minetest.get_all_craft_recipes(player_name)
|
||||
if recipes then
|
||||
for _, recipe in ipairs(recipes) do
|
||||
|
||||
local unknowns
|
||||
|
||||
for _,chk in pairs(recipe.items) do
|
||||
local groupchk = string.find(chk, "group:")
|
||||
if (not groupchk and not minetest.registered_items[chk])
|
||||
or (groupchk and not ui.get_group_item(string.gsub(chk, "group:", "")).item)
|
||||
or minetest.get_item_group(chk, "not_in_craft_guide") ~= 0 then
|
||||
unknowns = true
|
||||
end
|
||||
end
|
||||
|
||||
if not unknowns then
|
||||
for _, itemname in ipairs(all_names) do
|
||||
local recipes = minetest.get_all_craft_recipes(itemname)
|
||||
for _, recipe in ipairs(recipes or {}) do
|
||||
if is_recipe_craftable(recipe) then
|
||||
ui.register_craft(recipe)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(ui.items_list)
|
||||
ui.items_list_size = #ui.items_list
|
||||
print("Unified Inventory. Inventory size: "..ui.items_list_size)
|
||||
|
||||
-- Analyse dropped items -> custom "digging" recipes
|
||||
for _, name in ipairs(ui.items_list) do
|
||||
local def = minetest.registered_items[name]
|
||||
-- Simple drops
|
||||
@ -201,8 +212,8 @@ minetest.after(0.01, function()
|
||||
end
|
||||
end)
|
||||
|
||||
---------------- Home API ----------------
|
||||
|
||||
-- load_home
|
||||
local function load_home()
|
||||
local input = io.open(ui.home_filename, "r")
|
||||
if not input then
|
||||
@ -219,6 +230,7 @@ local function load_home()
|
||||
end
|
||||
io.close(input)
|
||||
end
|
||||
|
||||
load_home()
|
||||
|
||||
function ui.set_home(player, pos)
|
||||
@ -247,7 +259,8 @@ function ui.go_home(player)
|
||||
return false
|
||||
end
|
||||
|
||||
-- register_craft
|
||||
---------------- Crafting API ----------------
|
||||
|
||||
function ui.register_craft(options)
|
||||
if not options.output then
|
||||
return
|
||||
@ -270,14 +283,12 @@ function ui.register_craft(options)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local craft_type_defaults = {
|
||||
width = 3,
|
||||
height = 3,
|
||||
uses_crafting_grid = false,
|
||||
}
|
||||
|
||||
|
||||
function ui.craft_type_defaults(name, options)
|
||||
if not options.description then
|
||||
options.description = name
|
||||
@ -288,8 +299,7 @@ end
|
||||
|
||||
|
||||
function ui.register_craft_type(name, options)
|
||||
ui.registered_craft_types[name] =
|
||||
ui.craft_type_defaults(name, options)
|
||||
ui.registered_craft_types[name] = ui.craft_type_defaults(name, options)
|
||||
end
|
||||
|
||||
|
||||
@ -346,6 +356,8 @@ ui.register_craft_type("digging_chance", {
|
||||
height = 1,
|
||||
})
|
||||
|
||||
---------------- GUI registrations ----------------
|
||||
|
||||
function ui.register_page(name, def)
|
||||
ui.pages[name] = def
|
||||
end
|
||||
@ -361,6 +373,8 @@ function ui.register_button(name, def)
|
||||
table.insert(ui.buttons, def)
|
||||
end
|
||||
|
||||
---------------- Callback registrations ----------------
|
||||
|
||||
function ui.register_on_initialized(callback)
|
||||
if type(callback) ~= "function" then
|
||||
error(("Initialized callback must be a function, %s given."):format(type(callback)))
|
||||
@ -375,6 +389,8 @@ function ui.register_on_craft_registered(callback)
|
||||
table.insert(ui.craft_registered_callbacks, callback)
|
||||
end
|
||||
|
||||
---------------- List getters ----------------
|
||||
|
||||
function ui.get_recipe_list(output)
|
||||
return ui.crafts_for.recipe[output]
|
||||
end
|
||||
@ -387,11 +403,15 @@ function ui.get_registered_outputs()
|
||||
return outputs
|
||||
end
|
||||
|
||||
---------------- Player utilities ----------------
|
||||
|
||||
function ui.is_creative(playername)
|
||||
return minetest.check_player_privs(playername, {creative=true})
|
||||
or minetest.settings:get_bool("creative_mode")
|
||||
end
|
||||
|
||||
---------------- Formspec helpers ----------------
|
||||
|
||||
function ui.single_slot(xpos, ypos, bright)
|
||||
return string.format("background9[%f,%f;%f,%f;ui_single_slot%s.png;false;16]",
|
||||
xpos, ypos, ui.imgscale, ui.imgscale, (bright and "_bright" or "") )
|
||||
|
@ -96,6 +96,9 @@ function unified_inventory.register_category(category_name, config)
|
||||
end
|
||||
update_category_list()
|
||||
end
|
||||
|
||||
-- TODO: Mark these for removal. They are pretty much useless
|
||||
|
||||
function unified_inventory.set_category_symbol(category_name, symbol)
|
||||
ensure_category_exists(category_name)
|
||||
unified_inventory.registered_categories[category_name].symbol = symbol
|
||||
|
@ -1,7 +1,8 @@
|
||||
unified_inventory API
|
||||
=====================
|
||||
|
||||
This file provides information about the API of unified_inventory.
|
||||
This file provides information about the API of unified_inventory
|
||||
and can be viewed in Markdown readers.
|
||||
|
||||
API revisions within unified_inventory can be checked using:
|
||||
|
||||
@ -163,68 +164,57 @@ Register a non-standard craft recipe:
|
||||
Categories
|
||||
----------
|
||||
|
||||
Register a new category:
|
||||
The config table (second argument) is optional, and all its members are optional
|
||||
See the unified_inventory.set_category_* functions for more details on the members of the config table
|
||||
* `unified_inventory.register_category(name, def)`
|
||||
* Registers a new category
|
||||
* `name` (string): internal category name
|
||||
* `def` (optional, table): also its fields are optional
|
||||
|
||||
unified_inventory.register_category("category_name", {
|
||||
symbol = "mod_name:item_name" or "texture.png",
|
||||
symbol = source,
|
||||
-- ^ Can be in the format "mod_name:item_name" or "texture.png",
|
||||
label = "Human Readable Label",
|
||||
index = 5,
|
||||
-- ^ Categories are sorted by index. Lower numbers appear before higher ones.
|
||||
-- By default, the name is translated to a number: AA -> 0.0101, ZZ -> 0.2626
|
||||
--- Predefined category indices: "all" = -2, "uncategorized" = -1
|
||||
items = {
|
||||
"mod_name:item_name",
|
||||
"another_mod:different_item"
|
||||
}
|
||||
-- ^ List of items within this category
|
||||
})
|
||||
* `unified_inventory.remove_category(name)`
|
||||
* Removes an entire category
|
||||
|
||||
Add / override the symbol for a category:
|
||||
The category does not need to exist first
|
||||
The symbol can be an item name or a texture image
|
||||
If unset this will default to "default:stick"
|
||||
Modifier functions (to be removed)
|
||||
|
||||
unified_inventory.set_category_symbol("category_name", "mod_name:item_name" or "texture.png")
|
||||
* `unified_inventory.set_category_symbol(name, source)`
|
||||
* Changes the symbol of the category. The category does not need to exist yet.
|
||||
* `name` (string): internal category name
|
||||
* `source` (string, optional): `"mod_name:item_name"` or `"texture.png"`.
|
||||
Defaults to `"default:stick"` if not specified.
|
||||
* `unified_inventory.set_category_label(name, label)`
|
||||
* Changes the human readable label of the category.
|
||||
* `name` (string): internal category name
|
||||
* `label` (string): human readable label. Defaults to the category name.
|
||||
* `unified_inventory.set_category_index(name, index)`
|
||||
* Changes the sorting index of the category.
|
||||
* `name` (string): internal category name
|
||||
* `index` (numeric): any real number
|
||||
|
||||
Add / override the human readable label for a category:
|
||||
If unset this will default to the category name
|
||||
Item management
|
||||
|
||||
unified_inventory.set_category_label("category_name", "Human Readable Label")
|
||||
* ` unified_inventory.add_category_item(name, itemname)`
|
||||
* Adds a single item to the category
|
||||
* `itemname` (string): self-explanatory
|
||||
* `unified_inventory.add_category_items(name, { itemname1, itemname2, ... }`
|
||||
* Same as above but with multiple items
|
||||
* `unified_inventory.remove_category_item(name, itemname)`
|
||||
* Removes an item from the category
|
||||
* `unified_inventory.find_category(itemname)`
|
||||
* Looks up the first category containing this item
|
||||
* Returns: category name (string) or nil
|
||||
* `unified_inventory.find_categories(itemname)`
|
||||
* Looks up the item name within all registered categories
|
||||
* Returns: array of category names (table)
|
||||
|
||||
Add / override the sorting index of the category:
|
||||
Must be a number, can also be negative (-5) or fractional (2.345)
|
||||
This determines the position the category appears in the list of categories
|
||||
The "all" meta-category has index -2, the "misc"/"uncategorized" meta-category has index -1, use a negative number smaller than these to make a category appear before these in the list
|
||||
By default categories are sorted alphabetically with an index between 0.0101(AA) and 0.2626(ZZ)
|
||||
|
||||
unified_inventory.set_category_index("category_name", 5)
|
||||
|
||||
Add a single item to a category:
|
||||
|
||||
unified_inventory.add_category_item("category_name", "mod_name:item_name")
|
||||
|
||||
Add multiple items to a category:
|
||||
|
||||
unified_inventory.add_category_items("category_name", {
|
||||
"mod_name:item_name",
|
||||
"another_mod:different_item"
|
||||
})
|
||||
|
||||
Remove an item from a category:
|
||||
|
||||
unified_inventory.remove_category_item("category_name", "mod_name:item_name")
|
||||
|
||||
Remove a category entirely:
|
||||
|
||||
unified_inventory.remove_category("category_name")
|
||||
|
||||
Finding existing items in categories:
|
||||
This will find the first category an item exists in
|
||||
It should be used for checking if an item is catgorised
|
||||
Returns "category_name" or nil
|
||||
|
||||
unified_inventory.find_category("mod_name:item_name")
|
||||
|
||||
|
||||
This will find all the categories an item exists in
|
||||
Returns a number indexed table (list) of category names
|
||||
|
||||
unified_inventory.find_categories("mod_name:item_name")
|
||||
|
@ -52,6 +52,8 @@ unified_inventory = {
|
||||
list_img_offset = 0.13,
|
||||
standard_background = "bgcolor[#0000]background9[0,0;1,1;ui_formbg_9_sliced.png;true;16]",
|
||||
|
||||
hide_disabled_buttons = minetest.settings:get_bool("unified_inventory_hide_disabled_buttons", false),
|
||||
|
||||
version = 4
|
||||
}
|
||||
|
||||
|
@ -52,11 +52,13 @@ local function formspec_tab_buttons(player, formspec, style)
|
||||
|
||||
local filtered_inv_buttons = {}
|
||||
|
||||
for i, def in pairs(ui.buttons) do
|
||||
for _, def in pairs(ui.buttons) do
|
||||
if not (style.is_lite_mode and def.hide_lite) then
|
||||
if def.condition == nil or def.condition(player) or not ui.hide_disabled_buttons then
|
||||
table.insert(filtered_inv_buttons, def)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local needs_scrollbar = #filtered_inv_buttons > style.main_button_cols * style.main_button_rows
|
||||
|
||||
@ -71,13 +73,14 @@ local function formspec_tab_buttons(player, formspec, style)
|
||||
local pos_y = math.floor((i - 1) / style.main_button_cols) * style.btn_spc
|
||||
|
||||
if def.type == "image" then
|
||||
if (def.condition == nil or def.condition(player) == true) then
|
||||
if (def.condition == nil or def.condition(player)) then
|
||||
formspec[n] = string.format("image_button[%g,%g;%g,%g;%s;%s;]",
|
||||
pos_x, pos_y, style.btn_size, style.btn_size,
|
||||
F(def.image),
|
||||
F(def.name))
|
||||
formspec[n+1] = "tooltip["..F(def.name)..";"..(def.tooltip or "").."]"
|
||||
n = n+2
|
||||
|
||||
else
|
||||
formspec[n] = string.format("image[%g,%g;%g,%g;%s^[colorize:#808080:alpha]",
|
||||
pos_x, pos_y, style.btn_size, style.btn_size,
|
||||
@ -88,9 +91,10 @@ local function formspec_tab_buttons(player, formspec, style)
|
||||
end
|
||||
formspec[n] = "scroll_container_end[]"
|
||||
if needs_scrollbar then
|
||||
local total_rows = math.ceil(#filtered_inv_buttons / style.main_button_cols)
|
||||
formspec[n+1] = ("scrollbaroptions[max=%i;arrows=hide]"):format(
|
||||
-- This calculation is not 100% accurate but "good enough"
|
||||
math.ceil((#filtered_inv_buttons - 1) / style.main_button_cols) * style.btn_spc * 5
|
||||
(total_rows - style.main_button_rows) * style.btn_spc * 10
|
||||
)
|
||||
formspec[n+2] = ("scrollbar[%g,%g;0.4,%g;vertical;tabbtnscroll;0]"):format(
|
||||
style.main_button_x + style.main_button_cols * style.btn_spc - 0.1, -- x pos
|
||||
@ -329,7 +333,7 @@ function ui.set_inventory_formspec(player, page)
|
||||
end
|
||||
end
|
||||
|
||||
local function valid_def(def)
|
||||
function ui.is_itemdef_listable(def)
|
||||
return (not def.groups.not_in_creative_inventory
|
||||
or def.groups.not_in_creative_inventory == 0)
|
||||
and def.description
|
||||
@ -342,9 +346,11 @@ function ui.apply_filter(player, filter, search_dir)
|
||||
return false
|
||||
end
|
||||
local player_name = player:get_player_name()
|
||||
|
||||
local lfilter = string.lower(filter)
|
||||
local ffilter
|
||||
if lfilter:sub(1, 6) == "group:" then
|
||||
-- Group filter: all groups of the item must match
|
||||
local groups = lfilter:sub(7):split(",")
|
||||
ffilter = function(name, def)
|
||||
for _, group in ipairs(groups) do
|
||||
@ -356,6 +362,7 @@ function ui.apply_filter(player, filter, search_dir)
|
||||
return true
|
||||
end
|
||||
else
|
||||
-- Name filter: fuzzy match item names and descriptions
|
||||
local player_info = minetest.get_player_information(player_name)
|
||||
local lang = player_info and player_info.lang_code or ""
|
||||
|
||||
@ -368,35 +375,41 @@ function ui.apply_filter(player, filter, search_dir)
|
||||
or llocaldesc and string.find(llocaldesc, lfilter, 1, true)
|
||||
end
|
||||
end
|
||||
ui.filtered_items_list[player_name]={}
|
||||
|
||||
local is_itemdef_listable = ui.is_itemdef_listable
|
||||
local filtered_items = {}
|
||||
|
||||
local category = ui.current_category[player_name] or 'all'
|
||||
if category == 'all' then
|
||||
for name, def in pairs(minetest.registered_items) do
|
||||
if valid_def(def)
|
||||
if is_itemdef_listable(def)
|
||||
and ffilter(name, def) then
|
||||
table.insert(ui.filtered_items_list[player_name], name)
|
||||
table.insert(filtered_items, name)
|
||||
end
|
||||
end
|
||||
elseif category == 'uncategorized' then
|
||||
for name, def in pairs(minetest.registered_items) do
|
||||
if (not ui.find_category(name))
|
||||
and valid_def(def)
|
||||
if is_itemdef_listable(def)
|
||||
and not ui.find_category(name)
|
||||
and ffilter(name, def) then
|
||||
table.insert(ui.filtered_items_list[player_name], name)
|
||||
table.insert(filtered_items, name)
|
||||
end
|
||||
end
|
||||
else
|
||||
for name,exists in pairs(ui.registered_category_items[category]) do
|
||||
-- Any other category is selected
|
||||
for name, exists in pairs(ui.registered_category_items[category]) do
|
||||
local def = minetest.registered_items[name]
|
||||
if exists and def
|
||||
and valid_def(def)
|
||||
and is_itemdef_listable(def)
|
||||
and ffilter(name, def) then
|
||||
table.insert(ui.filtered_items_list[player_name], name)
|
||||
table.insert(filtered_items, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(ui.filtered_items_list[player_name])
|
||||
ui.filtered_items_list_size[player_name] = #ui.filtered_items_list[player_name]
|
||||
table.sort(filtered_items)
|
||||
|
||||
ui.filtered_items_list_size[player_name] = #filtered_items
|
||||
ui.filtered_items_list[player_name] = filtered_items
|
||||
ui.current_index[player_name] = 1
|
||||
ui.activefilter[player_name] = filter
|
||||
ui.active_search_direction[player_name] = search_dir
|
||||
|
@ -1,6 +1,6 @@
|
||||
name = unified_inventory
|
||||
|
||||
optional_depends = default, creative, sfinv, datastorage, farming
|
||||
optional_depends = default, creative, sfinv, datastorage
|
||||
description = """
|
||||
Unified Inventory replaces the default survival and creative inventory.
|
||||
It adds a nicer interface and a number of features, such as a crafting guide.
|
||||
|
@ -10,5 +10,8 @@ unified_inventory_bags (Enable bags) bool true
|
||||
#and the give privilege.
|
||||
unified_inventory_trash (Enable trash) bool true
|
||||
|
||||
#If enabled, disabled buttons will be hidden instead of grayed out.
|
||||
unified_inventory_hide_disabled_buttons (Hide disabled buttons) bool false
|
||||
|
||||
|
||||
unified_inventory_automatic_categorization (Items automatically added to categories) bool true
|
Loading…
Reference in New Issue
Block a user