waterpump bugfix
This commit is contained in:
parent
2eb9546625
commit
fe835455c4
@ -198,6 +198,8 @@ techage.manual_DE.aText = {
|
||||
"TA4: Zukunft (Future Age)\n"..
|
||||
"Regenerative Energiequellen wie Wind\\, Sonne und Biokraft helfen dir\\, das Ölzeitalter zu verlassen. Mit modernen Technologien und intelligenten Maschinen machst du dich auf in die Zukunft.\n"..
|
||||
"\n"..
|
||||
"Hinweis: Mit Klicken auf die Pluszeichen kommst du in die Unterkapitel dieser Anleitung.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Diese Dokumentation ist sowohl \"ingame\" (Block Konstruktionsplan) als auch auf GitHub als MD-Files verfügbar.\n"..
|
||||
@ -1459,7 +1461,7 @@ techage.manual_DE.aText = {
|
||||
}
|
||||
|
||||
techage.manual_DE.aItemName = {
|
||||
"wlanchip",
|
||||
"techage_ta4",
|
||||
"",
|
||||
"",
|
||||
"meridium",
|
||||
|
@ -198,6 +198,8 @@ techage.manual_EN.aText = {
|
||||
"TA4: Future Age\n"..
|
||||
"Renewable energy sources such as wind\\, sun and biofuels help you to leave the oil age. With modern technologies and intelligent machines you set out into the future.\n"..
|
||||
"\n"..
|
||||
"Note: With a click on the plus sign you get into the subchapters of this manual.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"This documentation is available both \"ingame\" (block construction plan) and on GitHub as MD files.\n"..
|
||||
@ -1449,7 +1451,7 @@ techage.manual_EN.aText = {
|
||||
}
|
||||
|
||||
techage.manual_EN.aItemName = {
|
||||
"wlanchip",
|
||||
"techage_ta4",
|
||||
"",
|
||||
"",
|
||||
"meridium",
|
||||
|
BIN
images/steamengine.png
Normal file
BIN
images/steamengine.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 464 KiB |
@ -83,9 +83,10 @@ local function on_nopower(pos)
|
||||
end
|
||||
|
||||
local function pumping(pos, nvm)
|
||||
if not nvm.running then
|
||||
State:nopower(pos, nvm)
|
||||
else
|
||||
if techage.needs_power(nvm) then
|
||||
power.consumer_alive(pos, Cable, CYCLE_TIME)
|
||||
end
|
||||
if nvm.running then
|
||||
local leftover = liquid.put(pos, 6, "techage:water", 1)
|
||||
if leftover and leftover > 0 then
|
||||
State:blocked(pos, nvm)
|
||||
@ -94,7 +95,6 @@ local function pumping(pos, nvm)
|
||||
State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
return
|
||||
end
|
||||
State:idle(pos, nvm)
|
||||
end
|
||||
|
||||
-- converts power into hydrogen
|
||||
|
604
manuals/api.md
604
manuals/api.md
@ -1,604 +0,0 @@
|
||||
# Techage APIs und Design
|
||||
|
||||
*Hinweis: Dieses Dokument folgt dem markdown Standard und ist mit Typora erstellt. Damit hat man links das Inhaltsverzeichnis zur Übersicht und zum Navigieren. Zur Not geht aber jeder Editor.*
|
||||
|
||||
## History
|
||||
|
||||
- v1.0 - 03.10.2019 - Erster Entwurf
|
||||
- v1.1 - 26.10.2019 - `networks.lua` hinzugefügt
|
||||
|
||||
## Hierarchiediagramm
|
||||
|
||||
```
|
||||
+-------------------------------------------------------------+ +-------------------+
|
||||
| consumer | | liquid |
|
||||
| (tubing/commands/states/formspec/power/connections/node) | | (Pipe/put/take) |
|
||||
+-------------------------------------------------------------+ +-------------------+
|
||||
| | | |
|
||||
V V V V
|
||||
+-----------------+ +-----------------+ +-------------------+ +-------------------+
|
||||
| command | | node_states | | power | | networks |
|
||||
|(tubing/commands)| |(states/formspec)| |(power,connections)| | (connections) |
|
||||
+-----------------+ +-----------------+ +-------------------+ +-------------------+
|
||||
| | | |
|
||||
V V V V
|
||||
+-----------------------------------------------------------------------------------+
|
||||
| Tube/tubelib2 |
|
||||
| (tubes, mem, get_node_pos) |
|
||||
+-----------------------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
## Klasse `Tube` (Mod tubelib2)
|
||||
|
||||
Da Techage auf tubelib2 aufsetzt, soll auch diese Mod hier soweit behandelt werden, wie notwendig.
|
||||
|
||||
`tubelib2` dient zur Verknüpfung von Blöcken über tubes/pipes/cables. Tubes sind dabei "primary nodes", die Blöcke "secundary nodes". Die Features dabei sind:
|
||||
|
||||
- platzieren von Tubes, so dass diese mit benachbarten Tubes oder registrierten Blöcken eine Verbindung eingehen
|
||||
- Event-Handling, so dass registrierte Blöcke über Änderungen an den Tube-Verbindungen informiert werden
|
||||
- API-Funktionen, um die Position des Blockes gegenüber (peer node) zu bestimmen
|
||||
|
||||
```lua
|
||||
-- From source node to destination node via tubes.
|
||||
-- pos is the source node position, dir the output dir
|
||||
-- The returned pos is the destination position, dir
|
||||
-- is the direction into the destination node.
|
||||
function Tube:get_connected_node_pos(pos, dir)
|
||||
local key = S(pos)
|
||||
if self.connCache[key] and self.connCache[key][dir] then
|
||||
local item = self.connCache[key][dir]
|
||||
return item.pos2, Turn180Deg[item.dir2]
|
||||
end
|
||||
local fpos,fdir = self:walk_tube_line(pos, dir)
|
||||
local spos = get_pos(fpos,fdir)
|
||||
self:add_to_cache(pos, dir, spos, Turn180Deg[fdir])
|
||||
self:add_to_cache(spos, Turn180Deg[fdir], pos, dir)
|
||||
return spos, fdir
|
||||
end
|
||||
|
||||
-- Check if node at given position is a tubelib2 compatible node,
|
||||
-- able to receive and/or deliver items.
|
||||
-- If dir == nil then node_pos = pos
|
||||
-- Function returns the result (true/false), new pos, and the node
|
||||
function Tube:compatible_node(pos, dir)
|
||||
local npos = vector.add(pos, Dir6dToVector[dir or 0])
|
||||
local node = self:get_node_lvm(npos)
|
||||
return self.secondary_node_names[node.name], npos, node
|
||||
end
|
||||
```
|
||||
|
||||
Um mit `tubelib2` arbeiten zu können, muss zuvor eine Tube Instanz angelegt werden:
|
||||
|
||||
```lua
|
||||
local Tube = tubelib2.Tube:new(...)
|
||||
```
|
||||
|
||||
Hier die Parameter:
|
||||
|
||||
```lua
|
||||
dirs_to_check = attr.dirs_to_check or {1,2,3,4,5,6},
|
||||
max_tube_length = attr.max_tube_length or 1000,
|
||||
primary_node_names = Tbl(attr.primary_node_names or {}),
|
||||
secondary_node_names = Tbl(attr.secondary_node_names or {}),
|
||||
show_infotext = attr.show_infotext or false,
|
||||
force_to_use_tubes = attr.force_to_use_tubes or false, -- Block an Block oder Tubes dazw.
|
||||
clbk_after_place_tube = attr.after_place_tube, -- hiermit wird die Tube ausgetauscht (1)
|
||||
tube_type = attr.tube_type or "unknown", -- hier einen eindeutigen Namen für die Instanz
|
||||
```
|
||||
|
||||
zu (1): Bei einfachen Tubes reicht hier:
|
||||
|
||||
```lua
|
||||
minetest.swap_node(pos, {name = "tubelib2:tube"..tube_type, param2 = param2})
|
||||
```
|
||||
|
||||
tube_type bei "swap_node" ist "S" oder "A" (straight or angled)
|
||||
|
||||
### Registrierung
|
||||
|
||||
Alle Blöcke mit Tube-Support müssen bei `tubelib2` registriert werden über:
|
||||
|
||||
```lua
|
||||
Tube:add_secondary_node_names({names})
|
||||
```
|
||||
|
||||
### Events
|
||||
|
||||
#### Änderungen an den Nodes
|
||||
|
||||
Damit die Tubes und die gegenüber angeschlossenen Blöcke über Änderungen informiert werden, existieren 2 Funktionen:
|
||||
|
||||
```lua
|
||||
after_place_node = function(pos, placer)
|
||||
Tube:after_place_node(pos [, {tube_dir}])
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Tube:after_dig_node(pos [, {tube_dir}])
|
||||
end,
|
||||
```
|
||||
|
||||
Diese müssen in jedem Fall aufgerufen werden, sonst werden die Daten der benachbarten Tubes nicht aktualisiert. Der Parameter `tube_dir` ist optional, macht aber Sinn, so dass nicht alle 6 Seiten geprüft werden müssen.
|
||||
|
||||
#### Änderungen an Tubes/anderen Nodes
|
||||
|
||||
Damit der Block über Änderungen an Tubes oder Peer-Blöcken informiert wird, gibt es zwei Möglichkeiten:
|
||||
|
||||
1. Knoten-spezifische callback Funktionen
|
||||
2. Zentrale callback Funktionen
|
||||
|
||||
##### 1. Knoten-spezifische callback Funktion `tubelib2_on_update`
|
||||
|
||||
```lua
|
||||
tubelib2_on_update(node, pos, out_dir, peer_pos, peer_in_dir)
|
||||
```
|
||||
|
||||
Die Funktion muss Teil von `minetest.register_node()` sein.
|
||||
|
||||
##### 2. Knoten-spezifische callback Funktion `tubelib2_on_update2`
|
||||
|
||||
```lua
|
||||
tubelib2_on_update2(node, pos, self)
|
||||
```
|
||||
|
||||
Dies ist eine neue Funktion von tubelib2 v1.6
|
||||
Durch den Paramater `self` können nun unterschiedliche Instanzen den tubelib2 unterschieden werden, was für die verschiedenen Kabel/Röhren von techage notwendig wurde.
|
||||
|
||||
##### 3. Zentrale callback Funktion `register_on_tube_update`
|
||||
|
||||
```lua
|
||||
Tube:register_on_tube_update(function(node, pos, out_dir, peer_pos, peer_in_dir)
|
||||
...
|
||||
end)
|
||||
```
|
||||
|
||||
Wird 1) oder 2) aufgerufen, wird 3) **nicht** mehr gerufen!
|
||||
|
||||
### API Funktionen
|
||||
|
||||
```lua
|
||||
tubelib2.get_pos(pos, dir)
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Techage `command`
|
||||
|
||||
### Dir vs. Side
|
||||
|
||||
`tubelib2` arbeitet nur mit dirs (siehe oben). Oft ist aber die Arbeitsweise mit `sides` einfacher.
|
||||
|
||||
Techage definiert `sides` , die wie folgt definiert sind `{B=1, R=2, F=3, L=4, D=5, U=6}`:
|
||||
|
||||
```
|
||||
sides: dirs:
|
||||
U
|
||||
| B
|
||||
| / 6 (N)
|
||||
+--|-----+ | 1
|
||||
/ o /| | /
|
||||
+--------+ | |/
|
||||
L <----| |o----> R (W) 4 <-------+-------> 2 (O)
|
||||
| o | | /|
|
||||
| / | + / |
|
||||
| / |/ 3 |
|
||||
+-/------+ (S) 5
|
||||
/ |
|
||||
F |
|
||||
D
|
||||
```
|
||||
|
||||
`techage/command.lua` definiert hier:
|
||||
|
||||
```lua
|
||||
techage.side_to_outdir(side, param2) -- "B/R/F/L/D/U", node.param2
|
||||
```
|
||||
|
||||
In Ergänzung zu `tubelib2` sind in `command` Funktionen für den Austausch von Items von Inventar zu Inventar (Tubing) und Kommandos für Datenaustausch definiert.
|
||||
|
||||
Zusätzlich etabliert `command` das Knoten-Nummern-System für die Adressierung bei Kommandos.
|
||||
|
||||
Dazu muss jeder Knoten bei `command` an- und abgemeldet werden:
|
||||
|
||||
```lua
|
||||
techage.add_node(pos, name) --> number
|
||||
techage.remove_node(pos)
|
||||
```
|
||||
|
||||
Soll der Knoten Kommandos empfangen und/oder Items austauschen können, ist folgende Registrierung notwendig (alle Funktionen sind optional):
|
||||
|
||||
```lua
|
||||
techage.register_node(names, {
|
||||
on_pull_item = func(pos, in_dir, num),
|
||||
on_push_item = func(pos, in_dir, item),
|
||||
on_unpull_item = func(pos, in_dir, item),
|
||||
on_recv_message = func(pos, src, topic, payload),
|
||||
on_node_load = func(pos), -- LBM function
|
||||
on_transfer = func(pos, in_dir, topic, payload),
|
||||
})
|
||||
```
|
||||
|
||||
### Client API
|
||||
|
||||
Bspw. der Pusher als Client nutzt:
|
||||
|
||||
```lua
|
||||
techage.pull_items(pos, out_dir, num)
|
||||
techage.push_items(pos, out_dir, stack)
|
||||
techage.unpull_items(pos, out_dir, stack)
|
||||
```
|
||||
|
||||
### Server API
|
||||
|
||||
Für den Server (chest mit Inventar) existieren dazu folgende Funktionen:
|
||||
|
||||
```lua
|
||||
techage.get_items(inv, listname, num)
|
||||
techage.put_items(inv, listname, stack)
|
||||
techage.get_inv_state(inv, listname)
|
||||
```
|
||||
|
||||
### Hopper API
|
||||
|
||||
Es gibt bspw. mit dem Hopper aber auch einen Block, der nicht über Tubes sondern nur mit direkten Nachbarn Items austauschen soll. Dazu dient dieser Satz an Funktionen:
|
||||
|
||||
```lua
|
||||
techage.neighbour_pull_items(pos, out_dir, num)
|
||||
techage.neighbour_push_items(pos, out_dir, stack)
|
||||
techage.neighbour_unpull_items(pos, out_dir, stack)
|
||||
```
|
||||
|
||||
### Nummern bezogene Kommando API
|
||||
|
||||
Kommunikation ohne Tubes, Addressierung nur über Knoten-Nummern
|
||||
|
||||
```lua
|
||||
techage.not_protected(number, placer_name, clicker_name) --> true/false
|
||||
techage.check_numbers(numbers, placer_name) --> true/false (for send_multi)
|
||||
techage.send_multi(src, numbers, topic, payload) --> to many nodes
|
||||
techage.send_single(src, number, topic, payload) --> to one node with response
|
||||
```
|
||||
|
||||
### Positions bezogene Kommando API
|
||||
|
||||
Kommunikation mit Tubes oder mit direkten Nachbar-Knoten über pos/dir. Im Falle von Tubes muss bei `network` die Tube Instanz angegeben werden.
|
||||
|
||||
```lua
|
||||
techage.transfer(pos, outdir, topic, payload, network, nodenames)
|
||||
-- The destination node location is either:
|
||||
-- A) a destination position, specified by pos
|
||||
-- B) a neighbor position, specified by caller pos/outdir, or pos/side
|
||||
-- C) a tubelib2 network connection, specified by caller pos/outdir, or pos/side
|
||||
-- outdir is one of: 1..6 or alternative a 'side'
|
||||
-- side is one of: "B", "R", "F", "L", "D", "U"
|
||||
-- network is a tuebelib2 network instance
|
||||
-- opt: nodenames is a table of valid callee node names
|
||||
```
|
||||
|
||||
### Sonstige API
|
||||
|
||||
```lua
|
||||
techage.side_to_indir(side, param2) --> indir
|
||||
techage.get_node_info(dest_num) --> { pos, name }
|
||||
techage.get_node_number(pos) --> number
|
||||
techage.get_new_number(pos, name) --> should ne be needed (repair function)
|
||||
```
|
||||
|
||||
## Wrapper `power` (veraltet)
|
||||
|
||||
Im Gegensatz zu `tubelib2` und `command` verwaltet `power` ganze Netzwerke und nicht nur Einzelverbindungen zwischen zwei Knoten. Dazu muss `power` in jedem Knoten eine Connection-Liste anlegen, die alle angeschlossenen Tubes beinhaltet.
|
||||
|
||||
Nur so können mit der internen Funktion `connection_walk` alle Knoten im Netzwerk erreicht werden.
|
||||
|
||||
`power` besitzt die Funktion:
|
||||
|
||||
```lua
|
||||
techage.power.register_node(names, {
|
||||
conn_sides = {"L", "R", "U", "D", "F", "B"},
|
||||
on_power = func(pos, mem), -- für Verbraucher (einschalten)
|
||||
on_nopower = func(pos, mem), -- für Verbraucher (ausschalten)
|
||||
on_getpower = func(pos, mem), -- für Solarzellen (Strom einsammeln)
|
||||
power_network = Tube, -- tubelib2 Instanz
|
||||
after_place_node = func(pos, placer, itemstack, pointed_thing),
|
||||
after_dig_node = func(pos, oldnode, oldmetadata, digger)
|
||||
after_tube_update = func(node, pos, out_dir, peer_pos, peer_in_dir)
|
||||
})
|
||||
```
|
||||
|
||||
Durch die Registrierung des Nodes werden die Knoten-eigenen `after_...` Funktionen überschrieben. Optional können deshalb eigene Funktionen bei `register_node` übergeben werden.
|
||||
|
||||
```lua
|
||||
-- after_place_node decorator
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
local res = <node>.after_place_node(pos, placer, itemstack, pointed_thing)
|
||||
<Tube>:after_place_node(pos)
|
||||
return res
|
||||
end,
|
||||
-- after_dig_node decorator
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
<Tube>:after_dig_node(pos)
|
||||
minetest.after(0.1, tubelib2.del_mem, pos) -- At latest...
|
||||
return <node>.after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||
end,
|
||||
-- called after any connection change via
|
||||
-- --> tubelib2
|
||||
-- --> register_on_tube_update callback (cable)
|
||||
-- --> after_tube_update (power)
|
||||
after_tube_update = function(node, pos, out_dir, peer_pos, peer_in_dir)
|
||||
mem.connections = ... -- aktualisieren/löschen
|
||||
return <node>.after_tube_update(node, pos, out_dir, peer_pos, peer_in_dir)
|
||||
end,
|
||||
|
||||
```
|
||||
|
||||
Und es erfolgt eine Registrierung bei Tube:
|
||||
|
||||
```
|
||||
<Tube>:add_secondary_node_names({name})
|
||||
```
|
||||
|
||||
**Damit ist es nicht mehr notwendig, die `tubelib2` callback Funktionen `after_place_node` und `after_dig_node` sowie `after_tube_update` selbst zu codieren.**
|
||||
|
||||
**Soll aber der Knoten außer Power auch Kommandos empfangen oder senden können, oder am Tubing teilnehmen, so müssen die `command` bezogenen Funktionen zusätzlich beachtet werden.**
|
||||
|
||||
### Alternative API
|
||||
|
||||
Sollen die Knoten-eigenen `after_...` Funktionen nicht überschrieben werden, so bietet sich folgende, alternative API an:
|
||||
|
||||
```lua
|
||||
techage.power.enrich_node(names, pwr_def)
|
||||
techage.power.after_place_node(pos)
|
||||
techage.power.after_dig_node(pos, oldnode)
|
||||
techage.power.after_tube_update2(node, pos, out_dir, peer_pos, peer_in_dir)
|
||||
```
|
||||
|
||||
### `power`/`power2` API
|
||||
|
||||
```lua
|
||||
techage.power.side_to_dir(param2, side) --> outdir
|
||||
techage.power.side_to_outdir(pos, side) --> outdir
|
||||
techage.power.set_conn_dirs(pos, sides) --> store as meta "power_dirs"
|
||||
techage.get_pos(pos, side) --> new pos
|
||||
techage.power.after_rotate_node(pos, cable) -- update cables
|
||||
techage.power.percent(max_val, curr_val) --> percent value
|
||||
techage.power.formspec_power_bar(max_power, current_power) --> formspec string
|
||||
techage.power.power_cut(pos, dir, cable, cut) -- for switches
|
||||
|
||||
techage.power.network_changed(pos, mem) -- for each network change from any node
|
||||
|
||||
techage.power.generator_start(pos, mem, available) -- on start
|
||||
techage.power.generator_update(pos, mem, available) -- on any change of performance
|
||||
techage.power.generator_stop(pos, mem) -- on stop
|
||||
techage.power.generator_alive(pos, mem) -- every 2 s
|
||||
|
||||
techage.power.consumer_start(pos, mem, cycle_time, needed)
|
||||
techage.power.consumer_stop(pos, mem)
|
||||
techage.power.consumer_alive(pos, mem)
|
||||
techage.power.power_available(pos, mem, needed) -- lamp turn on function
|
||||
|
||||
techage.power.secondary_start(pos, mem, available, needed)
|
||||
techage.power.secondary_stop(pos, mem)
|
||||
techage.power.secondary_alive(pos, mem, capa_curr, capa_max)
|
||||
|
||||
techage.power.power_accounting(pos, mem) --> {network data...} (used by info tool)
|
||||
techage.power.get_power(start_pos) --> sum (used by solar cells)
|
||||
techage.power.power_network_available(start_pos) --> bool (used by TES generator)
|
||||
techage.power.mark_nodes(name, start_pos) -- used by debugging tool
|
||||
techage.power.limited_connection_walk(pos, clbk) --> num_nodes (used by terminal)
|
||||
```
|
||||
|
||||
## Klasse `NodeStates`
|
||||
|
||||
`NodeStates` abstrahiert die Zustände einer Maschine:
|
||||
|
||||
```lua
|
||||
techage.RUNNING = 1 -- in normal operation/turned on
|
||||
techage.BLOCKED = 2 -- a pushing node is blocked due to a full destination inventory
|
||||
techage.STANDBY = 3 -- nothing to do (e.g. no input items), or node (world) not loaded
|
||||
techage.NOPOWER = 4 -- only for power consuming nodes, no operation
|
||||
techage.FAULT = 5 -- any fault state (e.g. wrong source items)
|
||||
techage.STOPPED = 6 -- not operational/turned off
|
||||
```
|
||||
|
||||
Dazu muss eine Instanz von `NodeStates` angelegt werden:
|
||||
|
||||
```lua
|
||||
State = techage.NodeStates:new({
|
||||
node_name_passive = "mymod:name_pas",
|
||||
node_name_active = "mymod:name_act",
|
||||
infotext_name = "MyBlock",
|
||||
cycle_time = 2,
|
||||
standby_ticks = 6,
|
||||
formspec_func = func(self, pos, mem), --> string
|
||||
on_state_change = func(pos, old_state, new_state),
|
||||
can_start = func(pos, mem, state) --> true or false/<error string>
|
||||
has_power = func(pos, mem, state), --> true/false (for consumer)
|
||||
start_node = func(pos, mem, state),
|
||||
stop_node = func(pos, mem, state),
|
||||
})
|
||||
```
|
||||
|
||||
**Wird `NodeStates` verwendet, muss der Knoten die definierten Zustände unterstützen und sollte die formspec mit dem Button und die callbacks `can_start`, `start_node` und `stop_node` implementieren.**
|
||||
|
||||
Ein Beispiel dafür ist der Boiler aus `./steam_engine/boiler.lua`
|
||||
|
||||
### Methods
|
||||
|
||||
```lua
|
||||
node_init(pos, mem, number) -- to be called once
|
||||
stop(pos, mem)
|
||||
start(pos, mem)
|
||||
start_from_timer(pos, mem) -- to be used from node timer functions
|
||||
standby(pos, mem)
|
||||
blocked(pos, mem)
|
||||
nopower(pos, mem)
|
||||
fault(pos, mem, err_string) -- err_string is optional
|
||||
get_state(mem) --> state
|
||||
is_active(mem)
|
||||
start_if_standby(pos) -- used from allow_metadata_inventory functions
|
||||
idle(pos, mem) -- To be called if node is idle
|
||||
keep_running(pos, mem, val, num_items) -- to keep the node in state RUNNING
|
||||
state_button_event(pos, mem, fields) -- called from on_receive_fields
|
||||
get_state_button_image -- see techage.state_button()
|
||||
on_receive_message(pos, topic, payload) -- for command interface
|
||||
on_node_load(pos, not_start_timer) -- LBM actions
|
||||
|
||||
```
|
||||
|
||||
### Helper API
|
||||
|
||||
```lua
|
||||
techage.state_button(state) --> button layout for formspec
|
||||
techage.get_power_image(pos, mem) --> power symbol for formspec
|
||||
|
||||
techage.is_operational(mem) -- true if node_timer should be executed
|
||||
techage.needs_power(mem) --> true/false state dependent
|
||||
techage.needs_power2(state) --> true/false state dependent
|
||||
techage.get_state_string(mem) --> "running"
|
||||
|
||||
NodeStates:node_init(pos, mem, number)
|
||||
```
|
||||
|
||||
## Wrapper `consumer`
|
||||
|
||||
Wie auch `power` bietet `consumer` einen Registrierungs-Wrapper, der dem Knoten einige Eigenschaften und Funktionen hinzufügt.
|
||||
|
||||
```lua
|
||||
techage.register_consumer("autocrafter", S("Autocrafter"), tiles, {
|
||||
drawtype = "normal",
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing -- anstatt 'techage.register_node'
|
||||
after_place_node = func(pos, placer), -- knotenspezifischer Teil
|
||||
can_dig = fubnc(pos, player), -- knotenspezifischer Teil
|
||||
node_timer = func(pos, elapsed), -- knotenspezifischer Teil
|
||||
on_receive_fields = func(pos, formname, fields, player), -- knotenspez. Teil
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,1,2,4}, -- Verarbeitungsleistung in items/cycle
|
||||
power_consumption = {0,4,6,9}, -- Stromverbrauch (optional)
|
||||
}) --> node_name_ta2, node_name_ta3, node_name_ta4
|
||||
```
|
||||
|
||||
Diese `register_consumer` Funktion deckt alles generische ab, was ein Knoten bzgl. Power, Tubing, Kommandos (Status, on/off), formspec, swap_node(act/pas) benötigt, damit auch node_states, tubelib2.
|
||||
|
||||
Dabei werden auch bereits definiert:
|
||||
|
||||
- `push` und `pull` Richtung für das Tubing (links/rechts)
|
||||
- Umschalten des Knotens zwischen aktiv und passiv
|
||||
- `has_power` / `start_node` / `stop_node` / `on_power` / `on_nopower`
|
||||
- Unterstützung Achsenantrieb (TA2) oder Strom (TA3+)
|
||||
- Strom/Achsen von vorne oder hinten (alles andere muss selbst definiert werden)
|
||||
|
||||
Ein einfaches Beispiele dafür wäre: `pusher.lua`
|
||||
|
||||
**Es darf in `after_place_node` kein `tubelib2.init_mem(pos)` aufgerufen werden, sonst werden die Definitionen wieder zerstört!!!**
|
||||
|
||||
## Modul `networks`
|
||||
|
||||
Tubelib2 verwaltet nur 1:1 Beziehungen, keine Netzwerke. Dazu wurde `power` entwickelt. Allerdings lässt `power` nicht mehrere unterschiedliche Netzwerke pro Knoten zu, da die Daten nicht unterschiedenen werden können.
|
||||
|
||||
Deshalb wurde das Modul `networks.lua` entwickelt. Dies wird primär für Liquids benötigt, soll aber später `power` ablösen.
|
||||
|
||||
`liquid_pipe.lua` ist die erste Implementierung von `networks`.
|
||||
|
||||
### Anwendung
|
||||
|
||||
Um `networks` nutzen zu können muss tubelib2_on_update2 implementiert werden:
|
||||
|
||||
```lua
|
||||
tubelib2_on_update2 = function(pos, node, tlib2)
|
||||
networks.update_network(pos, tlib2)
|
||||
end,
|
||||
```
|
||||
|
||||
Zusätzlich muss eine Table pro Netzwerk angelegt werden:
|
||||
|
||||
```lua
|
||||
networks = {
|
||||
pipe = { -- network name/type
|
||||
sides = {R = 1}, -- connection sides for pipes
|
||||
ntype = "junc", -- node type
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
Durch die Abstufung in bspw. `pipe` sind parallel auch andere Netze möglich wie:
|
||||
|
||||
- `power` für Strom
|
||||
- `solar` für die roten Solarkabel
|
||||
- `steam` usw.
|
||||
|
||||
Im Speicher wird lediglich die Netzwerk ID gespeichert:
|
||||
|
||||
```lua
|
||||
mem.pipe.netID = val
|
||||
mem.solar.netID = val
|
||||
mem.power.netID = val
|
||||
```
|
||||
|
||||
Damit wird der Speicherbedarf pro Knoten drastisch reduziert. Allein schon deshalb macht die Umstellung von `power` auf `networks` Sinn.
|
||||
|
||||
### Implementierung
|
||||
|
||||
Die netID ist wie bei `power` die größte hash-Nummer aller Knoten-Positionen. Diese Nummer muss in jedem Knoten gespeichert werden.
|
||||
|
||||
Im Gegensatz zu `power` werden die `connections` zu anderen Knoten nicht mehr unter `mem`, sondern nur als eine Zahl in Node `meta` gespeichert. Dabei wird pro Richtungen (dir) nur ein Bit abgespeichert. Die Verbindung zum nächsten Knoten muss über `tlib2:get_connected_node_pos(pos, outdir)` bestimmt werden. Da tubelib2 diese Verbindungen auch schon im Cache speichert, sollte dies völlig ausreichend sein. Besonders dann, wenn für den Betrieb die `networks` Tabellen genutzt werden.
|
||||
|
||||
Bei jeder Änderung an Netzwerk wird folgendes aufgerufen:
|
||||
|
||||
```lua
|
||||
function techage.networks.update_network(pos, tlib2)
|
||||
node_connections(pos, tlib2)
|
||||
local netID = determine_netID(pos, tlib2)
|
||||
Networks[netID] = store_netID(pos, netID, tlib2)
|
||||
end
|
||||
```
|
||||
|
||||
Dabei werden:
|
||||
|
||||
- die Verbindingsinformationen im Knoten aktualisiert
|
||||
- die netID bestimmt und in allen Knoten gespeichert
|
||||
- die Netzwerk Tabellen generiert (pro Knotentyp `ntype` eine Tabelle)
|
||||
|
||||
Um bspw. alle Consumer durchzuklappern, kann dann einfach die Tabelle über
|
||||
|
||||
```
|
||||
networks.get_network(pos, Pipe).con
|
||||
```
|
||||
|
||||
abgerufen werden.
|
||||
|
||||
### API
|
||||
|
||||
`networks` setzt auch auf `sides`, wie `command` oder `power` und nutzt dafür aber seine eigenen Funktionen. Bei `power` fliegt das dann irgendwann raus, bei `command` evtl. auch??
|
||||
|
||||
```lua
|
||||
techage.networks.side_to_outdir(pos, side) -- beim after_place_node
|
||||
techage.networks.valid_indir(pos, indir, param2, net_name) -- bei bspw. on_push_item
|
||||
techage.networks.update_network(pos, tlib2) -- from tubelib2_on_update2
|
||||
techage.networks.get_network(pos, tlib2)
|
||||
techage.networks.get_network_table(pos, tlib2, ntype) -- comfort function
|
||||
techage.networks.connection_walk(pos, tlib2, clbk) -- classic way
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
## Anhang
|
||||
|
||||
### Unschönheiten
|
||||
|
||||
#### Problem: Verbindungen zu zwei Netzwerken
|
||||
|
||||
Es ist nicht möglich, einen Knoten in zwei unterschiedlichen Netzwerken (bspw. Strom, Dampf) über `techage.power.register_node()` anzumelden. `power` würde zweimal übereinander die gleichen Knoten-internen Variablen wie `mem.connections` im Knoten anlegen und nutzen. Das geht und muss schief gehen. Aktuell gibt es dafür keine Lösung.
|
||||
|
||||
### ToDo
|
||||
|
||||
- tubelib2.mem beschreiben
|
||||
- Aufteilung in node/meta/mem/cache beschreiben
|
||||
|
Loading…
Reference in New Issue
Block a user