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)
if meta and physics then
-- store the player privs default values
meta:set_int("autobahn_speed", physics.speed)
meta:set_float("autobahn_speed", physics.speed)
-- set operator privs
meta:set_int("autobahn_isactive", 1)
physics.speed = 3.5
@ -67,7 +67,7 @@ local function reset_player_privs(player)
if meta and physics then
-- restore the player privs default values
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
-- delete stored default values
meta:set_string("autobahn_speed", "")

View File

@ -43,7 +43,7 @@ The mod features are:
- Extra Minecart privs for rail workers
- Ingame documentation (German and English), based on the mod "doc"
- 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
@ -74,50 +74,20 @@ Introduction
at least every 16 nodes/meters)
9. Place a Minecart in front of the buffer and check whether it starts after the
configured time
10. Check the cart state via the chat command: /mycart <num>
'<num>' is the cart number, or get a list of carts with /mycart
10. Check the cart state via the chat command: `/mycart <num>`
`<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
Minecart to get cart and items back
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>
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.
The block has to be placed below the rail.
see [Wiki](https://github.com/joe7575/minecart/wiki)
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
@ -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
-------
@ -193,4 +155,5 @@ History
Speed limit signs and cart terminal added
2021-09-02 V2.01 Chat command /stopcart added
2021-10-18 V2.02 Cart reproduction bug fixed
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
See license.txt for more information
]]--
--
@ -21,20 +21,20 @@
function minecart.is_cart_available(pos, param2, radius)
return minecart.get_nodecart_nearby(pos, param2, radius) ~= nil or
minecart.get_entitycart_nearby(pos, param2, radius) ~= nil
end
end
-- Function returns true if a standing cart as node is avaliable
function minecart.is_nodecart_available(pos, param2, radius)
return minecart.get_nodecart_nearby(pos, param2, radius) ~= nil
end
end
-- Function returns true if a standing cart as entity is avaliable
function minecart.is_entitycart_available(pos, param2, radius)
return minecart.get_entitycart_nearby(pos, param2, radius) ~= nil
end
end
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
minecart.start_nodecart(pos2, node.name, nil, punch_dir)
return true
@ -45,4 +45,39 @@ function minecart.punch_cart(pos, param2, radius, punch_dir)
minecart.push_entitycart(entity, punch_dir)
return true
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
See license.txt for more information
]]--
-- for lazy programmers
@ -142,7 +142,7 @@ end
minetest.register_entity("minecart:marker", {
initial_properties = {
visual = "upright_sprite",
visual = "upright_sprite",
textures = {"minecart_marker_cube.png"},
use_texture_alpha = minecart.CLIP,
physical = false,
@ -229,7 +229,7 @@ function minecart.manage_attachment(player, entity, get_on)
return
end
player_api.player_attached[player_name] = get_on
local obj = entity.object
if get_on then
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
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
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)
if not pos2 or not minecart.is_rail(pos2) then
-- 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
local node = minetest.get_node(pos2)
local ndef = minetest.registered_nodes[node_name]
local rail = node.name
minetest.swap_node(pos2, {name = node_name, param2 = param2})
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_int("userID", userID)
meta:set_string("infotext", owner .. ": " .. userID)
if cargo and ndef.set_cargo then
ndef.set_cargo(pos2, cargo)
end
@ -295,7 +297,7 @@ end
function minecart.add_entitycart(pos, node_name, entity_name, vel, cargo, owner, userID)
local obj = minetest.add_entity(pos, entity_name)
local objID = minecart.get_object_id(obj)
if objID then
local entity = obj:get_luaentity()
entity.start_pos = pos
@ -312,7 +314,7 @@ end
function minecart.start_entitycart(self, pos, facedir)
local route = {}
self.is_running = true
self.arrival_time = 0
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
self.no_normal_start = self.start_pos == nil
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 {})
end
end
function minecart.remove_nodecart(pos)
local node = minetest.get_node(pos)
function minecart.remove_nodecart(pos, node)
node = node or minetest.get_node(pos)
local ndef = minetest.registered_nodes[node.name]
local meta = M(pos)
local rail = meta:get_string("removed_rail")
local param2 = meta:get_int("removed_rail_param2")
if rail == "" then rail = "air" end
local userID = meta:get_int("userID")
local owner = meta:get_string("owner")
meta:set_string("infotext", "")
meta:set_string("formspec", "")
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
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)
-- Remove node
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)
entity.sound_handle = nil
end
local rot = entity.object:get_rotation()
local dir = minetest.yaw_to_dir(rot.y)
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")
end
minecart.stop_monitoring(self.owner, self.userID, pos)
minecart.stop_recording(self, pos)
minecart.stop_recording(self, pos)
self.object:remove()
end

View File

@ -7,7 +7,7 @@
MIT
See license.txt for more information
]]--
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", "demo/minecart.c", minecart_demo)
end
end)
end)

View File

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

View File

@ -7,7 +7,7 @@
MIT
See license.txt for more information
]]--
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 function stop_cart(self, cart_pos)
local player
self.is_running = false
self.arrival_time = 0
if self.driver then
local player = minetest.get_player_by_name(self.driver)
player = minetest.get_player_by_name(self.driver)
if player then
minecart.stop_recording(self, cart_pos)
minecart.stop_recording(self, cart_pos)
minecart.manage_attachment(player, self, false)
end
end
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)
end
minecart.entity_to_node(cart_pos, self)
if player then
player:set_pos(cart_pos)
end
end
local function get_ctrl(self, pos)
@ -50,20 +54,20 @@ end
local function new_speed(self, new_dir)
self.cart_speed = self.cart_speed or 0
local rail_speed = (self.waypoint.speed or 0) / 10
if rail_speed <= 0 then
rail_speed = math.max(self.cart_speed + rail_speed, 0)
elseif rail_speed <= self.cart_speed then
rail_speed = math.max((self.cart_speed + rail_speed) / 2, 0)
end
-- Speed corrections
if new_dir.y == 1 then
if rail_speed < 1 then rail_speed = 0 end
else
if rail_speed < 0.4 then rail_speed = 0 end
end
self.cart_speed = rail_speed -- store for next cycle
return rail_speed
end
@ -82,7 +86,7 @@ local function running(self)
facedir = minetest.dir_to_facedir(dir)
end
local cart_pos, wayp_pos, is_junction
if self.reenter then -- through monitoring
cart_pos = H2P(self.reenter[1])
-- pos correction on slopes
@ -120,14 +124,14 @@ local function running(self)
stop_cart(self, wayp_pos)
return
end
if is_junction then
if self.is_recording then
set_junctions(self, wayp_pos)
end
self.ctrl = nil
end
--print("running", LEN(self.junctions))
local dist = vector.distance(cart_pos, self.waypoint.cart_pos or self.waypoint.pos)
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
end
new_speed = math.min(new_speed, self.speed_limit)
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?
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)
--print("extra_cycle", P2S(cart_pos), P2S(wayp_pos), P2S(new_cart_pos), new_speed)
end
-- Slope corrections
--print("Slope corrections", P2S(new_dir), P2S(cart_pos))
if new_dir.y ~= 0 then
cart_pos.y = cart_pos.y + 0.2
end
end
-- Calc velocity, rotation and arrival_time
local yaw = minetest.dir_to_yaw(new_dir)
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))
self.arrival_time = self.timebase + (dist / new_speed)
-- needed for recording
self.curr_speed = new_speed
self.curr_speed = new_speed
self.num_sections = (self.num_sections or 0) + 1
-- Got stuck somewhere
if new_speed < 0.1 or dist < 0 then
minetest.log("warning", "[Minecart] Got stuck somewhere " .. new_speed .. " " .. dist)
stop_cart(self, wayp_pos)
return
end
self.object:set_pos(cart_pos)
self.object:set_rotation({x = pitch, y = yaw, z = 0})
self.object:set_velocity(vel)
@ -194,12 +198,12 @@ end
local function on_step(self, dtime)
self.timebase = (self.timebase or 0) + dtime
if self.is_running then
if self.arrival_time <= self.timebase then
running(self)
end
if (self.sound_ttl or 0) <= self.timebase then
play_sound(self)
self.sound_ttl = self.timebase + 1.0
@ -208,7 +212,7 @@ local function on_step(self, dtime)
if self.sound_handle then
minetest.sound_stop(self.sound_handle)
self.sound_handle = nil
end
end
end
if self.driver then
@ -219,7 +223,7 @@ local function on_step(self, dtime)
end
if recording_junctions(self) then
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)
minecart.manage_attachment(player, self, false)
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
if self.driver then
-- 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.remove_entity(self, pos, puncher)
minecart.manage_attachment(puncher, self, false)
else
-- 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)
end
end
@ -272,11 +276,11 @@ local function on_entitycard_punch(self, puncher, time_from_last_punch, tool_cap
end
local facedir = minetest.dir_to_facedir(dir or {x=0, y=0, z=0})
minecart.start_entitycart(self, pos, facedir or 0)
minecart.start_recording(self, pos)
minecart.start_recording(self, pos)
end
end
end
-- Player get on / off
local function on_entitycard_rightclick(self, clicker)
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
-- get off
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.entity_to_node(pos, self)
else
-- get on
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)
end
end
@ -312,7 +316,7 @@ function minecart.get_entitycart_nearby(pos, param2, radius)
return entity
end
end
end
end
end
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_rightclick = on_entitycard_rightclick
entity_def.on_detach_child = on_entitycard_detach_child
entity_def.owner = nil
entity_def.driver = nil
entity_def.cargo = {}
minetest.register_entity(entity_name, entity_def)
-- register node for punching
minecart.register_cart_names(node_name, entity_name, cart_type)

View File

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

View File

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

View File

@ -13,7 +13,7 @@
minecart = {}
-- 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.teleport_enabled = minetest.settings:get_bool("minecart_teleport_enabled") == true

View File

@ -3,6 +3,7 @@ Station name=Stationsname
Waiting time/sec=Wartezeit/s
connected to=verbunden mit
Not connected!=Nicht verbunden!
Minecart Railway Buffer=Minecart Prellbock
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.
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
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.
Minecart Railway Buffer=Minecart Prellbock
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)
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
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
stopped=gestoppt
dropped=fallen gelassen
is not existing!=existiert nicht!
Enter cart number=Gebe Cart Nummer ein
Save=Speichern
[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
Minecart Landmark=Minecart Meilenstein
Cart Pusher=Wagen Anschieber
left=links
right=rechts
straight=geradeaus
@ -49,6 +49,7 @@ Recording=Aufzeichnung
speed=Tempo
next junction=nächste Weiche
Travel time=Fahrzeit
[minecart] Recording canceled!=
[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] 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
Cart List=Cart Liste
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=
connected to=
Not connected!=
Minecart Railway Buffer=
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.=
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=
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.=
Minecart Railway Buffer=
Minecart Hopper=
Minecart Landmark=
Cart Pusher=
Minecart (Sneak+Click to pick up)=
Output cart state and position, or a list of carts, if no cart number is given.=
List of carts=
Stop amd return a missing/running cart.=
Stop and return/drop a missing/running cart.=
Cart=
stopped=
dropped=
is not existing!=
Enter cart number=
Save=
[minecart] Area is protected!=
Allow to dig/place rails in Minecart Landmark areas=
Minecart Landmark=
Cart Pusher=
left=
right=
straight=
@ -49,6 +49,7 @@ Recording=
speed=
next junction=
Travel time=
[minecart] Recording canceled!=
[minecart] Route stored!=
[minecart] Speed @= %u m/s, Time @= %u s, Route length @= %u m=
[minecart] Your route is too short to record!=

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@
MIT
See license.txt for more information
]]--
-- 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 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 pos3 = minetest.find_node_near(pos2, radius or 0.5, minecart.lCartNodeNames, true)
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
minecart.monitoring_add_cart(owner, userID, pos, node_name, entity_name)
else
M(pos):set_string("infotext",
M(pos):set_string("infotext",
minetest.get_color_escape_sequence("#FFFF00") .. owner .. ": 0")
return
end
@ -48,7 +48,7 @@ function minecart.start_nodecart(pos, node_name, puncher, punch_dir)
if obj then
local entity = obj:get_luaentity()
local facedir
if puncher then
local yaw = puncher:get_look_horizontal()
entity.object:set_rotation({x = 0, y = yaw, z = 0})
@ -72,7 +72,7 @@ function minecart.show_formspec(pos, clicker)
"size[4,3]" ..
"label[0,0;" .. S("Enter cart number") .. ":]" ..
"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
@ -81,7 +81,7 @@ function minecart.on_nodecart_place(itemstack, placer, pointed_thing)
local node_name = itemstack:get_name()
local param2 = minetest.dir_to_facedir(placer:get_look_dir())
local owner = placer:get_player_name()
-- Add node
if minecart.is_rail(pointed_thing.under) then
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
itemstack:take_item()
end
return itemstack
end
-- Start the node cart (or dig by shift+leftclick)
function minecart.on_nodecart_punch(pos, node, puncher, pointed_thing)
--print("on_nodecart_punch")
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 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]
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.monitoring_remove_cart(owner, userID)
end
@ -134,7 +133,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local userID = tonumber(fields.userID) or 0
if minecart.userID_available(owner, userID) then
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") ..
player:get_player_name() .. ": " .. userID)
local node = minetest.get_node(cart_pos)

View File

@ -3,11 +3,11 @@
Minecart
========
Copyright (C) 2019-2021 Joachim Stolberg
Copyright (C) 2019-2023 Joachim Stolberg
MIT
See license.txt for more information
]]--
local S = minecart.S
@ -77,7 +77,7 @@ minetest.register_node("minecart:landmark", {
return true
end
end,
can_dig = function(pos, digger)
local meta = minetest.get_meta(pos)
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
return true
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")..")")
return false
end,
on_punch = function(pos, node, puncher, pointed_thing)
minecart.set_land_marker(pos, RANGE, 20)
end,
paramtype2 = "facedir",
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
use_texture_alpha = minecart.CLIP,
groups = {cracky = 3, stone = 1},
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
@ -135,7 +137,10 @@ minetest.register_node("minecart:ballast_slope", {
type = "fixed",
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
},
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
use_texture_alpha = minecart.CLIP,
groups = {crumbly = 1, cracky = 3},
sounds = default.node_sound_stone_defaults(),
})
@ -157,7 +162,10 @@ minetest.register_node("minecart:ballast_ramp", {
type = "fixed",
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
},
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
use_texture_alpha = minecart.CLIP,
groups = {crumbly = 1, cracky = 3},
sounds = default.node_sound_stone_defaults(),
})

View File

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

View File

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

View File

@ -7,7 +7,7 @@
MIT
See license.txt for more information
]]--
-- for lazy programmers
@ -29,7 +29,7 @@ local function dashboard_destroy(self)
end
local function dashboard_create(self)
if self.driver then
if self.driver then
local player = minetest.get_player_by_name(self.driver)
if player then
dashboard_destroy(self)
@ -51,13 +51,13 @@ local function dashboard_update(self)
local player = minetest.get_player_by_name(self.driver)
if player then
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")
local speed = math.floor((self.curr_speed or 0) + 0.5)
local s = string.format(S("Recording") ..
" | " .. S("speed") ..
": %.1f | " .. S("next junction") ..
": %-8s | " .. S("Travel time") .. ": %.1f s",
local s = string.format(S("Recording") ..
" | " .. S("speed") ..
": %.1f | " .. S("next junction") ..
": %-8s | " .. S("Travel time") .. ": %.1f s",
speed, dir, time)
player:hud_change(self.hud_id, "text", s)
end
@ -83,7 +83,7 @@ end
--
-- Route recording
--
function minecart.start_recording(self, pos)
function minecart.start_recording(self, pos)
--print("start_recording")
if self.driver then
self.start_pos = minecart.get_buffer_pos(pos, self.driver)
@ -103,7 +103,7 @@ function minecart.start_recording(self, pos)
end
end
function minecart.stop_recording(self, pos, force_exit)
function minecart.stop_recording(self, pos, force_exit)
--print("stop_recording")
if self.driver and self.is_recording then
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!"))
elseif dest_pos and player and #self.checkpoints > 3 then
-- 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
local route = {
dest_pos = dest_pos,
@ -138,19 +138,19 @@ function minecart.stop_recording(self, pos, force_exit)
self.junctions = nil
end
function minecart.recording_waypoints(self)
function minecart.recording_waypoints(self)
local pos = vector.round(self.object:get_pos())
-- pos correction on slopes
if not minecart.is_rail(pos) then
pos.y = pos.y - 1
end
-- 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)
self.checkpoints[#self.checkpoints+1] = {
-- cart_pos, next_waypoint_pos, speed, dot
P2H(pos),
P2H(wp_pos),
P2H(pos),
P2H(wp_pos),
math.floor(self.curr_speed + 0.5),
self.waypoint.dot
}

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@
MIT
See license.txt for more information
]]--
-- for lazy programmers
@ -19,7 +19,7 @@ local P2H = minetest.hash_node_position
local sDir = {[0] = "north", "east", "south", "west"}
local function DOTS(dots)
local function DOTS(dots)
if dots then
return table.concat(dots, ", ")
else
@ -50,15 +50,15 @@ local function test_get_route(pos, node, player)
if route.cart_pos then
minecart.set_marker(route.cart_pos, "cart", 0.3, 10)
end
-- determine some kind of current y
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 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)
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))
end
end

View File

@ -80,7 +80,7 @@ All this testing nodes can be enabled via mod settings `networks_test_enabled =
### 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
Textures: CC BY-SA 3.0
@ -131,3 +131,6 @@ Required: tubelib2
**2022-09-10 V0.12**
- 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
========
Copyright (C) 2021 Joachim Stolberg
Copyright (C) 2021-2023 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -13,7 +13,7 @@
networks = {}
-- 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
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)
amount = math.floor((amount or 0) + 0.5)
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.amount = amount
return 0
@ -292,4 +293,4 @@ function networks.liquid.get_liquids(pos, tlib2)
out[#out + 1] = k
end
return out
end
end

View File

@ -3,7 +3,7 @@
Networks
========
Copyright (C) 2021 Joachim Stolberg
Copyright (C) 2021-2023 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -439,3 +439,13 @@ function networks.power.get_network_data(pos, tlib2, outdir)
end
return DEFAULT_DATA
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_above <slot> - dig block above 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_behind <slot> - put a sign behind the bot
dig_sign <slot> - remove the sign

View File

@ -395,6 +395,42 @@ signs_bot.register_botcommand("rotate_item", {
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
minetest.register_node("signs_bot:torch", {
description = S("Bot torch"),

View File

@ -27,7 +27,7 @@ In the worst case, the server crashes.**
### 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
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
**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**
- Improve flycontroller
- Remove handover for movecontroller

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2022 Joachim Stolberg
Copyright (C) 2019-2023 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -19,7 +19,7 @@ local M = minetest.get_meta
local S = techage.S
local TA4_INV_SIZE = 32
local EX_POINTS = 20
local EX_POINTS = 15
local hyperloop = techage.hyperloop
local remote_pos = techage.hyperloop.remote_pos
@ -49,7 +49,7 @@ local function allow_metadata_inventory_put(pos, listname, index, stack, player)
end
shared_inv.before_inv_access(pos, listname)
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()
end
return 0
@ -61,7 +61,7 @@ local function allow_metadata_inventory_take(pos, listname, index, stack, player
end
shared_inv.before_inv_access(pos, listname)
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()
end
return 0
@ -141,36 +141,64 @@ minetest.register_node("techage:ta5_hl_chest", {
techage.register_node({"techage:ta5_hl_chest"}, {
on_inv_request = function(pos, in_dir, access_type)
pos = remote_pos(pos)
local meta = minetest.get_meta(pos)
return meta:get_inventory(), "main"
if pos then
local meta = minetest.get_meta(pos)
if meta then
return meta:get_inventory(), "main"
end
end
end,
on_pull_item = function(pos, in_dir, num, item_name)
pos = remote_pos(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return techage.get_items(pos, inv, "main", num)
if pos then
local meta = minetest.get_meta(pos)
if meta then
local inv = meta:get_inventory()
if inv then
return techage.get_items(pos, inv, "main", num)
end
end
end
return false
end,
on_push_item = function(pos, in_dir, stack)
if techage.hyperloop.is_paired(pos) then
pos = remote_pos(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return techage.put_items(inv, "main", stack)
if pos then
local meta = minetest.get_meta(pos)
if meta then
local inv = meta:get_inventory()
if inv then
return techage.put_items(inv, "main", stack)
end
end
end
end
return false
end,
on_unpull_item = function(pos, in_dir, stack)
pos = remote_pos(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return techage.put_items(inv, "main", stack)
if pos then
local meta = minetest.get_meta(pos)
if meta then
local inv = meta:get_inventory()
if inv then
return techage.put_items(inv, "main", stack)
end
end
end
return false
end,
on_recv_message = function(pos, src, topic, payload)
if topic == "state" then
pos = remote_pos(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return techage.get_inv_state(inv, "main")
if meta then
local inv = meta:get_inventory()
if inv then
return techage.get_inv_state(inv, "main")
end
end
return "error"
else
return "unsupported"
end
@ -178,8 +206,12 @@ techage.register_node({"techage:ta5_hl_chest"}, {
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 131 then -- Chest State
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return 0, {techage.get_inv_state_num(inv, "main")}
if meta then
local inv = meta:get_inventory()
if inv then
return 0, {techage.get_inv_state_num(inv, "main")}
end
end
else
return 2, ""
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}
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 name = item.name or "air"
local param2 = item.param2 or 0
@ -49,12 +50,18 @@ local function set_node(item)
nvm.running = false
M(item.base_pos):set_string("status", S("Stopped"))
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)
minetest.set_node(dest_pos, {name=name, param2=param2})
meta:from_table(item.metadata or {})
meta:set_string("ta_move_block", "")
meta:set_int("ta_door_locked", 1)
if name ~= "techage:moveblock" then
minetest.set_node(dest_pos, {name=name, param2=param2})
meta:from_table(item.metadata or {})
meta:set_string("ta_move_block", "")
meta:set_int("ta_door_locked", 1)
end
return
end
local meta = M(dest_pos)
@ -63,7 +70,9 @@ local function set_node(item)
return
end
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
@ -294,7 +303,7 @@ local function detach_player(player)
end
-- 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 res = obj:get_attach()
if not res then -- not already attached
@ -305,20 +314,20 @@ local function attach_single_object(parent, obj, dir)
yaw = obj:get_rotation().y
end
-- 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
local rot = parent:get_rotation()
if self.param2 >= 20 then
dir = rotate(dir, 2 * math.pi - rot.y)
dir.y = -dir.y
dir.x = -dir.x
distance = rotate(distance, 2 * math.pi - rot.y)
distance.y = -distance.y
distance.x = -distance.x
rot.y = rot.y - yaw
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
end
dir = vector.multiply(dir, 29)
obj:set_attach(parent, "", dir, vector.multiply(rot, 180 / math.pi))
distance = vector.multiply(distance, 29)
obj:set_attach(parent, "", distance, vector.multiply(rot, 180 / math.pi))
obj:set_properties({visual_size = {x=2.9, y=2.9}})
if obj:is_player() then
if lock_player(obj) then
@ -332,19 +341,21 @@ end
-- Attach all objects around to the parent object
-- 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)
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()
if entity then
local mod = entity.name:gmatch("(.-):")()
if techage.RegisteredMobsMods[mod] then
dir.y = dir.y + yoffs
attach_single_object(parent, obj, dir)
distance.y = distance.y + yoffs
attach_single_object(parent, obj, distance)
end
elseif obj:is_player() then
attach_single_object(parent, obj, dir)
attach_single_object(parent, obj, distance)
end
end
end
@ -380,10 +391,11 @@ end
local function entity_to_node(pos, obj)
local self = obj:get_luaentity()
if self and self.item then
local playername = self.players and self.players[1] and self.players[1].name
detach_objects(pos, self)
monitoring_del_entity(self.item)
minetest.after(0.1, obj.remove, obj)
set_node(self.item)
set_node(self.item, playername)
end
end
@ -392,9 +404,12 @@ end
-- * start_pos and dest_pos are entity positions
local function node_to_entity(base_pos, start_pos, dest_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
node = minetest.deserialize(meta:get_string("ta_move_block"))
metadata = {}
@ -424,6 +439,7 @@ local function node_to_entity(base_pos, start_pos, dest_pos)
metadata = metadata or {},
dest_pos = dest_pos,
base_pos = base_pos,
cartdef = cartdef,
}
monitoring_add_entity(self.item)
@ -432,7 +448,7 @@ local function node_to_entity(base_pos, start_pos, dest_pos)
self.entities = {}
-- Prepare for path walk
self.path_idx = 1
return obj
return obj, self.item.cartdef ~= nil
end
end
@ -536,6 +552,9 @@ local function is_valid_dest(pos)
if techage.is_air_like(node.name) then
return true
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
return true
end
@ -543,9 +562,15 @@ local function is_valid_dest(pos)
end
local function is_simple_node(pos)
local node =techage.get_node_lvm(pos)
local ndef = minetest.registered_nodes[node.name]
return not techage.is_air_like(node.name) and techage.can_dig_node(node.name, ndef)
local node = techage.get_node_lvm(pos)
if not minecart.is_rail(pos, node.name) then
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
-- 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
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
local offs = {x=0, y=height or 1, z=0}
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)
if is_cart then
attach_objects(pos1, 0, obj, yoffs, {x = 0, y = -0.4, z = 0})
else
local offs = {x=0, y=height or 1, z=0}
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
local self = obj:get_luaentity()
@ -801,6 +830,21 @@ function flylib.remove_node(pos)
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)
unlock_player(player)
end)

View File

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

View File

@ -75,6 +75,24 @@ techage.liquid.recv_message = {
return "unsupported"
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")

View File

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

View File

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

View File

@ -21,7 +21,7 @@ local Pipe = techage.LiquidPipe
local MP = minetest.get_modpath("minecart")
local liquid = networks.liquid
local CAPACITY = 100
local CAPACITY = 200
local function on_rightclick(pos, node, clicker)
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)
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
local mem = techage.get_mem(pos)
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_appl_open.png^techage_frame_ta3.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",
},
@ -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_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,
animation = {
type = "vertical_frames",

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2021 Joachim Stolberg
Copyright (C) 2019-2023 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -157,7 +157,7 @@ local function create_task(pos, task)
end
-- 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"]
for idx,pos2 in ipairs(nvm.magnet_positions or {}) do
local res = ndef.on_cyclic_check(pos2)
@ -173,6 +173,29 @@ local function magnet_on_cyclic_check(pos, nvm)
return true
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", {
description = S("TA4 Collider Detector Core"),
tiles = {
@ -202,29 +225,33 @@ minetest.register_node("techage:ta4_detector_core", {
on_timer = function(pos, elapsed)
local nvm = techage.get_nvm(pos)
if not magnet_on_cyclic_check(pos, nvm) then
techage.del_laser(pos)
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
if nvm.running then
if not magnets_on_cyclic_check(pos, nvm) then
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.magnet_positions = nil
terminal_message(pos, "Detector stopped.")
end
if nvm.running then
play_sound(pos)
else
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)
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
return true
@ -287,6 +314,7 @@ local function start_task(pos)
end
nvm.magnet_positions = t
techage.send_single(own_num, term_num, "append", "ok")
cable_inlets_turn_on_off(pos, true)
coroutine.yield()
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 .. "!!!")
nvm.magnet_positions = nil
nvm.locked = false
cable_inlets_turn_on_off(pos, false)
return
end
else
@ -323,12 +352,14 @@ local function start_task(pos)
techage.send_single(own_num, term_num, "append", err .. "!!!")
nvm.magnet_positions = nil
nvm.locked = false
cable_inlets_turn_on_off(pos, false)
return
end
else
techage.send_single(own_num, term_num, "append", "defect!!!")
nvm.magnet_positions = nil
nvm.locked = false
cable_inlets_turn_on_off(pos, false)
return
end
coroutine.yield()
@ -337,7 +368,7 @@ local function start_task(pos)
techage.send_single(own_num, term_num, "append", "ok")
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.running = true
end
@ -372,6 +403,9 @@ techage.register_node({"techage:ta4_detector_core"}, {
nvm.running = false
techage.del_laser(pos)
nvm.locked = false
magnets_turn_off(pos, nvm)
cable_inlets_turn_on_off(pos, false)
nvm.magnet_positions = nil
return "Detector stopped."
elseif topic == "status" 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)
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
end,
@ -346,6 +350,11 @@ function techage.power_inlet_check(pos, node, meta, nvm)
return false, "no power"
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"})
techage.register_node({"techage:ta4_collider_cable_inlet"}, {

View File

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

View File

@ -21,7 +21,6 @@ techage.manual_DE.aTitel = {
"3,TA1 Schleusengriff / TA1 Sluice Handle",
"3,TA1 Apfelholzbrett / TA1 Apple Wood Board",
"3,TA1 Apfel Mühlbachbrett / TA1 Apple Millrace Board",
"2, ",
"2,Erze und Werkzeuge",
"3,Hammer",
"3,Kiessieb / Gravel Sieve",
@ -432,7 +431,6 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
"",
"TA1 hat seine eigenen Werkzeuge wie Hammer und Kiessieb\\, aber auch der Minecart Hopper kann genutzt werden.\n"..
"\n"..
"\n"..
@ -981,7 +979,7 @@ techage.manual_DE.aText = {
"\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"..
"In den Tankwagen passen 100 Einheiten.\n"..
"In den Tankwagen passen 200 Einheiten.\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"..
" - man kann auch durch Wände oder andere Blöcke fliegen\n"..
" - auch die Zielposition für die Blöcke kann belegt sein. Die Blöcke werden in diesem Falle \"unsichtbar\" gespeichert. Dies ist für Schiebetüren und ähnliches gedacht\n"..
" - Über das Gabelschlüssel-Menü kann im Controller auch ein \"handover\" programmiert werden. Durch Eingabe einer Blocknummer werden die Blöcke dann an den nächsten Move Controller übergeben. So lassen sich auch zusammenhängende Bewegungen über mehrere Move Controller realisieren.\n"..
"\n"..
"Der Move Controller unterstützt folgende techage Kommandos:\n"..
"\n"..
@ -2112,7 +2109,7 @@ techage.manual_DE.aText = {
"\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"..
"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",
@ -2122,7 +2119,7 @@ techage.manual_DE.aText = {
"\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"..
"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",
@ -2134,25 +2131,25 @@ techage.manual_DE.aText = {
"\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"..
"Ein Teleport-Block benötigt 12 ku Strom.\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",
"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"..
"Ein Teleport-Block benötigt 12 ku Strom.\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",
"Die Hyperloop Teleport Blöcke erlauben den Aufbau von Hyperloop Netzwerk ohne Hyperloop-Röhren.\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",
"",
"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",
"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",
@ -2190,7 +2187,6 @@ techage.manual_DE.aItemName = {
"ta1_sluice_handle",
"ta1_board1",
"ta1_board2",
"",
"ta1_gravelsieve",
"hammer",
"ta1_gravelsieve",
@ -2451,7 +2447,6 @@ techage.manual_DE.aPlanTable = {
"",
"",
"",
"",
"hoppersieve",
"",
"",

View File

@ -983,7 +983,7 @@ techage.manual_EN.aText = {
"\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"..
"100 units fit in the tank truck.\n"..
"200 units fit in the tank truck.\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"..
" - you can also fly through walls or other blocks\n"..
" - The target position for the blocks can also be occupied. In this case\\, the blocks are saved \"invisibly\". This is intended for sliding doors and the like\n"..
" - A \"handover\" can also be programmed in the controller via the open-ended wrench menu. By entering a block number\\, the blocks are then transferred to the next move controller. In this way\\, connected movements can also be implemented using several Move Controllers.\n"..
"\n"..
"The Move Controller supports the following techage commands:\n"..
"\n"..
@ -2118,7 +2117,7 @@ techage.manual_EN.aText = {
"\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"..
"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",
@ -2128,7 +2127,7 @@ techage.manual_EN.aText = {
"\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"..
"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",
@ -2138,25 +2137,25 @@ techage.manual_EN.aText = {
"\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"..
"Each Teleport blocks requires 12 ku of electricity.\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",
"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"..
"Each Teleport blocks requires 12 ku of electricity.\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",
"The Hyperloop Teleport Blocks allow the construction of a Hyperloop network without Hyperloop tubes.\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",
"",
"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",
"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",

View File

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

View File

@ -26,6 +26,7 @@ local STANDBY_TICKS = 3
local PWR_NEEDED = 35
local PWR_UNITS_PER_HYDROGEN_ITEM = 80
local CAPACITY = 200
local TURNOFF_THRESHOLD = "40%"
local function evaluate_percent(s)
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)
end
elseif curr_load == 0 then
nvm.taken = 0
State:nopower(pos, nvm)
else
nvm.taken = 0
State:standby(pos, nvm, S("Turnoff point reached"))
end
else
nvm.taken = 0
State:blocked(pos, nvm, S("Storage full"))
end
if techage.is_activeformspec(pos) then
@ -161,6 +165,8 @@ local function after_place_node(pos)
State:node_init(pos, nvm, number)
local node = minetest.get_node(pos)
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)
Cable:after_place_node(pos)
end
@ -201,7 +207,7 @@ local tool_config = {
name = "turnoff",
label = S("Turnoff point"),
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)
if not meta:contains("reduction") then
meta:set_string("reduction", "100%")
meta:set_string("turnoff", "100%")
meta:set_string("turnoff", TURNOFF_THRESHOLD)
end
end,
})

View File

@ -219,7 +219,7 @@ function techage.display.write_row(pos, payload, cycle_time, beduino)
nvm.text = nvm.text or {}
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
str = payload:sub(2) or "oops"
else

View File

@ -13,7 +13,7 @@
techage = {}
-- Version for compatibility checks, see readme.md/history
techage.version = 1.10
techage.version = 1.11
if minetest.global_exists("tubelib") then
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
minetest.log("error", "[techage] Techage requires tubelib2 version 2.2 or newer!")
return
elseif minetest.global_exists("minecart") and minecart.version < 2.03 then
minetest.log("error", "[techage] Techage requires minecart version 2.03 or newer!")
elseif minetest.global_exists("minecart") and minecart.version < 2.04 then
minetest.log("error", "[techage] Techage requires minecart version 2.04 or newer!")
return
elseif minetest.global_exists("lcdlib") and lcdlib.version < 1.01 then
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
minetest.log("error", "[techage] Techage requires safer_lua version 1.01 or newer!")
return
elseif minetest.global_exists("networks") and networks.version < 0.12 then
minetest.log("error", "[techage] Techage requires networks version 0.12 or newer!")
elseif minetest.global_exists("networks") and networks.version < 0.13 then
minetest.log("error", "[techage] Techage requires networks version 0.13 or newer!")
return
elseif minetest.global_exists("hyperloop") and hyperloop.version < 2.07 then
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,
paramtype = "light",
use_texture_alpha = techage.CLIP,
drop = "techage:meltingpot",
is_ground_content = false,
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", {
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"}
})
techage.recipes.add("ta3_electronic_fab", {
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"}
})
@ -81,17 +83,20 @@ techage.recipes.add("ta4_electronic_fab", {
techage.recipes.add("ta4_electronic_fab", {
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"}
})
techage.recipes.add("ta4_electronic_fab", {
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"},
ex_points = 10,
})
techage.recipes.add("ta4_electronic_fab", {
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"},
ex_points = 50,
ex_points = 25,
})

View File

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

View File

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

View File

@ -291,6 +291,10 @@ TA2 Cylinder=TA2 Zylinder
### 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 Core=TA4 Collider Detektorkern
TA4 Detector=TA4 Detektor
@ -500,8 +504,10 @@ Move=Bewege
Move A-B=Bewege A-B
Move B-A=Bewege B-A
Move block height=Move Block Höhe
Object offset=Objekt Offset
Stored=Gespeichert
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 ###
@ -665,7 +671,6 @@ TA4 Hydrogen=TA4 Wasserstoff
### hyperloop.lua ###
### sensorchest.lua ###
### teleport.lua ###
### terminal.lua ###
not connected=nicht verbunden
@ -746,7 +751,6 @@ Block has an@nadditional wrench menu=Block besitzt ein@nzusätzliches@nSchrauben
### lib.lua ###
### sensorchest.lua ###
### terminal.lua ###
connected with=verbunden mit
@ -888,27 +892,22 @@ TA4 Streetlamp Solar Cell=TA4 Straßenlampen-Solarzelle
### minichest.lua ###
Test Chest=
Test Chest=Testkiste
### minitank.lua ###
Test Mini Tank=
Test Mini Tank=Testminitank
### movecontroller.lua ###
Error: Invalid distance !!=Fehler: Ungültige Entfernung !!
Handover to A=Übergabe an A
Handover to B=Übergabe an B
Move distance=Entfernung
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
Reset=Rücksetzen
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
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 ###
@ -1170,6 +1169,8 @@ stopped=gestoppt
Commands=Kommandos
Cycle time=Zykluszeit
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!
Start=Start
Stop=Stopp
@ -1192,8 +1193,8 @@ TA5 Fusion Reactor Shell=TA5 Fusionsreaktor Hülle
### signallamp.lua ###
TA4 Wind Turbine Signal Lamp=TA4 Windkraftanlagenlampe
TechAge Signal Lamp=TechAge Signallampe
TechAge Signal Lamp 2 =TechAge Signallampe 2
TechAge Color Lamp=TechAge Farblampe
TechAge Color Lamp 2=TechAge Farblampe 2
### signallamp_2x.lua ###
@ -1401,7 +1402,6 @@ TA5 Teleport Block Items=TA5 Teleport Block Gegenstände
Syntax error, try help=Syntax Fehler, nutze help
TA3 Terminal=TA3 Terminal
TA4 Collider Terminal=TA4 Collider Terminal
TA4 Terminal=TA4 Terminal
commands like: help=Kommandos wie: help
@ -1511,4 +1511,11 @@ TA4 Collider Detector Worker=TA4 Collider Detektor Worker
##### 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 !!

View File

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

View File

@ -45,9 +45,18 @@ local WRENCH_MENU = {
name = "cycletime",
label = S("Cycle time"),
tooltip = S("Timer cycle time (default: 100 ms)"),
default = "1",
default = "100ms",
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)
@ -171,6 +180,7 @@ local function formspec(nvm, meta)
return "size[10,8]" ..
style ..
techage.wrench_image(9.3, -0.25) ..
"tabheader[0,0;tab;edit,help;1;;true]" ..
"label[0.1,-0.2;" .. S("Commands") .. ":]" ..
textarea ..
@ -325,7 +335,7 @@ techage.register_node({"techage:ta4_sequencer"}, {
mem.idx = tonumber(payload or 1) or 1
restart_timer(pos, 1)
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
minetest.get_node_timer(pos):stop()
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
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.
In den Tankwagen passen 100 Einheiten.
In den Tankwagen passen 200 Einheiten.
[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.
100 units fit in the tank truck.
200 units fit in the tank truck.
[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
- man kann auch durch Wände oder andere Blöcke fliegen
- auch die Zielposition für die Blöcke kann belegt sein. Die Blöcke werden in diesem Falle "unsichtbar" gespeichert. Dies ist für Schiebetüren und ähnliches gedacht
- Über das Gabelschlüssel-Menü kann im Controller auch ein "handover" programmiert werden. Durch Eingabe einer Blocknummer werden die Blöcke dann an den nächsten Move Controller übergeben. So lassen sich auch zusammenhängende Bewegungen über mehrere Move Controller realisieren.
Der Move Controller unterstützt folgende techage Kommandos:

View File

@ -570,7 +570,6 @@ Instructions:
- The movement can be tested with the menu buttons "Move A-B" and "Move B-A"
- you can also fly through walls or other blocks
- The target position for the blocks can also be occupied. In this case, the blocks are saved "invisibly". This is intended for sliding doors and the like
- A "handover" can also be programmed in the controller via the open-ended wrench menu. By entering a block number, the blocks are then transferred to the next move controller. In this way, connected movements can also be implemented using several Move Controllers.
The Move Controller supports the following techage commands:

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.
Die Nutzung der TA5 Hyperloop Kiste benötigt 20 Erfahrungspunkte.
Die Nutzung der TA5 Hyperloop Kiste benötigt 15 Erfahrungspunkte.
[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.
Die Nutzung des TA5 Hyperloop Tanks benötigt 20 Erfahrungspunkte.
Die Nutzung des TA5 Hyperloop Tanks benötigt 15 Erfahrungspunkte.
[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
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.
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 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.
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]
@ -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 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
@ -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
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]

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.
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]
@ -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.
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]
@ -120,21 +120,21 @@ The map on the right shows how the blocks can be used.
### 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.
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 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.
60 experience points are required to use the teleport blocks.
30 experience points are required to use the teleport blocks.
[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 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
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]

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 |
| "fuel" | number | fuel value of a fuel consuming block |
| "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 |
| "flowrate" | Total flow rate in liquid units | Only for TA4 Pumps |
| "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 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)
- [ ](./manual_ta1_DE.md#-)
- [Erze und Werkzeuge](./manual_ta1_DE.md#erze-und-werkzeuge)
- [Hammer](./manual_ta1_DE.md#hammer)
- [Kiessieb / Gravel Sieve](./manual_ta1_DE.md#kiessieb--gravel-sieve)

View File

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

View File

@ -265,6 +265,34 @@ techage.register_node({"techage:ta4_movecontroller"}, {
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({
output = "techage:ta4_movecontroller",
recipe = {
@ -273,3 +301,12 @@ minetest.register_craft({
{"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
=======
Copyright (C) 2019-2021 Joachim Stolberg
Copyright (C) 2019-2023 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -27,10 +27,11 @@ local control = networks.control
local HELP = S([[Commands
help . . . print this text
cls . . . . . clear screen
gen . . . . print all generators
sto . . . . . print all storage systems
con . . . . . print main consumers
cls . . . . clear screen
gen . . print generators
sto . . print storage systems
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)
@ -41,7 +42,6 @@ local function row(num, label, data)
"label[8.5,"..y..";" .. data .. "]"
end
local function formspec1(pos, data)
local mem = techage.get_mem(pos)
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").."]"
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 tbl = {}
local outdir = M(pos):get_int("outdir")
local resp = control.request(pos, Cable, outdir, "gen", "info")
for _, item in ipairs(resp) do
local name = item.type .. " (" .. item.number .. ")"
if item.running then
local s = string.format("%s (%s): %s/%u ku (%s)",
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 resp = control.request(pos, Cable, outdir, "sto", "info")
for _, item in ipairs(resp) do
local name = item.type .. " (" .. item.number .. ")"
if item.running then
local s = string.format("%s (%s): %s/%s kud",
item.type, item.number,
techage.round(item.load / techage.CYCLES_PER_DAY),
techage.round(item.capa / techage.CYCLES_PER_DAY))
tbl[#tbl + 1] = s
else
local s = string.format("%s (%s): %s/%s kud (off)",
item.type, item.number,
techage.round(item.load / techage.CYCLES_PER_DAY),
techage.round(item.capa / techage.CYCLES_PER_DAY))
tbl[#tbl + 1] = s
-- TA4/TA5 heatexchangers are no storage systems
if item.capa and item.capa > 1 then
if item.running then
local s = string.format("%s (%s): %s/%s kud",
item.type, item.number,
techage.round(item.load / techage.CYCLES_PER_DAY),
techage.round(item.capa / techage.CYCLES_PER_DAY))
tbl[#tbl + 1] = s
else
local s = string.format("%s (%s): %s/%s kud (off)",
item.type, item.number,
techage.round(item.load / techage.CYCLES_PER_DAY),
techage.round(item.capa / techage.CYCLES_PER_DAY))
tbl[#tbl + 1] = s
end
end
end
table.sort(tbl)
return table.concat(tbl, "\n")
end
local function consumers(pos)
local function consumers(pos, min, max)
local tbl = {}
local outdir = M(pos):get_int("outdir")
local netw = networks.get_network_table(pos, Cable, outdir) or {}
@ -147,7 +169,17 @@ local function consumers(pos)
if number then
local name = techage.get_node_lvm(item.pos).name
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
table.sort(tbl)
@ -157,7 +189,7 @@ end
local function output(pos, command, text)
local meta = M(pos)
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)
end
@ -177,8 +209,10 @@ local function command(pos, nvm, command)
output(pos, command, generators(pos))
elseif cmd == "sto" then
output(pos, command, storages(pos))
elseif cmd == "con" then
output(pos, command, consumers(pos))
elseif cmd == "con1" then
output(pos, command, consumers(pos, 1, 10))
elseif cmd == "con2" then
output(pos, command, consumers(pos, 9, 1000))
elseif command ~= "" then
output(pos, command, "")
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"))
Cable:after_place_node(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,
after_dig_node = function(pos)
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Cable:after_dig_node(pos)
techage.remove_node(pos, oldnode, oldmetadata)
techage.del_mem(pos)
end,
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"})
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({
output = "techage:ta3_power_terminal",
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 power = networks.power
local control = networks.control
local function node_timer(pos, elapsed)
local nvm = techage.get_nvm(pos)
@ -46,7 +47,7 @@ local function node_timer(pos, elapsed)
power.start_storage_calc(pos, Cable, 5)
nvm.providing = true
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
end
else
@ -105,6 +106,27 @@ minetest.register_node("techage:ta4_solar_minicell", {
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"}, {
on_recv_message = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2021 Joachim Stolberg
Copyright (C) 2019-2023 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -21,6 +21,7 @@ local S2P = minetest.string_to_pos
local Cable = techage.ElectricCable
local Axle = techage.Axle
local power = networks.power
local control = networks.control
local CYCLE_TIME = 2
local PWR_PERF = 24
@ -45,9 +46,7 @@ local function node_timer_on(pos, elapsed)
nvm.buffer = nvm.buffer + taken - 1 -- some loss
if nvm.buffer >= PWR_PERF then
local tp1 = tonumber(meta:get_string("termpoint1"))
local tp2 = tonumber(meta:get_string("termpoint2"))
nvm.provided = power.provide_power(pos, Cable, outdir, PWR_PERF, tp1, tp2)
nvm.provided = power.provide_power(pos, Cable, outdir, PWR_PERF, 0.8, 1.0)
nvm.load = power.get_storage_load(pos, Cable, outdir, PWR_PERF)
nvm.buffer = nvm.buffer - nvm.provided
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"}, 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({
output = "techage:ta2_generator_off",
recipe = {

View File

@ -22,6 +22,7 @@ local fuel = techage.fuel
local Pipe = techage.LiquidPipe
local power = networks.power
local liquid = networks.liquid
local control = networks.control
local CYCLE_TIME = 2
local STANDBY_TICKS = 1
@ -327,6 +328,27 @@ local liquid_def = {
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)
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"}, {
on_recv_message = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B