built on 05/03/2023 11:54:37

This commit is contained in:
Joachim Stolberg 2023-03-05 11:54:37 +01:00
parent c84701ecc8
commit f3478e3269
77 changed files with 1175 additions and 534 deletions

View File

@ -46,7 +46,7 @@ local function set_player_privs(player)
meta:set_int("player_physics_locked", 1) meta:set_int("player_physics_locked", 1)
if meta and physics then if meta and physics then
-- store the player privs default values -- store the player privs default values
meta:set_int("autobahn_speed", physics.speed) meta:set_float("autobahn_speed", physics.speed)
-- set operator privs -- set operator privs
meta:set_int("autobahn_isactive", 1) meta:set_int("autobahn_isactive", 1)
physics.speed = 3.5 physics.speed = 3.5
@ -67,7 +67,7 @@ local function reset_player_privs(player)
if meta and physics then if meta and physics then
-- restore the player privs default values -- restore the player privs default values
meta:set_int("autobahn_isactive", 0) meta:set_int("autobahn_isactive", 0)
physics.speed = meta:get_int("autobahn_speed") physics.speed = meta:get_float("autobahn_speed")
if physics.speed == 0 then physics.speed = 1 end if physics.speed == 0 then physics.speed = 1 end
-- delete stored default values -- delete stored default values
meta:set_string("autobahn_speed", "") meta:set_string("autobahn_speed", "")

View File

