built on 11/12/2020 18:07:29
This commit is contained in:
parent
98d9e1b7cf
commit
67ba0cde5b
@ -92,24 +92,24 @@ minetest.register_on_respawnplayer(function(player)
|
||||
end
|
||||
end)
|
||||
|
||||
local function control_player(player)
|
||||
local player_name = player:get_player_name()
|
||||
local function control_player(player_name)
|
||||
if Currently_left_the_game[player_name] then
|
||||
Currently_left_the_game[player_name] = nil
|
||||
return
|
||||
end
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
if player then
|
||||
local pos = player:get_pos()
|
||||
if pos then
|
||||
--pos.y = math.floor(pos.y)
|
||||
local node = minetest.get_node(pos)
|
||||
if string.sub(node.name,1,13) == "autobahn:node" then
|
||||
minetest.after(0.5, control_player, player)
|
||||
minetest.after(0.5, control_player, player_name)
|
||||
else
|
||||
pos.y = pos.y - 1
|
||||
node = minetest.get_node(pos)
|
||||
if string.sub(node.name,1,13) == "autobahn:node" then
|
||||
minetest.after(0.5, control_player, player)
|
||||
minetest.after(0.5, control_player, player_name)
|
||||
else
|
||||
reset_player_privs(player)
|
||||
end
|
||||
@ -125,11 +125,13 @@ local NodeTbl1 = {
|
||||
["autobahn:node3"] = true,
|
||||
["autobahn:node4"] = true,
|
||||
["autobahn:node5"] = true,
|
||||
["autobahn:node6"] = true,
|
||||
["autobahn:node12"] = true,
|
||||
["autobahn:node22"] = true,
|
||||
["autobahn:node32"] = true,
|
||||
["autobahn:node42"] = true,
|
||||
["autobahn:node52"] = true,
|
||||
["autobahn:node62"] = true,
|
||||
}
|
||||
local NodeTbl2 = {
|
||||
["autobahn:node11"] = true,
|
||||
@ -137,6 +139,7 @@ local NodeTbl2 = {
|
||||
["autobahn:node31"] = true,
|
||||
["autobahn:node41"] = true,
|
||||
["autobahn:node51"] = true,
|
||||
["autobahn:node61"] = true,
|
||||
}
|
||||
local NodeTbl3 = {
|
||||
["autobahn:node1"] = true,
|
||||
@ -144,6 +147,7 @@ local NodeTbl3 = {
|
||||
["autobahn:node3"] = true,
|
||||
["autobahn:node4"] = true,
|
||||
["autobahn:node5"] = true,
|
||||
["autobahn:node6"] = true,
|
||||
}
|
||||
|
||||
-- 1) _o_
|
||||
@ -227,7 +231,9 @@ local function register_node(name, tiles, drawtype, mesh, box, drop)
|
||||
sunlight_propagates = true,
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
is_ground_content = false,
|
||||
groups = {cracky=2, crumbly=2, not_in_creative_inventory=(mesh==nil) and 0 or 1},
|
||||
groups = {cracky=2, crumbly=2,
|
||||
fall_damage_add_percent = -80,
|
||||
not_in_creative_inventory=(mesh==nil) and 0 or 1},
|
||||
drop = "autobahn:"..drop,
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
@ -239,7 +245,8 @@ local function register_node(name, tiles, drawtype, mesh, box, drop)
|
||||
reset_player_privs(clicker)
|
||||
else
|
||||
set_player_privs(clicker)
|
||||
minetest.after(0.5, control_player, clicker)
|
||||
local player_name = clicker:get_player_name()
|
||||
minetest.after(0.5, control_player, player_name)
|
||||
end
|
||||
end,
|
||||
})
|
||||
@ -277,12 +284,14 @@ local Nodes = {
|
||||
{name="node31", tiles={"autobahn3.png","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp1.obj", box=sb1, drop="node3"},
|
||||
{name="node41", tiles={"autobahn2.png^[transformR180]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp1.obj", box=sb1, drop="node4"},
|
||||
{name="node51", tiles={"autobahn4.png^[transformR90]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp1.obj", box=sb1, drop="node5"},
|
||||
{name="node61", tiles={"autobahn5.png^[transformR90]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp1.obj", box=sb1, drop="node6"},
|
||||
|
||||
{name="node12", tiles={"autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node1"},
|
||||
{name="node22", tiles={"autobahn2.png","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node2"},
|
||||
{name="node32", tiles={"autobahn3.png","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node3"},
|
||||
{name="node42", tiles={"autobahn2.png^[transformR180]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node4"},
|
||||
{name="node52", tiles={"autobahn4.png^[transformR90]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node5"},
|
||||
{name="node62", tiles={"autobahn5.png^[transformR90]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node6"},
|
||||
}
|
||||
|
||||
for _,item in ipairs(Nodes) do
|
||||
@ -405,10 +414,14 @@ if minetest.global_exists("minecart") then
|
||||
minecart.register_protected_node("autobahn:node21")
|
||||
minecart.register_protected_node("autobahn:node31")
|
||||
minecart.register_protected_node("autobahn:node41")
|
||||
minecart.register_protected_node("autobahn:node51")
|
||||
minecart.register_protected_node("autobahn:node61")
|
||||
minecart.register_protected_node("autobahn:node12")
|
||||
minecart.register_protected_node("autobahn:node22")
|
||||
minecart.register_protected_node("autobahn:node32")
|
||||
minecart.register_protected_node("autobahn:node42")
|
||||
minecart.register_protected_node("autobahn:node52")
|
||||
minecart.register_protected_node("autobahn:node62")
|
||||
end
|
||||
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
# textdomain: basic_materials
|
||||
Silicon lump=Silikonklumpen
|
||||
Simple Integrated Circuit=einfacher Integrierter Schaltkreis
|
||||
Simple Motor=einfacher Motor
|
||||
Silicon lump=Siliziumklumpen
|
||||
Simple Integrated Circuit=Einfacher Integrierter Schaltkreis
|
||||
Simple Motor=Einfacher Motor
|
||||
Heating element=Heizelement
|
||||
Simple energy crystal=einfacher Energiekristall
|
||||
Simple energy crystal=Einfacher Energiekristall
|
||||
|
||||
Spool of steel wire=Spule mit Stahldraht
|
||||
Spool of copper wire=Spule mit Kupferdraht
|
||||
@ -12,22 +12,22 @@ Spool of gold wire=Spule mit Golddraht
|
||||
Steel Strip=Stahlstreifen
|
||||
Copper Strip=Kupferstreifen
|
||||
Steel Bar=Stahlstab
|
||||
Chainlinks (brass)=Messing-Kettenglieder
|
||||
Chainlinks (steel)=Stahl-Kettenglieder
|
||||
Chainlinks (brass)=Messingkettenglieder
|
||||
Chainlinks (steel)=Stahlkettenglieder
|
||||
Brass Ingot=Messingbarren
|
||||
Steel gear=Stahlzahnrad
|
||||
Padlock=Vorhängeschloss
|
||||
Chain (steel, hanging)=Stahlkette
|
||||
Chain (brass, hanging)=Messingkette
|
||||
Chain (steel, hanging)=Hängende Stahlkette
|
||||
Chain (brass, hanging)=Hängende Messingkette
|
||||
Brass Block=Messingblock
|
||||
|
||||
Oil extract=raffiniertes Öl
|
||||
Unprocessed paraffin=unbearbeitetes Paraffin
|
||||
Uncooked Terracotta Base=ungebranntes Terrakotta
|
||||
Wet Cement=nasser Zement
|
||||
Oil extract=Ölextrakt
|
||||
Unprocessed paraffin=Unverarbeitetes Paraffin
|
||||
Uncooked Terracotta Base=Ungebranntes Terrakotta
|
||||
Wet Cement=Nasser Zement
|
||||
Cement=Zement
|
||||
Concrete Block=Betonblock
|
||||
|
||||
Plastic sheet=Kunststoffplatte
|
||||
Plastic strips=Kunststoffstreifen
|
||||
Empty wire spool=leere Drahtspule
|
||||
Empty wire spool=Leere Drahtspule
|
||||
|
@ -117,4 +117,4 @@ History
|
||||
2020-06-27 v1.07 Route storage and cart command bugfixes
|
||||
2020-07-24 V1.08 Adapted to new techage ICTA style
|
||||
2020-08-14 V1.09 Hopper support for digtron, protector:chest and default:furnace added
|
||||
|
||||
2020-11-12 V1.10 Make carts more robust against server lag
|
||||
|
@ -53,8 +53,18 @@ local function on_punch(pos, node, puncher)
|
||||
if not minecart.teleport_enabled then return end
|
||||
local route = minecart.get_route(P2S(pos))
|
||||
if route and route.dest_pos and puncher and puncher:is_player() then
|
||||
|
||||
-- only teleport if the user is not pressing shift
|
||||
if not puncher:get_player_control()['sneak'] then
|
||||
puncher:set_pos(S2P(route.dest_pos))
|
||||
local playername = puncher:get_player_name()
|
||||
local pos = S2P(route.dest_pos)
|
||||
|
||||
local teleport = function()
|
||||
-- Make sure the player object still exists
|
||||
local player = minetest.get_player_by_name(playername)
|
||||
if player and pos then player:set_pos(pos) end
|
||||
end
|
||||
minetest.after(0.25, teleport)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -17,6 +17,12 @@
|
||||
-- 2) Only the owner can start the recording
|
||||
-- 3) But any player can act as cargo, cart punched by owner or buffer
|
||||
|
||||
local SLOPE_ACCELERATION = 3
|
||||
local MAX_SPEED = 7
|
||||
local PUNCH_SPEED = 3
|
||||
local SLOWDOWN = 0.4
|
||||
local RAILTYPE = minetest.get_item_group("carts:rail", "connect_to_raillike")
|
||||
local Y_OFFS_ON_SLOPES = 0.5
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
@ -24,6 +30,83 @@ 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
|
||||
local MP = minetest.get_modpath("minecart")
|
||||
local D = function(pos) return minetest.pos_to_string(vector.round(pos)) end
|
||||
|
||||
local tRails = {
|
||||
["carts:rail"] = true,
|
||||
["carts:powerrail"] = true,
|
||||
["carts:brakerail"] = true,
|
||||
}
|
||||
|
||||
local lRails = {"carts:rail", "carts:powerrail", "carts:brakerail"}
|
||||
|
||||
local function get_rail_node(pos)
|
||||
local rail_pos = vector.round(pos)
|
||||
local node = minecart.get_node_lvm(rail_pos)
|
||||
if tRails[node.name] then
|
||||
return rail_pos, node
|
||||
end
|
||||
end
|
||||
|
||||
local function find_rail_node(pos)
|
||||
local rail_pos = vector.round(pos)
|
||||
local node = get_rail_node(rail_pos)
|
||||
if node then
|
||||
return rail_pos, node
|
||||
end
|
||||
local pos1 = {x=rail_pos.x-1, y=rail_pos.y-1, z=rail_pos.z-1}
|
||||
local pos2 = {x=rail_pos.x+1, y=rail_pos.y+1, z=rail_pos.z+1}
|
||||
for _,pos3 in ipairs(minetest.find_nodes_in_area(pos1, pos2, lRails)) do
|
||||
--print("invalid position1", D(pos), D(pos3))
|
||||
return pos3, minecart.get_node_lvm(pos3)
|
||||
end
|
||||
--print("invalid position2", D(pos))
|
||||
end
|
||||
|
||||
local function get_pitch(dir)
|
||||
local pitch = 0
|
||||
if dir.y == -1 then
|
||||
pitch = -math.pi/4
|
||||
elseif dir.y == 1 then
|
||||
pitch = math.pi/4
|
||||
end
|
||||
return pitch * (dir.z == 0 and -1 or 1)
|
||||
end
|
||||
|
||||
local function get_yaw(dir)
|
||||
local yaw = 0
|
||||
if dir.x < 0 then
|
||||
yaw = math.pi/2*3
|
||||
elseif dir.x > 0 then
|
||||
yaw = math.pi/2
|
||||
elseif dir.z < 0 then
|
||||
yaw = math.pi
|
||||
end
|
||||
return yaw
|
||||
end
|
||||
|
||||
local function push_cart(self, pos, punch_dir, puncher)
|
||||
local vel = self.object:get_velocity()
|
||||
punch_dir = punch_dir or carts:velocity_to_dir(puncher:get_look_dir())
|
||||
punch_dir.y = 0
|
||||
local cart_dir = carts:get_rail_direction(pos, punch_dir, nil, nil, RAILTYPE)
|
||||
|
||||
-- Always start in horizontal direction
|
||||
cart_dir.y = 0
|
||||
|
||||
if vector.equals(cart_dir, {x=0, y=0, z=0}) then return end
|
||||
|
||||
local speed = vector.multiply(cart_dir, PUNCH_SPEED)
|
||||
local new_vel = vector.add(vel, speed)
|
||||
local yaw = get_yaw(cart_dir)
|
||||
local pitch = get_pitch(cart_dir)
|
||||
|
||||
self.object:set_rotation({x = pitch, y = yaw, z = 0})
|
||||
self.object:set_velocity(new_vel)
|
||||
|
||||
self.old_pos = vector.round(pos)
|
||||
self.stopped = false
|
||||
end
|
||||
|
||||
local api = {}
|
||||
|
||||
@ -94,31 +177,20 @@ function api:on_punch(puncher, time_from_last_punch, tool_capabilities, directio
|
||||
return
|
||||
end
|
||||
|
||||
-- running carts can't be punched or removed from external
|
||||
if not stopped then
|
||||
return
|
||||
end
|
||||
|
||||
-- Punched by non-authorized player
|
||||
if puncher_name and not puncher_is_owner then
|
||||
minetest.chat_send_player(puncher_name, S("[minecart] Cart is protected by ")..(self.owner or ""))
|
||||
return
|
||||
end
|
||||
|
||||
if not self.railtype then
|
||||
local node = minetest.get_node(pos).name
|
||||
self.railtype = minetest.get_item_group(node, "connect_to_raillike")
|
||||
end
|
||||
|
||||
-- Punched by non-player
|
||||
if not puncher_name then
|
||||
local cart_dir = carts:get_rail_direction(pos, direction, nil, nil, self.railtype)
|
||||
local cart_dir = carts:get_rail_direction(pos, direction, nil, nil, RAILTYPE)
|
||||
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
|
||||
return
|
||||
end
|
||||
self.velocity = vector.multiply(cart_dir, 2)
|
||||
self.punched = true
|
||||
api.load_cargo(self, pos)
|
||||
push_cart(self, pos, cart_dir)
|
||||
minecart.start_cart(pos, self.myID)
|
||||
return
|
||||
end
|
||||
@ -131,7 +203,7 @@ function api:on_punch(puncher, time_from_last_punch, tool_capabilities, directio
|
||||
end
|
||||
-- detach driver
|
||||
if self.driver then
|
||||
carts:manage_attachment(puncher_name, nil)
|
||||
carts:manage_attachment(puncher, nil)
|
||||
end
|
||||
-- Pick up cart
|
||||
api.remove_cart(self, pos, puncher)
|
||||
@ -147,23 +219,7 @@ function api:on_punch(puncher, time_from_last_punch, tool_capabilities, directio
|
||||
|
||||
api.load_cargo(self, pos)
|
||||
|
||||
-- Normal punch by owner to start the cart
|
||||
local punch_dir = carts:velocity_to_dir(puncher:get_look_dir())
|
||||
punch_dir.y = 0
|
||||
local cart_dir = carts:get_rail_direction(pos, punch_dir, nil, nil, self.railtype)
|
||||
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
|
||||
return
|
||||
end
|
||||
|
||||
self.velocity = vector.multiply(cart_dir, 2)
|
||||
self.old_dir = cart_dir
|
||||
self.punched = true
|
||||
end
|
||||
|
||||
local function rail_on_step_event(handler, obj, dtime)
|
||||
if handler then
|
||||
handler(obj, dtime)
|
||||
end
|
||||
push_cart(self, pos, nil, puncher)
|
||||
end
|
||||
|
||||
-- sound refresh interval = 1.0sec
|
||||
@ -193,65 +249,92 @@ local function rail_sound(self, dtime)
|
||||
end
|
||||
end
|
||||
|
||||
local function get_railparams(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
return carts.railparams[node.name] or {}
|
||||
end
|
||||
|
||||
local v3_len = vector.length
|
||||
local function rail_on_step(self, dtime)
|
||||
local vel = self.object:get_velocity()
|
||||
local function rail_on_step(self)
|
||||
-- Check if same position as before
|
||||
local pos = self.object:get_pos()
|
||||
local rot = self.object:get_rotation()
|
||||
local stopped = minecart.stopped(vel) and rot.x == 0
|
||||
local on_slope = rot.x ~= 0
|
||||
--print("rail_on_step_new", P2S(pos), rot.x)
|
||||
|
||||
-- cart position correction on slopes
|
||||
if on_slope then
|
||||
pos.y = pos.y - Y_OFFS_ON_SLOPES
|
||||
end
|
||||
|
||||
-- Used as fallback position
|
||||
self.old_pos = self.old_pos or pos
|
||||
local pos_rounded = vector.round(pos)
|
||||
-- Same pos as before
|
||||
if vector.equals(pos_rounded, self.old_pos) then
|
||||
return -- nothing todo
|
||||
end
|
||||
|
||||
-- Check if stopped
|
||||
local vel = self.object:get_velocity()
|
||||
local stopped = not on_slope and minecart.stopped(vel)
|
||||
local is_minecart = self.node_name == nil
|
||||
local recording = is_minecart and self.driver == self.owner
|
||||
|
||||
-- cart position correction on slopes
|
||||
if rot.x ~= 0 then
|
||||
pos.y = pos.y - 0.5
|
||||
end
|
||||
|
||||
if self.punched then
|
||||
vel = vector.add(vel, self.velocity)
|
||||
self.object:set_velocity(vel)
|
||||
self.old_dir.y = 0
|
||||
self.stopped = false
|
||||
elseif stopped and not self.stopped then
|
||||
if stopped then
|
||||
if not self.stopped then
|
||||
local param2 = minetest.dir_to_facedir(self.old_dir)
|
||||
api.stop_cart(pos, self, self.node_name or "minecart:cart", param2)
|
||||
if recording then
|
||||
minecart.stop_recording(self, pos, vel, self.driver)
|
||||
minecart.stop_recording(self, pos_rounded, vel, self.driver)
|
||||
end
|
||||
api.unload_cargo(self, pos)
|
||||
self.stopped = true
|
||||
self.object:set_velocity({x=0, y=0, z=0})
|
||||
self.object:set_acceleration({x=0, y=0, z=0})
|
||||
return
|
||||
elseif stopped then
|
||||
return
|
||||
end
|
||||
self.old_pos = pos_rounded
|
||||
return -- nothing todo
|
||||
end
|
||||
|
||||
if recording then
|
||||
minecart.store_next_waypoint(self, pos, vel)
|
||||
-- Check if invalid position (not on rail anymore)
|
||||
local rail_pos, node = get_rail_node(pos)
|
||||
if not node then
|
||||
rail_pos, node = find_rail_node(self.old_pos)
|
||||
if rail_pos then
|
||||
pos_rounded = rail_pos
|
||||
if on_slope then
|
||||
self.object:set_pos({x=rail_pos.x, y=rail_pos.y + Y_OFFS_ON_SLOPES, z=rail_pos.z})
|
||||
else
|
||||
self.object:set_pos(rail_pos)
|
||||
end
|
||||
|
||||
local cart_dir = carts:velocity_to_dir(vel)
|
||||
local same_dir = vector.equals(cart_dir, self.old_dir)
|
||||
local update = {}
|
||||
|
||||
if self.old_pos and not self.punched and same_dir then
|
||||
local flo_pos = vector.round(pos)
|
||||
local flo_old = vector.round(self.old_pos)
|
||||
if vector.equals(flo_pos, flo_old) then
|
||||
-- Do not check one node multiple times
|
||||
return
|
||||
else
|
||||
self.object:set_pos(pos)
|
||||
minetest.log("error", "[minecart] No valid position "..(P2S(pos) or "nil"))
|
||||
return -- no valid position
|
||||
end
|
||||
end
|
||||
|
||||
local ctrl, player
|
||||
-- Calc speed (value)
|
||||
local speed = math.sqrt((vel.x+vel.z)^2 + vel.y^2)
|
||||
-- Check if slope position
|
||||
if pos_rounded.y > self.old_pos.y then
|
||||
speed = speed - SLOPE_ACCELERATION
|
||||
elseif pos_rounded.y < self.old_pos.y then
|
||||
speed = speed + SLOPE_ACCELERATION
|
||||
else
|
||||
speed = speed - SLOWDOWN
|
||||
end
|
||||
-- Add power/brake rail acceleration
|
||||
local acc = (carts.railparams[node.name] or {}).acceleration or 0
|
||||
speed = speed + acc
|
||||
|
||||
-- Determine new direction
|
||||
local dir = carts:velocity_to_dir(vel)
|
||||
if speed < 0 then
|
||||
if on_slope then
|
||||
dir = vector.multiply(dir, -1)
|
||||
-- start with a value > 0
|
||||
speed = 0.5
|
||||
else
|
||||
speed = 0
|
||||
end
|
||||
end
|
||||
|
||||
-- Get player controls
|
||||
local ctrl, player
|
||||
if recording then
|
||||
player = minetest.get_player_by_name(self.driver)
|
||||
if player then
|
||||
@ -259,158 +342,56 @@ local function rail_on_step(self, dtime)
|
||||
end
|
||||
end
|
||||
|
||||
local railparams
|
||||
|
||||
-- dir: New moving direction of the cart
|
||||
-- switch_keys: Currently pressed L/R key, used to ignore the key on the next rail node
|
||||
local dir, switch_keys = carts:get_rail_direction(
|
||||
pos, cart_dir, ctrl, self.old_switch, self.railtype
|
||||
)
|
||||
-- new_dir: New moving direction of the cart
|
||||
-- keys: Currently pressed L/R key, used to ignore the key on the next rail node
|
||||
local new_dir, keys = carts:get_rail_direction(rail_pos, dir, ctrl, self.old_keys, RAILTYPE)
|
||||
|
||||
-- handle junctions
|
||||
if switch_keys then -- recording
|
||||
minecart.set_junction(self, pos, dir, switch_keys)
|
||||
if recording and keys then
|
||||
minecart.set_junction(self, rail_pos, new_dir, keys)
|
||||
else -- normal run
|
||||
dir, switch_keys = minecart.get_junction(self, pos, dir)
|
||||
new_dir, keys = minecart.get_junction(self, rail_pos, new_dir)
|
||||
end
|
||||
self.old_keys = keys
|
||||
|
||||
local dir_changed = not vector.equals(dir, self.old_dir)
|
||||
|
||||
local new_acc = {x=0, y=0, z=0}
|
||||
if vector.equals(dir, {x=0, y=0, z=0}) then
|
||||
vel = {x = 0, y = 0, z = 0}
|
||||
local pos_r = vector.round(pos)
|
||||
if not carts:is_rail(pos_r, self.railtype)
|
||||
and self.old_pos then
|
||||
pos = self.old_pos
|
||||
else
|
||||
pos = pos_r
|
||||
end
|
||||
update.pos = true
|
||||
update.vel = true
|
||||
else
|
||||
-- Direction change detected
|
||||
if dir_changed then
|
||||
vel = vector.multiply(dir, math.abs(vel.x + vel.z))
|
||||
update.vel = true
|
||||
if dir.y ~= self.old_dir.y then
|
||||
pos = vector.round(pos)
|
||||
update.pos = true
|
||||
end
|
||||
end
|
||||
-- Center on the rail
|
||||
if dir.z ~= 0 and math.floor(pos.x + 0.5) ~= pos.x then
|
||||
pos.x = math.floor(pos.x + 0.5)
|
||||
update.pos = true
|
||||
end
|
||||
if dir.x ~= 0 and math.floor(pos.z + 0.5) ~= pos.z then
|
||||
pos.z = math.floor(pos.z + 0.5)
|
||||
update.pos = true
|
||||
end
|
||||
|
||||
-- Slow down or speed up..
|
||||
local acc = dir.y * -1.5
|
||||
|
||||
-- Get rail for corrected position
|
||||
railparams = get_railparams(pos)
|
||||
|
||||
-- no need to check for railparams == nil since we always make it exist.
|
||||
local speed_mod = railparams.acceleration
|
||||
if speed_mod and speed_mod ~= 0 then
|
||||
-- Try to make it similar to the original carts mod
|
||||
acc = acc + speed_mod
|
||||
else
|
||||
acc = acc - 0.4
|
||||
end
|
||||
|
||||
new_acc = vector.multiply(dir, acc)
|
||||
end
|
||||
|
||||
-- Limits
|
||||
local max_vel = carts.speed_max
|
||||
for _, v in pairs({"x","y","z"}) do
|
||||
if math.abs(vel[v]) > max_vel then
|
||||
vel[v] = carts:get_sign(vel[v]) * max_vel
|
||||
new_acc[v] = 0
|
||||
update.vel = true
|
||||
end
|
||||
end
|
||||
|
||||
self.object:set_acceleration(new_acc)
|
||||
self.old_pos = vector.round(pos)
|
||||
if not vector.equals(dir, {x=0, y=0, z=0}) then
|
||||
self.old_dir = vector.new(dir)
|
||||
end
|
||||
self.old_switch = switch_keys
|
||||
|
||||
if self.punched then
|
||||
self.punched = false
|
||||
update.vel = true
|
||||
end
|
||||
|
||||
railparams = railparams or get_railparams(pos)
|
||||
|
||||
if not (update.vel or update.pos) then
|
||||
rail_on_step_event(railparams.on_step, self, dtime)
|
||||
-- Detect U-turn
|
||||
if (dir.x ~= 0 and dir.x == -new_dir.x) or (dir.z ~= 0 and dir.z == -new_dir.z) then
|
||||
-- Stop the cart
|
||||
self.object:set_velocity({x=0, y=0, z=0})
|
||||
self.object:move_to(pos_rounded)
|
||||
return
|
||||
end
|
||||
|
||||
local yaw = 0
|
||||
if self.old_dir.x < 0 then
|
||||
yaw = math.pi/2*3
|
||||
elseif self.old_dir.x > 0 then
|
||||
yaw = math.pi/2
|
||||
elseif self.old_dir.z < 0 then
|
||||
yaw = math.pi
|
||||
end
|
||||
--self.object:set_yaw(yaw * math.pi)
|
||||
|
||||
local pitch = 0
|
||||
if self.old_dir.z ~= 0 then
|
||||
if dir.y == -1 then
|
||||
pitch = -math.pi/4
|
||||
elseif dir.y == 1 then
|
||||
pitch = math.pi/4
|
||||
end
|
||||
-- New direction
|
||||
elseif not vector.equals(dir, new_dir) then
|
||||
if new_dir.y ~= 0 then
|
||||
self.object:set_pos({x=pos_rounded.x, y=pos_rounded.y + Y_OFFS_ON_SLOPES, z=pos_rounded.z})
|
||||
else
|
||||
if dir.y == -1 then
|
||||
pitch = math.pi/4
|
||||
elseif dir.y == 1 then
|
||||
pitch = -math.pi/4
|
||||
self.object:set_pos(pos_rounded)
|
||||
end
|
||||
end
|
||||
|
||||
-- Set velocity and rotation
|
||||
local new_vel = vector.multiply(new_dir, math.min(speed, MAX_SPEED))
|
||||
local yaw = get_yaw(new_dir)
|
||||
local pitch = get_pitch(new_dir)
|
||||
|
||||
self.object:set_rotation({x = pitch, y = yaw, z = 0})
|
||||
self.object:set_velocity(new_vel)
|
||||
|
||||
-- cart position correction on slopes
|
||||
if pitch ~= 0 then
|
||||
pos.y = pos.y + 0.5
|
||||
update.pos = true
|
||||
vel = vector.divide(vel, 2)
|
||||
update.vel = true
|
||||
elseif self.old_pitch ~= 0 then
|
||||
vel = vector.multiply(vel, 2)
|
||||
update.vel = true
|
||||
end
|
||||
self.old_pitch = pitch
|
||||
|
||||
if update.vel then
|
||||
self.object:set_velocity(vel)
|
||||
end
|
||||
if update.pos then
|
||||
if dir_changed then
|
||||
self.object:set_pos(pos)
|
||||
else
|
||||
self.object:move_to(pos)
|
||||
end
|
||||
if recording then
|
||||
minecart.store_next_waypoint(self, rail_pos, vel)
|
||||
end
|
||||
|
||||
-- call event handler
|
||||
rail_on_step_event(railparams.on_step, self, dtime)
|
||||
self.old_pos = pos_rounded
|
||||
end
|
||||
|
||||
function api:on_step(dtime)
|
||||
rail_on_step(self, dtime)
|
||||
rail_sound(self, dtime)
|
||||
self.delay = (self.delay or 0) + dtime
|
||||
if self.delay > 0.09 then
|
||||
rail_on_step(self)
|
||||
rail_sound(self, self.delay)
|
||||
self.delay = 0
|
||||
end
|
||||
end
|
||||
|
||||
return api
|
||||
|
@ -49,7 +49,7 @@ function api.get_station_name(pos)
|
||||
end
|
||||
end
|
||||
|
||||
function api.load_cart(pos, vel, item)
|
||||
function api.load_cart(pos, vel, pitch, yaw, item)
|
||||
-- Add cart to map
|
||||
local obj = minetest.add_entity(pos, item.entity_name or "minecart:cart", nil)
|
||||
-- Determine ID
|
||||
@ -67,6 +67,7 @@ function api.load_cart(pos, vel, item)
|
||||
item.cargo = nil
|
||||
-- Start cart
|
||||
obj:set_velocity(vel)
|
||||
obj:set_rotation({x = pitch or 0, y = yaw or 0, z = 0})
|
||||
return myID
|
||||
else
|
||||
print("Entity has no ID")
|
||||
|
@ -13,12 +13,10 @@
|
||||
minecart = {}
|
||||
|
||||
-- Version for compatibility checks, see readme.md/history
|
||||
minecart.version = 1.09
|
||||
minecart.version = 1.10
|
||||
|
||||
minecart.hopper_enabled = minetest.settings:get_bool("minecart_hopper_enabled") ~= false
|
||||
minecart.teleport_enabled = minetest.settings:get_bool("minecart_teleport_enabled") ~= false
|
||||
|
||||
print("minecart_hopper_enabled", dump(minetest.settings:get_bool("minecart_hopper_enabled")))
|
||||
minecart.teleport_enabled = minetest.settings:get_bool("minecart_teleport_enabled") == true
|
||||
|
||||
minecart.S = minetest.get_translator("minecart")
|
||||
local MP = minetest.get_modpath("minecart")
|
||||
|
@ -51,6 +51,24 @@ function minecart.register_cart_names(cart_name_stopped, cart_name_running)
|
||||
end
|
||||
end
|
||||
|
||||
function minecart.get_node_lvm(pos)
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
if node then
|
||||
return node
|
||||
end
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local MinEdge, MaxEdge = vm:read_from_map(pos, pos)
|
||||
local data = vm:get_data()
|
||||
local param2_data = vm:get_param2_data()
|
||||
local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge})
|
||||
local idx = area:indexp(pos)
|
||||
node = {
|
||||
name = minetest.get_name_from_content_id(data[idx]),
|
||||
param2 = param2_data[idx]
|
||||
}
|
||||
return node
|
||||
end
|
||||
|
||||
function minecart.stopped(vel, tolerance)
|
||||
tolerance = tolerance or 0.05
|
||||
return math.abs(vel.x) < tolerance and math.abs(vel.z) < tolerance
|
||||
@ -64,6 +82,13 @@ local function is_air_like(name)
|
||||
return false
|
||||
end
|
||||
|
||||
function minecart.range(val, min, max)
|
||||
val = tonumber(val)
|
||||
if val < min then return min end
|
||||
if val > max then return max end
|
||||
return val
|
||||
end
|
||||
|
||||
function minecart.get_next_node(pos, param2)
|
||||
local pos2 = param2 and vector.add(pos, param2_to_dir[param2]) or pos
|
||||
local node = minetest.get_node(pos2)
|
||||
|
@ -33,26 +33,26 @@ local NodesAtStation = {}
|
||||
--
|
||||
-- Helper functions
|
||||
--
|
||||
local function calc_pos_and_vel(item)
|
||||
local function get_pos_vel_pitch_yaw(item)
|
||||
if item.start_time and item.start_key then -- cart on recorded route
|
||||
local run_time = minetest.get_gametime() - item.start_time
|
||||
local waypoints = get_route(item.start_key).waypoints
|
||||
local waypoint = waypoints[run_time]
|
||||
if waypoint then
|
||||
return S2P(waypoint[1]), S2P(waypoint[2])
|
||||
return S2P(waypoint[1]), S2P(waypoint[2]), 0, 0
|
||||
end
|
||||
end
|
||||
if item.last_pos then
|
||||
item.last_pos = vector.round(item.last_pos)
|
||||
if carts:is_rail(item.last_pos, minetest.raillike_group("rail")) then
|
||||
return item.last_pos, item.last_vel
|
||||
return item.last_pos, item.last_vel, item.last_pitch or 0, item.last_yaw or 0
|
||||
end
|
||||
item.last_pos.y = item.last_pos.y - 1
|
||||
if carts:is_rail(item.last_pos, minetest.raillike_group("rail")) then
|
||||
return item.last_pos, item.last_vel
|
||||
return item.last_pos, item.last_vel, item.last_pitch or 0, item.last_yaw or 0
|
||||
end
|
||||
end
|
||||
return item.start_pos, {x=0, y=0, z=0}
|
||||
return item.start_pos, {x=0, y=0, z=0}, 0, 0
|
||||
end
|
||||
|
||||
--
|
||||
@ -132,24 +132,29 @@ local function monitoring()
|
||||
if entity then -- cart entity running
|
||||
local pos = entity.object:get_pos()
|
||||
local vel = entity.object:get_velocity()
|
||||
local rot = entity.object:get_rotation()
|
||||
if not minetest.get_node_or_nil(pos) then -- unloaded area
|
||||
lib.unload_cart(pos, vel, entity, item)
|
||||
item.stopped = minecart.stopped(vel)
|
||||
end
|
||||
-- store last pos from cart
|
||||
item.last_pos, item.last_vel = pos, vel
|
||||
item.last_pos, item.last_vel, item.last_pitch, item.last_yaw = pos, vel, rot.x, rot.y
|
||||
|
||||
else -- no cart running
|
||||
local pos, vel = calc_pos_and_vel(item)
|
||||
local pos, vel, pitch, yaw = get_pos_vel_pitch_yaw(item)
|
||||
if pos and vel then
|
||||
if minetest.get_node_or_nil(pos) then -- loaded area
|
||||
local myID = lib.load_cart(pos, vel, item)
|
||||
if pitch > 0 then
|
||||
pos.y = pos.y + 0.5
|
||||
end
|
||||
local myID = lib.load_cart(pos, vel, pitch, yaw, item)
|
||||
if myID then
|
||||
item.stopped = minecart.stopped(vel)
|
||||
to_be_added[myID] = table.copy(item)
|
||||
CartsOnRail[key] = nil -- invalid old ID
|
||||
end
|
||||
end
|
||||
item.last_pos, item.last_vel = pos, vel
|
||||
item.last_pos, item.last_vel, item.last_pitch, item.last_yaw = pos, vel, pitch, yaw
|
||||
else
|
||||
-- should never happen
|
||||
minetest.log("error", "[minecart] Cart of owner "..(item.owner or "nil").." got lost")
|
||||
|
@ -19,7 +19,7 @@ Instructions:
|
||||
|
||||
Important to know:
|
||||
- 12 units of hydrogen are sufficient for a flight of 6 minutes
|
||||
- Maximum 5 items stacks in your inventory are allowed including the controller.
|
||||
- Maximum of 99 items in your inventory are allowed including the controller.
|
||||
Otherwise you would be too heavy :-)
|
||||
- The Jetpack also wears out and can be used for approximately 10 flights
|
||||
- Always hold the controller tight during the flight, otherwise it will switch off :)
|
||||
|
@ -13,13 +13,16 @@
|
||||
-- Load support for I18n.
|
||||
local S = minetest.get_translator("ta4_jetpack")
|
||||
|
||||
local ta4_jetpack = {}
|
||||
|
||||
local Players = {}
|
||||
local Jetpacks = {}
|
||||
local ItemsBlocklist = {}
|
||||
|
||||
local MAX_HEIGHT = tonumber(minetest.settings:get("ta4_jetpack_max_height")) or 500
|
||||
local MAX_VSPEED = tonumber(minetest.settings:get("ta4_jetpack_max_vertical_speed")) or 20
|
||||
local MAX_HSPEED = (tonumber(minetest.settings:get("ta4_jetpack_max_horizontal_speed")) or 12) / 4
|
||||
local MAX_NUM_INV_ITEMS = tonumber(minetest.settings:get("ta4_jetpack_max_num_inv_items")) or 5
|
||||
local MAX_NUM_INV_ITEMS = tonumber(minetest.settings:get("ta4_jetpack_max_num_inv_items")) or 99
|
||||
|
||||
-- Flight time maximum 6 min or 360 s or 3600 steps.
|
||||
-- 12 units hydrogen for 3600 steps means 0.0033 units hydrogen / step.
|
||||
@ -31,6 +34,11 @@ local STEPS_TO_FUEL = 0.0033
|
||||
|
||||
local WEAR_VALUE = 180 -- roughly 10 flys, 6 min each
|
||||
|
||||
-- API function to register items that are forbidden in inventory during flight.
|
||||
ta4_jetpack.register_forbidden_item = function(itemname)
|
||||
ItemsBlocklist[itemname] = true
|
||||
end
|
||||
|
||||
local function store_player_physics(player)
|
||||
local meta = player:get_meta()
|
||||
-- Check access conflicts with other mods
|
||||
@ -143,19 +151,22 @@ local function check_player_load(player)
|
||||
local bags_meta = meta:get_string("unified_inventory:bags")
|
||||
if bags_meta then
|
||||
if next(minetest.deserialize(bags_meta) or {}) then
|
||||
return S("check your bags!")
|
||||
return S("You are too heavy: Check your bags!")
|
||||
end
|
||||
end
|
||||
for _, stack in ipairs(inv:get_list("craft") or {}) do
|
||||
if not stack:is_empty() then
|
||||
return S("check your carfting menu!")
|
||||
return S("You are too heavy: Check your crafting menu!")
|
||||
end
|
||||
end
|
||||
local count = 0
|
||||
for _, stack in ipairs(inv:get_list("main") or {}) do
|
||||
count = count + (stack:is_empty() and 0 or 1)
|
||||
count = count + stack:get_count()
|
||||
if count > MAX_NUM_INV_ITEMS then
|
||||
return S("check your inventory!")
|
||||
return S("You are too heavy: Check your inventory!")
|
||||
end
|
||||
if ItemsBlocklist[stack:get_name()] then
|
||||
return S("You may not transport @1 with a jetpack!", stack:get_description())
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -349,7 +360,7 @@ local function turn_controller_on_off(itemstack, user)
|
||||
-- check inventory load
|
||||
local res = check_player_load(user)
|
||||
if res then
|
||||
minetest.chat_send_player(name, S("[Jetpack] You are too heavy: ")..res)
|
||||
minetest.chat_send_player(name, S("[Jetpack]").." "..res)
|
||||
return itemstack
|
||||
end
|
||||
-- check fuel
|
||||
@ -533,3 +544,6 @@ techage.add_manual_items({
|
||||
ta4_jetpack = "ta4_jetpack.png",
|
||||
ta4_jetpack_controller = 'ta4_jetpack_controller_inv.png'})
|
||||
|
||||
ta4_jetpack.register_forbidden_item("techage:cylinder_large_hydrogen")
|
||||
ta4_jetpack.register_forbidden_item("techage:cylinder_small_hydrogen")
|
||||
ta4_jetpack.register_forbidden_item("techage:hydrogen")
|
||||
|
@ -5,10 +5,11 @@ TA4 Jetpack=TA4 Jetpac
|
||||
TA4 Jetpack Controller Off=TA4 Jetpack Controller Aus
|
||||
TA4 Jetpack Controller On=TA4 Jetpack Controller An
|
||||
Use the controller (left click) to fill the tank with hydrogen=Benutze den Controller (linksklick) um den Tank mit Wasserstoff zu füllen
|
||||
[Jetpack] You are too heavy: =[Jetpack] Du bist zu schwer:
|
||||
You are too heavy: Check your bags!=Du bist zu schwer: Prüfe deine Rucksäcke!
|
||||
You are too heavy: Check your crafting menu!=Du bist zu schwer: Prüfe dein Crafting Menü!
|
||||
You are too heavy: Check your inventory!=Du bist zu schwer: Prüfe dein Inventar!
|
||||
You may not transport @1 with a jetpack!=Du darfst @1 nicht mit dem Jetpack transportieren!
|
||||
[Jetpack]=[Jetpack]
|
||||
[Jetpack] You don't have your jetpack on your back!=[Jetpack] Du hast dein Jetpack nicht auf dem Rücken!
|
||||
[Jetpack] Your tank is empty!=[Jetpack] Dein Tank ist leer!
|
||||
check your bags!=Prüfe deine Rucksäcke!
|
||||
check your carfting menu!=Prüfe dein Crafting Menü!
|
||||
check your inventory!=Prüfe dein Inventar!
|
||||
##### not used anymore #####
|
@ -3,9 +3,11 @@ TA4 Jetpack=
|
||||
TA4 Jetpack Controller Off=
|
||||
TA4 Jetpack Controller On=
|
||||
Use the controller (left click) to fill the tank with hydrogen=
|
||||
[Jetpack] You are too heavy: =
|
||||
You are too heavy: Check your bags!=
|
||||
You are too heavy: Check your crafting menu!=
|
||||
You are too heavy: Check your inventory!=
|
||||
You may not transport @1 with a jetpack!=
|
||||
[Jetpack]=
|
||||
[Jetpack] You don't have your jetpack on your back!=
|
||||
[Jetpack] Your tank is empty!=
|
||||
check your bags!=
|
||||
check your carfting menu!=
|
||||
check your inventory!=
|
||||
##### not used anymore #####
|
@ -17,7 +17,7 @@ techage.add_to_manual('DE', {
|
||||
"\n"..
|
||||
"\n",
|
||||
" - 12 Einheiten Wasserstoff reichen für einen Flug von 6 Minuten\n"..
|
||||
" - Maximal 5 Stapel von Gegenständen im Spieler-Inventar sind zulässig\\, einschließlich des Controllers\n(Sonst wärst du zu schwer :-)\n"..
|
||||
" - Maximal 99 Gegenstände im Spieler-Inventar sind zulässig\\, einschließlich des Controllers\n(Sonst wärst du zu schwer :-)\n"..
|
||||
" - Das Jetpack nutzt sich ab und kann für ca. 10 Flüge verwendet werden\n"..
|
||||
" - Halte den Controller während des Fluges immer fest\\, sonst schaltet er sich aus :)\n"..
|
||||
"\n"..
|
||||
|
@ -21,7 +21,7 @@ Das Jetpack ist inspiriert vom Jetpack von spirit689 (https://github.com/spirit6
|
||||
## Was du wissen solltest
|
||||
|
||||
- 12 Einheiten Wasserstoff reichen für einen Flug von 6 Minuten
|
||||
- Maximal 5 Stapel von Gegenständen im Spieler-Inventar sind zulässig, einschließlich des Controllers
|
||||
- Maximal 99 Gegenstände im Spieler-Inventar sind zulässig, einschließlich des Controllers
|
||||
(Sonst wärst du zu schwer :-)
|
||||
- Das Jetpack nutzt sich ab und kann für ca. 10 Flüge verwendet werden
|
||||
- Halte den Controller während des Fluges immer fest, sonst schaltet er sich aus :)
|
||||
|
@ -18,7 +18,7 @@ techage.add_to_manual('EN', {
|
||||
"\n"..
|
||||
"\n",
|
||||
" - 12 units of hydrogen are sufficient for a flight of 6 minutes\n"..
|
||||
" - Maximum 5 items stacks in your inventory are allowed including the controller.\nOtherwise you would be too heavy :-)\n"..
|
||||
" - Maximum 99 items in your inventory are allowed including the controller.\nOtherwise you would be too heavy :-)\n"..
|
||||
" - The Jetpack also wears out and can be used for approximately 10 flights\n"..
|
||||
" - Always hold the controller tight during the flight\\, otherwise it will switch off :)\n"..
|
||||
"\n"..
|
||||
|
@ -22,7 +22,7 @@ and by the historical game Lunar Lander.
|
||||
## Important to know
|
||||
|
||||
- 12 units of hydrogen are sufficient for a flight of 6 minutes
|
||||
- Maximum 5 items stacks in your inventory are allowed including the controller.
|
||||
- Maximum 99 items in your inventory are allowed including the controller.
|
||||
Otherwise you would be too heavy :-)
|
||||
- The Jetpack also wears out and can be used for approximately 10 flights
|
||||
- Always hold the controller tight during the flight, otherwise it will switch off :)
|
||||
|
@ -8,7 +8,7 @@ ta4_jetpack_max_vertical_speed (maximum vertical speed) int 20
|
||||
ta4_jetpack_max_horizontal_speed (maximum horizontal speed) int 12
|
||||
|
||||
# Maximum number of inventory items a player can take
|
||||
ta4_jetpack_max_num_inv_items (maximum number of inventory items) int 5
|
||||
ta4_jetpack_max_num_inv_items (maximum number of inventory items) int 99
|
||||
|
||||
|
||||
|
||||
|
@ -1,28 +0,0 @@
|
||||
The Techage mod for Minetest is
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
License of source code
|
||||
----------------------
|
||||
|
||||
This mod is free software; you can redistribute and/or
|
||||
modify it under the terms of the GNU General Public License version 3 or later
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This mod is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this mod; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
|
||||
License of media (textures, sounds and documentation)
|
||||
-----------------------------------------------------
|
||||
|
||||
All textures, sounds and documentation files are licensed under the
|
||||
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||
http://creativecommons.org/licenses/by-sa/3.0/
|
@ -77,6 +77,14 @@ Available worlds will be converted to 'lsqlite3', but there is no way back, so:
|
||||
|
||||
### History
|
||||
|
||||
**2020-11-01 V0.25**
|
||||
- Pull request #37: Trowel: Add protection support (from Thomas-S)
|
||||
- Pull request #38: Charcoal Pile: Ignore "ignore" nodes (from Thomas-S)
|
||||
- Autocrafter: Add register function for uncraftable items
|
||||
- Fix bug: Tubes do not recognize when TA2 nodes are added/removed
|
||||
- TA4 chest/tank: Add 'public' checkbox to allow public access
|
||||
- Add nodes TA2 Power Generator and TA3 Electric Motor
|
||||
|
||||
**2020-10-20 V0.24**
|
||||
- Pull request #27: Liquid Tanks: Add protection support (from Thomas-S)
|
||||
- Pull request #28: Quarry: Improve digging behaviour (from Thomas-S)
|
||||
|
@ -178,7 +178,7 @@ techage.register_node({"techage:chest_ta2", "techage:chest_ta3"}, {
|
||||
|
||||
local function formspec4(pos)
|
||||
return "size[10,9]"..
|
||||
"tabheader[0,0;tab;"..S("Inventory,Configuration")..";1;;true]"..
|
||||
"tabheader[0,0;tab;"..S("Inventory,Pre-Assignment,Config")..";1;;true]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
@ -189,9 +189,9 @@ local function formspec4(pos)
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
local function formspec4_cfg(pos)
|
||||
local function formspec4_pre(pos)
|
||||
return "size[10,9]"..
|
||||
"tabheader[0,0;tab;"..S("Inventory,Configuration")..";2;;true]"..
|
||||
"tabheader[0,0;tab;"..S("Inventory,Pre-Assignment,Config")..";2;;true]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
@ -201,8 +201,23 @@ local function formspec4_cfg(pos)
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
local function formspec4_cfg(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local label = meta:get_string("label") or ""
|
||||
local public = dump((meta:get_int("public") or 0) == 1)
|
||||
return "size[10,5]"..
|
||||
"tabheader[0,0;tab;"..S("Inventory,Pre-Assignment,Config")..";3;;true]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"field[0.5,1;9,1;label;"..S("Node label:")..";"..label.."]" ..
|
||||
"checkbox[1,2;public;"..S("Allow public access to the chest")..";"..public.."]"..
|
||||
"button_exit[3.5,4;3,1;exit;"..S("Save").."]"
|
||||
end
|
||||
|
||||
local function ta4_allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
local public = M(pos):get_int("public") == 1
|
||||
if not public and minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
@ -214,7 +229,8 @@ local function ta4_allow_metadata_inventory_put(pos, listname, index, stack, pla
|
||||
end
|
||||
|
||||
local function ta4_allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
local public = M(pos):get_int("public") == 1
|
||||
if not public and minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
@ -226,7 +242,8 @@ local function ta4_allow_metadata_inventory_take(pos, listname, index, stack, pl
|
||||
end
|
||||
|
||||
local function ta4_allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
local public = M(pos):get_int("public") == 1
|
||||
if not public and minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
@ -276,10 +293,25 @@ minetest.register_node("techage:chest_ta4", {
|
||||
mem.filter = nil
|
||||
meta:set_string("formspec", formspec4(pos))
|
||||
elseif fields.tab == "2" then
|
||||
meta:set_string("formspec", formspec4_pre(pos))
|
||||
elseif fields.tab == "3" then
|
||||
meta:set_string("formspec", formspec4_cfg(pos))
|
||||
elseif fields.quit == "true" then
|
||||
mem.filter = nil
|
||||
end
|
||||
if fields.public then
|
||||
meta:set_int("public", fields.public == "true" and 1 or 0)
|
||||
end
|
||||
if fields.exit then
|
||||
local number = meta:get_string("node_number")
|
||||
if fields.label ~= "" then
|
||||
meta:set_string("infotext", minetest.formspec_escape(fields.label).." #"..number)
|
||||
else
|
||||
meta:set_string("infotext", S("TA4 Protected Chest").." "..number)
|
||||
end
|
||||
meta:set_string("label", fields.label)
|
||||
meta:set_string("formspec", formspec4_cfg(pos))
|
||||
end
|
||||
end,
|
||||
|
||||
techage_set_numbers = function(pos, numbers, player_name)
|
||||
|
@ -180,10 +180,7 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState
|
||||
if (meta:contains("node_number")) then
|
||||
meta:set_string("node_number", "")
|
||||
end
|
||||
local number = "-"
|
||||
if stage > 2 then
|
||||
number = techage.add_node(pos, name_pas)
|
||||
end
|
||||
local number = techage.add_node(pos, name_pas, stage == 2)
|
||||
if crd.power_netw then
|
||||
crd.power_netw:after_place_node(pos)
|
||||
end
|
||||
|
@ -35,7 +35,7 @@ local function formspec(self, pos, nvm)
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
power.formspec_label_bar(0, 0.8, S("power"), PWR_CAPA, nvm.provided)..
|
||||
power.formspec_label_bar(pos, 0, 0.8, S("power"), PWR_CAPA, nvm.provided)..
|
||||
"image_button[2.8,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[2.8,2;1,1;"..self:get_state_tooltip(nvm).."]"
|
||||
end
|
||||
|
@ -20,11 +20,16 @@ local S = techage.S
|
||||
local DESCRIPTION = S("TA4 8x2000 Chest")
|
||||
local STACK_SIZE = 2000
|
||||
|
||||
local function gen_stack(inv, idx)
|
||||
inv[idx] = {name = "", count = 0}
|
||||
end
|
||||
|
||||
local function gen_inv(nvm)
|
||||
nvm.inventory = {}
|
||||
for i = 1,8 do
|
||||
nvm.inventory[i] = {name = "", count = 0}
|
||||
gen_stack(nvm.inventory, i)
|
||||
end
|
||||
return nvm.inventory
|
||||
end
|
||||
|
||||
local function repair_inv(nvm)
|
||||
@ -32,33 +37,26 @@ local function repair_inv(nvm)
|
||||
for i = 1,8 do
|
||||
local item = nvm.inventory[i]
|
||||
if not item or type(item) ~= "table"
|
||||
or not item.name or type(item.name) ~= "string"
|
||||
or not item.count or type(item.count) ~= "number" then
|
||||
nvm.inventory[i] = {name = "", count = 0}
|
||||
or not item.name or type(item.name) ~= "string" or item.name == ""
|
||||
or not item.count or type(item.count) ~= "number" or item.count < 1
|
||||
then
|
||||
gen_stack(nvm.inventory, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function get_stack(nvm, idx)
|
||||
nvm.inventory = nvm.inventory or {}
|
||||
if nvm.inventory[idx] then
|
||||
return nvm.inventory[idx]
|
||||
end
|
||||
nvm.inventory[idx] = {name = "", count = 0}
|
||||
return nvm.inventory[idx]
|
||||
return nvm.inventory[idx] or gen_stack(nvm.inventory, idx)
|
||||
end
|
||||
|
||||
local function get_count(nvm, idx)
|
||||
if idx and idx > 0 then
|
||||
nvm.inventory = nvm.inventory or {}
|
||||
if nvm.inventory[idx] then
|
||||
return nvm.inventory[idx].count or 0
|
||||
else
|
||||
return 0
|
||||
end
|
||||
if idx and idx > 0 then
|
||||
return nvm.inventory[idx] and nvm.inventory[idx].count or 0
|
||||
else
|
||||
local count = 0
|
||||
for _,item in ipairs(nvm.inventory or {}) do
|
||||
for _,item in ipairs(nvm.inventory) do
|
||||
count = count + item.count or 0
|
||||
end
|
||||
return count
|
||||
@ -68,9 +66,7 @@ end
|
||||
local function get_itemstring(nvm, idx)
|
||||
if idx and idx > 0 then
|
||||
nvm.inventory = nvm.inventory or {}
|
||||
if nvm.inventory[idx] then
|
||||
return nvm.inventory[idx].name or ""
|
||||
end
|
||||
return nvm.inventory[idx] and nvm.inventory[idx].name or ""
|
||||
end
|
||||
return ""
|
||||
end
|
||||
@ -97,11 +93,11 @@ local function inv_state(nvm)
|
||||
end
|
||||
|
||||
local function max_stacksize(item_name)
|
||||
local ndef = minetest.registered_nodes[item_name] or minetest.registered_items[item_name] or minetest.registered_craftitems[item_name]
|
||||
if ndef then
|
||||
return ndef.stack_max
|
||||
end
|
||||
return 0
|
||||
-- It is sufficient to use minetest.registered_items as all registration
|
||||
-- functions (node, craftitems, tools) add the definitions there.
|
||||
local ndef = minetest.registered_items[item_name]
|
||||
-- Return 1 as fallback so that slots with unknown items can be emptied.
|
||||
return ndef and ndef.stack_max or 1
|
||||
end
|
||||
|
||||
local function get_stacksize(pos)
|
||||
@ -112,102 +108,159 @@ local function get_stacksize(pos)
|
||||
return size
|
||||
end
|
||||
|
||||
-- Sort the items into the nvm inventory
|
||||
local function sort_in(pos, nvm, stack)
|
||||
local old_counts = {}
|
||||
local orig_count = stack:get_count()
|
||||
for idx,item in ipairs(nvm.inventory or {}) do
|
||||
if item.name and (item.name == "" or item.name == stack:get_name()) then
|
||||
local count = math.min(stack:get_count(), get_stacksize(pos) - item.count)
|
||||
old_counts[idx] = item.count -- store old value
|
||||
item.count = item.count + count
|
||||
item.name = stack:get_name()
|
||||
stack:set_count(stack:get_count() - count)
|
||||
if stack:get_count() == 0 then
|
||||
return true
|
||||
-- Returns a boolean that indicates if an itemstack and nvmstack can be combined.
|
||||
-- The second return value is a string describing the reason.
|
||||
-- This function guarantees not to modify any of both stacks.
|
||||
local function doesItemStackMatchNvmStack(itemstack, nvmstack)
|
||||
if itemstack:get_count() == 0 or nvmstack.count == 0 then
|
||||
return true, "Empty stack"
|
||||
end
|
||||
if nvmstack.name and nvmstack.name ~= "" and nvmstack.name ~= itemstack:get_name() then
|
||||
return false, "Mismatching names"
|
||||
end
|
||||
|
||||
-- The following seems to be the most reliable approach to compare meta.
|
||||
local nvm_meta = ItemStack():get_meta()
|
||||
nvm_meta:from_table(minetest.deserialize(nvmstack.meta))
|
||||
if not nvm_meta:equals(itemstack:get_meta()) then
|
||||
return false, "Mismatching meta"
|
||||
end
|
||||
-- restore old values
|
||||
for idx,cnt in pairs(old_counts) do
|
||||
nvm.inventory[idx].count = cnt
|
||||
if (nvmstack.wear or 0) ~= itemstack:get_wear() then
|
||||
return false, "Mismatching wear"
|
||||
end
|
||||
stack:set_count(orig_count)
|
||||
return false
|
||||
return true, "Stacks match"
|
||||
end
|
||||
|
||||
local function move_items_to_stack(item, stack, num)
|
||||
item.count = item.count - num
|
||||
stack.count = stack.count + num
|
||||
if stack.count > 0 then
|
||||
stack.name = item.name
|
||||
|
||||
-- Generic function for adding items to the 8x2000 Chest
|
||||
-- This function guarantees not to modify the itemstack.
|
||||
-- The number of items that were added to the chest is returned.
|
||||
local function add_to_chest(pos, input_stack, idx)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local nvm_stack = get_stack(nvm, idx)
|
||||
if input_stack:get_count() == 0 then
|
||||
return 0
|
||||
end
|
||||
if item.count == 0 then
|
||||
item.name = "" -- empty
|
||||
if not doesItemStackMatchNvmStack(input_stack, nvm_stack) then
|
||||
return 0
|
||||
end
|
||||
local count = math.min(input_stack:get_count(), get_stacksize(pos) - (nvm_stack.count or 0))
|
||||
if nvm_stack.count == 0 then
|
||||
nvm_stack.name = input_stack:get_name()
|
||||
nvm_stack.meta = minetest.serialize(input_stack:get_meta():to_table())
|
||||
nvm_stack.wear = input_stack:get_wear()
|
||||
end
|
||||
nvm_stack.count = nvm_stack.count + count
|
||||
return count
|
||||
end
|
||||
|
||||
local function stackOrNil(stack)
|
||||
if stack and stack.get_count and stack:get_count() > 0 then
|
||||
return stack
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function get_item(pos, nvm, item_name, count)
|
||||
local stack = {count = 0}
|
||||
-- Generic function for taking items from the 8x2000 Chest
|
||||
-- output_stack is directly modified; but nil can also be supplied.
|
||||
-- The resulting output_stack is returned from the function.
|
||||
-- keep_assignment indicates if the meta information for this function should be considered (manual vs. tubes).
|
||||
local function take_from_chest(pos, idx, output_stack, max_total_count, keep_assignment)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local nvm_stack = get_stack(nvm, idx)
|
||||
output_stack = output_stack or ItemStack()
|
||||
local assignment_count = keep_assignment and M(pos):get_int("assignment") == 1 and 1 or 0
|
||||
local count = math.min(nvm_stack.count - assignment_count, max_stacksize(nvm_stack.name))
|
||||
if max_total_count then
|
||||
count = math.min(count, max_total_count - output_stack:get_count())
|
||||
end
|
||||
if count < 1 then
|
||||
return stackOrNil(output_stack)
|
||||
end
|
||||
if not doesItemStackMatchNvmStack(output_stack, nvm_stack) then
|
||||
return stackOrNil(output_stack)
|
||||
end
|
||||
output_stack:add_item(ItemStack({
|
||||
name = nvm_stack.name,
|
||||
count = count,
|
||||
wear = nvm_stack.wear,
|
||||
}))
|
||||
output_stack:get_meta():from_table(minetest.deserialize(nvm_stack.meta))
|
||||
nvm_stack.count = nvm_stack.count - count
|
||||
if nvm_stack.count == 0 then
|
||||
gen_stack(nvm.inventory or {}, idx)
|
||||
end
|
||||
return stackOrNil(output_stack)
|
||||
end
|
||||
|
||||
-- Function for adding items to the 8x2000 Chest via automation, e.g. pushers
|
||||
local function tube_add_to_chest(pos, input_stack)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.inventory = nvm.inventory or {}
|
||||
|
||||
if item_name then
|
||||
-- Take specified items from the chest
|
||||
for _,item in ipairs(nvm.inventory) do
|
||||
if item.name == item_name then
|
||||
local num = math.min(item.count, count - stack.count, max_stacksize(item.name))
|
||||
if M(pos):get_int("assignment") == 1 and num == item.count then
|
||||
-- never take the last item
|
||||
num = num - 1
|
||||
end
|
||||
stack = move_items_to_stack(item, stack, num)
|
||||
if stack.count == count then
|
||||
return ItemStack(stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif M(pos):get_int("priority") == 1 then
|
||||
-- Take any items. The position within the inventory is from right to left
|
||||
for idx = 8,1,-1 do
|
||||
local item = nvm.inventory[idx]
|
||||
if item.name ~= "" and (stack.name == nil or stack.name == item.name) then
|
||||
local num = math.min(item.count, count - stack.count, max_stacksize(item.name))
|
||||
if M(pos):get_int("assignment") == 1 and num == item.count then
|
||||
-- never take the last item
|
||||
num = num - 1
|
||||
end
|
||||
stack = move_items_to_stack(item, stack, num)
|
||||
if stack.count == count then
|
||||
return ItemStack(stack)
|
||||
end
|
||||
end
|
||||
-- Backup some values needed for restoring the old
|
||||
-- state if items can't fully be added to chest.
|
||||
local orig_count = input_stack:get_count()
|
||||
local backup = table.copy(nvm.inventory)
|
||||
|
||||
for idx = 1,8 do
|
||||
input_stack:take_item(add_to_chest(pos, input_stack, idx))
|
||||
end
|
||||
|
||||
if input_stack:get_count() > 0 then
|
||||
nvm.inventory = backup -- Restore old nvm inventory
|
||||
input_stack:set_count(orig_count) -- Restore input_stack
|
||||
return false -- No items were added to chest
|
||||
else
|
||||
-- Take any items. The position within the inventory
|
||||
-- is incremented each time so that different item stacks will be considered.
|
||||
return true -- Items were added successfully
|
||||
end
|
||||
end
|
||||
|
||||
-- Function for taking items from the 8x2000 Chest via automation, e.g. pushers
|
||||
local function tube_take_from_chest(pos, item_name, count)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
nvm.inventory = nvm.inventory or {}
|
||||
mem.startpos = mem.startpos or 1
|
||||
for idx = mem.startpos, mem.startpos + 8 do
|
||||
idx = (idx % 8) + 1
|
||||
local item = nvm.inventory[idx]
|
||||
if item.name ~= "" and (stack.name == nil or stack.name == item.name) then
|
||||
local num = math.min(item.count, count - stack.count, max_stacksize(item.name))
|
||||
if M(pos):get_int("assignment") == 1 and num == item.count then
|
||||
-- never take the last item
|
||||
num = num - 1
|
||||
end
|
||||
stack = move_items_to_stack(item, stack, num)
|
||||
if stack.count == count then
|
||||
mem.startpos = idx
|
||||
return ItemStack(stack)
|
||||
local prio = M(pos):get_int("priority") == 1
|
||||
local startpos = prio and 8 or mem.startpos
|
||||
local endpos = prio and 1 or mem.startpos + 8
|
||||
local step = prio and -1 or 1
|
||||
local itemstack = ItemStack()
|
||||
for idx = startpos,endpos,step do
|
||||
idx = ((idx - 1) % 8) + 1
|
||||
local nvmstack = get_stack(nvm, idx)
|
||||
if not item_name or item_name == nvmstack.name then
|
||||
take_from_chest(pos, idx, itemstack, count - itemstack:get_count(), true)
|
||||
if itemstack:get_count() == count then
|
||||
mem.startpos = idx + 1
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
mem.startpos = idx
|
||||
mem.startpos = idx + 1
|
||||
end
|
||||
return stackOrNil(itemstack)
|
||||
end
|
||||
|
||||
-- Function for manually adding items to the 8x2000 Chest via the formspec
|
||||
local function inv_add_to_chest(pos, idx)
|
||||
local inv = M(pos):get_inventory()
|
||||
local inv_stack = inv:get_stack("main", idx)
|
||||
local count = add_to_chest(pos, inv_stack, idx)
|
||||
inv_stack:set_count(inv_stack:get_count() - count)
|
||||
inv:set_stack("main", idx, inv_stack)
|
||||
end
|
||||
|
||||
-- Function for manually taking items from the 8x2000 Chest via the formspec
|
||||
local function inv_take_from_chest(pos, idx)
|
||||
local inv = M(pos):get_inventory()
|
||||
local inv_stack = inv:get_stack("main", idx)
|
||||
if inv_stack:get_count() > 0 then
|
||||
return
|
||||
end
|
||||
if stack.count > 0 then
|
||||
return ItemStack(stack)
|
||||
local output_stack = take_from_chest(pos, idx)
|
||||
if output_stack then
|
||||
inv:set_stack("main", idx, output_stack)
|
||||
end
|
||||
end
|
||||
|
||||
@ -218,9 +271,15 @@ local function formspec_container(x, y, nvm, inv)
|
||||
tbl[#tbl+1] = "box["..(xpos - 0.03)..",0;0.86,0.9;#808080]"
|
||||
local stack = get_stack(nvm, i)
|
||||
if stack.name ~= "" then
|
||||
local itemname = stack.name.." "..stack.count
|
||||
local itemstack = ItemStack({
|
||||
name = stack.name,
|
||||
count = stack.count,
|
||||
wear = stack.wear,
|
||||
})
|
||||
itemstack:get_meta():from_table(minetest.deserialize(stack.meta))
|
||||
local itemname = itemstack:to_string()
|
||||
--tbl[#tbl+1] = "item_image["..xpos..",1;1,1;"..itemname.."]"
|
||||
tbl[#tbl+1] = techage.item_image(xpos, 0, itemname)
|
||||
tbl[#tbl+1] = techage.item_image(xpos, 0, itemname, stack.count)
|
||||
end
|
||||
if inv:get_stack("main", i):get_count() == 0 then
|
||||
tbl[#tbl+1] = "image_button["..xpos..",1;1,1;techage_form_get_arrow.png;get"..i..";]"
|
||||
@ -366,47 +425,6 @@ local function on_rightclick(pos, node, clicker)
|
||||
end
|
||||
end
|
||||
|
||||
-- take items from chest
|
||||
local function move_from_nvm_to_inv(pos, idx)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
local inv_stack = inv:get_stack("main", idx)
|
||||
local nvm_stack = get_stack(nvm, idx)
|
||||
|
||||
if nvm_stack.count > 0 and inv_stack:get_count() == 0 then
|
||||
local count = math.min(nvm_stack.count, max_stacksize(nvm_stack.name))
|
||||
nvm_stack.count = nvm_stack.count - count
|
||||
inv:set_stack("main", idx, {name = nvm_stack.name, count = count})
|
||||
if nvm_stack.count == 0 then
|
||||
nvm_stack.name = ""
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- add items to chest
|
||||
local function move_from_inv_to_nvm(pos, idx)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
local inv_stack = inv:get_stack("main", idx)
|
||||
local nvm_stack = get_stack(nvm, idx)
|
||||
|
||||
if inv_stack:get_count() > 0 then
|
||||
-- Don't handle items with meta or wear information because it would get lost.
|
||||
local meta_table = inv_stack:get_meta():to_table()
|
||||
if meta_table ~= nil and next(meta_table.fields) ~= nil or inv_stack:get_wear() ~= 0 then
|
||||
return
|
||||
end
|
||||
|
||||
if nvm_stack.count == 0 or nvm_stack.name == inv_stack:get_name() then
|
||||
local count = math.min(inv_stack:get_count(), get_stacksize(pos) - nvm_stack.count)
|
||||
nvm_stack.count = nvm_stack.count + count
|
||||
nvm_stack.name = inv_stack:get_name()
|
||||
inv_stack:set_count(inv_stack:get_count() - count)
|
||||
inv:set_stack("main", idx, inv_stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
@ -414,10 +432,10 @@ local function on_receive_fields(pos, formname, fields, player)
|
||||
|
||||
for i = 1,8 do
|
||||
if fields["get"..i] ~= nil then
|
||||
move_from_nvm_to_inv(pos, i)
|
||||
inv_take_from_chest(pos, i)
|
||||
break
|
||||
elseif fields["add"..i] ~= nil then
|
||||
move_from_inv_to_nvm(pos, i)
|
||||
inv_add_to_chest(pos, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
@ -534,24 +552,21 @@ minetest.register_node("techage:ta4_chest_dummy", {
|
||||
|
||||
techage.register_node({"techage:ta4_chest"}, {
|
||||
on_pull_item = function(pos, in_dir, num, item_name)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local res = get_item(pos, nvm, item_name, num)
|
||||
local res = tube_take_from_chest(pos, item_name, num)
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
end
|
||||
return res
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local res = sort_in(pos, nvm, stack)
|
||||
local res = tube_add_to_chest(pos, stack)
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
end
|
||||
return res
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local res = sort_in(pos, nvm, stack)
|
||||
local res = tube_add_to_chest(pos, stack)
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
end
|
||||
|
@ -207,29 +207,40 @@ end
|
||||
-- Add node to the techage lists.
|
||||
-- Function determines and returns the node position number,
|
||||
-- needed for message communication.
|
||||
function techage.add_node(pos, name)
|
||||
-- If TA2 node, return '-' instead of a real number, because
|
||||
-- TA2 nodes should not support number based commands.
|
||||
function techage.add_node(pos, name, is_ta2)
|
||||
if item_handling_node(name) then
|
||||
Tube:after_place_node(pos)
|
||||
end
|
||||
if is_ta2 then
|
||||
return "-"
|
||||
end
|
||||
local key = minetest.hash_node_position(pos)
|
||||
return NumbersToBeRecycled[key] or get_number(pos, true)
|
||||
local num = NumbersToBeRecycled[key]
|
||||
if num then
|
||||
backend.set_nodepos(num, pos)
|
||||
NumbersToBeRecycled[key] = nil
|
||||
return num
|
||||
end
|
||||
return get_number(pos, true)
|
||||
end
|
||||
|
||||
-- Function removes the node from the techage lists.
|
||||
function techage.remove_node(pos, oldnode, oldmetadata)
|
||||
local number = oldmetadata and oldmetadata.fields and oldmetadata.fields.node_number
|
||||
local number = oldmetadata and oldmetadata.fields and oldmetadata.fields.node_number or oldmetadata.fields.number
|
||||
print("number1", dump(oldmetadata))
|
||||
number = number or get_number(pos)
|
||||
print("number2", number)
|
||||
if number and tonumber(number) then
|
||||
local key = minetest.hash_node_position(pos)
|
||||
NumbersToBeRecycled[key] = number
|
||||
local ninfo = NodeInfoCache[number] or update_nodeinfo(number)
|
||||
if ninfo then
|
||||
NodeInfoCache[number] = nil
|
||||
if item_handling_node(ninfo.name) then
|
||||
print("number3", number)
|
||||
end
|
||||
if oldnode and item_handling_node(oldnode.name) then
|
||||
Tube:after_dig_node(pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -240,19 +240,15 @@ function techage.is_ocean(pos)
|
||||
return true
|
||||
end
|
||||
|
||||
function techage.item_image(x, y, itemname)
|
||||
function techage.item_image(x, y, itemname, count)
|
||||
local name, size = unpack(string.split(itemname, " "))
|
||||
size = count and count or size
|
||||
size = tonumber(size) or 1
|
||||
local label = ""
|
||||
local tooltip = ""
|
||||
local ndef = minetest.registered_nodes[name] or minetest.registered_items[name] or minetest.registered_craftitems[name]
|
||||
local text = minetest.formspec_escape(ItemStack(itemname):get_description())
|
||||
local tooltip = "tooltip["..x..","..y..";1,1;"..text..";#0C3D32;#FFFFFF]"
|
||||
|
||||
if ndef and ndef.description then
|
||||
local text = minetest.formspec_escape(ndef.description)
|
||||
tooltip = "tooltip["..x..","..y..";1,1;"..text..";#0C3D32;#FFFFFF]"
|
||||
end
|
||||
|
||||
if ndef and ndef.stack_max == 1 then
|
||||
size = tonumber(size)
|
||||
if minetest.registered_tools[name] and size > 1 then
|
||||
local offs = 0
|
||||
if size < 10 then
|
||||
offs = 0.65
|
||||
|
@ -36,6 +36,19 @@ function techage.liquid.formspec(pos, nvm)
|
||||
if nvm.liquid and nvm.liquid.amount and nvm.liquid.amount > 0 and nvm.liquid.name then
|
||||
itemname = nvm.liquid.name.." "..nvm.liquid.amount
|
||||
end
|
||||
local name = minetest.get_node(pos).name
|
||||
if name == "techage:ta4_tank" then
|
||||
local public = dump((M(pos):get_int("public") or 0) == 1)
|
||||
return "size[5,3]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;4.8,0.5;#c6e8ff]"..
|
||||
"label[1.5,-0.1;"..minetest.colorize("#000000", title).."]"..
|
||||
help(4.4, -0.1)..
|
||||
techage.item_image(2, 1, itemname)..
|
||||
"checkbox[0.1,2.5;public;"..S("Allow public access to the tank")..";"..public.."]"
|
||||
else
|
||||
return "size[4,2]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
@ -44,6 +57,7 @@ function techage.liquid.formspec(pos, nvm)
|
||||
"label[1,-0.1;"..minetest.colorize("#000000", title).."]"..
|
||||
help(3.4, -0.1)..
|
||||
techage.item_image(1.5, 1, itemname)
|
||||
end
|
||||
end
|
||||
|
||||
function techage.liquid.is_empty(pos)
|
||||
@ -205,7 +219,8 @@ local function empty_on_punch(pos, nvm, full_container, item_count)
|
||||
end
|
||||
|
||||
function techage.liquid.on_punch(pos, node, puncher, pointed_thing)
|
||||
if minetest.is_protected(pos, puncher:get_player_name()) then
|
||||
local public = M(pos):get_int("public") == 1
|
||||
if not public and minetest.is_protected(pos, puncher:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -26,6 +26,8 @@ end
|
||||
|
||||
function techage.mark_region(name, pos1, pos2, owner, secs)
|
||||
|
||||
if not name or not pos1 or not pos2 then return end
|
||||
|
||||
techage.unmark_region(name)
|
||||
|
||||
local thickness = 0.2
|
||||
@ -82,6 +84,7 @@ minetest.register_entity(":techage:region_cube", {
|
||||
textures = {"techage_cube_mark.png"},
|
||||
use_texture_alpha = true,
|
||||
physical = false,
|
||||
glow = 12,
|
||||
},
|
||||
on_step = function(self, dtime)
|
||||
if marker_region[self.player_name] == nil then
|
||||
|
@ -114,7 +114,7 @@ minetest.register_entity(":techage:position_side", {
|
||||
physical = false,
|
||||
visual_size = {x = 1.1, y = 1.1, z = 1.1},
|
||||
collisionbox = {-0.55,-0.55,-0.55, 0.55,0.55,0.55},
|
||||
glow = 8,
|
||||
glow = 12,
|
||||
},
|
||||
on_step = function(self, dtime)
|
||||
if marker_region[self.player_name] == nil then
|
||||
|
@ -243,7 +243,7 @@ local function collect_network_nodes(pos, outdir, tlib2)
|
||||
end
|
||||
for _,ntype in ipairs(ntypes) do
|
||||
if not netw[ntype] then netw[ntype] = {} end
|
||||
netw[ntype][#netw[ntype] + 1] = {pos = pos, indir = indir, nominal = ndef.nominal or 0}
|
||||
netw[ntype][#netw[ntype] + 1] = {pos = pos, indir = indir, nominal = ndef.nominal}
|
||||
end
|
||||
end)
|
||||
netw.best_before = minetest.get_gametime() + BEST_BEFORE
|
||||
|
@ -41,7 +41,7 @@ function techage.valid_place_for_windturbine(pos, player_name, num_turbines)
|
||||
if data then
|
||||
local name = minetest.get_biome_name(data.biome)
|
||||
if not string.find(name, "ocean") then
|
||||
chat_message(player_name, S("This is a "..name.." biome and no ocean!"))
|
||||
chat_message(player_name, S("This is a").." "..name.." "..S("biome and no ocean!"))
|
||||
return false
|
||||
end
|
||||
end
|
||||
@ -60,7 +60,7 @@ function techage.valid_place_for_windturbine(pos, player_name, num_turbines)
|
||||
pos2 = {x=pos.x+20, y=1, z=pos.z+20}
|
||||
num = #minetest.find_nodes_in_area(pos1, pos2,
|
||||
{"default:water_source", "default:water_flowing", "ignore"})
|
||||
print(num, (41 * 41 * 0.9))
|
||||
|
||||
if num < (41*41 * 0.8) then
|
||||
techage.mark_region(player_name, pos1, pos2, "")
|
||||
chat_message(player_name, S("Here is not enough water (41x41 m)!"))
|
||||
@ -69,6 +69,7 @@ function techage.valid_place_for_windturbine(pos, player_name, num_turbines)
|
||||
-- Check for next wind turbine
|
||||
pos1 = {x=pos.x-13, y=2, z=pos.z-13}
|
||||
pos2 = {x=pos.x+13, y=22, z=pos.z+13}
|
||||
|
||||
num = #minetest.find_nodes_in_area(pos1, pos2, {"techage:ta4_wind_turbine"})
|
||||
if num > num_turbines then
|
||||
techage.mark_region(player_name, pos1, pos2, "")
|
||||
|
@ -59,6 +59,15 @@ local function take_liquid(pos, indir, name, amount)
|
||||
return amount, name
|
||||
end
|
||||
|
||||
local function untake_liquid(pos, indir, name, amount)
|
||||
local leftover = liquid.srv_put(pos, indir, name, amount)
|
||||
if techage.is_activeformspec(pos) then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", liquid.formspec(pos, nvm))
|
||||
end
|
||||
return leftover
|
||||
end
|
||||
|
||||
local function put_liquid(pos, indir, name, amount)
|
||||
-- check if it is not powder
|
||||
local ndef = minetest.registered_craftitems[name] or {}
|
||||
@ -153,6 +162,7 @@ minetest.register_node("techage:tank_cart", {
|
||||
peek = liquid.srv_peek,
|
||||
put = put_liquid,
|
||||
take = take_liquid,
|
||||
untake = untake_liquid,
|
||||
},
|
||||
networks = networks_def,
|
||||
on_rightclick = on_rightclick,
|
||||
|
@ -157,9 +157,11 @@ local function untake(recipe, pos, liquids)
|
||||
for _,item in pairs(recipe.input) do
|
||||
if item.name ~= "" then
|
||||
local outdir = liquids[item.name] or reload_liquids(pos)[item.name]
|
||||
if outdir then
|
||||
liquid.untake(pos, outdir, item.name, item.num)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function dosing(pos, nvm, elapsed)
|
||||
|
@ -32,7 +32,7 @@ local function formspec(self, pos, nvm)
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
power.formspec_label_bar(0, 0.8, S("power"), PWR_CAPA, nvm.provided)..
|
||||
power.formspec_label_bar(pos, 0, 0.8, S("power"), PWR_CAPA, nvm.provided)..
|
||||
"image_button[2.8,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[2.8,2;1,1;"..self:get_state_tooltip(nvm).."]"
|
||||
end
|
||||
|
@ -49,7 +49,7 @@ local function formspec(self, pos, nvm)
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;4.8,0.5;#c6e8ff]"..
|
||||
"label[1,-0.1;"..minetest.colorize("#000000", S("Digtron Battery")).."]"..
|
||||
power.formspec_label_bar(0, 0.8, S("Load"), TOTAL_MAX, total, S("Coal Equivalents"))..
|
||||
power.formspec_label_bar(pos, 0, 0.8, S("Load"), TOTAL_MAX, total, S("Coal Equivalents"))..
|
||||
"image_button[2.6,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[2.6,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"image[3.75,2;1,1;"..techage.get_power_image(pos, nvm).."]"
|
||||
|
@ -48,6 +48,7 @@ techage.Items = {
|
||||
ta2_chest = "techage:chest_ta2",
|
||||
ta2_forceload = "techage:forceload",
|
||||
ta2_driveaxle = "techage:axle",
|
||||
ta2_generator = "techage:ta2_generator_off",
|
||||
---------------------
|
||||
techage_ta3 = "techage_ta3.png",
|
||||
techage_ta31 = "techage_ta3b.png",
|
||||
@ -114,6 +115,7 @@ techage.Items = {
|
||||
ta3_pipe_wall_entry = "techage:ta3_pipe_wall_entry",
|
||||
ta3_mesecons_converter = "techage:ta3_mesecons_converter",
|
||||
ta3_valve = "techage:ta3_valve_closed",
|
||||
ta3_motor = "techage:ta3_motor_off",
|
||||
----------------------------
|
||||
techage_ta4 = "techage_ta4.png",
|
||||
ta4_windturbine = "techage:ta4_wind_turbine",
|
||||
|
@ -28,6 +28,7 @@ techage.manual_DE.aTitel = {
|
||||
"3,TA2 Schwungrad / Flywheel",
|
||||
"3,TA2 Dampfleitungen / Steam Pipe",
|
||||
"3,TA2 Antriebsachsen / TA2 Drive Axle",
|
||||
"3,TA2 Stromgenerator / TA2 Power Generator",
|
||||
"2,Items schieben und sortieren",
|
||||
"3,Röhren / TechAge Tube",
|
||||
"3,TA2 Schieber / Pusher",
|
||||
@ -66,6 +67,8 @@ techage.manual_DE.aTitel = {
|
||||
"3,TA3 Kleiner Stromgenerator / Tiny Power Generator",
|
||||
"3,TA3 Akku Block / Akku Box",
|
||||
"3,TA3 Strom Terminal / Power Terminal",
|
||||
"3,TA3 Elektromotor / TA3 Electric Motor",
|
||||
"3,TA3 Strom Terminal / Power Terminal",
|
||||
"2,TA3 Industrieofen",
|
||||
"3,TA3 Ofen-Ölbrenner / Furnace Oil Burner",
|
||||
"3,TA3 Ofenoberteil / Furnace Top",
|
||||
@ -399,6 +402,14 @@ techage.manual_DE.aText = {
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Um Lampen oder andere Stromverbraucher an einer Dampfmaschine betreiben zu können\\, wird der TA2 Stromgenerator benötigt. Der TA2 Stromgenerator muss auf einer Seite mit Antriebsachsen verbunden werden und liefert dann auf der anderen Seite elektrischen Strom.\n"..
|
||||
"\n"..
|
||||
"Wird der Stromgenerator nicht mit ausreichend Kraft versorgt\\, geht er in einen Fehlerzustand und muss über einen Rechtsklick wieder aktiviert werden.\n"..
|
||||
"\n"..
|
||||
"Das Stromgenerator nimmt primär max. 25 ku an Achsenkraft auf und gibt sekundär max. 24 ku als Strom wieder ab. Er verbraucht also ein ku für die Umwandlung.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Um Gegenstände (Items) von einer Verarbeitungsstation zur nächsten weiter zu transportieren\\, werden Schieber und Röhren verwendet. Siehe Plan.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
@ -424,6 +435,8 @@ techage.manual_DE.aText = {
|
||||
"\n"..
|
||||
"Der Verteiler besitzt dazu ein Menü mit 4 Filter mit unterschiedlichen Farben\\, entsprechend den 4 Ausgängen. Soll ein Ausgang genutzt werden\\, so muss der entsprechende Filter über die \"on\" Checkbox aktiviert werden. Alle Items\\, die für diesen Filter konfiguriert sind\\, werden über den zugeordneten Ausgang ausgegeben. Wird ein Filter aktiviert\\, ohne das Items konfiguriert werden\\, so sprechen wir hier von einem \"nicht-konfigurierten\"\\, offenen Ausgang.\n"..
|
||||
"\n"..
|
||||
"*Achtung: Der Verteiler ist an seinen Ausgängen gleichzeitig ein Schieber. Daher niemals die Gegenstände mit einem Schieber aus dem Verteiler ziehen!*\n"..
|
||||
"\n"..
|
||||
"Für einen nicht-konfigurierten Ausgang gibt es zwei Betriebsarten:\n"..
|
||||
"\n"..
|
||||
"1) Alle Items ausgeben\\, die an keine anderen Ausgängen ausgegeben werden können\\, auch wenn diese blockiert sind.\n"..
|
||||
@ -649,6 +662,21 @@ techage.manual_DE.aText = {
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Um TA2 Maschinen über das Stromnetz betreiben zu können\\, wird der TA3 Elektromotor benötigt. Dieser wandelt Strom in Achsenkraft um.\n"..
|
||||
"Wird der Elektromotor nicht mit ausreichend Strom versorgt\\, geht er in einen Fehlerzustand und muss über einen Rechtsklick wieder aktiviert werden.\n"..
|
||||
"\n"..
|
||||
"Das Elektromotor nimmt primär max. 40 ku an Strom auf und gibt sekundär max. 39 ku als Achsenkraft wieder ab. Er verbraucht also ein ku für die Umwandlung.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Das Strom-Terminal muss mit dem Stromnetz verbunden werden. Es zeigt Daten aus dem Stromnetz an.\n"..
|
||||
"\n"..
|
||||
"In der oberen Hälfte werden nur die Daten eines ausgewählten Typs ausgegeben. Wird als Typ bspw. \"Kraftwerk\" gewählt\\, so werden nur die Daten von Öl- und Kohlekraftwerken gesammelt und ausgegeben. Links werden die Daten von Generatoren (Stromabgabe) und rechts die Daten von Energiespeichern (Stromaufnahme) ausgegeben. Beim Akkublocks bspw. wird beides ausgegeben\\, da der Akku Strom aufnehmen und abgeben kann.\n"..
|
||||
"\n"..
|
||||
"In der unteren Hälfte werden die Daten aller Generatoren und Speichersystemen des ganzen Stromnetzen zusammengefasst ausgegeben.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Der TA3 Industrieofen dient als Ergänzung zu normalen Ofen (furnace). Damit können alle Waren mit \"Koch\" Rezepten\\, auch im Industrieofen hergestellt werden. Es gibt aber auch spezielle Rezepte\\, die nur im Industrieofen hergestellt werden können.\n"..
|
||||
"Der Industrieofen hat sein eigenes Menü zur Rezeptauswahl. Abhängig von den Waren im Industrieofen Inventar links kann rechts das Ausgangsprodukt gewählt werden.\n"..
|
||||
"\n"..
|
||||
@ -935,7 +963,7 @@ techage.manual_DE.aText = {
|
||||
" - 'pub' schalte in den öffentlichen Modus um\n"..
|
||||
" - 'priv' schalte in den privaten Modus um\n"..
|
||||
"\n"..
|
||||
"Im privaten Modul kann nur der Besitzer selbst Kommandos eingeben oder Tasten nutzen.\n"..
|
||||
"Im privaten Modus (private) kann das Terminal nur von Spielern verwendet werden\\, die an diesem Ort bauen können\\, also Protection Rechte besitzen. Im öffentlichen Modus (public) können alle Spieler die vorkonfigurierten Tasten verwenden.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
@ -1070,10 +1098,11 @@ techage.manual_DE.aText = {
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Eine Windkraftanlagen liefern immer dann Strom\\, wenn Wind vorhanden ist. Im Spiel gibt es keinen Wind\\, aber die Mod simuliert dies dadurch\\, dass sich nur morgens (5:00 - 9:00) und abends (17:00 - 21:00) die Windräder drehen und damit Strom liefern\\, sofern diese an geeigneten Stellen errichtet werden.\n"..
|
||||
"Eine Windkraftanlage liefern immer dann Strom\\, wenn Wind vorhanden ist. Im Spiel gibt es keinen Wind\\, aber die Mod simuliert dies dadurch\\, dass sich nur morgens (5:00 - 9:00) und abends (17:00 - 21:00) die Windräder drehen. Eine Windkraftanlage liefert nur dann Strom\\, wenn sie an einer geeigneten Stelle aufgestellt ist.\n"..
|
||||
"\n"..
|
||||
"Die TA Windkraftanlagen sind reine Offshore Anlagen\\, das heißt\\, die müssen im Meer (Wasser) errichtet werden. Dies bedeutet\\, dass um den Mast herum mit einem Abstand von 20 Blöcken nur Wasser sein darf und das mindestens 2 Blöcke tief.\n"..
|
||||
"Der Rotor muss in einer Höhe (Y-Koordinate) von 12 bis maximal 20 m platziert werden. Der Abstand zu weiteren Windkraftanlagen muss mindestens 14 m betragen.\n"..
|
||||
"Die TA Windkraftanlagen sind reine Offshore Anlagen\\, das heißt\\, die müssen im Meer errichtet werden. Dies bedeutet\\, dass Windkraftanlagen nur in einem Meer (occean) Biom errichtet werden können und dass um den Mast herum ausreichend Wasser und freie Sicht vorhanden sein müssen.\n"..
|
||||
"\n"..
|
||||
"Um eine geeignete Stelle zu finden\\, musst du mit dem Schraubenschlüssel (TechAge Info Werkzeug) auf das Wasser klicken. Ob diese Stelle für den Mast der Windkraftanlage geeignet ist\\, wird dir als Chat Nachricht angezeigt.\n"..
|
||||
"\n"..
|
||||
"Der Strom muss vom Rotor-Block durch den Mast nach unten geführt werden. Dazu zuerst die Stromleitung nach oben ziehen und das Stromkabel dann mit TA4 Säulenblöcke \"verputzen\". Unten kann eine Arbeitsplattform errichtet werden. Der Plan rechts zeigt den Aufbau im oberen Teil.\n"..
|
||||
"\n"..
|
||||
@ -1160,7 +1189,7 @@ techage.manual_DE.aText = {
|
||||
" - Hülle mit 7x7x7 Concrete Blocks\\, gefüllt mit 125 Gravel\\, Speicherkapazität: 2\\,5 Tage bei 60 ku\n"..
|
||||
" - Hülle mit 9x9x9 Concrete Blocks\\, gefüllt mit 343 Gravel\\, Speicherkapazität: 6\\,5 Tage bei 60 ku\n"..
|
||||
"\n"..
|
||||
"In der Betonhülle darf ein Fenster aus einem Obsidian Glas Block sein. Dieses muss ziemlich in der Mitte der Wand platziert werden. Durch dieses Fenster sieht man\\, ob der Speicher mehr als 80 % geladen ist. Im Plan rechts sieht man den Aufbau aus TA4 Wärmetauscher bestehend aus 3 Blöcken\\, der TA4 Turbine und dem TA4 Generator. Beim Wärmetauscher ist auf die Ausrichtung achten (der Pfeil bei Block 1 muss zur Turbine zeigen).\n"..
|
||||
"In der Betonhülle darf ein Fenster aus einem Obsidian Glas Block sein. Dieses muss ziemlich in der Mitte der Wand platziert werden. Durch dieses Fenster sieht man\\, ob der Speicher mehr als 80 % geladen ist. Im Plan rechts sieht man den Aufbau aus TA4 Wärmetauscher bestehend aus 3 Blöcken\\, der TA4 Turbine und dem TA4 Generator. Beim Wärmetauscher ist auf die Ausrichtung zu achten (der Pfeil bei Block 1 muss zur Turbine zeigen).\n"..
|
||||
"\n"..
|
||||
"Entgegen dem Plan rechts müssen die Anschlüsse am Speicherblock auf gleicher Ebene sein (horizontal angeordnet\\, also nicht unten und oben). Die Rohrzuläufe (TA4 Pipe Inlet) müssen genau in der Mitte der Wand sein und stehen sich damit gegenüber. Als Röhren kommen die gelbel TA4 Röhren zum Einsatz. Die TA3 Dampfrohre können hier nicht verwendet werden.\n"..
|
||||
"Sowohl der Generator als auch der Wärmetauscher haben einen Stromanschluss und müssen mit dem Stromnetz verbunden werden.\n"..
|
||||
@ -1349,9 +1378,9 @@ techage.manual_DE.aText = {
|
||||
"Wird etwas in die Kiste gelegt\\, oder entnommen\\, oder eine der Tasten \"F1\"/\"F2\" gedrückt\\, so wird ein Event-Signal an den Lua Controller gesendet.\n"..
|
||||
"Die Sensor Kiste unterstützt folgende Kommandos:\n"..
|
||||
"\n"..
|
||||
" - Über 'state = $read_data(<num>\\, \"state\")' kann der Status der Kiste abgefragt werden. Mögliche Antworten sind: \"empty\"\\, \"loaded\"\\, \"full\"\n"..
|
||||
" - Über 'name\\, action = $read_data(<num>\\, \"action\")' kann die letzte Spieleraktion abgefragt werden. 'name' ist der Spielername\\, Als 'action' wird zurückgeliefert: \"put\"\\, \"take\"\\, \"f1\"\\, \"f2\".\n"..
|
||||
" - Über 'stacks = $read_data(<num>\\, \"stacks\")' kann der Inhalt der Kiste ausgelesen werden. Siehe dazu: https://github.com/joe7575/techage/blob/master/manuals/ta4_lua_controller_EN.md#sensor-chest\n"..
|
||||
" - Über 'state = $send_cmnd(<num>\\, \"state\")' kann der Status der Kiste abgefragt werden. Mögliche Antworten sind: \"empty\"\\, \"loaded\"\\, \"full\"\n"..
|
||||
" - Über 'name\\, action = $send_cmnd(<num>\\, \"action\")' kann die letzte Spieleraktion abgefragt werden. 'name' ist der Spielername\\, Als 'action' wird zurückgeliefert: \"put\"\\, \"take\"\\, \"f1\"\\, \"f2\".\n"..
|
||||
" - Über 'stacks = $send_cmnd(<num>\\, \"stacks\")' kann der Inhalt der Kiste ausgelesen werden. Siehe dazu: https://github.com/joe7575/techage/blob/master/manuals/ta4_lua_controller_EN.md#sensor-chest\n"..
|
||||
" - Über '$send_cmnd(<num>\\, \"text\"\\, \"press both buttons andnput something into the chest\")' kann der Text im Menü der Sensor Kiste gesetzt werden.\n"..
|
||||
"\n"..
|
||||
"Über die Checkbox \"Erlaube öffentlichen Zugriff\" kann eingestellt werden\\, ob die Kiste von jedem genutzt werden darf\\, oder nur von Spielern die hier Zugriffsrechte haben.\n"..
|
||||
@ -1497,7 +1526,7 @@ techage.manual_DE.aText = {
|
||||
"\n"..
|
||||
"Der Kiste besitzt ein zusätzliches Kommandos für den Lua Controller:\n"..
|
||||
"\n"..
|
||||
" - 'count' dient zur Anfrage\\, wie viele Items in der Kiste sind.\nBeispiel 1: '$read_data(CHEST\\, \"count\")' --> Summe der Items über alle 8 Speicher\nBeispiel 2: '$read_data(CHEST\\, \"count\"\\, 2)' --> Anzahl der Items in Speicher 2 (zweiter von links)\n"..
|
||||
" - 'count' dient zur Anfrage\\, wie viele Items in der Kiste sind.\nBeispiel 1: '$send_cmnd(CHEST\\, \"count\")' --> Summe der Items über alle 8 Speicher\nBeispiel 2: '$send_cmnd(CHEST\\, \"count\"\\, 2)' --> Anzahl der Items in Speicher 2 (zweiter von links)\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
@ -1572,6 +1601,7 @@ techage.manual_DE.aItemName = {
|
||||
"ta2_flywheel",
|
||||
"ta2_steampipe",
|
||||
"ta2_driveaxle",
|
||||
"ta2_generator",
|
||||
"",
|
||||
"tube",
|
||||
"ta2_pusher",
|
||||
@ -1610,6 +1640,8 @@ techage.manual_DE.aItemName = {
|
||||
"ta3_tinygenerator",
|
||||
"ta3_akkublock",
|
||||
"ta3_powerterminal",
|
||||
"ta3_motor",
|
||||
"ta3_powerterminal",
|
||||
"",
|
||||
"ta3_furnacefirebox",
|
||||
"ta3_furnace",
|
||||
@ -1764,6 +1796,7 @@ techage.manual_DE.aPlanTable = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"itemtransport",
|
||||
"",
|
||||
"",
|
||||
@ -1802,6 +1835,8 @@ techage.manual_DE.aPlanTable = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"ta3_furnace",
|
||||
"",
|
||||
"",
|
||||
|
@ -28,6 +28,7 @@ techage.manual_EN.aTitel = {
|
||||
"3,TA2 Flywheel",
|
||||
"3,TA2 Steam Pipes",
|
||||
"3,TA2 Drive Axle / TA2 Gearbox",
|
||||
"3,TA2 Power Generator",
|
||||
"2,Push and sort items",
|
||||
"3,TechAge Tube",
|
||||
"3,TA2 Pusher",
|
||||
@ -66,6 +67,7 @@ techage.manual_EN.aTitel = {
|
||||
"3,TA3 Small Power Generator",
|
||||
"3,TA3 Battery Block",
|
||||
"3,TA3 Power Terminal",
|
||||
"3,TA3 Electric Motor",
|
||||
"2,TA3 Industrial Furnace",
|
||||
"3,TA3 Furnace Oil Burner",
|
||||
"3,TA3 Furnace Top",
|
||||
@ -399,6 +401,14 @@ techage.manual_EN.aText = {
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"The TA2 Power Generator is required to operate lamps or other power consumers on a steam engine. The TA2 Power Generator has to be connected to drive axles on one side and then supplies electricity on the other side.\n"..
|
||||
"\n"..
|
||||
"If the Power Generator is not supplied with sufficient power\\, it goes into an error state and must be reactivated with a right-click.\n"..
|
||||
"\n"..
|
||||
"The Power Generator takes max. 25 ku of axle power and provides on the other side max. 24 ku as electricity. So he consumes one ku for the conversion.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"In order to transport objects from one processing station to the next\\, pushers and tubes are used. See plan.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
@ -424,6 +434,8 @@ techage.manual_EN.aText = {
|
||||
"\n"..
|
||||
"The distributor has a menu with 4 filters with different colors\\, corresponding to the 4 outputs. If an output is to be used\\, the corresponding filter must be activated via the \"on\" checkbox. All items that are configured for this filter are output via the assigned output. If a filter is activated without items being configured\\, we are talking about an \"unconfigured\"\\, open output.\n"..
|
||||
"\n"..
|
||||
"*Attention: The distributor is also a pusher at its output sides. Therefore\\, never pull items out of the distributor with a pusher!*\n"..
|
||||
"\n"..
|
||||
"There are two operating modes for a non-configured output:\n"..
|
||||
"\n"..
|
||||
"1) Output all items that cannot be output to any other exit\\, even if they are blocked.\n"..
|
||||
@ -649,6 +661,13 @@ techage.manual_EN.aText = {
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"The TA3 Electric Motor is required in order to be able to operate TA2 machines via the power grid. The TA3 Electric Motor converts electricity into axle power.\n"..
|
||||
"If the electric motor is not supplied with sufficient power\\, it goes into an fault state and must be reactivated with a right-click.\n"..
|
||||
"\n"..
|
||||
"The electric motor takes max. 40 ku of electricity and provides on the other side max. 39 ku as axle power. So he consumes one ku for the conversion.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"The TA3 industrial furnace serves as a supplement to normal furnaces. This means that all goods can be produced with \"cooking\" recipes\\, even in an industrial furnace. But there are also special recipes that can only be made in an industrial furnace.\n"..
|
||||
"The industrial furnace has its own menu for recipe selection. Depending on the goods in the industrial furnace inventory on the left\\, the output product can be selected on the right.\n"..
|
||||
"\n"..
|
||||
@ -933,7 +952,9 @@ techage.manual_EN.aText = {
|
||||
" - 'pub' switch to public mode\n"..
|
||||
" - 'priv' switch to private mode\n"..
|
||||
"\n"..
|
||||
"In the private mode\\, only the owner can enter commands himself or use keys.\n"..
|
||||
"In private mode\\, the terminal can only be used by players who can build at this location\\, i.e. who have protection rights.\n"..
|
||||
"\n"..
|
||||
"In public mode\\, all players can use the preconfigured keys.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
@ -1060,10 +1081,11 @@ techage.manual_EN.aText = {
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"A wind turbine always delivers electricity when there is wind. There is no wind in the game\\, but the mod simulates this by only turning the wind turbines in the morning (5:00 a.m. - 9:00 a.m.) and in the evening (5:00 p.m. - 9:00 p.m.) and thus supplying electricity\\, provided they are positioned appropriately.\n"..
|
||||
"A wind turbine always supplies electricity when there is wind. There is no wind in the game\\, but the mod simulates this by turning the wind turbines only in the morning (5:00 - 9:00) and in the evening (17:00 - 21:00). A wind turbine only supplies electricity if it is set up in a suitable location.\n"..
|
||||
"\n"..
|
||||
"The TA wind turbines are pure offshore plants\\, which means that they have to be installed in the sea (water). This means that there must be in the minimum 20 blocks of water around the mast and at least 2 blocks deep.\n"..
|
||||
"The rotor must be placed at a height (Y coordinate) of 12 to a maximum of 20 m. The distance to other wind turbines must be at least 14 m.\n"..
|
||||
"The TA wind power plants are pure offshore plants\\, which means that they have to be built in the sea. This means that wind turbines can only be build in a sea (occean) biome and that there must be sufficient water and a clear view around the mast.\n"..
|
||||
"\n"..
|
||||
"To find a suitable spot\\, click on the water with the wrench (TechAge Info Tool). A chat message will show you whether this position is suitable for the mast of the wind turbine.\n"..
|
||||
"\n"..
|
||||
"The current must be led from the rotor block down through the mast. First pull the power line up and then \"plaster\" the power cable with TA4 pillar blocks. A work platform can be built below. The plan on the right shows the structure in the upper part.\n"..
|
||||
"\n"..
|
||||
@ -1340,9 +1362,9 @@ techage.manual_EN.aText = {
|
||||
"If something is put into the box or removed\\, or one of the \"F1\" / \"F2\" keys is pressed\\, an event signal is sent to the Lua controller.\n"..
|
||||
"The sensor box supports the following commands:\n"..
|
||||
"\n"..
|
||||
" - The status of the box can be queried via 'state = $read_data(<num>\\, \"state\")'. Possible answers are: \"empty\"\\, \"loaded\"\\, \"full\"\n"..
|
||||
" - The last player action can be queried via 'name\\, action = $read_data(<num>\\, \"action\")'. 'name' is the player name. One of the following is returned as 'action': \"put\"\\, \"take\"\\, \"f1\"\\, \"f2\".\n"..
|
||||
" - The contents of the box can be read out via 'stacks = $read_data(<num>\\, \"stacks\")'. See: https://github.com/joe7575/techage/blob/master/manuals/ta4_lua_controller_EN.md#sensor-chest\n"..
|
||||
" - The status of the box can be queried via 'state = $send_cmnd(<num>\\, \"state\")'. Possible answers are: \"empty\"\\, \"loaded\"\\, \"full\"\n"..
|
||||
" - The last player action can be queried via 'name\\, action = $send_cmnd(<num>\\, \"action\")'. 'name' is the player name. One of the following is returned as 'action': \"put\"\\, \"take\"\\, \"f1\"\\, \"f2\".\n"..
|
||||
" - The contents of the box can be read out via 'stacks = $send_cmnd(<num>\\, \"stacks\")'. See: https://github.com/joe7575/techage/blob/master/manuals/ta4_lua_controller_EN.md#sensor-chest\n"..
|
||||
" - Via '$send_cmnd(<num>\\, \"text\"\\, \"press both buttons andnput something into the chest\")' the text can be set in the menu of the sensor box.\n"..
|
||||
"\n"..
|
||||
"The checkbox \"Allow public chest access\" can be used to set whether the box can be used by everyone or only by players who have access/protection rights here.\n"..
|
||||
@ -1471,7 +1493,7 @@ techage.manual_EN.aText = {
|
||||
"\n"..
|
||||
"If the chest is filled with a pusher\\, all stores fill from left to right. If all 8 stores are full and no further items can be added\\, further items are rejected.\n"..
|
||||
"\n"..
|
||||
"* Row function *\n"..
|
||||
"*Row function*\n"..
|
||||
"\n"..
|
||||
"Several TA4 8x2000 chests can be connected to a large chest with more content. To do this\\, the chests must be placed in a row one after the other.\n"..
|
||||
"\n"..
|
||||
@ -1488,7 +1510,7 @@ techage.manual_EN.aText = {
|
||||
"\n"..
|
||||
"The chest has an additional command for the Lua controller:\n"..
|
||||
"\n"..
|
||||
" - 'count' is used to request how many items are in the chest.\nExample 1: '$read_data(CHEST\\, \"count\")' -> Sum of items across all 8 stores\nExample 2: '$read_data(CHEST\\, \"count\"\\, 2)' -> number of items in store 2 (second from left)\n"..
|
||||
" - 'count' is used to request how many items are in the chest.\nExample 1: '$send_cmnd(CHEST\\, \"count\")' -> Sum of items across all 8 stores\nExample 2: '$send_cmnd(CHEST\\, \"count\"\\, 2)' -> number of items in store 2 (second from left)\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
@ -1563,6 +1585,7 @@ techage.manual_EN.aItemName = {
|
||||
"ta2_flywheel",
|
||||
"ta2_steampipe",
|
||||
"ta2_driveaxle",
|
||||
"ta2_generator",
|
||||
"",
|
||||
"tube",
|
||||
"ta2_pusher",
|
||||
@ -1601,6 +1624,7 @@ techage.manual_EN.aItemName = {
|
||||
"ta3_tinygenerator",
|
||||
"ta3_akkublock",
|
||||
"ta3_powerterminal",
|
||||
"ta3_motor",
|
||||
"",
|
||||
"ta3_furnacefirebox",
|
||||
"ta3_furnace",
|
||||
@ -1755,6 +1779,7 @@ techage.manual_EN.aPlanTable = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"itemtransport",
|
||||
"",
|
||||
"",
|
||||
@ -1793,6 +1818,7 @@ techage.manual_EN.aPlanTable = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"ta3_furnace",
|
||||
"",
|
||||
"",
|
||||
|
@ -185,7 +185,7 @@ local PN270 = {"techage_gaspipe_knee.png^[transformR270", "techage:ta4_pipeS"}
|
||||
techage.ConstructionPlans["ta3_tank"] = {
|
||||
{false, false, false, false, false, false, false, false, false, false},
|
||||
{false, Tubes, PushR, Tubes, Fillr, Tubes, PushR, Tubes, false, false},
|
||||
{false, false, false, false, TANK3, PIPEH, PIPEH, Pump, PIPEH, Tank},
|
||||
{false, false, false, false, TANK3, PIPEH, PIPEH, Pump, PIPEH, false},
|
||||
{false, false, false, false, false, false, false, false, false, false},
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ local function formspec(self, pos, nvm)
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
power.formspec_label_bar(0, 0.8, S("Electricity"), PWR_CAPA, nvm.provided)..
|
||||
power.formspec_label_bar(pos, 0, 0.8, S("Electricity"), PWR_CAPA, nvm.provided)..
|
||||
"image_button[2.8,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[2.8,2;1,1;"..self:get_state_tooltip(nvm).."]"
|
||||
end
|
||||
|
@ -44,8 +44,8 @@ local function formspec(self, pos, nvm)
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;5.8,0.5;#c6e8ff]"..
|
||||
"label[2,-0.1;"..minetest.colorize( "#000000", S("Heat Exchanger")).."]"..
|
||||
power.formspec_label_bar(0, 0.8, S("Electricity"), needed_max, needed)..
|
||||
power.formspec_label_bar(3.5, 0.8, S("Thermal"), capa_max, capa, "")..
|
||||
power.formspec_label_bar(pos, 0, 0.8, S("Electricity"), needed_max, needed)..
|
||||
power.formspec_label_bar(pos, 3.5, 0.8, S("Thermal"), capa_max, capa, "")..
|
||||
arrow..
|
||||
"image_button[2.5,3;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[2.5,3;1,1;"..self:get_state_tooltip(nvm).."]"
|
||||
|
@ -111,7 +111,7 @@ local function process(inv, recipe, output)
|
||||
if recipe.waste then
|
||||
local leftover = inv:add_item("dst", ItemStack(recipe.waste))
|
||||
if leftover:get_count() > 0 then
|
||||
inv:set_list("src", leftover)
|
||||
inv:add_item("src", leftover)
|
||||
return techage.BLOCKED
|
||||
end
|
||||
end
|
||||
|
@ -242,7 +242,12 @@ local tubing = {
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "output" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return string.split(nvm.output or "unknown", " ")[1]
|
||||
else
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ local function formspec(self, pos, nvm)
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;5.8,0.5;#c6e8ff]"..
|
||||
"label[2.5,-0.1;"..minetest.colorize( "#000000", S("Electrolyzer")).."]"..
|
||||
techage.power.formspec_label_bar(0.1, 0.8, S("Electricity"), PWR_NEEDED, nvm.taken)..
|
||||
techage.power.formspec_label_bar(pos, 0.1, 0.8, S("Electricity"), PWR_NEEDED, nvm.taken)..
|
||||
arrow..
|
||||
"image_button[3,2.5;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[3,2.5;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
@ -156,6 +156,15 @@ local function after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||
Cable:after_dig_node(pos)
|
||||
end
|
||||
|
||||
local function put(pos, indir, name, amount)
|
||||
local leftover = liquid.srv_put(pos, indir, name, amount)
|
||||
if techage.is_activeformspec(pos) then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", formspec(State, pos, nvm))
|
||||
end
|
||||
return leftover
|
||||
end
|
||||
|
||||
local function tubelib2_on_update2(pos, outdir, tlib2, node)
|
||||
if tlib2.tube_type == "pipe2" then
|
||||
liquid.update_network(pos, outdir, tlib2)
|
||||
@ -182,14 +191,8 @@ local netw_def = {
|
||||
local liquid_def = {
|
||||
capa = CAPACITY,
|
||||
peek = liquid.srv_peek,
|
||||
put = function(pos, indir, name, amount)
|
||||
local leftover = liquid.srv_put(pos, indir, name, amount)
|
||||
if techage.is_activeformspec(pos) then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", formspec(State, pos, nvm))
|
||||
end
|
||||
return leftover
|
||||
end,
|
||||
put = put,
|
||||
untake = put,
|
||||
take = function(pos, indir, name, amount)
|
||||
amount, name = liquid.srv_take(pos, indir, name, amount)
|
||||
if techage.is_activeformspec(pos) then
|
||||
|
@ -48,7 +48,7 @@ local function formspec(self, pos, nvm)
|
||||
arrow..
|
||||
"image_button[2,2.5;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[2,2.5;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
techage.power.formspec_label_bar(3.5, 0.8, S("Electricity"), PWR_CAPA, nvm.given)
|
||||
techage.power.formspec_label_bar(pos, 3.5, 0.8, S("Electricity"), PWR_CAPA, nvm.given)
|
||||
end
|
||||
|
||||
local function start_node(pos, nvm, state)
|
||||
|
469
techage/i18n.py
469
techage/i18n.py
@ -1,79 +1,448 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Script to generate the template file and update the translation files.
|
||||
# Copy the script into the mod or modpack root folder and run it there.
|
||||
#
|
||||
# Copyright (C) 2019 Joachim Stolberg
|
||||
# Copyright (C) 2019 Joachim Stolberg, 2020 FaceDeer, 2020 Louis Royer
|
||||
# LGPLv2.1+
|
||||
#
|
||||
# Copy the script into the mod root folder and adapt the last code lines to you needs.
|
||||
# See https://github.com/minetest-tools/update_translations for
|
||||
# potential future updates to this script.
|
||||
|
||||
from __future__ import print_function
|
||||
import os, fnmatch, re, shutil
|
||||
import os, fnmatch, re, shutil, errno
|
||||
from sys import argv as _argv
|
||||
from sys import stderr as _stderr
|
||||
|
||||
pattern_lua = re.compile(r'[ \.=^\t]S\("(.+?)"\)', re.DOTALL)
|
||||
pattern_tr = re.compile(r'(.+?[^@])=(.+)')
|
||||
# Running params
|
||||
params = {"recursive": False,
|
||||
"help": False,
|
||||
"mods": False,
|
||||
"verbose": False,
|
||||
"folders": [],
|
||||
"no-old-file": False
|
||||
}
|
||||
# Available CLI options
|
||||
options = {"recursive": ['--recursive', '-r'],
|
||||
"help": ['--help', '-h'],
|
||||
"mods": ['--installed-mods'],
|
||||
"verbose": ['--verbose', '-v'],
|
||||
"no-old-file": ['--no-old-file']
|
||||
}
|
||||
|
||||
def gen_template(templ_file, lkeyStrings):
|
||||
lOut = []
|
||||
lkeyStrings.sort()
|
||||
for s in lkeyStrings:
|
||||
lOut.append("%s=" % s)
|
||||
open(templ_file, "wt").write("\n".join(lOut))
|
||||
# Strings longer than this will have extra space added between
|
||||
# them in the translation files to make it easier to distinguish their
|
||||
# beginnings and endings at a glance
|
||||
doublespace_threshold = 60
|
||||
|
||||
def set_params_folders(tab: list):
|
||||
'''Initialize params["folders"] from CLI arguments.'''
|
||||
# Discarding argument 0 (tool name)
|
||||
for param in tab[1:]:
|
||||
stop_param = False
|
||||
for option in options:
|
||||
if param in options[option]:
|
||||
stop_param = True
|
||||
break
|
||||
if not stop_param:
|
||||
params["folders"].append(os.path.abspath(param))
|
||||
|
||||
def set_params(tab: list):
|
||||
'''Initialize params from CLI arguments.'''
|
||||
for option in options:
|
||||
for option_name in options[option]:
|
||||
if option_name in tab:
|
||||
params[option] = True
|
||||
break
|
||||
|
||||
def print_help(name):
|
||||
'''Prints some help message.'''
|
||||
print(f'''SYNOPSIS
|
||||
{name} [OPTIONS] [PATHS...]
|
||||
DESCRIPTION
|
||||
{', '.join(options["help"])}
|
||||
prints this help message
|
||||
{', '.join(options["recursive"])}
|
||||
run on all subfolders of paths given
|
||||
{', '.join(options["mods"])}
|
||||
run on locally installed modules
|
||||
{', '.join(options["no-old-file"])}
|
||||
do not create *.old files
|
||||
{', '.join(options["verbose"])}
|
||||
add output information
|
||||
''')
|
||||
|
||||
|
||||
def main():
|
||||
'''Main function'''
|
||||
set_params(_argv)
|
||||
set_params_folders(_argv)
|
||||
if params["help"]:
|
||||
print_help(_argv[0])
|
||||
elif params["recursive"] and params["mods"]:
|
||||
print("Option --installed-mods is incompatible with --recursive")
|
||||
else:
|
||||
# Add recursivity message
|
||||
print("Running ", end='')
|
||||
if params["recursive"]:
|
||||
print("recursively ", end='')
|
||||
# Running
|
||||
if params["mods"]:
|
||||
print(f"on all locally installed modules in {os.path.abspath('~/.minetest/mods/')}")
|
||||
run_all_subfolders("~/.minetest/mods")
|
||||
elif len(params["folders"]) >= 2:
|
||||
print("on folder list:", params["folders"])
|
||||
for f in params["folders"]:
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(f)
|
||||
else:
|
||||
update_folder(f)
|
||||
elif len(params["folders"]) == 1:
|
||||
print("on folder", params["folders"][0])
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(params["folders"][0])
|
||||
else:
|
||||
update_folder(params["folders"][0])
|
||||
else:
|
||||
print("on folder", os.path.abspath("./"))
|
||||
if params["recursive"]:
|
||||
run_all_subfolders(os.path.abspath("./"))
|
||||
else:
|
||||
update_folder(os.path.abspath("./"))
|
||||
|
||||
#group 2 will be the string, groups 1 and 3 will be the delimiters (" or ')
|
||||
#See https://stackoverflow.com/questions/46967465/regex-match-text-in-either-single-or-double-quote
|
||||
pattern_lua_s = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*(["\'])((?:\\\1|(?:(?!\1)).)*)(\1)[\s,\)]', re.DOTALL)
|
||||
pattern_lua_fs = re.compile(r'[\.=^\t,{\(\s]N?FS\(\s*(["\'])((?:\\\1|(?:(?!\1)).)*)(\1)[\s,\)]', re.DOTALL)
|
||||
pattern_lua_bracketed_s = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*\[\[(.*?)\]\][\s,\)]', re.DOTALL)
|
||||
pattern_lua_bracketed_fs = re.compile(r'[\.=^\t,{\(\s]N?FS\(\s*\[\[(.*?)\]\][\s,\)]', re.DOTALL)
|
||||
|
||||
# Handles "concatenation" .. " of strings"
|
||||
pattern_concat = re.compile(r'["\'][\s]*\.\.[\s]*["\']', re.DOTALL)
|
||||
|
||||
pattern_tr = re.compile(r'(.*?[^@])=(.*)')
|
||||
pattern_name = re.compile(r'^name[ ]*=[ ]*([^ \n]*)')
|
||||
pattern_tr_filename = re.compile(r'\.tr$')
|
||||
pattern_po_language_code = re.compile(r'(.*)\.po$')
|
||||
|
||||
#attempt to read the mod's name from the mod.conf file. Returns None on failure
|
||||
def get_modname(folder):
|
||||
try:
|
||||
with open(os.path.join(folder, "mod.conf"), "r", encoding='utf-8') as mod_conf:
|
||||
for line in mod_conf:
|
||||
match = pattern_name.match(line)
|
||||
if match:
|
||||
return match.group(1)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
return None
|
||||
|
||||
#If there are already .tr files in /locale, returns a list of their names
|
||||
def get_existing_tr_files(folder):
|
||||
out = []
|
||||
for root, dirs, files in os.walk(os.path.join(folder, 'locale/')):
|
||||
for name in files:
|
||||
if pattern_tr_filename.search(name):
|
||||
out.append(name)
|
||||
return out
|
||||
|
||||
# A series of search and replaces that massage a .po file's contents into
|
||||
# a .tr file's equivalent
|
||||
def process_po_file(text):
|
||||
# The first three items are for unused matches
|
||||
text = re.sub(r'#~ msgid "', "", text)
|
||||
text = re.sub(r'"\n#~ msgstr ""\n"', "=", text)
|
||||
text = re.sub(r'"\n#~ msgstr "', "=", text)
|
||||
# comment lines
|
||||
text = re.sub(r'#.*\n', "", text)
|
||||
# converting msg pairs into "=" pairs
|
||||
text = re.sub(r'msgid "', "", text)
|
||||
text = re.sub(r'"\nmsgstr ""\n"', "=", text)
|
||||
text = re.sub(r'"\nmsgstr "', "=", text)
|
||||
# various line breaks and escape codes
|
||||
text = re.sub(r'"\n"', "", text)
|
||||
text = re.sub(r'"\n', "\n", text)
|
||||
text = re.sub(r'\\"', '"', text)
|
||||
text = re.sub(r'\\n', '@n', text)
|
||||
# remove header text
|
||||
text = re.sub(r'=Project-Id-Version:.*\n', "", text)
|
||||
# remove double-spaced lines
|
||||
text = re.sub(r'\n\n', '\n', text)
|
||||
return text
|
||||
|
||||
# Go through existing .po files and, if a .tr file for that language
|
||||
# *doesn't* exist, convert it and create it.
|
||||
# The .tr file that results will subsequently be reprocessed so
|
||||
# any "no longer used" strings will be preserved.
|
||||
# Note that "fuzzy" tags will be lost in this process.
|
||||
def process_po_files(folder, modname):
|
||||
for root, dirs, files in os.walk(os.path.join(folder, 'locale/')):
|
||||
for name in files:
|
||||
code_match = pattern_po_language_code.match(name)
|
||||
if code_match == None:
|
||||
continue
|
||||
language_code = code_match.group(1)
|
||||
tr_name = modname + "." + language_code + ".tr"
|
||||
tr_file = os.path.join(root, tr_name)
|
||||
if os.path.exists(tr_file):
|
||||
if params["verbose"]:
|
||||
print(f"{tr_name} already exists, ignoring {name}")
|
||||
continue
|
||||
fname = os.path.join(root, name)
|
||||
with open(fname, "r", encoding='utf-8') as po_file:
|
||||
if params["verbose"]:
|
||||
print(f"Importing translations from {name}")
|
||||
text = process_po_file(po_file.read())
|
||||
with open(tr_file, "wt", encoding='utf-8') as tr_out:
|
||||
tr_out.write(text)
|
||||
|
||||
# from https://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python/600612#600612
|
||||
# Creates a directory if it doesn't exist, silently does
|
||||
# nothing if it already exists
|
||||
def mkdir_p(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError as exc: # Python >2.5
|
||||
if exc.errno == errno.EEXIST and os.path.isdir(path):
|
||||
pass
|
||||
else: raise
|
||||
|
||||
# Converts the template dictionary to a text to be written as a file
|
||||
# dKeyStrings is a dictionary of localized string to source file sets
|
||||
# dOld is a dictionary of existing translations and comments from
|
||||
# the previous version of this text
|
||||
def strings_to_text(dkeyStrings, dOld, mod_name, header_comments):
|
||||
lOut = [f"# textdomain: {mod_name}\n"]
|
||||
if header_comments is not None:
|
||||
lOut.append(header_comments)
|
||||
|
||||
dGroupedBySource = {}
|
||||
|
||||
for key in dkeyStrings:
|
||||
sourceList = list(dkeyStrings[key])
|
||||
sourceList.sort()
|
||||
sourceString = "\n".join(sourceList)
|
||||
listForSource = dGroupedBySource.get(sourceString, [])
|
||||
listForSource.append(key)
|
||||
dGroupedBySource[sourceString] = listForSource
|
||||
|
||||
lSourceKeys = list(dGroupedBySource.keys())
|
||||
lSourceKeys.sort()
|
||||
for source in lSourceKeys:
|
||||
localizedStrings = dGroupedBySource[source]
|
||||
localizedStrings.sort()
|
||||
lOut.append("")
|
||||
lOut.append(source)
|
||||
lOut.append("")
|
||||
for localizedString in localizedStrings:
|
||||
val = dOld.get(localizedString, {})
|
||||
translation = val.get("translation", "")
|
||||
comment = val.get("comment")
|
||||
if len(localizedString) > doublespace_threshold and not lOut[-1] == "":
|
||||
lOut.append("")
|
||||
if comment != None:
|
||||
lOut.append(comment)
|
||||
lOut.append(f"{localizedString}={translation}")
|
||||
if len(localizedString) > doublespace_threshold:
|
||||
lOut.append("")
|
||||
|
||||
|
||||
unusedExist = False
|
||||
for key in dOld:
|
||||
if key not in dkeyStrings:
|
||||
val = dOld[key]
|
||||
translation = val.get("translation")
|
||||
comment = val.get("comment")
|
||||
# only keep an unused translation if there was translated
|
||||
# text or a comment associated with it
|
||||
if translation != None and (translation != "" or comment):
|
||||
if not unusedExist:
|
||||
unusedExist = True
|
||||
lOut.append("\n\n##### not used anymore #####\n")
|
||||
if len(key) > doublespace_threshold and not lOut[-1] == "":
|
||||
lOut.append("")
|
||||
if comment != None:
|
||||
lOut.append(comment)
|
||||
lOut.append(f"{key}={translation}")
|
||||
if len(key) > doublespace_threshold:
|
||||
lOut.append("")
|
||||
return "\n".join(lOut) + '\n'
|
||||
|
||||
# Writes a template.txt file
|
||||
# dkeyStrings is the dictionary returned by generate_template
|
||||
def write_template(templ_file, dkeyStrings, mod_name):
|
||||
# read existing template file to preserve comments
|
||||
existing_template = import_tr_file(templ_file)
|
||||
|
||||
text = strings_to_text(dkeyStrings, existing_template[0], mod_name, existing_template[2])
|
||||
mkdir_p(os.path.dirname(templ_file))
|
||||
with open(templ_file, "wt", encoding='utf-8') as template_file:
|
||||
template_file.write(text)
|
||||
|
||||
|
||||
# Gets all translatable strings from a lua file
|
||||
def read_lua_file_strings(lua_file):
|
||||
lOut = []
|
||||
text = open(lua_file).read()
|
||||
for s in pattern_lua.findall(text):
|
||||
with open(lua_file, encoding='utf-8') as text_file:
|
||||
text = text_file.read()
|
||||
#TODO remove comments here
|
||||
|
||||
text = re.sub(pattern_concat, "", text)
|
||||
|
||||
strings = []
|
||||
for s in pattern_lua_s.findall(text):
|
||||
strings.append(s[1])
|
||||
for s in pattern_lua_bracketed_s.findall(text):
|
||||
strings.append(s)
|
||||
for s in pattern_lua_fs.findall(text):
|
||||
strings.append(s[1])
|
||||
for s in pattern_lua_bracketed_fs.findall(text):
|
||||
strings.append(s)
|
||||
|
||||
for s in strings:
|
||||
s = re.sub(r'"\.\.\s+"', "", s)
|
||||
s = re.sub("@[^@=n]", "@@", s)
|
||||
s = re.sub("@[^@=0-9]", "@@", s)
|
||||
s = s.replace('\\"', '"')
|
||||
s = s.replace("\\'", "'")
|
||||
s = s.replace("\n", "@n")
|
||||
s = s.replace("\\n", "@n")
|
||||
s = s.replace("=", "@=")
|
||||
lOut.append(s)
|
||||
return lOut
|
||||
|
||||
def inport_tr_file(tr_file):
|
||||
# Gets strings from an existing translation file
|
||||
# returns both a dictionary of translations
|
||||
# and the full original source text so that the new text
|
||||
# can be compared to it for changes.
|
||||
# Returns also header comments in the third return value.
|
||||
def import_tr_file(tr_file):
|
||||
dOut = {}
|
||||
text = None
|
||||
header_comment = None
|
||||
if os.path.exists(tr_file):
|
||||
for line in open(tr_file, "r").readlines():
|
||||
s = line.strip()
|
||||
if s == "" or s[0] == "#":
|
||||
continue
|
||||
match = pattern_tr.match(s)
|
||||
if match:
|
||||
dOut[match.group(1)] = match.group(2)
|
||||
return dOut
|
||||
with open(tr_file, "r", encoding='utf-8') as existing_file :
|
||||
# save the full text to allow for comparison
|
||||
# of the old version with the new output
|
||||
text = existing_file.read()
|
||||
existing_file.seek(0)
|
||||
# a running record of the current comment block
|
||||
# we're inside, to allow preceeding multi-line comments
|
||||
# to be retained for a translation line
|
||||
latest_comment_block = None
|
||||
for line in existing_file.readlines():
|
||||
line = line.rstrip('\n')
|
||||
if line[:3] == "###":
|
||||
if header_comment is None:
|
||||
# Save header comments
|
||||
header_comment = latest_comment_block or ""
|
||||
# Stip textdomain line
|
||||
tmp_h_c = ""
|
||||
for l in header_comment.split('\n'):
|
||||
if not l.startswith("# textdomain:"):
|
||||
tmp_h_c += l + '\n'
|
||||
header_comment = tmp_h_c
|
||||
|
||||
def generate_template(templ_file):
|
||||
lOut = []
|
||||
for root, dirs, files in os.walk('./'):
|
||||
# Reset comment block if we hit a header
|
||||
latest_comment_block = None
|
||||
continue
|
||||
if line[:1] == "#":
|
||||
# Save the comment we're inside
|
||||
if not latest_comment_block:
|
||||
latest_comment_block = line
|
||||
else:
|
||||
latest_comment_block = latest_comment_block + "\n" + line
|
||||
continue
|
||||
match = pattern_tr.match(line)
|
||||
if match:
|
||||
# this line is a translated line
|
||||
outval = {}
|
||||
outval["translation"] = match.group(2)
|
||||
if latest_comment_block:
|
||||
# if there was a comment, record that.
|
||||
outval["comment"] = latest_comment_block
|
||||
latest_comment_block = None
|
||||
dOut[match.group(1)] = outval
|
||||
return (dOut, text, header_comment)
|
||||
|
||||
# Walks all lua files in the mod folder, collects translatable strings,
|
||||
# and writes it to a template.txt file
|
||||
# Returns a dictionary of localized strings to source file sets
|
||||
# that can be used with the strings_to_text function.
|
||||
def generate_template(folder, mod_name):
|
||||
dOut = {}
|
||||
for root, dirs, files in os.walk(folder):
|
||||
for name in files:
|
||||
if fnmatch.fnmatch(name, "*.lua"):
|
||||
fname = os.path.join(root, name)
|
||||
found = read_lua_file_strings(fname)
|
||||
print(fname, len(found))
|
||||
lOut.extend(found)
|
||||
lOut = list(set(lOut))
|
||||
lOut.sort()
|
||||
gen_template(templ_file, lOut)
|
||||
return lOut
|
||||
if params["verbose"]:
|
||||
print(f"{fname}: {str(len(found))} translatable strings")
|
||||
|
||||
def update_tr_file(lNew, mod_name, tr_file):
|
||||
lOut = ["# textdomain: %s\n" % mod_name]
|
||||
if os.path.exists(tr_file):
|
||||
shutil.copyfile(tr_file, tr_file+".old")
|
||||
dOld = inport_tr_file(tr_file)
|
||||
for key in lNew:
|
||||
val = dOld.get(key, "")
|
||||
lOut.append("%s=%s" % (key, val))
|
||||
lOut.append("##### not used anymore #####")
|
||||
for key in dOld:
|
||||
if key not in lNew:
|
||||
lOut.append("%s=%s" % (key, dOld[key]))
|
||||
open(tr_file, "w").write("\n".join(lOut))
|
||||
for s in found:
|
||||
sources = dOut.get(s, set())
|
||||
sources.add(f"### {os.path.basename(fname)} ###")
|
||||
dOut[s] = sources
|
||||
|
||||
data = generate_template("./locale/template.txt")
|
||||
update_tr_file(data, "techage", "./locale/techage.de.tr")
|
||||
#update_tr_file(data, "techage", "./locale/techage.fr.tr")
|
||||
print("Done.\n")
|
||||
if len(dOut) == 0:
|
||||
return None
|
||||
templ_file = os.path.join(folder, "locale/template.txt")
|
||||
write_template(templ_file, dOut, mod_name)
|
||||
return dOut
|
||||
|
||||
# Updates an existing .tr file, copying the old one to a ".old" file
|
||||
# if any changes have happened
|
||||
# dNew is the data used to generate the template, it has all the
|
||||
# currently-existing localized strings
|
||||
def update_tr_file(dNew, mod_name, tr_file):
|
||||
if params["verbose"]:
|
||||
print(f"updating {tr_file}")
|
||||
|
||||
tr_import = import_tr_file(tr_file)
|
||||
dOld = tr_import[0]
|
||||
textOld = tr_import[1]
|
||||
|
||||
textNew = strings_to_text(dNew, dOld, mod_name, tr_import[2])
|
||||
|
||||
if textOld and textOld != textNew:
|
||||
print(f"{tr_file} has changed.")
|
||||
if not params["no-old-file"]:
|
||||
shutil.copyfile(tr_file, f"{tr_file}.old")
|
||||
|
||||
with open(tr_file, "w", encoding='utf-8') as new_tr_file:
|
||||
new_tr_file.write(textNew)
|
||||
|
||||
# Updates translation files for the mod in the given folder
|
||||
def update_mod(folder):
|
||||
modname = get_modname(folder)
|
||||
if modname is not None:
|
||||
process_po_files(folder, modname)
|
||||
print(f"Updating translations for {modname}")
|
||||
data = generate_template(folder, modname)
|
||||
if data == None:
|
||||
print(f"No translatable strings found in {modname}")
|
||||
else:
|
||||
for tr_file in get_existing_tr_files(folder):
|
||||
update_tr_file(data, modname, os.path.join(folder, "locale/", tr_file))
|
||||
else:
|
||||
print(f"\033[31mUnable to find modname in folder {folder}.\033[0m", file=_stderr)
|
||||
exit(1)
|
||||
|
||||
# Determines if the folder being pointed to is a mod or a mod pack
|
||||
# and then runs update_mod accordingly
|
||||
def update_folder(folder):
|
||||
is_modpack = os.path.exists(os.path.join(folder, "modpack.txt")) or os.path.exists(os.path.join(folder, "modpack.conf"))
|
||||
if is_modpack:
|
||||
subfolders = [f.path for f in os.scandir(folder) if f.is_dir()]
|
||||
for subfolder in subfolders:
|
||||
update_mod(subfolder + "/")
|
||||
else:
|
||||
update_mod(folder)
|
||||
print("Done.")
|
||||
|
||||
def run_all_subfolders(folder):
|
||||
for modfolder in [f.path for f in os.scandir(folder) if f.is_dir()]:
|
||||
update_folder(modfolder + "/")
|
||||
|
||||
|
||||
main()
|
||||
|
@ -385,13 +385,9 @@ minetest.register_node("techage:ta4_icta_controller", {
|
||||
|
||||
on_receive_fields = on_receive_fields,
|
||||
|
||||
on_dig = function(pos, node, puncher, pointed_thing)
|
||||
if minetest.is_protected(pos, puncher:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
techage.remove_node(pos)
|
||||
minetest.node_dig(pos, node, puncher, pointed_thing)
|
||||
after_dig_node = function(pos, oldnode, oldmetadata)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
techage.del_mem(pos)
|
||||
end,
|
||||
|
||||
on_timer = on_timer,
|
||||
|
@ -14,6 +14,8 @@
|
||||
|
||||
local S = techage.S
|
||||
|
||||
techage.display = {}
|
||||
|
||||
local NUM_ROWS = 5
|
||||
local RADIUS = 6
|
||||
local Param2ToFacedir = {[0] = 0, 0, 3, 1, 2, 0}
|
||||
@ -33,7 +35,7 @@ local function lcdlib_bugfix(text_tbl)
|
||||
return ""
|
||||
end
|
||||
|
||||
local function display_update(pos, objref)
|
||||
function techage.display.display_update(pos, objref)
|
||||
pos = vector.round(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local text = lcdlib_bugfix(nvm.text)
|
||||
@ -44,7 +46,7 @@ local function display_update(pos, objref)
|
||||
visual_size = {x=0.94, y=0.94} })
|
||||
end
|
||||
|
||||
local function display_updateXL(pos, objref)
|
||||
function techage.display.display_updateXL(pos, objref)
|
||||
pos = vector.round(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local text = lcdlib_bugfix(nvm.text)
|
||||
@ -55,7 +57,7 @@ local function display_updateXL(pos, objref)
|
||||
visual_size = {x=0.94*1.9, y=0.94} })
|
||||
end
|
||||
|
||||
local function on_timer(pos)
|
||||
function techage.display.on_timer(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.ticks = mem.ticks or 0
|
||||
|
||||
@ -77,7 +79,7 @@ local function on_timer(pos)
|
||||
return true
|
||||
end
|
||||
|
||||
local lcd_box = {
|
||||
techage.display.lcd_box = {
|
||||
type = "wallmounted",
|
||||
wall_top = {-8/16, 15/32, -8/16, 8/16, 8/16, 8/16}
|
||||
}
|
||||
@ -90,13 +92,13 @@ minetest.register_node("techage:ta4_display", {
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
paramtype2 = "wallmounted",
|
||||
node_box = lcd_box,
|
||||
selection_box = lcd_box,
|
||||
node_box = techage.display.lcd_box,
|
||||
selection_box = techage.display.lcd_box,
|
||||
light_source = 6,
|
||||
|
||||
display_entities = {
|
||||
["techage:display_entity"] = { depth = 0.42,
|
||||
on_display_update = display_update},
|
||||
on_display_update = techage.display.display_update},
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
@ -114,7 +116,7 @@ minetest.register_node("techage:ta4_display", {
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
end,
|
||||
|
||||
on_timer = on_timer,
|
||||
on_timer = techage.display.on_timer,
|
||||
on_place = lcdlib.on_place,
|
||||
on_construct = lcdlib.on_construct,
|
||||
on_destruct = lcdlib.on_destruct,
|
||||
@ -124,7 +126,7 @@ minetest.register_node("techage:ta4_display", {
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
})
|
||||
|
||||
local lcd_boxXL = {
|
||||
techage.display.lcd_boxXL = {
|
||||
type = "fixed",
|
||||
fixed = {-0.9, -8/16, -8/16, 0.9, -15/32, 8/16}
|
||||
}
|
||||
@ -137,13 +139,13 @@ minetest.register_node("techage:ta4_displayXL", {
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
paramtype2 = "wallmounted",
|
||||
node_box = lcd_boxXL,
|
||||
selection_box = lcd_boxXL,
|
||||
node_box = techage.display.lcd_boxXL,
|
||||
selection_box = techage.display.lcd_boxXL,
|
||||
light_source = 6,
|
||||
|
||||
display_entities = {
|
||||
["techage:display_entityXL"] = { depth = 0.42,
|
||||
on_display_update = display_updateXL},
|
||||
on_display_update = techage.display.display_updateXL},
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
@ -161,7 +163,7 @@ minetest.register_node("techage:ta4_displayXL", {
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
end,
|
||||
|
||||
on_timer = on_timer,
|
||||
on_timer = techage.display.on_timer,
|
||||
on_place = lcdlib.on_place,
|
||||
on_construct = lcdlib.on_construct,
|
||||
on_destruct = lcdlib.on_destruct,
|
||||
@ -189,7 +191,7 @@ minetest.register_craft({
|
||||
},
|
||||
})
|
||||
|
||||
local function add_line(pos, payload, cycle_time)
|
||||
function techage.display.add_line(pos, payload, cycle_time)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
nvm.text = nvm.text or {}
|
||||
@ -206,7 +208,7 @@ local function add_line(pos, payload, cycle_time)
|
||||
table.insert(nvm.text, payload)
|
||||
end
|
||||
|
||||
local function write_row(pos, payload, cycle_time)
|
||||
function techage.display.write_row(pos, payload, cycle_time)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
nvm.text = nvm.text or {}
|
||||
@ -227,7 +229,7 @@ local function write_row(pos, payload, cycle_time)
|
||||
nvm.text[row] = str
|
||||
end
|
||||
|
||||
local function clear_screen(pos, cycle_time)
|
||||
function techage.display.clear_screen(pos, cycle_time)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.ticks = mem.ticks or 0
|
||||
@ -242,11 +244,11 @@ end
|
||||
techage.register_node({"techage:ta4_display"}, {
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "add" then -- add one line and scroll if necessary
|
||||
add_line(pos, payload, 1)
|
||||
techage.display.add_line(pos, payload, 1)
|
||||
elseif topic == "set" then -- overwrite the given row
|
||||
write_row(pos, payload, 1)
|
||||
techage.display.write_row(pos, payload, 1)
|
||||
elseif topic == "clear" then -- clear the screen
|
||||
clear_screen(pos, 1)
|
||||
techage.display.clear_screen(pos, 1)
|
||||
end
|
||||
end,
|
||||
})
|
||||
@ -254,11 +256,11 @@ techage.register_node({"techage:ta4_display"}, {
|
||||
techage.register_node({"techage:ta4_displayXL"}, {
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "add" then -- add one line and scroll if necessary
|
||||
add_line(pos, payload, 2)
|
||||
techage.display.add_line(pos, payload, 2)
|
||||
elseif topic == "set" then -- overwrite the given row
|
||||
write_row(pos, payload, 2)
|
||||
techage.display.write_row(pos, payload, 2)
|
||||
elseif topic == "clear" then -- clear the screen
|
||||
clear_screen(pos, 2)
|
||||
techage.display.clear_screen(pos, 2)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
@ -13,7 +13,7 @@
|
||||
techage = {}
|
||||
|
||||
-- Version for compatibility checks, see readme.md/history
|
||||
techage.version = 0.23
|
||||
techage.version = 0.25
|
||||
|
||||
if minetest.global_exists("tubelib") then
|
||||
minetest.log("error", "[techage] Techage can't be used together with the mod tubelib!")
|
||||
@ -217,6 +217,8 @@ dofile(MP.."/oil/reboiler.lua")
|
||||
-- TA3 power based
|
||||
dofile(MP.."/ta3_power/tiny_generator.lua")
|
||||
dofile(MP.."/ta3_power/akkubox.lua")
|
||||
dofile(MP.."/ta3_power/axle2power.lua")
|
||||
dofile(MP.."/ta3_power/power2axle.lua")
|
||||
|
||||
-- Digtron
|
||||
if minetest.global_exists("digtron") then
|
||||
|
@ -97,6 +97,7 @@ end
|
||||
|
||||
local function flame(pos, height, heat, first_time)
|
||||
local idx
|
||||
local playername = minetest.get_meta(pos):get_string("playername")
|
||||
pos = {x=pos.x, y=pos.y+height, z=pos.z}
|
||||
for idx=heat,1,-1 do
|
||||
pos = {x=pos.x, y=pos.y+1, z=pos.z}
|
||||
@ -113,6 +114,9 @@ local function flame(pos, height, heat, first_time)
|
||||
end
|
||||
return
|
||||
end
|
||||
if minetest.is_protected(pos, playername) then
|
||||
return
|
||||
end
|
||||
minetest.add_node(pos, {name = "techage:flame"..math.min(idx,7)})
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_int("heat", idx)
|
||||
|
@ -46,7 +46,7 @@ techage.recipes.add("ta4_doser", {
|
||||
|
||||
-- Hydrogenate
|
||||
techage.recipes.add("ta4_doser", {
|
||||
output = "techage:bitumen 2",
|
||||
output = "techage:bitumen 1",
|
||||
input = {
|
||||
"techage:fueloil 1",
|
||||
"techage:hydrogen 1",
|
||||
@ -55,7 +55,7 @@ techage.recipes.add("ta4_doser", {
|
||||
})
|
||||
|
||||
techage.recipes.add("ta4_doser", {
|
||||
output = "techage:fueloil 2",
|
||||
output = "techage:fueloil 1",
|
||||
input = {
|
||||
"techage:naphtha 1",
|
||||
"techage:hydrogen 1",
|
||||
@ -64,7 +64,7 @@ techage.recipes.add("ta4_doser", {
|
||||
})
|
||||
|
||||
techage.recipes.add("ta4_doser", {
|
||||
output = "techage:naphtha 2",
|
||||
output = "techage:naphtha 1",
|
||||
input = {
|
||||
"techage:gasoline 1",
|
||||
"techage:hydrogen 1",
|
||||
|
@ -20,6 +20,7 @@ local Cable = techage.ElectricCable
|
||||
local power = techage.power
|
||||
local Flowers = {}
|
||||
local Plants = {}
|
||||
local Ignore = { ["flowers:waterlily_waving"] = true }
|
||||
-- 9 plant positions below the light
|
||||
local Positions = {
|
||||
{x = 0, y =-1, z = 0},
|
||||
@ -143,16 +144,20 @@ minetest.after(1, function()
|
||||
if name and type(name) == "string" then
|
||||
local mod = string.split(name, ":")[1]
|
||||
if mod == "flowers" or mod == "bakedclay" then -- Bakedclay also registers flowers as decoration.
|
||||
if not Ignore[name] then
|
||||
techage.register_flower(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for name,ndef in pairs(minetest.registered_nodes) do
|
||||
if type(name) == "string" then
|
||||
local mod = string.split(name, ":")[1]
|
||||
if mod == "farming" and ndef.on_timer then -- probably a plant that still needs to grow
|
||||
if not Ignore[name] then
|
||||
techage.register_plant(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
@ -217,6 +217,14 @@ minetest.register_node("techage:ta4_tank", {
|
||||
tubelib2_on_update2 = function(pos, outdir, tlib2, node)
|
||||
liquid.update_network(pos, outdir)
|
||||
end,
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
if fields.public then
|
||||
M(pos):set_int("public", fields.public == "true" and 1 or 0)
|
||||
end
|
||||
end,
|
||||
on_timer = node_timer,
|
||||
on_punch = liquid.on_punch,
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -222,16 +222,17 @@ minetest.register_node("techage:ta3_sequencer", {
|
||||
|
||||
on_receive_fields = on_receive_fields,
|
||||
|
||||
on_dig = function(pos, node, puncher, pointed_thing)
|
||||
can_dig = function(pos, puncher)
|
||||
if minetest.is_protected(pos, puncher:get_player_name()) then
|
||||
return
|
||||
return false
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if not nvm.running then
|
||||
techage.remove_node(pos)
|
||||
minetest.node_dig(pos, node, puncher, pointed_thing)
|
||||
return not nvm.running
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
techage.del_mem(pos)
|
||||
end
|
||||
end,
|
||||
|
||||
on_timer = check_rules,
|
||||
|
@ -15,41 +15,23 @@
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local HELP_TA3 = S("#### TA3 Terminal ####@n"..
|
||||
"@n"..
|
||||
"Send commands to your machines@n"..
|
||||
"and output text messages from your@n"..
|
||||
"machines to the Terminal.@n"..
|
||||
"@n"..
|
||||
"Command syntax:@n"..
|
||||
" cmd <num> <cmnd>@n"..
|
||||
"@n"..
|
||||
"example: cmd 181 on@n"..
|
||||
"<num> is the number of the node to which the command is sent@n"..
|
||||
"'on' is the command to turn machines/nodes on@n"..
|
||||
"Further commands can be retrieved by clicking on@n"..
|
||||
"machines/nodes with the Techage Info Tool.@n"..
|
||||
"@n"..
|
||||
"Local commands:@n"..
|
||||
"- clear = clear screen@n"..
|
||||
"- help = this message@n"..
|
||||
"- pub = switch to public use@n"..
|
||||
"- priv = switch to private use@n"..
|
||||
"To program a user button with a command:@n"..
|
||||
" set <button-num> <button-text> <command>@n"..
|
||||
"e.g. 'set 1 ON cmd 123 on'@n")
|
||||
local HELP_TA3 = "Syntax:\n"..
|
||||
" cmd <num> <cmnd>\n"..
|
||||
"\n"..
|
||||
"like: cmd 181 on\n"..
|
||||
"or: cmd 4573 state\n"..
|
||||
"\n"..
|
||||
"Local commands:\n"..
|
||||
"- clear = clear screen\n"..
|
||||
"- help = this message\n"..
|
||||
"- pub = switch to public use of buttons\n"..
|
||||
"- priv = switch to private use of buttons\n"..
|
||||
"To program a user button with a command:\n"..
|
||||
" set <button-num> <button-text> <command>\n"..
|
||||
"e.g.: set 1 ON cmd 123 on"
|
||||
|
||||
local CMNDS_TA3 = S("Syntax error, try help")
|
||||
|
||||
--local function formspec1()
|
||||
-- return "size[6,4]"..
|
||||
-- default.gui_bg..
|
||||
-- default.gui_bg_img..
|
||||
-- default.gui_slots..
|
||||
-- "field[0.5,1;5,1;number;Techage Controller number:;]" ..
|
||||
-- "button_exit[1.5,2.5;2,1;exit;Save]"
|
||||
--end
|
||||
|
||||
local function get_string(meta, num, default)
|
||||
local s = meta:get_string("bttn_text"..num)
|
||||
if not s or s == "" then
|
||||
@ -106,6 +88,7 @@ end
|
||||
local function command(pos, command, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local owner = meta:get_string("owner") or ""
|
||||
|
||||
if command then
|
||||
command = command:sub(1,80)
|
||||
command = string.trim(command)
|
||||
@ -117,16 +100,15 @@ local function command(pos, command, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("output", HELP_TA3)
|
||||
meta:set_string("formspec", formspec2(meta))
|
||||
elseif command == "pub" and owner == player then
|
||||
elseif command == "pub" then
|
||||
meta:set_int("public", 1)
|
||||
output(pos, player..":$ "..command)
|
||||
output(pos, S("Switched to public use!"))
|
||||
elseif command == "priv" and owner == player then
|
||||
elseif command == "priv" then
|
||||
meta:set_int("public", 0)
|
||||
output(pos, player..":$ "..command)
|
||||
output(pos, S("Switched to private use!"))
|
||||
elseif meta:get_int("public") == 1 or owner == player or
|
||||
minetest.check_player_privs(player, "server") then
|
||||
else
|
||||
output(pos, "$ "..command)
|
||||
local own_num = meta:get_string("node_number")
|
||||
local num, cmnd, payload = command:match('^cmd%s+([0-9]+)%s+(%w+)%s*(.*)$')
|
||||
@ -206,16 +188,25 @@ local function register_terminal(num, tiles, node_box, selection_box)
|
||||
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local public = meta:get_int("public") == 1
|
||||
local protected = minetest.is_protected(pos, player:get_player_name())
|
||||
|
||||
if not protected then
|
||||
local evt = minetest.explode_table_event(fields.output)
|
||||
if evt.type == "DCL" then
|
||||
local s = get_line_text(pos, evt.row)
|
||||
meta:set_string("command", s)
|
||||
meta:set_string("formspec", formspec2(meta))
|
||||
return
|
||||
elseif (fields.key_enter == "true" or fields.ok) and fields.cmnd ~= "" then
|
||||
command(pos, fields.cmnd, player:get_player_name())
|
||||
meta:set_string("command", "")
|
||||
meta:set_string("formspec", formspec2(meta))
|
||||
elseif fields.bttn1 then send_cmnd(pos, meta, 1)
|
||||
return
|
||||
end
|
||||
end
|
||||
if public or not protected then
|
||||
if fields.bttn1 then send_cmnd(pos, meta, 1)
|
||||
elseif fields.bttn2 then send_cmnd(pos, meta, 2)
|
||||
elseif fields.bttn3 then send_cmnd(pos, meta, 3)
|
||||
elseif fields.bttn4 then send_cmnd(pos, meta, 4)
|
||||
@ -225,6 +216,7 @@ local function register_terminal(num, tiles, node_box, selection_box)
|
||||
elseif fields.bttn8 then send_cmnd(pos, meta, 8)
|
||||
elseif fields.bttn9 then send_cmnd(pos, meta, 9)
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata)
|
||||
|
@ -541,13 +541,9 @@ minetest.register_node("techage:ta4_lua_controller", {
|
||||
end
|
||||
end,
|
||||
|
||||
on_dig = function(pos, node, puncher, pointed_thing)
|
||||
if minetest.is_protected(pos, puncher:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
techage.remove_node(pos)
|
||||
minetest.node_dig(pos, node, puncher, pointed_thing)
|
||||
after_dig_node = function(pos, oldnode, oldmetadata)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
techage.del_mem(pos)
|
||||
end,
|
||||
|
||||
on_timer = on_timer,
|
||||
@ -631,7 +627,7 @@ techage.register_node({"techage:ta4_lua_controller"}, {
|
||||
elseif topic == "term" then
|
||||
set_input(pos, number, "term", payload)
|
||||
elseif topic == "msg" then
|
||||
set_input(pos, number, "msg", payload)
|
||||
set_input(pos, number, "msg", {src = src, data = payload})
|
||||
elseif topic == "state" then
|
||||
local running = meta:get_int("running") or STATE_STOPPED
|
||||
return techage.StateStrings[running] or "stopped"
|
||||
|
@ -86,11 +86,14 @@ minetest.register_node("techage:ta4_server", {
|
||||
return
|
||||
end
|
||||
techage.del_mem(pos)
|
||||
techage.remove_node(pos)
|
||||
minetest.node_dig(pos, node, puncher, pointed_thing)
|
||||
end,
|
||||
|
||||
on_timer = function(pos, elasped)
|
||||
after_dig_node = function(pos, oldnode, oldmetadata)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
end,
|
||||
|
||||
on_timer = function(pos, elasped)
|
||||
local meta = M(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.size = nvm.size or 0
|
||||
|
@ -108,7 +108,7 @@ local function command(pos, cmnd, player)
|
||||
if techage.lua_ctlr.not_protected(owner, num) then
|
||||
--output(pos, player..":$ msg "..num.." "..text)
|
||||
output(pos, "> msg "..num.." "..text)
|
||||
techage.send_single(own_number, num, "msg", {src=own_number, text=text})
|
||||
techage.send_single(own_number, num, "msg", text)
|
||||
return
|
||||
end
|
||||
end
|
||||
@ -230,26 +230,31 @@ techage.lua_ctlr.register_action("put_term", {
|
||||
})
|
||||
|
||||
techage.lua_ctlr.register_function("get_msg", {
|
||||
cmnd = function(self)
|
||||
cmnd = function(self, raw)
|
||||
local msg = techage.lua_ctlr.get_msg(self.meta.number)
|
||||
if msg then
|
||||
return msg.src, msg.text
|
||||
local data = msg.data
|
||||
if not raw then
|
||||
data = tostring(data or "")
|
||||
end
|
||||
return msg.src, data
|
||||
end
|
||||
end,
|
||||
help = ' $get_msg() --> number and text string or nil\n'..
|
||||
help = ' $get_msg([raw]) --> number and any value or nil\n'..
|
||||
' If the optional `raw` parameter is not set or false,\n'..
|
||||
' the second return value is guaranteed to be a string.\n'..
|
||||
' Read a received messages. Number is the node\n'..
|
||||
' number of the sender.\n'..
|
||||
' example: num,msg = $get_msg().'
|
||||
})
|
||||
|
||||
techage.lua_ctlr.register_action("send_msg", {
|
||||
cmnd = function(self, num, text)
|
||||
local msg = {src = self.meta.number, text = tostring(text or "")}
|
||||
cmnd = function(self, num, data)
|
||||
if techage.lua_ctlr.not_protected(self.meta.owner, num) then
|
||||
techage.send_single(self.meta.number, num, "msg", msg)
|
||||
techage.send_single(self.meta.number, num, "msg", data)
|
||||
end
|
||||
end,
|
||||
help = " $send_msg(num, text)\n"..
|
||||
help = " $send_msg(num, data)\n"..
|
||||
' Send a message to the controller with number "num".\n'..
|
||||
' example: $send_msg("0123", "test")'
|
||||
})
|
||||
|
@ -70,6 +70,17 @@ Die Antriebsachsen dienen zur Kraftübertragung von der Dampfmaschine zu anderen
|
||||
|
||||
[ta2_driveaxle|image]
|
||||
|
||||
### TA2 Stromgenerator / TA2 Power Generator
|
||||
|
||||
Um Lampen oder andere Stromverbraucher an einer Dampfmaschine betreiben zu können, wird der TA2 Stromgenerator benötigt. Der TA2 Stromgenerator muss auf einer Seite mit Antriebsachsen verbunden werden und liefert dann auf der anderen Seite elektrischen Strom.
|
||||
|
||||
Wird der Stromgenerator nicht mit ausreichend Kraft versorgt, geht er in einen Fehlerzustand und muss über einen Rechtsklick wieder aktiviert werden.
|
||||
|
||||
Das Stromgenerator nimmt primär max. 25 ku an Achsenkraft auf und gibt sekundär max. 24 ku als Strom wieder ab. Er verbraucht also ein ku für die Umwandlung.
|
||||
|
||||
[ta2_generator|image]
|
||||
|
||||
|
||||
|
||||
## Items schieben und sortieren
|
||||
|
||||
@ -107,6 +118,8 @@ Der Verteiler ist in der Lage, die Items aus seinem Inventar sortiert in bis zu
|
||||
|
||||
Der Verteiler besitzt dazu ein Menü mit 4 Filter mit unterschiedlichen Farben, entsprechend den 4 Ausgängen. Soll ein Ausgang genutzt werden, so muss der entsprechende Filter über die "on" Checkbox aktiviert werden. Alle Items, die für diesen Filter konfiguriert sind, werden über den zugeordneten Ausgang ausgegeben. Wird ein Filter aktiviert, ohne das Items konfiguriert werden, so sprechen wir hier von einem "nicht-konfigurierten", offenen Ausgang.
|
||||
|
||||
**Achtung: Der Verteiler ist an seinen Ausgängen gleichzeitig ein Schieber. Daher niemals die Gegenstände mit einem Schieber aus dem Verteiler ziehen!**
|
||||
|
||||
Für einen nicht-konfigurierten Ausgang gibt es zwei Betriebsarten:
|
||||
|
||||
1) Alle Items ausgeben, die an keine anderen Ausgängen ausgegeben werden können, auch wenn diese blockiert sind.
|
||||
|
@ -71,6 +71,18 @@ The drive axles are used to transmit power from the steam engine to other machin
|
||||
|
||||
[ta2_driveaxle|image]
|
||||
|
||||
|
||||
### TA2 Power Generator
|
||||
|
||||
The TA2 Power Generator is required to operate lamps or other power consumers on a steam engine. The TA2 Power Generator has to be connected to drive axles on one side and then supplies electricity on the other side.
|
||||
|
||||
If the Power Generator is not supplied with sufficient power, it goes into an error state and must be reactivated with a right-click.
|
||||
|
||||
The Power Generator takes max. 25 ku of axle power and provides on the other side max. 24 ku as electricity. So he consumes one ku for the conversion.
|
||||
|
||||
[ta2_generator|image]
|
||||
|
||||
|
||||
## Push and sort items
|
||||
|
||||
In order to transport objects from one processing station to the next, pushers and tubes are used. See plan.
|
||||
@ -107,6 +119,8 @@ The distributor is able to transport the items from his inventory sorted in up t
|
||||
|
||||
The distributor has a menu with 4 filters with different colors, corresponding to the 4 outputs. If an output is to be used, the corresponding filter must be activated via the "on" checkbox. All items that are configured for this filter are output via the assigned output. If a filter is activated without items being configured, we are talking about an "unconfigured", open output.
|
||||
|
||||
**Attention: The distributor is also a pusher at its output sides. Therefore, never pull items out of the distributor with a pusher!**
|
||||
|
||||
There are two operating modes for a non-configured output:
|
||||
|
||||
1) Output all items that cannot be output to any other exit, even if they are blocked.
|
||||
|
@ -198,6 +198,27 @@ In der unteren Hälfte werden die Daten aller Generatoren und Speichersystemen d
|
||||
[ta3_powerterminal|image]
|
||||
|
||||
|
||||
### TA3 Elektromotor / TA3 Electric Motor
|
||||
|
||||
Um TA2 Maschinen über das Stromnetz betreiben zu können, wird der TA3 Elektromotor benötigt. Dieser wandelt Strom in Achsenkraft um.
|
||||
Wird der Elektromotor nicht mit ausreichend Strom versorgt, geht er in einen Fehlerzustand und muss über einen Rechtsklick wieder aktiviert werden.
|
||||
|
||||
Das Elektromotor nimmt primär max. 40 ku an Strom auf und gibt sekundär max. 39 ku als Achsenkraft wieder ab. Er verbraucht also ein ku für die Umwandlung.
|
||||
|
||||
[ta3_motor|image]
|
||||
|
||||
|
||||
### TA3 Strom Terminal / Power Terminal
|
||||
|
||||
Das Strom-Terminal muss mit dem Stromnetz verbunden werden. Es zeigt Daten aus dem Stromnetz an.
|
||||
|
||||
In der oberen Hälfte werden nur die Daten eines ausgewählten Typs ausgegeben. Wird als Typ bspw. "Kraftwerk" gewählt, so werden nur die Daten von Öl- und Kohlekraftwerken gesammelt und ausgegeben. Links werden die Daten von Generatoren (Stromabgabe) und rechts die Daten von Energiespeichern (Stromaufnahme) ausgegeben. Beim Akkublocks bspw. wird beides ausgegeben, da der Akku Strom aufnehmen und abgeben kann.
|
||||
|
||||
In der unteren Hälfte werden die Daten aller Generatoren und Speichersystemen des ganzen Stromnetzen zusammengefasst ausgegeben.
|
||||
|
||||
[ta3_powerterminal|image]
|
||||
|
||||
|
||||
## TA3 Industrieofen
|
||||
|
||||
Der TA3 Industrieofen dient als Ergänzung zu normalen Ofen (furnace). Damit können alle Waren mit "Koch" Rezepten, auch im Industrieofen hergestellt werden. Es gibt aber auch spezielle Rezepte, die nur im Industrieofen hergestellt werden können.
|
||||
@ -569,7 +590,7 @@ Das Terminal besitzt folgende, lokalen Kommandos:
|
||||
- `pub` schalte in den öffentlichen Modus um
|
||||
- `priv` schalte in den privaten Modus um
|
||||
|
||||
Im privaten Modul kann nur der Besitzer selbst Kommandos eingeben oder Tasten nutzen.
|
||||
Im privaten Modus (private) kann das Terminal nur von Spielern verwendet werden, die an diesem Ort bauen können, also Protection Rechte besitzen. Im öffentlichen Modus (public) können alle Spieler die vorkonfigurierten Tasten verwenden.
|
||||
|
||||
[ta3_terminal|image]
|
||||
|
||||
|
@ -198,6 +198,18 @@ In the lower half, the data of all generators and storage systems of the entire
|
||||
[ta3_powerterminal|image]
|
||||
|
||||
|
||||
### TA3 Electric Motor
|
||||
|
||||
The TA3 Electric Motor is required in order to be able to operate TA2 machines via the power grid. The TA3 Electric Motor converts electricity into axle power.
|
||||
If the electric motor is not supplied with sufficient power, it goes into an fault state and must be reactivated with a right-click.
|
||||
|
||||
The electric motor takes max. 40 ku of electricity and provides on the other side max. 39 ku as axle power. So he consumes one ku for the conversion.
|
||||
|
||||
[ta3_motor|image]
|
||||
|
||||
|
||||
|
||||
|
||||
## TA3 Industrial Furnace
|
||||
|
||||
The TA3 industrial furnace serves as a supplement to normal furnaces. This means that all goods can be produced with "cooking" recipes, even in an industrial furnace. But there are also special recipes that can only be made in an industrial furnace.
|
||||
@ -567,7 +579,9 @@ The terminal has the following local commands:
|
||||
- `pub` switch to public mode
|
||||
- `priv` switch to private mode
|
||||
|
||||
In the private mode, only the owner can enter commands himself or use keys.
|
||||
In private mode, the terminal can only be used by players who can build at this location, i.e. who have protection rights.
|
||||
|
||||
In public mode, all players can use the preconfigured keys.
|
||||
|
||||
[ta3_terminal|image]
|
||||
|
||||
|
@ -7,10 +7,11 @@ Regenerative Energiequellen wie Wind, Sonne und Biokraft helfen dir, das Ölzeit
|
||||
|
||||
## Windkraftanlage
|
||||
|
||||
Eine Windkraftanlagen liefern immer dann Strom, wenn Wind vorhanden ist. Im Spiel gibt es keinen Wind, aber die Mod simuliert dies dadurch, dass sich nur morgens (5:00 - 9:00) und abends (17:00 - 21:00) die Windräder drehen und damit Strom liefern, sofern diese an geeigneten Stellen errichtet werden.
|
||||
Eine Windkraftanlage liefern immer dann Strom, wenn Wind vorhanden ist. Im Spiel gibt es keinen Wind, aber die Mod simuliert dies dadurch, dass sich nur morgens (5:00 - 9:00) und abends (17:00 - 21:00) die Windräder drehen. Eine Windkraftanlage liefert nur dann Strom, wenn sie an einer geeigneten Stelle aufgestellt ist.
|
||||
|
||||
Die TA Windkraftanlagen sind reine Offshore Anlagen, das heißt, die müssen im Meer (Wasser) errichtet werden. Dies bedeutet, dass um den Mast herum mit einem Abstand von 20 Blöcken nur Wasser sein darf und das mindestens 2 Blöcke tief.
|
||||
Der Rotor muss in einer Höhe (Y-Koordinate) von 12 bis maximal 20 m platziert werden. Der Abstand zu weiteren Windkraftanlagen muss mindestens 14 m betragen.
|
||||
Die TA Windkraftanlagen sind reine Offshore Anlagen, das heißt, die müssen im Meer errichtet werden. Dies bedeutet, dass Windkraftanlagen nur in einem Meer (occean) Biom errichtet werden können und dass um den Mast herum ausreichend Wasser und freie Sicht vorhanden sein müssen.
|
||||
|
||||
Um eine geeignete Stelle zu finden, musst du mit dem Schraubenschlüssel (TechAge Info Werkzeug) auf das Wasser klicken. Ob diese Stelle für den Mast der Windkraftanlage geeignet ist, wird dir als Chat Nachricht angezeigt.
|
||||
|
||||
Der Strom muss vom Rotor-Block durch den Mast nach unten geführt werden. Dazu zuerst die Stromleitung nach oben ziehen und das Stromkabel dann mit TA4 Säulenblöcke "verputzen". Unten kann eine Arbeitsplattform errichtet werden. Der Plan rechts zeigt den Aufbau im oberen Teil.
|
||||
|
||||
@ -390,9 +391,9 @@ Die TA4 Sensor Kiste dient zum Aufbau von Automatischen Lagern oder Verkaufsauto
|
||||
Wird etwas in die Kiste gelegt, oder entnommen, oder eine der Tasten "F1"/"F2" gedrückt, so wird ein Event-Signal an den Lua Controller gesendet.
|
||||
Die Sensor Kiste unterstützt folgende Kommandos:
|
||||
|
||||
- Über `state = $read_data(<num>, "state")` kann der Status der Kiste abgefragt werden. Mögliche Antworten sind: "empty", "loaded", "full"
|
||||
- Über `name, action = $read_data(<num>, "action")` kann die letzte Spieleraktion abgefragt werden. `name` ist der Spielername, Als `action` wird zurückgeliefert: "put", "take", "f1", "f2".
|
||||
- Über `stacks = $read_data(<num>, "stacks")` kann der Inhalt der Kiste ausgelesen werden. Siehe dazu: https://github.com/joe7575/techage/blob/master/manuals/ta4_lua_controller_EN.md#sensor-chest
|
||||
- Über `state = $send_cmnd(<num>, "state")` kann der Status der Kiste abgefragt werden. Mögliche Antworten sind: "empty", "loaded", "full"
|
||||
- Über `name, action = $send_cmnd(<num>, "action")` kann die letzte Spieleraktion abgefragt werden. `name` ist der Spielername, Als `action` wird zurückgeliefert: "put", "take", "f1", "f2".
|
||||
- Über `stacks = $send_cmnd(<num>, "stacks")` kann der Inhalt der Kiste ausgelesen werden. Siehe dazu: https://github.com/joe7575/techage/blob/master/manuals/ta4_lua_controller_EN.md#sensor-chest
|
||||
- Über `$send_cmnd(<num>, "text", "press both buttons and\nput something into the chest")` kann der Text im Menü der Sensor Kiste gesetzt werden.
|
||||
|
||||
Über die Checkbox "Erlaube öffentlichen Zugriff" kann eingestellt werden, ob die Kiste von jedem genutzt werden darf, oder nur von Spielern die hier Zugriffsrechte haben.
|
||||
@ -596,8 +597,8 @@ Die Kiste kann nur von den Spielern genutzt werden, die an diesem Ort auch bauen
|
||||
Der Kiste besitzt ein zusätzliches Kommandos für den Lua Controller:
|
||||
|
||||
- `count` dient zur Anfrage, wie viele Items in der Kiste sind.
|
||||
Beispiel 1: `$read_data(CHEST, "count")` --> Summe der Items über alle 8 Speicher
|
||||
Beispiel 2: `$read_data(CHEST, "count", 2)` --> Anzahl der Items in Speicher 2 (zweiter von links)
|
||||
Beispiel 1: `$send_cmnd(CHEST, "count")` --> Summe der Items über alle 8 Speicher
|
||||
Beispiel 2: `$send_cmnd(CHEST, "count", 2)` --> Anzahl der Items in Speicher 2 (zweiter von links)
|
||||
|
||||
[ta4_8x2000_chest|image]
|
||||
|
||||
|
@ -7,10 +7,11 @@ Renewable energy sources such as wind, sun and biofuels help you to leave the oi
|
||||
|
||||
## Wind Turbine
|
||||
|
||||
A wind turbine always delivers electricity when there is wind. There is no wind in the game, but the mod simulates this by only turning the wind turbines in the morning (5:00 a.m. - 9:00 a.m.) and in the evening (5:00 p.m. - 9:00 p.m.) and thus supplying electricity, provided they are positioned appropriately.
|
||||
A wind turbine always supplies electricity when there is wind. There is no wind in the game, but the mod simulates this by turning the wind turbines only in the morning (5:00 - 9:00) and in the evening (17:00 - 21:00). A wind turbine only supplies electricity if it is set up in a suitable location.
|
||||
|
||||
The TA wind turbines are pure offshore plants, which means that they have to be installed in the sea (water). This means that there must be in the minimum 20 blocks of water around the mast and at least 2 blocks deep.
|
||||
The rotor must be placed at a height (Y coordinate) of 12 to a maximum of 20 m. The distance to other wind turbines must be at least 14 m.
|
||||
The TA wind power plants are pure offshore plants, which means that they have to be built in the sea. This means that wind turbines can only be build in a sea (occean) biome and that there must be sufficient water and a clear view around the mast.
|
||||
|
||||
To find a suitable spot, click on the water with the wrench (TechAge Info Tool). A chat message will show you whether this position is suitable for the mast of the wind turbine.
|
||||
|
||||
The current must be led from the rotor block down through the mast. First pull the power line up and then "plaster" the power cable with TA4 pillar blocks. A work platform can be built below. The plan on the right shows the structure in the upper part.
|
||||
|
||||
@ -392,9 +393,9 @@ The TA4 sensor box is used to set up automatic warehouses or vending machines in
|
||||
If something is put into the box or removed, or one of the "F1" / "F2" keys is pressed, an event signal is sent to the Lua controller.
|
||||
The sensor box supports the following commands:
|
||||
|
||||
- The status of the box can be queried via `state = $read_data(<num>, "state")`. Possible answers are: "empty", "loaded", "full"
|
||||
- The last player action can be queried via `name, action = $read_data(<num>, "action")`. `name` is the player name. One of the following is returned as `action`: "put", "take", "f1", "f2".
|
||||
- The contents of the box can be read out via `stacks = $read_data(<num>, "stacks")`. See: https://github.com/joe7575/techage/blob/master/manuals/ta4_lua_controller_EN.md#sensor-chest
|
||||
- The status of the box can be queried via `state = $send_cmnd(<num>, "state")`. Possible answers are: "empty", "loaded", "full"
|
||||
- The last player action can be queried via `name, action = $send_cmnd(<num>, "action")`. `name` is the player name. One of the following is returned as `action`: "put", "take", "f1", "f2".
|
||||
- The contents of the box can be read out via `stacks = $send_cmnd(<num>, "stacks")`. See: https://github.com/joe7575/techage/blob/master/manuals/ta4_lua_controller_EN.md#sensor-chest
|
||||
- Via `$send_cmnd(<num>, "text", "press both buttons and\nput something into the chest")` the text can be set in the menu of the sensor box.
|
||||
|
||||
The checkbox "Allow public chest access" can be used to set whether the box can be used by everyone or only by players who have access/protection rights here.
|
||||
@ -579,7 +580,7 @@ The TA4 8x2000 chest does not have a normal inventory like other chest, but has
|
||||
|
||||
If the chest is filled with a pusher, all stores fill from left to right. If all 8 stores are full and no further items can be added, further items are rejected.
|
||||
|
||||
** Row function **
|
||||
**Row function**
|
||||
|
||||
Several TA4 8x2000 chests can be connected to a large chest with more content. To do this, the chests must be placed in a row one after the other.
|
||||
|
||||
@ -597,8 +598,8 @@ The chest can only be used by players who can build at this location, i.e. who h
|
||||
The chest has an additional command for the Lua controller:
|
||||
|
||||
- `count` is used to request how many items are in the chest.
|
||||
Example 1: `$read_data(CHEST, "count")` -> Sum of items across all 8 stores
|
||||
Example 2: `$read_data(CHEST, "count", 2)` -> number of items in store 2 (second from left)
|
||||
Example 1: `$send_cmnd(CHEST, "count")` -> Sum of items across all 8 stores
|
||||
Example 2: `$send_cmnd(CHEST, "count", 2)` -> number of items in store 2 (second from left)
|
||||
|
||||
[ta4_8x2000_chest|image]
|
||||
|
||||
|
@ -106,7 +106,7 @@ class MyRenderer(mistune.Renderer):
|
||||
##
|
||||
def block_code(self, code, lang):
|
||||
text = formspec_escape(code.strip())
|
||||
lines = text.split("\n")
|
||||
lines = text.split("\\n")
|
||||
lines = [" " + item for item in lines]
|
||||
self.TextChunck.extend(lines)
|
||||
self.TextChunck.append("")
|
||||
|
@ -346,10 +346,16 @@ In addition to Lua standard function the Lua Controller provides the following f
|
||||
|
||||
### Techage Command Functions
|
||||
|
||||
* `$read_data(num, ident, add_data)` - Read any kind of data from another block with the given number _num_.
|
||||
_ident_ specifies the data to be read.
|
||||
_add_data_ is for additional data and normally not needed.
|
||||
The result is block dependent (see table below):
|
||||
With the `$send_cmnd(num, ident, add_data)` function, you can send commands to and retrieve data from another block with the given number _num_.
|
||||
The possible commands can be classified in two groups: Commands for reading data and commands for triggering an action.
|
||||
Please note, that this is not a technical distinction, only a logical.
|
||||
|
||||
**Reading data**
|
||||
|
||||
- _ident_ specifies the data to be read.
|
||||
- _add_data_ is for additional data and normally not needed.
|
||||
- The result is block dependent (see table below)
|
||||
|
||||
|
||||
| ident | returned data | comment |
|
||||
| ------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
||||
@ -358,18 +364,22 @@ In addition to Lua standard function the Lua Controller provides the following f
|
||||
| "state" | one of: "empty", "loaded", "full" | State of a chest or Sensor Chest |
|
||||
| "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 = $read_data("223", "load") |
|
||||
| "load" | number | Read the load value in percent (0..100) of a tank, silo, accu, or battery block, or from the Signs Bot Box. Silo and tank return two values: The percentage value and the absolute value in units.<br /> Example: percent, absolute = $send_cmnd("223", "load") |
|
||||
| "delivered" | number | Read the current delivered power value of a generator block. A power consuming block (accu) provides a negative value |
|
||||
| "action" | player-name, action-string | only for Sensor Chests |
|
||||
| "stacks" | Array with up to 4 Stores with the inventory content (see example) | only for Sensor Chests |
|
||||
| "action" | player-name, action-string | Only for Sensor Chests |
|
||||
| "stacks" | Array with up to 4 Stores with the inventory content (see example) | Only for Sensor Chests |
|
||||
| "count" | number | Read the item counter of the TA4 Item Detector block |
|
||||
| "count" | number of items | Read the total amount of TA4 chest items. An optional number as `add_data` is used to address only one inventory slot (1..8, from left to right). |
|
||||
| "itemstring" | item string of the given slot | Specific command for the TA4 8x2000 Chest to read the item type (technical name) of one chest slot, specified via `add_data` (1..8).<br />Example: s = $read_data("223", "itemstring", 1) |
|
||||
| "itemstring" | item string of the given slot | Specific command for the TA4 8x2000 Chest to read the item type (technical name) of one chest slot, specified via `add_data` (1..8).<br />Example: s = $send_cmnd("223", "itemstring", 1) |
|
||||
| "output" | recipe output string, <br />e.g.: "default:glass" | Only for the Industrial Furnace. If no recipe is active, the command returns "unknown" |
|
||||
|
||||
|
||||
|
||||
**Trigger an action**
|
||||
|
||||
* `$send_cmnd(num, cmnd, data)` - Send a command to another block. _num_ is the number of the remote block, like "1234". _cmnd_ is the command, _data_ is additional data (see table below):
|
||||
- _num_ is the number of the remote block, like "1234"
|
||||
- _cmnd_ is the command
|
||||
- _data_ is additional data (see table below)
|
||||
|
||||
| cmnd | data | comment |
|
||||
| -------------------------------- | ------------ | ------------------------------------------------------------ |
|
||||
@ -406,11 +416,10 @@ In contrast the Controller can send text strings to the terminal.
|
||||
|
||||
### Further Functions
|
||||
|
||||
Messages are used to transport data between Controllers. Messages are text strings or any other data. Incoming messages are stored in order (up to 10) and can be read one after the other.
|
||||
* `$get_msg()` - Read a received message. The function returns the sender number and the message. (see example "Emails")
|
||||
Messages are used to transport data between Controllers. Messages can contain arbitrary data. Incoming messages are stored in order (up to 10) and can be read one after the other.
|
||||
* `$get_msg([raw])` - Read a received message. The function returns the sender number and the message. (see example "Emails"). If the _raw_ parameter is not set or false, the message is guaranteed to be a string.
|
||||
* `$send_msg(num, msg)` - Send a message to another Controller. _num_ is the destination number. (see example "Emails")
|
||||
|
||||
|
||||
* `$chat(text)` - Send yourself a chat message. _text_ is a text string.
|
||||
|
||||
* `$door(pos, text)` - Open/Close a door at position "pos".
|
||||
@ -419,7 +428,7 @@ Messages are used to transport data between Controllers. Messages are text strin
|
||||
|
||||
* `$item_description("default:apple")`
|
||||
Get the description (item name) for a specified itemstring, e. g. determined via the TA4 8x2000 Chest command `itemstring`:
|
||||
`str = $read_data("223", "itemstring", 1)`
|
||||
`str = $send_cmnd("223", "itemstring", 1)`
|
||||
`descr = $item_description(str)`
|
||||
|
||||
|
||||
@ -504,15 +513,15 @@ if ticks % 60 == 0 then
|
||||
$display(DISPLAY, 1, min.." min")
|
||||
|
||||
-- Cactus chest overrun
|
||||
sts = $read_data("1034", "state") -- read pusher status
|
||||
sts = $send_cmnd("1034", "state") -- read pusher status
|
||||
if sts == "blocked" then $display(DISPLAY, 2, "Cactus full") end
|
||||
|
||||
-- Tree chest overrun
|
||||
sts = $read_data("1065", "state") -- read pusher status
|
||||
sts = $send_cmnd("1065", "state") -- read pusher status
|
||||
if sts == "blocked" then $display(DISPLAY, 3, "Tree full") end
|
||||
|
||||
-- Furnace fuel empty
|
||||
sts = $read_data("1544", "state") -- read pusher status
|
||||
sts = $send_cmnd("1544", "state") -- read pusher status
|
||||
if sts == "standby" then $display(DISPLAY, 4, "Furnace fuel") end
|
||||
end
|
||||
```
|
||||
@ -570,7 +579,7 @@ loop() code:
|
||||
|
||||
```lua
|
||||
if event then
|
||||
name = $read_data(SENSOR, "name")
|
||||
name = $send_cmnd(SENSOR, "name")
|
||||
if name == "" then -- no player arround
|
||||
$clear_screen(DISPLAY)
|
||||
else
|
||||
@ -602,13 +611,13 @@ loop() code:
|
||||
```lua
|
||||
if event and $get_input(SENSOR) == "on" then
|
||||
-- read inventory state
|
||||
state = $read_data(SENSOR, "state")
|
||||
state = $send_cmnd(SENSOR, "state")
|
||||
$print("state: "..state)
|
||||
-- read player name and action
|
||||
name, action = $read_data(SENSOR, "action")
|
||||
name, action = $send_cmnd(SENSOR, "action")
|
||||
$print("action"..": "..name.." "..action)
|
||||
-- read inventory content
|
||||
stacks = $read_data(SENSOR, "stacks")
|
||||
stacks = $send_cmnd(SENSOR, "stacks")
|
||||
for i,stack in stacks.next() do
|
||||
$print("stack: "..stack.get("name").." "..stack.get("count"))
|
||||
end
|
||||
|
Binary file not shown.
@ -27,6 +27,7 @@
|
||||
- [TA2 Schwungrad / Flywheel](./manual_ta2_DE.md#ta2-schwungrad--flywheel)
|
||||
- [TA2 Dampfleitungen / Steam Pipe](./manual_ta2_DE.md#ta2-dampfleitungen--steam-pipe)
|
||||
- [TA2 Antriebsachsen / TA2 Drive Axle](./manual_ta2_DE.md#ta2-antriebsachsen--ta2-drive-axle)
|
||||
- [TA2 Stromgenerator / TA2 Power Generator](./manual_ta2_DE.md#ta2-stromgenerator--ta2-power-generator)
|
||||
- [Items schieben und sortieren](./manual_ta2_DE.md#items-schieben-und-sortieren)
|
||||
- [Röhren / TechAge Tube](./manual_ta2_DE.md#röhren--techage-tube)
|
||||
- [TA2 Schieber / Pusher](./manual_ta2_DE.md#ta2-schieber--pusher)
|
||||
@ -44,10 +45,10 @@
|
||||
- [TA2 Flüssigkeitensammler / Liquid Sampler](./manual_ta2_DE.md#ta2-flüssigkeitensammler--liquid-sampler)
|
||||
- [TA2 Gesicherte Kiste / Protected Chest](./manual_ta2_DE.md#ta2-gesicherte-kiste--protected-chest)
|
||||
- [Techage Forceload Block](./manual_ta2_DE.md#techage-forceload-block)
|
||||
- [TA3: Ölzeitalter](./manual_ta3_DE.md#ta3:-ölzeitalter)
|
||||
- [Kohlekraftwerk / Ölkraftwerk](./manual_ta3_DE.md#kohlekraftwerk--ölkraftwerk)
|
||||
- [TA3: Ölzeitalter](./manual_ta3_DE.md#ta3:-Ölzeitalter)
|
||||
- [Kohlekraftwerk / Ölkraftwerk](./manual_ta3_DE.md#kohlekraftwerk--Ölkraftwerk)
|
||||
- [TA3 Kraftwerks-Feuerbox / Power Station Firebox](./manual_ta3_DE.md#ta3-kraftwerks-feuerbox--power-station-firebox)
|
||||
- [TA3 Kraftwerks-Ölbrenner / TA3 Power Station Oil Burner](./manual_ta3_DE.md#ta3-kraftwerks-ölbrenner--ta3-power-station-oil-burner)
|
||||
- [TA3 Kraftwerks-Ölbrenner / TA3 Power Station Oil Burner](./manual_ta3_DE.md#ta3-kraftwerks-Ölbrenner--ta3-power-station-oil-burner)
|
||||
- [TA3 Boiler unten/oben](./manual_ta3_DE.md#ta3-boiler-untenoben)
|
||||
- [TA3 Turbine](./manual_ta3_DE.md#ta3-turbine)
|
||||
- [TA3 Generator](./manual_ta3_DE.md#ta3-generator)
|
||||
@ -65,8 +66,10 @@
|
||||
- [TA3 Kleiner Stromgenerator / Tiny Power Generator](./manual_ta3_DE.md#ta3-kleiner-stromgenerator--tiny-power-generator)
|
||||
- [TA3 Akku Block / Akku Box](./manual_ta3_DE.md#ta3-akku-block---akku-box)
|
||||
- [TA3 Strom Terminal / Power Terminal](./manual_ta3_DE.md#ta3-strom-terminal--power-terminal)
|
||||
- [TA3 Elektromotor / TA3 Electric Motor](./manual_ta3_DE.md#ta3-elektromotor--ta3-electric-motor)
|
||||
- [TA3 Strom Terminal / Power Terminal](./manual_ta3_DE.md#ta3-strom-terminal--power-terminal)
|
||||
- [TA3 Industrieofen](./manual_ta3_DE.md#ta3-industrieofen)
|
||||
- [TA3 Ofen-Ölbrenner / Furnace Oil Burner](./manual_ta3_DE.md#ta3-ofen-ölbrenner--furnace-oil-burner)
|
||||
- [TA3 Ofen-Ölbrenner / Furnace Oil Burner](./manual_ta3_DE.md#ta3-ofen-Ölbrenner--furnace-oil-burner)
|
||||
- [TA3 Ofenoberteil / Furnace Top](./manual_ta3_DE.md#ta3-ofenoberteil--furnace-top)
|
||||
- [TA3 Gebläse / Booster](./manual_ta3_DE.md#ta3-gebläse--booster)
|
||||
- [Flüssigkeiten](./manual_ta3_DE.md#flüssigkeiten)
|
||||
@ -76,18 +79,18 @@
|
||||
- [TA4 Röhre / Pipe](./manual_ta3_DE.md#ta4-röhre--pipe)
|
||||
- [TA3 Rohr/Wanddurchbruch / TA3 Pipe Wall Entry Blöcke](./manual_ta3_DE.md#ta3-rohrwanddurchbruch--ta3-pipe-wall-entry-blöcke)
|
||||
- [TA Ventil / TA Valve](./manual_ta3_DE.md#ta-ventil--ta-valve)
|
||||
- [Öl-Förderung](./manual_ta3_DE.md#öl-förderung)
|
||||
- [TA3 Ölexplorer / Oil Explorer](./manual_ta3_DE.md#ta3-ölexplorer--oil-explorer)
|
||||
- [TA3 Ölbohrkiste / Oil Drill Box](./manual_ta3_DE.md#ta3-ölbohrkiste--oil-drill-box)
|
||||
- [TA3 Ölpumpe / Oil Pumpjack](./manual_ta3_DE.md#ta3-ölpumpe--oil-pumpjack)
|
||||
- [Öl-Förderung](./manual_ta3_DE.md#Öl-förderung)
|
||||
- [TA3 Ölexplorer / Oil Explorer](./manual_ta3_DE.md#ta3-Ölexplorer--oil-explorer)
|
||||
- [TA3 Ölbohrkiste / Oil Drill Box](./manual_ta3_DE.md#ta3-Ölbohrkiste--oil-drill-box)
|
||||
- [TA3 Ölpumpe / Oil Pumpjack](./manual_ta3_DE.md#ta3-Ölpumpe--oil-pumpjack)
|
||||
- [TA3 Bohrgestänge / Drill Pipe](./manual_ta3_DE.md#ta3-bohrgestänge--drill-pipe)
|
||||
- [Öltank / Oil Tank](./manual_ta3_DE.md#öltank--oil-tank)
|
||||
- [Öl-Transport](./manual_ta3_DE.md#öl-transport)
|
||||
- [Öl-Transport mit dem Tankwagen](./manual_ta3_DE.md#öl-transport-mit-dem-tankwagen)
|
||||
- [Öl-Transport mit Fässern über Minecarts](./manual_ta3_DE.md#öl-transport-mit-fässern-über-minecarts)
|
||||
- [Öltank / Oil Tank](./manual_ta3_DE.md#Öltank--oil-tank)
|
||||
- [Öl-Transport](./manual_ta3_DE.md#Öl-transport)
|
||||
- [Öl-Transport mit dem Tankwagen](./manual_ta3_DE.md#Öl-transport-mit-dem-tankwagen)
|
||||
- [Öl-Transport mit Fässern über Minecarts](./manual_ta3_DE.md#Öl-transport-mit-fässern-über-minecarts)
|
||||
- [Tankwagen / Tank Cart](./manual_ta3_DE.md#tankwagen--tank-cart)
|
||||
- [Kistenwagen / Chest Cart](./manual_ta3_DE.md#kistenwagen--chest-cart)
|
||||
- [Öl-Verarbeitung](./manual_ta3_DE.md#öl-verarbeitung)
|
||||
- [Öl-Verarbeitung](./manual_ta3_DE.md#Öl-verarbeitung)
|
||||
- [Destillationsturm / distiller tower](./manual_ta3_DE.md#destillationsturm--distiller-tower)
|
||||
- [Aufkocher / reboiler)](./manual_ta3_DE.md#aufkocher--reboiler))
|
||||
- [Logik-/Schalt-Blöcke](./manual_ta3_DE.md#logik-schalt-blöcke)
|
||||
|
@ -27,6 +27,7 @@
|
||||
- [TA2 Flywheel](./manual_ta2_EN.md#ta2-flywheel)
|
||||
- [TA2 Steam Pipes](./manual_ta2_EN.md#ta2-steam-pipes)
|
||||
- [TA2 Drive Axle / TA2 Gearbox](./manual_ta2_EN.md#ta2-drive-axle--ta2-gearbox)
|
||||
- [TA2 Power Generator](./manual_ta2_EN.md#ta2-power-generator)
|
||||
- [Push and sort items](./manual_ta2_EN.md#push-and-sort-items)
|
||||
- [TechAge Tube](./manual_ta2_EN.md#techage-tube)
|
||||
- [TA2 Pusher](./manual_ta2_EN.md#ta2-pusher)
|
||||
@ -65,6 +66,7 @@
|
||||
- [TA3 Small Power Generator](./manual_ta3_EN.md#ta3-small-power-generator)
|
||||
- [TA3 Battery Block](./manual_ta3_EN.md#ta3-battery-block)
|
||||
- [TA3 Power Terminal](./manual_ta3_EN.md#ta3-power-terminal)
|
||||
- [TA3 Electric Motor](./manual_ta3_EN.md#ta3-electric-motor)
|
||||
- [TA3 Industrial Furnace](./manual_ta3_EN.md#ta3-industrial-furnace)
|
||||
- [TA3 Furnace Oil Burner](./manual_ta3_EN.md#ta3-furnace-oil-burner)
|
||||
- [TA3 Furnace Top](./manual_ta3_EN.md#ta3-furnace-top)
|
||||
|
@ -27,7 +27,7 @@ local function start_consumer(tbl, tlib_type)
|
||||
if def and def["cstate"] == NOPOWER and (def["calive"] or 0) > 0 then
|
||||
local ndef = net_def(v.pos, tlib_type)
|
||||
def["cstate"] = RUNNING
|
||||
def["taken"] = v.nominal or 0
|
||||
def["taken"] = v.nominal or def.curr_power or 0
|
||||
if ndef.on_power then
|
||||
ndef.on_power(v.pos, tlib_type)
|
||||
end
|
||||
@ -73,10 +73,10 @@ local function get_consumer_sum(tbl, tlib_type, cycle_time)
|
||||
if def and def["cstate"] ~= STOPPED then
|
||||
def["calive"] = (def["calive"] or 1) - cycle_time/2
|
||||
if def["calive"] >= 0 then
|
||||
sum = sum + v.nominal
|
||||
sum = sum + (v.nominal or def.curr_power or 0)
|
||||
end
|
||||
end
|
||||
--print(N(v.pos), P2S(v.pos), def["cstate"], def["calive"])
|
||||
--print(N(v.pos), P2S(v.pos), def["cstate"], def["calive"], sum)
|
||||
end
|
||||
return sum
|
||||
end
|
||||
@ -155,7 +155,7 @@ function techage.power.get_con1_sum(network, tlib_type)
|
||||
local nvm = techage.get_nvm(v.pos)
|
||||
local def = nvm[tlib_type] -- power related network data
|
||||
if def and def["cstate"] ~= STOPPED then
|
||||
sum = sum + v.nominal
|
||||
sum = sum + (v.nominal or def.curr_power or 0)
|
||||
end
|
||||
end
|
||||
return sum
|
||||
|
@ -48,11 +48,24 @@ function techage.power.formspec_power_bar(max_power, current_power)
|
||||
return "techage_form_level_bg.png^[lowpart:"..percent..":techage_form_level_fg.png"
|
||||
end
|
||||
|
||||
function techage.power.formspec_label_bar(x, y, label, max_power, current_power, unit)
|
||||
function techage.power.formspec_label_bar(pos, x, y, label, max_power, current_power, unit)
|
||||
local percent, ypos
|
||||
current_power = current_power or 0
|
||||
|
||||
max_power = max_power or 1
|
||||
unit = unit or "ku"
|
||||
|
||||
if current_power == 0 then
|
||||
-- check if power network is overloaded
|
||||
if techage.power.network_overloaded(pos, techage.ElectricCable) then
|
||||
return "container["..x..","..y.."]"..
|
||||
"box[0,0;2.3,3.3;#395c74]"..
|
||||
"label[0.2,0;"..label.."]"..
|
||||
"label[0.7,0.4;"..max_power.." "..unit.."]"..
|
||||
"image[0,0.5;1,3;techage_form_level_red_fg.png]"..
|
||||
"container_end[]"
|
||||
end
|
||||
end
|
||||
current_power = current_power or 0
|
||||
if current_power == 0 then
|
||||
percent = 0
|
||||
ypos = 2.8
|
||||
|
@ -148,6 +148,17 @@ function techage.power.power_available(pos, Cable)
|
||||
return netw and netw.on and netw.alive and netw.alive > 0
|
||||
end
|
||||
|
||||
function techage.power.network_overloaded(pos, Cable)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local tlib_type = Cable.tube_type
|
||||
local netID = nvm[Cable.tube_type] and nvm[Cable.tube_type]["netID"]
|
||||
local netw = networks.has_network(tlib_type, netID)
|
||||
if netw then
|
||||
local sum = (netw.available1 or 0) + (netw.available2 or 0)
|
||||
return sum > 0 and sum < (netw.needed1 or 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- this is more a try to start, the start will be performed by on_power()
|
||||
function techage.power.consumer_start(pos, Cable, cycle_time)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
@ -228,5 +239,24 @@ function techage.power.generator_alive(pos, Cable, cycle_time, outdir, curr_powe
|
||||
return 0
|
||||
end
|
||||
|
||||
-- Calculate the needed power over all con1 consumers
|
||||
function techage.power.needed_power(pos, Cable, outdir)
|
||||
local sum = 0
|
||||
networks.connection_walk(pos, outdir, Cable, function(pos, indir, node)
|
||||
local net = net_def(pos, Cable.tube_type) -- network definition
|
||||
if net.ntype == "con1" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local def = nvm[Cable.tube_type] -- power related data
|
||||
|
||||
if def and def["cstate"] ~= STOPPED then
|
||||
if def["calive"] >= 0 then
|
||||
sum = sum + (net.nominal or def.curr_power or 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
return sum
|
||||
end
|
||||
|
||||
-- function delete_netID(pos, outdir, Cable)
|
||||
techage.power.delete_netID = delete_netID
|
||||
|
@ -129,10 +129,10 @@ local function formspec(pos, nvm)
|
||||
"box[0,-0.1;9.8,0.5;#c6e8ff]"..
|
||||
"label[4,-0.1;"..minetest.colorize( "#000000", S("Network Data")).."]"..
|
||||
"label[9.5,-0.1;"..minetest.colorize( "#000000", star).."]"..
|
||||
power.formspec_label_bar(0, 0.7, S("Genera. 1"), gen1.pow_act, gen1.pow_used)..
|
||||
power.formspec_label_bar(2.5, 0.7, S("Genera. 2"), gen2.pow_act, gen2.pow_used)..
|
||||
power.formspec_label_bar(5, 0.7, S("Consum. 2"), con2.pow_act, con2.pow_used)..
|
||||
power.formspec_label_bar(7.5, 0.7, S("Consum. 1"), con1.pow_act, con1.pow_used)..
|
||||
power.formspec_label_bar(pos, 0, 0.7, S("Genera. 1"), gen1.pow_act, gen1.pow_used)..
|
||||
power.formspec_label_bar(pos, 2.5, 0.7, S("Genera. 2"), gen2.pow_act, gen2.pow_used)..
|
||||
power.formspec_label_bar(pos, 5, 0.7, S("Consum. 2"), con2.pow_act, con2.pow_used)..
|
||||
power.formspec_label_bar(pos, 7.5, 0.7, S("Consum. 1"), con1.pow_act, con1.pow_used)..
|
||||
"box[0,4.3;9.8,0.4;#c6e8ff]"..
|
||||
"box[0,4.85;9.8,0.4;#395c74]"..
|
||||
"box[0,5.35;9.8,0.4;#395c74]"..
|
||||
|
@ -37,6 +37,7 @@ local Generators = {
|
||||
S("Energy storage"),
|
||||
S("Fuel cell"),
|
||||
S("Electrolyzer"),
|
||||
S("TA2 Generator"),
|
||||
}
|
||||
|
||||
local Storage = {
|
||||
@ -55,6 +56,7 @@ local GeneratorPerformances = {
|
||||
60, -- S("Energy storage")
|
||||
25, -- S("Fuel cell")
|
||||
30, -- S("Electrolyzer")
|
||||
24, -- S("TA2 Generator")
|
||||
}
|
||||
|
||||
--
|
||||
|
@ -67,8 +67,8 @@ local function formspec(self, pos, nvm)
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;5.8,0.5;#c6e8ff]"..
|
||||
"label[2.5,-0.1;"..minetest.colorize( "#000000", S("Inverter")).."]"..
|
||||
power.formspec_label_bar(0, 0.8, S("Power DC"), PWR_PERF, max_power)..
|
||||
power.formspec_label_bar(3.5, 0.8, S("Power AC"), max_power, delivered)..
|
||||
power.formspec_label_bar(pos, 0, 0.8, S("Power DC"), PWR_PERF, max_power)..
|
||||
power.formspec_label_bar(pos, 3.5, 0.8, S("Power AC"), max_power, delivered)..
|
||||
arrow..
|
||||
"image_button[2.5,3;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[2.5,3;1,1;"..self:get_state_tooltip(nvm).."]"
|
||||
|
@ -38,7 +38,7 @@ local function formspec(self, pos, nvm)
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
power.formspec_label_bar(0, 0.8, S("power"), PWR_CAPA, nvm.provided)..
|
||||
power.formspec_label_bar(pos, 0, 0.8, S("power"), PWR_CAPA, nvm.provided)..
|
||||
"image_button[2.8,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[2.8,2;1,1;"..self:get_state_tooltip(nvm).."]"
|
||||
end
|
||||
|
@ -36,7 +36,7 @@ local function formspec(self, pos, nvm)
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;4.8,0.5;#c6e8ff]"..
|
||||
"label[1,-0.1;"..minetest.colorize( "#000000", S("TA3 Akku Box")).."]"..
|
||||
power.formspec_label_bar(0, 0.8, S("Load"), PWR_CAPA, capa)..
|
||||
power.formspec_label_bar(pos, 0, 0.8, S("Load"), PWR_CAPA, capa)..
|
||||
"image_button[2.6,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[3,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"label[3.7,1.2;"..S("Electricity").."]"..
|
||||
|
236
techage/ta3_power/axle2power.lua
Normal file
236
techage/ta3_power/axle2power.lua
Normal file
@ -0,0 +1,236 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2 Power Generator
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S2P = minetest.string_to_pos
|
||||
|
||||
local Cable = techage.ElectricCable
|
||||
local Axle = techage.Axle
|
||||
local power = techage.power
|
||||
local networks = techage.networks
|
||||
|
||||
local CYCLE_TIME = 2
|
||||
local PWR_PERF = 24
|
||||
|
||||
local function swap_node(pos, name)
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if node.name == name then
|
||||
return
|
||||
end
|
||||
node.name = name
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
|
||||
local function on_power(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.axle = nvm.axle or {}
|
||||
nvm.consumer_powered = true
|
||||
M(pos):set_string("infotext", S("TA2 Power Generator"))
|
||||
swap_node(pos, "techage:ta2_generator_on")
|
||||
nvm.ticks = 0
|
||||
local outdir = M(pos):get_int("outdir")
|
||||
nvm.axle.curr_power = techage.power.needed_power(pos, Cable, outdir)
|
||||
end
|
||||
|
||||
local function on_nopower(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.consumer_powered = false
|
||||
if (nvm.ticks or 0) < 4 then
|
||||
M(pos):set_string("infotext", S("TA2 Power Generator: Overload fault?\n(restart with right-click)"))
|
||||
end
|
||||
nvm.ticks = 0
|
||||
end
|
||||
|
||||
local function node_timer(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.axle = nvm.axle or {}
|
||||
|
||||
-- trigger network on consumer side
|
||||
nvm.ticks = (nvm.ticks or 0) + 1
|
||||
if nvm.ticks % 2 then
|
||||
power.consumer_alive(pos, Axle, CYCLE_TIME)
|
||||
end
|
||||
|
||||
-- handle generator side delayed
|
||||
if nvm.ticks > 3 then
|
||||
local outdir = M(pos):get_int("outdir")
|
||||
|
||||
if nvm.consumer_powered and not nvm.running_as_generator then
|
||||
nvm.running_as_generator = true
|
||||
power.generator_start(pos, Cable, CYCLE_TIME, outdir, nvm.max_power)
|
||||
elseif not nvm.consumer_powered and nvm.running_as_generator then
|
||||
nvm.running_as_generator = false
|
||||
power.generator_stop(pos, Cable, outdir)
|
||||
end
|
||||
|
||||
if nvm.running_as_generator then
|
||||
nvm.axle.curr_power = power.generator_alive(pos, Cable, CYCLE_TIME, outdir, PWR_PERF) + 1
|
||||
else
|
||||
swap_node(pos, "techage:ta2_generator_off")
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function tubelib2_on_update2(pos, outdir, tlib2, node)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.axle = nvm.axle or {}
|
||||
nvm.axle.curr_power = 1
|
||||
power.update_network(pos, outdir, tlib2)
|
||||
end
|
||||
|
||||
minetest.register_node("techage:ta2_generator_off", {
|
||||
description = S("TA2 Power Generator"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta2.png^techage_frame_ta2_top.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_hole_electric.png",
|
||||
"techage_filling_ta2.png^techage_axle_clutch.png^techage_frame_ta2.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_generator_red.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_generator_red.png^[transformFX]",
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=2, crumbly=2, choppy=2},
|
||||
on_rotate = screwdriver.disallow,
|
||||
is_ground_content = false,
|
||||
|
||||
after_place_node = function(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.axle = nvm.axle or {}
|
||||
nvm.axle.curr_power = 1
|
||||
nvm.consumer_powered = false
|
||||
nvm.running_as_generator = false
|
||||
M(pos):set_int("outdir", networks.side_to_outdir(pos, "R"))
|
||||
M(pos):set_int("leftdir", networks.side_to_outdir(pos, "L"))
|
||||
Cable:after_place_node(pos)
|
||||
Axle:after_place_node(pos)
|
||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||
power.consumer_start(pos, Axle, CYCLE_TIME*2)
|
||||
M(pos):set_string("infotext", S("TA2 Power Generator"))
|
||||
end,
|
||||
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.axle = nvm.axle or {}
|
||||
nvm.axle.curr_power = 1
|
||||
M(pos):set_string("infotext", S("TA2 Power Generator"))
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode)
|
||||
Cable:after_dig_node(pos)
|
||||
Axle:after_dig_node(pos)
|
||||
techage.del_mem(pos)
|
||||
end,
|
||||
|
||||
tubelib2_on_update2 = tubelib2_on_update2,
|
||||
on_timer = node_timer,
|
||||
networks = {
|
||||
ele1 = {
|
||||
sides = {R = 1},
|
||||
ntype = "gen1",
|
||||
nominal = PWR_PERF,
|
||||
},
|
||||
axle = {
|
||||
sides = {L = 1},
|
||||
ntype = "con1",
|
||||
on_power = on_power,
|
||||
on_nopower = on_nopower,
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_node("techage:ta2_generator_on", {
|
||||
description = S("TA2 Power Generator"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta2.png^techage_frame_ta2_top.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_hole_electric.png",
|
||||
{
|
||||
image = "techage_filling4_ta2.png^techage_axle_clutch4.png^techage_frame4_ta2.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.6,
|
||||
},
|
||||
},
|
||||
{
|
||||
image = "techage_filling4_ta2.png^techage_appl_generator_red4.png^techage_frame4_ta2.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.3,
|
||||
},
|
||||
},
|
||||
{
|
||||
image = "techage_filling4_ta2.png^techage_appl_generator_red4.png^[transformFX]^techage_frame4_ta2.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.3,
|
||||
},
|
||||
},
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
is_ground_content = false,
|
||||
drop = "",
|
||||
groups = {not_in_creative_inventory=1},
|
||||
diggable = false,
|
||||
|
||||
tubelib2_on_update2 = tubelib2_on_update2,
|
||||
on_timer = node_timer,
|
||||
networks = {
|
||||
ele1 = {
|
||||
sides = {R = 1},
|
||||
ntype = "gen1",
|
||||
nominal = PWR_PERF,
|
||||
},
|
||||
axle = {
|
||||
sides = {L = 1},
|
||||
ntype = "con1",
|
||||
on_power = on_power,
|
||||
on_nopower = on_nopower,
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
techage.register_node({"techage:ta2_generator_off", "techage:ta2_generator_on"}, {
|
||||
on_node_load = function(pos, node)
|
||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||
end,
|
||||
})
|
||||
|
||||
Cable:add_secondary_node_names({"techage:ta2_generator_off", "techage:ta2_generator_on"})
|
||||
Axle:add_secondary_node_names({"techage:ta2_generator_off", "techage:ta2_generator_on"})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:ta2_generator_off",
|
||||
recipe = {
|
||||
{"basic_materials:steel_bar", "dye:red", "default:wood"},
|
||||
{'techage:axle', 'basic_materials:gear_steel', 'techage:electric_cableS'},
|
||||
{"default:wood", "techage:iron_ingot", "basic_materials:steel_bar"},
|
||||
},
|
||||
})
|
||||
|
245
techage/ta3_power/power2axle.lua
Normal file
245
techage/ta3_power/power2axle.lua
Normal file
@ -0,0 +1,245 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA3 Electric Motor
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S2P = minetest.string_to_pos
|
||||
|
||||
local Cable = techage.ElectricCable
|
||||
local Axle = techage.Axle
|
||||
local power = techage.power
|
||||
local networks = techage.networks
|
||||
|
||||
local CYCLE_TIME = 2
|
||||
local PWR_PERF = 40
|
||||
|
||||
-- Axles texture animation
|
||||
local function switch_axles(pos, on)
|
||||
for _,outdir in ipairs(networks.get_node_connections(pos, "axle")) do
|
||||
Axle:switch_tube_line(pos, outdir, on and "on" or "off")
|
||||
end
|
||||
end
|
||||
|
||||
local function swap_node(pos, name)
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if node.name == name then
|
||||
return
|
||||
end
|
||||
node.name = name
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
|
||||
local function on_power(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.ele1 = nvm.ele1 or {}
|
||||
nvm.consumer_powered = true
|
||||
M(pos):set_string("infotext", S("TA3 Electric Motor"))
|
||||
swap_node(pos, "techage:ta3_motor_on")
|
||||
nvm.ticks = 0
|
||||
local outdir = M(pos):get_int("outdir")
|
||||
nvm.ele1.curr_power = techage.power.needed_power(pos, Axle, outdir)
|
||||
end
|
||||
|
||||
local function on_nopower(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.consumer_powered = false
|
||||
if (nvm.ticks or 0) < 4 then
|
||||
M(pos):set_string("infotext", S("TA3 Electric Motor: Overload fault?\n(restart with right-click)"))
|
||||
end
|
||||
nvm.ticks = 0
|
||||
end
|
||||
|
||||
local function node_timer(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.ele1 = nvm.ele1 or {}
|
||||
|
||||
-- trigger network on consumer side
|
||||
nvm.ticks = (nvm.ticks or 0) + 1
|
||||
if nvm.ticks % 2 then
|
||||
power.consumer_alive(pos, Cable, CYCLE_TIME)
|
||||
end
|
||||
|
||||
-- handle generator side delayed
|
||||
if nvm.ticks > 3 then
|
||||
local outdir = M(pos):get_int("outdir")
|
||||
|
||||
if nvm.consumer_powered and not nvm.running_as_generator then
|
||||
nvm.running_as_generator = true
|
||||
power.generator_start(pos, Axle, CYCLE_TIME, outdir, nvm.max_power)
|
||||
switch_axles(pos, true)
|
||||
elseif not nvm.consumer_powered and nvm.running_as_generator then
|
||||
nvm.running_as_generator = false
|
||||
power.generator_stop(pos, Axle, outdir)
|
||||
switch_axles(pos, false)
|
||||
end
|
||||
|
||||
if nvm.running_as_generator then
|
||||
nvm.ele1.curr_power = power.generator_alive(pos, Axle, CYCLE_TIME, outdir, PWR_PERF) + 1
|
||||
else
|
||||
swap_node(pos, "techage:ta3_motor_off")
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function tubelib2_on_update2(pos, outdir, tlib2, node)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.ele1 = nvm.ele1 or {}
|
||||
nvm.ele1.curr_power = 1
|
||||
power.update_network(pos, outdir, tlib2)
|
||||
end
|
||||
|
||||
minetest.register_node("techage:ta3_motor_off", {
|
||||
description = S("TA3 Electric Motor"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta3.png^techage_frame_ta3_top.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_axle_clutch.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_appl_hole_electric.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_generator_red.png^[transformFX]",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_generator_red.png",
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=2, crumbly=2, choppy=2},
|
||||
on_rotate = screwdriver.disallow,
|
||||
is_ground_content = false,
|
||||
|
||||
after_place_node = function(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.ele1 = nvm.ele1 or {}
|
||||
nvm.ele1.curr_power = 1
|
||||
nvm.consumer_powered = false
|
||||
nvm.running_as_generator = false
|
||||
M(pos):set_int("outdir", networks.side_to_outdir(pos, "R"))
|
||||
M(pos):set_int("leftdir", networks.side_to_outdir(pos, "L"))
|
||||
Cable:after_place_node(pos)
|
||||
Axle:after_place_node(pos)
|
||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||
power.consumer_start(pos, Cable, CYCLE_TIME*2)
|
||||
M(pos):set_string("infotext", S("TA3 Electric Motor"))
|
||||
end,
|
||||
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.ele1 = nvm.ele1 or {}
|
||||
nvm.ele1.curr_power = 1
|
||||
M(pos):set_string("infotext", S("TA3 Electric Motor"))
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode)
|
||||
Cable:after_dig_node(pos)
|
||||
Axle:after_dig_node(pos)
|
||||
techage.del_mem(pos)
|
||||
end,
|
||||
|
||||
tubelib2_on_update2 = tubelib2_on_update2,
|
||||
on_timer = node_timer,
|
||||
networks = {
|
||||
axle = {
|
||||
sides = {R = 1},
|
||||
ntype = "gen1",
|
||||
nominal = PWR_PERF,
|
||||
},
|
||||
ele1 = {
|
||||
sides = {L = 1},
|
||||
ntype = "con1",
|
||||
on_power = on_power,
|
||||
on_nopower = on_nopower,
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_node("techage:ta3_motor_on", {
|
||||
description = S("TA3 Electric Motor"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta3.png^techage_frame_ta3_top.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png",
|
||||
{
|
||||
image = "techage_filling4_ta3.png^techage_axle_clutch4.png^techage_frame4_ta3.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.6,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_hole_electric.png",
|
||||
{
|
||||
image = "techage_filling4_ta3.png^techage_appl_generator_red4.png^[transformFX]^techage_frame4_ta3.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.3,
|
||||
},
|
||||
},
|
||||
{
|
||||
image = "techage_filling4_ta3.png^techage_appl_generator_red4.png^techage_frame4_ta3.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.3,
|
||||
},
|
||||
},
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
is_ground_content = false,
|
||||
drop = "",
|
||||
groups = {not_in_creative_inventory=1},
|
||||
diggable = false,
|
||||
|
||||
tubelib2_on_update2 = tubelib2_on_update2,
|
||||
on_timer = node_timer,
|
||||
networks = {
|
||||
axle = {
|
||||
sides = {R = 1},
|
||||
ntype = "gen1",
|
||||
nominal = PWR_PERF,
|
||||
},
|
||||
ele1 = {
|
||||
sides = {L = 1},
|
||||
ntype = "con1",
|
||||
on_power = on_power,
|
||||
on_nopower = on_nopower,
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
techage.register_node({"techage:ta3_motor_off", "techage:ta3_motor_on"}, {
|
||||
on_node_load = function(pos, node)
|
||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||
end,
|
||||
})
|
||||
|
||||
Cable:add_secondary_node_names({"techage:ta3_motor_off", "techage:ta3_motor_on"})
|
||||
Axle:add_secondary_node_names({"techage:ta3_motor_off", "techage:ta3_motor_on"})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:ta3_motor_off",
|
||||
recipe = {
|
||||
{"basic_materials:steel_bar", "dye:red", "default:wood"},
|
||||
{'techage:electric_cableS', 'basic_materials:gear_steel', 'techage:axle'},
|
||||
{"default:wood", "techage:iron_ingot", "basic_materials:steel_bar"},
|
||||
},
|
||||
})
|
||||
|
@ -39,7 +39,7 @@ local function formspec(self, pos, nvm)
|
||||
"image[1.4,1.6;1,1;techage_form_arrow_bg.png^[transformR270]"..
|
||||
"image_button[1.4,3.2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[1.5,3;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
power.formspec_label_bar(2.5, 0.8, S("Electricity"), PWR_CAPA, nvm.provided)
|
||||
power.formspec_label_bar(pos, 2.5, 0.8, S("Electricity"), PWR_CAPA, nvm.provided)
|
||||
end
|
||||
|
||||
local function play_sound(pos)
|
||||
|
BIN
techage/textures/techage_appl_generator_red.png
Normal file
BIN
techage/textures/techage_appl_generator_red.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
BIN
techage/textures/techage_appl_generator_red4.png
Normal file
BIN
techage/textures/techage_appl_generator_red4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
@ -245,6 +245,11 @@ local function read_state(itemstack, user, pointed_thing)
|
||||
fuel = dump(fuel)
|
||||
minetest.chat_send_player(user:get_player_name(), ndef.description.." "..number..": fuel = "..fuel.." ")
|
||||
end
|
||||
local output = techage.send_single("0", number, "output", nil)
|
||||
if output and output ~= "" and output ~= "unsupported" then
|
||||
output = dump(output)
|
||||
minetest.chat_send_player(user:get_player_name(), ndef.description.." "..number..": output = "..output.." ")
|
||||
end
|
||||
local load, abs = techage.send_single("0", number, "load", nil)
|
||||
if load and load ~= "" and load ~= "unsupported" then
|
||||
load, abs = dump(load), abs and dump(abs) or "--"
|
||||
|
@ -51,46 +51,9 @@ end
|
||||
local function add_rotor(pos, nvm, player_name)
|
||||
nvm.error = false
|
||||
|
||||
-- Check for next wind turbine
|
||||
local pos1 = {x=pos.x-13, y=pos.y-9, z=pos.z-13}
|
||||
local pos2 = {x=pos.x+13, y=pos.y+10, z=pos.z+13}
|
||||
local num = #minetest.find_nodes_in_area(pos1, pos2, {"techage:ta4_wind_turbine"})
|
||||
if num > 1 then
|
||||
if player_name then
|
||||
techage.mark_region(player_name, pos1, pos2, "")
|
||||
minetest.chat_send_player(player_name, S("[TA4 Wind Turbine]")..
|
||||
" "..S("The wind turbines are too close together!"))
|
||||
end
|
||||
M(pos):set_string("infotext", S("TA4 Wind Turbine").." "..S("Error"))
|
||||
nvm.error = true
|
||||
return
|
||||
end
|
||||
|
||||
-- Check for water surface (occean)
|
||||
pos1 = {x=pos.x-20, y=0, z=pos.z-20}
|
||||
pos2 = {x=pos.x+20, y=1, z=pos.z+20}
|
||||
local num = #minetest.find_nodes_in_area(pos1, pos2, {"default:water_source", "default:water_flowing", "ignore"})
|
||||
if num < (41*41*2-MAX_NUM_FOREIGN_NODES) then
|
||||
if player_name then
|
||||
techage.mark_region(player_name, pos1, pos2, "")
|
||||
minetest.chat_send_player(player_name, S("[TA4 Wind Turbine]")..
|
||||
" "..S("More water expected (2 m deep)!"))
|
||||
end
|
||||
M(pos):set_string("infotext", S("TA4 Wind Turbine").." "..S("Error"))
|
||||
nvm.error = true
|
||||
return
|
||||
end
|
||||
|
||||
if pos.y < 12 or pos.y > 20 then
|
||||
if player_name then
|
||||
pos1 = {x=pos.x-13, y=12, z=pos.z-13}
|
||||
pos2 = {x=pos.x+13, y=20, z=pos.z+13}
|
||||
techage.mark_region(player_name, pos1, pos2, "")
|
||||
minetest.chat_send_player(player_name, S("[TA4 Wind Turbine]")..
|
||||
" "..S("No wind at this altitude!"))
|
||||
end
|
||||
M(pos):set_string("infotext", S("TA4 Wind Turbine").." "..S("Error"))
|
||||
if not techage.valid_place_for_windturbine(pos, nil, 1) then
|
||||
nvm.error = true
|
||||
M(pos):set_string("infotext", S("TA4 Wind Turbine")..": "..S("Not suitable position!"))
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -58,7 +58,7 @@ function tubelib2.get_node_lvm(pos)
|
||||
local data = vm:get_data()
|
||||
local param2_data = vm:get_param2_data()
|
||||
local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge})
|
||||
local idx = area:index(pos.x, pos.y, pos.z)
|
||||
local idx = area:indexp(pos)
|
||||
node = {
|
||||
name = minetest.get_name_from_content_id(data[idx]),
|
||||
param2 = param2_data[idx]
|
||||
|
Loading…
Reference in New Issue
Block a user