built on 30/10/2021 16:52:44
@ -24,7 +24,7 @@ lcdlib = {}
|
||||
lcdlib.registered_fonts = {}
|
||||
|
||||
-- Version for compatibility checks
|
||||
lcdlib.version = 1.0
|
||||
lcdlib.version = 1.01
|
||||
|
||||
-- Local functions
|
||||
------------------
|
||||
@ -180,7 +180,7 @@ end
|
||||
-- @return Texture string
|
||||
|
||||
function lcdlib.make_multiline_texture(font_name, text, width, height,
|
||||
maxlines, valign, color)
|
||||
maxlines, valign, color, y_offs)
|
||||
local texture = ""
|
||||
local lines = {}
|
||||
local textheight = 0
|
||||
@ -199,7 +199,7 @@ function lcdlib.make_multiline_texture(font_name, text, width, height,
|
||||
|
||||
if #lines then
|
||||
if valign == "top" then
|
||||
y = 0
|
||||
y = y_offs or 0
|
||||
elseif valign == "bottom" then
|
||||
y = height - textheight
|
||||
else
|
||||
|
@ -152,3 +152,4 @@ History
|
||||
2021-04-10 V2.00 Complete revision to make carts robust against server load/lag,
|
||||
Speed limit signs and cart terminal added
|
||||
2021-09-02 V2.01 Chat command /stopcart added
|
||||
2021-10-18 V2.02 Cart reproduction bug fixed
|
||||
|
@ -257,9 +257,6 @@ function minecart.add_nodecart(pos, node_name, param2, cargo, owner, userID)
|
||||
pos2 = minetest.find_node_near(pos, 1, minecart.lRails)
|
||||
if not pos2 or not minecart.is_rail(pos2) then
|
||||
pos2 = minetest.find_node_near(pos, 2, minecart.lRails)
|
||||
if not pos2 or not minecart.is_rail(pos2) then
|
||||
pos2 = minetest.find_node_near(pos, 2, {"air"})
|
||||
end
|
||||
end
|
||||
else
|
||||
pos2 = vector.new(pos)
|
||||
@ -282,8 +279,6 @@ function minecart.add_nodecart(pos, node_name, param2, cargo, owner, userID)
|
||||
ndef.after_place_node(pos2)
|
||||
end
|
||||
return pos2
|
||||
else
|
||||
minetest.add_item(pos, ItemStack({name = node_name}))
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -363,9 +358,13 @@ function minecart.entity_to_node(pos, entity)
|
||||
local dir = minetest.yaw_to_dir(rot.y)
|
||||
local facedir = minetest.dir_to_facedir(dir)
|
||||
minecart.stop_recording(entity, pos)
|
||||
entity.object:remove()
|
||||
local pos2 = minecart.add_nodecart(pos, entity.node_name, facedir, entity.cargo, entity.owner, entity.userID)
|
||||
minecart.stop_monitoring(entity.owner, entity.userID, pos2)
|
||||
if pos2 then
|
||||
minecart.stop_monitoring(entity.owner, entity.userID, pos2)
|
||||
entity.object:remove()
|
||||
else
|
||||
minecart.start_entitycart(entity, pos, facedir)
|
||||
end
|
||||
end
|
||||
|
||||
function minecart.add_node_to_player_inventory(pos, player, node_name)
|
||||
@ -388,9 +387,10 @@ function minecart.remove_entity(self, pos, player)
|
||||
minetest.sound_stop(self.sound_handle)
|
||||
self.sound_handle = nil
|
||||
end
|
||||
minecart.add_node_to_player_inventory(pos, player, self.node_name or "minecart:cart")
|
||||
if player then
|
||||
minecart.add_node_to_player_inventory(pos, player, self.node_name or "minecart:cart")
|
||||
end
|
||||
minecart.stop_monitoring(self.owner, self.userID, pos)
|
||||
minecart.stop_recording(self, pos)
|
||||
minecart.monitoring_remove_cart(self.owner, self.userID)
|
||||
self.object:remove()
|
||||
end
|
||||
|
@ -159,13 +159,16 @@ minetest.register_craft({
|
||||
})
|
||||
|
||||
minetest.register_lbm({
|
||||
label = "Delete waiting times",
|
||||
name = "minecart:del_time",
|
||||
label = "Delete metadata",
|
||||
name = "minecart:metadata",
|
||||
nodenames = {"minecart:buffer"},
|
||||
run_at_every_load = false,
|
||||
run_at_every_load = true,
|
||||
action = function(pos, node)
|
||||
-- delete old data
|
||||
minecart.get_route(pos)
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
-- delete old metadata around the buffer (bugfix)
|
||||
local pos1 = {x = pos.x - 2, y = pos.y - 2, z = pos.z - 2}
|
||||
local pos2 = {x = pos.x + 2, y = pos.y + 2, z = pos.z + 2}
|
||||
for _, pos in ipairs(minetest.find_nodes_with_meta(pos1, pos2)) do
|
||||
minecart.del_metadata(pos)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
@ -186,7 +186,7 @@ local function play_sound(self)
|
||||
if self.object then
|
||||
self.sound_handle = minetest.sound_play(
|
||||
"carts_cart_moving", {
|
||||
object = self.object,
|
||||
pos = self.object:get_pos(),
|
||||
gain = (self.curr_speed or 0) / MAX_SPEED,
|
||||
})
|
||||
end
|
||||
|
@ -13,7 +13,7 @@
|
||||
minecart = {}
|
||||
|
||||
-- Version for compatibility checks, see readme.md/history
|
||||
minecart.version = 2.01
|
||||
minecart.version = 2.02
|
||||
|
||||
minecart.hopper_enabled = minetest.settings:get_bool("minecart_hopper_enabled") ~= false
|
||||
minecart.teleport_enabled = minetest.settings:get_bool("minecart_teleport_enabled") == true
|
||||
@ -35,7 +35,7 @@ dofile(MP .. "/api.lua")
|
||||
dofile(MP .. "/minecart.lua")
|
||||
dofile(MP .. "/buffer.lua")
|
||||
dofile(MP .. "/protection.lua")
|
||||
--dofile(MP .. "/tool.lua") # for debugging only
|
||||
--dofile(MP .. "/tool.lua") -- for debugging only
|
||||
dofile(MP .. "/signs.lua")
|
||||
dofile(MP .. "/terminal.lua")
|
||||
dofile(MP .. "/pusher.lua")
|
||||
|
@ -68,9 +68,6 @@ local function get_checkpoint(cart)
|
||||
cp = cart.checkpoints[cart.idx]
|
||||
end
|
||||
local pos = H2P(cp[1])
|
||||
-- if M(pos):contains("waypoints") then
|
||||
-- print("get_checkpoint", P2S(H2P(cp[1])), P2S(H2P(cp[2])))
|
||||
-- end
|
||||
return cp, cart.idx == #cart.checkpoints
|
||||
end
|
||||
|
||||
@ -81,13 +78,15 @@ local function get_cart_state_and_loc(name, userID, query_pos)
|
||||
if tCartsOnRail[name] and tCartsOnRail[name][userID] then
|
||||
local cart = tCartsOnRail[name][userID]
|
||||
local pos = cart.last_pos or cart.pos
|
||||
local loc = minecart.get_buffer_name(cart.pos) or
|
||||
math.floor(vector.distance(pos, query_pos))
|
||||
if cart.objID == 0 then
|
||||
return "stopped", minecart.get_buffer_name(cart.pos) or
|
||||
math.floor(vector.distance(pos, query_pos)), cart.node_name
|
||||
else
|
||||
return "running", math.floor(vector.distance(pos, query_pos)), cart.node_name
|
||||
if pos then
|
||||
local loc = minecart.get_buffer_name(cart.pos) or
|
||||
math.floor(vector.distance(pos, query_pos))
|
||||
if cart.objID == 0 then
|
||||
return "stopped", minecart.get_buffer_name(cart.pos) or
|
||||
math.floor(vector.distance(pos, query_pos)), cart.node_name
|
||||
else
|
||||
return "running", math.floor(vector.distance(pos, query_pos)), cart.node_name
|
||||
end
|
||||
end
|
||||
end
|
||||
return "unknown", 0, "unknown"
|
||||
@ -103,21 +102,41 @@ local function get_cart_info(owner, userID, query_pos)
|
||||
end
|
||||
end
|
||||
|
||||
local function logging(cart, err)
|
||||
local s = string.format("[Minecart] Cart %s/%u %s!", cart.owner, cart.userID, err)
|
||||
minetest.log("warning", s)
|
||||
end
|
||||
|
||||
-- check cart data
|
||||
local function valid_cart(cart)
|
||||
if cart.objID == nil or cart.objID == 0 then
|
||||
return false
|
||||
end
|
||||
if tCartsOnRail[cart.owner] and tCartsOnRail[cart.owner][cart.userID] then
|
||||
return true
|
||||
end
|
||||
logging(cart, "with invalid data")
|
||||
local entity = minetest.luaentities[cart.objID]
|
||||
if entity then
|
||||
entity.object:remove()
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function monitoring(cycle)
|
||||
local cart = pop(cycle)
|
||||
|
||||
-- All running cars
|
||||
while cart do
|
||||
-- All running cars
|
||||
if cart.objID and cart.objID ~= 0 then
|
||||
if valid_cart(cart) then
|
||||
cart.idx = cart.idx + 1
|
||||
local entity = minetest.luaentities[cart.objID]
|
||||
if entity then -- cart entity running
|
||||
local pos = entity.object:get_pos()
|
||||
if pos then
|
||||
cart.last_pos = vector.round(pos)
|
||||
--print("entity card " .. cart.userID .. " at " .. P2S(cart.last_pos))
|
||||
else
|
||||
minetest.log("warning", "[Minecart] entity card without pos!")
|
||||
logging(cart, "without pos")
|
||||
end
|
||||
push(cycle, cart)
|
||||
elseif cart.checkpoints then
|
||||
@ -130,16 +149,15 @@ local function monitoring(cycle)
|
||||
end
|
||||
push(cycle, cart)
|
||||
else
|
||||
minetest.log("warning", "[Minecart] zombie got lost")
|
||||
logging(cart, "as zombie got lost")
|
||||
end
|
||||
else
|
||||
local pos = cart.last_pos or cart.pos
|
||||
pos = minecart.add_nodecart(pos, cart.node_name, 0, cart.cargo, cart.owner, cart.userID)
|
||||
cart.objID = 0
|
||||
cart.pos = pos
|
||||
--print("cart to node", cycle, cart.userID, P2S(pos))
|
||||
minecart.stop_monitoring(cart.owner, cart.userID, pos)
|
||||
logging(cart, "stopped at " .. (P2S(pos) or "unknown"))
|
||||
end
|
||||
elseif cart and not cart.objID and tCartsOnRail[cart.owner] then
|
||||
elseif not cart.objID and tCartsOnRail[cart.owner] then
|
||||
-- Delete carts marked as "to be deleted"
|
||||
tCartsOnRail[cart.owner][cart.userID] = nil
|
||||
end
|
||||
@ -184,6 +202,7 @@ function minecart.stop_monitoring(owner, userID, pos)
|
||||
--print("stop_monitoring", owner, userID)
|
||||
if tCartsOnRail[owner] and tCartsOnRail[owner][userID] then
|
||||
tCartsOnRail[owner][userID].pos = pos
|
||||
-- Mark as "stopped"
|
||||
tCartsOnRail[owner][userID].objID = 0
|
||||
minecart.store_carts()
|
||||
end
|
||||
@ -192,14 +211,20 @@ end
|
||||
function minecart.monitoring_remove_cart(owner, userID)
|
||||
--print("monitoring_remove_cart", owner, userID)
|
||||
if tCartsOnRail[owner] and tCartsOnRail[owner][userID] then
|
||||
tCartsOnRail[owner][userID].objID = nil
|
||||
tCartsOnRail[owner][userID] = nil
|
||||
-- Cart stopped?
|
||||
if tCartsOnRail[owner][userID].objID == 0 then
|
||||
-- Can directly be deleted
|
||||
tCartsOnRail[owner][userID] = nil
|
||||
else -- Cart running
|
||||
-- Mark as "to be deleted" by monitoring
|
||||
tCartsOnRail[owner][userID].objID = nil
|
||||
end
|
||||
minecart.store_carts()
|
||||
end
|
||||
end
|
||||
|
||||
function minecart.monitoring_valid_cart(owner, userID, pos, node_name)
|
||||
if tCartsOnRail[owner] and tCartsOnRail[owner][userID] then
|
||||
if tCartsOnRail[owner] and tCartsOnRail[owner][userID] and tCartsOnRail[owner][userID].pos then
|
||||
return vector.equals(tCartsOnRail[owner][userID].pos, pos) and
|
||||
tCartsOnRail[owner][userID].node_name == node_name
|
||||
end
|
||||
@ -245,29 +270,38 @@ minetest.register_chatcommand("mycart", {
|
||||
|
||||
minetest.register_chatcommand("stopcart", {
|
||||
params = "<cart-num>",
|
||||
description = S("Stop amd return a missing/running cart."),
|
||||
description = S("Stop and return/drop a missing/running cart."),
|
||||
func = function(owner, param)
|
||||
local userID = tonumber(param)
|
||||
local player_pos = minetest.get_player_by_name(owner):get_pos()
|
||||
if userID then
|
||||
local data = minecart.get_cart_monitoring_data(owner, userID)
|
||||
if data then
|
||||
if data.objID and data.objID ~= 0 then
|
||||
local entity = minetest.luaentities[data.objID]
|
||||
if entity then -- cart entity running
|
||||
minecart.entity_to_node(player_pos, entity)
|
||||
minecart.monitoring_remove_cart(owner, userID)
|
||||
if data and data.objID then
|
||||
local entity = minetest.luaentities[data.objID]
|
||||
--print("stopcart", userID, data.pos, data.objID, entity)
|
||||
if data.objID == 0 then
|
||||
-- Cart as node
|
||||
if data.pos then
|
||||
local meta = M(data.pos)
|
||||
if owner == meta:get_string("owner") and userID == meta:get_int("userID") then
|
||||
minecart.remove_nodecart(data.pos)
|
||||
end
|
||||
end
|
||||
elseif entity then
|
||||
-- Cart as entity
|
||||
minecart.remove_entity(entity, data.pos)
|
||||
else
|
||||
local pos = data.last_pos or data.pos
|
||||
local cargo, _, _ = minecart.remove_nodecart(pos)
|
||||
minecart.add_nodecart(player_pos, data.node_name, 0, cargo, owner, userID)
|
||||
minecart.monitoring_remove_cart(owner, userID)
|
||||
-- Cart as zombie/invalid/corrupted
|
||||
-- nothing to do
|
||||
end
|
||||
return true, S("Cart") .. " " .. userID .. " " .. S("stopped")
|
||||
minetest.add_item(player_pos, ItemStack({name = data.node_name}))
|
||||
minecart.monitoring_remove_cart(owner, userID)
|
||||
return true, S("Cart") .. " " .. userID .. " " .. S("dropped")
|
||||
else
|
||||
return false, S("Cart") .. " " .. userID .. " " .. S("is not existing!")
|
||||
end
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
})
|
||||
|
@ -585,6 +585,9 @@ end
|
||||
-- minecart.get_next_buffer(pos, facedir)
|
||||
minecart.get_next_buffer = get_next_buffer
|
||||
|
||||
-- minecart.del_metadata(pos)
|
||||
minecart.del_metadata = del_metadata
|
||||
|
||||
--minetest.register_lbm({
|
||||
-- label = "Delete waypoints",
|
||||
-- name = "minecart:del_meta",
|
||||
|
@ -50,30 +50,15 @@ minetest.register_on_mods_loaded(function()
|
||||
else
|
||||
local t = minetest.deserialize(storage:get_string("CartsOnRail")) or {}
|
||||
for owner, carts in pairs(t) do
|
||||
minecart.CartsOnRail[owner] = {}
|
||||
minecart.CartsOnRail[owner] = minecart.CartsOnRail[owner] or {}
|
||||
for userID, cart in pairs(carts) do
|
||||
print("reload cart", owner, userID, cart.objID)
|
||||
minecart.CartsOnRail[owner][userID] = cart
|
||||
-- mark all entity carts as zombified
|
||||
if cart.objID and cart.objID ~= 0 then
|
||||
cart.objID = -1
|
||||
minecart.push(1, cart)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.after(10, function()
|
||||
for owner, carts in pairs(minecart.CartsOnRail) do
|
||||
for userID, cart in pairs(carts) do
|
||||
-- Remove node carts that are not available anymore
|
||||
if cart.pos and (cart.objID == 0 or not cart.objID) then
|
||||
local node = minecart.get_node_lvm(cart.pos)
|
||||
if not minecart.tNodeNames[node.name] then
|
||||
-- Mark as "to be deleted"
|
||||
print("Node cart deleted", owner, userID)
|
||||
minecart.CartsOnRail[owner][userID] = nil
|
||||
if cart.objID then
|
||||
minecart.CartsOnRail[owner][userID] = cart
|
||||
-- mark all entity carts as zombified
|
||||
if cart.objID ~= 0 then
|
||||
cart.objID = -1
|
||||
minecart.push(1, cart)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -78,7 +78,8 @@ local function click_left(itemstack, placer, pointed_thing)
|
||||
if pointed_thing.type == "node" then
|
||||
local pos = pointed_thing.under
|
||||
if minecart.is_rail(pos) then
|
||||
test_get_buffer(pos, placer)
|
||||
--test_get_buffer(pos, placer)
|
||||
minecart.delete_waypoint(pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -183,4 +183,5 @@ optional: farming redo, node_io, doc, techage, minecart, xdecor, compost
|
||||
- 2021-04-24 v1.07 * Adapted to minecart v2.0
|
||||
- 2021-05-04 v1.08 * Add print command, improve error msg
|
||||
- 2021-08-22 v1.09 * Add soup commands and signs, add aspen sign
|
||||
- 2021-09-18 v1.10 * Add techage command 'set <num>' to the Bot Control Unit
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
GPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Signgs Changer/Control Unit for Bot Control
|
||||
Signs Changer/Control Unit for Bot Control
|
||||
|
||||
]]--
|
||||
|
||||
|
@ -61,12 +61,29 @@ local function harvesting(base_pos, mem)
|
||||
|
||||
if pos and lib.not_protected(base_pos, pos) then
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
local drop = Flowers[node.name] or is_tree(node)
|
||||
if drop then
|
||||
minetest.remove_node(pos)
|
||||
local leftover = bot_inv_put_item(base_pos, 0, ItemStack(drop))
|
||||
if leftover and leftover:get_count() > 0 then
|
||||
signs_bot.lib.drop_items(mem.robot_pos, leftover)
|
||||
if node.name ~= "default:papyrus" then
|
||||
local drop = Flowers[node.name] or is_tree(node)
|
||||
if drop then
|
||||
minetest.remove_node(pos)
|
||||
local leftover = bot_inv_put_item(base_pos, 0, ItemStack(drop))
|
||||
if leftover and leftover:get_count() > 0 then
|
||||
signs_bot.lib.drop_items(mem.robot_pos, leftover)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- papyrus is a special plant that is collected upwards when cut
|
||||
local count = 0
|
||||
while node.name == "default:papyrus" and lib.not_protected(base_pos, pos) do
|
||||
minetest.remove_node(pos)
|
||||
pos = { x = pos.x, y = pos.y + 1, z = pos.z }
|
||||
count = count + 1
|
||||
node = minetest.get_node(pos)
|
||||
end
|
||||
if count > 0 then
|
||||
local leftover = bot_inv_put_item(base_pos, 0, ItemStack("default:papyrus " .. count))
|
||||
if leftover and leftover:get_count() > 0 then
|
||||
signs_bot.lib.drop_items(mem.robot_pos, leftover)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -76,7 +93,7 @@ signs_bot.register_botcommand("cutting", {
|
||||
mod = "farming",
|
||||
params = "",
|
||||
num_param = 0,
|
||||
description = S("Cutting flowers, leaves and tree blocks\nin front of the robot\non a 3x3 field."),
|
||||
description = S("Cutting flowers, papyrus,\nleaves and tree blocks\nin front of the robot\non a 3x3 field."),
|
||||
cmnd = function(base_pos, mem)
|
||||
if not mem.steps then
|
||||
mem.pos_tbl = signs_bot.lib.gen_position_table(mem.robot_pos, mem.robot_param2, 3, 3, 0)
|
||||
|
@ -551,3 +551,5 @@ techage.add_manual_items({
|
||||
ta4_jetpack.register_forbidden_item("techage:cylinder_large_hydrogen")
|
||||
ta4_jetpack.register_forbidden_item("techage:cylinder_small_hydrogen")
|
||||
ta4_jetpack.register_forbidden_item("techage:hydrogen")
|
||||
ta4_jetpack.register_forbidden_item("digtron:loaded_crate")
|
||||
ta4_jetpack.register_forbidden_item("digtron:loaded_locked_crate")
|
@ -81,6 +81,13 @@ Available worlds will be converted to 'lsqlite3', but there is no way back, so:
|
||||
|
||||
### History
|
||||
|
||||
**2021-10-24 V1.03**
|
||||
- Add TA4 Sequencer for time controlled command sequences
|
||||
- Add TA4 Move Controller for moving blocks
|
||||
- Add techage command counting function to be able to limit the amount of commands/min.
|
||||
- Pull request #67: Add switch mode for 4x Button (by realmicu)
|
||||
- Pull request #69: Add option to keep assignment for TA4 Tank (by Thomas-S)
|
||||
|
||||
**2021-09-18 V1.02**
|
||||
- TA4 Chest: Fix items disappearing (PR #64 by Thomas--S)
|
||||
- Add support for colored cables (PR #63 by Thomas--S)
|
||||
|
@ -152,6 +152,7 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState
|
||||
formspec_func = tNode.formspec,
|
||||
on_state_change = tNode.on_state_change,
|
||||
can_start = tNode.can_start,
|
||||
quick_start = tNode.quick_start,
|
||||
has_power = tNode.has_power or power_used and has_power or nil,
|
||||
start_node = power_used and start_node or nil,
|
||||
stop_node = power_used and stop_node or nil,
|
||||
|
@ -350,11 +350,27 @@ local function search_chest_in_front(pos, node)
|
||||
end
|
||||
if node.name == "techage:ta4_chest" then
|
||||
minetest.after(1, count_number_of_chests, pos1)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.front_chest_pos = pos1
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function get_front_chest_pos(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if nvm.front_chest_pos then
|
||||
return nvm.front_chest_pos
|
||||
end
|
||||
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if search_chest_in_front(pos, node) then
|
||||
return nvm.front_chest_pos
|
||||
end
|
||||
|
||||
return pos
|
||||
end
|
||||
|
||||
local function convert_to_chest_again(pos, node, player)
|
||||
local dir = techage.side_to_outdir("B", node.param2)
|
||||
local pos1 = tubelib2.get_pos(pos, dir)
|
||||
@ -594,6 +610,33 @@ techage.register_node({"techage:ta4_chest"}, {
|
||||
end,
|
||||
})
|
||||
|
||||
techage.register_node({"techage:ta4_chest_dummy"}, {
|
||||
on_pull_item = function(pos, in_dir, num, item_name)
|
||||
local fc_pos = get_front_chest_pos(pos)
|
||||
local res = tube_take_from_chest(fc_pos, item_name, num)
|
||||
if techage.is_activeformspec(fc_pos) then
|
||||
M(fc_pos):set_string("formspec", formspec(fc_pos))
|
||||
end
|
||||
return res
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local fc_pos = get_front_chest_pos(pos)
|
||||
local res = tube_add_to_chest(fc_pos, stack)
|
||||
if techage.is_activeformspec(fc_pos) then
|
||||
M(fc_pos):set_string("formspec", formspec(fc_pos))
|
||||
end
|
||||
return res
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local fc_pos = get_front_chest_pos(pos)
|
||||
local res = tube_add_to_chest(fc_pos, stack)
|
||||
if techage.is_activeformspec(fc_pos) then
|
||||
M(fc_pos):set_string("formspec", formspec(fc_pos))
|
||||
end
|
||||
return res
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:ta4_chest",
|
||||
|
@ -175,7 +175,7 @@ local function pushing(pos, crd, meta, nvm)
|
||||
end
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local function node_timer(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
pushing(pos, crd, M(pos), nvm)
|
||||
@ -253,6 +253,7 @@ local _, node_name_ta3, node_name_ta4 =
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
quick_start = node_timer,
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = M(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
@ -268,7 +269,7 @@ local _, node_name_ta3, node_name_ta4 =
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
allow_metadata_inventory_move = function() return 0 end,
|
||||
on_receive_fields = on_receive_fields,
|
||||
node_timer = keep_running,
|
||||
node_timer = node_timer,
|
||||
on_rotate = screwdriver.disallow,
|
||||
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
|
@ -27,6 +27,7 @@ local string_split = string.split
|
||||
local NodeDef = techage.NodeDef
|
||||
local Tube = techage.Tube
|
||||
local is_cart_available = minecart.is_nodecart_available
|
||||
local techage_counting_hit = techage.counting_hit
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Database
|
||||
@ -253,6 +254,14 @@ function techage.remove_node(pos, oldnode, oldmetadata)
|
||||
end
|
||||
end
|
||||
|
||||
-- Repairs the node number after it was erased by `backend.delete_invalid_entries`
|
||||
function techage.repair_number(pos)
|
||||
local number = techage.get_node_number(pos)
|
||||
if number then
|
||||
backend.set_nodepos(number, pos)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Node register function
|
||||
@ -324,6 +333,7 @@ function techage.send_multi(src, numbers, topic, payload)
|
||||
if ninfo and ninfo.name and ninfo.pos then
|
||||
local ndef = NodeDef[ninfo.name]
|
||||
if ndef and ndef.on_recv_message then
|
||||
techage_counting_hit()
|
||||
ndef.on_recv_message(ninfo.pos, src, topic, payload)
|
||||
end
|
||||
end
|
||||
@ -336,6 +346,7 @@ function techage.send_single(src, number, topic, payload)
|
||||
if ninfo and ninfo.name and ninfo.pos then
|
||||
local ndef = NodeDef[ninfo.name]
|
||||
if ndef and ndef.on_recv_message then
|
||||
techage_counting_hit()
|
||||
return ndef.on_recv_message(ninfo.pos, src, topic, payload)
|
||||
end
|
||||
end
|
||||
|
68
techage/basis/counting.lua
Normal file
@ -0,0 +1,68 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2021 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Count techage commands player related
|
||||
|
||||
]]--
|
||||
|
||||
local PlayerName
|
||||
local PlayerPoints = {}
|
||||
local LastPlayerPoints = {}
|
||||
local S = techage.S
|
||||
|
||||
local MAX_POINTS = tonumber(minetest.settings:get("techage_command_limit")) or 1200
|
||||
|
||||
function techage.counting_start(player_name)
|
||||
PlayerName = player_name
|
||||
PlayerPoints[PlayerName] = PlayerPoints[PlayerName] or 0
|
||||
end
|
||||
|
||||
function techage.counting_stop()
|
||||
PlayerName = nil
|
||||
end
|
||||
|
||||
function techage.counting_hit()
|
||||
if PlayerName then
|
||||
PlayerPoints[PlayerName] = PlayerPoints[PlayerName] + 1
|
||||
end
|
||||
end
|
||||
|
||||
local function output()
|
||||
for name, val in pairs(PlayerPoints) do
|
||||
if val > MAX_POINTS then
|
||||
local obj = minetest.get_player_by_name(name)
|
||||
if obj then
|
||||
minetest.chat_send_player(name,
|
||||
S("[techage] The limit for 'number of commands per minute' has been exceeded.") ..
|
||||
" " .. string.format(MAX_POINTS .. " " .. S("is allowed. Current value is") .. " " .. val));
|
||||
minetest.log("action", "[techage] " .. name ..
|
||||
" exceeds the limit for commands per minute. value = " .. val)
|
||||
local factor = 100 / (obj:get_armor_groups().fleshy or 100)
|
||||
obj:punch(obj, 1.0, {full_punch_interval=1.0, damage_groups = {fleshy=factor * 5}})
|
||||
end
|
||||
end
|
||||
end
|
||||
LastPlayerPoints = table.copy(PlayerPoints)
|
||||
PlayerPoints = {}
|
||||
minetest.after(60, output)
|
||||
end
|
||||
|
||||
minetest.after(60, output)
|
||||
|
||||
|
||||
minetest.register_chatcommand("ta_limit", {
|
||||
description = "Get your current techage command limit value",
|
||||
func = function(name)
|
||||
local num = LastPlayerPoints[name] or 0
|
||||
return true, S("Your current value is") .. " " .. num .. " " .. S("per minute") .. ". " ..
|
||||
MAX_POINTS .. " " .. S("is allowed")
|
||||
end
|
||||
})
|
||||
|
@ -102,7 +102,7 @@ for _, size in ipairs(SIZES) do
|
||||
physical = false,
|
||||
collide_with_objects = false,
|
||||
pointable = false,
|
||||
static_save = true,
|
||||
static_save = false,
|
||||
visual_size = {x = size, y = 0.05, z = 0.05},
|
||||
glow = 14,
|
||||
shaded = true,
|
||||
|
@ -38,21 +38,18 @@ function techage.liquid.formspec(pos, nvm)
|
||||
end
|
||||
local name = minetest.get_node(pos).name
|
||||
if name == "techage:ta4_tank" then
|
||||
local public = dump((M(pos):get_int("public") or 0) == 1)
|
||||
return "size[5,3]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
local meta = M(pos)
|
||||
local public = dump((meta:get_int("public") or 0) == 1)
|
||||
local keep_assignment = dump((meta:get_int("keep_assignment") or 0) == 1)
|
||||
return "size[5,3.5]"..
|
||||
"box[0,-0.1;4.8,0.5;#c6e8ff]"..
|
||||
"label[1.5,-0.1;"..minetest.colorize("#000000", title).."]"..
|
||||
help(4.4, -0.1)..
|
||||
techage.item_image(2, 1, itemname)..
|
||||
"checkbox[0.1,2.5;public;"..S("Allow public access to the tank")..";"..public.."]"
|
||||
"checkbox[0.1,2.5;public;"..S("Allow public access to the tank")..";"..public.."]"..
|
||||
"checkbox[0.1,3;keep_assignment;"..S("keep assignment")..";"..keep_assignment.."]"
|
||||
else
|
||||
return "size[4,2]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;3.8,0.5;#c6e8ff]"..
|
||||
"label[1,-0.1;"..minetest.colorize("#000000", title).."]"..
|
||||
help(3.4, -0.1)..
|
||||
|
@ -183,6 +183,7 @@ function NodeStates:new(attr)
|
||||
stop_node = attr.stop_node,
|
||||
formspec_func = attr.formspec_func,
|
||||
on_state_change = attr.on_state_change,
|
||||
quick_start = attr.quick_start,
|
||||
}
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
@ -272,6 +273,10 @@ function NodeStates:start(pos, nvm)
|
||||
self.on_state_change(pos, state, RUNNING)
|
||||
end
|
||||
start_timer_delayed(pos, self.cycle_time)
|
||||
|
||||
if self.quick_start and state == STOPPED then
|
||||
self.quick_start(pos, 0)
|
||||
end
|
||||
return true
|
||||
end
|
||||
return false
|
||||
|
@ -118,6 +118,9 @@ minetest.register_node("techage:tank_cart", {
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.liquid = nvm.liquid or {}
|
||||
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
|
||||
-- Delete the network between pump and cart
|
||||
Pipe:after_dig_node(pos)
|
||||
Pipe:after_place_node(pos)
|
||||
end,
|
||||
|
||||
set_cargo = function(pos, data)
|
||||
|
@ -191,6 +191,9 @@ techage.Items = {
|
||||
ta4_electricmeter = "techage:ta4_electricmeter",
|
||||
ta4_transformer = "techage:ta4_transformer",
|
||||
power_reduction = "techage_power_reduction.png",
|
||||
ta4_button_4x = "techage:ta4_button_4x",
|
||||
ta4_sequencer = "techage:ta4_sequencer",
|
||||
ta4_movecontroller = "techage:ta4_movecontroller",
|
||||
|
||||
--ta4_ "",
|
||||
}
|
||||
|
@ -183,9 +183,12 @@ techage.manual_DE.aTitel = {
|
||||
"3,TA4 Lua Controller Terminal",
|
||||
"2,TA4 Logik-/Schalt-Module",
|
||||
"3,TA4 Taster/Schalter / Button/Switch",
|
||||
"3,TA4 4x Taster / 4x Button",
|
||||
"3,TA4 Spieler Detektor / Player Detector",
|
||||
"3,TA4 Zustandssammler / State Collector",
|
||||
"3,TA4 Detektor / Detector",
|
||||
"3,TA4 Move Controller",
|
||||
"3,TA4 Sequenzer",
|
||||
"2,TA4 Lampen",
|
||||
"3,TA4 LED Pflanzenlampe / TA4 LED Grow Light",
|
||||
"3,TA4 LED Straßenlampe / TA4 LED Street Lamp",
|
||||
@ -1126,6 +1129,7 @@ techage.manual_DE.aText = {
|
||||
"Der Detektor ist eine spezieller Röhrenblock\\, der erkennt\\, wenn Items über die Röhre weitergegeben werden. Es muss dazu auf beiden Seiten mit der Röhre verbunden sein. Werden Items mit einem Schieber in den Detektor geschoben\\, gibt er diese automatisch weiter.\n"..
|
||||
"Er sendet ein 'on'\\, wenn ein Item erkannt wird\\, gefolgt von einem 'off' eine Sekunde später.\n"..
|
||||
"Danach werden weitere Kommando für 8 Sekunden blockiert.\n"..
|
||||
"Die Wartezeit\\, sowie die Items\\, die ein Kommando auslösen sollen\\, können über das Gabelschlüssel-Menü konfiguriert werden.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
@ -1558,6 +1562,10 @@ techage.manual_DE.aText = {
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Dieser Block hat vier Taster\\, die über das Schraubenschlüssel-Menü individuell konfiguriert werden können. Für jeden Taster kann die Beschriftung und die Zielblockadresse konfiguriert werden. Zusätzlich kann für jeden Taster das Kommando konfiguriert werden\\, welches gesendet werden soll.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Beim TA4 Spieler Detektor hat sich nur das Aussehen geändert. Die Funktionalität ist gleich wie beim TA3 Spieler Detektor.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
@ -1571,6 +1579,50 @@ techage.manual_DE.aText = {
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Der TA4 Move Controller ist ähnlich zum \"Door Controller 2\"\\, aber die ausgewählten Blöcke werden nicht entfernt\\, sondern können bewegt werden.\n"..
|
||||
"Da die bewegten Blöcke Spieler und Mobs mitnehmen können\\, die auf dem Block stehen\\, können damit Fahrstühle und ähnliche Transportsysteme gebaut werden.\n"..
|
||||
"\n"..
|
||||
"Anleitung:\n"..
|
||||
"\n"..
|
||||
" - Controller setzen und die Blöcke\\, die bewegt werden sollen\\, über das Menü an-trainieren (Es können bis zu 16 Blöcke an-trainiert werden)\n"..
|
||||
" - die \"Flugstrecke\" muss über eine x\\,y\\,z Angabe (relativ) eingegeben werden (die maximale Distanz beträgt 100 m)\n"..
|
||||
" - mit den Menü-Tasten \"Bewege A-B\" sowie \"Bewege B-A\" kann die Bewegung getestet werden\n"..
|
||||
" - man kann auch durch Wände oder andere Blöcke fliegen\n"..
|
||||
" - auch die Zielposition für die Blöcke kann belegt sein. Die Blöcke werden in diesem Falle \"unsichtbar\" gespeichert. Dies ist für Schiebetüren und ähnliches gedacht\n"..
|
||||
" - Über das Gabelschlüssel-Menü kann im Controller auch ein \"handover\" programmiert werden. Durch Eingabe einer Blocknummer werden die Blöcke dann an den nächsten Move Controller übergeben. So lassen sich auch zusammenhängende Bewegungen über mehrere Move Controller realisieren.\n"..
|
||||
"\n"..
|
||||
"Der Move Controller unterstützt folgende techage Kommandos:\n"..
|
||||
"\n"..
|
||||
" - 'a2b' Bewege Block von A nach B\n"..
|
||||
" - 'b2a' Bewege Block von B nach A\n"..
|
||||
" - 'move' Bewege Block auf die andere Seite\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"über den TA4 Sequenzer können ganze Abläufe programmiert werden. Hier ein Beispiel:\n"..
|
||||
"\n"..
|
||||
" -- this is a comment\n"..
|
||||
" \\[1\\] send 1234 a2b\n"..
|
||||
" \\[30\\] send 1234 b2a\n"..
|
||||
" \\[60\\] goto 1\n"..
|
||||
"\n"..
|
||||
" - Jede Zeile beginnt mit einem Nummer\\, welche einem Zeitpunkt entspricht '\\[<num>\\]'\n"..
|
||||
" - Für Zeitpunkte sind Werte von 1 bis 50000 zulässig\n"..
|
||||
" - 1 entspricht 100 ms\\, 50000 entspricht in etwa 4 Spieltagen\n"..
|
||||
" - Leerzeilen oder Kommentare sind erlaubt ('-- comment')\n"..
|
||||
" - Mit 'send <num> <command> <data>' kann man ein Kommando an einen Block senden\n"..
|
||||
" - Mit 'goto <num>' kann man an eine andere Zeile/Zeitpunkt springen\n"..
|
||||
" - Mit 'stop' kann man den Sequenzer verzögert stoppen\\, so dass er kein neues Kommando\nvon einem Taster oder anderem Block annimmt (um eine Bewegung abzuschließen)\nOhne 'stop' geht der Sequenzer sofort nach dem letzten Kommando in den stopped Modus.\n"..
|
||||
"\n"..
|
||||
"Der TA4 Sequenzer unterstützt folgende techage Kommandos:\n"..
|
||||
"\n"..
|
||||
" - 'goto <num>' Zu einer Kommandozeile springen und damit den Sequenzer starten\n"..
|
||||
" - 'stop' Den Sequenzer anhalten\n"..
|
||||
"\n"..
|
||||
"Das 'goto' Kommando wird nur angenommen\\, wenn der Sequenzer gestoppt ist.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"TA4 beinhaltet eine Reihe von leistungsstarken Lampen\\, die eine bessere Ausleuchtung ermöglichen oder Spezialaufgaben übernehmen.\n"..
|
||||
"\n",
|
||||
"Die TA4 LED Pflanzenlampe ermöglicht ein schnelles und kräftiges Wachstum aller Pflanzen aus der 'farming' Mod. Die Lampe beleuchtet ein 3x3 großes Feld\\, so dass sich damit auch Pflanzen unter Tage anbauen lassen.\n"..
|
||||
@ -1932,9 +1984,12 @@ techage.manual_DE.aItemName = {
|
||||
"ta4_terminal",
|
||||
"",
|
||||
"ta4_button",
|
||||
"ta4_button_4x",
|
||||
"ta4_playerdetector",
|
||||
"ta4_collector",
|
||||
"ta4_detector",
|
||||
"ta4_movecontroller",
|
||||
"ta4_sequencer",
|
||||
"",
|
||||
"ta4_growlight",
|
||||
"ta4_streetlamp",
|
||||
@ -2154,6 +2209,9 @@ techage.manual_DE.aPlanTable = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"ta4_liquid_filter_base",
|
||||
"ta4_liquid_filter_gravel",
|
||||
"ta4_liquid_filter_top",
|
||||
|
@ -183,9 +183,12 @@ techage.manual_EN.aTitel = {
|
||||
"3,TA4 Lua Controller Terminal",
|
||||
"2,TA4 Logic/Switching Modules",
|
||||
"3,TA4 Button/Switch",
|
||||
"3,TA4 4x Button",
|
||||
"3,TA4 Player Detector",
|
||||
"3,TA4 State Collector",
|
||||
"3,TA4 Detector",
|
||||
"3,TA4 Move Controller",
|
||||
"3,TA4 Sequencer",
|
||||
"2,TA4 Lamps",
|
||||
"3,TA4 LED Grow Light",
|
||||
"3,TA4 Street Lamp",
|
||||
@ -1125,6 +1128,7 @@ techage.manual_EN.aText = {
|
||||
"The detector is a special tube block that detects when items are passed on through the tube. To do this\\, it must be connected to tubes on both sides. If items are pushed into the detector with a pusher\\, they are automatically passed on.\n"..
|
||||
"It sends an 'on' when an item is recognized\\, followed by an 'off' a second later.\n"..
|
||||
"Then further commands are blocked for 8 seconds.\n"..
|
||||
"The waiting time and the items that should trigger a command can be configured using the open-ended wrench menu. \n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
@ -1200,7 +1204,7 @@ techage.manual_EN.aText = {
|
||||
"\n"..
|
||||
"\n",
|
||||
"",
|
||||
"The Techage Info Tool (wrench) has several functions. It shows the time\\, position\\, temperature and biome when an unknown block is clicked on.\n"..
|
||||
"The Techage Info Tool (open-ended wrench) has several functions. It shows the time\\, position\\, temperature and biome when an unknown block is clicked on.\n"..
|
||||
"If you click on a TechAge block with command interface\\, all available data will be shown (see also \"Logic / switching blocks\").\n"..
|
||||
"\n"..
|
||||
"With Shift + right click an extended menu can be opened for some blocks. Depending on the block\\, further data can be called up or special settings can be made here. In the case of a generator\\, for example\\, the charging curve/switch-off can be programmed. \n"..
|
||||
@ -1556,6 +1560,10 @@ techage.manual_EN.aText = {
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"This block has four buttons that can be individually configured using the wrench menu. The labeling and the target block address can be configured for each button. In addition\\, the command that is to be sent can be configured for each button. \n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Only the appearance of the TA4 player detector has changed. The functionality is the same as with the TA3 player detector.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
@ -1569,6 +1577,50 @@ techage.manual_EN.aText = {
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"The TA4 Move Controller is similar to \"Door Controller 2\"\\, but the selected blocks are not removed\\, but can be moved.\n"..
|
||||
"Since the moving blocks can take players and mobs standing on the block with them\\, elevators and similar transport systems can be built with them.\n"..
|
||||
"\n"..
|
||||
"Instructions:\n"..
|
||||
"\n"..
|
||||
" - Set the controller and train the blocks to be moved via the menu (up to 16 blocks can be trained)\n"..
|
||||
" - the \"flight route\" must be entered via an x\\, y\\, z specification (relative) (the maximum distance is 100 m)\n"..
|
||||
" - The movement can be tested with the menu buttons \"Move A-B\" and \"Move B-A\"\n"..
|
||||
" - you can also fly through walls or other blocks\n"..
|
||||
" - The target position for the blocks can also be occupied. In this case\\, the blocks are saved \"invisibly\". This is intended for sliding doors and the like\n"..
|
||||
" - A \"handover\" can also be programmed in the controller via the open-ended wrench menu. By entering a block number\\, the blocks are then transferred to the next move controller. In this way\\, connected movements can also be implemented using several Move Controllers.\n"..
|
||||
"\n"..
|
||||
"The Move Controller supports the following techage commands:\n"..
|
||||
"\n"..
|
||||
" - 'a2b' Move block from A to B.\n"..
|
||||
" - 'b2a' Move block from B to A.\n"..
|
||||
" - 'move' Move block to the other side\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Entire processes can be programmed using the TA4 sequencer. Here's an example:\n"..
|
||||
"\n"..
|
||||
" -- this is a comment\n"..
|
||||
" \\[1\\] send 1234 a2b\n"..
|
||||
" \\[30\\] send 1234 b2a\n"..
|
||||
" \\[60\\] goto 1\n"..
|
||||
"\n"..
|
||||
" - Each line begins with a number which corresponds to a point in time '\\[<num>\\]'\n"..
|
||||
" - Values from 1 to 50000 are permitted for times\n"..
|
||||
" - 1 corresponds to 100 ms\\, 50000 corresponds to about 4 game days\n"..
|
||||
" - Empty lines or comments are allowed ('-- comment')\n"..
|
||||
" - With 'send <num> <command> <data>' you can send a command to a block\n"..
|
||||
" - With 'goto <num>' you can jump to another line / point in time\n"..
|
||||
" - With 'stop' you can stop the sequencer with a delay so that it does not receive a new command\naccepts from a button or other block (to complete a movement)\nWithout 'stop'\\, the sequencer goes into stopped mode immediately after the last command.\n"..
|
||||
"\n"..
|
||||
"The TA4 sequencer supports the following techage commands:\n"..
|
||||
"\n"..
|
||||
" - 'goto <num>' Jump to a command line and start the sequencer\n"..
|
||||
" - 'stop' Stop the sequencer\n"..
|
||||
"\n"..
|
||||
"The 'goto' command is only accepted when the sequencer is stopped.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"TA4 contains a series of powerful lamps that enable better illumination or take on special tasks.\n"..
|
||||
"\n",
|
||||
"The TA4 LED grow light enables fast and vigorous growth of all plants from the 'farming' mod. The lamp illuminates a 3x3 field\\, so that plants can also be grown underground.\n"..
|
||||
@ -1931,9 +1983,12 @@ techage.manual_EN.aItemName = {
|
||||
"ta4_terminal",
|
||||
"",
|
||||
"ta4_button",
|
||||
"ta4_button_4x",
|
||||
"ta4_playerdetector",
|
||||
"ta4_collector",
|
||||
"ta4_detector",
|
||||
"ta4_movecontroller",
|
||||
"ta4_sequencer",
|
||||
"",
|
||||
"ta4_growlight",
|
||||
"ta4_streetlamp",
|
||||
@ -2153,6 +2208,9 @@ techage.manual_EN.aPlanTable = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"ta4_liquid_filter_base",
|
||||
"ta4_liquid_filter_gravel",
|
||||
"ta4_liquid_filter_top",
|
||||
|
@ -43,7 +43,7 @@ function techage.display.display_update(pos, objref)
|
||||
"default", text,
|
||||
70, 70, NUM_ROWS, "top", "#000")
|
||||
objref:set_properties({ textures = {texture},
|
||||
visual_size = {x=0.94, y=0.94} })
|
||||
visual_size = {x=0.94, y=0.94} })
|
||||
end
|
||||
|
||||
function techage.display.display_updateXL(pos, objref)
|
||||
@ -54,7 +54,7 @@ function techage.display.display_updateXL(pos, objref)
|
||||
"default", text,
|
||||
126, 70, NUM_ROWS, "top", "#000")
|
||||
objref:set_properties({ textures = {texture},
|
||||
visual_size = {x=0.94*1.9, y=0.94} })
|
||||
visual_size = {x=0.94*1.9, y=0.94} })
|
||||
end
|
||||
|
||||
function techage.display.on_timer(pos)
|
||||
|
BIN
techage/images/watermill.png
Normal file
After Width: | Height: | Size: 453 KiB |
@ -13,7 +13,7 @@
|
||||
techage = {}
|
||||
|
||||
-- Version for compatibility checks, see readme.md/history
|
||||
techage.version = 1.02
|
||||
techage.version = 1.03
|
||||
|
||||
if minetest.global_exists("tubelib") then
|
||||
minetest.log("error", "[techage] Techage can't be used together with the mod tubelib!")
|
||||
@ -30,8 +30,8 @@ elseif minetest.global_exists("tubelib2") and tubelib2.version < 1.9 then
|
||||
elseif minetest.global_exists("minecart") and minecart.version < 1.08 then
|
||||
minetest.log("error", "[techage] Techage requires minecart version 1.08 or newer!")
|
||||
return
|
||||
elseif minetest.global_exists("lcdlib") and lcdlib.version < 1.0 then
|
||||
minetest.log("error", "[techage] Techage requires lcdlib version 1.0 or newer!")
|
||||
elseif minetest.global_exists("lcdlib") and lcdlib.version < 1.01 then
|
||||
minetest.log("error", "[techage] Techage requires lcdlib version 1.01 or newer!")
|
||||
return
|
||||
elseif minetest.global_exists("safer_lua") and safer_lua.version < 1.0 then
|
||||
minetest.log("error", "[techage] Techage requires safer_lua version 1.0 or newer!")
|
||||
@ -73,6 +73,7 @@ end
|
||||
-- Basis features
|
||||
local MP = minetest.get_modpath("techage")
|
||||
dofile(MP.."/basis/lib.lua") -- helper functions
|
||||
dofile(MP.."/basis/counting.lua") -- command counting
|
||||
dofile(MP.."/basis/fake_player.lua") -- dummy player object
|
||||
dofile(MP.."/basis/node_store.lua")
|
||||
dofile(MP.."/basis/gravel_lib.lua") -- ore probability
|
||||
@ -263,6 +264,7 @@ dofile(MP.."/logic/repeater.lua")
|
||||
dofile(MP.."/logic/programmer.lua")
|
||||
dofile(MP.."/logic/signallamp.lua")
|
||||
dofile(MP.."/logic/sequencer.lua")
|
||||
dofile(MP.."/logic/sequencer2.lua")
|
||||
dofile(MP.."/logic/timer.lua")
|
||||
dofile(MP.."/logic/lua_logic.lua") -- old
|
||||
dofile(MP.."/logic/logic_block.lua") -- new
|
||||
@ -274,6 +276,8 @@ dofile(MP.."/logic/doorblock.lua")
|
||||
dofile(MP.."/logic/doorcontroller.lua") -- old
|
||||
dofile(MP.."/logic/doorcontroller2.lua") -- new
|
||||
dofile(MP.."/logic/collector.lua")
|
||||
dofile(MP.."/logic/button_4x.lua")
|
||||
dofile(MP.."/logic/movecontroller.lua")
|
||||
if minetest.global_exists("mesecon") then
|
||||
dofile(MP.."/logic/mesecons_converter.lua")
|
||||
end
|
||||
|
@ -74,12 +74,12 @@ local function node_timer(pos, elapsed)
|
||||
if not inv:is_empty("src") then
|
||||
local taken = techage.get_items(pos, inv, "src", 1)
|
||||
if liquid.is_container_empty(taken:get_name()) then
|
||||
return liquid.fill_container({x = pos.x, y = pos.y+1, z = pos.z}, inv, taken:get_name())
|
||||
liquid.fill_container({x = pos.x, y = pos.y+1, z = pos.z}, inv, taken:get_name())
|
||||
else
|
||||
return liquid.empty_container({x = pos.x, y = pos.y-1, z = pos.z}, inv, taken:get_name())
|
||||
liquid.empty_container({x = pos.x, y = pos.y-1, z = pos.z}, inv, taken:get_name())
|
||||
end
|
||||
end
|
||||
return false
|
||||
return true
|
||||
end
|
||||
|
||||
minetest.register_node("techage:filler", {
|
||||
@ -124,7 +124,7 @@ minetest.register_node("techage:filler", {
|
||||
on_rotate = screwdriver.disallow, -- important!
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
use_texture_alpha = techage.CLIP,
|
||||
use_texture_alpha = techage.CLIP,
|
||||
is_ground_content = false,
|
||||
groups = {cracky=2, crumbly=2, choppy=2},
|
||||
sounds = default.node_sound_defaults(),
|
||||
|
@ -45,7 +45,6 @@ local function pumping(pos, nvm, state, capa)
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.dbg_cycles = (mem.dbg_cycles or 0) - 1
|
||||
local outdir = M(pos):get_int("outdir")
|
||||
--print("pumping", outdir, Flip[outdir])
|
||||
local taken, name = liquid.take(pos, Pipe, Flip[outdir], nil, capa, mem.dbg_cycles > 0)
|
||||
if taken > 0 then
|
||||
local leftover = liquid.put(pos, Pipe, outdir, name, taken, mem.dbg_cycles > 0)
|
||||
|
@ -53,6 +53,9 @@ end
|
||||
|
||||
local function take_liquid(pos, indir, name, amount)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if (M(pos):get_int("keep_assignment") or 0) == 1 then
|
||||
amount = math.max(math.min(amount, ((nvm.liquid or {}).amount or 0) - 1), 0)
|
||||
end
|
||||
amount, name = liquid.srv_take(nvm, name, amount)
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
|
||||
@ -219,6 +222,9 @@ minetest.register_node("techage:ta4_tank", {
|
||||
if fields.public then
|
||||
M(pos):set_int("public", fields.public == "true" and 1 or 0)
|
||||
end
|
||||
if fields.keep_assignment then
|
||||
M(pos):set_int("keep_assignment", fields.keep_assignment == "true" and 1 or 0)
|
||||
end
|
||||
end,
|
||||
on_timer = node_timer,
|
||||
on_punch = techage.liquid.on_punch,
|
||||
|
@ -43,6 +43,9 @@ minetest.register_node("techage:ta3_valve_open", {
|
||||
return false
|
||||
end,
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
if minetest.is_protected(pos, clicker:get_player_name()) then
|
||||
return
|
||||
end
|
||||
if liquid.turn_valve_off(pos, Pipe, "techage:ta3_valve_closed", "techage:ta3_valve_open") then
|
||||
minetest.sound_play("techage_valve", {
|
||||
pos = pos,
|
||||
@ -84,6 +87,9 @@ minetest.register_node("techage:ta3_valve_closed", {
|
||||
},
|
||||
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
if minetest.is_protected(pos, clicker:get_player_name()) then
|
||||
return
|
||||
end
|
||||
if liquid.turn_valve_on(pos, Pipe, "techage:ta3_valve_closed", "techage:ta3_valve_open") then
|
||||
minetest.sound_play("techage_valve", {
|
||||
pos = pos,
|
||||
|
@ -113,6 +113,12 @@ Access:=Zugriff:
|
||||
TA3 Button/Switch=TA3 Taster/Schalter
|
||||
TA4 Button/Switch=TA4 Schalter/Taster
|
||||
|
||||
### button.lua ###
|
||||
### button_4x.lua ###
|
||||
### signallamp_4x.lua ###
|
||||
|
||||
Command=Kommando
|
||||
|
||||
### button.lua ###
|
||||
### cart_detector.lua ###
|
||||
### detector.lua ###
|
||||
@ -130,10 +136,33 @@ Insert destination node number(s)=Gebe Zielnummer(n) ein
|
||||
### doorcontroller.lua ###
|
||||
### mesecons_converter.lua ###
|
||||
### repeater.lua ###
|
||||
### sequencer2.lua ###
|
||||
### submenu.lua ###
|
||||
|
||||
Save=Speichern
|
||||
|
||||
### button.lua ###
|
||||
### signallamp_4x.lua ###
|
||||
|
||||
Command to be sent=Zu sendender Befehl
|
||||
|
||||
### button_4x.lua ###
|
||||
|
||||
Command to be sent (ignored for switches)=Zu sendender Befehl (wird für Schalter ignoriert)
|
||||
Label=Beschriftung
|
||||
Label for the button=Beschriftung für die Taste
|
||||
Momentary button or on/off switch=Taster oder Ein-/Ausschalter
|
||||
TA4 4x Button=TA4 4x Taster
|
||||
Type=Typ
|
||||
|
||||
### button_4x.lua ###
|
||||
### signallamp_4x.lua ###
|
||||
|
||||
Access=Zugriff
|
||||
Button protection=Tastenschutz
|
||||
Destination block number=Zielblocknummer
|
||||
Number=Nummer
|
||||
|
||||
### cart_detector.lua ###
|
||||
|
||||
TA3 Cart Detector=TA3 Wagen Detektor
|
||||
@ -204,14 +233,32 @@ TA3 Melting=TA3 Schmelzen
|
||||
|
||||
TA3 Cooler=TA3 Kühler
|
||||
|
||||
### counting.lua ###
|
||||
|
||||
Your current value is=Der aktuelle Wert ist
|
||||
[techage] The limit for 'number of commands per minute' has been exceeded.=[techage] Das Limit für 'Anzahl Befehle pro Minute' wurde überschritten.
|
||||
is allowed=ist erlaubt
|
||||
is allowed. Current value is=ist erlaubt. Aktueller Wert ist
|
||||
per minute=pro Minute
|
||||
|
||||
### cylinder.lua ###
|
||||
|
||||
TA2 Cylinder=TA2 Zylinder
|
||||
|
||||
### detector.lua ###
|
||||
|
||||
Configured Items=Konfigurierte Gegenstände
|
||||
Items which generate an 'on' command.@nIf empty, all passed items generate an 'on' command.=Items, die einen 'on'-Kommando generieren.@nWenn leer, generieren alle übergebenen Items einen 'on'-Befehl.
|
||||
On Time=ON Zeit
|
||||
TA3 Detector=TA3 Detektor
|
||||
TA4 Detector=TA4 Detektor
|
||||
The time after the 'off' command@nuntil the next 'on' command is accepted.=Die Zeit nach dem 'off' Kommando,@nbis das nächste 'on' Kommando akzeptiert wird.
|
||||
The time between the 'on' and 'off' commands.=Die Zeit zwischen den 'on' und 'off' Kommandos.
|
||||
|
||||
### detector.lua ###
|
||||
### logic_block.lua ###
|
||||
|
||||
Blocking Time=Sperrzeit
|
||||
|
||||
### display.lua ###
|
||||
|
||||
@ -250,15 +297,19 @@ Blocks are back=Blöcke sind wieder da
|
||||
Blocks are disappeared=Blöcke sind verschwunden
|
||||
Click on all the blocks that are part of the door/gate=Klicke auf alle Blöcke, die Teil des Tores sind
|
||||
Ctrl,Inv=Ctrl,Inv
|
||||
Done=Fertig
|
||||
Record=Aufzeichnen
|
||||
Recording...=Aufzeichnung...
|
||||
Remove=Entfernen
|
||||
Set=Setzen
|
||||
TA3 Door Controller II=TA3 Tür Controller II
|
||||
block positions are stored.=Block Positionen gespeichert.
|
||||
with door sound=mit Türgeräusch
|
||||
|
||||
### doorcontroller2.lua ###
|
||||
### movecontroller.lua ###
|
||||
|
||||
Done=Fertig
|
||||
Record=Aufzeichnen
|
||||
Recording...=Aufzeichnung...
|
||||
block positions are stored.=Block Positionen gespeichert.
|
||||
|
||||
### drillbox.lua ###
|
||||
|
||||
Build derrick=Errichte Ölturm
|
||||
@ -370,6 +421,7 @@ loaded=geladen
|
||||
|
||||
### formspecs.lua ###
|
||||
|
||||
Block has a wrench menu=Block hat ein Gabelschlüssel-Menü
|
||||
Charge termination=Ladebegrenzung
|
||||
Current output [ku]=Aktueller Ausgabewert
|
||||
Maximum output [ku]=Maximaler Ausgabewert
|
||||
@ -570,6 +622,11 @@ Allow public access to the tank=Erlaube öffentlichen Zugriff auf den Tank
|
||||
Liquid Tank=Flüssigkeitstank
|
||||
To add liquids punch@nthe tank@nwith a liquid container=Um Flüssigkeit nachzufüllen,@nschlage mit einem Flüssigkeitsbehälter@nauf den Block
|
||||
|
||||
### liquid_lib.lua ###
|
||||
### ta4_chest.lua ###
|
||||
|
||||
keep assignment=Zuordnung beibehalten
|
||||
|
||||
### liquid_pipe.lua ###
|
||||
|
||||
TA Junction Pipe=TA Leitungskupplung
|
||||
@ -595,8 +652,8 @@ no usable water=Kein brauchbares Wasser
|
||||
@nRule:@n<output> @= on/off if <input-expression> is true@n=@nRegel:@n<output> @= on/off if <input-expression> is true@n
|
||||
@nThe internal processing time for all@ncommands is 100 ms.=@nDie interne Durchlaufzeit für alle@nKommandos beträgt 100 ms.
|
||||
@nValid operators:@nand or on off me @=@= ~@= ( )@n=@nGültige Operatoren:@nand or on off @=@= ~@= ( )@n
|
||||
Blocking Time=Sperrzeit
|
||||
Help=Hilfe
|
||||
Clear=Löschen
|
||||
Debug=Debug
|
||||
Inputs=Eingänge
|
||||
Outputs=Ausgänge
|
||||
Rules=Regeln
|
||||
@ -606,10 +663,20 @@ Syntax=Syntax
|
||||
### logic_block.lua ###
|
||||
### lua_logic.lua ###
|
||||
|
||||
Store=Speichern
|
||||
TA3 Logic Block=TA3 Logikblock
|
||||
Update=Update
|
||||
|
||||
### logic_block.lua ###
|
||||
### lua_logic.lua ###
|
||||
### movecontroller.lua ###
|
||||
|
||||
Store=Speichern
|
||||
|
||||
### logic_block.lua ###
|
||||
### sequencer2.lua ###
|
||||
|
||||
Help=Hilfe
|
||||
|
||||
### lye.lua ###
|
||||
|
||||
Lye=Lauge
|
||||
@ -667,6 +734,28 @@ TA1 Pine Wood Board=TA1 Kiefernholzbrett
|
||||
|
||||
TA4 Streetlamp Solar Cell=TA4 Straßenlampen-Solarzelle
|
||||
|
||||
### movecontroller.lua ###
|
||||
|
||||
Click on all blocks that shall be moved=Klicke auf alle Blöcke, die verschoben werden sollen
|
||||
Destination position is protected=Zielposition ist geschützt
|
||||
Error: Distance > 100 m !!=Fehler: Distanz > 100 m !!
|
||||
Handover to A=Übergabe an A
|
||||
Handover to B=Übergabe an B
|
||||
Maximum Speed=Maximalgeschwindigkeit
|
||||
Maximum speed for the moving block.=Maximale Geschwindigkeit für den beweglichen Block.
|
||||
Move A-B=Bewege A-B
|
||||
Move B-A=Bewege B-A
|
||||
Move block height=Move Block Höhe
|
||||
Move distance (A to B)=Entfernung (A nach B)
|
||||
No valid destination position=Keine gültige Zielposition
|
||||
No valid node at the start position=Kein gültiger Block an der Startposition
|
||||
Number of the next movecontroller.=Nummer des nächsten Move Controllers.
|
||||
Number of the previous movecontroller.=Nummer des vorherigen Move Controllers.
|
||||
Position list error=Positionslistenfehler
|
||||
Start position is protected=Startposition ist geschützt
|
||||
TA4 Move Controller=TA4 Move Controller
|
||||
Value in the range of 0.0 to 1.0=Wert im Bereich von 0.0 bis 1.0
|
||||
|
||||
### node_detector.lua ###
|
||||
|
||||
Send signal if nodes have been:=Sende ein Signal falls Blöcke:
|
||||
@ -750,7 +839,7 @@ TA Power Pole Top 2 (for landlines)=TA Strommastkopf 2 (für Überlandleitungen)
|
||||
|
||||
### power_terminal2.lua ###
|
||||
|
||||
Commands@nhelp . . . print this text@ncls . . . . . clear screen@ngen . . . . print all generators@nsto . . . . . print all storage systems@n=Kommandos@nhelp . . . diesen Text ausgeben@ncls . . . . . Bildschirm löschen@ngen . . . . Alle Generatoren ausgeben@nsto . . . . . Alle Speichersysteme ausgeben@n
|
||||
Commands@nhelp . . . print this text@ncls . . . . . clear screen@ngen . . . . print all generators@nsto . . . . . print all storage systems@ncon . . . . . print main consumers@n=Kommandos@nhelp . . . diesen Text ausgeben@ncls . . . . . Bildschirm löschen@ngen . . . . Alle Generatoren ausgeben@nsto . . . . . Alle Speichersysteme ausgeben@ncon . . . . . Hauptverbraucher ausgeben@n
|
||||
Consumer=Verbraucher
|
||||
Network Data=Netzwerkdaten
|
||||
Number of consumers:=Anzahl der Verbraucher
|
||||
@ -877,14 +966,48 @@ not connected=nicht verbunden
|
||||
### sequencer.lua ###
|
||||
|
||||
TA3 Sequencer=TA3 Sequenzer
|
||||
|
||||
### sequencer.lua ###
|
||||
### sequencer2.lua ###
|
||||
|
||||
stopped=gestoppt
|
||||
|
||||
### sequencer2.lua ###
|
||||
|
||||
- 'goto <num>' (jump to another line)@n= - 'goto <num>' (springe zu einer anderen Zeile)@n
|
||||
- 'send <node num> <cmnd>' (techage command)@n= - 'send <node num> <cmnd>' (techage Kommando)@n
|
||||
- 'stop' (stop the execution)@n= - 'stop' (stoppe die Ausführung)@n
|
||||
- 1 corresponds to 100 ms@n= - 1 entspricht 100 ms@n
|
||||
- 50000 corresponds to 4 game days@n= - 50000 entspricht 4 Spieltagen@n
|
||||
'[<num>] <command>'@n='[<num>] <command>'@n
|
||||
<command> is one of the following:@n=<command> ist eines der folgenden:@n
|
||||
<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
|
||||
Example:@n=Beispiel:
|
||||
Invalid command!=Ungültiges Kommando!
|
||||
Start=Start
|
||||
Stop=Stopp
|
||||
Syntax:@n=Syntax:@n
|
||||
TA4 Sequencer=TA4 Sequenzer
|
||||
running=läuft
|
||||
the timeslot when the command is executed.@n=der Zeitpunkt, wenn der Befehl ausgeführt wird.@n
|
||||
|
||||
### sequencer2.lua ###
|
||||
### submenu.lua ###
|
||||
|
||||
Cancel=Abbruch
|
||||
|
||||
### signallamp.lua ###
|
||||
|
||||
TA4 Wind Turbine Signal Lamp=TA4 Windkraftanlagenlampe
|
||||
TechAge Signal Lamp=TechAge Signallampe
|
||||
TechAge Signal Lamp (can be colored)=TechAge Signallampe (kann gefärbt werden)
|
||||
|
||||
### signallamp_4x.lua ###
|
||||
|
||||
TA4 4x Signal Lamp=
|
||||
|
||||
### silicon.lua ###
|
||||
|
||||
TA4 Silicon Wafer=TA4 Silizium-Wafer
|
||||
@ -902,7 +1025,6 @@ TA Lamp=TA Lampe
|
||||
|
||||
TA1 Sluice Gate=TA1 Schleusenschieber
|
||||
TA1 Sluice Handle=TA1 Schleusengriff
|
||||
Your pond is too small!=Der Teich ist zu klein!
|
||||
|
||||
### solarcell.lua ###
|
||||
|
||||
@ -948,7 +1070,6 @@ TA4 LED Street Lamp Pole=TA4 LED Lampenmast
|
||||
|
||||
### submenu.lua ###
|
||||
|
||||
Cancel=Abbruch
|
||||
Note: You can't change any values while the block is running!=Hinweis: Während der Block läuft, kann kein Wert geändert werden!
|
||||
Refresh=Aktualisieren
|
||||
|
||||
@ -982,7 +1103,6 @@ Size=Größe
|
||||
TA4 8x2000 Chest=TA4 8x2000 Kiste
|
||||
Unlock=Entsperren
|
||||
Unlock connected chest@nif all slots are below 2000=Nachfolgende Kiste entsperren,@nsofern alle Speicherplätze <= 2000
|
||||
keep assignment=Zuordnung beibehalten
|
||||
right to left=von rechts nach links
|
||||
|
||||
### ta4_doser.lua ###
|
||||
@ -1099,11 +1219,6 @@ Usmium Powder=Usmium Pulver
|
||||
TA Valve=TA Ventil
|
||||
TA3 Valve=TA3 Ventil
|
||||
|
||||
### water.lua ###
|
||||
|
||||
Flowing Water=Fließendes Wasser
|
||||
Water Source=Wasserquelle
|
||||
|
||||
### waterinlet.lua ###
|
||||
|
||||
Error: No natural water!=Fehler: Kein natürliches Wasser!
|
||||
@ -1132,3 +1247,8 @@ This is not the surface of the ocean!=Das ist nicht die Meeresoberfläche!
|
||||
[TA4 Wind Turbine]=[TA4 Windkraftanlage]
|
||||
biome and no ocean!=Biom und keine Meer (ocean)!
|
||||
is a suitable place for a wind turbine!=ist ein geeigneter Ort für eine Windkraftanlage!
|
||||
|
||||
|
||||
##### not used anymore #####
|
||||
|
||||
[techage] The limit for commands per minute has been exceeded.=[techage] Das Limit für Befehle pro Minute wurde überschritten.
|
||||
|
@ -113,6 +113,12 @@ Access:=
|
||||
TA3 Button/Switch=
|
||||
TA4 Button/Switch=
|
||||
|
||||
### button.lua ###
|
||||
### button_4x.lua ###
|
||||
### signallamp_4x.lua ###
|
||||
|
||||
Command=
|
||||
|
||||
### button.lua ###
|
||||
### cart_detector.lua ###
|
||||
### detector.lua ###
|
||||
@ -130,10 +136,33 @@ Insert destination node number(s)=
|
||||
### doorcontroller.lua ###
|
||||
### mesecons_converter.lua ###
|
||||
### repeater.lua ###
|
||||
### sequencer2.lua ###
|
||||
### submenu.lua ###
|
||||
|
||||
Save=
|
||||
|
||||
### button.lua ###
|
||||
### signallamp_4x.lua ###
|
||||
|
||||
Command to be sent=
|
||||
|
||||
### button_4x.lua ###
|
||||
|
||||
Command to be sent (ignored for switches)=
|
||||
Label=
|
||||
Label for the button=
|
||||
Momentary button or on/off switch=
|
||||
TA4 4x Button=
|
||||
Type=
|
||||
|
||||
### button_4x.lua ###
|
||||
### signallamp_4x.lua ###
|
||||
|
||||
Access=
|
||||
Button protection=
|
||||
Destination block number=
|
||||
Number=
|
||||
|
||||
### cart_detector.lua ###
|
||||
|
||||
TA3 Cart Detector=
|
||||
@ -204,14 +233,32 @@ TA3 Melting=
|
||||
|
||||
TA3 Cooler=
|
||||
|
||||
### counting.lua ###
|
||||
|
||||
Your current value is=
|
||||
[techage] The limit for 'number of commands per minute' has been exceeded.=
|
||||
is allowed=
|
||||
is allowed. Current value is=
|
||||
per minute=
|
||||
|
||||
### cylinder.lua ###
|
||||
|
||||
TA2 Cylinder=
|
||||
|
||||
### detector.lua ###
|
||||
|
||||
Configured Items=
|
||||
Items which generate an 'on' command.@nIf empty, all passed items generate an 'on' command.=
|
||||
On Time=
|
||||
TA3 Detector=
|
||||
TA4 Detector=
|
||||
The time after the 'off' command@nuntil the next 'on' command is accepted.=
|
||||
The time between the 'on' and 'off' commands.=
|
||||
|
||||
### detector.lua ###
|
||||
### logic_block.lua ###
|
||||
|
||||
Blocking Time=
|
||||
|
||||
### display.lua ###
|
||||
|
||||
@ -250,15 +297,19 @@ Blocks are back=
|
||||
Blocks are disappeared=
|
||||
Click on all the blocks that are part of the door/gate=
|
||||
Ctrl,Inv=
|
||||
Done=
|
||||
Record=
|
||||
Recording...=
|
||||
Remove=
|
||||
Set=
|
||||
TA3 Door Controller II=
|
||||
block positions are stored.=
|
||||
with door sound=
|
||||
|
||||
### doorcontroller2.lua ###
|
||||
### movecontroller.lua ###
|
||||
|
||||
Done=
|
||||
Record=
|
||||
Recording...=
|
||||
block positions are stored.=
|
||||
|
||||
### drillbox.lua ###
|
||||
|
||||
Build derrick=
|
||||
@ -370,6 +421,7 @@ loaded=
|
||||
|
||||
### formspecs.lua ###
|
||||
|
||||
Block has a wrench menu=
|
||||
Charge termination=
|
||||
Current output [ku]=
|
||||
Maximum output [ku]=
|
||||
@ -570,6 +622,11 @@ Allow public access to the tank=
|
||||
Liquid Tank=
|
||||
To add liquids punch@nthe tank@nwith a liquid container=
|
||||
|
||||
### liquid_lib.lua ###
|
||||
### ta4_chest.lua ###
|
||||
|
||||
keep assignment=
|
||||
|
||||
### liquid_pipe.lua ###
|
||||
|
||||
TA Junction Pipe=
|
||||
@ -595,8 +652,8 @@ no usable water=
|
||||
@nRule:@n<output> @= on/off if <input-expression> is true@n=
|
||||
@nThe internal processing time for all@ncommands is 100 ms.=
|
||||
@nValid operators:@nand or on off me @=@= ~@= ( )@n=
|
||||
Blocking Time=
|
||||
Help=
|
||||
Clear=
|
||||
Debug=
|
||||
Inputs=
|
||||
Outputs=
|
||||
Rules=
|
||||
@ -606,10 +663,20 @@ Syntax=
|
||||
### logic_block.lua ###
|
||||
### lua_logic.lua ###
|
||||
|
||||
Store=
|
||||
TA3 Logic Block=
|
||||
Update=
|
||||
|
||||
### logic_block.lua ###
|
||||
### lua_logic.lua ###
|
||||
### movecontroller.lua ###
|
||||
|
||||
Store=
|
||||
|
||||
### logic_block.lua ###
|
||||
### sequencer2.lua ###
|
||||
|
||||
Help=
|
||||
|
||||
### lye.lua ###
|
||||
|
||||
Lye=
|
||||
@ -667,6 +734,28 @@ TA1 Pine Wood Board=
|
||||
|
||||
TA4 Streetlamp Solar Cell=
|
||||
|
||||
### movecontroller.lua ###
|
||||
|
||||
Click on all blocks that shall be moved=
|
||||
Destination position is protected=
|
||||
Error: Distance > 100 m !!=
|
||||
Handover to A=
|
||||
Handover to B=
|
||||
Maximum Speed=
|
||||
Maximum speed for the moving block.=
|
||||
Move A-B=
|
||||
Move B-A=
|
||||
Move block height=
|
||||
Move distance (A to B)=
|
||||
No valid destination position=
|
||||
No valid node at the start position=
|
||||
Number of the next movecontroller.=
|
||||
Number of the previous movecontroller.=
|
||||
Position list error=
|
||||
Start position is protected=
|
||||
TA4 Move Controller=
|
||||
Value in the range of 0.0 to 1.0=
|
||||
|
||||
### node_detector.lua ###
|
||||
|
||||
Send signal if nodes have been:=
|
||||
@ -750,7 +839,7 @@ TA Power Pole Top 2 (for landlines)=
|
||||
|
||||
### power_terminal2.lua ###
|
||||
|
||||
Commands@nhelp . . . print this text@ncls . . . . . clear screen@ngen . . . . print all generators@nsto . . . . . print all storage systems@n=
|
||||
Commands@nhelp . . . print this text@ncls . . . . . clear screen@ngen . . . . print all generators@nsto . . . . . print all storage systems@ncon . . . . . print main consumers@n=
|
||||
Consumer=
|
||||
Network Data=
|
||||
Number of consumers:=
|
||||
@ -877,14 +966,48 @@ not connected=
|
||||
### sequencer.lua ###
|
||||
|
||||
TA3 Sequencer=
|
||||
|
||||
### sequencer.lua ###
|
||||
### sequencer2.lua ###
|
||||
|
||||
stopped=
|
||||
|
||||
### sequencer2.lua ###
|
||||
|
||||
- 'goto <num>' (jump to another line)@n=
|
||||
- 'send <node num> <cmnd>' (techage command)@n=
|
||||
- 'stop' (stop the execution)@n=
|
||||
- 1 corresponds to 100 ms@n=
|
||||
- 50000 corresponds to 4 game days@n=
|
||||
'[<num>] <command>'@n=
|
||||
<command> is one of the following:@n=
|
||||
<num> is a number from 1 to 50000 and is@n=
|
||||
@n=
|
||||
Commands=
|
||||
Example:@n=
|
||||
Invalid command!=
|
||||
Start=
|
||||
Stop=
|
||||
Syntax:@n=
|
||||
TA4 Sequencer=
|
||||
running=
|
||||
the timeslot when the command is executed.@n=
|
||||
|
||||
### sequencer2.lua ###
|
||||
### submenu.lua ###
|
||||
|
||||
Cancel=
|
||||
|
||||
### signallamp.lua ###
|
||||
|
||||
TA4 Wind Turbine Signal Lamp=
|
||||
TechAge Signal Lamp=
|
||||
TechAge Signal Lamp (can be colored)=
|
||||
|
||||
### signallamp_4x.lua ###
|
||||
|
||||
TA4 4x Signal Lamp=
|
||||
|
||||
### silicon.lua ###
|
||||
|
||||
TA4 Silicon Wafer=
|
||||
@ -902,7 +1025,6 @@ TA Lamp=
|
||||
|
||||
TA1 Sluice Gate=
|
||||
TA1 Sluice Handle=
|
||||
Your pond is too small!=
|
||||
|
||||
### solarcell.lua ###
|
||||
|
||||
@ -948,7 +1070,6 @@ TA4 LED Street Lamp Pole=
|
||||
|
||||
### submenu.lua ###
|
||||
|
||||
Cancel=
|
||||
Note: You can't change any values while the block is running!=
|
||||
Refresh=
|
||||
|
||||
@ -982,7 +1103,6 @@ Size=
|
||||
TA4 8x2000 Chest=
|
||||
Unlock=
|
||||
Unlock connected chest@nif all slots are below 2000=
|
||||
keep assignment=
|
||||
right to left=
|
||||
|
||||
### ta4_doser.lua ###
|
||||
@ -1099,11 +1219,6 @@ Usmium Powder=
|
||||
TA Valve=
|
||||
TA3 Valve=
|
||||
|
||||
### water.lua ###
|
||||
|
||||
Flowing Water=
|
||||
Water Source=
|
||||
|
||||
### waterinlet.lua ###
|
||||
|
||||
Error: No natural water!=
|
||||
|
@ -19,6 +19,16 @@ local NDEF = function(pos) return (minetest.registered_nodes[techage.get_node_lv
|
||||
|
||||
local logic = techage.logic
|
||||
|
||||
local WRENCH_MENU = {
|
||||
{
|
||||
type = "ascii",
|
||||
name = "command",
|
||||
label = S("Command"),
|
||||
tooltip = S("Command to be sent"),
|
||||
default = "on",
|
||||
},
|
||||
}
|
||||
|
||||
local function switch_on(pos)
|
||||
local cycle_time = M(pos):get_int("cycle_time")
|
||||
local name = techage.get_node_lvm(pos).name
|
||||
@ -27,7 +37,10 @@ local function switch_on(pos)
|
||||
elseif name == "techage:ta4_button_off" then
|
||||
logic.swap_node(pos, "techage:ta4_button_on")
|
||||
end
|
||||
logic.send_on(pos, M(pos), cycle_time)
|
||||
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)
|
||||
minetest.sound_play("techage_button", {
|
||||
pos = pos,
|
||||
gain = 0.5,
|
||||
@ -249,6 +262,7 @@ minetest.register_node("techage:ta4_button_off", {
|
||||
meta:set_int("cycle_time", 0)
|
||||
end,
|
||||
|
||||
ta4_formspec = WRENCH_MENU,
|
||||
on_receive_fields = on_receive_fields,
|
||||
on_rightclick = on_rightclick_on,
|
||||
techage_set_numbers = techage_set_numbers,
|
||||
|
297
techage/logic/button_4x.lua
Normal file
@ -0,0 +1,297 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2017-2021 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA4 Logic fourfold button
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local function get_button_num(pos, clicker, pointed_thing)
|
||||
-- use the node behind the button to get better results
|
||||
if clicker and pointed_thing then
|
||||
local offs = vector.subtract(pointed_thing.under, pointed_thing.above)
|
||||
pointed_thing.under = vector.add(pointed_thing.under, offs)
|
||||
pointed_thing.above = vector.add(pointed_thing.above, offs)
|
||||
local pos1 = minetest.pointed_thing_to_face_pos(clicker, pointed_thing)
|
||||
local y = pos1.y - pos.y
|
||||
|
||||
if y < -0.3 then
|
||||
return 4
|
||||
elseif y < -0.03 and y > -0.22 then
|
||||
return 3
|
||||
elseif y > 0.03 and y < 0.22 then
|
||||
return 2
|
||||
elseif y > 0.3 then
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local WRENCH_MENU = {
|
||||
{
|
||||
type = "dropdown",
|
||||
choices = "button,switch",
|
||||
name = "type",
|
||||
label = S("Type"),
|
||||
tooltip = S("Momentary button or on/off switch"),
|
||||
default = "1",
|
||||
},
|
||||
{
|
||||
type = "ascii",
|
||||
name = "label1",
|
||||
label = S("Label") .. " 1",
|
||||
tooltip = S("Label for the button"),
|
||||
default = "1",
|
||||
},
|
||||
{
|
||||
type = "numbers",
|
||||
name = "dest_number1",
|
||||
label = S("Number") .. " 1",
|
||||
tooltip = S("Destination block number"),
|
||||
default = "",
|
||||
},
|
||||
{
|
||||
type = "ascii",
|
||||
name = "command1",
|
||||
label = S("Command") .. " 1",
|
||||
tooltip = S("Command to be sent (ignored for switches)"),
|
||||
default = "1",
|
||||
},
|
||||
{
|
||||
type = "ascii",
|
||||
name = "label2",
|
||||
label = S("Label") .. " 2",
|
||||
tooltip = S("Label for the button"),
|
||||
default = "1",
|
||||
},
|
||||
{
|
||||
type = "numbers",
|
||||
name = "dest_number2",
|
||||
label = S("Number") .. " 2",
|
||||
tooltip = S("Destination block number"),
|
||||
default = "",
|
||||
},
|
||||
{
|
||||
type = "ascii",
|
||||
name = "command2",
|
||||
label = S("Command") .. " 2",
|
||||
tooltip = S("Command to be sent (ignored for switches)"),
|
||||
default = "2",
|
||||
},
|
||||
{
|
||||
type = "ascii",
|
||||
name = "label3",
|
||||
label = S("Label") .. " 3",
|
||||
tooltip = S("Label for the button"),
|
||||
default = "1",
|
||||
},
|
||||
{
|
||||
type = "numbers",
|
||||
name = "dest_number3",
|
||||
label = S("Number") .. " 3",
|
||||
tooltip = S("Destination block number"),
|
||||
default = "",
|
||||
},
|
||||
{
|
||||
type = "ascii",
|
||||
name = "command3",
|
||||
label = S("Command") .. " 3",
|
||||
tooltip = S("Command to be sent (ignored for switches)"),
|
||||
default = "3",
|
||||
},
|
||||
{
|
||||
type = "ascii",
|
||||
name = "label4",
|
||||
label = S("Label") .. " 4",
|
||||
tooltip = S("Label for the button"),
|
||||
default = "1",
|
||||
},
|
||||
{
|
||||
type = "numbers",
|
||||
name = "dest_number4",
|
||||
label = S("Number") .. " 4",
|
||||
tooltip = S("Destination block number"),
|
||||
default = "",
|
||||
},
|
||||
{
|
||||
type = "ascii",
|
||||
name = "command4",
|
||||
label = S("Command") .. " 4",
|
||||
tooltip = S("Command to be sent (ignored for switches)"),
|
||||
default = "4",
|
||||
},
|
||||
{
|
||||
type = "dropdown",
|
||||
choices = "private,protected,public",
|
||||
name = "access",
|
||||
label = S("Access"),
|
||||
tooltip = S("Button protection"),
|
||||
default = "8",
|
||||
},
|
||||
}
|
||||
|
||||
local function send_cmnd(pos, num, cmd)
|
||||
local meta = M(pos)
|
||||
local own_num = meta:get_string("node_number")
|
||||
local dest = meta:get_string("dest_number" .. num)
|
||||
local command, payload = cmd, nil
|
||||
if not cmd then
|
||||
local s = meta:get_string("command" .. num)
|
||||
command, payload = unpack(string.split(s, " ", false, 1))
|
||||
end
|
||||
local owner = meta:get_string("owner")
|
||||
if techage.check_numbers(dest, owner) then
|
||||
techage.send_multi(own_num, dest, command, payload)
|
||||
end
|
||||
end
|
||||
|
||||
local function button_update(pos, objref)
|
||||
local meta = M(pos)
|
||||
pos = vector.round(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.button = nvm.button or {}
|
||||
local tbl = {meta:get_string("label1"), " ", meta:get_string("label2"), " ", meta:get_string("label3"), " ", meta:get_string("label4")}
|
||||
local text = "< " .. table.concat(tbl, "\n< ")
|
||||
local texture = lcdlib.make_multiline_texture("default", text, 96, 96, 7, "top", "#000", 6)
|
||||
|
||||
if nvm.button[1] then
|
||||
texture = texture .. "^techage_smartline_button_4x_on1.png"
|
||||
end
|
||||
if nvm.button[2] then
|
||||
texture = texture .. "^techage_smartline_button_4x_on2.png"
|
||||
end
|
||||
if nvm.button[3] then
|
||||
texture = texture .. "^techage_smartline_button_4x_on3.png"
|
||||
end
|
||||
if nvm.button[4] then
|
||||
texture = texture .. "^techage_smartline_button_4x_on4.png"
|
||||
end
|
||||
objref:set_properties({ textures = {texture}, visual_size = {x=1, y=1} })
|
||||
end
|
||||
|
||||
local function switch_off(pos, num)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.button = nvm.button or {}
|
||||
nvm.button[num] = nil
|
||||
lcdlib.update_entities(pos)
|
||||
end
|
||||
|
||||
local function switch_on(pos, num)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.button = nvm.button or {}
|
||||
nvm.button[num] = true
|
||||
lcdlib.update_entities(pos)
|
||||
end
|
||||
|
||||
local lcd_box = {-8/16, -8/16, 7.75/16, 8/16, 8/16, 8/16}
|
||||
|
||||
minetest.register_node("techage:ta4_button_4x", {
|
||||
description = S("TA4 4x Button"),
|
||||
inventory_image = 'techage_smartline_button_4x.png',
|
||||
tiles = {'techage_smartline_button_4x.png'},
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
use_texture_alpha = "clip",
|
||||
sunlight_propagates = true,
|
||||
paramtype2 = "facedir",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = lcd_box,
|
||||
},
|
||||
light_source = 6,
|
||||
|
||||
display_entities = {
|
||||
["techage:display_entity"] = { depth = 0.48,
|
||||
on_display_update = button_update},
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local number = techage.add_node(pos, "techage:ta4_button_4x")
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("node_number", number)
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
meta:set_string("infotext", "TA4 4x Button " .. number)
|
||||
meta:set_string("type", "button")
|
||||
meta:set_string("label1", "B1")
|
||||
meta:set_string("label2", "B2")
|
||||
meta:set_string("label3", "B3")
|
||||
meta:set_string("label4", "B4")
|
||||
lcdlib.update_entities(pos)
|
||||
end,
|
||||
|
||||
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||
if clicker and clicker:is_player() then
|
||||
local playername = clicker:get_player_name()
|
||||
if minetest.is_protected(pos, playername) then
|
||||
return
|
||||
end
|
||||
-- Check node settings in addition
|
||||
local access = M(pos):get_string("access")
|
||||
local owner = M(pos):get_string("owner")
|
||||
if access == "private" and playername ~= owner then
|
||||
return
|
||||
end
|
||||
|
||||
local num = get_button_num(pos, clicker, pointed_thing)
|
||||
if num then
|
||||
local typ = M(pos):get_string("type")
|
||||
if typ == "switch" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.button = nvm.button or {}
|
||||
if nvm.button[num] then
|
||||
switch_off(pos, num)
|
||||
send_cmnd(pos, num, "off")
|
||||
else
|
||||
switch_on(pos, num)
|
||||
send_cmnd(pos, num, "on")
|
||||
end
|
||||
else
|
||||
switch_on(pos, num)
|
||||
send_cmnd(pos, num)
|
||||
minetest.after(0.5, switch_off, pos, num)
|
||||
end
|
||||
minetest.sound_play("techage_button", {
|
||||
pos = pos,
|
||||
gain = 0.5,
|
||||
max_hear_distance = 5,
|
||||
})
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
ta_after_formspec = function(pos, fields, playername)
|
||||
lcdlib.update_entities(pos)
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
end,
|
||||
|
||||
ta3_formspec = WRENCH_MENU,
|
||||
on_place = lcdlib.on_place,
|
||||
on_construct = lcdlib.on_construct,
|
||||
on_destruct = lcdlib.on_destruct,
|
||||
on_rotate = lcdlib.on_rotate,
|
||||
groups = {cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:ta4_button_4x",
|
||||
recipe = {
|
||||
{"", "techage:ta4_button_off", "techage:ta4_button_off"},
|
||||
{"", "techage:ta4_button_off", "techage:ta4_button_off"},
|
||||
{"", "", ""},
|
||||
},
|
||||
})
|
@ -86,8 +86,8 @@ local function on_timer(pos,elapsed)
|
||||
|
||||
if nvm.idx > #nvm.poll_numbers then
|
||||
nvm.idx = 1
|
||||
send_event(nvm, meta)
|
||||
if nvm.stored_state ~= nvm.common_state then
|
||||
send_event(nvm, meta)
|
||||
local own_number = meta:get_string("own_number")
|
||||
meta:set_string("infotext", S("TA4 State Collector").." "..own_number..': "'..lStates[nvm.common_state]..'"')
|
||||
nvm.stored_state = nvm.common_state
|
||||
|
@ -19,6 +19,33 @@ local NDEF = function(pos) return (minetest.registered_nodes[techage.get_node_lv
|
||||
|
||||
local logic = techage.logic
|
||||
local BLOCKING_TIME = 8 -- seconds
|
||||
local ON_TIME = 1
|
||||
|
||||
local WRENCH_MENU = {
|
||||
{
|
||||
type = "dropdown",
|
||||
choices = "1,2,4,6,8,12,16",
|
||||
name = "ontime",
|
||||
label = S("On Time") .. " [s]",
|
||||
tooltip = S("The time between the 'on' and 'off' commands."),
|
||||
default = "1",
|
||||
},
|
||||
{
|
||||
type = "dropdown",
|
||||
choices = "2,4,6,8,12,16,20",
|
||||
name = "blockingtime",
|
||||
label = S("Blocking Time") .. " [s]",
|
||||
tooltip = S("The time after the 'off' command\nuntil the next 'on' command is accepted."),
|
||||
default = "8",
|
||||
},
|
||||
{
|
||||
type = "items",
|
||||
name = "config",
|
||||
label = S("Configured Items"),
|
||||
tooltip = S("Items which generate an 'on' command.\nIf empty, all passed items generate an 'on' command."),
|
||||
size = 4,
|
||||
}
|
||||
}
|
||||
|
||||
local function switch_on(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
@ -30,8 +57,11 @@ local function switch_on(pos)
|
||||
else
|
||||
logic.swap_node(pos, "techage:ta4_detector_on")
|
||||
end
|
||||
logic.send_on(pos, M(pos), 1)
|
||||
mem.time = t + BLOCKING_TIME
|
||||
local meta = M(pos)
|
||||
local on_time = math.max(meta:get_int("ontime"), ON_TIME)
|
||||
local blocking_time = tonumber(meta:get_string("blockingtime")) or BLOCKING_TIME
|
||||
logic.send_on(pos, meta, on_time)
|
||||
mem.time = t + blocking_time + on_time
|
||||
end
|
||||
end
|
||||
|
||||
@ -48,12 +78,15 @@ end
|
||||
local function formspec(meta)
|
||||
local numbers = meta:get_string("numbers") or ""
|
||||
return "size[7.5,3]"..
|
||||
techage.wrench_image(7, -0.1) ..
|
||||
"field[0.5,1;7,1;numbers;"..S("Insert destination node number(s)")..";"..numbers.."]" ..
|
||||
"button_exit[2,2;3,1;exit;"..S("Save").."]"
|
||||
end
|
||||
|
||||
local function after_place_node(pos, placer)
|
||||
local meta = M(pos)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('cfg', 4)
|
||||
logic.after_place_node(pos, placer, "techage:ta3_detector_off", NDEF(pos).description)
|
||||
logic.infotext(meta, NDEF(pos).description)
|
||||
meta:set_string("formspec", formspec(meta))
|
||||
@ -97,6 +130,7 @@ minetest.register_node("techage:ta3_detector_off", {
|
||||
on_receive_fields = on_receive_fields,
|
||||
techage_set_numbers = techage_set_numbers,
|
||||
after_dig_node = after_dig_node,
|
||||
ta3_formspec = WRENCH_MENU,
|
||||
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype = "light",
|
||||
@ -124,6 +158,7 @@ minetest.register_node("techage:ta3_detector_on", {
|
||||
on_rotate = screwdriver.disallow,
|
||||
techage_set_numbers = techage_set_numbers,
|
||||
after_dig_node = after_dig_node,
|
||||
ta3_formspec = WRENCH_MENU,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=2, cracky=2, crumbly=2, not_in_creative_inventory=1},
|
||||
@ -148,6 +183,7 @@ minetest.register_node("techage:ta4_detector_off", {
|
||||
on_receive_fields = on_receive_fields,
|
||||
techage_set_numbers = techage_set_numbers,
|
||||
after_dig_node = after_dig_node,
|
||||
ta3_formspec = WRENCH_MENU,
|
||||
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype = "light",
|
||||
@ -175,6 +211,7 @@ minetest.register_node("techage:ta4_detector_on", {
|
||||
on_rotate = screwdriver.disallow,
|
||||
techage_set_numbers = techage_set_numbers,
|
||||
after_dig_node = after_dig_node,
|
||||
ta3_formspec = WRENCH_MENU,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=2, cracky=2, crumbly=2, not_in_creative_inventory=1},
|
||||
@ -204,7 +241,10 @@ minetest.register_craft({
|
||||
techage.register_node({"techage:ta3_detector_off", "techage:ta3_detector_on"}, {
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
if techage.safe_push_items(pos, in_dir, stack) then
|
||||
switch_on(pos)
|
||||
local inv = minetest.get_inventory({type = "node", pos = pos})
|
||||
if not inv or inv:is_empty("cfg") or inv:contains_item("cfg", ItemStack(stack:get_name())) then
|
||||
switch_on(pos)
|
||||
end
|
||||
return true
|
||||
end
|
||||
return false
|
||||
|
@ -230,7 +230,7 @@ minetest.register_node("techage:ta3_doorcontroller2", {
|
||||
local meta = M(pos)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('main', 16)
|
||||
logic.after_place_node(pos, placer, "techage:ta3_doorcontroller", S("TA3 Door Controller II"))
|
||||
logic.after_place_node(pos, placer, "techage:ta3_doorcontroller2", S("TA3 Door Controller II"))
|
||||
logic.infotext(meta, S("TA3 Door Controller II"))
|
||||
local nvm = techage.get_nvm(pos)
|
||||
meta:set_string("formspec", formspec1(nvm, meta))
|
||||
@ -321,7 +321,9 @@ minetest.register_node("techage:ta3_doorcontroller2", {
|
||||
return inv:is_empty("main")
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata)
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
local name = digger:get_player_name()
|
||||
unmark_all(name)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
end,
|
||||
|
||||
@ -423,3 +425,5 @@ for _, name in ipairs(ProtectorDoors) do
|
||||
logic.register_doorcontroller_nodes({name .. "_" .. postfix})
|
||||
end
|
||||
end
|
||||
|
||||
logic.SimpleNodes = RegisteredNodes
|
||||
|
@ -67,6 +67,15 @@ function techage.logic.send_on(pos, meta, time)
|
||||
return own_num == numbers
|
||||
end
|
||||
|
||||
function techage.logic.send_cmnd(pos, meta, cmnd, payload, time)
|
||||
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)
|
||||
end
|
||||
|
||||
function techage.logic.send_off(pos, meta)
|
||||
local own_num = meta:get_string("node_number") or ""
|
||||
local numbers = meta:get_string("numbers") or ""
|
||||
|
812
techage/logic/movecontroller.lua
Normal file
@ -0,0 +1,812 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2020-2021 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA4 Move Controller
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S2P = minetest.string_to_pos
|
||||
local S = techage.S
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Entity / Move / Attach / Detach
|
||||
-------------------------------------------------------------------------------
|
||||
local MIN_SPEED = 0.4
|
||||
local MAX_SPEED = 8
|
||||
|
||||
local function to_vector(s)
|
||||
local x,y,z = unpack(string.split(s, ","))
|
||||
if x and y and z then
|
||||
return {
|
||||
x=tonumber(x) or 0,
|
||||
y=tonumber(y) or 0,
|
||||
z=tonumber(z) or 0,
|
||||
}
|
||||
end
|
||||
return {x=0, y=0, z=0}
|
||||
end
|
||||
|
||||
-- Only the ID ist stored, not the object
|
||||
local function get_object_id(object)
|
||||
for id, entity in pairs(minetest.luaentities) do
|
||||
if entity.object == object then
|
||||
return id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- determine exact position of attached entities
|
||||
local function obj_pos(obj)
|
||||
local _, _, pos = obj:get_attach()
|
||||
pos = vector.divide(pos, 29)
|
||||
return vector.add(obj:get_pos(), pos)
|
||||
end
|
||||
|
||||
-- Check access conflicts with other mods
|
||||
local function lock_player(player)
|
||||
local meta = player:get_meta()
|
||||
if meta:get_int("player_physics_locked") == 0 then
|
||||
meta:set_int("player_physics_locked", 1)
|
||||
meta:set_string("player_physics_locked_by", "ta_movecontroller")
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function unlock_player(player)
|
||||
local meta = player:get_meta()
|
||||
if meta:get_int("player_physics_locked") == 1 then
|
||||
if meta:get_string("player_physics_locked_by") == "ta_movecontroller" then
|
||||
meta:set_int("player_physics_locked", 0)
|
||||
meta:set_string("player_physics_locked_by", "")
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function detach_player(player)
|
||||
local pos = obj_pos(player)
|
||||
player:set_detach()
|
||||
player:set_properties({visual_size = {x=1, y=1}})
|
||||
player:set_pos(pos)
|
||||
-- TODO: move to save position
|
||||
end
|
||||
|
||||
|
||||
-- Attach player/mob to given parent object (block)
|
||||
local function attach_single_object(parent, obj, dir)
|
||||
local self = parent:get_luaentity()
|
||||
local rot = obj:get_rotation()
|
||||
local res = obj:get_attach()
|
||||
if not res then
|
||||
local offs = table.copy(dir)
|
||||
dir = vector.multiply(dir, 29)
|
||||
obj:set_attach(parent, "", dir, rot, true)
|
||||
obj:set_properties({visual_size = {x=2.9, y=2.9}})
|
||||
if obj:is_player() then
|
||||
if lock_player(obj) then
|
||||
table.insert(self.players, {name = obj:get_player_name(), offs = offs})
|
||||
end
|
||||
else
|
||||
table.insert(self.entities, {objID = get_object_id(obj), offs = offs})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Attach all objects around to the parent object
|
||||
-- offs is the search/attach position offset
|
||||
local function attach_objects(pos, offs, parent)
|
||||
local pos1 = vector.add(pos, offs)
|
||||
for _, obj in pairs(minetest.get_objects_inside_radius(pos1, 0.9)) do
|
||||
local dir = vector.subtract(obj:get_pos(), pos)
|
||||
local entity = obj:get_luaentity()
|
||||
if entity then
|
||||
if entity.name == "__builtin:item" then -- dropped items
|
||||
--obj:set_attach(objref, "", {x=0, y=0, z=0}, {x=0, y=0, z=0}, true) -- hier kracht es
|
||||
elseif entity.name ~= "techage:move_item" then
|
||||
attach_single_object(parent, obj, dir)
|
||||
end
|
||||
elseif obj:is_player() then
|
||||
attach_single_object(parent, obj, dir)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Detach all attached objects from the parent object
|
||||
local function detach_objects(pos, self)
|
||||
for _, item in ipairs(self.entities or {}) do
|
||||
local entity = minetest.luaentities[item.objID]
|
||||
if entity then
|
||||
local obj = entity.object
|
||||
obj:set_detach()
|
||||
obj:set_properties({visual_size = {x=1, y=1}})
|
||||
local pos1 = vector.add(pos, item.offs)
|
||||
obj:set_pos(pos1)
|
||||
end
|
||||
end
|
||||
for _, item in ipairs(self.players or {}) do
|
||||
local obj = minetest.get_player_by_name(item.name)
|
||||
if obj then
|
||||
obj:set_detach()
|
||||
obj:set_properties({visual_size = {x=1, y=1}})
|
||||
local pos1 = vector.add(pos, item.offs)
|
||||
obj:set_pos(pos1)
|
||||
unlock_player(obj)
|
||||
end
|
||||
end
|
||||
self.entities = {}
|
||||
self.players = {}
|
||||
end
|
||||
|
||||
local function entity_to_node(pos, obj)
|
||||
local self = obj:get_luaentity()
|
||||
if self then
|
||||
local name = self.item or "air"
|
||||
local metadata = self.metadata or {}
|
||||
local rot = obj:get_rotation()
|
||||
detach_objects(pos, self)
|
||||
obj:remove()
|
||||
|
||||
pos = vector.round(pos)
|
||||
local dir = minetest.yaw_to_dir(rot.y or 0)
|
||||
local param2 = minetest.dir_to_facedir(dir) or 0
|
||||
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", "")
|
||||
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
|
||||
end
|
||||
end
|
||||
|
||||
local function node_to_entity(pos, handover)
|
||||
local meta = M(pos)
|
||||
local node, metadata
|
||||
|
||||
if meta:contains("ta_move_block") then
|
||||
node = minetest.deserialize(meta:get_string("ta_move_block"))
|
||||
metadata = {}
|
||||
meta:set_string("ta_move_block", "")
|
||||
else
|
||||
node = minetest.get_node(pos)
|
||||
meta:set_string("ta_move_block", "")
|
||||
metadata = meta:to_table()
|
||||
minetest.remove_node(pos)
|
||||
end
|
||||
local dir = minetest.facedir_to_dir(node.param2)
|
||||
local yaw = minetest.dir_to_yaw(dir)
|
||||
local obj = minetest.add_entity(pos, "techage:move_item")
|
||||
if obj then
|
||||
local self = obj:get_luaentity()
|
||||
obj:set_rotation({x=0, y=yaw, z=0})
|
||||
obj:set_properties({wield_item=node.name})
|
||||
obj:set_armor_groups({immortal=1})
|
||||
self.item = node.name
|
||||
self.metadata = metadata or {}
|
||||
self.handover = handover
|
||||
self.start_pos = table.copy(pos)
|
||||
return obj
|
||||
end
|
||||
end
|
||||
|
||||
local function capture_entity(pos)
|
||||
local l = minetest.get_objects_in_area(pos, pos)
|
||||
for _, obj in ipairs(l) do
|
||||
local self = obj:get_luaentity()
|
||||
if self and self.name == "techage:move_item" then
|
||||
return obj
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- move block direction
|
||||
local function determine_dir(pos1, pos2)
|
||||
local vdist = vector.subtract(pos2, pos1)
|
||||
local ndist = vector.length(vdist)
|
||||
return vector.divide(vdist, ndist)
|
||||
end
|
||||
|
||||
local function move_entity(obj, pos2, dir, max_speed)
|
||||
local self = obj:get_luaentity()
|
||||
self.max_speed = max_speed
|
||||
self.dest_pos = table.copy(pos2)
|
||||
self.dir = dir
|
||||
local acc = vector.multiply(dir, max_speed / 2)
|
||||
obj:set_acceleration(acc)
|
||||
end
|
||||
|
||||
-- Handover the entity to the next movecontroller
|
||||
local function handover_to(pos, self)
|
||||
local info = techage.get_node_info(self.handover)
|
||||
if info and info.name == "techage:ta4_movecontroller" then
|
||||
local mem = techage.get_mem(info.pos)
|
||||
if not mem.entities_are_there then
|
||||
mem.entities_are_there = true
|
||||
-- copy move direction
|
||||
--print("techage.get_nvm(pos).pos_2to1", techage.get_nvm(pos).pos_2to1)
|
||||
techage.get_nvm(info.pos).pos_2to1 = techage.get_nvm(pos).pos_2to1
|
||||
minetest.after(0.2, techage.send_single, "0", self.handover, "handover")
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_entity("techage:move_item", {
|
||||
initial_properties = {
|
||||
pointable = true,
|
||||
makes_footstep_sound = true,
|
||||
static_save = true,
|
||||
collide_with_objects = false,
|
||||
physical = false,
|
||||
visual = "wielditem",
|
||||
wield_item = "default:dirt",
|
||||
visual_size = {x=0.67, y=0.67, z=0.67},
|
||||
selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||
},
|
||||
|
||||
get_staticdata = function(self)
|
||||
return minetest.serialize({
|
||||
item = self.item,
|
||||
max_speed = self.max_speed,
|
||||
dest_pos = self.dest_pos,
|
||||
start_pos = self.start_pos,
|
||||
dir = self.dir,
|
||||
metadata = self.metadata,
|
||||
respawn = true,
|
||||
})
|
||||
end,
|
||||
|
||||
on_activate = function(self, staticdata)
|
||||
if staticdata then
|
||||
local tbl = minetest.deserialize(staticdata) or {}
|
||||
self.item = tbl.item or "air"
|
||||
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.dir = tbl.dir or {x=0, y=0, z=0}
|
||||
self.metadata = tbl.metadata or {}
|
||||
self.object:set_properties({wield_item = self.item})
|
||||
if tbl.respawn then
|
||||
entity_to_node(self.start_pos, self.object)
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
on_step = function(self, dtime, moveresult)
|
||||
if self.dest_pos then
|
||||
local obj = self.object
|
||||
local pos = obj:get_pos()
|
||||
local dist = vector.distance(pos, self.dest_pos)
|
||||
local speed = vector.length(obj:get_velocity())
|
||||
|
||||
-- Landing
|
||||
if dist < 0.05 then
|
||||
obj:move_to(self.dest_pos, true)
|
||||
obj:set_acceleration({x=0, y=0, z=0})
|
||||
obj:set_velocity({x=0, y=0, z=0})
|
||||
self.dest_pos = nil
|
||||
if not self.handover or not handover_to(pos, self) then
|
||||
minetest.after(0.5, entity_to_node, pos, obj)
|
||||
end
|
||||
self.ttl = 2
|
||||
return
|
||||
end
|
||||
|
||||
-- Braking or limit max speed
|
||||
if speed > (dist * 2) or speed > self.max_speed then
|
||||
local speed = math.min(speed, math.max(dist * 2, MIN_SPEED))
|
||||
local vel = vector.multiply(self.dir,speed)
|
||||
obj:set_velocity(vel)
|
||||
obj:set_acceleration({x=0, y=0, z=0})
|
||||
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
|
||||
end
|
||||
end,
|
||||
|
||||
})
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Marker / Record
|
||||
-------------------------------------------------------------------------------
|
||||
local MarkedNodes = {} -- t[player] = {{entity, pos},...}
|
||||
local CurrentPos -- to mark punched entities
|
||||
local SimpleNodes = techage.logic.SimpleNodes
|
||||
|
||||
local function is_valid_dest(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
local ndef = minetest.registered_nodes[node.name]
|
||||
if ndef and ndef.buildable_to then
|
||||
return true
|
||||
end
|
||||
if not M(pos):contains("ta_move_block") then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function is_simple_node(pos)
|
||||
-- special handling
|
||||
local name = minetest.get_node(pos).name
|
||||
if SimpleNodes[name] ~= nil then
|
||||
return SimpleNodes[name]
|
||||
end
|
||||
|
||||
local ndef = minetest.registered_nodes[name]
|
||||
if not ndef or name == "air" or name == "ignore" then return false end
|
||||
-- don't remove nodes with some intelligence or undiggable nodes
|
||||
if ndef.drop == "" then return false end
|
||||
if ndef.diggable == false then return false end
|
||||
if ndef.after_dig_node then return false end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local function table_add(tbl, offs)
|
||||
if not tbl or not offs then return end
|
||||
|
||||
local tbl2 = {}
|
||||
for _, v in ipairs(tbl) do
|
||||
tbl2[#tbl2 + 1] = vector.add(v, offs)
|
||||
end
|
||||
return tbl2
|
||||
end
|
||||
|
||||
local function unmark_position(name, pos)
|
||||
pos = vector.round(pos)
|
||||
for idx,item in ipairs(MarkedNodes[name] or {}) do
|
||||
if vector.equals(pos, item.pos) then
|
||||
item.entity:remove()
|
||||
table.remove(MarkedNodes[name], idx)
|
||||
CurrentPos = pos
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function unmark_all(name)
|
||||
for _,item in ipairs(MarkedNodes[name] or {}) do
|
||||
item.entity:remove()
|
||||
end
|
||||
MarkedNodes[name] = nil
|
||||
end
|
||||
|
||||
local function mark_position(name, pos)
|
||||
MarkedNodes[name] = MarkedNodes[name] or {}
|
||||
pos = vector.round(pos)
|
||||
if not CurrentPos or not vector.equals(pos, CurrentPos) then -- entity not punched?
|
||||
local entity = minetest.add_entity(pos, "techage:moveblock_marker")
|
||||
if entity ~= nil then
|
||||
entity:get_luaentity().player_name = name
|
||||
table.insert(MarkedNodes[name], {pos = pos, entity = entity})
|
||||
end
|
||||
CurrentPos = nil
|
||||
return true
|
||||
end
|
||||
CurrentPos = nil
|
||||
end
|
||||
|
||||
local function get_poslist(name)
|
||||
local idx = 0
|
||||
local lst = {}
|
||||
for _,item in ipairs(MarkedNodes[name] or {}) do
|
||||
table.insert(lst, item.pos)
|
||||
idx = idx + 1
|
||||
if idx >= 16 then break end
|
||||
end
|
||||
return lst
|
||||
end
|
||||
|
||||
minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing)
|
||||
if puncher and puncher:is_player() then
|
||||
local name = puncher:get_player_name()
|
||||
|
||||
if not MarkedNodes[name] then
|
||||
return
|
||||
end
|
||||
|
||||
mark_position(name, pointed_thing.under)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
minetest.register_entity(":techage:moveblock_marker", {
|
||||
initial_properties = {
|
||||
visual = "cube",
|
||||
textures = {
|
||||
"techage_cube_mark.png",
|
||||
"techage_cube_mark.png",
|
||||
"techage_cube_mark.png",
|
||||
"techage_cube_mark.png",
|
||||
"techage_cube_mark.png",
|
||||
"techage_cube_mark.png",
|
||||
},
|
||||
--use_texture_alpha = true,
|
||||
physical = false,
|
||||
visual_size = {x=1.1, y=1.1},
|
||||
collisionbox = {-0.55,-0.55,-0.55, 0.55,0.55,0.55},
|
||||
glow = 8,
|
||||
},
|
||||
on_step = function(self, dtime)
|
||||
self.ttl = (self.ttl or 2400) - 1
|
||||
if self.ttl <= 0 then
|
||||
local pos = self.object:get_pos()
|
||||
unmark_position(self.player_name, pos)
|
||||
end
|
||||
end,
|
||||
on_punch = function(self, hitter)
|
||||
local pos = self.object:get_pos()
|
||||
local name = hitter:get_player_name()
|
||||
if name == self.player_name then
|
||||
unmark_position(name, pos)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- TA4 Move Controller
|
||||
-------------------------------------------------------------------------------
|
||||
local WRENCH_MENU = {
|
||||
{
|
||||
type = "dropdown",
|
||||
choices = "0.5,1,2,4,6,8",
|
||||
name = "max_speed",
|
||||
label = S("Maximum Speed"),
|
||||
tooltip = S("Maximum speed for the moving block."),
|
||||
default = "8",
|
||||
},
|
||||
{
|
||||
type = "number",
|
||||
name = "handoverB",
|
||||
label = S("Handover to B"),
|
||||
tooltip = S("Number of the next movecontroller."),
|
||||
default = "",
|
||||
},
|
||||
{
|
||||
type = "number",
|
||||
name = "handoverA",
|
||||
label = S("Handover to A"),
|
||||
tooltip = S("Number of the previous movecontroller."),
|
||||
default = "",
|
||||
},
|
||||
{
|
||||
type = "float",
|
||||
name = "height",
|
||||
label = S("Move block height"),
|
||||
tooltip = S("Value in the range of 0.0 to 1.0"),
|
||||
default = "1.0",
|
||||
},
|
||||
}
|
||||
|
||||
local function formspec(nvm, meta)
|
||||
local status = meta:get_string("status")
|
||||
local distance = meta:contains("distance") and meta:get_string("distance") or "0,3,0"
|
||||
return "size[8,5]" ..
|
||||
default.gui_bg ..
|
||||
default.gui_bg_img ..
|
||||
default.gui_slots ..
|
||||
"box[0,-0.1;7.2,0.5;#c6e8ff]" ..
|
||||
"label[0.2,-0.1;" .. minetest.colorize( "#000000", S("TA4 Move Controller")) .. "]" ..
|
||||
techage.wrench_image(7.4, -0.05) ..
|
||||
"button[0.1,0.8;3.8,1;record;" .. S("Record") .. "]" ..
|
||||
"button[4.1,0.8;3.8,1;ready;" .. S("Done") .. "]" ..
|
||||
"field[0.4,2.5;3.8,1;distance;" .. S("Move distance (A to B)") .. ";" .. distance .. "]" ..
|
||||
"button[4.1,2.2;3.8,1;store;" .. S("Store") .. "]" ..
|
||||
"button[0.1,3.3;3.8,1;moveAB;" .. S("Move A-B") .. "]" ..
|
||||
"button[4.1,3.3;3.8,1;moveBA;" .. S("Move B-A") .. "]" ..
|
||||
"label[0.3,4.3;" .. status .. "]"
|
||||
end
|
||||
|
||||
local function move_node(pos, pos1, pos2, max_speed, handover, height)
|
||||
local meta = M(pos)
|
||||
local dir = determine_dir(pos1, pos2)
|
||||
local obj = node_to_entity(pos1, handover)
|
||||
local self = obj:get_luaentity()
|
||||
self.players = {}
|
||||
self.entities = {}
|
||||
|
||||
if obj then
|
||||
local offs = {x=0, y=height or 1, z=0}
|
||||
attach_objects(pos1, offs, obj)
|
||||
if dir.y == 0 then
|
||||
if (dir.x ~= 0 and dir.z == 0) or (dir.x == 0 and dir.z ~= 0) then
|
||||
attach_objects(pos1, dir, obj)
|
||||
end
|
||||
end
|
||||
move_entity(obj, pos2, dir, max_speed)
|
||||
end
|
||||
end
|
||||
|
||||
local function move_nodes(pos, lpos1, lpos2, handover)
|
||||
local meta = M(pos)
|
||||
local owner = meta:get_string("owner")
|
||||
local max_speed = meta:contains("max_speed") and meta:get_int("max_speed") or MAX_SPEED
|
||||
local height = meta:contains("height") and meta:get_float("height") or 1
|
||||
height = techage.in_range(height, 0, 1)
|
||||
|
||||
if #lpos1 == #lpos2 then
|
||||
for idx = 1, #lpos1 do
|
||||
local pos1 = lpos1[idx]
|
||||
local pos2 = lpos2[idx]
|
||||
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, pos1, pos2, max_speed, handover, height)
|
||||
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
|
||||
end
|
||||
else
|
||||
if minetest.is_protected(pos1, owner) then
|
||||
meta:set_string("status", S("Start position is protected"))
|
||||
else
|
||||
meta:set_string("status", S("Destination position is protected"))
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
else
|
||||
meta:set_string("status", S("Position list error"))
|
||||
return false
|
||||
end
|
||||
local info = techage.get_node_info(handover)
|
||||
if info and info.name == "techage:ta4_movecontroller" then
|
||||
local mem = techage.get_mem(info.pos)
|
||||
mem.num_entities = #lpos1
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function moveon_nodes(pos, lpos1, lpos2, handover)
|
||||
local meta = M(pos)
|
||||
local owner = meta:get_string("owner")
|
||||
local max_speed = meta:contains("max_speed") and meta:get_int("max_speed") or MAX_SPEED
|
||||
|
||||
if #lpos1 == #lpos2 then
|
||||
for idx = 1, #lpos1 do
|
||||
local pos1 = lpos1[idx]
|
||||
local pos2 = lpos2[idx]
|
||||
if not minetest.is_protected(pos1, owner) and not minetest.is_protected(pos2, owner) then
|
||||
if is_valid_dest(pos2) then
|
||||
local dir = determine_dir(pos1, pos2)
|
||||
local obj = capture_entity(pos1)
|
||||
if obj then
|
||||
obj:get_luaentity().handover = handover
|
||||
move_entity(obj, pos2, dir, max_speed)
|
||||
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
|
||||
end
|
||||
else
|
||||
if minetest.is_protected(pos1, owner) then
|
||||
meta:set_string("status", S("Start position is protected"))
|
||||
else
|
||||
meta:set_string("status", S("Destination position is protected"))
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
else
|
||||
meta:set_string("status", S("Position list error"))
|
||||
return false
|
||||
end
|
||||
local info = techage.get_node_info(handover)
|
||||
if info and info.name == "techage:ta4_movecontroller" then
|
||||
local mem = techage.get_mem(info.pos)
|
||||
mem.num_entities = #lpos1
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function move_to_other_pos(pos)
|
||||
local meta = M(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
|
||||
if nvm.pos_2to1 then
|
||||
local lpos1 = nvm.lpos1 or {}
|
||||
local lpos2 = nvm.lpos2 or {}
|
||||
nvm.pos_2to1 = false
|
||||
local handover = meta:contains("handoverA") and meta:get_string("handoverA")
|
||||
return move_nodes(pos, lpos2, lpos1, handover)
|
||||
else
|
||||
local lpos1 = nvm.lpos1 or {}
|
||||
local lpos2 = nvm.lpos2 or {}
|
||||
nvm.pos_2to1 = true
|
||||
local handover = meta:contains("handoverB") and meta:get_string("handoverB")
|
||||
return move_nodes(pos, lpos1, lpos2, handover)
|
||||
end
|
||||
end
|
||||
|
||||
local function takeover(pos)
|
||||
local meta = M(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.entities_are_there = nil
|
||||
|
||||
if nvm.pos_2to1 then
|
||||
local lpos1 = nvm.lpos1 or {}
|
||||
local lpos2 = nvm.lpos2 or {}
|
||||
nvm.pos_2to1 = false
|
||||
local handover = meta:contains("handoverA") and meta:get_string("handoverA")
|
||||
return moveon_nodes(pos, lpos2, lpos1, handover)
|
||||
else
|
||||
local lpos1 = nvm.lpos1 or {}
|
||||
local lpos2 = nvm.lpos2 or {}
|
||||
nvm.pos_2to1 = true
|
||||
local handover = meta:contains("handoverB") and meta:get_string("handoverB")
|
||||
return moveon_nodes(pos, lpos1, lpos2, handover)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("techage:ta4_movecontroller", {
|
||||
description = S("TA4 Move Controller"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta4.png^techage_frame_ta4_top.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4_top.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_movecontroller.png",
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
local meta = M(pos)
|
||||
techage.logic.after_place_node(pos, placer, "techage:ta4_movecontroller", S("TA4 Move Controller"))
|
||||
techage.logic.infotext(meta, S("TA4 Move Controller"))
|
||||
local nvm = techage.get_nvm(pos)
|
||||
meta:set_string("formspec", formspec(nvm, meta))
|
||||
end,
|
||||
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
local meta = M(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
|
||||
if fields.record then
|
||||
nvm.lpos1 = nil
|
||||
nvm.lpos2 = nil
|
||||
nvm.pos_2to1 = false
|
||||
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"))
|
||||
MarkedNodes[name] = {}
|
||||
meta:set_string("formspec", formspec(nvm, meta))
|
||||
elseif fields.ready then
|
||||
local name = player:get_player_name()
|
||||
local pos_list = get_poslist(name)
|
||||
local text = #pos_list.." "..S("block positions are stored.")
|
||||
meta:set_string("status", text)
|
||||
meta:set_string("distance", fields.distance)
|
||||
nvm.lpos1 = pos_list
|
||||
nvm.lpos2 = table_add(pos_list, to_vector(fields.distance))
|
||||
nvm.pos_2to1 = false
|
||||
unmark_all(name)
|
||||
meta:set_string("formspec", formspec(nvm, meta))
|
||||
elseif fields.store then
|
||||
local dist = to_vector(fields.distance)
|
||||
local l = math.hypot(dist.x, math.hypot(dist.y, dist.z))
|
||||
if l <= 100 then
|
||||
meta:set_string("distance", fields.distance)
|
||||
nvm.lpos2 = table_add(nvm.lpos1, to_vector(fields.distance))
|
||||
nvm.pos_2to1 = false
|
||||
else
|
||||
meta:set_string("status", S("Error: Distance > 100 m !!"))
|
||||
end
|
||||
meta:set_string("formspec", formspec(nvm, meta))
|
||||
elseif fields.moveAB then
|
||||
meta:set_string("status", "")
|
||||
nvm.pos_2to1 = false
|
||||
if move_to_other_pos(pos) then
|
||||
meta:set_string("formspec", formspec(nvm, meta))
|
||||
local name = player:get_player_name()
|
||||
MarkedNodes[name] = nil
|
||||
end
|
||||
elseif fields.moveBA then
|
||||
meta:set_string("status", "")
|
||||
nvm.pos_2to1 = true
|
||||
if move_to_other_pos(pos) then
|
||||
meta:set_string("formspec", formspec(nvm, meta))
|
||||
local name = player:get_player_name()
|
||||
MarkedNodes[name] = nil
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
local name = digger:get_player_name()
|
||||
unmark_all(name)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
end,
|
||||
|
||||
ta4_formspec = WRENCH_MENU,
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
local INFO = [[Commands: 'a2b', 'b2a', 'move']]
|
||||
|
||||
techage.register_node({"techage:ta4_movecontroller"}, {
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "info" then
|
||||
return INFO
|
||||
elseif topic == "a2b" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.pos_2to1 = false
|
||||
return move_to_other_pos(pos)
|
||||
elseif topic == "b2a" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.pos_2to1 = true
|
||||
return move_to_other_pos(pos)
|
||||
elseif topic == "move" then
|
||||
return move_to_other_pos(pos)
|
||||
elseif topic == "handover" then
|
||||
return takeover(pos)
|
||||
end
|
||||
return false
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:ta4_movecontroller",
|
||||
recipe = {
|
||||
{"default:steel_ingot", "dye:blue", "default:steel_ingot"},
|
||||
{"default:mese_crystal_fragment", "techage:ta4_wlanchip", "default:mese_crystal_fragment"},
|
||||
{"group:wood", "basic_materials:gear_steel", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
unlock_player(player)
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
if unlock_player(player) then
|
||||
detach_player(player)
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_dieplayer(function(player)
|
||||
if unlock_player(player) then
|
||||
detach_player(player)
|
||||
end
|
||||
end)
|
@ -103,7 +103,9 @@ techage.register_node({"techage:ta3_repeater"}, {
|
||||
return false
|
||||
else
|
||||
local numbers = M(pos):get_string("numbers") or ""
|
||||
techage.counting_start(M(pos):get_string("owner"))
|
||||
techage.send_multi(src, numbers, topic, payload)
|
||||
techage.counting_stop()
|
||||
end
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
|
@ -60,7 +60,7 @@ local function formspec_help()
|
||||
"label[0,1;Define a sequence of commands\nto control other machines.]"..
|
||||
"label[0,2.2;Numbers(s) are the node numbers,\nthe command shall sent to.]"..
|
||||
"label[0,3.4;The commands 'on'/'off' are used\n for machines and other nodes.]"..
|
||||
"label[0,4.6;Offset is the time to the\nnext line in seconds (1..999).]"..
|
||||
"label[0,4.6;Offset is the time to the\nnext line in seconds (0.2 to 999).]"..
|
||||
"label[0,5.8;If endless is set, the Sequencer\nrestarts again and again.]"..
|
||||
"label[0,7;The command ' ' does nothing,\nonly consuming the offset time.]"..
|
||||
"button[3,8;2,1;exit;close]"
|
||||
@ -106,6 +106,7 @@ local function check_rules(pos, elapsed)
|
||||
nvm.running = nvm.running or false
|
||||
nvm.index = nvm.index or 1
|
||||
nvm.endless = nvm.endless or false
|
||||
techage.counting_start(M(pos):get_string("owner"))
|
||||
while true do -- process all rules as long as offs == 0
|
||||
local rule = nvm.rules[nvm.index]
|
||||
local offs = tonumber(nvm.rules[nvm.index].offs or 1)
|
||||
@ -119,12 +120,15 @@ local function check_rules(pos, elapsed)
|
||||
if offs > 0 then
|
||||
-- we can't restart the timer within the function om_timer
|
||||
minetest.after(0, restart_timer, pos, offs)
|
||||
techage.counting_stop()
|
||||
return false
|
||||
end
|
||||
else
|
||||
techage.counting_stop()
|
||||
return stop_the_sequencer(pos)
|
||||
end
|
||||
end
|
||||
techage.counting_stop()
|
||||
return false
|
||||
end
|
||||
|
||||
|
318
techage/logic/sequencer2.lua
Normal file
@ -0,0 +1,318 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2017-2021 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA4 Sequencer
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local logic = techage.logic
|
||||
|
||||
local HELP = S("Syntax:\n") ..
|
||||
S("'[<num>] <command>'\n") ..
|
||||
S("\n") ..
|
||||
S("<num> is a number from 1 to 50000 and is\n") ..
|
||||
S("the timeslot when the command is executed.\n") ..
|
||||
S(" - 1 corresponds to 100 ms\n") ..
|
||||
S(" - 50000 corresponds to 4 game days\n") ..
|
||||
S("\n") ..
|
||||
S("<command> is one of the following:\n") ..
|
||||
S(" - 'send <node num> <cmnd>' (techage command)\n") ..
|
||||
S(" - 'goto <num>' (jump to another line)\n") ..
|
||||
S(" - 'stop' (stop the execution)\n") ..
|
||||
S("\n") ..
|
||||
S("Example:\n") ..
|
||||
" -- move controller commands\n" ..
|
||||
" [1] send 1234 a2b\n" ..
|
||||
" [30] send 1234 b2a\n" ..
|
||||
" [60] goto 1 -- keep going"
|
||||
|
||||
local function strsplit(text)
|
||||
text = text:gsub("\r\n", "\n")
|
||||
text = text:gsub("\r", "\n")
|
||||
return string.split(text, "\n", true)
|
||||
end
|
||||
|
||||
local function trim(s)
|
||||
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
||||
end
|
||||
|
||||
local function command(s)
|
||||
local num, cmd, pld = unpack(string.split(s, " ", false, 2))
|
||||
if not num or not cmd then
|
||||
return S("Invalid command!")
|
||||
end
|
||||
return {number = num, cmnd = cmd, payload = pld}
|
||||
end
|
||||
|
||||
local function add_error(text, line_num)
|
||||
local tbl = {}
|
||||
for idx, line in ipairs(strsplit(text)) do
|
||||
if idx == line_num and not string.find(line, '--<<== error') then
|
||||
tbl[#tbl+1] = line.." --<<== error"
|
||||
else
|
||||
tbl[#tbl+1] = line
|
||||
end
|
||||
end
|
||||
return table.concat(tbl, "\n")
|
||||
end
|
||||
|
||||
local function exception(tRes, line, s)
|
||||
if tRes then
|
||||
tRes.line = line
|
||||
tRes.error = s
|
||||
end
|
||||
end
|
||||
|
||||
local function compile(s, tRes)
|
||||
local tCode = {}
|
||||
local old_idx = 0
|
||||
local start_idx
|
||||
|
||||
for i, line in ipairs(strsplit(s)) do
|
||||
line = trim(line)
|
||||
line = string.split(line, "--", true, 1)[1] or ""
|
||||
if line ~= "" then
|
||||
local idx, cmnd1, cmnd2 = unpack(string.split(line, " ", false, 2))
|
||||
idx = tonumber(string.match(idx, "^%[(%d+)%]$"))
|
||||
if not idx then
|
||||
return exception(tRes, i, "Syntax error!")
|
||||
end
|
||||
if idx > 50000 then
|
||||
return exception(tRes, i, "Order error!")
|
||||
end
|
||||
if idx <= old_idx then
|
||||
return exception(tRes, i, "Order error!")
|
||||
end
|
||||
start_idx = start_idx or idx
|
||||
if old_idx ~= 0 and not tCode[old_idx].next_idx then
|
||||
tCode[old_idx].next_idx = idx
|
||||
end
|
||||
if cmnd1 == "send" then
|
||||
local res = command(cmnd2)
|
||||
if type(res) == "string" then
|
||||
return exception(tRes, i, res)
|
||||
end
|
||||
tCode[idx] = res
|
||||
elseif cmnd1 == "goto" then
|
||||
tCode[idx] = {next_idx = tonumber(cmnd2) or 1}
|
||||
elseif cmnd1 == "stop" then
|
||||
tCode[idx] = false
|
||||
elseif cmnd1 == nil then
|
||||
tCode[idx] = {}
|
||||
end
|
||||
old_idx = idx
|
||||
end
|
||||
end
|
||||
-- Returns:
|
||||
-- {
|
||||
-- start_idx = 1,
|
||||
-- tCode = {
|
||||
-- <idx> = {number = <number>, cmnd = <string>, payload = <data>, next_idx = <idx>},
|
||||
-- ...
|
||||
-- },
|
||||
-- }
|
||||
return {start_idx=start_idx, tCode=tCode}
|
||||
end
|
||||
|
||||
local function check_syntax(meta)
|
||||
local tRes = {}
|
||||
local res = compile(meta:get_string("text"), tRes)
|
||||
if not res then
|
||||
meta:set_string("err_msg", tRes.error)
|
||||
meta:set_string("text", add_error(meta:get_string("text"), tRes.line))
|
||||
return false
|
||||
else
|
||||
meta:set_string("err_msg", "")
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function formspec(nvm, meta)
|
||||
local text = meta:get_string("text")
|
||||
text = minetest.formspec_escape(text)
|
||||
local bttn = nvm.running and ("stop;" .. S("Stop")) or ("start;" .. S("Start"))
|
||||
local style = nvm.running and "style_type[textarea;font=mono;textcolor=#888888;border=false]" or
|
||||
"style_type[textarea;font=mono;textcolor=#FFFFFF;border=false]"
|
||||
local textarea = nvm.running and "textarea[0.3,0.2;10,8.3;;;"..text.."]" or
|
||||
"textarea[0.3,0.2;10,8.3;text;;"..text.."]"
|
||||
|
||||
return "size[10,8]" ..
|
||||
style ..
|
||||
"tabheader[0,0;tab;edit,help;1;;true]" ..
|
||||
"label[0.1,-0.2;" .. S("Commands") .. ":]" ..
|
||||
textarea ..
|
||||
"background[0.1,0.3;9.8,7.0;techage_form_mask.png]" ..
|
||||
"label[0.1,7.5;" .. meta:get_string("err_msg") .. "]" ..
|
||||
"button_exit[3.4,7.5;2.2,1;cancel;" .. S("Cancel") .. "]" ..
|
||||
"button[5.6,7.5;2.2,1;save;" .. S("Save") .. "]" ..
|
||||
"button[7.8,7.5;2.2,1;" .. bttn .. "]"
|
||||
end
|
||||
|
||||
local function formspec_help(meta)
|
||||
local text = "" --minetest.formspec_escape("hepl")
|
||||
return "size[10,8]"..
|
||||
"style_type[textarea;font=mono;textcolor=#FFFFFF;border=false]"..
|
||||
"tabheader[0,0;tab;edit,help;2;;true]"..
|
||||
"textarea[0.3,0.3;10,9;;" .. S("Help") .. ":;"..minetest.formspec_escape(HELP).."]" ..
|
||||
"background[0.1,0.3;9.8,8.0;techage_form_mask.png]"
|
||||
end
|
||||
|
||||
local function restart_timer(pos, time)
|
||||
local timer = minetest.get_node_timer(pos)
|
||||
if timer:is_started() then
|
||||
timer:stop()
|
||||
end
|
||||
timer:start(time / 10)
|
||||
end
|
||||
|
||||
local function node_timer(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if nvm.running then
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.code = mem.code or compile(M(pos):get_string("text"))
|
||||
if mem.code then
|
||||
mem.idx = mem.idx or mem.code.start_idx
|
||||
local code = mem.code.tCode[mem.idx]
|
||||
if code and code.cmnd then
|
||||
local src = M(pos):get_string("node_number")
|
||||
techage.counting_start(M(pos):get_string("owner"))
|
||||
techage.send_single(src, code.number, code.cmnd, code.payload)
|
||||
techage.counting_stop()
|
||||
end
|
||||
if code and code.next_idx then
|
||||
local offs = code.next_idx - mem.idx
|
||||
minetest.after(0, restart_timer, pos, math.max(offs, 1))
|
||||
mem.idx = code.next_idx
|
||||
else
|
||||
nvm.running = false
|
||||
local meta = M(pos)
|
||||
meta:set_string("formspec", formspec(nvm, meta))
|
||||
logic.infotext(meta, S("TA4 Sequencer"), S("stopped"))
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
local meta = M(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
nvm.running = nvm.running or false
|
||||
|
||||
print(1, dump(fields))
|
||||
if fields.stop then
|
||||
nvm.running = false
|
||||
minetest.get_node_timer(pos):stop()
|
||||
logic.infotext(meta, S("TA4 Sequencer"), S("stopped"))
|
||||
elseif not nvm.running then
|
||||
print(2)
|
||||
if fields.tab == "2" then
|
||||
print(3)
|
||||
meta:set_string("formspec", formspec_help(meta))
|
||||
return
|
||||
elseif fields.tab == "1" then
|
||||
meta:set_string("formspec", formspec(nvm, meta))
|
||||
return
|
||||
end
|
||||
|
||||
if fields.save then
|
||||
nvm.running = false
|
||||
meta:set_string("text", fields.text or "")
|
||||
mem.code = nil
|
||||
mem.idx = nil
|
||||
elseif fields.start then
|
||||
if check_syntax(meta) then
|
||||
nvm.running = true
|
||||
meta:set_string("text", fields.text or "")
|
||||
mem.code = nil
|
||||
mem.idx = nil
|
||||
minetest.get_node_timer(pos):start(0.5)
|
||||
logic.infotext(meta, S("TA4 Sequencer"), S("running"))
|
||||
end
|
||||
end
|
||||
end
|
||||
meta:set_string("formspec", formspec(nvm, meta))
|
||||
end
|
||||
|
||||
minetest.register_node("techage:ta4_sequencer", {
|
||||
description = S("TA4 Sequencer"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta4.png^techage_frame_ta4_top.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4_top.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_sequencer.png",
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = M(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
logic.after_place_node(pos, placer, "techage:ta4_sequencer", S("TA4 Sequencer"))
|
||||
logic.infotext(meta, S("TA4 Sequencer"), S("stopped"))
|
||||
nvm.running = false
|
||||
meta:set_string("formspec", formspec(nvm, meta))
|
||||
end,
|
||||
|
||||
on_receive_fields = on_receive_fields,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
techage.del_mem(pos)
|
||||
end,
|
||||
|
||||
on_timer = node_timer,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:ta4_sequencer",
|
||||
recipe = {
|
||||
{"default:steel_ingot", "dye:blue", "default:steel_ingot"},
|
||||
{"techage:ta4_ramchip", "default:mese_crystal", "techage:ta4_wlanchip"},
|
||||
{"techage:aluminum", "group:wood", "techage:aluminum"},
|
||||
},
|
||||
})
|
||||
|
||||
local INFO = [[Commands: 'goto <num>', 'stop']]
|
||||
|
||||
techage.register_node({"techage:ta4_sequencer"}, {
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if topic == "goto" and not nvm.running then
|
||||
local mem = techage.get_mem(pos)
|
||||
nvm.running = true
|
||||
mem.idx = tonumber(payload or 1) or 1
|
||||
restart_timer(pos, 0.1)
|
||||
logic.infotext(M(pos), S("TA4 Sequencer"), S("running"))
|
||||
elseif topic == "stop" then
|
||||
nvm.running = false
|
||||
minetest.get_node_timer(pos):stop()
|
||||
logic.infotext(M(pos), S("TA4 Sequencer"), S("stopped"))
|
||||
elseif topic == "info" then
|
||||
return INFO
|
||||
else
|
||||
return "unsupported"
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
@ -201,6 +201,7 @@ local function register_terminal(num, tiles, node_box, selection_box)
|
||||
meta:set_string("command", S("commands like: help"))
|
||||
meta:set_string("formspec", formspec2(meta))
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
meta:set_string("infotext", S("TA3 Terminal") .. " " .. number)
|
||||
end,
|
||||
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
|
@ -403,7 +403,8 @@ local function call_loop(pos, meta, elapsed)
|
||||
local code = Cache[number].code
|
||||
local res = safer_lua.run_loop(pos, elapsed, code, error)
|
||||
if res then
|
||||
t = minetest.get_us_time() - t
|
||||
-- Don't count thread changes
|
||||
t = math.min(minetest.get_us_time() - t, 1000)
|
||||
cpu = math.floor(((cpu * 20) + t) / 21)
|
||||
meta:set_int("cpu", cpu)
|
||||
meta:set_string("infotext", "Controller "..number..": running ("..cpu.."us)")
|
||||
|
@ -695,6 +695,7 @@ Detektoren scannen ihre Umgebung ab und senden ein `on`-Kommando, wenn das Gesuc
|
||||
Der Detektor ist eine spezieller Röhrenblock, der erkennt, wenn Items über die Röhre weitergegeben werden. Es muss dazu auf beiden Seiten mit der Röhre verbunden sein. Werden Items mit einem Schieber in den Detektor geschoben, gibt er diese automatisch weiter.
|
||||
Er sendet ein `on`, wenn ein Item erkannt wird, gefolgt von einem `off` eine Sekunde später.
|
||||
Danach werden weitere Kommando für 8 Sekunden blockiert.
|
||||
Die Wartezeit, sowie die Items, die ein Kommando auslösen sollen, können über das Gabelschlüssel-Menü konfiguriert werden.
|
||||
|
||||
|
||||
[ta3_detector|image]
|
||||
|
@ -690,6 +690,7 @@ Detectors scan their surroundings and send an `on` command when the search is re
|
||||
The detector is a special tube block that detects when items are passed on through the tube. To do this, it must be connected to tubes on both sides. If items are pushed into the detector with a pusher, they are automatically passed on.
|
||||
It sends an `on` when an item is recognized, followed by an `off` a second later.
|
||||
Then further commands are blocked for 8 seconds.
|
||||
The waiting time and the items that should trigger a command can be configured using the open-ended wrench menu.
|
||||
|
||||
|
||||
[ta3_detector|image]
|
||||
@ -810,7 +811,7 @@ The processing power is up to 8 times one item every 4 seconds.
|
||||
|
||||
### Techage Info Tool
|
||||
|
||||
The Techage Info Tool (wrench) has several functions. It shows the time, position, temperature and biome when an unknown block is clicked on.
|
||||
The Techage Info Tool (open-ended wrench) has several functions. It shows the time, position, temperature and biome when an unknown block is clicked on.
|
||||
If you click on a TechAge block with command interface, all available data will be shown (see also "Logic / switching blocks").
|
||||
|
||||
With Shift + right click an extended menu can be opened for some blocks. Depending on the block, further data can be called up or special settings can be made here. In the case of a generator, for example, the charging curve/switch-off can be programmed.
|
||||
|
@ -470,6 +470,12 @@ Beim TA4 Taster/Schalter hat sich nur das Aussehen geändert. Die Funktionalitä
|
||||
|
||||
[ta4_button|image]
|
||||
|
||||
### TA4 4x Taster / 4x Button
|
||||
|
||||
Dieser Block hat vier Taster, die über das Schraubenschlüssel-Menü individuell konfiguriert werden können. Für jeden Taster kann die Beschriftung und die Zielblockadresse konfiguriert werden. Zusätzlich kann für jeden Taster das Kommando konfiguriert werden, welches gesendet werden soll.
|
||||
|
||||
[ta4_button_4x|image]
|
||||
|
||||
### TA4 Spieler Detektor / Player Detector
|
||||
|
||||
Beim TA4 Spieler Detektor hat sich nur das Aussehen geändert. Die Funktionalität ist gleich wie beim TA3 Spieler Detektor.
|
||||
@ -489,6 +495,60 @@ Diesen Zähler kann man über das Kommando 'count' abfragen und über 'reset' zu
|
||||
|
||||
[ta4_detector|image]
|
||||
|
||||
### TA4 Move Controller
|
||||
|
||||
Der TA4 Move Controller ist ähnlich zum "Door Controller 2", aber die ausgewählten Blöcke werden nicht entfernt, sondern können bewegt werden.
|
||||
Da die bewegten Blöcke Spieler und Mobs mitnehmen können, die auf dem Block stehen, können damit Fahrstühle und ähnliche Transportsysteme gebaut werden.
|
||||
|
||||
Anleitung:
|
||||
|
||||
- Controller setzen und die Blöcke, die bewegt werden sollen, über das Menü an-trainieren (Es können bis zu 16 Blöcke an-trainiert werden)
|
||||
- die "Flugstrecke" muss über eine x,y,z Angabe (relativ) eingegeben werden (die maximale Distanz beträgt 100 m)
|
||||
- mit den Menü-Tasten "Bewege A-B" sowie "Bewege B-A" kann die Bewegung getestet werden
|
||||
- man kann auch durch Wände oder andere Blöcke fliegen
|
||||
- auch die Zielposition für die Blöcke kann belegt sein. Die Blöcke werden in diesem Falle "unsichtbar" gespeichert. Dies ist für Schiebetüren und ähnliches gedacht
|
||||
- Über das Gabelschlüssel-Menü kann im Controller auch ein "handover" programmiert werden. Durch Eingabe einer Blocknummer werden die Blöcke dann an den nächsten Move Controller übergeben. So lassen sich auch zusammenhängende Bewegungen über mehrere Move Controller realisieren.
|
||||
|
||||
Der Move Controller unterstützt folgende techage Kommandos:
|
||||
|
||||
- `a2b` Bewege Block von A nach B
|
||||
- `b2a` Bewege Block von B nach A
|
||||
- `move` Bewege Block auf die andere Seite
|
||||
|
||||
[ta4_movecontroller|image]
|
||||
|
||||
|
||||
### TA4 Sequenzer
|
||||
|
||||
über den TA4 Sequenzer können ganze Abläufe programmiert werden. Hier ein Beispiel:
|
||||
|
||||
```
|
||||
-- this is a comment
|
||||
[1] send 1234 a2b
|
||||
[30] send 1234 b2a
|
||||
[60] goto 1
|
||||
```
|
||||
|
||||
- Jede Zeile beginnt mit einem Nummer, welche einem Zeitpunkt entspricht `[<num>]`
|
||||
- Für Zeitpunkte sind Werte von 1 bis 50000 zulässig
|
||||
- 1 entspricht 100 ms, 50000 entspricht in etwa 4 Spieltagen
|
||||
- Leerzeilen oder Kommentare sind erlaubt (`-- comment`)
|
||||
- Mit `send <num> <command> <data>` kann man ein Kommando an einen Block senden
|
||||
- Mit `goto <num>` kann man an eine andere Zeile/Zeitpunkt springen
|
||||
- Mit `stop` kann man den Sequenzer verzögert stoppen, so dass er kein neues Kommando
|
||||
von einem Taster oder anderem Block annimmt (um eine Bewegung abzuschließen)
|
||||
Ohne `stop` geht der Sequenzer sofort nach dem letzten Kommando in den stopped Modus.
|
||||
|
||||
Der TA4 Sequenzer unterstützt folgende techage Kommandos:
|
||||
|
||||
- `goto <num>` Zu einer Kommandozeile springen und damit den Sequenzer starten
|
||||
- `stop` Den Sequenzer anhalten
|
||||
|
||||
Das `goto` Kommando wird nur angenommen, wenn der Sequenzer gestoppt ist.
|
||||
|
||||
[ta4_sequencer|image]
|
||||
|
||||
|
||||
|
||||
## TA4 Lampen
|
||||
|
||||
|
@ -463,6 +463,12 @@ Only the appearance of the TA4 button/switch has changed. The functionality is t
|
||||
|
||||
[ta4_button|image]
|
||||
|
||||
### TA4 4x Button
|
||||
|
||||
This block has four buttons that can be individually configured using the wrench menu. The labeling and the target block address can be configured for each button. In addition, the command that is to be sent can be configured for each button.
|
||||
|
||||
[ta4_button_4x|image]
|
||||
|
||||
### TA4 Player Detector
|
||||
|
||||
Only the appearance of the TA4 player detector has changed. The functionality is the same as with the TA3 player detector.
|
||||
@ -482,6 +488,60 @@ This counter can be queried with the 'count' command and reset with 'reset'.
|
||||
|
||||
[ta4_detector|image]
|
||||
|
||||
### TA4 Move Controller
|
||||
|
||||
The TA4 Move Controller is similar to "Door Controller 2", but the selected blocks are not removed, but can be moved.
|
||||
Since the moving blocks can take players and mobs standing on the block with them, elevators and similar transport systems can be built with them.
|
||||
|
||||
Instructions:
|
||||
|
||||
- Set the controller and train the blocks to be moved via the menu (up to 16 blocks can be trained)
|
||||
- the "flight route" must be entered via an x, y, z specification (relative) (the maximum distance is 100 m)
|
||||
- The movement can be tested with the menu buttons "Move A-B" and "Move B-A"
|
||||
- you can also fly through walls or other blocks
|
||||
- The target position for the blocks can also be occupied. In this case, the blocks are saved "invisibly". This is intended for sliding doors and the like
|
||||
- A "handover" can also be programmed in the controller via the open-ended wrench menu. By entering a block number, the blocks are then transferred to the next move controller. In this way, connected movements can also be implemented using several Move Controllers.
|
||||
|
||||
The Move Controller supports the following techage commands:
|
||||
|
||||
- `a2b` Move block from A to B.
|
||||
- `b2a` Move block from B to A.
|
||||
- `move` Move block to the other side
|
||||
|
||||
[ta4_movecontroller|image]
|
||||
|
||||
### TA4 Sequencer
|
||||
|
||||
Entire processes can be programmed using the TA4 sequencer. Here's an example:
|
||||
|
||||
```
|
||||
-- this is a comment
|
||||
[1] send 1234 a2b
|
||||
[30] send 1234 b2a
|
||||
[60] goto 1
|
||||
```
|
||||
|
||||
- Each line begins with a number which corresponds to a point in time `[<num>]`
|
||||
- Values from 1 to 50000 are permitted for times
|
||||
- 1 corresponds to 100 ms, 50000 corresponds to about 4 game days
|
||||
- Empty lines or comments are allowed (`-- comment`)
|
||||
- With `send <num> <command> <data>` you can send a command to a block
|
||||
- With `goto <num>` you can jump to another line / point in time
|
||||
- With `stop` you can stop the sequencer with a delay so that it does not receive a new command
|
||||
accepts from a button or other block (to complete a movement)
|
||||
Without `stop`, the sequencer goes into stopped mode immediately after the last command.
|
||||
|
||||
The TA4 sequencer supports the following techage commands:
|
||||
|
||||
- `goto <num>` Jump to a command line and start the sequencer
|
||||
- `stop` Stop the sequencer
|
||||
|
||||
The `goto` command is only accepted when the sequencer is stopped.
|
||||
|
||||
[ta4_sequencer|image]
|
||||
|
||||
|
||||
|
||||
|
||||
## TA4 Lamps
|
||||
|
||||
|
@ -182,9 +182,12 @@
|
||||
- [TA4 Lua Controller Terminal](./manual_ta4_DE.md#ta4-lua-controller-terminal)
|
||||
- [TA4 Logik-/Schalt-Module](./manual_ta4_DE.md#ta4-logik-schalt-module)
|
||||
- [TA4 Taster/Schalter / Button/Switch](./manual_ta4_DE.md#ta4-tasterschalter--buttonswitch)
|
||||
- [TA4 4x Taster / 4x Button](./manual_ta4_DE.md#ta4-4x-taster--4x-button)
|
||||
- [TA4 Spieler Detektor / Player Detector](./manual_ta4_DE.md#ta4-spieler-detektor--player-detector)
|
||||
- [TA4 Zustandssammler / State Collector](./manual_ta4_DE.md#ta4-zustandssammler--state-collector)
|
||||
- [TA4 Detektor / Detector](./manual_ta4_DE.md#ta4-detektor--detector)
|
||||
- [TA4 Move Controller](./manual_ta4_DE.md#ta4-move-controller)
|
||||
- [TA4 Sequenzer](./manual_ta4_DE.md#ta4-sequenzer)
|
||||
- [TA4 Lampen](./manual_ta4_DE.md#ta4-lampen)
|
||||
- [TA4 LED Pflanzenlampe / TA4 LED Grow Light](./manual_ta4_DE.md#ta4-led-pflanzenlampe--ta4-led-grow-light)
|
||||
- [TA4 LED Straßenlampe / TA4 LED Street Lamp](./manual_ta4_DE.md#ta4-led-straßenlampe--ta4-led-street-lamp)
|
||||
|
@ -182,9 +182,12 @@
|
||||
- [TA4 Lua Controller Terminal](./manual_ta4_EN.md#ta4-lua-controller-terminal)
|
||||
- [TA4 Logic/Switching Modules](./manual_ta4_EN.md#ta4-logicswitching-modules)
|
||||
- [TA4 Button/Switch](./manual_ta4_EN.md#ta4-buttonswitch)
|
||||
- [TA4 4x Button](./manual_ta4_EN.md#ta4-4x-button)
|
||||
- [TA4 Player Detector](./manual_ta4_EN.md#ta4-player-detector)
|
||||
- [TA4 State Collector](./manual_ta4_EN.md#ta4-state-collector)
|
||||
- [TA4 Detector](./manual_ta4_EN.md#ta4-detector)
|
||||
- [TA4 Move Controller](./manual_ta4_EN.md#ta4-move-controller)
|
||||
- [TA4 Sequencer](./manual_ta4_EN.md#ta4-sequencer)
|
||||
- [TA4 Lamps](./manual_ta4_EN.md#ta4-lamps)
|
||||
- [TA4 LED Grow Light](./manual_ta4_EN.md#ta4-led-grow-light)
|
||||
- [TA4 Street Lamp](./manual_ta4_EN.md#ta4-street-lamp)
|
||||
|
@ -253,6 +253,12 @@ minetest.register_node("techage:oilexplorer", {
|
||||
end,
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
techage.unmark_region(digger:get_player_name())
|
||||
local xpos = (math.floor(pos.x / 16) * 16)
|
||||
local ypos = (math.floor(pos.y / 16) * 16)
|
||||
local zpos = (math.floor(pos.z / 16) * 16)
|
||||
local pos1 = {x=xpos, y=ypos, z=zpos}
|
||||
local pos2 = {x=xpos+15, y=ypos+15, z=zpos+15}
|
||||
techage.mark_region(digger:get_player_name(), pos1, pos2)
|
||||
end,
|
||||
is_ground_content = false,
|
||||
groups = {snappy=2,cracky=2,oddly_breakable_by_hand=2},
|
||||
|
@ -178,7 +178,7 @@ minetest.register_craft({
|
||||
})
|
||||
|
||||
techage.ElectricCable = Cable
|
||||
techage.ELE1_MAX_CABLE_LENGTH = ELE1_MAX_CABLE_LENGTH
|
||||
techage.ELE1_MAX_CABLE_LENGTH = ELE1_MAX_CABLE_LENGHT
|
||||
|
||||
|
||||
for idx, color in ipairs({ "white", "grey", "black", "brown", "yellow", "red", "dark_green", "blue" }) do
|
||||
|
@ -165,6 +165,11 @@ end
|
||||
-------------------------------------------------------------------------------
|
||||
-- API formspec functions
|
||||
-------------------------------------------------------------------------------
|
||||
function techage.wrench_image(x, y)
|
||||
return "image["..x.."," .. y .. ";0.5,0.5;techage_inv_wrench.png]" ..
|
||||
"tooltip["..x.."," .. y .. ";0.5,0.5;" .. S("Block has a wrench menu") .. ";#0C3D32;#FFFFFF]"
|
||||
end
|
||||
|
||||
function techage.storage_formspec(self, pos, nvm, label, netw_data, curr_load, max_load)
|
||||
return "size[6.3,4]" ..
|
||||
default.gui_bg ..
|
||||
|
@ -26,3 +26,7 @@ techage_use_marshal (use lua-marshal as serialize/deserialize functions) bool fa
|
||||
# Use the external library 'lsqlite3' for for faster storing of data.
|
||||
# See also 'README.md'.
|
||||
techage_use_sqlite (use sqlite database) bool false
|
||||
|
||||
# To reduce the server CPU load, the number of sent techage commands
|
||||
# per player and minute can be limited.
|
||||
techage_command_limit (Max. number of commands sent per minute) int 1200
|
@ -130,6 +130,7 @@ end
|
||||
local function after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||
local outdir = tonumber(oldmetadata.fields.outdir or 0)
|
||||
Cable:after_dig_node(pos, {outdir})
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
techage.del_mem(pos)
|
||||
end
|
||||
|
||||
|
BIN
techage/textures/techage_appl_movecontroller.png
Normal file
After Width: | Height: | Size: 642 B |
BIN
techage/textures/techage_inv_wrench.png
Normal file
After Width: | Height: | Size: 172 B |
BIN
techage/textures/techage_smartline_button_4x.png
Normal file
After Width: | Height: | Size: 180 B |
BIN
techage/textures/techage_smartline_button_4x_on1.png
Normal file
After Width: | Height: | Size: 107 B |
BIN
techage/textures/techage_smartline_button_4x_on2.png
Normal file
After Width: | Height: | Size: 107 B |
BIN
techage/textures/techage_smartline_button_4x_on3.png
Normal file
After Width: | Height: | Size: 107 B |
BIN
techage/textures/techage_smartline_button_4x_on4.png
Normal file
After Width: | Height: | Size: 107 B |
@ -76,7 +76,7 @@ local function read_state(itemstack, user, pointed_thing)
|
||||
if ndef and ndef.description then
|
||||
local info = techage.send_single("0", number, "info", nil)
|
||||
if info and info ~= "" and info ~= "unsupported" then
|
||||
info = dump(info)
|
||||
info = tostring(info)
|
||||
minetest.chat_send_player(user:get_player_name(), ndef.description.." "..number..":\n"..info.." ")
|
||||
end
|
||||
local state = techage.send_single("0", number, "state", nil)
|
||||
@ -136,6 +136,16 @@ end
|
||||
local context = {}
|
||||
|
||||
local function settings_menu(pos, playername)
|
||||
if minetest.is_protected(pos, playername) then
|
||||
return
|
||||
end
|
||||
-- Check node settings in addition
|
||||
local access = M(pos):get_string("access")
|
||||
local owner = M(pos):get_string("owner")
|
||||
if access == "private" and playername ~= owner then
|
||||
return
|
||||
end
|
||||
|
||||
local number = techage.get_node_number(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
local ndef = minetest.registered_nodes[node.name]
|
||||
@ -143,14 +153,15 @@ local function settings_menu(pos, playername)
|
||||
|
||||
context[playername] = pos
|
||||
if form_def then
|
||||
minetest.show_formspec(playername, "techage:ta_formspec", menu.generate_formspec(pos, ndef, form_def))
|
||||
minetest.show_formspec(playername, "techage:ta_formspec",
|
||||
menu.generate_formspec(pos, ndef, form_def, playername))
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname ~= "techage:ta_formspec" then
|
||||
return false
|
||||
end
|
||||
if formname ~= "techage:ta_formspec" then
|
||||
return false
|
||||
end
|
||||
|
||||
local playername = player:get_player_name()
|
||||
local pos = context[playername]
|
||||
@ -162,11 +173,15 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
local form_def = ndef and (ndef.ta3_formspec or ndef.ta4_formspec)
|
||||
|
||||
if form_def then
|
||||
if menu.eval_input(pos, ndef, form_def, fields) then
|
||||
if menu.eval_input(pos, form_def, fields, playername) then
|
||||
--context[playername] = pos
|
||||
minetest.after(0.2, function()
|
||||
minetest.show_formspec(playername, "techage:ta_formspec", menu.generate_formspec(pos, ndef, form_def))
|
||||
minetest.show_formspec(playername, "techage:ta_formspec",
|
||||
menu.generate_formspec(pos, ndef, form_def, playername))
|
||||
end)
|
||||
if ndef.ta_after_formspec then
|
||||
ndef.ta_after_formspec(pos, fields, playername)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -22,10 +22,25 @@ local function index(list, x)
|
||||
return nil
|
||||
end
|
||||
|
||||
local function allow_put(inv, listname, index, stack, player)
|
||||
local list = inv:get_list(listname)
|
||||
stack:set_count(1)
|
||||
inv:set_stack(listname, index, stack)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function allow_take(inv, listname, index, stack, player)
|
||||
local list = inv:get_list(listname)
|
||||
stack:set_count(0)
|
||||
inv:set_stack(listname, index, stack)
|
||||
return 0
|
||||
end
|
||||
|
||||
|
||||
-- generate the formspec string to be placed into a container frame
|
||||
local function generate_formspec_substring(pos, meta, form_def)
|
||||
local function generate_formspec_substring(pos, meta, form_def, player_name)
|
||||
local tbl = {}
|
||||
local player_inv_needed = false
|
||||
if meta and form_def then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
|
||||
@ -97,6 +112,9 @@ local function generate_formspec_substring(pos, meta, form_def)
|
||||
local idx = index(l, val) or 1
|
||||
tbl[#tbl+1] = "dropdown[4.72," .. (offs) .. ";5.5,1.4;" .. elem.name .. ";" .. elem.choices .. ";" .. idx .. "]"
|
||||
end
|
||||
elseif elem.type == "items" then
|
||||
tbl[#tbl+1] = "list[detached:" .. minetest.formspec_escape(player_name) .. "_techage_wrench_menu;cfg;4.75," .. offs .. ";" .. elem.size .. ",1;]"
|
||||
player_inv_needed = true
|
||||
end
|
||||
end
|
||||
if nvm.running or techage.is_running(nvm) then
|
||||
@ -104,17 +122,18 @@ local function generate_formspec_substring(pos, meta, form_def)
|
||||
tbl[#tbl+1] = "label[0," .. offs .. ";" .. S("Note: You can't change any values while the block is running!") .. "]"
|
||||
end
|
||||
end
|
||||
return table.concat(tbl, "")
|
||||
|
||||
return player_inv_needed, table.concat(tbl, "")
|
||||
end
|
||||
|
||||
local function value_check(elem, value)
|
||||
if elem.check then
|
||||
return elem.check(value)
|
||||
end
|
||||
return true
|
||||
return value ~= nil
|
||||
end
|
||||
|
||||
local function evaluate_data(pos, meta, form_def, fields)
|
||||
local function evaluate_data(pos, meta, form_def, fields, player_name)
|
||||
local res = true
|
||||
|
||||
if meta and form_def then
|
||||
@ -125,7 +144,9 @@ local function evaluate_data(pos, meta, form_def, fields)
|
||||
for idx,elem in ipairs(form_def) do
|
||||
if elem.type == "number" then
|
||||
if fields[elem.name] then
|
||||
if fields[elem.name]:find("^[%d ]+$") then
|
||||
if fields[elem.name] == "" then
|
||||
meta:set_string(elem.name, "")
|
||||
elseif fields[elem.name]:find("^[%d ]+$") then
|
||||
local val = tonumber(fields[elem.name])
|
||||
if value_check(elem, val) then
|
||||
meta:set_int(elem.name, val)
|
||||
@ -139,14 +160,18 @@ local function evaluate_data(pos, meta, form_def, fields)
|
||||
end
|
||||
elseif elem.type == "numbers" then
|
||||
if fields[elem.name] then
|
||||
if fields[elem.name]:find("^[%d ]+$") and value_check(elem, fields[elem.name]) then
|
||||
if fields[elem.name] == "" then
|
||||
meta:set_string(elem.name, "")
|
||||
elseif fields[elem.name]:find("^[%d ]+$") and value_check(elem, fields[elem.name]) then
|
||||
meta:set_string(elem.name, fields[elem.name])
|
||||
else
|
||||
res = false
|
||||
end
|
||||
end
|
||||
elseif elem.type == "float" then
|
||||
if fields[elem.name] then
|
||||
if fields[elem.name] == ""then
|
||||
meta:set_string(elem.name, "")
|
||||
elseif fields[elem.name] then
|
||||
local val = tonumber(fields[elem.name])
|
||||
if val and value_check(elem, val) then
|
||||
meta:set_string(elem.name, val)
|
||||
@ -155,7 +180,9 @@ local function evaluate_data(pos, meta, form_def, fields)
|
||||
end
|
||||
end
|
||||
elseif elem.type == "ascii" then
|
||||
if fields[elem.name] then
|
||||
if fields[elem.name] == ""then
|
||||
meta:set_string(elem.name, "")
|
||||
elseif fields[elem.name] then
|
||||
if value_check(elem, fields[elem.name]) then
|
||||
meta:set_string(elem.name, fields[elem.name])
|
||||
else
|
||||
@ -166,44 +193,93 @@ local function evaluate_data(pos, meta, form_def, fields)
|
||||
if fields[elem.name] ~= nil then
|
||||
meta:set_string(elem.name, fields[elem.name])
|
||||
end
|
||||
elseif elem.type == "items" then
|
||||
local inv_name = minetest.formspec_escape(player_name) .. "_techage_wrench_menu"
|
||||
local dinv = minetest.get_inventory({type = "detached", name = inv_name})
|
||||
local ninv = minetest.get_inventory({type = "node", pos = pos})
|
||||
if dinv and ninv then
|
||||
for i = 1, ninv:get_size("cfg") do
|
||||
ninv:set_stack("cfg", i, dinv:get_stack("cfg", i))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
function menu.generate_formspec(pos, ndef, form_def)
|
||||
function menu.generate_formspec(pos, ndef, form_def, player_name)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local number = techage.get_node_number(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.star = ((mem.star or 0) + 1) % 2
|
||||
local star = mem.star == 1 and "*" or ""
|
||||
local inv_name = minetest.formspec_escape(player_name) .. "_techage_wrench_menu"
|
||||
minetest.create_detached_inventory(inv_name, {
|
||||
allow_put = allow_put,
|
||||
allow_take = allow_take})
|
||||
local dinv = minetest.get_inventory({type = "detached", name = inv_name})
|
||||
local ninv = minetest.get_inventory({type = "node", pos = pos})
|
||||
if dinv and ninv then
|
||||
dinv:set_size('cfg', ninv:get_size("cfg"))
|
||||
for i = 1, ninv:get_size("cfg") do
|
||||
dinv:set_stack("cfg", i, ninv:get_stack("cfg", i))
|
||||
end
|
||||
end
|
||||
|
||||
if meta and number and ndef and form_def then
|
||||
local title = ndef.description .. " (" .. number .. ")"
|
||||
local player_inv_needed, text = generate_formspec_substring(pos, meta, form_def, player_name)
|
||||
local buttons
|
||||
|
||||
return "size[10,9]" ..
|
||||
default.gui_bg ..
|
||||
default.gui_bg_img ..
|
||||
default.gui_slots ..
|
||||
"box[0,-0.1;9.8,0.5;#c6e8ff]" ..
|
||||
"label[0.2,-0.1;" .. minetest.colorize( "#000000", title) .. "]" ..
|
||||
"label[9.5,-0.1;" .. minetest.colorize( "#000000", star) .. "]" ..
|
||||
"container[0,1]" ..
|
||||
generate_formspec_substring(pos, meta, form_def) ..
|
||||
"container_end[]" ..
|
||||
"button[0.5,8.4;3,1;refresh;" .. S("Refresh") .. "]" ..
|
||||
"button_exit[3.5,8.4;3,1;cancel;" .. S("Cancel") .. "]" ..
|
||||
"button[6.5,8.4;3,1;save;" .. S("Save") .. "]"
|
||||
if player_inv_needed then
|
||||
buttons = "button[0.5,6.2;3,1;refresh;" .. S("Refresh") .. "]" ..
|
||||
"button_exit[3.5,6.2;3,1;cancel;" .. S("Cancel") .. "]" ..
|
||||
"button[6.5,6.2;3,1;save;" .. S("Save") .. "]" ..
|
||||
"list[current_player;main;1,7.2;8,2;]"
|
||||
else
|
||||
buttons = "button[0.5,8.4;3,1;refresh;" .. S("Refresh") .. "]" ..
|
||||
"button_exit[3.5,8.4;3,1;cancel;" .. S("Cancel") .. "]" ..
|
||||
"button[6.5,8.4;3,1;save;" .. S("Save") .. "]"
|
||||
end
|
||||
|
||||
if #form_def > 8 then
|
||||
local size = (#form_def * 10) - 60
|
||||
return "size[10,9]" ..
|
||||
default.gui_bg ..
|
||||
default.gui_bg_img ..
|
||||
default.gui_slots ..
|
||||
"box[0,-0.1;9.8,0.5;#c6e8ff]" ..
|
||||
"label[0.2,-0.1;" .. minetest.colorize( "#000000", title) .. "]" ..
|
||||
"label[9.5,-0.1;" .. minetest.colorize( "#000000", star) .. "]" ..
|
||||
"scrollbaroptions[max=" .. size .. "]" ..
|
||||
"scrollbar[9.4,0.6;0.4,7.7;vertical;wrenchmenu;]" ..
|
||||
"scroll_container[0,1;12,9;wrenchmenu;vertical;]" ..
|
||||
text ..
|
||||
"scroll_container_end[]" ..
|
||||
buttons
|
||||
else
|
||||
return "size[10,9]" ..
|
||||
default.gui_bg ..
|
||||
default.gui_bg_img ..
|
||||
default.gui_slots ..
|
||||
"box[0,-0.1;9.8,0.5;#c6e8ff]" ..
|
||||
"label[0.2,-0.1;" .. minetest.colorize( "#000000", title) .. "]" ..
|
||||
"label[9.5,-0.1;" .. minetest.colorize( "#000000", star) .. "]" ..
|
||||
"container[0,1]" ..
|
||||
text ..
|
||||
"container_end[]" ..
|
||||
buttons
|
||||
end
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
function menu.eval_input(pos, ndef, form_def, fields)
|
||||
function menu.eval_input(pos, form_def, fields, player_name)
|
||||
--print(dump(fields))
|
||||
if fields.save then
|
||||
local meta = minetest.get_meta(pos)
|
||||
evaluate_data(pos, meta, form_def, fields)
|
||||
evaluate_data(pos, meta, form_def, fields, player_name)
|
||||
end
|
||||
return fields.refresh or fields.save
|
||||
end
|
||||
|