@ -43,7 +43,7 @@ The mod features are:
- Extra Minecart privs for rail workers - Extra Minecart privs for rail workers
- Ingame documentation (German and English), based on the mod "doc" - Ingame documentation (German and English), based on the mod "doc"
- API to register carts from other mods - API to register carts from other mods
- chat command '/mycart <num>' to output cart state and location - chat command `/mycart <num>` to output cart state and location
- Command interface for Techage (Lua and ICTA) and for Beduino Controllers - Command interface for Techage (Lua and ICTA) and for Beduino Controllers
@ -74,50 +74,20 @@ Introduction
at least every 16 nodes/meters) at least every 16 nodes/meters)
9. Place a Minecart in front of the buffer and check whether it starts after the 9. Place a Minecart in front of the buffer and check whether it starts after the
configured time configured time
10. Check the cart state via the chat command: /mycart <num> 10. Check the cart state via the chat command: `/mycart <num>`
'<num>' is the cart number, or get a list of carts with /mycart `<num>` is the cart number, or get a list of carts with `/mycart`
11. Drop items into the Minecart and punch the cart to start it, or "sneak+click" the 11. Drop items into the Minecart and punch the cart to start it, or "sneak+click" the
Minecart to get cart and items back Minecart to get cart and items back
12. Dig the cart with 'sneak+click' (as usual). The items will be drop down. 12. Dig the cart with 'sneak+click' (as usual). The items will be drop down.
13. To retrieve lost carts, use the chat command: /stopcart <num> 13. To retrieve lost carts, use the chat command: /stopcart <num>
Hopper
------
![hopper](https://github.com/joe7575/minecart/blob/master/hopper.png)
The Hopper is used to load/unload Minecarts.
The Hopper can pull and push items into/out off chests and can drop/pick up items
to/from Minecarts. To unload a Minecart place the hopper below the rail.
To load the Minecart, place the hopper right next to the Minecart.
Cart Pusher ## Manual
-----------
Used to push a cart if the cart does not stop directly at a buffer. see [Wiki](https://github.com/joe7575/minecart/wiki)
The block has to be placed below the rail.
Cart Speed / Speed Limit Signs
------------------------------
As before, the speed of the carts is also influenced by power rails.
Brake rails are irrelevant, the cart does not brake here.
The maximum speed is 8 m/s. This assumes a ratio of power rails
to normal rails of 1 to 4 on a flat section of rail. A rail section is a
series of rail nodes without a change of direction. After every curve / kink,
the speed for the next section of the route is newly determined,
taking into account the swing of the cart. This means that a cart can
roll over short rail sections without power rails.
In order to additionally brake the cart at certain points
(at switches or in front of a buffer), speed limit signs can be placed
on the track. With these signs the speed can be reduced to 4, 2, or 1 m / s.
The "No speed limit" sign can be used to remove the speed limit.
The speed limit signs must be placed next to the track so that they can
be read from the cart. This allows different speeds in each direction of travel.
## Command Interface ## Command Interface
@ -159,14 +129,6 @@ The Cart Terminal has a Beduino command interface with the commands:
Migration to v2
---------------
The way how carts are monitored and the cart speed is calculated has changed.
Therefore, it is necessary that all carts are repositioned and the
recording is repeated.
Rails and buffers are not affected and can be kept unchanged.
History History
------- -------
@ -193,4 +155,5 @@ History
Speed limit signs and cart terminal added Speed limit signs and cart terminal added
2021-09-02 V2.01 Chat command /stopcart added 2021-09-02 V2.01 Chat command /stopcart added
2021-10-18 V2.02 Cart reproduction bug fixed 2021-10-18 V2.02 Cart reproduction bug fixed
2023-01-04 V2.03 Techage and Beduino command interface added 2023-01-04 V2.03 Techage and Beduino command interface added
2023-02-05 V2.04 New API functions added, EOL blanks removed

View File

@ -7,7 +7,7 @@
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--
-- --
@ -21,20 +21,20 @@
function minecart.is_cart_available(pos, param2, radius) function minecart.is_cart_available(pos, param2, radius)
return minecart.get_nodecart_nearby(pos, param2, radius) ~= nil or return minecart.get_nodecart_nearby(pos, param2, radius) ~= nil or
minecart.get_entitycart_nearby(pos, param2, radius) ~= nil minecart.get_entitycart_nearby(pos, param2, radius) ~= nil
end end
-- Function returns true if a standing cart as node is avaliable -- Function returns true if a standing cart as node is avaliable
function minecart.is_nodecart_available(pos, param2, radius) function minecart.is_nodecart_available(pos, param2, radius)
return minecart.get_nodecart_nearby(pos, param2, radius) ~= nil return minecart.get_nodecart_nearby(pos, param2, radius) ~= nil
end end
-- Function returns true if a standing cart as entity is avaliable -- Function returns true if a standing cart as entity is avaliable
function minecart.is_entitycart_available(pos, param2, radius) function minecart.is_entitycart_available(pos, param2, radius)
return minecart.get_entitycart_nearby(pos, param2, radius) ~= nil return minecart.get_entitycart_nearby(pos, param2, radius) ~= nil
end end
function minecart.punch_cart(pos, param2, radius, punch_dir) function minecart.punch_cart(pos, param2, radius, punch_dir)
local pos2, node = minecart.get_nodecart_nearby(pos, param2, radius) local pos2, node = minecart.get_nodecart_nearby(pos, param2, radius)
if pos2 then if pos2 then
minecart.start_nodecart(pos2, node.name, nil, punch_dir) minecart.start_nodecart(pos2, node.name, nil, punch_dir)
return true return true
@ -45,4 +45,39 @@ function minecart.punch_cart(pos, param2, radius, punch_dir)
minecart.push_entitycart(entity, punch_dir) minecart.push_entitycart(entity, punch_dir)
return true return true
end end
end end
--------------------------------------------------------------------------------------------
-- API functions for other mods to add/remove carts
--------------------------------------------------------------------------------------------
function minecart.is_cart(name)
return minecart.tNodeNames[name] ~= nil
end
-- Remove a cart, available as node
function minecart.remove_cart(pos)
local node = minecart.get_node_lvm(pos)
local cargo, owner, userID = minecart.remove_nodecart(pos, node)
minecart.monitoring_remove_cart(owner, userID)
local cartdef = {cargo = cargo, owner = owner, userID = userID}
return cartdef
end
-- Place and start the cart
function minecart.place_and_start_cart(pos, node, cartdef, player)
local name = minecart.get_node_lvm(pos).name
if minecart.is_rail(pos, name) or minecart.is_cart(name) then
local vel = {x = 0, y = 0, z = 0}
local entity_name = minecart.tNodeNames[node.name]
local obj = minecart.add_entitycart(pos, node.name, entity_name, vel,
cartdef.cargo, cartdef.owner, cartdef.userID)
local entity = obj:get_luaentity()
minecart.monitoring_add_cart(cartdef.owner, cartdef.userID, pos, node.name, entity_name)
if player then
minecart.manage_attachment(player, entity, true)
end
minecart.start_entitycart(entity, pos, 0)
else
minecart.add_nodecart(pos, node.name, node.param2, cartdef.cargo, cartdef.owner, cartdef.userID, true)
end
end

View File

@ -7,7 +7,7 @@
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--
-- for lazy programmers -- for lazy programmers
@ -142,7 +142,7 @@ end
minetest.register_entity("minecart:marker", { minetest.register_entity("minecart:marker", {
initial_properties = { initial_properties = {
visual = "upright_sprite", visual = "upright_sprite",
textures = {"minecart_marker_cube.png"}, textures = {"minecart_marker_cube.png"},
use_texture_alpha = minecart.CLIP, use_texture_alpha = minecart.CLIP,
physical = false, physical = false,
@ -229,7 +229,7 @@ function minecart.manage_attachment(player, entity, get_on)
return return
end end
player_api.player_attached[player_name] = get_on player_api.player_attached[player_name] = get_on
local obj = entity.object local obj = entity.object
if get_on then if get_on then
player:set_attach(obj, "", {x=0, y=-4.5, z=-4}, {x=0, y=0, z=0}) player:set_attach(obj, "", {x=0, y=-4.5, z=-4}, {x=0, y=0, z=0})
@ -254,10 +254,12 @@ function minecart.register_cart_names(node_name, entity_name, cart_type)
minecart.tCartTypes[node_name] = cart_type minecart.tCartTypes[node_name] = cart_type
end end
function minecart.add_nodecart(pos, node_name, param2, cargo, owner, userID) function minecart.add_nodecart(pos, node_name, param2, cargo, owner, userID, force)
if pos and node_name and param2 and cargo and owner and userID then if pos and node_name and param2 and cargo and owner and userID then
local pos2 local pos2
if not minecart.is_rail(pos) then if force then
pos2 = pos
elseif not minecart.is_rail(pos) then
pos2 = minetest.find_node_near(pos, 1, minecart.lRails) pos2 = minetest.find_node_near(pos, 1, minecart.lRails)
if not pos2 or not minecart.is_rail(pos2) then if not pos2 or not minecart.is_rail(pos2) then
-- If no rail is around, use an available cart as new search center -- If no rail is around, use an available cart as new search center
@ -273,14 +275,14 @@ function minecart.add_nodecart(pos, node_name, param2, cargo, owner, userID)
if pos2 then if pos2 then
local node = minetest.get_node(pos2) local node = minetest.get_node(pos2)
local ndef = minetest.registered_nodes[node_name] local ndef = minetest.registered_nodes[node_name]
local rail = node.name
minetest.swap_node(pos2, {name = node_name, param2 = param2}) minetest.swap_node(pos2, {name = node_name, param2 = param2})
local meta = M(pos2) local meta = M(pos2)
meta:set_string("removed_rail", rail) meta:set_string("removed_rail", node.name)
meta:set_string("removed_rail_param2", node.param2)
meta:set_string("owner", owner) meta:set_string("owner", owner)
meta:set_int("userID", userID) meta:set_int("userID", userID)
meta:set_string("infotext", owner .. ": " .. userID) meta:set_string("infotext", owner .. ": " .. userID)
if cargo and ndef.set_cargo then if cargo and ndef.set_cargo then
ndef.set_cargo(pos2, cargo) ndef.set_cargo(pos2, cargo)
end end
@ -295,7 +297,7 @@ end
function minecart.add_entitycart(pos, node_name, entity_name, vel, cargo, owner, userID) function minecart.add_entitycart(pos, node_name, entity_name, vel, cargo, owner, userID)
local obj = minetest.add_entity(pos, entity_name) local obj = minetest.add_entity(pos, entity_name)
local objID = minecart.get_object_id(obj) local objID = minecart.get_object_id(obj)
if objID then if objID then
local entity = obj:get_luaentity() local entity = obj:get_luaentity()
entity.start_pos = pos entity.start_pos = pos
@ -312,7 +314,7 @@ end
function minecart.start_entitycart(self, pos, facedir) function minecart.start_entitycart(self, pos, facedir)
local route = {} local route = {}
self.is_running = true self.is_running = true
self.arrival_time = 0 self.arrival_time = 0
self.start_pos = minecart.get_buffer_pos(pos, self.owner) or minecart.get_next_buffer(pos, facedir) self.start_pos = minecart.get_buffer_pos(pos, self.owner) or minecart.get_next_buffer(pos, facedir)
@ -324,26 +326,33 @@ function minecart.start_entitycart(self, pos, facedir)
-- If set the start waypoint will be deleted -- If set the start waypoint will be deleted
self.no_normal_start = self.start_pos == nil self.no_normal_start = self.start_pos == nil
if self.driver == nil then if self.driver == nil then
minecart.start_monitoring(self.owner, self.userID, pos, self.objID, minecart.start_monitoring(self.owner, self.userID, pos, self.objID,
route.checkpoints, route.junctions, self.cargo or {}) route.checkpoints, route.junctions, self.cargo or {})
end end
end end
function minecart.remove_nodecart(pos) function minecart.remove_nodecart(pos, node)
local node = minetest.get_node(pos) node = node or minetest.get_node(pos)
local ndef = minetest.registered_nodes[node.name] local ndef = minetest.registered_nodes[node.name]
local meta = M(pos) local meta = M(pos)
local rail = meta:get_string("removed_rail") local rail = meta:get_string("removed_rail")
local param2 = meta:get_int("removed_rail_param2")
if rail == "" then rail = "air" end if rail == "" then rail = "air" end
local userID = meta:get_int("userID") local userID = meta:get_int("userID")
local owner = meta:get_string("owner") local owner = meta:get_string("owner")
meta:set_string("infotext", "") meta:set_string("infotext", "")
meta:set_string("formspec", "") meta:set_string("formspec", "")
local cargo = ndef.get_cargo and ndef.get_cargo(pos) or {} local cargo = ndef.get_cargo and ndef.get_cargo(pos) or {}
minetest.swap_node(pos, {name = rail}) minetest.swap_node(pos, {name = rail, param2 = param2})
return cargo, owner, userID return cargo, owner, userID
end end
function minecart.is_usable_cart(pos, node)
-- cart needs a rail bwelow
local rail = M(pos):get_string("removed_rail")
return minecart.is_rail(pos, rail)
end
function minecart.node_to_entity(pos, node_name, entity_name) function minecart.node_to_entity(pos, node_name, entity_name)
-- Remove node -- Remove node
local cargo, owner, userID = minecart.remove_nodecart(pos) local cargo, owner, userID = minecart.remove_nodecart(pos)
@ -362,7 +371,7 @@ function minecart.entity_to_node(pos, entity)
minetest.sound_stop(entity.sound_handle) minetest.sound_stop(entity.sound_handle)
entity.sound_handle = nil entity.sound_handle = nil
end end
local rot = entity.object:get_rotation() local rot = entity.object:get_rotation()
local dir = minetest.yaw_to_dir(rot.y) local dir = minetest.yaw_to_dir(rot.y)
local facedir = minetest.dir_to_facedir(dir) local facedir = minetest.dir_to_facedir(dir)
@ -400,6 +409,6 @@ function minecart.remove_entity(self, pos, player)
minecart.add_node_to_player_inventory(pos, player, self.node_name or "minecart:cart") minecart.add_node_to_player_inventory(pos, player, self.node_name or "minecart:cart")
end end
minecart.stop_monitoring(self.owner, self.userID, pos) minecart.stop_monitoring(self.owner, self.userID, pos)
minecart.stop_recording(self, pos) minecart.stop_recording(self, pos)
self.object:remove() self.object:remove()
end end

View File

@ -7,7 +7,7 @@
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--
local minecart_lib = [[ local minecart_lib = [[
@ -90,4 +90,4 @@ minetest.register_on_mods_loaded(function()
vm16.register_ro_file("beduino", "lib/minecart.c", minecart_lib) vm16.register_ro_file("beduino", "lib/minecart.c", minecart_lib)
vm16.register_ro_file("beduino", "demo/minecart.c", minecart_demo) vm16.register_ro_file("beduino", "demo/minecart.c", minecart_demo)
end end
end) end)

View File

@ -7,7 +7,7 @@
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--

View File

@ -7,7 +7,7 @@
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
@ -25,21 +25,25 @@ local player_ctrl = minecart.player_ctrl
local tEntityNames = minecart.tEntityNames local tEntityNames = minecart.tEntityNames
local function stop_cart(self, cart_pos) local function stop_cart(self, cart_pos)
local player
self.is_running = false self.is_running = false
self.arrival_time = 0 self.arrival_time = 0
if self.driver then if self.driver then
local player = minetest.get_player_by_name(self.driver) player = minetest.get_player_by_name(self.driver)
if player then if player then
minecart.stop_recording(self, cart_pos) minecart.stop_recording(self, cart_pos)
minecart.manage_attachment(player, self, false) minecart.manage_attachment(player, self, false)
end end
end end
if not minecart.get_buffer_pos(cart_pos, self.owner) then if not minecart.get_buffer_pos(cart_pos, self.owner) then
-- Probably somewhere in the pampas -- Probably somewhere in the pampas
minecart.delete_cart_waypoint(cart_pos) minecart.delete_cart_waypoint(cart_pos)
end end
minecart.entity_to_node(cart_pos, self) minecart.entity_to_node(cart_pos, self)
if player then
player:set_pos(cart_pos)
end
end end
local function get_ctrl(self, pos) local function get_ctrl(self, pos)
@ -50,20 +54,20 @@ end
local function new_speed(self, new_dir) local function new_speed(self, new_dir)
self.cart_speed = self.cart_speed or 0 self.cart_speed = self.cart_speed or 0
local rail_speed = (self.waypoint.speed or 0) / 10 local rail_speed = (self.waypoint.speed or 0) / 10
if rail_speed <= 0 then if rail_speed <= 0 then
rail_speed = math.max(self.cart_speed + rail_speed, 0) rail_speed = math.max(self.cart_speed + rail_speed, 0)
elseif rail_speed <= self.cart_speed then elseif rail_speed <= self.cart_speed then
rail_speed = math.max((self.cart_speed + rail_speed) / 2, 0) rail_speed = math.max((self.cart_speed + rail_speed) / 2, 0)
end end
-- Speed corrections -- Speed corrections
if new_dir.y == 1 then if new_dir.y == 1 then
if rail_speed < 1 then rail_speed = 0 end if rail_speed < 1 then rail_speed = 0 end
else else
if rail_speed < 0.4 then rail_speed = 0 end if rail_speed < 0.4 then rail_speed = 0 end
end end
self.cart_speed = rail_speed -- store for next cycle self.cart_speed = rail_speed -- store for next cycle
return rail_speed return rail_speed
end end
@ -82,7 +86,7 @@ local function running(self)
facedir = minetest.dir_to_facedir(dir) facedir = minetest.dir_to_facedir(dir)
end end
local cart_pos, wayp_pos, is_junction local cart_pos, wayp_pos, is_junction
if self.reenter then -- through monitoring if self.reenter then -- through monitoring
cart_pos = H2P(self.reenter[1]) cart_pos = H2P(self.reenter[1])
-- pos correction on slopes -- pos correction on slopes
@ -120,14 +124,14 @@ local function running(self)
stop_cart(self, wayp_pos) stop_cart(self, wayp_pos)
return return
end end
if is_junction then if is_junction then
if self.is_recording then if self.is_recording then
set_junctions(self, wayp_pos) set_junctions(self, wayp_pos)
end end
self.ctrl = nil self.ctrl = nil
end end
--print("running", LEN(self.junctions)) --print("running", LEN(self.junctions))
local dist = vector.distance(cart_pos, self.waypoint.cart_pos or self.waypoint.pos) local dist = vector.distance(cart_pos, self.waypoint.cart_pos or self.waypoint.pos)
local new_dir = dot2dir(self.waypoint.dot) local new_dir = dot2dir(self.waypoint.dot)
@ -138,7 +142,7 @@ local function running(self)
self.speed_limit = minecart.get_speedlimit(wayp_pos, facedir) or self.speed_limit self.speed_limit = minecart.get_speedlimit(wayp_pos, facedir) or self.speed_limit
end end
new_speed = math.min(new_speed, self.speed_limit) new_speed = math.min(new_speed, self.speed_limit)
local new_cart_pos, extra_cycle = minecart.get_current_cart_pos_correction( local new_cart_pos, extra_cycle = minecart.get_current_cart_pos_correction(
wayp_pos, facedir, dir.y, self.waypoint.dot) -- TODO: Why has self.waypoint no dot? wayp_pos, facedir, dir.y, self.waypoint.dot) -- TODO: Why has self.waypoint no dot?
if extra_cycle and not vector.equals(cart_pos, new_cart_pos) then if extra_cycle and not vector.equals(cart_pos, new_cart_pos) then
@ -147,13 +151,13 @@ local function running(self)
dist = vector.distance(cart_pos, new_cart_pos) dist = vector.distance(cart_pos, new_cart_pos)
--print("extra_cycle", P2S(cart_pos), P2S(wayp_pos), P2S(new_cart_pos), new_speed) --print("extra_cycle", P2S(cart_pos), P2S(wayp_pos), P2S(new_cart_pos), new_speed)
end end
-- Slope corrections -- Slope corrections
--print("Slope corrections", P2S(new_dir), P2S(cart_pos)) --print("Slope corrections", P2S(new_dir), P2S(cart_pos))
if new_dir.y ~= 0 then if new_dir.y ~= 0 then
cart_pos.y = cart_pos.y + 0.2 cart_pos.y = cart_pos.y + 0.2
end end
-- Calc velocity, rotation and arrival_time -- Calc velocity, rotation and arrival_time
local yaw = minetest.dir_to_yaw(new_dir) local yaw = minetest.dir_to_yaw(new_dir)
local pitch = new_dir.y * math.pi/4 local pitch = new_dir.y * math.pi/4
@ -161,16 +165,16 @@ local function running(self)
local vel = vector.multiply(new_dir, new_speed / ((new_dir.y ~= 0) and 1.41 or 1)) local vel = vector.multiply(new_dir, new_speed / ((new_dir.y ~= 0) and 1.41 or 1))
self.arrival_time = self.timebase + (dist / new_speed) self.arrival_time = self.timebase + (dist / new_speed)
-- needed for recording -- needed for recording
self.curr_speed = new_speed self.curr_speed = new_speed
self.num_sections = (self.num_sections or 0) + 1 self.num_sections = (self.num_sections or 0) + 1
-- Got stuck somewhere -- Got stuck somewhere
if new_speed < 0.1 or dist < 0 then if new_speed < 0.1 or dist < 0 then
minetest.log("warning", "[Minecart] Got stuck somewhere " .. new_speed .. " " .. dist) minetest.log("warning", "[Minecart] Got stuck somewhere " .. new_speed .. " " .. dist)
stop_cart(self, wayp_pos) stop_cart(self, wayp_pos)
return return
end end
self.object:set_pos(cart_pos) self.object:set_pos(cart_pos)
self.object:set_rotation({x = pitch, y = yaw, z = 0}) self.object:set_rotation({x = pitch, y = yaw, z = 0})
self.object:set_velocity(vel) self.object:set_velocity(vel)
@ -194,12 +198,12 @@ end
local function on_step(self, dtime) local function on_step(self, dtime)
self.timebase = (self.timebase or 0) + dtime self.timebase = (self.timebase or 0) + dtime
if self.is_running then if self.is_running then
if self.arrival_time <= self.timebase then if self.arrival_time <= self.timebase then
running(self) running(self)
end end
if (self.sound_ttl or 0) <= self.timebase then if (self.sound_ttl or 0) <= self.timebase then
play_sound(self) play_sound(self)
self.sound_ttl = self.timebase + 1.0 self.sound_ttl = self.timebase + 1.0
@ -208,7 +212,7 @@ local function on_step(self, dtime)
if self.sound_handle then if self.sound_handle then
minetest.sound_stop(self.sound_handle) minetest.sound_stop(self.sound_handle)
self.sound_handle = nil self.sound_handle = nil
end end
end end
if self.driver then if self.driver then
@ -219,7 +223,7 @@ local function on_step(self, dtime)
end end
if recording_junctions(self) then if recording_junctions(self) then
local pos = vector.round(self.object:get_pos()) local pos = vector.round(self.object:get_pos())
minecart.stop_recording(self, pos, true) minecart.stop_recording(self, pos, true)
local player = minetest.get_player_by_name(self.driver) local player = minetest.get_player_by_name(self.driver)
minecart.manage_attachment(player, self, false) minecart.manage_attachment(player, self, false)
minecart.entity_to_node(pos, self) minecart.entity_to_node(pos, self)
@ -252,13 +256,13 @@ local function on_entitycard_punch(self, puncher, time_from_last_punch, tool_cap
-- Dig cart -- Dig cart
if self.driver then if self.driver then
-- remove cart as driver -- remove cart as driver
minecart.stop_recording(self, pos, true) minecart.stop_recording(self, pos, true)
minecart.monitoring_remove_cart(self.owner, self.userID) minecart.monitoring_remove_cart(self.owner, self.userID)
minecart.remove_entity(self, pos, puncher) minecart.remove_entity(self, pos, puncher)
minecart.manage_attachment(puncher, self, false) minecart.manage_attachment(puncher, self, false)
else else
-- remove cart from outside -- remove cart from outside
minecart.monitoring_remove_cart(self.owner, self.userID) minecart.monitoring_remove_cart(self.owner, self.userID)
minecart.remove_entity(self, pos, puncher) minecart.remove_entity(self, pos, puncher)
end end
end end
@ -272,11 +276,11 @@ local function on_entitycard_punch(self, puncher, time_from_last_punch, tool_cap
end end
local facedir = minetest.dir_to_facedir(dir or {x=0, y=0, z=0}) local facedir = minetest.dir_to_facedir(dir or {x=0, y=0, z=0})
minecart.start_entitycart(self, pos, facedir or 0) minecart.start_entitycart(self, pos, facedir or 0)
minecart.start_recording(self, pos) minecart.start_recording(self, pos)
end end
end end
end end
-- Player get on / off -- Player get on / off
local function on_entitycard_rightclick(self, clicker) local function on_entitycard_rightclick(self, clicker)
if clicker and clicker:is_player() and self.driver_allowed then if clicker and clicker:is_player() and self.driver_allowed then
@ -284,13 +288,13 @@ local function on_entitycard_rightclick(self, clicker)
if self.driver then if self.driver then
-- get off -- get off
local pos = vector.round(self.object:get_pos()) local pos = vector.round(self.object:get_pos())
minecart.stop_recording(self, pos, true) minecart.stop_recording(self, pos, true)
minecart.manage_attachment(clicker, self, false) minecart.manage_attachment(clicker, self, false)
minecart.entity_to_node(pos, self) minecart.entity_to_node(pos, self)
else else
-- get on -- get on
local pos = vector.round(self.object:get_pos()) local pos = vector.round(self.object:get_pos())
minecart.stop_recording(self, pos, true) minecart.stop_recording(self, pos, true)
minecart.manage_attachment(clicker, self, true) minecart.manage_attachment(clicker, self, true)
end end
end end
@ -312,7 +316,7 @@ function minecart.get_entitycart_nearby(pos, param2, radius)
return entity return entity
end end
end end
end end
end end
function minecart.push_entitycart(self, punch_dir) function minecart.push_entitycart(self, punch_dir)
@ -333,11 +337,11 @@ function minecart.register_cart_entity(entity_name, node_name, cart_type, entity
entity_def.on_step = on_step entity_def.on_step = on_step
entity_def.on_rightclick = on_entitycard_rightclick entity_def.on_rightclick = on_entitycard_rightclick
entity_def.on_detach_child = on_entitycard_detach_child entity_def.on_detach_child = on_entitycard_detach_child
entity_def.owner = nil entity_def.owner = nil
entity_def.driver = nil entity_def.driver = nil
entity_def.cargo = {} entity_def.cargo = {}
minetest.register_entity(entity_name, entity_def) minetest.register_entity(entity_name, entity_def)
-- register node for punching -- register node for punching
minecart.register_cart_names(node_name, entity_name, cart_type) minecart.register_cart_names(node_name, entity_name, cart_type)

View File

@ -7,7 +7,7 @@
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--
local NUM_ITEMS = 4 local NUM_ITEMS = 4
@ -112,7 +112,7 @@ minetest.register_node("minecart:hopper", {
local inv = M(pos):get_inventory() local inv = M(pos):get_inventory()
inv:set_size('main', 4) inv:set_size('main', 4)
end, end,
after_place_node = function(pos, placer) after_place_node = function(pos, placer)
local meta = M(pos) local meta = M(pos)
meta:set_string("owner", placer:get_player_name()) meta:set_string("owner", placer:get_player_name())
@ -130,7 +130,7 @@ minetest.register_node("minecart:hopper", {
end end
return true return true
end, end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player) allow_metadata_inventory_put = function(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then if minetest.is_protected(pos, player:get_player_name()) then
return 0 return 0
@ -145,13 +145,13 @@ minetest.register_node("minecart:hopper", {
end end
return stack:get_count() return stack:get_count()
end, end,
after_dig_node = function(pos, oldnode, oldmetadata, digger) after_dig_node = function(pos, oldnode, oldmetadata, digger)
for _,stack in ipairs(oldmetadata.inventory.main) do for _,stack in ipairs(oldmetadata.inventory.main) do
minetest.add_item(pos, stack) minetest.add_item(pos, stack)
end end
end, end,
paramtype = "light", paramtype = "light",
sunlight_propagates = true, sunlight_propagates = true,
paramtype2 = "facedir", paramtype2 = "facedir",

View File

@ -7,7 +7,7 @@
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--
-- for lazy programmers -- for lazy programmers
@ -43,7 +43,7 @@ function minecart.take_items(pos, param2, num)
local def = RegisteredInventories[node.name] local def = RegisteredInventories[node.name]
local owner = M(pos):get_string("owner") local owner = M(pos):get_string("owner")
local inv = minetest.get_inventory({type="node", pos=npos}) local inv = minetest.get_inventory({type="node", pos=npos})
if def and inv and def.take_listname and (not def.allow_take or def.allow_take(npos, nil, owner)) then if def and inv and def.take_listname and (not def.allow_take or def.allow_take(npos, nil, owner)) then
return minecart.inv_take_items(inv, def.take_listname, num) return minecart.inv_take_items(inv, def.take_listname, num)
elseif def and def.take_item then elseif def and def.take_item then
@ -61,7 +61,7 @@ function minecart.put_items(pos, param2, stack)
local def = RegisteredInventories[node.name] local def = RegisteredInventories[node.name]
local owner = M(pos):get_string("owner") local owner = M(pos):get_string("owner")
local inv = minetest.get_inventory({type="node", pos=npos}) local inv = minetest.get_inventory({type="node", pos=npos})
if def and inv and def.put_listname and (not def.allow_put or def.allow_put(npos, stack, owner)) then if def and inv and def.put_listname and (not def.allow_put or def.allow_put(npos, stack, owner)) then
local leftover = inv:add_item(def.put_listname, stack) local leftover = inv:add_item(def.put_listname, stack)
if leftover:get_count() > 0 then if leftover:get_count() > 0 then
@ -93,7 +93,7 @@ function minecart.untake_items(pos, param2, stack)
end end
local def = RegisteredInventories[node.name] local def = RegisteredInventories[node.name]
local inv = minetest.get_inventory({type="node", pos=npos}) local inv = minetest.get_inventory({type="node", pos=npos})
if def and inv and def.take_listname then if def and inv and def.take_listname then
return inv:add_item(def.take_listname, stack) return inv:add_item(def.take_listname, stack)
elseif def and def.untake_item then elseif def and def.untake_item then
@ -128,14 +128,14 @@ minecart.register_inventory({"minecart:hopper"}, {
allow_inventory_put = function(pos, stack, player_name) allow_inventory_put = function(pos, stack, player_name)
local owner = M(pos):get_string("owner") local owner = M(pos):get_string("owner")
return owner == player_name return owner == player_name
end, end,
listname = "main", listname = "main",
}, },
take = { take = {
allow_inventory_take = function(pos, stack, player_name) allow_inventory_take = function(pos, stack, player_name)
local owner = M(pos):get_string("owner") local owner = M(pos):get_string("owner")
return owner == player_name return owner == player_name
end, end,
listname = "main", listname = "main",
}, },
}) })

View File

@ -13,7 +13,7 @@
minecart = {} minecart = {}
-- Version for compatibility checks, see readme.md/history -- Version for compatibility checks, see readme.md/history
minecart.version = 2.03 minecart.version = 2.04
minecart.hopper_enabled = minetest.settings:get_bool("minecart_hopper_enabled") ~= false minecart.hopper_enabled = minetest.settings:get_bool("minecart_hopper_enabled") ~= false
minecart.teleport_enabled = minetest.settings:get_bool("minecart_teleport_enabled") == true minecart.teleport_enabled = minetest.settings:get_bool("minecart_teleport_enabled") == true

View File

@ -3,6 +3,7 @@ Station name=Stationsname
Waiting time/sec=Wartezeit/s Waiting time/sec=Wartezeit/s
connected to=verbunden mit connected to=verbunden mit
Not connected!=Nicht verbunden! Not connected!=Nicht verbunden!
Minecart Railway Buffer=Minecart Prellbock
Summary=Zusammenfassung Summary=Zusammenfassung
1. Place your rails and build a route with two endpoints. Junctions are allowed as long as each route has its own start and endpoint.=1. Baue eine Schienenstrecke mit zwei Enden. Kreuzungen sind zulässig, solange jede Route ihre eigenen Start- und Endpunkte hat. 1. Place your rails and build a route with two endpoints. Junctions are allowed as long as each route has its own start and endpoint.=1. Baue eine Schienenstrecke mit zwei Enden. Kreuzungen sind zulässig, solange jede Route ihre eigenen Start- und Endpunkte hat.
2. Place a Railway Buffer at both endpoints (buffers are always needed, they store the route and timing information).=2. Platziere einen Prellbock an beide Schienenenden (Prellböcke sind zwingend notwendig, sie speichern die Routen- und Zeit-Informationen). 2. Place a Railway Buffer at both endpoints (buffers are always needed, they store the route and timing information).=2. Platziere einen Prellbock an beide Schienenenden (Prellböcke sind zwingend notwendig, sie speichern die Routen- und Zeit-Informationen).
@ -27,21 +28,20 @@ Minecart Cart=Wagen
Minecart Speed Signs=Geschwindigkeitsbegrenzungszeichen Minecart Speed Signs=Geschwindigkeitsbegrenzungszeichen
If several carts are running on one route,@nit can happen that a buffer position is already occupied and one cart therefore stops earlier.@nIn this case, the cart pusher is used to push the cart towards the buffer again.@nThis block must be placed under the rail at a distance of 2 m in front of the buffer.=Wenn mehrere Wagen auf einer Route fahren, kann es vorkommen,@ndass eine Prellbock Position bereits belegt ist und ein Wagen daher früher anhält.@nDer Cart Anschieber dient in diesem Fall dazu, die Wagen wieder in Richtung Prellbock anzuschieben.@nDieser Block muss unter der Schiene mit 2 m Abstand vor dem Prellbock platziert werden. If several carts are running on one route,@nit can happen that a buffer position is already occupied and one cart therefore stops earlier.@nIn this case, the cart pusher is used to push the cart towards the buffer again.@nThis block must be placed under the rail at a distance of 2 m in front of the buffer.=Wenn mehrere Wagen auf einer Route fahren, kann es vorkommen,@ndass eine Prellbock Position bereits belegt ist und ein Wagen daher früher anhält.@nDer Cart Anschieber dient in diesem Fall dazu, die Wagen wieder in Richtung Prellbock anzuschieben.@nDieser Block muss unter der Schiene mit 2 m Abstand vor dem Prellbock platziert werden.
Limit the cart speed with speed limit signs.@n@nAs before, the speed of the carts is also influenced by power rails.@nBrake rails are irrelevant, the cart does not brake here.@nThe maximum speed is 8 m/s. This assumes a ratio of power rails@nto normal rails of 1 to 4 on a flat section of rail. A rail section is a@nseries of rail nodes without a change of direction. After every curve / kink,@nthe speed for the next section of the route is newly determined,@ntaking into account the swing of the cart. This means that a cart can@nroll over short rail sections without power rails.@n@nIn order to additionally brake the cart at certain points@n(at switches or in front of a buffer), speed limit signs can be placed@non the track. With these signs the speed can be reduced to 4, 2, or 1 m / s.@nThe "No speed limit" sign can be used to remove the speed limit.@n@nThe speed limit signs must be placed next to the track so that they can@nbe read from the cart. This allows different speeds in each direction of travel.=Begrenze die Geschwindigkeit der Wagen mit Geschwindigkeitsbegrenzungszeichen@n@nDie Geschwindigkeit der Carts wird wie bisher auch über "power rails" beeinflusst. "Brake rails" sind ohne Bedeutung, das Cart bremst hier nicht. Die maximale Geschwindigkeit beträgt 8 m/s. Dies setzt eine Verhältnis von "power rails" zu "normal rails" von 1 zu 4 auf einem ebenen Streckenabschnitt voraus. Ein Streckenabschnitt ist dabei ein Reihe von Schienenblöcken ohne Richtungsänderung. Nach jeder Kurve/Knick wird die Geschwindigkeit für den nächsten Streckenabschnitt neu bestimmt, wobei hier der Schwung des Carts mit berücksichtigt wird. So kann ein Cart auch über kurze Streckenabschnitt ohne "power rails" rollen.@n@nUm das Cart zusätzlich an bestimmten Stellen abzubremsen (an Weichen oder vor einen Puffer), können Geschwindigkeitsbegrenzungszeichen an der Strecke platziert werden. Durch diese Zeichen kann die Geschwindigkeit auf 4, 2, oder 1 m/s reduziert werden. Durch das Aufhebungszeichen kann die Geschwindigkeitsbegrenzung wieder aufgehoben werden.@n@nDie Geschwindigkeitsbegrenzungszeichen müssen so neben die Strecke platziert werden, dass sie vom Cart ablesbar sind. Dies erlaubt damit unterschiedliche Geschwindigkeiten pro Fahrtrichtung. Limit the cart speed with speed limit signs.@n@nAs before, the speed of the carts is also influenced by power rails.@nBrake rails are irrelevant, the cart does not brake here.@nThe maximum speed is 8 m/s. This assumes a ratio of power rails@nto normal rails of 1 to 4 on a flat section of rail. A rail section is a@nseries of rail nodes without a change of direction. After every curve / kink,@nthe speed for the next section of the route is newly determined,@ntaking into account the swing of the cart. This means that a cart can@nroll over short rail sections without power rails.@n@nIn order to additionally brake the cart at certain points@n(at switches or in front of a buffer), speed limit signs can be placed@non the track. With these signs the speed can be reduced to 4, 2, or 1 m / s.@nThe "No speed limit" sign can be used to remove the speed limit.@n@nThe speed limit signs must be placed next to the track so that they can@nbe read from the cart. This allows different speeds in each direction of travel.=Begrenze die Geschwindigkeit der Wagen mit Geschwindigkeitsbegrenzungszeichen@n@nDie Geschwindigkeit der Carts wird wie bisher auch über "power rails" beeinflusst. "Brake rails" sind ohne Bedeutung, das Cart bremst hier nicht. Die maximale Geschwindigkeit beträgt 8 m/s. Dies setzt eine Verhältnis von "power rails" zu "normal rails" von 1 zu 4 auf einem ebenen Streckenabschnitt voraus. Ein Streckenabschnitt ist dabei ein Reihe von Schienenblöcken ohne Richtungsänderung. Nach jeder Kurve/Knick wird die Geschwindigkeit für den nächsten Streckenabschnitt neu bestimmt, wobei hier der Schwung des Carts mit berücksichtigt wird. So kann ein Cart auch über kurze Streckenabschnitt ohne "power rails" rollen.@n@nUm das Cart zusätzlich an bestimmten Stellen abzubremsen (an Weichen oder vor einen Puffer), können Geschwindigkeitsbegrenzungszeichen an der Strecke platziert werden. Durch diese Zeichen kann die Geschwindigkeit auf 4, 2, oder 1 m/s reduziert werden. Durch das Aufhebungszeichen kann die Geschwindigkeitsbegrenzung wieder aufgehoben werden.@n@nDie Geschwindigkeitsbegrenzungszeichen müssen so neben die Strecke platziert werden, dass sie vom Cart ablesbar sind. Dies erlaubt damit unterschiedliche Geschwindigkeiten pro Fahrtrichtung.
Minecart Railway Buffer=Minecart Prellbock
Minecart Hopper=Minecart Hopper Minecart Hopper=Minecart Hopper
Minecart Landmark=Minecart Meilenstein
Cart Pusher=Wagen Anschieber
Minecart (Sneak+Click to pick up)=Minecart (Shift+Klick zum Entfernen des Carts) Minecart (Sneak+Click to pick up)=Minecart (Shift+Klick zum Entfernen des Carts)
Output cart state and position, or a list of carts, if no cart number is given.=Gibt Status und Position des Wagens, oder eine Liste aller Wagen aus, wenn keine Wagennummer angegeben ist. Output cart state and position, or a list of carts, if no cart number is given.=Gibt Status und Position des Wagens, oder eine Liste aller Wagen aus, wenn keine Wagennummer angegeben ist.
List of carts=Liste aller Wagen List of carts=Liste aller Wagen
Stop amd return a missing/running cart.=Stoppe und hole einen vermissten Wagen zurück. Stop and return/drop a missing/running cart.=Stoppe und hole einen vermissten Wagen zurück.
Cart=Wagen Cart=Wagen
stopped=gestoppt dropped=fallen gelassen
is not existing!=existiert nicht! is not existing!=existiert nicht!
Enter cart number=Gebe Cart Nummer ein Enter cart number=Gebe Cart Nummer ein
Save=Speichern Save=Speichern
[minecart] Area is protected!=[minecart] Bereich ist geschützt! [minecart] Area is protected!=[minecart] Bereich ist geschützt!
Allow to dig/place rails in Minecart Landmark areas=Erlaubt dir, Schienen in Meilensteinbereichen zu setzen/zu entfernen Allow to dig/place rails in Minecart Landmark areas=Erlaubt dir, Schienen in Meilensteinbereichen zu setzen/zu entfernen
Minecart Landmark=Minecart Meilenstein
Cart Pusher=Wagen Anschieber
left=links left=links
right=rechts right=rechts
straight=geradeaus straight=geradeaus
@ -49,6 +49,7 @@ Recording=Aufzeichnung
speed=Tempo speed=Tempo
next junction=nächste Weiche next junction=nächste Weiche
Travel time=Fahrzeit Travel time=Fahrzeit
[minecart] Recording canceled!=
[minecart] Route stored!=[minecart] Strecke gespeichert [minecart] Route stored!=[minecart] Strecke gespeichert
[minecart] Speed @= %u m/s, Time @= %u s, Route length @= %u m=[minecart] Geschw. @= %u m/s, Zeit @= %u s, Routenlänge @= %u m [minecart] Speed @= %u m/s, Time @= %u s, Route length @= %u m=[minecart] Geschw. @= %u m/s, Zeit @= %u s, Routenlänge @= %u m
[minecart] Your route is too short to record!=[minecart] Deine Strecke ist zu kurz für eine Aufzeichnung! [minecart] Your route is too short to record!=[minecart] Deine Strecke ist zu kurz für eine Aufzeichnung!
@ -58,3 +59,9 @@ Speed "4"=Tempo "4"
No speed limit=Keine Geschwindigkeitsbegrenzung No speed limit=Keine Geschwindigkeitsbegrenzung
Cart List=Cart Liste Cart List=Cart Liste
Cart Terminal=Cart Terminal Cart Terminal=Cart Terminal
##### not used anymore #####
Stop amd return a missing/running cart.=Stoppe und hole einen vermissten Wagen zurück.
stopped=gestoppt

View File

@ -3,6 +3,7 @@ Station name=
Waiting time/sec= Waiting time/sec=
connected to= connected to=
Not connected!= Not connected!=
Minecart Railway Buffer=
Summary= Summary=
1. Place your rails and build a route with two endpoints. Junctions are allowed as long as each route has its own start and endpoint.= 1. Place your rails and build a route with two endpoints. Junctions are allowed as long as each route has its own start and endpoint.=
2. Place a Railway Buffer at both endpoints (buffers are always needed, they store the route and timing information).= 2. Place a Railway Buffer at both endpoints (buffers are always needed, they store the route and timing information).=
@ -27,21 +28,20 @@ Minecart Cart=
Minecart Speed Signs= Minecart Speed Signs=
If several carts are running on one route,@nit can happen that a buffer position is already occupied and one cart therefore stops earlier.@nIn this case, the cart pusher is used to push the cart towards the buffer again.@nThis block must be placed under the rail at a distance of 2 m in front of the buffer.= If several carts are running on one route,@nit can happen that a buffer position is already occupied and one cart therefore stops earlier.@nIn this case, the cart pusher is used to push the cart towards the buffer again.@nThis block must be placed under the rail at a distance of 2 m in front of the buffer.=
Limit the cart speed with speed limit signs.@n@nAs before, the speed of the carts is also influenced by power rails.@nBrake rails are irrelevant, the cart does not brake here.@nThe maximum speed is 8 m/s. This assumes a ratio of power rails@nto normal rails of 1 to 4 on a flat section of rail. A rail section is a@nseries of rail nodes without a change of direction. After every curve / kink,@nthe speed for the next section of the route is newly determined,@ntaking into account the swing of the cart. This means that a cart can@nroll over short rail sections without power rails.@n@nIn order to additionally brake the cart at certain points@n(at switches or in front of a buffer), speed limit signs can be placed@non the track. With these signs the speed can be reduced to 4, 2, or 1 m / s.@nThe "No speed limit" sign can be used to remove the speed limit.@n@nThe speed limit signs must be placed next to the track so that they can@nbe read from the cart. This allows different speeds in each direction of travel.= Limit the cart speed with speed limit signs.@n@nAs before, the speed of the carts is also influenced by power rails.@nBrake rails are irrelevant, the cart does not brake here.@nThe maximum speed is 8 m/s. This assumes a ratio of power rails@nto normal rails of 1 to 4 on a flat section of rail. A rail section is a@nseries of rail nodes without a change of direction. After every curve / kink,@nthe speed for the next section of the route is newly determined,@ntaking into account the swing of the cart. This means that a cart can@nroll over short rail sections without power rails.@n@nIn order to additionally brake the cart at certain points@n(at switches or in front of a buffer), speed limit signs can be placed@non the track. With these signs the speed can be reduced to 4, 2, or 1 m / s.@nThe "No speed limit" sign can be used to remove the speed limit.@n@nThe speed limit signs must be placed next to the track so that they can@nbe read from the cart. This allows different speeds in each direction of travel.=
Minecart Railway Buffer=
Minecart Hopper= Minecart Hopper=
Minecart Landmark=
Cart Pusher=
Minecart (Sneak+Click to pick up)= Minecart (Sneak+Click to pick up)=
Output cart state and position, or a list of carts, if no cart number is given.= Output cart state and position, or a list of carts, if no cart number is given.=
List of carts= List of carts=
Stop amd return a missing/running cart.= Stop and return/drop a missing/running cart.=
Cart= Cart=
stopped= dropped=
is not existing!= is not existing!=
Enter cart number= Enter cart number=
Save= Save=
[minecart] Area is protected!= [minecart] Area is protected!=
Allow to dig/place rails in Minecart Landmark areas= Allow to dig/place rails in Minecart Landmark areas=
Minecart Landmark=
Cart Pusher=
left= left=
right= right=
straight= straight=
@ -49,6 +49,7 @@ Recording=
speed= speed=
next junction= next junction=
Travel time= Travel time=
[minecart] Recording canceled!=
[minecart] Route stored!= [minecart] Route stored!=
[minecart] Speed @= %u m/s, Time @= %u s, Route length @= %u m= [minecart] Speed @= %u m/s, Time @= %u s, Route length @= %u m=
[minecart] Your route is too short to record!= [minecart] Your route is too short to record!=

View File

@ -7,7 +7,7 @@
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--
local S = minecart.S local S = minecart.S
@ -16,7 +16,7 @@ local M = minetest.get_meta
minetest.register_node("minecart:cart", { minetest.register_node("minecart:cart", {
description = S("Minecart (Sneak+Click to pick up)"), description = S("Minecart (Sneak+Click to pick up)"),
tiles = { tiles = {
-- up, down, right, left, back, front -- up, down, right, left, back, front
"carts_cart_top.png^minecart_appl_cart_top.png", "carts_cart_top.png^minecart_appl_cart_top.png",
"carts_cart_top.png", "carts_cart_top.png",
"carts_cart_side.png^minecart_logo.png", "carts_cart_side.png^minecart_logo.png",
@ -49,7 +49,7 @@ minetest.register_node("minecart:cart", {
groups = {cracky = 2, crumbly = 2, choppy = 2}, groups = {cracky = 2, crumbly = 2, choppy = 2},
node_placement_prediction = "", node_placement_prediction = "",
diggable = false, diggable = false,
on_place = minecart.on_nodecart_place, on_place = minecart.on_nodecart_place,
on_punch = minecart.on_nodecart_punch, on_punch = minecart.on_nodecart_punch,
@ -57,20 +57,22 @@ minetest.register_node("minecart:cart", {
if clicker and clicker:is_player() then if clicker and clicker:is_player() then
if M(pos):get_int("userID") ~= 0 then if M(pos):get_int("userID") ~= 0 then
-- enter the cart -- enter the cart
local object = minecart.node_to_entity(pos, "minecart:cart", "minecart:cart_entity") if minecart.is_usable_cart(pos, node) then
minecart.manage_attachment(clicker, object:get_luaentity(), true) local object = minecart.node_to_entity(pos, "minecart:cart", "minecart:cart_entity")
else minecart.manage_attachment(clicker, object:get_luaentity(), true)
end
else
minecart.show_formspec(pos, clicker) minecart.show_formspec(pos, clicker)
end end
end end
end, end,
set_cargo = function(pos, data) set_cargo = function(pos, data)
for _,item in ipairs(data or {}) do for _,item in ipairs(data or {}) do
minetest.add_item(pos, ItemStack(item)) minetest.add_item(pos, ItemStack(item))
end end
end, end,
get_cargo = function(pos) get_cargo = function(pos)
local data = {} local data = {}
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 1)) do for _, obj in pairs(minetest.get_objects_inside_radius(pos, 1)) do

View File

@ -7,9 +7,9 @@
MIT MIT
See license.txt for more information See license.txt for more information
Wrapper functions to get hopper support for other mods Wrapper functions to get hopper support for other mods
]]-- ]]--
-- for lazy programmers -- for lazy programmers
@ -19,7 +19,7 @@ local CacheForFuelNodeNames = {}
local function is_fuel(stack) local function is_fuel(stack)
local name = stack:get_name() local name = stack:get_name()
if CacheForFuelNodeNames[name] then if CacheForFuelNodeNames[name] then
return true return true
end end
if minetest.get_craft_result({method="fuel", width=1, items={stack}}).time ~= 0 then if minetest.get_craft_result({method="fuel", width=1, items={stack}}).time ~= 0 then
@ -28,6 +28,19 @@ local function is_fuel(stack)
return CacheForFuelNodeNames[name] return CacheForFuelNodeNames[name]
end end
------------------------------------------------------------------------------
-- Signs Bot
------------------------------------------------------------------------------
minecart.register_inventory({"signs_bot:box"}, {
put = {
listname = "main",
},
take = {
listname = "main",
},
})
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- default -- default
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -46,14 +59,14 @@ minecart.register_inventory({"default:chest_locked", "default:chest_locked_open"
allow_inventory_put = function(pos, stack, player_name) allow_inventory_put = function(pos, stack, player_name)
local owner = M(pos):get_string("owner") local owner = M(pos):get_string("owner")
return owner == player_name return owner == player_name
end, end,
listname = "main", listname = "main",
}, },
take = { take = {
allow_inventory_take = function(pos, stack, player_name) allow_inventory_take = function(pos, stack, player_name)
local owner = M(pos):get_string("owner") local owner = M(pos):get_string("owner")
return owner == player_name return owner == player_name
end, end,
listname = "main", listname = "main",
}, },
}) })
@ -68,8 +81,8 @@ minecart.register_inventory({"default:furnace", "default:furnace_active"}, {
minetest.get_node_timer(pos):start(1.0) minetest.get_node_timer(pos):start(1.0)
if leftover:get_count() > 0 then if leftover:get_count() > 0 then
return leftover return leftover
end end
end, end,
}, },
take = { take = {
-- fuel can't be taken -- fuel can't be taken
@ -108,8 +121,8 @@ minecart.register_inventory({"digtron:combined_storage"}, {
local leftover = inv:add_item(listname, stack) local leftover = inv:add_item(listname, stack)
if leftover:get_count() > 0 then if leftover:get_count() > 0 then
return leftover return leftover
end end
end, end,
}, },
take = { take = {
-- fuel can't be taken -- fuel can't be taken

View File

@ -7,7 +7,7 @@
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--
-- for lazy programmers -- for lazy programmers
@ -49,7 +49,7 @@ end
local function zombie_to_entity(pos, cart, checkpoint) local function zombie_to_entity(pos, cart, checkpoint)
local vel = {x = 0, y = 0, z = 0} local vel = {x = 0, y = 0, z = 0}
local obj = minecart.add_entitycart(pos, cart.node_name, cart.entity_name, local obj = minecart.add_entitycart(pos, cart.node_name, cart.entity_name,
vel, cart.cargo, cart.owner, cart.userID) vel, cart.cargo, cart.owner, cart.userID)
if obj then if obj then
local entity = obj:get_luaentity() local entity = obj:get_luaentity()
@ -72,7 +72,7 @@ local function get_checkpoint(cart)
end end
-- Function returns the cart state ("running" / "stopped") and -- Function returns the cart state ("running" / "stopped") and
-- the station name or position string, or if cart is running, -- the station name or position string, or if cart is running,
-- the distance to the query_pos. -- the distance to the query_pos.
local function get_cart_state_and_loc(name, userID, query_pos) local function get_cart_state_and_loc(name, userID, query_pos)
if tCartsOnRail[name] and tCartsOnRail[name][userID] then if tCartsOnRail[name] and tCartsOnRail[name][userID] then
@ -120,7 +120,7 @@ end
local function logging(cart, err) local function logging(cart, err)
local s = string.format("[Minecart] Cart %s/%u %s!", cart.owner, cart.userID, err) local s = string.format("[Minecart] Cart %s/%u %s!", cart.owner, cart.userID, err)
minetest.log("warning", s) minetest.log("warning", s)
end end
-- check cart data -- check cart data
local function valid_cart(cart) local function valid_cart(cart)
@ -140,7 +140,7 @@ end
local function monitoring(cycle) local function monitoring(cycle)
local cart = pop(cycle) local cart = pop(cycle)
-- All running cars -- All running cars
while cart do while cart do
if valid_cart(cart) then if valid_cart(cart) then
@ -198,7 +198,7 @@ function minecart.monitoring_add_cart(owner, userID, pos, node_name, entity_name
} }
minecart.store_carts() minecart.store_carts()
end end
function minecart.start_monitoring(owner, userID, pos, objID, checkpoints, junctions, cargo) function minecart.start_monitoring(owner, userID, pos, objID, checkpoints, junctions, cargo)
--print("start_monitoring", owner, userID) --print("start_monitoring", owner, userID)
if tCartsOnRail[owner] and tCartsOnRail[owner][userID] then if tCartsOnRail[owner] and tCartsOnRail[owner][userID] then
@ -242,7 +242,7 @@ end
function minecart.monitoring_valid_cart(owner, userID, pos, node_name) function minecart.monitoring_valid_cart(owner, userID, pos, node_name)
if tCartsOnRail[owner] and tCartsOnRail[owner][userID] and tCartsOnRail[owner][userID].pos then if tCartsOnRail[owner] and tCartsOnRail[owner][userID] and tCartsOnRail[owner][userID].pos then
return vector.equals(tCartsOnRail[owner][userID].pos, pos) and return vector.equals(tCartsOnRail[owner][userID].pos, pos) and
tCartsOnRail[owner][userID].node_name == node_name tCartsOnRail[owner][userID].node_name == node_name
end end
end end
@ -271,7 +271,7 @@ minetest.register_chatcommand("mycart", {
func = function(owner, param) func = function(owner, param)
local userID = tonumber(param) local userID = tonumber(param)
local query_pos = minetest.get_player_by_name(owner):get_pos() local query_pos = minetest.get_player_by_name(owner):get_pos()
if userID then if userID then
return true, get_cart_info(owner, userID, query_pos) return true, get_cart_info(owner, userID, query_pos)
elseif tCartsOnRail[owner] then elseif tCartsOnRail[owner] then
@ -295,12 +295,12 @@ minetest.register_chatcommand("stopcart", {
local data = minecart.get_cart_monitoring_data(owner, userID) local data = minecart.get_cart_monitoring_data(owner, userID)
if data and data.objID then if data and data.objID then
local entity = minetest.luaentities[data.objID] local entity = minetest.luaentities[data.objID]
--print("stopcart", userID, data.pos, data.objID, entity) --print("stopcart", userID, data.pos, data.objID, entity)
if data.objID == 0 then if data.objID == 0 then
-- Cart as node -- Cart as node
if data.pos then if data.pos then
local meta = M(data.pos) local meta = M(data.pos)
if owner == meta:get_string("owner") and userID == meta:get_int("userID") then if owner == meta:get_string("owner") and userID == meta:get_int("userID") then
minecart.remove_nodecart(data.pos) minecart.remove_nodecart(data.pos)
end end
end end
@ -340,17 +340,17 @@ end
function minecart.get_cart_list(pos, name) function minecart.get_cart_list(pos, name)
local userIDs = {} local userIDs = {}
local carts = {} local carts = {}
for userID, cart in pairs(tCartsOnRail[name] or {}) do for userID, cart in pairs(tCartsOnRail[name] or {}) do
userIDs[#userIDs + 1] = userID userIDs[#userIDs + 1] = userID
end end
table.sort(userIDs, function(a,b) return a < b end) table.sort(userIDs, function(a,b) return a < b end)
for _, userID in ipairs(userIDs) do for _, userID in ipairs(userIDs) do
carts[#carts + 1] = get_cart_info(name, userID, pos) carts[#carts + 1] = get_cart_info(name, userID, pos)
end end
return table.concat(carts, "\n") return table.concat(carts, "\n")
end end
@ -366,9 +366,9 @@ minetest.register_on_mods_loaded(function()
default = "", default = "",
}, },
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Read state from one of your carts", label = "Read state from one of your carts",
}, },
}, },
button = function(data, environ) -- default button label button = function(data, environ) -- default button label
@ -396,9 +396,9 @@ minetest.register_on_mods_loaded(function()
default = "", default = "",
}, },
{ {
type = "label", type = "label",
name = "lbl", name = "lbl",
label = "Read location from one of your carts", label = "Read location from one of your carts",
}, },
}, },
button = function(data, environ) -- default button label button = function(data, environ) -- default button label
@ -417,7 +417,7 @@ minetest.register_on_mods_loaded(function()
end, end,
}) })
techage.lua_ctlr.register_function("cart_state", { techage.lua_ctlr.register_function("cart_state", {
cmnd = function(self, num) cmnd = function(self, num)
num = tonumber(num) or 0 num = tonumber(num) or 0
return minecart.cmnd_cart_state(self.meta.owner, num) return minecart.cmnd_cart_state(self.meta.owner, num)
end, end,
@ -427,7 +427,7 @@ minetest.register_on_mods_loaded(function()
' example: sts = $cart_state(2)' ' example: sts = $cart_state(2)'
}) })
techage.lua_ctlr.register_function("cart_location", { techage.lua_ctlr.register_function("cart_location", {
cmnd = function(self, num) cmnd = function(self, num)
num = tonumber(num) or 0 num = tonumber(num) or 0
return minecart.cmnd_cart_location(self.meta.owner, num, self.meta.pos) return minecart.cmnd_cart_location(self.meta.owner, num, self.meta.pos)
end, end,

View File

@ -7,7 +7,7 @@
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--
-- for lazy programmers -- for lazy programmers
@ -16,7 +16,7 @@ local S = minecart.S
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local S2P = minetest.string_to_pos local S2P = minetest.string_to_pos
function minecart.get_nodecart_nearby(pos, param2, radius) function minecart.get_nodecart_nearby(pos, param2, radius)
local pos2 = param2 and vector.add(pos, minecart.param2_to_dir(param2)) or pos local pos2 = param2 and vector.add(pos, minecart.param2_to_dir(param2)) or pos
local pos3 = minetest.find_node_near(pos2, radius or 0.5, minecart.lCartNodeNames, true) local pos3 = minetest.find_node_near(pos2, radius or 0.5, minecart.lCartNodeNames, true)
if pos3 then if pos3 then
@ -35,7 +35,7 @@ function minecart.start_nodecart(pos, node_name, puncher, punch_dir)
if owner ~= "" and userID ~= "" and entity_name then if owner ~= "" and userID ~= "" and entity_name then
minecart.monitoring_add_cart(owner, userID, pos, node_name, entity_name) minecart.monitoring_add_cart(owner, userID, pos, node_name, entity_name)
else else
M(pos):set_string("infotext", M(pos):set_string("infotext",
minetest.get_color_escape_sequence("#FFFF00") .. owner .. ": 0") minetest.get_color_escape_sequence("#FFFF00") .. owner .. ": 0")
return return
end end
@ -48,7 +48,7 @@ function minecart.start_nodecart(pos, node_name, puncher, punch_dir)
if obj then if obj then
local entity = obj:get_luaentity() local entity = obj:get_luaentity()
local facedir local facedir
if puncher then if puncher then
local yaw = puncher:get_look_horizontal() local yaw = puncher:get_look_horizontal()
entity.object:set_rotation({x = 0, y = yaw, z = 0}) entity.object:set_rotation({x = 0, y = yaw, z = 0})
@ -72,7 +72,7 @@ function minecart.show_formspec(pos, clicker)
"size[4,3]" .. "size[4,3]" ..
"label[0,0;" .. S("Enter cart number") .. ":]" .. "label[0,0;" .. S("Enter cart number") .. ":]" ..
"field[1,1;3,1;userID;;]" .. "field[1,1;3,1;userID;;]" ..
"button_exit[1,2;2,1;exit;" .. S("Save") .. "]") "button_exit[1,2;2,1;exit;" .. S("Save") .. "]")
end end
end end
@ -81,7 +81,7 @@ function minecart.on_nodecart_place(itemstack, placer, pointed_thing)
local node_name = itemstack:get_name() local node_name = itemstack:get_name()
local param2 = minetest.dir_to_facedir(placer:get_look_dir()) local param2 = minetest.dir_to_facedir(placer:get_look_dir())
local owner = placer:get_player_name() local owner = placer:get_player_name()
-- Add node -- Add node
if minecart.is_rail(pointed_thing.under) then if minecart.is_rail(pointed_thing.under) then
minecart.add_nodecart(pointed_thing.under, node_name, param2, {}, owner, 0) minecart.add_nodecart(pointed_thing.under, node_name, param2, {}, owner, 0)
@ -102,20 +102,19 @@ function minecart.on_nodecart_place(itemstack, placer, pointed_thing)
and creative.is_enabled_for(placer:get_player_name())) then and creative.is_enabled_for(placer:get_player_name())) then
itemstack:take_item() itemstack:take_item()
end end
return itemstack return itemstack
end end
-- Start the node cart (or dig by shift+leftclick) -- Start the node cart (or dig by shift+leftclick)
function minecart.on_nodecart_punch(pos, node, puncher, pointed_thing) function minecart.on_nodecart_punch(pos, node, puncher, pointed_thing)
--print("on_nodecart_punch")
local owner = M(pos):get_string("owner") local owner = M(pos):get_string("owner")
local userID = M(pos):get_int("userID") local rail = M(pos):get_string("removed_rail")
if minecart.is_owner(puncher, owner) then if minecart.is_owner(puncher, owner) then
if puncher:get_player_control().sneak then if puncher:get_player_control().sneak or not minecart.is_rail(pos, rail) then
local ndef = minetest.registered_nodes[node.name] local ndef = minetest.registered_nodes[node.name]
if not ndef.has_cargo or not ndef.has_cargo(pos) then if not ndef.has_cargo or not ndef.has_cargo(pos) then
minecart.remove_nodecart(pos) local _, owner, userID = minecart.remove_nodecart(pos, node)
minecart.add_node_to_player_inventory(pos, puncher, node.name) minecart.add_node_to_player_inventory(pos, puncher, node.name)
minecart.monitoring_remove_cart(owner, userID) minecart.monitoring_remove_cart(owner, userID)
end end
@ -134,7 +133,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local userID = tonumber(fields.userID) or 0 local userID = tonumber(fields.userID) or 0
if minecart.userID_available(owner, userID) then if minecart.userID_available(owner, userID) then
M(cart_pos):set_int("userID", userID) M(cart_pos):set_int("userID", userID)
M(cart_pos):set_string("infotext", M(cart_pos):set_string("infotext",
minetest.get_color_escape_sequence("#FFFF00") .. minetest.get_color_escape_sequence("#FFFF00") ..
player:get_player_name() .. ": " .. userID) player:get_player_name() .. ": " .. userID)
local node = minetest.get_node(cart_pos) local node = minetest.get_node(cart_pos)

View File

@ -3,11 +3,11 @@
Minecart Minecart
======== ========
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2023 Joachim Stolberg
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--
local S = minecart.S local S = minecart.S
@ -77,7 +77,7 @@ minetest.register_node("minecart:landmark", {
return true return true
end end
end, end,
can_dig = function(pos, digger) can_dig = function(pos, digger)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
if meta:get_string("owner") == digger:get_player_name() then if meta:get_string("owner") == digger:get_player_name() then
@ -86,17 +86,19 @@ minetest.register_node("minecart:landmark", {
if minetest.check_player_privs(digger:get_player_name(), "minecart") then if minetest.check_player_privs(digger:get_player_name(), "minecart") then
return true return true
end end
minetest.chat_send_player(digger:get_player_name(), minetest.chat_send_player(digger:get_player_name(),
S("[minecart] Area is protected!").." (owner: "..meta:get_string("owner")..")") S("[minecart] Area is protected!").." (owner: "..meta:get_string("owner")..")")
return false return false
end, end,
on_punch = function(pos, node, puncher, pointed_thing) on_punch = function(pos, node, puncher, pointed_thing)
minecart.set_land_marker(pos, RANGE, 20) minecart.set_land_marker(pos, RANGE, 20)
end, end,
paramtype2 = "facedir", paramtype = "light",
sunlight_propagates = true, sunlight_propagates = true,
paramtype2 = "facedir",
use_texture_alpha = minecart.CLIP,
groups = {cracky = 3, stone = 1}, groups = {cracky = 3, stone = 1},
is_ground_content = false, is_ground_content = false,
sounds = default.node_sound_stone_defaults(), sounds = default.node_sound_stone_defaults(),
@ -135,7 +137,10 @@ minetest.register_node("minecart:ballast_slope", {
type = "fixed", type = "fixed",
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16}, fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
}, },
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir", paramtype2 = "facedir",
use_texture_alpha = minecart.CLIP,
groups = {crumbly = 1, cracky = 3}, groups = {crumbly = 1, cracky = 3},
sounds = default.node_sound_stone_defaults(), sounds = default.node_sound_stone_defaults(),
}) })
@ -157,7 +162,10 @@ minetest.register_node("minecart:ballast_ramp", {
type = "fixed", type = "fixed",
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16}, fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
}, },
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir", paramtype2 = "facedir",
use_texture_alpha = minecart.CLIP,
groups = {crumbly = 1, cracky = 3}, groups = {crumbly = 1, cracky = 3},
sounds = default.node_sound_stone_defaults(), sounds = default.node_sound_stone_defaults(),
}) })

View File

@ -7,7 +7,7 @@
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--
-- for lazy programmers -- for lazy programmers

View File

@ -7,7 +7,7 @@
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--
-- for lazy programmers -- for lazy programmers
@ -22,9 +22,9 @@ local SLOWDOWN = 0.3
local MAX_NODES = 100 local MAX_NODES = 100
--waypoint = { --waypoint = {
-- dot = travel direction, -- dot = travel direction,
-- pos = destination pos, -- pos = destination pos,
-- speed = 10 times the section speed (as int), -- speed = 10 times the section speed (as int),
-- limit = 10 times the speed limit (as int), -- limit = 10 times the speed limit (as int),
--} --}
-- --
@ -57,8 +57,8 @@ local tRailsExt = {
} }
local tSigns = { local tSigns = {
["minecart:speed1"] = 1, ["minecart:speed1"] = 1,
["minecart:speed2"] = 2, ["minecart:speed2"] = 2,
["minecart:speed4"] = 4, ["minecart:speed4"] = 4,
["minecart:speed8"] = 8, ["minecart:speed8"] = 8,
} }
@ -123,7 +123,7 @@ end
local function get_metadata(pos) local function get_metadata(pos)
local hash = P2H(pos) local hash = P2H(pos)
if tWaypoints[hash] then if tWaypoints[hash] then
return tWaypoints[hash] return tWaypoints[hash]
end end
local s = M(pos):get_string("waypoints") local s = M(pos):get_string("waypoints")
@ -175,8 +175,8 @@ end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
local function check_right(pos, facedir) local function check_right(pos, facedir)
local fdr = (facedir + 1) % 4 -- right local fdr = (facedir + 1) % 4 -- right
local new_pos = vector.add(pos, facedir2dir(fdr)) local new_pos = vector.add(pos, facedir2dir(fdr))
local name = get_node_lvm(new_pos).name local name = get_node_lvm(new_pos).name
if tRailsExt[name] or tSigns[name] then if tRailsExt[name] or tSigns[name] then
return true return true
@ -189,8 +189,8 @@ end
local function check_left(pos, facedir) local function check_left(pos, facedir)
local fdl = (facedir + 3) % 4 -- left local fdl = (facedir + 3) % 4 -- left
local new_pos = vector.add(pos, facedir2dir(fdl)) local new_pos = vector.add(pos, facedir2dir(fdl))
local name = get_node_lvm(new_pos).name local name = get_node_lvm(new_pos).name
if tRailsExt[name] or tSigns[name] then if tRailsExt[name] or tSigns[name] then
return true return true
@ -202,7 +202,7 @@ local function check_left(pos, facedir)
end end
local function get_next_pos(pos, facedir, y) local function get_next_pos(pos, facedir, y)
local new_pos = vector.add(pos, facedir2dir(facedir)) local new_pos = vector.add(pos, facedir2dir(facedir))
new_pos.y = new_pos.y + y new_pos.y = new_pos.y + y
local name = get_node_lvm(new_pos).name local name = get_node_lvm(new_pos).name
return tRailsExt[name] ~= nil, new_pos, tRailsPower[name] or 0 return tRailsExt[name] ~= nil, new_pos, tRailsPower[name] or 0
@ -225,7 +225,7 @@ local function find_next_waypoint(pos, facedir, y)
local name = get_node_lvm(pos).name local name = get_node_lvm(pos).name
local speed = tRailsPower[name] or 0 local speed = tRailsPower[name] or 0
local is_rail, new_pos, _speed local is_rail, new_pos, _speed
while cnt < MAX_NODES do while cnt < MAX_NODES do
is_rail, new_pos, _speed = get_next_pos(pos, facedir, y) is_rail, new_pos, _speed = get_next_pos(pos, facedir, y)
speed = speed + _speed speed = speed + _speed
@ -249,8 +249,8 @@ end
-- find_all_next_waypoints -- find_all_next_waypoints
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
local function check_front_up_down(pos, facedir) local function check_front_up_down(pos, facedir)
local new_pos = vector.add(pos, facedir2dir(facedir)) local new_pos = vector.add(pos, facedir2dir(facedir))
if tRailsExt[get_node_lvm(new_pos).name] then if tRailsExt[get_node_lvm(new_pos).name] then
return 0 return 0
end end
@ -278,11 +278,11 @@ end
local function recalc_speed(num_pow_rails, pos1, pos2, y) local function recalc_speed(num_pow_rails, pos1, pos2, y)
local num_norm_rails = vector.distance(pos1, pos2) - num_pow_rails local num_norm_rails = vector.distance(pos1, pos2) - num_pow_rails
local ratio, speed local ratio, speed
if y ~= 0 then if y ~= 0 then
num_norm_rails = math.floor(num_norm_rails / 1.41 + 0.5) num_norm_rails = math.floor(num_norm_rails / 1.41 + 0.5)
end end
if y ~= -1 then if y ~= -1 then
if num_pow_rails == 0 then if num_pow_rails == 0 then
return num_norm_rails * -SLOWDOWN return num_norm_rails * -SLOWDOWN
@ -293,7 +293,7 @@ local function recalc_speed(num_pow_rails, pos1, pos2, y)
else else
ratio = 3 + num_norm_rails * SLOWDOWN + num_pow_rails ratio = 3 + num_norm_rails * SLOWDOWN + num_pow_rails
end end
if y == 1 then if y == 1 then
speed = 7 - ratio speed = 7 - ratio
elseif y == -1 then elseif y == -1 then
@ -301,14 +301,14 @@ local function recalc_speed(num_pow_rails, pos1, pos2, y)
else else
speed = 11 - ratio speed = 11 - ratio
end end
return minecart.range(speed, 0, 8) return minecart.range(speed, 0, 8)
end end
local function find_all_next_waypoints(pos) local function find_all_next_waypoints(pos)
local wp = {} local wp = {}
local dots = {} local dots = {}
for facedir = 0,3 do for facedir = 0,3 do
local y = check_front_up_down(pos, facedir) local y = check_front_up_down(pos, facedir)
if y then if y then
@ -319,7 +319,7 @@ local function find_all_next_waypoints(pos)
wp[facedir] = {dot = dot, pos = new_pos, speed = speed, is_ramp = is_ramp} wp[facedir] = {dot = dot, pos = new_pos, speed = speed, is_ramp = is_ramp}
end end
end end
return wp return wp
end end
@ -331,7 +331,7 @@ local function ramp_correction(pos, wp, facedir)
if wp.is_ramp or pos.y < wp.pos.y then -- ramp detection if wp.is_ramp or pos.y < wp.pos.y then -- ramp detection
local dir = facedir2dir(facedir) local dir = facedir2dir(facedir)
local pos = wp.pos local pos = wp.pos
wp.cart_pos = { wp.cart_pos = {
x = pos.x - dir.x / 2, x = pos.x - dir.x / 2,
y = pos.y, y = pos.y,
@ -339,7 +339,7 @@ local function ramp_correction(pos, wp, facedir)
elseif pos.y > wp.pos.y then elseif pos.y > wp.pos.y then
local dir = facedir2dir(facedir) local dir = facedir2dir(facedir)
local pos = wp.pos local pos = wp.pos
wp.cart_pos = { wp.cart_pos = {
x = pos.x + dir.x / 2, x = pos.x + dir.x / 2,
y = pos.y, y = pos.y,
@ -350,23 +350,23 @@ end
-- Returns waypoint and is_junction -- Returns waypoint and is_junction
function minecart.get_waypoint(pos, facedir, ctrl, uturn) function minecart.get_waypoint(pos, facedir, ctrl, uturn)
local t = get_metadata(pos) local t = get_metadata(pos)
if not t then if not t then
t = find_all_next_waypoints(pos) t = find_all_next_waypoints(pos)
set_metadata(pos, t) set_metadata(pos, t)
end end
local left = (facedir + 3) % 4 local left = (facedir + 3) % 4
local right = (facedir + 1) % 4 local right = (facedir + 1) % 4
local back = (facedir + 2) % 4 local back = (facedir + 2) % 4
if ctrl.right and t[right] then return t[right], t[facedir] ~= nil or t[left] ~= nil end if ctrl.right and t[right] then return t[right], t[facedir] ~= nil or t[left] ~= nil end
if ctrl.left and t[left] then return t[left] , t[facedir] ~= nil or t[right] ~= nil end if ctrl.left and t[left] then return t[left] , t[facedir] ~= nil or t[right] ~= nil end
if t[facedir] then return ramp_correction(pos, t[facedir], facedir), false end if t[facedir] then return ramp_correction(pos, t[facedir], facedir), false end
if t[right] then return ramp_correction(pos, t[right], right), false end if t[right] then return ramp_correction(pos, t[right], right), false end
if t[left] then return ramp_correction(pos, t[left], left), false end if t[left] then return ramp_correction(pos, t[left], left), false end
if uturn and t[back] then return t[back], false end if uturn and t[back] then return t[back], false end
end end
@ -389,11 +389,11 @@ local function delete_next_metadata(pos, facedir, y)
if not is_rail then if not is_rail then
return return
end end
if has_metadata(new_pos) then if has_metadata(new_pos) then
del_metadata(new_pos) del_metadata(new_pos)
end end
pos = new_pos pos = new_pos
cnt = cnt + 1 cnt = cnt + 1
end end
@ -408,27 +408,27 @@ function minecart.delete_waypoint(pos)
delete_counterpart_metadata(pos, wp) delete_counterpart_metadata(pos, wp)
return return
end end
for facedir = 0,3 do for facedir = 0,3 do
local y = check_front_up_down(pos, facedir) local y = check_front_up_down(pos, facedir)
if y then if y then
local new_pos = vector.add(pos, facedir2dir(facedir)) local new_pos = vector.add(pos, facedir2dir(facedir))
new_pos.y = new_pos.y + y new_pos.y = new_pos.y + y
if has_metadata(new_pos) then if has_metadata(new_pos) then
local wp = get_metadata(new_pos) local wp = get_metadata(new_pos)
delete_counterpart_metadata(new_pos, wp) delete_counterpart_metadata(new_pos, wp)
else else
delete_next_metadata(pos, facedir, y) delete_next_metadata(pos, facedir, y)
end end
end end
end end
end end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- find next buffer (needed as starting position) -- find next buffer (needed as starting position)
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
local function get_next_waypoints(pos) local function get_next_waypoints(pos)
local t = get_metadata(pos) local t = get_metadata(pos)
if not t then if not t then
t = find_all_next_waypoints(pos) t = find_all_next_waypoints(pos)
end end
@ -439,7 +439,7 @@ local function get_next_pos_and_facedir(waypoints, facedir)
local cnt = 0 local cnt = 0
local newpos, newfacedir local newpos, newfacedir
facedir = (facedir + 2) % 4 -- opposite dir facedir = (facedir + 2) % 4 -- opposite dir
for i = 0, 3 do for i = 0, 3 do
if waypoints[i] then if waypoints[i] then
cnt = cnt + 1 cnt = cnt + 1
@ -449,7 +449,7 @@ local function get_next_pos_and_facedir(waypoints, facedir)
end end
end end
end end
-- no junction and valid facedir -- no junction and valid facedir
if cnt < 3 and newfacedir then if cnt < 3 and newfacedir then
return newpos, newfacedir return newpos, newfacedir
@ -493,13 +493,13 @@ carts:register_rail("minecart:powerrail", {
groups = carts:get_rail_groups({not_in_creative_inventory = 1}), groups = carts:get_rail_groups({not_in_creative_inventory = 1}),
drop = "carts:powerrail", drop = "carts:powerrail",
}, {}) }, {})
for name,_ in pairs(tRails) do for name,_ in pairs(tRails) do
minetest.override_item(name, { minetest.override_item(name, {
after_destruct = minecart.delete_waypoint, after_destruct = minecart.delete_waypoint,
after_place_node = minecart.delete_waypoint, after_place_node = minecart.delete_waypoint,
}) })
end end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- API functions -- API functions
@ -509,7 +509,7 @@ function minecart.get_current_cart_pos_correction(curr_pos, curr_fd, curr_y, new
if new_dot then if new_dot then
local new_y = (new_dot % 4) - 1 local new_y = (new_dot % 4) - 1
local new_fd = math.floor(new_dot / 4) local new_fd = math.floor(new_dot / 4)
if curr_y == -1 or new_y == -1 then if curr_y == -1 or new_y == -1 then
local new_fd = math.floor(new_dot / 4) local new_fd = math.floor(new_dot / 4)
local dir = facedir2dir(new_fd) local dir = facedir2dir(new_fd)
@ -537,14 +537,14 @@ end
-- Called by carts, returns the speed value or nil -- Called by carts, returns the speed value or nil
function minecart.get_speedlimit(pos, facedir) function minecart.get_speedlimit(pos, facedir)
local fd = (facedir + 1) % 4 -- right local fd = (facedir + 1) % 4 -- right
local new_pos = vector.add(pos, facedir2dir(fd)) local new_pos = vector.add(pos, facedir2dir(fd))
local node = get_node_lvm(new_pos) local node = get_node_lvm(new_pos)
if tSigns[node.name] and node.param2 == facedir then if tSigns[node.name] and node.param2 == facedir then
return tSigns[node.name] return tSigns[node.name]
end end
fd = (facedir + 3) % 4 -- left fd = (facedir + 3) % 4 -- left
new_pos = vector.add(pos, facedir2dir(fd)) new_pos = vector.add(pos, facedir2dir(fd))
node = get_node_lvm(new_pos) node = get_node_lvm(new_pos)
if tSigns[node.name] and node.param2 == facedir then if tSigns[node.name] and node.param2 == facedir then
return tSigns[node.name] return tSigns[node.name]
@ -555,25 +555,25 @@ end
function minecart.delete_cart_waypoint(pos) function minecart.delete_cart_waypoint(pos)
del_metadata(pos) del_metadata(pos)
end end
-- Called by signs, to delete the rail waypoints nearby -- Called by signs, to delete the rail waypoints nearby
function minecart.delete_signs_waypoint(pos) function minecart.delete_signs_waypoint(pos)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
local facedir = (node.param2 + 1) % 4 -- right local facedir = (node.param2 + 1) % 4 -- right
local new_pos = vector.add(pos, facedir2dir(facedir)) local new_pos = vector.add(pos, facedir2dir(facedir))
if tRailsExt[get_node_lvm(new_pos).name] then if tRailsExt[get_node_lvm(new_pos).name] then
minecart.delete_waypoint(new_pos) minecart.delete_waypoint(new_pos)
end end
facedir = (node.param2 + 3) % 4 -- left facedir = (node.param2 + 3) % 4 -- left
new_pos = vector.add(pos, facedir2dir(facedir)) new_pos = vector.add(pos, facedir2dir(facedir))
if tRailsExt[get_node_lvm(new_pos).name] then if tRailsExt[get_node_lvm(new_pos).name] then
minecart.delete_waypoint(new_pos) minecart.delete_waypoint(new_pos)
end end
end end
function minecart.is_rail(pos) function minecart.is_rail(pos, name)
return tRails[get_node_lvm(pos).name] ~= nil return tRails[name or get_node_lvm(pos).name] ~= nil
end end
-- To register node cart names -- To register node cart names

View File

@ -7,7 +7,7 @@
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--
-- for lazy programmers -- for lazy programmers
@ -29,7 +29,7 @@ local function dashboard_destroy(self)
end end
local function dashboard_create(self) local function dashboard_create(self)
if self.driver then if self.driver then
local player = minetest.get_player_by_name(self.driver) local player = minetest.get_player_by_name(self.driver)
if player then if player then
dashboard_destroy(self) dashboard_destroy(self)
@ -51,13 +51,13 @@ local function dashboard_update(self)
local player = minetest.get_player_by_name(self.driver) local player = minetest.get_player_by_name(self.driver)
if player then if player then
local time = self.runtime or 0 local time = self.runtime or 0
local dir = (self.ctrl and self.ctrl.left and S("left")) or local dir = (self.ctrl and self.ctrl.left and S("left")) or
(self.ctrl and self.ctrl.right and S("right")) or S("straight") (self.ctrl and self.ctrl.right and S("right")) or S("straight")
local speed = math.floor((self.curr_speed or 0) + 0.5) local speed = math.floor((self.curr_speed or 0) + 0.5)
local s = string.format(S("Recording") .. local s = string.format(S("Recording") ..
" | " .. S("speed") .. " | " .. S("speed") ..
": %.1f | " .. S("next junction") .. ": %.1f | " .. S("next junction") ..
": %-8s | " .. S("Travel time") .. ": %.1f s", ": %-8s | " .. S("Travel time") .. ": %.1f s",
speed, dir, time) speed, dir, time)
player:hud_change(self.hud_id, "text", s) player:hud_change(self.hud_id, "text", s)
end end
@ -83,7 +83,7 @@ end
-- --
-- Route recording -- Route recording
-- --
function minecart.start_recording(self, pos) function minecart.start_recording(self, pos)
--print("start_recording") --print("start_recording")
if self.driver then if self.driver then
self.start_pos = minecart.get_buffer_pos(pos, self.driver) self.start_pos = minecart.get_buffer_pos(pos, self.driver)
@ -103,7 +103,7 @@ function minecart.start_recording(self, pos)
end end
end end
function minecart.stop_recording(self, pos, force_exit) function minecart.stop_recording(self, pos, force_exit)
--print("stop_recording") --print("stop_recording")
if self.driver and self.is_recording then if self.driver and self.is_recording then
local dest_pos = minecart.get_buffer_pos(pos, self.driver) local dest_pos = minecart.get_buffer_pos(pos, self.driver)
@ -112,7 +112,7 @@ function minecart.stop_recording(self, pos, force_exit)
minetest.chat_send_player(self.driver, S("[minecart] Recording canceled!")) minetest.chat_send_player(self.driver, S("[minecart] Recording canceled!"))
elseif dest_pos and player and #self.checkpoints > 3 then elseif dest_pos and player and #self.checkpoints > 3 then
-- Remove last checkpoint, because it is potentially too close to the dest_pos -- Remove last checkpoint, because it is potentially too close to the dest_pos
table.remove(self.checkpoints) table.remove(self.checkpoints)
if self.start_pos then if self.start_pos then
local route = { local route = {
dest_pos = dest_pos, dest_pos = dest_pos,
@ -138,19 +138,19 @@ function minecart.stop_recording(self, pos, force_exit)
self.junctions = nil self.junctions = nil
end end
function minecart.recording_waypoints(self) function minecart.recording_waypoints(self)
local pos = vector.round(self.object:get_pos()) local pos = vector.round(self.object:get_pos())
-- pos correction on slopes -- pos correction on slopes
if not minecart.is_rail(pos) then if not minecart.is_rail(pos) then
pos.y = pos.y - 1 pos.y = pos.y - 1
end end
-- hier müsste überprüfung dest_pos rein -- hier müsste überprüfung dest_pos rein
self.sum_speed = self.sum_speed + self.curr_speed self.sum_speed = self.sum_speed + self.curr_speed
local wp_pos = check_waypoint(self, pos) local wp_pos = check_waypoint(self, pos)
self.checkpoints[#self.checkpoints+1] = { self.checkpoints[#self.checkpoints+1] = {
-- cart_pos, next_waypoint_pos, speed, dot -- cart_pos, next_waypoint_pos, speed, dot
P2H(pos), P2H(pos),
P2H(wp_pos), P2H(wp_pos),
math.floor(self.curr_speed + 0.5), math.floor(self.curr_speed + 0.5),
self.waypoint.dot self.waypoint.dot
} }

View File

@ -34,10 +34,10 @@ local function register_sign(def)
"default_steel_block.png", "default_steel_block.png",
"default_steel_block.png^"..def.image, "default_steel_block.png^"..def.image,
}, },
after_place_node = minecart.delete_signs_waypoint, after_place_node = minecart.delete_signs_waypoint,
preserve_metadata = minecart.delete_signs_waypoint, preserve_metadata = minecart.delete_signs_waypoint,
on_rotate = screwdriver.disallow, on_rotate = screwdriver.disallow,
paramtype = "light", paramtype = "light",
use_texture_alpha = minecart.CLIP, use_texture_alpha = minecart.CLIP,

View File

@ -7,7 +7,7 @@
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--
-- for lazy programmers -- for lazy programmers

View File

@ -7,7 +7,7 @@
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--
-- for lazy programmers -- for lazy programmers
@ -25,7 +25,7 @@ end
local function formspec(pos, text) local function formspec(pos, text)
text = minetest.formspec_escape(text) text = minetest.formspec_escape(text)
text = text:gsub("\n", ",") text = text:gsub("\n", ",")
return "size[11,9]".. return "size[11,9]"..
default.gui_bg.. default.gui_bg..
default.gui_bg_img.. default.gui_bg_img..
@ -54,7 +54,7 @@ minetest.register_node("minecart:terminal", {
{ -8/16, -8/16, 0/16, 8/16, 8/16, 8/16}, { -8/16, -8/16, 0/16, 8/16, 8/16, 8/16},
}, },
}, },
after_place_node = function(pos, placer) after_place_node = function(pos, placer)
local meta = M(pos) local meta = M(pos)
meta:set_string("owner", placer:get_player_name()) meta:set_string("owner", placer:get_player_name())
@ -66,7 +66,7 @@ minetest.register_node("minecart:terminal", {
end end
minetest.get_node_timer(pos):start(2) minetest.get_node_timer(pos):start(2)
end, end,
on_timer = function(pos, elapsed) on_timer = function(pos, elapsed)
if is_player_nearby(pos) then if is_player_nearby(pos) then
local text = minecart.get_cart_list(pos, M(pos):get_string("owner")) local text = minecart.get_cart_list(pos, M(pos):get_string("owner"))
@ -74,7 +74,7 @@ minetest.register_node("minecart:terminal", {
end end
return true return true
end, end,
paramtype2 = "facedir", paramtype2 = "facedir",
paramtype = "light", paramtype = "light",
use_texture_alpha = minecart.CLIP, use_texture_alpha = minecart.CLIP,
@ -131,4 +131,4 @@ minetest.register_on_mods_loaded(function()
end, end,
}) })
end end
end) end)

View File

@ -7,7 +7,7 @@
MIT MIT
See license.txt for more information See license.txt for more information
]]-- ]]--
-- for lazy programmers -- for lazy programmers
@ -19,7 +19,7 @@ local P2H = minetest.hash_node_position
local sDir = {[0] = "north", "east", "south", "west"} local sDir = {[0] = "north", "east", "south", "west"}
local function DOTS(dots) local function DOTS(dots)
if dots then if dots then
return table.concat(dots, ", ") return table.concat(dots, ", ")
else else
@ -50,15 +50,15 @@ local function test_get_route(pos, node, player)
if route.cart_pos then if route.cart_pos then
minecart.set_marker(route.cart_pos, "cart", 0.3, 10) minecart.set_marker(route.cart_pos, "cart", 0.3, 10)
end end
-- determine some kind of current y -- determine some kind of current y
old_pos = old_pos or pos old_pos = old_pos or pos
local curr_y = pos.y > old_pos.y and 1 or pos.y < old_pos.y and -1 or 0 local curr_y = pos.y > old_pos.y and 1 or pos.y < old_pos.y and -1 or 0
local cart_pos, extra_cycle = minecart.get_current_cart_pos_correction(pos, facedir, curr_y, route.dot) local cart_pos, extra_cycle = minecart.get_current_cart_pos_correction(pos, facedir, curr_y, route.dot)
minecart.set_marker(cart_pos, "curr", 0.3, 10) minecart.set_marker(cart_pos, "curr", 0.3, 10)
old_pos = pos old_pos = pos
print(string.format("Route: dist = %u, dot = %u, speed = %d, extra cycle = %s", print(string.format("Route: dist = %u, dot = %u, speed = %d, extra cycle = %s",
vector.distance(pos, route.pos), route.dot, route.speed or 0, extra_cycle)) vector.distance(pos, route.pos), route.dot, route.speed or 0, extra_cycle))
end end
end end

View File

@ -80,7 +80,7 @@ All this testing nodes can be enabled via mod settings `networks_test_enabled =
### License ### License
Copyright (C) 2021-2022 Joachim Stolberg Copyright (C) 2021-2023 Joachim Stolberg
Code: Licensed under the GNU AGPL version 3 or later. See LICENSE.txt Code: Licensed under the GNU AGPL version 3 or later. See LICENSE.txt
Textures: CC BY-SA 3.0 Textures: CC BY-SA 3.0
@ -131,3 +131,6 @@ Required: tubelib2
**2022-09-10 V0.12** **2022-09-10 V0.12**
- New API function `networks.liquid.get_liquids` added - New API function `networks.liquid.get_liquids` added
**2023-02-19 V0.13**
- New API function `networks.power.get_storage_percent` added

View File

@ -3,7 +3,7 @@
Networks Networks
======== ========
Copyright (C) 2021 Joachim Stolberg Copyright (C) 2021-2023 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -13,7 +13,7 @@
networks = {} networks = {}
-- Version for compatibility checks, see readme.md/history -- Version for compatibility checks, see readme.md/history
networks.version = 0.12 networks.version = 0.13
if not minetest.global_exists("tubelib2") or tubelib2.version < 2.2 then if not minetest.global_exists("tubelib2") or tubelib2.version < 2.2 then
minetest.log("error", "[networks] Networks requires tubelib2 version 2.2 or newer!") minetest.log("error", "[networks] Networks requires tubelib2 version 2.2 or newer!")

View File

@ -190,8 +190,9 @@ function networks.liquid.srv_put(nvm, name, amount, capa)
assert(capa and capa > 0) assert(capa and capa > 0)
amount = math.floor((amount or 0) + 0.5) amount = math.floor((amount or 0) + 0.5)
nvm.liquid = nvm.liquid or {} nvm.liquid = nvm.liquid or {}
nvm.liquid.amount = nvm.liquid.amount or 0
if not nvm.liquid.name then if nvm.liquid.amount == 0 or not nvm.liquid.name then
nvm.liquid.name = name nvm.liquid.name = name
nvm.liquid.amount = amount nvm.liquid.amount = amount
return 0 return 0
@ -292,4 +293,4 @@ function networks.liquid.get_liquids(pos, tlib2)
out[#out + 1] = k out[#out + 1] = k
end end
return out return out
end end

View File

@ -3,7 +3,7 @@
Networks Networks
======== ========
Copyright (C) 2021 Joachim Stolberg Copyright (C) 2021-2023 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -439,3 +439,13 @@ function networks.power.get_network_data(pos, tlib2, outdir)
end end
return DEFAULT_DATA return DEFAULT_DATA
end end
function networks.power.get_storage_percent(pos, tlib2, outdir)
assert(outdir)
local netID = networks.determine_netID(pos, tlib2, outdir)
if netID then
local pwr = Power[netID] or get_power_data(pos, tlib2, outdir, netID)
return (pwr.curr_load or 0) * 100 / (pwr.max_capa or 1)
end
return 0
end

View File

@ -85,6 +85,7 @@ For all Inventory commands applies: If the bot inventory stack specified by `<sl
dig_below <slot> - dig block under the robot dig_below <slot> - dig block under the robot
dig_above <slot> - dig block above the robot dig_above <slot> - dig block above the robot
rotate_item <lvl> <steps> - rotate a block in front of the robot rotate_item <lvl> <steps> - rotate a block in front of the robot
set_param2 <lvl> <param2> - set param2 of the block in front of the robot
place_sign <slot> - set sign place_sign <slot> - set sign
place_sign_behind <slot> - put a sign behind the bot place_sign_behind <slot> - put a sign behind the bot
dig_sign <slot> - remove the sign dig_sign <slot> - remove the sign

View File

@ -395,6 +395,42 @@ signs_bot.register_botcommand("rotate_item", {
end, end,
}) })
local function set_param2(base_pos, robot_pos, bot_param2, route, level, block_param2)
local pos1 = lib.dest_pos(robot_pos, bot_param2, route)
pos1.y = pos1.y + level
local node = tubelib2.get_node_lvm(pos1)
if not lib.not_protected(base_pos, pos1) then
return signs_bot.ERROR, S("Error: Position protected")
end
if lib.is_simple_node(node) then
if block_param2 then
minetest.swap_node(pos1, {name=node.name, param2=block_param2})
end
end
return signs_bot.DONE
end
signs_bot.register_botcommand("set_param2", {
mod = "place",
params = "<lvl> <param2>",
num_param = 2,
description = S("Set param2 of the block in front of the robot\n"..
"<lvl> is one of: -1 0 +1\n"..
"<param2> is: 0 - 23"),
check = function(lvl, param2)
param2 = tonumber(param2) or 0
if not param2 or param2 < 0 or param2 > 23 then
return false
end
return tValidLevels[lvl] ~= nil
end,
cmnd = function(base_pos, mem, lvl, param2)
local level = tValidLevels[lvl]
param2 = tonumber(param2) or 0
return set_param2(base_pos, mem.robot_pos, mem.robot_param2, {0}, level, param2)
end,
})
-- Simplified torch which can be placed w/o a fake player -- Simplified torch which can be placed w/o a fake player
minetest.register_node("signs_bot:torch", { minetest.register_node("signs_bot:torch", {
description = S("Bot torch"), description = S("Bot torch"),

View File

@ -27,7 +27,7 @@ In the worst case, the server crashes.**
### License ### License
Copyright (C) 2019-2022 Joachim Stolberg Copyright (C) 2019-2023 Joachim Stolberg
Code: Licensed under the GNU AGPL version 3 or later. See LICENSE.txt Code: Licensed under the GNU AGPL version 3 or later. See LICENSE.txt
Textures: CC BY-SA 3.0 Textures: CC BY-SA 3.0
@ -89,6 +89,24 @@ Available worlds will be converted to 'lsqlite3', but there is no way back, so:
### History ### History
**2023-03-05 V1.11**
- Reduce the number of necessary exp points for TA5 Hyperloop Chest,
TA5 Hyperloop Tank, and TA5 AI Chip II
- Fix possible kernel crashes with TA5 Hyperloop Chest and autocrafter
- Rework doorcontroller (menu changed)
- Increase tank cart storage size to 200 units
- Fix several paramtype/use_texture_alpha issues
- Add command 'load' to the TA4 power terminal
- Add beduino tank commands
- Fix power consumption bug for a stopped collider
- Fix electrolyzer formspec bug
- Add Rack and pinion node
- Expand ta4 sequencer wrench menu
- Accept mincart carts for the move controller
- movecontroller: Allow to move objects 'without' a move block
- Add empty_spool as fab output
- Fix doser goes blocked bug
**2023-02-04 V1.10** **2023-02-04 V1.10**
- Improve flycontroller - Improve flycontroller
- Remove handover for movecontroller - Remove handover for movecontroller

View File

@ -266,6 +266,9 @@ end
local function allow_metadata_inventory_put(pos, listname, index, stack, player) local function allow_metadata_inventory_put(pos, listname, index, stack, player)
if listname == "output" then
return 0
end
if minetest.is_protected(pos, player:get_player_name()) then if minetest.is_protected(pos, player:get_player_name()) then
return 0 return 0
end end
@ -285,6 +288,9 @@ local function allow_metadata_inventory_put(pos, listname, index, stack, player)
end end
local function allow_metadata_inventory_take(pos, listname, index, stack, player) local function allow_metadata_inventory_take(pos, listname, index, stack, player)
if listname == "output" then
return 0
end
if minetest.is_protected(pos, player:get_player_name()) then if minetest.is_protected(pos, player:get_player_name()) then
return 0 return 0
end end
@ -302,6 +308,9 @@ local function allow_metadata_inventory_take(pos, listname, index, stack, player
end end
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player) local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
if from_list == "output" or "to_list" == "output" then
return 0
end
if minetest.is_protected(pos, player:get_player_name()) then if minetest.is_protected(pos, player:get_player_name()) then
return 0 return 0
end end

View File

@ -77,8 +77,9 @@ local function making(pos, crd, nvm, inv)
local owner = M(pos):get_string("owner") local owner = M(pos):get_string("owner")
local rtype = RecipeType[crd.stage] local rtype = RecipeType[crd.stage]
local recipe = recipes.get(nvm, rtype, owner) local recipe = recipes.get(nvm, rtype, owner)
local output = ItemStack(recipe.output.name.." "..recipe.output.num) local output = ItemStack(recipe.output.name .. " " .. recipe.output.num)
if inv:room_for_item("dst", output) then local waste = recipe.waste and ItemStack(recipe.waste.name .. " " .. recipe.waste.num)
if inv:room_for_item("dst", output) and (not waste or inv:room_for_item("dst", waste)) then
for _,item in ipairs(recipe.input) do for _,item in ipairs(recipe.input) do
local input = ItemStack(item.name.." "..item.num) local input = ItemStack(item.name.." "..item.num)
if not inv:contains_item("src", input) then if not inv:contains_item("src", input) then
@ -91,6 +92,9 @@ local function making(pos, crd, nvm, inv)
inv:remove_item("src", input) inv:remove_item("src", input)
end end
inv:add_item("dst", output) inv:add_item("dst", output)
if waste then
inv:add_item("dst", waste)
end
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS) crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
return return
end end

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2022 Joachim Stolberg Copyright (C) 2019-2023 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -22,6 +22,7 @@ local STACK_SIZE = 2000
local function gen_stack(inv, idx) local function gen_stack(inv, idx)
inv[idx] = {name = "", count = 0} inv[idx] = {name = "", count = 0}
return inv[idx]
end end
local function gen_inv(nvm) local function gen_inv(nvm)
@ -377,7 +378,7 @@ local function search_chest_in_front(pos, node)
pos1 = tubelib2.get_pos(pos1, dir) pos1 = tubelib2.get_pos(pos1, dir)
cnt = cnt + 1 cnt = cnt + 1
end end
if node.name == "techage:ta4_chest" then if node.name == "techage:ta4_chest" and node.param2 == param2 then
minetest.after(1, count_number_of_chests, pos1) minetest.after(1, count_number_of_chests, pos1)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
nvm.front_chest_pos = pos1 nvm.front_chest_pos = pos1

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2022 Joachim Stolberg Copyright (C) 2019-2023 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -19,7 +19,7 @@ local M = minetest.get_meta
local S = techage.S local S = techage.S
local TA4_INV_SIZE = 32 local TA4_INV_SIZE = 32
local EX_POINTS = 20 local EX_POINTS = 15
local hyperloop = techage.hyperloop local hyperloop = techage.hyperloop
local remote_pos = techage.hyperloop.remote_pos local remote_pos = techage.hyperloop.remote_pos
@ -49,7 +49,7 @@ local function allow_metadata_inventory_put(pos, listname, index, stack, player)
end end
shared_inv.before_inv_access(pos, listname) shared_inv.before_inv_access(pos, listname)
local inv = minetest.get_inventory({type="node", pos=pos}) local inv = minetest.get_inventory({type="node", pos=pos})
if inv:room_for_item(listname, stack) then if inv and inv:room_for_item(listname, stack) then
return stack:get_count() return stack:get_count()
end end
return 0 return 0
@ -61,7 +61,7 @@ local function allow_metadata_inventory_take(pos, listname, index, stack, player
end end
shared_inv.before_inv_access(pos, listname) shared_inv.before_inv_access(pos, listname)
local inv = minetest.get_inventory({type="node", pos=pos}) local inv = minetest.get_inventory({type="node", pos=pos})
if inv:contains_item(listname, stack) then if inv and inv:contains_item(listname, stack) then
return stack:get_count() return stack:get_count()
end end
return 0 return 0
@ -141,36 +141,64 @@ minetest.register_node("techage:ta5_hl_chest", {
techage.register_node({"techage:ta5_hl_chest"}, { techage.register_node({"techage:ta5_hl_chest"}, {
on_inv_request = function(pos, in_dir, access_type) on_inv_request = function(pos, in_dir, access_type)
pos = remote_pos(pos) pos = remote_pos(pos)
local meta = minetest.get_meta(pos) if pos then
return meta:get_inventory(), "main" local meta = minetest.get_meta(pos)
if meta then
return meta:get_inventory(), "main"
end
end
end, end,
on_pull_item = function(pos, in_dir, num, item_name) on_pull_item = function(pos, in_dir, num, item_name)
pos = remote_pos(pos) pos = remote_pos(pos)
local meta = minetest.get_meta(pos) if pos then
local inv = meta:get_inventory() local meta = minetest.get_meta(pos)
return techage.get_items(pos, inv, "main", num) if meta then
local inv = meta:get_inventory()
if inv then
return techage.get_items(pos, inv, "main", num)
end
end
end
return false
end, end,
on_push_item = function(pos, in_dir, stack) on_push_item = function(pos, in_dir, stack)
if techage.hyperloop.is_paired(pos) then if techage.hyperloop.is_paired(pos) then
pos = remote_pos(pos) pos = remote_pos(pos)
local meta = minetest.get_meta(pos) if pos then
local inv = meta:get_inventory() local meta = minetest.get_meta(pos)
return techage.put_items(inv, "main", stack) if meta then
local inv = meta:get_inventory()
if inv then
return techage.put_items(inv, "main", stack)
end
end
end
end end
return false return false
end, end,
on_unpull_item = function(pos, in_dir, stack) on_unpull_item = function(pos, in_dir, stack)
pos = remote_pos(pos) pos = remote_pos(pos)
local meta = minetest.get_meta(pos) if pos then
local inv = meta:get_inventory() local meta = minetest.get_meta(pos)
return techage.put_items(inv, "main", stack) if meta then
local inv = meta:get_inventory()
if inv then
return techage.put_items(inv, "main", stack)
end
end
end
return false
end, end,
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
if topic == "state" then if topic == "state" then
pos = remote_pos(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local inv = meta:get_inventory() if meta then
return techage.get_inv_state(inv, "main") local inv = meta:get_inventory()
if inv then
return techage.get_inv_state(inv, "main")
end
end
return "error"
else else
return "unsupported" return "unsupported"
end end
@ -178,8 +206,12 @@ techage.register_node({"techage:ta5_hl_chest"}, {
on_beduino_request_data = function(pos, src, topic, payload) on_beduino_request_data = function(pos, src, topic, payload)
if topic == 131 then -- Chest State if topic == 131 then -- Chest State
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local inv = meta:get_inventory() if meta then
return 0, {techage.get_inv_state_num(inv, "main")} local inv = meta:get_inventory()
if inv then
return 0, {techage.get_inv_state_num(inv, "main")}
end
end
else else
return 2, "" return 2, ""
end end

View File

@ -37,7 +37,8 @@ local function rotate(v, yaw)
return {x = v.x * cosyaw - v.z * sinyaw, y = v.y, z = v.x * sinyaw + v.z * cosyaw} return {x = v.x * cosyaw - v.z * sinyaw, y = v.y, z = v.x * sinyaw + v.z * cosyaw}
end end
local function set_node(item) -- playername is needed for carts, to attach the player to the cart entity
local function set_node(item, playername)
local dest_pos = item.dest_pos local dest_pos = item.dest_pos
local name = item.name or "air" local name = item.name or "air"
local param2 = item.param2 or 0 local param2 = item.param2 or 0
@ -49,12 +50,18 @@ local function set_node(item)
nvm.running = false nvm.running = false
M(item.base_pos):set_string("status", S("Stopped")) M(item.base_pos):set_string("status", S("Stopped"))
if ndef1 and ndef2 then if ndef1 and ndef2 then
if ndef2.buildable_to then if minecart.is_cart(name) and (minecart.is_rail(dest_pos, node.name) or minecart.is_cart(name)) then
local player = playername and minetest.get_player_by_name(playername)
minecart.place_and_start_cart(dest_pos, {name = name, param2 = param2}, item.cartdef, player)
return
elseif ndef2.buildable_to then
local meta = M(dest_pos) local meta = M(dest_pos)
minetest.set_node(dest_pos, {name=name, param2=param2}) if name ~= "techage:moveblock" then
meta:from_table(item.metadata or {}) minetest.set_node(dest_pos, {name=name, param2=param2})
meta:set_string("ta_move_block", "") meta:from_table(item.metadata or {})
meta:set_int("ta_door_locked", 1) meta:set_string("ta_move_block", "")
meta:set_int("ta_door_locked", 1)
end
return return
end end
local meta = M(dest_pos) local meta = M(dest_pos)
@ -63,7 +70,9 @@ local function set_node(item)
return return
end end
elseif ndef1 then elseif ndef1 then
minetest.add_item(dest_pos, ItemStack(name)) if name ~= "techage:moveblock" then
minetest.add_item(dest_pos, ItemStack(name))
end
end end
end end
@ -294,7 +303,7 @@ local function detach_player(player)
end end
-- Attach player/mob to given parent object (block) -- Attach player/mob to given parent object (block)
local function attach_single_object(parent, obj, dir) local function attach_single_object(parent, obj, distance)
local self = parent:get_luaentity() local self = parent:get_luaentity()
local res = obj:get_attach() local res = obj:get_attach()
if not res then -- not already attached if not res then -- not already attached
@ -305,20 +314,20 @@ local function attach_single_object(parent, obj, dir)
yaw = obj:get_rotation().y yaw = obj:get_rotation().y
end end
-- store for later use -- store for later use
local offs = table.copy(dir) local offs = table.copy(distance)
-- Calc entity rotation, which is relative to the parent's rotation -- Calc entity rotation, which is relative to the parent's rotation
local rot = parent:get_rotation() local rot = parent:get_rotation()
if self.param2 >= 20 then if self.param2 >= 20 then
dir = rotate(dir, 2 * math.pi - rot.y) distance = rotate(distance, 2 * math.pi - rot.y)
dir.y = -dir.y distance.y = -distance.y
dir.x = -dir.x distance.x = -distance.x
rot.y = rot.y - yaw rot.y = rot.y - yaw
elseif self.param2 < 4 then elseif self.param2 < 4 then
dir = rotate(dir, 2 * math.pi - rot.y) distance = rotate(distance, 2 * math.pi - rot.y)
rot.y = rot.y - yaw rot.y = rot.y - yaw
end end
dir = vector.multiply(dir, 29) distance = vector.multiply(distance, 29)
obj:set_attach(parent, "", dir, vector.multiply(rot, 180 / math.pi)) obj:set_attach(parent, "", distance, vector.multiply(rot, 180 / math.pi))
obj:set_properties({visual_size = {x=2.9, y=2.9}}) obj:set_properties({visual_size = {x=2.9, y=2.9}})
if obj:is_player() then if obj:is_player() then
if lock_player(obj) then if lock_player(obj) then
@ -332,19 +341,21 @@ end
-- Attach all objects around to the parent object -- Attach all objects around to the parent object
-- offs is the search/attach position offset -- offs is the search/attach position offset
local function attach_objects(pos, offs, parent, yoffs) -- distance (optional) is the attach distance to the center of the entity
local function attach_objects(pos, offs, parent, yoffs, distance)
local pos1 = vector.add(pos, offs) local pos1 = vector.add(pos, offs)
for _, obj in pairs(minetest.get_objects_inside_radius(pos1, 0.9)) do for _, obj in pairs(minetest.get_objects_inside_radius(pos1, 0.9)) do
local dir = vector.subtract(obj:get_pos(), pos) -- keep relative object position
distance = distance or vector.subtract(obj:get_pos(), pos)
local entity = obj:get_luaentity() local entity = obj:get_luaentity()
if entity then if entity then
local mod = entity.name:gmatch("(.-):")() local mod = entity.name:gmatch("(.-):")()
if techage.RegisteredMobsMods[mod] then if techage.RegisteredMobsMods[mod] then
dir.y = dir.y + yoffs distance.y = distance.y + yoffs
attach_single_object(parent, obj, dir) attach_single_object(parent, obj, distance)
end end
elseif obj:is_player() then elseif obj:is_player() then
attach_single_object(parent, obj, dir) attach_single_object(parent, obj, distance)
end end
end end
end end
@ -380,10 +391,11 @@ end
local function entity_to_node(pos, obj) local function entity_to_node(pos, obj)
local self = obj:get_luaentity() local self = obj:get_luaentity()
if self and self.item then if self and self.item then
local playername = self.players and self.players[1] and self.players[1].name
detach_objects(pos, self) detach_objects(pos, self)
monitoring_del_entity(self.item) monitoring_del_entity(self.item)
minetest.after(0.1, obj.remove, obj) minetest.after(0.1, obj.remove, obj)
set_node(self.item) set_node(self.item, playername)
end end
end end
@ -392,9 +404,12 @@ end
-- * start_pos and dest_pos are entity positions -- * start_pos and dest_pos are entity positions
local function node_to_entity(base_pos, start_pos, dest_pos) local function node_to_entity(base_pos, start_pos, dest_pos)
local meta = M(start_pos) local meta = M(start_pos)
local node, metadata local node, metadata, cartdef
if meta:contains("ta_move_block") then node = techage.get_node_lvm(start_pos)
if minecart.is_cart(node.name) then
cartdef = minecart.remove_cart(start_pos)
elseif meta:contains("ta_move_block") then
-- Move-block stored as metadata -- Move-block stored as metadata
node = minetest.deserialize(meta:get_string("ta_move_block")) node = minetest.deserialize(meta:get_string("ta_move_block"))
metadata = {} metadata = {}
@ -424,6 +439,7 @@ local function node_to_entity(base_pos, start_pos, dest_pos)
metadata = metadata or {}, metadata = metadata or {},
dest_pos = dest_pos, dest_pos = dest_pos,
base_pos = base_pos, base_pos = base_pos,
cartdef = cartdef,
} }
monitoring_add_entity(self.item) monitoring_add_entity(self.item)
@ -432,7 +448,7 @@ local function node_to_entity(base_pos, start_pos, dest_pos)
self.entities = {} self.entities = {}
-- Prepare for path walk -- Prepare for path walk
self.path_idx = 1 self.path_idx = 1
return obj return obj, self.item.cartdef ~= nil
end end
end end
@ -536,6 +552,9 @@ local function is_valid_dest(pos)
if techage.is_air_like(node.name) then if techage.is_air_like(node.name) then
return true return true
end end
if minecart.is_rail(pos, node.name) or minecart.is_cart(node.name) then
return true
end
if not M(pos):contains("ta_move_block") then if not M(pos):contains("ta_move_block") then
return true return true
end end
@ -543,9 +562,15 @@ local function is_valid_dest(pos)
end end
local function is_simple_node(pos) local function is_simple_node(pos)
local node =techage.get_node_lvm(pos) local node = techage.get_node_lvm(pos)
local ndef = minetest.registered_nodes[node.name] if not minecart.is_rail(pos, node.name) then
return not techage.is_air_like(node.name) and techage.can_dig_node(node.name, ndef) if node.name == "air" then
minetest.swap_node(pos, {name = "techage:moveblock", param2 = 0})
return true
end
local ndef = minetest.registered_nodes[node.name]
return not techage.is_air_like(node.name) and techage.can_dig_node(node.name, ndef) or minecart.is_cart(node.name)
end
end end
-- Move node from 'pos1' to the destination, calculated by means of 'lmove' -- Move node from 'pos1' to the destination, calculated by means of 'lmove'
@ -562,14 +587,18 @@ local function move_node(pos, meta, pos1, lmove, max_speed, height)
if pos2 then if pos2 then
local dir = determine_dir(pos1, pos2) local dir = determine_dir(pos1, pos2)
local obj = node_to_entity(pos, pos1, dest_pos) local obj, is_cart = node_to_entity(pos, pos1, dest_pos)
if obj then if obj then
local offs = {x=0, y=height or 1, z=0} if is_cart then
attach_objects(pos1, offs, obj, yoffs) attach_objects(pos1, 0, obj, yoffs, {x = 0, y = -0.4, z = 0})
if dir.y == 0 then else
if (dir.x ~= 0 and dir.z == 0) or (dir.x == 0 and dir.z ~= 0) then local offs = {x=0, y=height or 1, z=0}
attach_objects(pos1, dir, obj, yoffs) attach_objects(pos1, offs, obj, yoffs)
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, yoffs)
end
end end
end end
local self = obj:get_luaentity() local self = obj:get_luaentity()
@ -801,6 +830,21 @@ function flylib.remove_node(pos)
end end
end end
minetest.register_node("techage:moveblock", {
description = "Techage Move Block",
drawtype = "normal",
tiles = {"techage_invisible.png"},
sunlight_propagates = true,
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
floodable = true,
is_ground_content = false,
groups = {not_in_creative_inventory=1},
drop = "",
})
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
unlock_player(player) unlock_player(player)
end) end)

View File

@ -184,7 +184,7 @@ function techage.hyperloop.remote_pos(pos)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
if Stations:get(nvm.rmt_pos) then if Stations:get(nvm.rmt_pos) then
if M(pos):contains("remote_name") then if M(pos):contains("remote_name") then
return nvm.rmt_pos return nvm.rmt_pos or pos
end end
end end
end end

View File

@ -75,6 +75,24 @@ techage.liquid.recv_message = {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_request_data = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == 128 then
return 0, techage.get_node_lvm(pos).name
elseif topic == 134 then
local nvm = techage.get_nvm(pos)
nvm.liquid = nvm.liquid or {}
nvm.liquid.amount = nvm.liquid.amount or 0
if payload[1] == 1 then
local value = techage.power.percent(LQD(pos).capa, nvm.liquid.amount)
return 0, {math.floor(value + 0.5)}
else
return 0, {nvm.liquid.amount}
end
else
return 2, ""
end
end,
} }
-- like: register_liquid("techage:ta3_barrel_oil", "techage:ta3_barrel_empty", 10, "techage:oil") -- like: register_liquid("techage:ta3_barrel_oil", "techage:ta3_barrel_empty", 10, "techage:oil")

View File

@ -159,8 +159,10 @@ function techage.recipes.on_receive_fields(pos, formname, fields, player)
if not nvm.running then if not nvm.running then
if fields.next == ">>" then if fields.next == ">>" then
nvm.recipe_idx = nvm.recipe_idx + 1 nvm.recipe_idx = nvm.recipe_idx + 1
return true
elseif fields.priv == "<<" then elseif fields.priv == "<<" then
nvm.recipe_idx = nvm.recipe_idx - 1 nvm.recipe_idx = nvm.recipe_idx - 1
return true
end end
end end
end end

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2022 Joachim Stolberg Copyright (C) 2019-2023 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -31,7 +31,7 @@ end
function techage.shared_inv.node_timer(pos, elapsed) function techage.shared_inv.node_timer(pos, elapsed)
local rmt_pos = remote_pos(pos) local rmt_pos = remote_pos(pos)
if techage.is_activeformspec(pos) then if rmt_pos and techage.is_activeformspec(pos) then
copy_inventory_list(rmt_pos, pos, "main") copy_inventory_list(rmt_pos, pos, "main")
return true return true
end end
@ -42,8 +42,10 @@ end
function techage.shared_inv.before_inv_access(pos, listname) function techage.shared_inv.before_inv_access(pos, listname)
if hyperloop.is_client(pos) then if hyperloop.is_client(pos) then
local rmt_pos = remote_pos(pos) local rmt_pos = remote_pos(pos)
copy_inventory_list(rmt_pos, pos, listname) if rmt_pos then
return true copy_inventory_list(rmt_pos, pos, listname)
return true
end
end end
return false return false
end end
@ -52,8 +54,10 @@ end
function techage.shared_inv.after_inv_access(pos, listname) function techage.shared_inv.after_inv_access(pos, listname)
if hyperloop.is_client(pos) then if hyperloop.is_client(pos) then
local rmt_pos = remote_pos(pos) local rmt_pos = remote_pos(pos)
copy_inventory_list(pos, rmt_pos, listname) if rmt_pos then
return true copy_inventory_list(pos, rmt_pos, listname)
return true
end
end end
return false return false
end end
@ -61,8 +65,10 @@ end
function techage.shared_inv.on_rightclick(pos, clicker, listname) function techage.shared_inv.on_rightclick(pos, clicker, listname)
if hyperloop.is_client(pos) then if hyperloop.is_client(pos) then
local rmt_pos = remote_pos(pos) local rmt_pos = remote_pos(pos)
copy_inventory_list(rmt_pos, pos, listname) if rmt_pos then
techage.set_activeformspec(pos, clicker) copy_inventory_list(rmt_pos, pos, listname)
minetest.get_node_timer(pos):start(2) techage.set_activeformspec(pos, clicker)
minetest.get_node_timer(pos):start(2)
end
end end
end end

View File

@ -21,7 +21,7 @@ local Pipe = techage.LiquidPipe
local MP = minetest.get_modpath("minecart") local MP = minetest.get_modpath("minecart")
local liquid = networks.liquid local liquid = networks.liquid
local CAPACITY = 100 local CAPACITY = 200
local function on_rightclick(pos, node, clicker) local function on_rightclick(pos, node, clicker)
if clicker and clicker:is_player() then if clicker and clicker:is_player() then

View File

@ -272,7 +272,11 @@ local function on_receive_fields(pos, formname, fields, player)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
if not nvm.running then if not nvm.running then
recipes.on_receive_fields(pos, formname, fields, player) if recipes.on_receive_fields(pos, formname, fields, player) then
local mem = techage.get_mem(pos)
mem.waste_leftover = nil
mem.output_leftover = nil
end
end end
local mem = techage.get_mem(pos) local mem = techage.get_mem(pos)
mem.dbg_cycles = 5 mem.dbg_cycles = 5

View File

@ -82,7 +82,7 @@ minetest.register_node("techage:turbine", {
"techage_filling_ta3.png^techage_frame_ta3.png", "techage_filling_ta3.png^techage_frame_ta3.png",
"techage_filling_ta3.png^techage_appl_open.png^techage_frame_ta3.png", "techage_filling_ta3.png^techage_appl_open.png^techage_frame_ta3.png",
"techage_filling_ta3.png^techage_frame_ta3.png^techage_steam_hole.png", "techage_filling_ta3.png^techage_frame_ta3.png^techage_steam_hole.png",
"techage_filling_ta3.png^techage_appl_turbine.png^techage_frame_ta3.png", "techage_filling_ta3.png^techage_appl_turbine.png^techage_frame_ta3.png^[transformFX",
"techage_filling_ta3.png^techage_appl_turbine.png^techage_frame_ta3.png", "techage_filling_ta3.png^techage_appl_turbine.png^techage_frame_ta3.png",
}, },
@ -105,7 +105,7 @@ minetest.register_node("techage:turbine_on", {
"techage_filling_ta3.png^techage_appl_open.png^techage_frame_ta3.png", "techage_filling_ta3.png^techage_appl_open.png^techage_frame_ta3.png",
"techage_filling_ta3.png^techage_frame_ta3.png^techage_steam_hole.png", "techage_filling_ta3.png^techage_frame_ta3.png^techage_steam_hole.png",
{ {
image = "techage_filling4_ta3.png^techage_appl_turbine4.png^techage_frame4_ta3.png", image = "techage_filling4_ta3.png^techage_appl_turbine4.png^techage_frame4_ta3.png^[transformFX",
backface_culling = false, backface_culling = false,
animation = { animation = {
type = "vertical_frames", type = "vertical_frames",

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2023 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -157,7 +157,7 @@ local function create_task(pos, task)
end end
-- Call on_cyclic_check of all magents so that the magnets don't need a FLB. -- Call on_cyclic_check of all magents so that the magnets don't need a FLB.
local function magnet_on_cyclic_check(pos, nvm) local function magnets_on_cyclic_check(pos, nvm)
local ndef = minetest.registered_nodes["techage:ta4_magnet"] local ndef = minetest.registered_nodes["techage:ta4_magnet"]
for idx,pos2 in ipairs(nvm.magnet_positions or {}) do for idx,pos2 in ipairs(nvm.magnet_positions or {}) do
local res = ndef.on_cyclic_check(pos2) local res = ndef.on_cyclic_check(pos2)
@ -173,6 +173,29 @@ local function magnet_on_cyclic_check(pos, nvm)
return true return true
end end
-- Turn off all magnets so that they don't consume power
local function magnets_turn_off(pos, nvm)
local ndef = minetest.registered_nodes["techage:ta4_magnet"]
for idx,pos2 in ipairs(nvm.magnet_positions or {}) do
ndef.on_turn_off(pos2)
end
end
local function cable_inlets_turn_on_off(pos, on)
local turn_on_off = function(pos, param2, item)
local pos2 = getpos(pos, param2, item.route, item.yoffs)
local node2 = minetest.get_node(pos2)
if item.name == node2.name then
local nvm = techage.get_nvm(pos2)
techage.power_inlet_turn_on_off(pos2, nvm, on)
end
end
local param2 = minetest.get_node(pos).param2
turn_on_off(pos, param2, Schedule[2])
turn_on_off(pos, param2, Schedule[3])
end
minetest.register_node("techage:ta4_detector_core", { minetest.register_node("techage:ta4_detector_core", {
description = S("TA4 Collider Detector Core"), description = S("TA4 Collider Detector Core"),
tiles = { tiles = {
@ -202,29 +225,33 @@ minetest.register_node("techage:ta4_detector_core", {
on_timer = function(pos, elapsed) on_timer = function(pos, elapsed)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
if not magnet_on_cyclic_check(pos, nvm) then if nvm.running then
techage.del_laser(pos) if not magnets_on_cyclic_check(pos, nvm) then
if nvm.running then
terminal_message(pos, "Detector stopped.")
nvm.running = false
end
nvm.magnet_positions = nil
elseif nvm.running then
local res = check_state(pos)
if res == true then
experience_points(pos)
add_laser(pos)
if nvm.ticks <= TIME_SLOTS then -- only once
terminal_message(pos, "Detector running.")
end
elseif res == false then
techage.del_laser(pos) techage.del_laser(pos)
terminal_message(pos, "Detector stopped.")
magnets_turn_off(pos, nvm)
cable_inlets_turn_on_off(pos, false)
nvm.running = false nvm.running = false
nvm.magnet_positions = nil nvm.magnet_positions = nil
terminal_message(pos, "Detector stopped.") else
end local res = check_state(pos)
if nvm.running then if res == true then
play_sound(pos) experience_points(pos)
add_laser(pos)
if nvm.ticks <= TIME_SLOTS then -- only once
terminal_message(pos, "Detector running.")
end
elseif res == false then
techage.del_laser(pos)
magnets_turn_off(pos, nvm)
cable_inlets_turn_on_off(pos, false)
nvm.running = false
nvm.magnet_positions = nil
terminal_message(pos, "Detector stopped.")
end
if nvm.running then
play_sound(pos)
end
end end
end end
return true return true
@ -287,6 +314,7 @@ local function start_task(pos)
end end
nvm.magnet_positions = t nvm.magnet_positions = t
techage.send_single(own_num, term_num, "append", "ok") techage.send_single(own_num, term_num, "append", "ok")
cable_inlets_turn_on_off(pos, true)
coroutine.yield() coroutine.yield()
techage.send_single(own_num, term_num, "text", "- Check magnets...") techage.send_single(own_num, term_num, "text", "- Check magnets...")
@ -310,6 +338,7 @@ local function start_task(pos)
techage.send_single(own_num, term_num, "append", err .. "!!!") techage.send_single(own_num, term_num, "append", err .. "!!!")
nvm.magnet_positions = nil nvm.magnet_positions = nil
nvm.locked = false nvm.locked = false
cable_inlets_turn_on_off(pos, false)
return return
end end
else else
@ -323,12 +352,14 @@ local function start_task(pos)
techage.send_single(own_num, term_num, "append", err .. "!!!") techage.send_single(own_num, term_num, "append", err .. "!!!")
nvm.magnet_positions = nil nvm.magnet_positions = nil
nvm.locked = false nvm.locked = false
cable_inlets_turn_on_off(pos, false)
return return
end end
else else
techage.send_single(own_num, term_num, "append", "defect!!!") techage.send_single(own_num, term_num, "append", "defect!!!")
nvm.magnet_positions = nil nvm.magnet_positions = nil
nvm.locked = false nvm.locked = false
cable_inlets_turn_on_off(pos, false)
return return
end end
coroutine.yield() coroutine.yield()
@ -337,7 +368,7 @@ local function start_task(pos)
techage.send_single(own_num, term_num, "append", "ok") techage.send_single(own_num, term_num, "append", "ok")
coroutine.yield() coroutine.yield()
techage.send_single(own_num, term_num, "text", "Collider started.") techage.send_single(own_num, term_num, "text", "Collider starting...")
nvm.ticks = 0 nvm.ticks = 0
nvm.running = true nvm.running = true
end end
@ -372,6 +403,9 @@ techage.register_node({"techage:ta4_detector_core"}, {
nvm.running = false nvm.running = false
techage.del_laser(pos) techage.del_laser(pos)
nvm.locked = false nvm.locked = false
magnets_turn_off(pos, nvm)
cable_inlets_turn_on_off(pos, false)
nvm.magnet_positions = nil
return "Detector stopped." return "Detector stopped."
elseif topic == "status" then elseif topic == "status" then
if nvm.running == true then if nvm.running == true then

View File

@ -328,7 +328,11 @@ minetest.register_node("techage:ta4_collider_cable_inlet", {
on_timer = function(pos, elapsed) on_timer = function(pos, elapsed)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
nvm.consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED) if nvm.running then
nvm.consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
else
nvm.consumed = 0
end
return true return true
end, end,
@ -346,6 +350,11 @@ function techage.power_inlet_check(pos, node, meta, nvm)
return false, "no power" return false, "no power"
end end
-- Used by the detector to turn on/off the node
function techage.power_inlet_turn_on_off(pos, nvm, on)
nvm.running = on
end
power.register_nodes({"techage:ta4_collider_cable_inlet"}, Cable, "con", {"F"}) power.register_nodes({"techage:ta4_collider_cable_inlet"}, Cable, "con", {"F"})
techage.register_node({"techage:ta4_collider_cable_inlet"}, { techage.register_node({"techage:ta4_collider_cable_inlet"}, {

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2023 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -93,6 +93,8 @@ minetest.register_node("techage:ta4_magnet", {
}, },
wield_scale = {x = 0.8, y = 0.8, z = 0.8}, wield_scale = {x = 0.8, y = 0.8, z = 0.8},
paramtype2 = "facedir", paramtype2 = "facedir",
paramtype = "light",
use_texture_alpha = techage.CLIP,
groups = {cracky = 1}, groups = {cracky = 1},
on_rotate = screwdriver.disallow, on_rotate = screwdriver.disallow,
is_ground_content = false, is_ground_content = false,
@ -119,14 +121,22 @@ minetest.register_node("techage:ta4_magnet", {
nvm.consumed = power.consume_power(pos, Cable, 6, PWR_NEEDED) nvm.consumed = power.consume_power(pos, Cable, 6, PWR_NEEDED)
if nvm.tube_damage then if nvm.tube_damage then
nvm.tube_damage = nil nvm.tube_damage = nil
nvm.running = nil
return -1 return -1
elseif nvm.liquid.amount == CAPACITY and elseif nvm.liquid.amount == CAPACITY and
nvm.liquid.name == "techage:isobutane" and nvm.liquid.name == "techage:isobutane" and
nvm.consumed == PWR_NEEDED then nvm.consumed == PWR_NEEDED then
nvm.running = true
return 0 return 0
end end
nvm.running = nil
return -2 return -2
end, end,
on_turn_off = function(pos)
local nvm = techage.get_nvm(pos)
nvm.running = nil
end,
tubelib2_on_update2 = function(pos, outdir, tlib2, node) tubelib2_on_update2 = function(pos, outdir, tlib2, node)
if tlib2.tube_type == "vtube" then if tlib2.tube_type == "vtube" then

View File

@ -21,7 +21,6 @@ techage.manual_DE.aTitel = {
"3,TA1 Schleusengriff / TA1 Sluice Handle", "3,TA1 Schleusengriff / TA1 Sluice Handle",
"3,TA1 Apfelholzbrett / TA1 Apple Wood Board", "3,TA1 Apfelholzbrett / TA1 Apple Wood Board",
"3,TA1 Apfel Mühlbachbrett / TA1 Apple Millrace Board", "3,TA1 Apfel Mühlbachbrett / TA1 Apple Millrace Board",
"2, ",
"2,Erze und Werkzeuge", "2,Erze und Werkzeuge",
"3,Hammer", "3,Hammer",
"3,Kiessieb / Gravel Sieve", "3,Kiessieb / Gravel Sieve",
@ -432,7 +431,6 @@ techage.manual_DE.aText = {
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
"",
"TA1 hat seine eigenen Werkzeuge wie Hammer und Kiessieb\\, aber auch der Minecart Hopper kann genutzt werden.\n".. "TA1 hat seine eigenen Werkzeuge wie Hammer und Kiessieb\\, aber auch der Minecart Hopper kann genutzt werden.\n"..
"\n".. "\n"..
"\n".. "\n"..
@ -981,7 +979,7 @@ techage.manual_DE.aText = {
"\n", "\n",
"Der Tankwagen dient zum Transport von Flüssigkeiten. Es kann wie Tanks mit Pumpen gefüllt bzw. geleert werden. In beiden Fällen muss die gelbe Röhre von oben mit dem Tankwagen verbunden werden.\n".. "Der Tankwagen dient zum Transport von Flüssigkeiten. Es kann wie Tanks mit Pumpen gefüllt bzw. geleert werden. In beiden Fällen muss die gelbe Röhre von oben mit dem Tankwagen verbunden werden.\n"..
"\n".. "\n"..
"In den Tankwagen passen 100 Einheiten.\n".. "In den Tankwagen passen 200 Einheiten.\n"..
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
@ -1726,7 +1724,6 @@ techage.manual_DE.aText = {
" - mit den Menü-Tasten \"Bewege A-B\" sowie \"Bewege B-A\" kann die Bewegung getestet werden\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".. " - 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".. " - 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".. "\n"..
"Der Move Controller unterstützt folgende techage Kommandos:\n".. "Der Move Controller unterstützt folgende techage Kommandos:\n"..
"\n".. "\n"..
@ -2112,7 +2109,7 @@ techage.manual_DE.aText = {
"\n".. "\n"..
"Für das Pairing musst du zuerst auf der einen Seite einen Namen für die Kiste eingeben\\, dann kannst du bei der anderen Kiste diesen Namen auswählen und so die beiden Blöcke verbinden.\n".. "Für das Pairing musst du zuerst auf der einen Seite einen Namen für die Kiste eingeben\\, dann kannst du bei der anderen Kiste diesen Namen auswählen und so die beiden Blöcke verbinden.\n"..
"\n".. "\n"..
"Die Nutzung der TA5 Hyperloop Kiste benötigt 20 Erfahrungspunkte.\n".. "Die Nutzung der TA5 Hyperloop Kiste benötigt 15 Erfahrungspunkte.\n"..
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
@ -2122,7 +2119,7 @@ techage.manual_DE.aText = {
"\n".. "\n"..
"Für das Pairing musst du zuerst auf der einen Seite einen Namen für den Tank eingeben\\, dann kannst du bei dem anderen Tank diesen Namen auswählen und so die beiden Blöcke verbinden.\n".. "Für das Pairing musst du zuerst auf der einen Seite einen Namen für den Tank eingeben\\, dann kannst du bei dem anderen Tank diesen Namen auswählen und so die beiden Blöcke verbinden.\n"..
"\n".. "\n"..
"Die Nutzung des TA5 Hyperloop Tanks benötigt 20 Erfahrungspunkte.\n".. "Die Nutzung des TA5 Hyperloop Tanks benötigt 15 Erfahrungspunkte.\n"..
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
@ -2134,25 +2131,25 @@ techage.manual_DE.aText = {
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
"Diese Teleport-Blöcke erlauben die Übertragung von Gegenständen und ersetzen somit eine Röhre. Dabei können Entfernungen von bis zu 200 Blöcken überbrückt werden.\n".. "Diese Teleport-Blöcke erlauben die Übertragung von Gegenständen und ersetzen somit eine Röhre. Dabei können Entfernungen von bis zu 500 Blöcken überbrückt werden.\n"..
"\n".. "\n"..
"Ein Teleport-Block benötigt 12 ku Strom.\n".. "Ein Teleport-Block benötigt 12 ku Strom.\n"..
"\n".. "\n"..
"Für die Nutzung der Teleport-Blöcke werden 60 Erfahrungspunkte benötigt.\n".. "Für die Nutzung der Teleport-Blöcke werden 30 Erfahrungspunkte benötigt.\n"..
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
"Diese Teleport-Blöcke erlauben die Übertragung von Flüssigkeiten und ersetzen somit eine gelbe Leitung. Dabei können Entfernungen von bis zu 200 Blöcken überbrückt werden.\n".. "Diese Teleport-Blöcke erlauben die Übertragung von Flüssigkeiten und ersetzen somit eine gelbe Leitung. Dabei können Entfernungen von bis zu 500 Blöcken überbrückt werden.\n"..
"\n".. "\n"..
"Ein Teleport-Block benötigt 12 ku Strom.\n".. "Ein Teleport-Block benötigt 12 ku Strom.\n"..
"\n".. "\n"..
"Für die Nutzung der Teleport-Blöcke werden 60 Erfahrungspunkte benötigt.\n".. "Für die Nutzung der Teleport-Blöcke werden 30 Erfahrungspunkte benötigt.\n"..
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
"Die Hyperloop Teleport Blöcke erlauben den Aufbau von Hyperloop Netzwerk ohne Hyperloop-Röhren.\n".. "Die Hyperloop Teleport Blöcke erlauben den Aufbau von Hyperloop Netzwerk ohne Hyperloop-Röhren.\n"..
"\n".. "\n"..
"Die Nutzung der Hyperloop Teleport Blöcke benötigt 120 Erfahrungspunkte.\n".. "Die Nutzung der Hyperloop Teleport Blöcke benötigt 60 Erfahrungspunkte.\n"..
"\n", "\n",
"", "",
"Der TA5 Container erlaubt Techage Anlagen ein- und an einer anderen Stelle wieder auszupacken.\n".. "Der TA5 Container erlaubt Techage Anlagen ein- und an einer anderen Stelle wieder auszupacken.\n"..
@ -2163,7 +2160,7 @@ techage.manual_DE.aText = {
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
"Der TA5 KI Chip II wird zur Herstellung des TA5 Fusionsreaktors benötigt. Der TA5 KI Chip II kann nur auf der TA4 Elektronik Fab hergestellt werden. Dazu werden 50 Erfahrungspunkte benötigt.\n".. "Der TA5 KI Chip II wird zur Herstellung des TA5 Fusionsreaktors benötigt. Der TA5 KI Chip II kann nur auf der TA4 Elektronik Fab hergestellt werden. Dazu werden 25 Erfahrungspunkte benötigt.\n"..
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
@ -2190,7 +2187,6 @@ techage.manual_DE.aItemName = {
"ta1_sluice_handle", "ta1_sluice_handle",
"ta1_board1", "ta1_board1",
"ta1_board2", "ta1_board2",
"",
"ta1_gravelsieve", "ta1_gravelsieve",
"hammer", "hammer",
"ta1_gravelsieve", "ta1_gravelsieve",
@ -2451,7 +2447,6 @@ techage.manual_DE.aPlanTable = {
"", "",
"", "",
"", "",
"",
"hoppersieve", "hoppersieve",
"", "",
"", "",

View File

@ -983,7 +983,7 @@ techage.manual_EN.aText = {
"\n", "\n",
"The tank truck is used to transport liquids. Like tanks\\, it can be filled with pumps or emptied. In both cases\\, the yellow tube must be connected to the tank truck from above.\n".. "The tank truck is used to transport liquids. Like tanks\\, it can be filled with pumps or emptied. In both cases\\, the yellow tube must be connected to the tank truck from above.\n"..
"\n".. "\n"..
"100 units fit in the tank truck.\n".. "200 units fit in the tank truck.\n"..
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
@ -1731,7 +1731,6 @@ techage.manual_EN.aText = {
" - The movement can be tested with the menu buttons \"Move A-B\" and \"Move B-A\"\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".. " - 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".. " - 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".. "\n"..
"The Move Controller supports the following techage commands:\n".. "The Move Controller supports the following techage commands:\n"..
"\n".. "\n"..
@ -2118,7 +2117,7 @@ techage.manual_EN.aText = {
"\n".. "\n"..
"For pairing you first have to enter a name for the chest on one side\\, then you can select this name for the other chest and thus connect the two blocks.\n".. "For pairing you first have to enter a name for the chest on one side\\, then you can select this name for the other chest and thus connect the two blocks.\n"..
"\n".. "\n"..
"The use of the TA5 Hyperloop Chest requires 20 experience points.\n".. "The use of the TA5 Hyperloop Chest requires 15 experience points.\n"..
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
@ -2128,7 +2127,7 @@ techage.manual_EN.aText = {
"\n".. "\n"..
"For pairing you first have to enter a name for the tank on one side\\, then you can select this name for the other tank and thus connect the two blocks.\n".. "For pairing you first have to enter a name for the tank on one side\\, then you can select this name for the other tank and thus connect the two blocks.\n"..
"\n".. "\n"..
"The use of the TA5 Hyperloop Tank requires 20 experience points.\n".. "The use of the TA5 Hyperloop Tank requires 15 experience points.\n"..
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
@ -2138,25 +2137,25 @@ techage.manual_EN.aText = {
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
"These teleport blocks allow the transfer of items and thus replace a tube. Distances of up to 200 blocks can be bridged.\n".. "These teleport blocks allow the transfer of items and thus replace a tube. Distances of up to 500 blocks can be bridged.\n"..
"\n".. "\n"..
"Each Teleport blocks requires 12 ku of electricity.\n".. "Each Teleport blocks requires 12 ku of electricity.\n"..
"\n".. "\n"..
"60 experience points are required to use the teleport blocks. \n".. "30 experience points are required to use the teleport blocks. \n"..
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
"These teleport blocks allow the transfer of liquids and thus replace a pipe. Distances of up to 200 blocks can be bridged.\n".. "These teleport blocks allow the transfer of liquids and thus replace a pipe. Distances of up to 500 blocks can be bridged.\n"..
"\n".. "\n"..
"Each Teleport blocks requires 12 ku of electricity.\n".. "Each Teleport blocks requires 12 ku of electricity.\n"..
"\n".. "\n"..
"60 experience points are required to use the teleport blocks. \n".. "30 experience points are required to use the teleport blocks. \n"..
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
"The Hyperloop Teleport Blocks allow the construction of a Hyperloop network without Hyperloop tubes.\n".. "The Hyperloop Teleport Blocks allow the construction of a Hyperloop network without Hyperloop tubes.\n"..
"\n".. "\n"..
"The use of the Hyperloop Teleport Blocks requires 120 experience points.\n".. "The use of the Hyperloop Teleport Blocks requires 60 experience points.\n"..
"\n", "\n",
"", "",
"The TA5 container allows Techage systems to be packed and unpacked at another location.\n".. "The TA5 container allows Techage systems to be packed and unpacked at another location.\n"..
@ -2167,7 +2166,7 @@ techage.manual_EN.aText = {
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
"The TA5 AI Chip II is required to build the TA5 Fusion Reactor. The TA5 AI Chip II can only be manufactured at the TA4 Electronics Fab. This requires 50 experience points.\n".. "The TA5 AI Chip II is required to build the TA5 Fusion Reactor. The TA5 AI Chip II can only be manufactured at the TA4 Electronics Fab. This requires 25 experience points.\n"..
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",

View File

@ -347,10 +347,10 @@ techage.register_node({"techage:heatexchanger2"}, {
elseif topic == "load" then elseif topic == "load" then
return techage.power.percent(nvm.capa_max, nvm.capa) return techage.power.percent(nvm.capa_max, nvm.capa)
elseif topic == "on" then elseif topic == "on" then
start_node(pos, techage.get_nvm(pos)) State:start(pos, nvm)
return true return true
elseif topic == "off" then elseif topic == "off" then
stop_node(pos, techage.get_nvm(pos)) State:stop(pos, nvm)
return true return true
else else
return "unsupported" return "unsupported"
@ -359,10 +359,10 @@ techage.register_node({"techage:heatexchanger2"}, {
on_beduino_receive_cmnd = function(pos, src, topic, payload) on_beduino_receive_cmnd = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
if topic == 1 and payload[1] == 1 then if topic == 1 and payload[1] == 1 then
start_node(pos, techage.get_nvm(pos)) State:start(pos, nvm)
return 0 return 0
elseif topic == 1 and payload[1] == 0 then elseif topic == 1 and payload[1] == 0 then
stop_node(pos, techage.get_nvm(pos)) State:stop(pos, nvm)
return 0 return 0
else else
return 2, "" return 2, ""
@ -382,7 +382,8 @@ techage.register_node({"techage:heatexchanger2"}, {
local data = power.get_network_data(pos, Cable, DOWN) local data = power.get_network_data(pos, Cable, DOWN)
return 0, {data.consumed - data.provided} return 0, {data.consumed - data.provided}
elseif topic == 134 then -- Tank Load Percent elseif topic == 134 then -- Tank Load Percent
return 0, {techage.power.percent(nvm.capa_max, nvm.capa)} local value = techage.power.percent(nvm.capa_max, nvm.capa)
return 0, {math.floor(value + 0.5)}
else else
return 2, "" return 2, ""
end end

View File

@ -26,6 +26,7 @@ local STANDBY_TICKS = 3
local PWR_NEEDED = 35 local PWR_NEEDED = 35
local PWR_UNITS_PER_HYDROGEN_ITEM = 80 local PWR_UNITS_PER_HYDROGEN_ITEM = 80
local CAPACITY = 200 local CAPACITY = 200
local TURNOFF_THRESHOLD = "40%"
local function evaluate_percent(s) local function evaluate_percent(s)
return (tonumber(s:sub(1, -2)) or 0) / 100 return (tonumber(s:sub(1, -2)) or 0) / 100
@ -124,11 +125,14 @@ local function node_timer(pos, elapsed)
State:keep_running(pos, nvm, 1) State:keep_running(pos, nvm, 1)
end end
elseif curr_load == 0 then elseif curr_load == 0 then
nvm.taken = 0
State:nopower(pos, nvm) State:nopower(pos, nvm)
else else
nvm.taken = 0
State:standby(pos, nvm, S("Turnoff point reached")) State:standby(pos, nvm, S("Turnoff point reached"))
end end
else else
nvm.taken = 0
State:blocked(pos, nvm, S("Storage full")) State:blocked(pos, nvm, S("Storage full"))
end end
if techage.is_activeformspec(pos) then if techage.is_activeformspec(pos) then
@ -161,6 +165,8 @@ local function after_place_node(pos)
State:node_init(pos, nvm, number) State:node_init(pos, nvm, number)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
M(pos):set_int("in_dir", techage.side_to_indir("R", node.param2)) M(pos):set_int("in_dir", techage.side_to_indir("R", node.param2))
M(pos):set_string("reduction", "100%")
M(pos):set_string("turnoff", TURNOFF_THRESHOLD)
Pipe:after_place_node(pos) Pipe:after_place_node(pos)
Cable:after_place_node(pos) Cable:after_place_node(pos)
end end
@ -201,7 +207,7 @@ local tool_config = {
name = "turnoff", name = "turnoff",
label = S("Turnoff point"), label = S("Turnoff point"),
tooltip = S("If the charge of the storage\nsystem falls below the configured value,\nthe block switches off"), tooltip = S("If the charge of the storage\nsystem falls below the configured value,\nthe block switches off"),
default = "98%", default = TURNOFF_THRESHOLD,
}, },
} }
@ -349,7 +355,7 @@ techage.register_node({"techage:ta4_electrolyzer", "techage:ta4_electrolyzer_on"
local meta = M(pos) local meta = M(pos)
if not meta:contains("reduction") then if not meta:contains("reduction") then
meta:set_string("reduction", "100%") meta:set_string("reduction", "100%")
meta:set_string("turnoff", "100%") meta:set_string("turnoff", TURNOFF_THRESHOLD)
end end
end, end,
}) })

View File

@ -219,7 +219,7 @@ function techage.display.write_row(pos, payload, cycle_time, beduino)
nvm.text = nvm.text or {} nvm.text = nvm.text or {}
mem.ticks = mem.ticks or 0 mem.ticks = mem.ticks or 0
if beduino then if beduino or type(payload) == "string" then
row = tonumber(payload:sub(1,1) or "1") or 1 row = tonumber(payload:sub(1,1) or "1") or 1
str = payload:sub(2) or "oops" str = payload:sub(2) or "oops"
else else

View File

@ -13,7 +13,7 @@
techage = {} techage = {}
-- Version for compatibility checks, see readme.md/history -- Version for compatibility checks, see readme.md/history
techage.version = 1.10 techage.version = 1.11
if minetest.global_exists("tubelib") then if minetest.global_exists("tubelib") then
minetest.log("error", "[techage] Techage can't be used together with the mod tubelib!") minetest.log("error", "[techage] Techage can't be used together with the mod tubelib!")
@ -27,8 +27,8 @@ elseif minetest.global_exists("techpack") then
elseif minetest.global_exists("tubelib2") and tubelib2.version < 2.2 then elseif minetest.global_exists("tubelib2") and tubelib2.version < 2.2 then
minetest.log("error", "[techage] Techage requires tubelib2 version 2.2 or newer!") minetest.log("error", "[techage] Techage requires tubelib2 version 2.2 or newer!")
return return
elseif minetest.global_exists("minecart") and minecart.version < 2.03 then elseif minetest.global_exists("minecart") and minecart.version < 2.04 then
minetest.log("error", "[techage] Techage requires minecart version 2.03 or newer!") minetest.log("error", "[techage] Techage requires minecart version 2.04 or newer!")
return return
elseif minetest.global_exists("lcdlib") and lcdlib.version < 1.01 then elseif minetest.global_exists("lcdlib") and lcdlib.version < 1.01 then
minetest.log("error", "[techage] Techage requires lcdlib version 1.01 or newer!") minetest.log("error", "[techage] Techage requires lcdlib version 1.01 or newer!")
@ -36,8 +36,8 @@ elseif minetest.global_exists("lcdlib") and lcdlib.version < 1.01 then
elseif minetest.global_exists("safer_lua") and safer_lua.version < 1.01 then elseif minetest.global_exists("safer_lua") and safer_lua.version < 1.01 then
minetest.log("error", "[techage] Techage requires safer_lua version 1.01 or newer!") minetest.log("error", "[techage] Techage requires safer_lua version 1.01 or newer!")
return return
elseif minetest.global_exists("networks") and networks.version < 0.12 then elseif minetest.global_exists("networks") and networks.version < 0.13 then
minetest.log("error", "[techage] Techage requires networks version 0.12 or newer!") minetest.log("error", "[techage] Techage requires networks version 0.13 or newer!")
return return
elseif minetest.global_exists("hyperloop") and hyperloop.version < 2.07 then elseif minetest.global_exists("hyperloop") and hyperloop.version < 2.07 then
minetest.log("error", "[techage] Techage requires hyperloop version 2.07 or newer!") minetest.log("error", "[techage] Techage requires hyperloop version 2.07 or newer!")

View File

@ -395,6 +395,8 @@ minetest.register_node("techage:meltingpot_active", {
can_dig = can_dig, can_dig = can_dig,
paramtype = "light",
use_texture_alpha = techage.CLIP,
drop = "techage:meltingpot", drop = "techage:meltingpot",
is_ground_content = false, is_ground_content = false,
groups = {cracky = 3, not_in_creative_inventory=1}, groups = {cracky = 3, not_in_creative_inventory=1},

View File

@ -51,11 +51,13 @@ minetest.register_craftitem("techage:ta5_aichip2", {
techage.recipes.add("ta2_electronic_fab", { techage.recipes.add("ta2_electronic_fab", {
output = "techage:vacuum_tube 2", output = "techage:vacuum_tube 2",
waste = "basic_materials:empty_spool 1",
input = {"default:glass 1", "basic_materials:copper_wire 1", "basic_materials:plastic_sheet 1", "techage:usmium_nuggets 1"} input = {"default:glass 1", "basic_materials:copper_wire 1", "basic_materials:plastic_sheet 1", "techage:usmium_nuggets 1"}
}) })
techage.recipes.add("ta3_electronic_fab", { techage.recipes.add("ta3_electronic_fab", {
output = "techage:vacuum_tube 2", output = "techage:vacuum_tube 2",
waste = "basic_materials:empty_spool 1",
input = {"default:glass 1", "basic_materials:copper_wire 1", "basic_materials:plastic_sheet 1", "techage:usmium_nuggets 1"} input = {"default:glass 1", "basic_materials:copper_wire 1", "basic_materials:plastic_sheet 1", "techage:usmium_nuggets 1"}
}) })
@ -81,17 +83,20 @@ techage.recipes.add("ta4_electronic_fab", {
techage.recipes.add("ta4_electronic_fab", { techage.recipes.add("ta4_electronic_fab", {
output = "techage:ta4_leds 8", output = "techage:ta4_leds 8",
waste = "basic_materials:empty_spool 1",
input = {"basic_materials:plastic_sheet 4", "basic_materials:copper_wire 1", "techage:ta4_silicon_wafer 1"} input = {"basic_materials:plastic_sheet 4", "basic_materials:copper_wire 1", "techage:ta4_silicon_wafer 1"}
}) })
techage.recipes.add("ta4_electronic_fab", { techage.recipes.add("ta4_electronic_fab", {
output = "techage:ta5_aichip 2", output = "techage:ta5_aichip 2",
waste = "basic_materials:empty_spool 2",
input = {"techage:ta4_leds 8", "basic_materials:copper_wire 1", "basic_materials:gold_wire 1", "techage:ta4_silicon_wafer 1"}, input = {"techage:ta4_leds 8", "basic_materials:copper_wire 1", "basic_materials:gold_wire 1", "techage:ta4_silicon_wafer 1"},
ex_points = 10, ex_points = 10,
}) })
techage.recipes.add("ta4_electronic_fab", { techage.recipes.add("ta4_electronic_fab", {
output = "techage:ta5_aichip2 2", output = "techage:ta5_aichip2 2",
waste = "basic_materials:empty_spool 2",
input = {"techage:ta4_leds 8", "basic_materials:copper_wire 1", "basic_materials:gold_wire 1", "techage:ta4_silicon_wafer 1"}, input = {"techage:ta4_leds 8", "basic_materials:copper_wire 1", "basic_materials:gold_wire 1", "techage:ta4_silicon_wafer 1"},
ex_points = 50, ex_points = 25,
}) })

View File

@ -55,6 +55,8 @@ local NodeNames = {
"techage:basalt_glass2", "techage:basalt_glass2",
"techage:bauxite_stone", "techage:bauxite_stone",
"techage:bauxite_cobble", "techage:bauxite_cobble",
"techage:cement_block",
} }
if(minetest.get_modpath("moreblocks")) then if(minetest.get_modpath("moreblocks")) then

View File

@ -26,7 +26,7 @@ local shared_tank = techage.shared_tank
local menu = techage.menu local menu = techage.menu
local CAPACITY = 1000 local CAPACITY = 1000
local EX_POINTS = 20 local EX_POINTS = 15
minetest.register_node("techage:ta5_hl_tank", { minetest.register_node("techage:ta5_hl_tank", {
description = S("TA5 Hyperloop Tank"), description = S("TA5 Hyperloop Tank"),

View File

@ -291,6 +291,10 @@ TA2 Cylinder=TA2 Zylinder
### detector.lua ### ### detector.lua ###
Countdown=Countdown
Counts down the number of items passed through@nand only triggers an 'on' command when it reaches zero.=Zählt die Anzahl der durchlaufenen Elemente herunter@nund löst nur dann einen 'ON'-Befehl aus, wenn er Null erreicht.
Current countdown=Aktueller Zähler
Current countdown value.=Aktueller Zählerwert.
TA4 Collider Detector=TA4 Collider Detektor TA4 Collider Detector=TA4 Collider Detektor
TA4 Collider Detector Core=TA4 Collider Detektorkern TA4 Collider Detector Core=TA4 Collider Detektorkern
TA4 Detector=TA4 Detektor TA4 Detector=TA4 Detektor
@ -500,8 +504,10 @@ Move=Bewege
Move A-B=Bewege A-B Move A-B=Bewege A-B
Move B-A=Bewege B-A Move B-A=Bewege B-A
Move block height=Move Block Höhe Move block height=Move Block Höhe
Object offset=Objekt Offset
Stored=Gespeichert Stored=Gespeichert
Value in the range of 0.0 to 1.0=Wert im Bereich von 0.0 bis 1.0 Value in the range of 0.0 to 1.0=Wert im Bereich von 0.0 bis 1.0
Y-offset for non-player objects like vehicles (-0.5 to 0.5)=Y-Offset für Nicht-Spieler Objekte wie Fahrzeuge (-0.5 bis 0.5)
### flywheel.lua ### ### flywheel.lua ###
@ -665,7 +671,6 @@ TA4 Hydrogen=TA4 Wasserstoff
### hyperloop.lua ### ### hyperloop.lua ###
### sensorchest.lua ### ### sensorchest.lua ###
### teleport.lua ### ### teleport.lua ###
### terminal.lua ###
not connected=nicht verbunden not connected=nicht verbunden
@ -746,7 +751,6 @@ Block has an@nadditional wrench menu=Block besitzt ein@nzusätzliches@nSchrauben
### lib.lua ### ### lib.lua ###
### sensorchest.lua ### ### sensorchest.lua ###
### terminal.lua ###
connected with=verbunden mit connected with=verbunden mit
@ -888,27 +892,22 @@ TA4 Streetlamp Solar Cell=TA4 Straßenlampen-Solarzelle
### minichest.lua ### ### minichest.lua ###
Test Chest= Test Chest=Testkiste
### minitank.lua ### ### minitank.lua ###
Test Mini Tank= Test Mini Tank=Testminitank
### movecontroller.lua ### ### movecontroller.lua ###
Error: Invalid distance !!=Fehler: Ungültige Entfernung !! Error: Invalid distance !!=Fehler: Ungültige Entfernung !!
Handover to A=Übergabe an A
Handover to B=Übergabe an B
Move distance=Entfernung Move distance=Entfernung
Move distance (A to B)=Entfernung (A nach B) Move distance (A to B)=Entfernung (A nach B)
Number of the next movecontroller=Nummer des nächsten Move Controllers
Number of the previous movecontroller=Nummer des vorhergehenden Move Controllers
Object offset=Objekt Offset
Operational mode=Betriebsmodus Operational mode=Betriebsmodus
Reset=Rücksetzen Reset=Rücksetzen
Switch to the remote controlled 'move xyz' mode=Wechseln in den ferngesteuerten 'move xyz'-Modus Switch to the remote controlled 'move xyz' mode=Wechseln in den ferngesteuerten 'move xyz'-Modus
TA Rack and Pinion=TA Zahnstange
TA4 Move Controller=TA4 Move Controller TA4 Move Controller=TA4 Move Controller
Y-offset for non-player objects like vehicles (-0.5 to 0.5)=Y-Offset für Nicht-Spieler Objekte wie Fahrzeuge (-0.5 bis 0.5)
### node_detector.lua ### ### node_detector.lua ###
@ -1170,6 +1169,8 @@ stopped=gestoppt
Commands=Kommandos Commands=Kommandos
Cycle time=Zykluszeit Cycle time=Zykluszeit
Example:@n=Beispiel: Example:@n=Beispiel:
If 'yes' a received OFF command won't stop the sequencer=Bei 'yes' stoppt ein empfangener OFF-Befehl den Sequenzer nicht
Ignore OFF command=OFF-Befehl ignorieren
Invalid command!=Ungültiges Kommando! Invalid command!=Ungültiges Kommando!
Start=Start Start=Start
Stop=Stopp Stop=Stopp
@ -1192,8 +1193,8 @@ TA5 Fusion Reactor Shell=TA5 Fusionsreaktor Hülle
### signallamp.lua ### ### signallamp.lua ###
TA4 Wind Turbine Signal Lamp=TA4 Windkraftanlagenlampe TA4 Wind Turbine Signal Lamp=TA4 Windkraftanlagenlampe
TechAge Signal Lamp=TechAge Signallampe TechAge Color Lamp=TechAge Farblampe
TechAge Signal Lamp 2 =TechAge Signallampe 2 TechAge Color Lamp 2=TechAge Farblampe 2
### signallamp_2x.lua ### ### signallamp_2x.lua ###
@ -1401,7 +1402,6 @@ TA5 Teleport Block Items=TA5 Teleport Block Gegenstände
Syntax error, try help=Syntax Fehler, nutze help Syntax error, try help=Syntax Fehler, nutze help
TA3 Terminal=TA3 Terminal TA3 Terminal=TA3 Terminal
TA4 Collider Terminal=TA4 Collider Terminal
TA4 Terminal=TA4 Terminal TA4 Terminal=TA4 Terminal
commands like: help=Kommandos wie: help commands like: help=Kommandos wie: help
@ -1511,4 +1511,11 @@ TA4 Collider Detector Worker=TA4 Collider Detektor Worker
##### not used anymore ##### ##### not used anymore #####
Handover to A=Übergabe an A
Handover to B=Übergabe an B
Number of the next movecontroller=Nummer des nächsten Move Controllers
Number of the previous movecontroller=Nummer des vorhergehenden Move Controllers
TechAge Signal Lamp=TechAge Signallampe
TechAge Signal Lamp 2 =TechAge Signallampe 2
TA4 Collider Terminal=TA4 Collider Terminal
Error: Max. length of the flight route exceeded !!=Fehler: Max. Flugstreckenlänge überschritten !! Error: Max. length of the flight route exceeded !!=Fehler: Max. Flugstreckenlänge überschritten !!

View File

@ -291,6 +291,10 @@ TA2 Cylinder=
### detector.lua ### ### detector.lua ###
Countdown=
Counts down the number of items passed through@nand only triggers an 'on' command when it reaches zero.=
Current countdown=
Current countdown value.=
TA4 Collider Detector= TA4 Collider Detector=
TA4 Collider Detector Core= TA4 Collider Detector Core=
TA4 Detector= TA4 Detector=
@ -500,8 +504,10 @@ Move=
Move A-B= Move A-B=
Move B-A= Move B-A=
Move block height= Move block height=
Object offset=
Stored= Stored=
Value in the range of 0.0 to 1.0= Value in the range of 0.0 to 1.0=
Y-offset for non-player objects like vehicles (-0.5 to 0.5)=
### flywheel.lua ### ### flywheel.lua ###
@ -665,7 +671,6 @@ TA4 Hydrogen=
### hyperloop.lua ### ### hyperloop.lua ###
### sensorchest.lua ### ### sensorchest.lua ###
### teleport.lua ### ### teleport.lua ###
### terminal.lua ###
not connected= not connected=
@ -746,7 +751,6 @@ Block has an@nadditional wrench menu=
### lib.lua ### ### lib.lua ###
### sensorchest.lua ### ### sensorchest.lua ###
### terminal.lua ###
connected with= connected with=
@ -897,18 +901,13 @@ Test Mini Tank=
### movecontroller.lua ### ### movecontroller.lua ###
Error: Invalid distance !!= Error: Invalid distance !!=
Handover to A=
Handover to B=
Move distance= Move distance=
Move distance (A to B)= Move distance (A to B)=
Number of the next movecontroller=
Number of the previous movecontroller=
Object offset=
Operational mode= Operational mode=
Reset= Reset=
Switch to the remote controlled 'move xyz' mode= Switch to the remote controlled 'move xyz' mode=
TA Rack and Pinion=
TA4 Move Controller= TA4 Move Controller=
Y-offset for non-player objects like vehicles (-0.5 to 0.5)=
### node_detector.lua ### ### node_detector.lua ###
@ -1170,6 +1169,8 @@ stopped=
Commands= Commands=
Cycle time= Cycle time=
Example:@n= Example:@n=
If 'yes' a received OFF command won't stop the sequencer=
Ignore OFF command=
Invalid command!= Invalid command!=
Start= Start=
Stop= Stop=
@ -1192,8 +1193,8 @@ TA5 Fusion Reactor Shell=
### signallamp.lua ### ### signallamp.lua ###
TA4 Wind Turbine Signal Lamp= TA4 Wind Turbine Signal Lamp=
TechAge Signal Lamp= TechAge Color Lamp=
TechAge Signal Lamp 2 = TechAge Color Lamp 2=
### signallamp_2x.lua ### ### signallamp_2x.lua ###
@ -1401,7 +1402,6 @@ TA5 Teleport Block Items=
Syntax error, try help= Syntax error, try help=
TA3 Terminal= TA3 Terminal=
TA4 Collider Terminal=
TA4 Terminal= TA4 Terminal=
commands like: help= commands like: help=

View File

@ -45,9 +45,18 @@ local WRENCH_MENU = {
name = "cycletime", name = "cycletime",
label = S("Cycle time"), label = S("Cycle time"),
tooltip = S("Timer cycle time (default: 100 ms)"), tooltip = S("Timer cycle time (default: 100 ms)"),
default = "1", default = "100ms",
values = {0.1, 0.2, 0.5, 1.0, 2.0} values = {0.1, 0.2, 0.5, 1.0, 2.0}
}, },
{
type = "dropdown",
choices = "no,yes",
name = "ignore_off",
label = S("Ignore OFF command"),
tooltip = S("If 'yes' a received OFF command won't stop the sequencer"),
default = "no",
values = {0, 1}
},
} }
local function cycle_time(pos) local function cycle_time(pos)
@ -171,6 +180,7 @@ local function formspec(nvm, meta)
return "size[10,8]" .. return "size[10,8]" ..
style .. style ..
techage.wrench_image(9.3, -0.25) ..
"tabheader[0,0;tab;edit,help;1;;true]" .. "tabheader[0,0;tab;edit,help;1;;true]" ..
"label[0.1,-0.2;" .. S("Commands") .. ":]" .. "label[0.1,-0.2;" .. S("Commands") .. ":]" ..
textarea .. textarea ..
@ -325,7 +335,7 @@ techage.register_node({"techage:ta4_sequencer"}, {
mem.idx = tonumber(payload or 1) or 1 mem.idx = tonumber(payload or 1) or 1
restart_timer(pos, 1) restart_timer(pos, 1)
logic.infotext(M(pos), S("TA4 Sequencer"), S("running")) logic.infotext(M(pos), S("TA4 Sequencer"), S("running"))
elseif topic == "stop" or topic == "off" then elseif topic == "stop" or (topic == "off" and M(pos):get_int("ignore_off") == 0) then
nvm.running = false nvm.running = false
minetest.get_node_timer(pos):stop() minetest.get_node_timer(pos):stop()
logic.infotext(M(pos), S("TA4 Sequencer"), S("stopped")) logic.infotext(M(pos), S("TA4 Sequencer"), S("stopped"))

View File

@ -110,12 +110,6 @@ Block in verschiedenen Holzsorten zum Bauen des Mühlbachkanals. Dieser Block ei
##
## Erze und Werkzeuge ## Erze und Werkzeuge
TA1 hat seine eigenen Werkzeuge wie Hammer und Kiessieb, aber auch der Minecart Hopper kann genutzt werden. TA1 hat seine eigenen Werkzeuge wie Hammer und Kiessieb, aber auch der Minecart Hopper kann genutzt werden.

View File

@ -440,7 +440,7 @@ Damit die Minecarts automatisch wieder starten, müssen die Prellböcke mit Stat
Der Tankwagen dient zum Transport von Flüssigkeiten. Es kann wie Tanks mit Pumpen gefüllt bzw. geleert werden. In beiden Fällen muss die gelbe Röhre von oben mit dem Tankwagen verbunden werden. Der Tankwagen dient zum Transport von Flüssigkeiten. Es kann wie Tanks mit Pumpen gefüllt bzw. geleert werden. In beiden Fällen muss die gelbe Röhre von oben mit dem Tankwagen verbunden werden.
In den Tankwagen passen 100 Einheiten. In den Tankwagen passen 200 Einheiten.
[tank_cart|image] [tank_cart|image]

View File

@ -441,7 +441,7 @@ For the Minecarts to start again automatically, the bumper blocks must be config
The tank truck is used to transport liquids. Like tanks, it can be filled with pumps or emptied. In both cases, the yellow tube must be connected to the tank truck from above. The tank truck is used to transport liquids. Like tanks, it can be filled with pumps or emptied. In both cases, the yellow tube must be connected to the tank truck from above.
100 units fit in the tank truck. 200 units fit in the tank truck.
[tank_cart | image] [tank_cart | image]

View File

@ -579,7 +579,6 @@ Anleitung:
- mit den Menü-Tasten "Bewege A-B" sowie "Bewege B-A" kann die Bewegung getestet werden - 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 - 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 - 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: Der Move Controller unterstützt folgende techage Kommandos:

View File

@ -570,7 +570,6 @@ Instructions:
- The movement can be tested with the menu buttons "Move A-B" and "Move B-A" - 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 - 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 - 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: The Move Controller supports the following techage commands:

View File

@ -92,7 +92,7 @@ Die TA5 Hyperloop Kiste muss man dazu auf eine Hyperloop Junction stellen. Die K
Für das Pairing musst du zuerst auf der einen Seite einen Namen für die Kiste eingeben, dann kannst du bei der anderen Kiste diesen Namen auswählen und so die beiden Blöcke verbinden. Für das Pairing musst du zuerst auf der einen Seite einen Namen für die Kiste eingeben, dann kannst du bei der anderen Kiste diesen Namen auswählen und so die beiden Blöcke verbinden.
Die Nutzung der TA5 Hyperloop Kiste benötigt 20 Erfahrungspunkte. Die Nutzung der TA5 Hyperloop Kiste benötigt 15 Erfahrungspunkte.
[ta5_chest|image] [ta5_chest|image]
@ -104,7 +104,7 @@ Den TA5 Hyperloop Tank muss man dazu auf eine Hyperloop Junction stellen. Der Ta
Für das Pairing musst du zuerst auf der einen Seite einen Namen für den Tank eingeben, dann kannst du bei dem anderen Tank diesen Namen auswählen und so die beiden Blöcke verbinden. Für das Pairing musst du zuerst auf der einen Seite einen Namen für den Tank eingeben, dann kannst du bei dem anderen Tank diesen Namen auswählen und so die beiden Blöcke verbinden.
Die Nutzung des TA5 Hyperloop Tanks benötigt 20 Erfahrungspunkte. Die Nutzung des TA5 Hyperloop Tanks benötigt 15 Erfahrungspunkte.
[ta5_tank|image] [ta5_tank|image]
@ -122,21 +122,21 @@ Der Plan rechts zeigt, wie die Blöcke genutzt werden können.
### TA5 Teleport Block Gegenstände / TA5 Teleport Block Items ### TA5 Teleport Block Gegenstände / TA5 Teleport Block Items
Diese Teleport-Blöcke erlauben die Übertragung von Gegenständen und ersetzen somit eine Röhre. Dabei können Entfernungen von bis zu 200 Blöcken überbrückt werden. Diese Teleport-Blöcke erlauben die Übertragung von Gegenständen und ersetzen somit eine Röhre. Dabei können Entfernungen von bis zu 500 Blöcken überbrückt werden.
Ein Teleport-Block benötigt 12 ku Strom. Ein Teleport-Block benötigt 12 ku Strom.
Für die Nutzung der Teleport-Blöcke werden 60 Erfahrungspunkte benötigt. Für die Nutzung der Teleport-Blöcke werden 30 Erfahrungspunkte benötigt.
[ta5_tele_tube|image] [ta5_tele_tube|image]
### TA5 Teleport Block Flüssigkeiten / TA5 Teleport Block Liquids ### TA5 Teleport Block Flüssigkeiten / TA5 Teleport Block Liquids
Diese Teleport-Blöcke erlauben die Übertragung von Flüssigkeiten und ersetzen somit eine gelbe Leitung. Dabei können Entfernungen von bis zu 200 Blöcken überbrückt werden. Diese Teleport-Blöcke erlauben die Übertragung von Flüssigkeiten und ersetzen somit eine gelbe Leitung. Dabei können Entfernungen von bis zu 500 Blöcken überbrückt werden.
Ein Teleport-Block benötigt 12 ku Strom. Ein Teleport-Block benötigt 12 ku Strom.
Für die Nutzung der Teleport-Blöcke werden 60 Erfahrungspunkte benötigt. Für die Nutzung der Teleport-Blöcke werden 30 Erfahrungspunkte benötigt.
[ta5_tele_pipe|image] [ta5_tele_pipe|image]
@ -144,7 +144,7 @@ Für die Nutzung der Teleport-Blöcke werden 60 Erfahrungspunkte benötigt.
Die Hyperloop Teleport Blöcke erlauben den Aufbau von Hyperloop Netzwerk ohne Hyperloop-Röhren. Die Hyperloop Teleport Blöcke erlauben den Aufbau von Hyperloop Netzwerk ohne Hyperloop-Röhren.
Die Nutzung der Hyperloop Teleport Blöcke benötigt 120 Erfahrungspunkte. Die Nutzung der Hyperloop Teleport Blöcke benötigt 60 Erfahrungspunkte.
## Weitere TA5 Blöcke/Items ## Weitere TA5 Blöcke/Items
@ -162,6 +162,6 @@ Der TA5 KI Chip wird teilweise zur Herstellung von TA5 Blöcken benötigt. Der T
### TA5 KI Chip II / TA5 AI Chip II ### TA5 KI Chip II / TA5 AI Chip II
Der TA5 KI Chip II wird zur Herstellung des TA5 Fusionsreaktors benötigt. Der TA5 KI Chip II kann nur auf der TA4 Elektronik Fab hergestellt werden. Dazu werden 50 Erfahrungspunkte benötigt. Der TA5 KI Chip II wird zur Herstellung des TA5 Fusionsreaktors benötigt. Der TA5 KI Chip II kann nur auf der TA4 Elektronik Fab hergestellt werden. Dazu werden 25 Erfahrungspunkte benötigt.
[ta5_aichip2|image] [ta5_aichip2|image]

View File

@ -92,7 +92,7 @@ The TA5 Hyperloop Chest has to be placed on a Hyperloop Junction. The chest has
For pairing you first have to enter a name for the chest on one side, then you can select this name for the other chest and thus connect the two blocks. For pairing you first have to enter a name for the chest on one side, then you can select this name for the other chest and thus connect the two blocks.
The use of the TA5 Hyperloop Chest requires 20 experience points. The use of the TA5 Hyperloop Chest requires 15 experience points.
[ta5_chest|image] [ta5_chest|image]
@ -104,7 +104,7 @@ The TA5 Hyperloop Tank has to be placed on a Hyperloop Junction.The tank has a s
For pairing you first have to enter a name for the tank on one side, then you can select this name for the other tank and thus connect the two blocks. For pairing you first have to enter a name for the tank on one side, then you can select this name for the other tank and thus connect the two blocks.
The use of the TA5 Hyperloop Tank requires 20 experience points. The use of the TA5 Hyperloop Tank requires 15 experience points.
[ta5_tank|image] [ta5_tank|image]
@ -120,21 +120,21 @@ The map on the right shows how the blocks can be used.
### TA5 Teleport Block Items ### TA5 Teleport Block Items
These teleport blocks allow the transfer of items and thus replace a tube. Distances of up to 200 blocks can be bridged. These teleport blocks allow the transfer of items and thus replace a tube. Distances of up to 500 blocks can be bridged.
Each Teleport blocks requires 12 ku of electricity. Each Teleport blocks requires 12 ku of electricity.
60 experience points are required to use the teleport blocks. 30 experience points are required to use the teleport blocks.
[ta5_tele_tube|image] [ta5_tele_tube|image]
### TA5 Teleport Block Liquids ### TA5 Teleport Block Liquids
These teleport blocks allow the transfer of liquids and thus replace a pipe. Distances of up to 200 blocks can be bridged. These teleport blocks allow the transfer of liquids and thus replace a pipe. Distances of up to 500 blocks can be bridged.
Each Teleport blocks requires 12 ku of electricity. Each Teleport blocks requires 12 ku of electricity.
60 experience points are required to use the teleport blocks. 30 experience points are required to use the teleport blocks.
[ta5_tele_pipe|image] [ta5_tele_pipe|image]
@ -142,7 +142,7 @@ Each Teleport blocks requires 12 ku of electricity.
The Hyperloop Teleport Blocks allow the construction of a Hyperloop network without Hyperloop tubes. The Hyperloop Teleport Blocks allow the construction of a Hyperloop network without Hyperloop tubes.
The use of the Hyperloop Teleport Blocks requires 120 experience points. The use of the Hyperloop Teleport Blocks requires 60 experience points.
@ -162,6 +162,6 @@ The TA5 AI Chip is partly required for the production of TA5 blocks. The TA5 AI
### TA5 AI Chip II ### TA5 AI Chip II
The TA5 AI Chip II is required to build the TA5 Fusion Reactor. The TA5 AI Chip II can only be manufactured at the TA4 Electronics Fab. This requires 50 experience points. The TA5 AI Chip II is required to build the TA5 Fusion Reactor. The TA5 AI Chip II can only be manufactured at the TA4 Electronics Fab. This requires 25 experience points.
[ta5_aichip2|image] [ta5_aichip2|image]

View File

@ -366,7 +366,9 @@ Please note, that this is not a technical distinction, only a logical.
| "state" | one of: "on", "off" | State of a TA4 Button | | "state" | one of: "on", "off" | State of a TA4 Button |
| "fuel" | number | fuel value of a fuel consuming block | | "fuel" | number | fuel value of a fuel consuming block |
| "depth" | number | Read the current depth value of a quarry block (1..80) | | "depth" | number | Read the current depth value of a quarry block (1..80) |
| "load" | number | Read the load value in percent (0..100) of a tank, silo, accu, or battery block, or from the Signs Bot Box. Silo and tank return two values: The percentage value and the absolute value in units.<br /> Example: percent, absolute = $send_cmnd("223", "load") | | "load" | number | Read the load value in percent (0..100) of a accu, or battery block. |
| "load" | number | Read the load value in percent (0..100) of a tank or silo. <br />Silo and tank return two values: <br />The percentage value and the absolute value in units.<br /> Example: percent, absolute = $send_cmnd("223", "load") |
| "load" | number | Read the grid storage amount in percent (0..100) from a TA3 Power Terminal. |
| "delivered" | number | Read the current delivered power value of a generator block. A power consuming block (accu) provides a negative value | | "delivered" | number | Read the current delivered power value of a generator block. A power consuming block (accu) provides a negative value |
| "flowrate" | Total flow rate in liquid units | Only for TA4 Pumps | | "flowrate" | Total flow rate in liquid units | Only for TA4 Pumps |
| "action" | player-name, action-string | Only for Sensor Chests | | "action" | player-name, action-string | Only for Sensor Chests |

View File

@ -20,7 +20,6 @@
- [TA1 Schleusengriff / TA1 Sluice Handle](./manual_ta1_DE.md#ta1-schleusengriff--ta1-sluice-handle) - [TA1 Schleusengriff / TA1 Sluice Handle](./manual_ta1_DE.md#ta1-schleusengriff--ta1-sluice-handle)
- [TA1 Apfelholzbrett / TA1 Apple Wood Board](./manual_ta1_DE.md#ta1-apfelholzbrett--ta1-apple-wood-board) - [TA1 Apfelholzbrett / TA1 Apple Wood Board](./manual_ta1_DE.md#ta1-apfelholzbrett--ta1-apple-wood-board)
- [TA1 Apfel Mühlbachbrett / TA1 Apple Millrace Board](./manual_ta1_DE.md#ta1-apfel-mühlbachbrett--ta1-apple-millrace-board) - [TA1 Apfel Mühlbachbrett / TA1 Apple Millrace Board](./manual_ta1_DE.md#ta1-apfel-mühlbachbrett--ta1-apple-millrace-board)
- [ ](./manual_ta1_DE.md#-)
- [Erze und Werkzeuge](./manual_ta1_DE.md#erze-und-werkzeuge) - [Erze und Werkzeuge](./manual_ta1_DE.md#erze-und-werkzeuge)
- [Hammer](./manual_ta1_DE.md#hammer) - [Hammer](./manual_ta1_DE.md#hammer)
- [Kiessieb / Gravel Sieve](./manual_ta1_DE.md#kiessieb--gravel-sieve) - [Kiessieb / Gravel Sieve](./manual_ta1_DE.md#kiessieb--gravel-sieve)

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2020-2022 Joachim Stolberg Copyright (C) 2020-2023 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -20,14 +20,68 @@ local S = techage.S
local logic = techage.logic local logic = techage.logic
local fly = techage.flylib local fly = techage.flylib
local NUMSLOTS = 16
local MarkedNodes = {} -- t[player] = {{entity, pos},...} local MarkedNodes = {} -- t[player] = {{entity, pos},...}
local CurrentPos -- to mark punched entities local CurrentPos -- to mark punched entities
local function is_simple_node(name) --------------------------------------------------------------------------
local ndef = minetest.registered_nodes[name] -- helper functions
return techage.can_dig_node(name, ndef) --------------------------------------------------------------------------
local function count_nodes(tbl, name)
if tbl[name] then
tbl[name] = tbl[name] + 1
else
tbl[name] = 1
end
end end
local function take_node(tbl, name)
if tbl[name] and tbl[name] > 0 then
tbl[name] = tbl[name] - 1
return true
end
end
local function next_node(tbl)
return function(tbl)
local name, cnt = next(tbl)
if cnt and cnt > 0 then
cnt = cnt - 1
if cnt == 0 then
tbl[name] = nil
else
tbl[name] = cnt
end
return name
end
end, tbl
end
local function get_new_nodename(item)
local name = item:get_name()
if name == "" then
return "air"
end
return name
end
local function get_node_name(nvm, slot)
local pos = nvm.pos_list[slot]
if pos then
return techage.get_node_lvm(pos).name
end
return "unknown"
end
local function is_simple_node(name)
local ndef = minetest.registered_nodes[name]
return name ~= "air" and techage.can_dig_node(name, ndef)
end
--------------------------------------------------------------------------
-- Marker
--------------------------------------------------------------------------
local function unmark_position(name, pos) local function unmark_position(name, pos)
pos = vector.round(pos) pos = vector.round(pos)
for idx,item in ipairs(MarkedNodes[name] or {}) do for idx,item in ipairs(MarkedNodes[name] or {}) do
@ -102,6 +156,9 @@ minetest.register_entity(":techage:marker", {
end, end,
}) })
--------------------------------------------------------------------------
-- formspec
--------------------------------------------------------------------------
local function formspec1(nvm, meta) local function formspec1(nvm, meta)
local status = meta:get_string("status") local status = meta:get_string("status")
local play_sound = dump(nvm.play_sound or false) local play_sound = dump(nvm.play_sound or false)
@ -109,8 +166,8 @@ local function formspec1(nvm, meta)
"tabheader[0,0;tab;"..S("Ctrl,Inv")..";1;;true]".. "tabheader[0,0;tab;"..S("Ctrl,Inv")..";1;;true]"..
"button[0.7,0.2;3,1;record;"..S("Record").."]".. "button[0.7,0.2;3,1;record;"..S("Record").."]"..
"button[4.3,0.2;3,1;ready;"..S("Done").."]".. "button[4.3,0.2;3,1;ready;"..S("Done").."]"..
"button[0.7,1.2;3,1;show;"..S("Set").."]".. "button[0.7,1.2;3,1;reset;"..S("Reset").."]"..
"button[4.3,1.2;3,1;hide;"..S("Remove").."]".. "button[4.3,1.2;3,1;exchange;"..S("Exchange").."]"..
"checkbox[4.3,2.1;play_sound;"..S("with door sound")..";"..play_sound.."]".. "checkbox[4.3,2.1;play_sound;"..S("with door sound")..";"..play_sound.."]"..
"label[0.5,2.3;"..status.."]".. "label[0.5,2.3;"..status.."]"..
"list[current_player;main;0,3.3;8,4;]" "list[current_player;main;0,3.3;8,4;]"
@ -136,10 +193,102 @@ local function play_sound(pos)
max_hear_distance = 15}) max_hear_distance = 15})
end end
--------------------------------------------------------------------------
-- Configuration
--------------------------------------------------------------------------
-- Store the current state of inventory and placed nodes
local function store_config(pos, nvm)
local meta = M(pos)
local inv = meta:get_inventory()
local item_list = inv:get_list("main")
local nodes = {exp_nodes = {}, inv_nodes = {}}
nvm.pos_list = nvm.pos_list or {}
nvm.param2_list = nvm.param2_list or {}
for idx = 1, NUMSLOTS do
local pos = nvm.pos_list[idx]
if pos then
local param2 = nvm.param2_list[idx] or 0
local item = item_list[idx]
if item and item:get_count() > 0 then
nodes.inv_nodes[idx] = {name = item:get_name(), param2 = param2}
end
local node = techage.get_node_lvm(pos)
if is_simple_node(node.name) or node.name == "air" then
nodes.exp_nodes[idx] = techage.get_node_lvm(pos)
end
end
end
meta:set_string("stored_config", minetest.serialize(nodes))
end
-- Generate a table of currently available inventory and placed nodes
local function available_nodes(pos, nvm, item_list)
local nodes = {}
for idx = 1, NUMSLOTS do
local item = item_list[idx]
if item and item:get_count() > 0 then
count_nodes(nodes, item:get_name())
end
local pos = nvm.pos_list[idx]
if pos then
local node = techage.get_node_lvm(pos)
if is_simple_node(node.name) then
count_nodes(nodes, node.name)
end
end
end
return nodes
end
local function restore_config(pos, nvm)
local meta = M(pos)
local inv = meta:get_inventory()
local item_list = inv:get_list("main")
local stock = available_nodes(pos, nvm, item_list)
local nodes = minetest.deserialize(meta:get_string("stored_config")) or {}
inv:set_list("main", {})
item_list = inv:get_list("main")
for idx, node in pairs(nodes.inv_nodes or {}) do
if take_node(stock, node.name) then
item_list[idx] = ItemStack(node.name)
end
end
inv:set_list("main", item_list)
for idx, node in pairs(nodes.exp_nodes or {}) do
local pos = nvm.pos_list[idx]
if take_node(stock, node.name) then
local param2 = nvm.param2_list[idx] or 0
fly.exchange_node(pos, node.name, param2)
nvm.expected_nodenames[idx] = node.name
else
fly.remove_node(pos)
nvm.expected_nodenames[idx] = "air"
end
end
for name in next_node(stock) do
inv:add_item("main", ItemStack(name))
end
return true
end
--------------------------------------------------------------------------
-- Exchange nodes
--------------------------------------------------------------------------
local function exchange_node(pos, item, param2) local function exchange_node(pos, item, param2)
local node = minetest.get_node_or_nil(pos) local node = minetest.get_node_or_nil(pos)
if node and is_simple_node(node.name) then if node and is_simple_node(node.name) or node.name == "air" then
if item and item:get_name() ~= "" and minetest.registered_nodes[item:get_name()] then if item and is_simple_node(item:get_name()) then
fly.exchange_node(pos, item:get_name(), param2) fly.exchange_node(pos, item:get_name(), param2)
else else
fly.remove_node(pos) fly.remove_node(pos)
@ -147,30 +296,48 @@ local function exchange_node(pos, item, param2)
if not techage.is_air_like(node.name) then if not techage.is_air_like(node.name) then
return ItemStack(node.name), node.param2 return ItemStack(node.name), node.param2
else else
return ItemStack(), nil return ItemStack(), param2
end end
end end
return item, param2 return item, param2
end end
local function expected_node(pos, nvm, idx, force, new_nodename)
local expected_name = force and nvm.expected_nodenames[idx] or nil
if expected_name then
local node = techage.get_node_lvm(pos)
if expected_name == node.name then
nvm.expected_nodenames[idx] = new_nodename
return true
else
return false
end
end
nvm.expected_nodenames[idx] = new_nodename
return true
end
local function exchange_nodes(pos, nvm, slot, force) local function exchange_nodes(pos, nvm, slot, force)
local meta = M(pos) local meta = M(pos)
local inv = meta:get_inventory() local inv = meta:get_inventory()
local item_list = inv:get_list("main") local item_list = inv:get_list("main")
local owner = meta:get_string("owner")
local res = false local res = false
nvm.pos_list = nvm.pos_list or {} nvm.pos_list = nvm.pos_list or {}
nvm.param2_list = nvm.param2_list or {} nvm.param2_list = nvm.param2_list or {}
nvm.expected_nodenames = nvm.expected_nodenames or {}
for idx = (slot or 1), (slot or 16) do for idx = (slot or 1), (slot or NUMSLOTS) do
local pos = nvm.pos_list[idx] local pos = nvm.pos_list[idx]
local item = item_list[idx] local item = item_list[idx]
if pos then if pos then
if (force == nil) if (force == nil)
or (force == "exch")
or (force == "dig" and item:get_count() == 0) or (force == "dig" and item:get_count() == 0)
or (force == "set" and item:get_count() > 0) then or (force == "set" and item:get_count() > 0) then
item_list[idx], nvm.param2_list[idx] = exchange_node(pos, item, nvm.param2_list[idx]) if expected_node(pos, nvm, idx, force, get_new_nodename(item)) then
item_list[idx], nvm.param2_list[idx] = exchange_node(pos, item, nvm.param2_list[idx])
end
res = true res = true
end end
end end
@ -180,14 +347,6 @@ local function exchange_nodes(pos, nvm, slot, force)
return res return res
end end
local function get_node_name(nvm, slot)
local pos = nvm.pos_list[slot]
if pos then
return techage.get_node_lvm(pos).name
end
return "unknown"
end
local function show_nodes(pos) local function show_nodes(pos)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
if not nvm.is_on then if not nvm.is_on then
@ -216,6 +375,17 @@ local function hide_nodes(pos)
end end
end end
local function exch_nodes(pos)
local nvm = techage.get_nvm(pos)
if nvm.play_sound then
minetest.sound_play("doors_door_open", {
pos = pos,
gain = 1,
max_hear_distance = 15})
end
return exchange_nodes(pos, nvm)
end
minetest.register_node("techage:ta3_doorcontroller2", { minetest.register_node("techage:ta3_doorcontroller2", {
description = S("TA3 Door Controller II"), description = S("TA3 Door Controller II"),
tiles = { tiles = {
@ -228,7 +398,7 @@ minetest.register_node("techage:ta3_doorcontroller2", {
after_place_node = function(pos, placer, itemstack) after_place_node = function(pos, placer, itemstack)
local meta = M(pos) local meta = M(pos)
local inv = meta:get_inventory() local inv = meta:get_inventory()
inv:set_size('main', 16) inv:set_size('main', NUMSLOTS)
logic.after_place_node(pos, placer, "techage:ta3_doorcontroller2", 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")) logic.infotext(meta, S("TA3 Door Controller II"))
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
@ -252,11 +422,12 @@ minetest.register_node("techage:ta3_doorcontroller2", {
elseif fields.record then elseif fields.record then
local inv = meta:get_inventory() local inv = meta:get_inventory()
nvm.pos_list = nil nvm.pos_list = nil
nvm.is_on = false
meta:set_string("status", S("Recording...")) meta:set_string("status", S("Recording..."))
local name = player:get_player_name() local name = player:get_player_name()
minetest.chat_send_player(name, S("Click on all the blocks that are part of the door/gate")) minetest.chat_send_player(name, S("Click on all the blocks that are part of the door/gate"))
nvm.expected_nodenames = {}
MarkedNodes[name] = {} MarkedNodes[name] = {}
meta:set_string("stored_config", "")
meta:set_string("formspec", formspec1(nvm, meta)) meta:set_string("formspec", formspec1(nvm, meta))
elseif fields.ready then elseif fields.ready then
local name = player:get_player_name() local name = player:get_player_name()
@ -264,25 +435,24 @@ minetest.register_node("techage:ta3_doorcontroller2", {
local text = #pos_list.." "..S("block positions are stored.") local text = #pos_list.." "..S("block positions are stored.")
meta:set_string("status", text) meta:set_string("status", text)
nvm.pos_list = pos_list nvm.pos_list = pos_list
nvm.is_on = true nvm.expected_nodenames = {}
unmark_all(name) unmark_all(name)
meta:set_string("stored_config", "")
meta:set_string("formspec", formspec1(nvm, meta)) meta:set_string("formspec", formspec1(nvm, meta))
elseif fields.show then elseif fields.exchange then
if show_nodes(pos) then if exch_nodes(pos) then
play_sound(pos) store_config(pos, nvm)
meta:set_string("status", S("Blocks are back")) meta:set_string("status", S("Blocks exchanged"))
meta:set_string("formspec", formspec1(nvm, meta))
local name = player:get_player_name()
MarkedNodes[name] = nil
end
elseif fields.hide then
if hide_nodes(pos) then
play_sound(pos)
meta:set_string("status", S("Blocks are disappeared"))
meta:set_string("formspec", formspec1(nvm, meta)) meta:set_string("formspec", formspec1(nvm, meta))
local name = player:get_player_name() local name = player:get_player_name()
MarkedNodes[name] = nil MarkedNodes[name] = nil
end end
elseif fields.reset then
restore_config(pos, nvm)
meta:set_string("status", S("Blocks reset"))
meta:set_string("formspec", formspec1(nvm, meta))
local name = player:get_player_name()
MarkedNodes[name] = nil
elseif fields.play_sound then elseif fields.play_sound then
nvm.play_sound = fields.play_sound == "true" nvm.play_sound = fields.play_sound == "true"
meta:set_string("formspec", formspec1(nvm, meta)) meta:set_string("formspec", formspec1(nvm, meta))
@ -340,7 +510,7 @@ techage.register_node({"techage:ta3_doorcontroller2"}, {
return show_nodes(pos) return show_nodes(pos)
elseif topic == "exchange" then elseif topic == "exchange" then
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
return exchange_nodes(pos, nvm, tonumber(payload)) return exchange_nodes(pos, nvm, tonumber(payload), "exch")
elseif topic == "set" then elseif topic == "set" then
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
return exchange_nodes(pos, nvm, tonumber(payload), "set") return exchange_nodes(pos, nvm, tonumber(payload), "set")
@ -350,6 +520,9 @@ techage.register_node({"techage:ta3_doorcontroller2"}, {
elseif topic == "get" then elseif topic == "get" then
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
return get_node_name(nvm, tonumber(payload)) return get_node_name(nvm, tonumber(payload))
elseif topic == "reset" then
local nvm = techage.get_nvm(pos)
return restore_config(pos, nvm)
end end
return false return false
end, end,
@ -360,13 +533,16 @@ techage.register_node({"techage:ta3_doorcontroller2"}, {
return show_nodes(pos) and 0 or 3 return show_nodes(pos) and 0 or 3
elseif topic == 9 and payload[1] == 0 then -- Exchange Block elseif topic == 9 and payload[1] == 0 then -- Exchange Block
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
return exchange_nodes(pos, nvm, payload[2] or 1) and 0 or 3 return exchange_nodes(pos, nvm, payload[2] or 1, "exch") and 0 or 3
elseif topic == 9 and payload[1] == 1 then -- Set Block elseif topic == 9 and payload[1] == 1 then -- Set Block
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
return exchange_nodes(pos, nvm, payload[2] or 1, "set") and 0 or 3 return exchange_nodes(pos, nvm, payload[2] or 1, "set") and 0 or 3
elseif topic == 9 and payload[1] == 2 then -- Dig Block elseif topic == 9 and payload[1] == 2 then -- Dig Block
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
return exchange_nodes(pos, nvm, payload[2] or 1, "dig") and 0 or 3 return exchange_nodes(pos, nvm, payload[2] or 1, "dig") and 0 or 3
elseif topic == 9 and payload[1] == 3 then -- reset
local nvm = techage.get_nvm(pos)
return restore_config(pos, nvm) and 0 or 3
end end
return 2 return 2
end, end,

View File

@ -265,6 +265,34 @@ techage.register_node({"techage:ta4_movecontroller"}, {
end, end,
}) })
minetest.register_node("techage:rack_and_pinion", {
description = S("TA Rack and Pinion"),
tiles = {
-- up, down, right, left, back, front
"default_steel_block.png",
"default_steel_block.png",
"default_steel_block.png",
"default_steel_block.png",
"default_steel_block.png",
"techage_rack_and_pinion.png",
},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{ -6/32, -16/32, 14.1/32, 6/32, 16/32, 16/32},
},
},
paramtype = "light",
use_texture_alpha = techage.CLIP,
sunlight_propagates = true,
paramtype2 = "facedir",
is_ground_content = false,
groups = {cracky = 1, level = 2},
sounds = default.node_sound_metal_defaults(),
})
minetest.register_craft({ minetest.register_craft({
output = "techage:ta4_movecontroller", output = "techage:ta4_movecontroller",
recipe = { recipe = {
@ -273,3 +301,12 @@ minetest.register_craft({
{"group:wood", "basic_materials:gear_steel", "group:wood"}, {"group:wood", "basic_materials:gear_steel", "group:wood"},
}, },
}) })
minetest.register_craft({
output = "techage:rack_and_pinion 10",
recipe = {
{"", "default:steel_ingot", ""},
{"basic_materials:steel_bar", "default:steel_ingot", "basic_materials:steel_bar"},
{"", "default:steel_ingot", ""},
},
})

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2023 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -27,10 +27,11 @@ local control = networks.control
local HELP = S([[Commands local HELP = S([[Commands
help . . . print this text help . . . print this text
cls . . . . . clear screen cls . . . . clear screen
gen . . . . print all generators gen . . print generators
sto . . . . . print all storage systems sto . . print storage systems
con . . . . . print main consumers con1 . . print consumers with power consumption between 1 and 10 ku
con2 . . print consumers with power consumption with 10 ku or above
]]) ]])
local function row(num, label, data) local function row(num, label, data)
@ -41,7 +42,6 @@ local function row(num, label, data)
"label[8.5,"..y..";" .. data .. "]" "label[8.5,"..y..";" .. data .. "]"
end end
local function formspec1(pos, data) local function formspec1(pos, data)
local mem = techage.get_mem(pos) local mem = techage.get_mem(pos)
local outdir = M(pos):get_int("outdir") local outdir = M(pos):get_int("outdir")
@ -94,12 +94,32 @@ local function formspec2(pos)
"button[7.9,7.4;2,1;enter;"..S("Enter").."]" "button[7.9,7.4;2,1;enter;"..S("Enter").."]"
end end
--------------------------------------------------------------------------------------
--Overwrite networks.power.consume_power function
--------------------------------------------------------------------------------------
local origin_consume_power = networks.power.consume_power
function networks.power.consume_power(pos, tlib2, outdir, amount)
local nvm = techage.get_nvm(pos)
nvm.power_taken = origin_consume_power(pos, tlib2, outdir, amount)
return nvm.power_taken
end
local function get_consumer_power_consumption(pos)
if pos then
local nvm = techage.get_nvm(pos)
if nvm.running or techage.needs_power(nvm) then
return nvm.power_taken or 0
end
end
return 0
end
local function generators(pos) local function generators(pos)
local tbl = {} local tbl = {}
local outdir = M(pos):get_int("outdir") local outdir = M(pos):get_int("outdir")
local resp = control.request(pos, Cable, outdir, "gen", "info") local resp = control.request(pos, Cable, outdir, "gen", "info")
for _, item in ipairs(resp) do for _, item in ipairs(resp) do
local name = item.type .. " (" .. item.number .. ")"
if item.running then if item.running then
local s = string.format("%s (%s): %s/%u ku (%s)", local s = string.format("%s (%s): %s/%u ku (%s)",
item.type, item.number, techage.round(item.provided), item.available, item.termpoint) item.type, item.number, techage.round(item.provided), item.available, item.termpoint)
@ -119,26 +139,28 @@ local function storages(pos)
local outdir = M(pos):get_int("outdir") local outdir = M(pos):get_int("outdir")
local resp = control.request(pos, Cable, outdir, "sto", "info") local resp = control.request(pos, Cable, outdir, "sto", "info")
for _, item in ipairs(resp) do for _, item in ipairs(resp) do
local name = item.type .. " (" .. item.number .. ")" -- TA4/TA5 heatexchangers are no storage systems
if item.running then if item.capa and item.capa > 1 then
local s = string.format("%s (%s): %s/%s kud", if item.running then
item.type, item.number, local s = string.format("%s (%s): %s/%s kud",
techage.round(item.load / techage.CYCLES_PER_DAY), item.type, item.number,
techage.round(item.capa / techage.CYCLES_PER_DAY)) techage.round(item.load / techage.CYCLES_PER_DAY),
tbl[#tbl + 1] = s techage.round(item.capa / techage.CYCLES_PER_DAY))
else tbl[#tbl + 1] = s
local s = string.format("%s (%s): %s/%s kud (off)", else
item.type, item.number, local s = string.format("%s (%s): %s/%s kud (off)",
techage.round(item.load / techage.CYCLES_PER_DAY), item.type, item.number,
techage.round(item.capa / techage.CYCLES_PER_DAY)) techage.round(item.load / techage.CYCLES_PER_DAY),
tbl[#tbl + 1] = s techage.round(item.capa / techage.CYCLES_PER_DAY))
tbl[#tbl + 1] = s
end
end end
end end
table.sort(tbl) table.sort(tbl)
return table.concat(tbl, "\n") return table.concat(tbl, "\n")
end end
local function consumers(pos) local function consumers(pos, min, max)
local tbl = {} local tbl = {}
local outdir = M(pos):get_int("outdir") local outdir = M(pos):get_int("outdir")
local netw = networks.get_network_table(pos, Cable, outdir) or {} local netw = networks.get_network_table(pos, Cable, outdir) or {}
@ -147,7 +169,17 @@ local function consumers(pos)
if number then if number then
local name = techage.get_node_lvm(item.pos).name local name = techage.get_node_lvm(item.pos).name
name = (minetest.registered_nodes[name] or {}).description or "unknown" name = (minetest.registered_nodes[name] or {}).description or "unknown"
tbl[#tbl + 1] = name .. " (" .. number .. ")" local taken = techage.round(get_consumer_power_consumption(item.pos))
if taken > min and taken < max then
tbl[#tbl + 1] = string.format("%s (%s): %s ku", name, number, taken)
end
else
local name = techage.get_node_lvm(item.pos).name
name = (minetest.registered_nodes[name] or {}).description or "unknown"
local taken = techage.round(get_consumer_power_consumption(item.pos))
if taken > min and taken < max then
tbl[#tbl + 1] = string.format("%s: %s ku", name, taken)
end
end end
end end
table.sort(tbl) table.sort(tbl)
@ -157,7 +189,7 @@ end
local function output(pos, command, text) local function output(pos, command, text)
local meta = M(pos) local meta = M(pos)
text = meta:get_string("output") .. "\n$ " .. command .. "\n" .. (text or "") text = meta:get_string("output") .. "\n$ " .. command .. "\n" .. (text or "")
text = text:sub(-2000,-1) text = text:sub(-5000,-1)
meta:set_string("output", text) meta:set_string("output", text)
end end
@ -177,8 +209,10 @@ local function command(pos, nvm, command)
output(pos, command, generators(pos)) output(pos, command, generators(pos))
elseif cmd == "sto" then elseif cmd == "sto" then
output(pos, command, storages(pos)) output(pos, command, storages(pos))
elseif cmd == "con" then elseif cmd == "con1" then
output(pos, command, consumers(pos)) output(pos, command, consumers(pos, 1, 10))
elseif cmd == "con2" then
output(pos, command, consumers(pos, 9, 1000))
elseif command ~= "" then elseif command ~= "" then
output(pos, command, "") output(pos, command, "")
end end
@ -204,13 +238,18 @@ minetest.register_node("techage:ta3_power_terminal", {
}, },
}, },
after_place_node = function(pos) after_place_node = function(pos, placer)
M(pos):set_int("outdir", networks.side_to_outdir(pos, "B")) M(pos):set_int("outdir", networks.side_to_outdir(pos, "B"))
Cable:after_place_node(pos) Cable:after_place_node(pos)
M(pos):set_string("formspec", formspec1(pos)) M(pos):set_string("formspec", formspec1(pos))
local number = techage.add_node(pos, "techage:ta3_power_terminal")
M(pos):set_string("node_number", number)
M(pos):set_string("owner", placer:get_player_name())
M(pos):set_string("infotext", S("TA3 Power Terminal").." "..number)
end, end,
after_dig_node = function(pos) after_dig_node = function(pos, oldnode, oldmetadata, digger)
Cable:after_dig_node(pos) Cable:after_dig_node(pos)
techage.remove_node(pos, oldnode, oldmetadata)
techage.del_mem(pos) techage.del_mem(pos)
end, end,
on_rightclick = function(pos, node, clicker) on_rightclick = function(pos, node, clicker)
@ -271,6 +310,28 @@ minetest.register_node("techage:ta3_power_terminal", {
power.register_nodes({"techage:ta3_power_terminal"}, Cable, "con", {"B"}) power.register_nodes({"techage:ta3_power_terminal"}, Cable, "con", {"B"})
techage.register_node({"techage:ta3_power_terminal"}, {
on_recv_message = function(pos, src, topic, payload)
if topic == "load" then
local outdir = M(pos):get_int("outdir")
local value = networks.power.get_storage_percent(pos, Cable, outdir)
return techage.round(value)
else
return "unsupported"
end
end,
on_beduino_request_data = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == 134 then
local outdir = M(pos):get_int("outdir")
local value = networks.power.get_storage_percent(pos, Cable, outdir)
return 0, {math.floor(value + 0.5)}
else
return 2, ""
end
end,
})
minetest.register_craft({ minetest.register_craft({
output = "techage:ta3_power_terminal", output = "techage:ta3_power_terminal",
recipe = { recipe = {

View File

@ -23,6 +23,7 @@ local PWR_CAPA = 2400 -- ticks (2s) with 1 ku ==> 80 min = 4 game days
local Cable = techage.ElectricCable local Cable = techage.ElectricCable
local power = networks.power local power = networks.power
local control = networks.control
local function node_timer(pos, elapsed) local function node_timer(pos, elapsed)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
@ -46,7 +47,7 @@ local function node_timer(pos, elapsed)
power.start_storage_calc(pos, Cable, 5) power.start_storage_calc(pos, Cable, 5)
nvm.providing = true nvm.providing = true
else else
nvm.provided = power.provide_power(pos, Cable, 5, PWR_PERF) nvm.provided = power.provide_power(pos, Cable, 5, PWR_PERF, 0.8, 1.0)
nvm.capa = nvm.capa - nvm.provided nvm.capa = nvm.capa - nvm.provided
end end
else else
@ -105,6 +106,27 @@ minetest.register_node("techage:ta4_solar_minicell", {
power.register_nodes({"techage:ta4_solar_minicell"}, Cable, "gen", {"D"}) power.register_nodes({"techage:ta4_solar_minicell"}, Cable, "gen", {"D"})
control.register_nodes({"techage:ta4_solar_minicell"}, {
on_receive = function(pos, tlib2, topic, payload)
end,
on_request = function(pos, tlib2, topic)
if topic == "info" then
local nvm = techage.get_nvm(pos)
local meta = M(pos)
return {
type = S("TA4 Streetlamp Solar Cell"),
number = meta:get_string("node_number") or "",
running = nvm.providing or false,
available = PWR_PERF,
provided = nvm.provided or 0,
termpoint = "80% - 100%",
}
end
return false
end,
}
)
techage.register_node({"techage:ta4_solar_minicell"}, { techage.register_node({"techage:ta4_solar_minicell"}, {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2023 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -21,6 +21,7 @@ local S2P = minetest.string_to_pos
local Cable = techage.ElectricCable local Cable = techage.ElectricCable
local Axle = techage.Axle local Axle = techage.Axle
local power = networks.power local power = networks.power
local control = networks.control
local CYCLE_TIME = 2 local CYCLE_TIME = 2
local PWR_PERF = 24 local PWR_PERF = 24
@ -45,9 +46,7 @@ local function node_timer_on(pos, elapsed)
nvm.buffer = nvm.buffer + taken - 1 -- some loss nvm.buffer = nvm.buffer + taken - 1 -- some loss
if nvm.buffer >= PWR_PERF then if nvm.buffer >= PWR_PERF then
local tp1 = tonumber(meta:get_string("termpoint1")) nvm.provided = power.provide_power(pos, Cable, outdir, PWR_PERF, 0.8, 1.0)
local tp2 = tonumber(meta:get_string("termpoint2"))
nvm.provided = power.provide_power(pos, Cable, outdir, PWR_PERF, tp1, tp2)
nvm.load = power.get_storage_load(pos, Cable, outdir, PWR_PERF) nvm.load = power.get_storage_load(pos, Cable, outdir, PWR_PERF)
nvm.buffer = nvm.buffer - nvm.provided nvm.buffer = nvm.buffer - nvm.provided
end end
@ -172,6 +171,27 @@ techage.register_node({"techage:ta2_generator_off", "techage:ta2_generator_on"},
power.register_nodes({"techage:ta2_generator_off", "techage:ta2_generator_on"}, Axle, "con", {"L"}) power.register_nodes({"techage:ta2_generator_off", "techage:ta2_generator_on"}, Axle, "con", {"L"})
power.register_nodes({"techage:ta2_generator_off", "techage:ta2_generator_on"}, Cable, "gen", {"R"}) power.register_nodes({"techage:ta2_generator_off", "techage:ta2_generator_on"}, Cable, "gen", {"R"})
control.register_nodes({"techage:ta2_generator_off", "techage:ta2_generator_on"}, {
on_receive = function(pos, tlib2, topic, payload)
end,
on_request = function(pos, tlib2, topic)
if topic == "info" then
local nvm = techage.get_nvm(pos)
local meta = M(pos)
return {
type = S("TA2 Power Generator"),
number = "---",
running = true,
available = PWR_PERF,
provided = nvm.provided or 0,
termpoint = "80% - 100%",
}
end
return false
end,
}
)
minetest.register_craft({ minetest.register_craft({
output = "techage:ta2_generator_off", output = "techage:ta2_generator_off",
recipe = { recipe = {

View File

@ -22,6 +22,7 @@ local fuel = techage.fuel
local Pipe = techage.LiquidPipe local Pipe = techage.LiquidPipe
local power = networks.power local power = networks.power
local liquid = networks.liquid local liquid = networks.liquid
local control = networks.control
local CYCLE_TIME = 2 local CYCLE_TIME = 2
local STANDBY_TICKS = 1 local STANDBY_TICKS = 1
@ -327,6 +328,27 @@ local liquid_def = {
power.register_nodes({"techage:tiny_generator", "techage:tiny_generator_on"}, Cable, "gen", {"R"}) power.register_nodes({"techage:tiny_generator", "techage:tiny_generator_on"}, Cable, "gen", {"R"})
liquid.register_nodes({"techage:tiny_generator", "techage:tiny_generator_on"}, Pipe, "tank", nil, liquid_def) liquid.register_nodes({"techage:tiny_generator", "techage:tiny_generator_on"}, Pipe, "tank", nil, liquid_def)
control.register_nodes({"techage:tiny_generator", "techage:tiny_generator_on"}, {
on_receive = function(pos, tlib2, topic, payload)
end,
on_request = function(pos, tlib2, topic)
if topic == "info" then
local nvm = techage.get_nvm(pos)
local meta = M(pos)
return {
type = S("TA3 Tiny Power Generator"),
number = meta:get_string("node_number") or "",
running = techage.is_running(nvm) or false,
available = PWR_PERF,
provided = nvm.provided or 0,
termpoint = meta:get_string("termpoint"),
}
end
return false
end,
}
)
techage.register_node({"techage:tiny_generator", "techage:tiny_generator_on"}, { techage.register_node({"techage:tiny_generator", "techage:tiny_generator_on"}, {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)

View File

@ -28,8 +28,8 @@ local STANDBY_TICKS = 4
local COUNTDOWN_TICKS = 4 local COUNTDOWN_TICKS = 4
local CYCLE_TIME = 2 local CYCLE_TIME = 2
local PWR_NEEDED = 12 local PWR_NEEDED = 12
local EX_POINTS = 60 local EX_POINTS = 30
local MAX_DIST = 200 local MAX_DIST = 500
local DESCRIPTION = S("TA5 Teleport Block Liquids") local DESCRIPTION = S("TA5 Teleport Block Liquids")
local function formspec(self, pos, nvm) local function formspec(self, pos, nvm)

View File

@ -27,8 +27,8 @@ local STANDBY_TICKS = 4
local COUNTDOWN_TICKS = 4 local COUNTDOWN_TICKS = 4
local CYCLE_TIME = 2 local CYCLE_TIME = 2
local PWR_NEEDED = 12 local PWR_NEEDED = 12
local EX_POINTS = 60 local EX_POINTS = 30
local MAX_DIST = 200 local MAX_DIST = 500
local DESCRIPTION = S("TA5 Teleport Block Items") local DESCRIPTION = S("TA5 Teleport Block Items")
local function formspec(self, pos, nvm) local function formspec(self, pos, nvm)

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B