work in progress to v2

This commit is contained in:
Joachim Stolberg 2018-12-22 16:58:11 +01:00
parent 46ed544d84
commit 041d6a684d
58 changed files with 1509 additions and 1253 deletions

@ -1,4 +1,27 @@
# TechPack V1.16
# TechPack V2.00 (WIP)
**THIS IS WORK IN PROGRESS**
**For your world use the stable release ![v1.16](https://github.com/joe7575/techpack/releases/tag/v1.16)**
## Planned for v2
- switch to library tubelib2
- introduce a new machine state model
- add new machine state "defect"
- add a tubelib Repair Kit for defect blocks
- Forceload block as part of tubelib
- support for intllib
## Current state
- Switch to tubelib2 is done (not fully tested).
- Pusher, Distributor, and Grinder already support the new state 'defect'. The AGING_VALUE is currently much to low. This is for testing only.
- The Repair Kit is available and can be used to repair defect machines.
- The mod 'basic_materials' is now needed for the Repair Kit.
- Due to server crashes I can happen that all loaded nodes loose their timers. Therefore, all "timed" nodes got an "on_node_load" function, which is used to restart the timer.
TechPack, a Mining, Crafting, & Farming Modpack for Minetest.

@ -3,16 +3,6 @@
Gravel Sieve Mod
================
v0.01 by JoSt
Derived from the work of RealBadAngel, Maciej Kasatkin (screwdriver)
Copyright (C) 2017 Joachim Stolberg
Copyright (C) 2013-2016 RealBadAngel, Maciej Kasatkin
Copyright (C) 2013-2016 Various Minetest developers and contributors
LGPLv2.1+
See LICENSE.txt for more information
]]--
@ -45,6 +35,7 @@ gravelsieve.handler = function(itemstack, user, pointed_thing)
loop=false})
end
itemstack:add_wear(65535 / (500 - 1))
return itemstack
end
@ -52,8 +43,7 @@ minetest.register_tool("gravelsieve:hammer", {
description = "Hammer converts Cobblestone into Gravel",
inventory_image = "gravelsieve_hammer.png",
on_use = function(itemstack, user, pointed_thing)
gravelsieve.handler(itemstack, user, pointed_thing)
return itemstack
return gravelsieve.handler(itemstack, user, pointed_thing)
end,
})

@ -424,12 +424,8 @@ if minetest.global_exists("tubelib") then
local meta = minetest.get_meta(pos)
return tubelib.put_item(meta, "dst", item)
end,
on_recv_message = function(pos, topic, payload)
if topic == "on" then
start_the_machine(pos)
elseif topic == "off" then
stop_the_machine(pos)
end
on_node_load = function(pos)
minetest.get_node_timer(pos):start(1.0)
end,
})
end

@ -491,4 +491,10 @@ tubelib.register_node("sl_controller:controller", {}, {
return "unsupported"
end
end,
on_node_load = function(pos)
local meta = minetest.get_meta(pos)
if meta:get_int("running") ~= tubelib.STATE_STOPPED then
minetest.get_node_timer(pos):start(1)
end
end,
})

@ -150,6 +150,9 @@ tubelib.register_node("sl_controller:server", {}, {
end
end
end,
on_node_load = function(pos)
minetest.get_node_timer(pos):start(20)
end,
})

@ -885,6 +885,12 @@ tubelib.register_node("smartline:controller", {}, {
return "unsupported"
end
end,
on_node_load = function(pos)
local meta = minetest.get_meta(pos)
if meta:get_int("state") == tubelib.RUNNING then
minetest.get_node_timer(pos):start(1)
end
end,
})
-- List of Controller actions and conditions is dependent on loaded mods.

@ -2,5 +2,6 @@ default
doors
tubelib
lcdlib
sl_controller
mail?

@ -156,3 +156,10 @@ else
})
end
tubelib.register_node("smartline:battery",
{"smartline:battery25", "smartline:battery50", "smartline:battery75"},
{
on_node_load = function(pos)
minetest.get_node_timer(pos):start(30)
end,
})

@ -505,5 +505,11 @@ tubelib.register_node("smartline:controller2", {}, {
return "unsupported"
end
end,
on_node_load = function(pos)
local meta = minetest.get_meta(pos)
if meta:get_int("state") == tubelib.RUNNING then
minetest.get_node_timer(pos):start(1)
end
end,
})

@ -220,5 +220,8 @@ tubelib.register_node("smartline:playerdetector", {"smartline:playerdetector_act
return meta:get_string("player_name")
end
end,
on_node_load = function(pos)
minetest.get_node_timer(pos):start(1.0)
end,
})

@ -124,4 +124,7 @@ tubelib.register_node("smartline:repeater", {}, {
return tubelib.send_message(numbers, owner, nil, topic, payload)
end
end,
on_node_load = function(pos)
minetest.get_node_timer(pos):start(1)
end,
})

@ -137,7 +137,7 @@ local function start_the_sequencer(pos)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", 1)
meta:set_int("running", RUNNING_STATE)
meta:set_int("index", 1)
meta:set_string("infotext", "SmartLine Sequencer "..number..": running (1/"..NUM_SLOTS..")")
local rules = minetest.deserialize(meta:get_string("rules"))
@ -282,4 +282,11 @@ tubelib.register_node("smartline:sequencer", {}, {
meta:set_int("endless", 0)
end
end,
on_node_load = function(pos)
local meta = minetest.get_meta(pos)
if meta:get_int("running") ~= STOP_STATE then
meta:set_int("running", RUNNING_STATE)
minetest.get_node_timer(pos):start(1)
end
end,
})

@ -215,6 +215,17 @@ minetest.register_node("smartline:timer", {
is_ground_content = false,
})
tubelib.register_node("smartline:timer", {}, {
on_node_load = function(pos)
local meta = minetest.get_meta(pos)
minetest.get_node_timer(pos):start(CYCLE_TIME)
-- check rules for just loaded areas
local done = {false,false,false,false,false,false}
meta:set_string("done", minetest.serialize(done))
check_rules(pos,0)
end,
})
minetest.register_craft({
output = "smartline:timer",
@ -224,20 +235,3 @@ minetest.register_craft({
{"", "default:mese_crystal", ""},
},
})
minetest.register_lbm({
label = "[SmartLine] Timer update",
name = "smartline:update",
nodenames = {"smartline:timer"},
run_at_every_load = true,
action = function(pos, node)
local meta = minetest.get_meta(pos)
-- check rules for just loaded areas
local done = {false,false,false,false,false,false}
meta:set_string("done", minetest.serialize(done))
check_rules(pos,0)
end
})

@ -29,12 +29,11 @@ Download: ![GitHub](https://github.com/joe7575/Minetest-Tubelib/archive/master.z
## Dependencies
default
tubelib2
basic_materials
# License
Copyright (C) 2017-2018 Joachim Stolberg
Code: Licensed under the GNU LGPL version 2.1 or later. See LICENSE.txt and http://www.gnu.org/licenses/lgpl-2.1.txt
Textures: CC0
## Dependencies
default

@ -14,7 +14,12 @@
]]--
-------------------------------------------------------------------
--- for lazy programmers
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local P = minetest.string_to_pos
local M = minetest.get_meta
------------------------------------------------------------------
-- Data base storage
-------------------------------------------------------------------
local storage = minetest.get_mod_storage()
@ -53,12 +58,7 @@ local Name2Name = {} -- translation table
local string_find = string.find
local string_split = string.split
local tubelib_NodeDef = tubelib.NodeDef
local get_neighbor_pos = tubelib.get_neighbor_pos
local read_node_with_vm = tubelib.read_node_with_vm
-- Translate from facedir to contact side of the other node
-- (left for one is right for the other node)
local FacedirToSide = {[0] = "F", "L", "B", "R", "U", "D"}
local Tube = tubelib.Tube
-- Generate a key string based on the given pos table,
-- Used internaly as table key,
@ -77,16 +77,6 @@ local function get_number(pos)
return string.format("%.04u", Key2Number[key])
end
-- Determine the contact side of the node at the given pos
-- param facedir: facedir to the node
local function get_node_side(npos, facedir)
local node = minetest.get_node_or_nil(npos) or read_node_with_vm(npos)
if facedir < 4 then
facedir = (facedir - node.param2 + 4) % 4
end
return FacedirToSide[facedir], node
end
local function generate_Key2Number()
local key
for num,item in pairs(Number2Pos) do
@ -109,6 +99,50 @@ local function not_protected(pos, placer_name, clicker_name)
return false
end
local function register_lbm(name, nodenames)
minetest.register_lbm({
label = "[Tubelib] Node update",
name = name.."update",
nodenames = nodenames,
run_at_every_load = true,
action = function(pos, node)
local name = Name2Name[node.name]
if tubelib_NodeDef[name] and tubelib_NodeDef[name].on_node_load then
tubelib_NodeDef[name].on_node_load(pos)
end
end
})
end
local DirToSide = {"B", "R", "F", "L", "D", "U"}
local function dir_to_side(dir, param2)
if dir < 5 then
dir = (((dir - 1) - (param2 % 4)) % 4) + 1
end
return DirToSide[dir]
end
local SideToDir = {B=1, R=2, F=3, L=4, D=5, U=6}
local function side_to_dir(side, param2)
local dir = SideToDir[side]
if dir < 5 then
dir = (((dir - 1) + (param2 % 4)) % 4) + 1
end
return dir
end
local function get_dest_node(pos, side)
local _,node = Tube:get_node(pos)
local dir = side_to_dir(side, node.param2)
local spos, sdir = Tube:get_connected_node_pos(pos, dir)
_,node = Tube:get_node(spos)
local in_side = dir_to_side(sdir, node.param2)
return spos, in_side, Name2Name[node.name] or node.name
end
-------------------------------------------------------------------
-- API helper functions
-------------------------------------------------------------------
@ -213,6 +247,8 @@ end
-- on_push_item = func(pos, side, item, player_name),
-- on_unpull_item = func(pos, side, item, player_name),
-- on_recv_message = func(pos, topic, payload),
-- on_node_load = func(pos), -- LBM function
-- on_node_repair = func(pos), -- repair defect (feature!) nodes
-- }
function tubelib.register_node(name, add_names, node_definition)
tubelib_NodeDef[name] = node_definition
@ -223,11 +259,22 @@ function tubelib.register_node(name, add_names, node_definition)
end
if node_definition.on_pull_item or node_definition.on_push_item or
node_definition.is_pusher then
Tube:add_secondary_node_names({name})
Tube:add_secondary_node_names(add_names)
tubelib.KnownNodes[name] = true
for _,n in ipairs(add_names) do
tubelib.KnownNodes[n] = true
end
end
-- register LBM
if node_definition.on_node_load then
local nodenames = {name}
for _,n in ipairs(add_names) do
nodenames[#nodenames + 1] = n
end
register_lbm(name, nodenames)
end
end
-------------------------------------------------------------------
@ -257,15 +304,23 @@ function tubelib.send_request(number, topic, payload)
return false
end
-- for defect nodes
function tubelib.repair_node(pos)
local node = minetest.get_node(pos)
local name = Name2Name[node.name]
if tubelib_NodeDef[name] and tubelib_NodeDef[name].on_node_repair then
return tubelib_NodeDef[name].on_node_repair(pos)
end
return false
end
-------------------------------------------------------------------
-- Client side Push/Pull item functions
-------------------------------------------------------------------
function tubelib.pull_items(pos, side, player_name)
local npos, facedir = get_neighbor_pos(pos, side)
local npos, nside, name = get_dest_node(pos, side)
if npos == nil then return end
local nside, node = get_node_side(npos, facedir)
local name = Name2Name[node.name]
if tubelib_NodeDef[name] and tubelib_NodeDef[name].on_pull_item then
return tubelib_NodeDef[name].on_pull_item(npos, nside, player_name)
end
@ -273,13 +328,11 @@ function tubelib.pull_items(pos, side, player_name)
end
function tubelib.push_items(pos, side, items, player_name)
local npos, facedir = get_neighbor_pos(pos, side)
local npos, nside, name = get_dest_node(pos, side)
if npos == nil then return end
local nside, node = get_node_side(npos, facedir)
local name = Name2Name[node.name]
if tubelib_NodeDef[name] and tubelib_NodeDef[name].on_push_item then
return tubelib_NodeDef[name].on_push_item(npos, nside, items, player_name)
elseif node.name == "air" then
elseif name == "air" then
minetest.add_item(npos, items)
return true
end
@ -287,10 +340,8 @@ function tubelib.push_items(pos, side, items, player_name)
end
function tubelib.unpull_items(pos, side, items, player_name)
local npos, facedir = get_neighbor_pos(pos, side)
local npos, nside, name = get_dest_node(pos, side)
if npos == nil then return end
local nside, node = get_node_side(npos, facedir)
local name = Name2Name[node.name]
if tubelib_NodeDef[name] and tubelib_NodeDef[name].on_unpull_item then
return tubelib_NodeDef[name].on_unpull_item(npos, nside, items, player_name)
end
@ -298,10 +349,8 @@ function tubelib.unpull_items(pos, side, items, player_name)
end
function tubelib.pull_stack(pos, side, player_name)
local npos, facedir = get_neighbor_pos(pos, side)
local npos, nside, name = get_dest_node(pos, side)
if npos == nil then return end
local nside, node = get_node_side(npos, facedir)
local name = Name2Name[node.name]
if tubelib_NodeDef[name] then
if tubelib_NodeDef[name].on_pull_stack then
return tubelib_NodeDef[name].on_pull_stack(npos, nside, player_name)
@ -483,6 +532,6 @@ generate_Key2Number()
-- maintain data after one minute
-- (minetest.get_day_count() will not be valid at start time)
minetest.after(60, data_maintenance)
minetest.after(5, data_maintenance)

@ -1 +1,4 @@
default
tubelib2
basic_materials

@ -12,20 +12,63 @@
A more complex node acting as server and client.
This node claims a position number and registers its message and items interface.
The Distributor supports the following messages:
The Distributor is based on the class NodeStates and supports the following messages:
- topic = "on", payload = nil
- topic = "off" , payload = nil
- topic = "state", payload = nil,
response is "running", "stopped", "standby", or "not supported"
]]--
-- for lazy programmers
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local P = minetest.string_to_pos
local M = minetest.get_meta
local MAX_NUM_PER_CYC = 20 -- maximum number of items, which can be pushed per slot
local NUM_FILTER_ELEM = 6
local NUM_FILTER_SLOTS = 4
local TICKS_TO_SLEEP = 5
local COUNTDOWN_TICKS = 6
local STANDBY_TICKS = 4
local CYCLE_TIME = 2
local STOP_STATE = 0
local STANDBY_STATE = -1
local State = tubelib.NodeStates:new({
node_name_passive = "tubelib:distributor",
node_name_active = "tubelib:distributor_active",
node_name_defect = "tubelib:distributor_defect",
infotext_name = "Tubelib Distributor",
cycle_time = CYCLE_TIME,
standby_ticks = STANDBY_TICKS,
aging_factor = 10,
})
local function formspec(pos, meta)
local filter = minetest.deserialize(meta:get_string("filter"))
return "size[10.5,8.5]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"list[context;src;0,0;2,4;]"..
"image[2,1.5;1,1;tubelib_gui_arrow.png]"..
"image_button[2,3;1,1;"..State:get_state_button_image(meta)..";state_button;]"..
"checkbox[3,0;filter1;On;"..dump(filter[1]).."]"..
"checkbox[3,1;filter2;On;"..dump(filter[2]).."]"..
"checkbox[3,2;filter3;On;"..dump(filter[3]).."]"..
"checkbox[3,3;filter4;On;"..dump(filter[4]).."]"..
"image[4,0;0.3,1;tubelib_red.png]"..
"image[4,1;0.3,1;tubelib_green.png]"..
"image[4,2;0.3,1;tubelib_blue.png]"..
"image[4,3;0.3,1;tubelib_yellow.png]"..
"list[context;red;4.5,0;6,1;]"..
"list[context;green;4.5,1;6,1;]"..
"list[context;blue;4.5,2;6,1;]"..
"list[context;yellow;4.5,3;6,1;]"..
"list[current_player;main;1.25,4.5;8,4;]"..
"listring[context;src]"..
"listring[current_player;main]"
end
State:register_formspec_func(formspec)
-- Return a key/value table with all items and the corresponding stack numbers
local function invlist_content_as_kvlist(list)
@ -83,34 +126,9 @@ local function num_items(moved_items, name, filter_item_names, rejected_item_nam
end
end
end
local function distributor_formspec(state, filter)
return "size[10.5,8.5]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"list[context;src;0,0;2,4;]"..
"image[2,1.5;1,1;tubelib_gui_arrow.png]"..
"image_button[2,3;1,1;".. tubelib.state_button(state) ..";button;]"..
"checkbox[3,0;filter1;On;"..dump(filter[1]).."]"..
"checkbox[3,1;filter2;On;"..dump(filter[2]).."]"..
"checkbox[3,2;filter3;On;"..dump(filter[3]).."]"..
"checkbox[3,3;filter4;On;"..dump(filter[4]).."]"..
"image[4,0;0.3,1;tubelib_red.png]"..
"image[4,1;0.3,1;tubelib_green.png]"..
"image[4,2;0.3,1;tubelib_blue.png]"..
"image[4,3;0.3,1;tubelib_yellow.png]"..
"list[context;red;4.5,0;6,1;]"..
"list[context;green;4.5,1;6,1;]"..
"list[context;blue;4.5,2;6,1;]"..
"list[context;yellow;4.5,3;6,1;]"..
"list[current_player;main;1.25,4.5;8,4;]"..
"listring[context;src]"..
"listring[current_player;main]"
end
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos)
local meta = M(pos)
local inv = meta:get_inventory()
local list = inv:get_list(listname)
@ -118,6 +136,9 @@ local function allow_metadata_inventory_put(pos, listname, index, stack, player)
return 0
end
if listname == "src" then
if State:get_state(M(pos)) == tubelib.STANDBY then
State:start(pos, meta)
end
return stack:get_count()
elseif invlist_num_entries(list) < MAX_NUM_PER_CYC then
return stack:get_count()
@ -133,7 +154,7 @@ local function allow_metadata_inventory_take(pos, listname, index, stack, player
end
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
local meta = minetest.get_meta(pos)
local meta = M(pos)
local inv = meta:get_inventory()
local stack = inv:get_stack(from_list, from_index)
return allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
@ -145,7 +166,7 @@ local FilterCache = {} -- local cache for filter settings
local function filter_settings(pos)
local hash = minetest.hash_node_position(pos)
local meta = minetest.get_meta(pos)
local meta = M(pos)
local inv = meta:get_inventory()
local filter = minetest.deserialize(meta:get_string("filter")) or {false,false,false,false}
local kvFilterItemNames = {} -- {<item:name> = true,...}
@ -169,54 +190,9 @@ local function filter_settings(pos)
}
end
local function start_the_machine(pos)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", TICKS_TO_SLEEP)
node.name = "tubelib:distributor_active"
minetest.swap_node(pos, node)
meta:set_string("infotext", "Tubelib Distributor "..number..": running")
local filter = minetest.deserialize(meta:get_string("filter"))
meta:set_string("formspec", distributor_formspec(tubelib.RUNNING, filter))
minetest.get_node_timer(pos):start(CYCLE_TIME)
return false
end
local function stop_the_machine(pos)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", STOP_STATE)
node.name = "tubelib:distributor"
minetest.swap_node(pos, node)
meta:set_string("infotext", "Tubelib Distributor "..number..": stopped")
local filter = minetest.deserialize(meta:get_string("filter"))
meta:set_string("formspec", distributor_formspec(tubelib.STOPPED, filter))
minetest.get_node_timer(pos):stop()
return false
end
local function goto_sleep(pos)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", STANDBY_STATE)
node.name = "tubelib:distributor"
minetest.swap_node(pos, node)
meta:set_string("infotext", "Tubelib Distributor "..number..": standby")
local filter = minetest.deserialize(meta:get_string("filter"))
meta:set_string("formspec", distributor_formspec(tubelib.STANDBY, filter))
minetest.get_node_timer(pos):start(CYCLE_TIME * TICKS_TO_SLEEP)
return false
end
-- move items to the output slots
local function keep_running(pos, elapsed)
local meta = minetest.get_meta(pos)
local running = meta:get_int("running") - 1
-- move items from configured filters to the output
local function distributing(pos, meta)
local player_name = meta:get_string("player_name")
--print("running", running)
local slot_idx = meta:get_int("slot_idx") or 1
meta:set_int("slot_idx", (slot_idx + 1) % NUM_FILTER_SLOTS)
local side = Num2Ascii[slot_idx+1]
@ -243,11 +219,10 @@ local function keep_running(pos, elapsed)
if items == nil then
-- this slot is empty
return true
return false
end
local busy = false
-- move items from configured filters to the output
if next(items) then
for _,item in ipairs(items) do
local name, num = item[1], item[2]
@ -289,30 +264,26 @@ local function keep_running(pos, elapsed)
FilterCache[hash].kvRejectedItemNames = {}
end
end
if busy == true then
if running <= 0 then
return start_the_machine(pos)
else
running = TICKS_TO_SLEEP
end
else
if running <= 0 then
return goto_sleep(pos)
end
end
meta:set_string("item_counter", minetest.serialize(counter))
meta:set_int("running", running)
return true
return busy
end
-- move items to the output slots
local function keep_running(pos, elapsed)
local meta = M(pos)
if distributing(pos, meta) then
State:keep_running(pos, meta, COUNTDOWN_TICKS)
else
State:idle(pos, meta)
end
return State:is_active(meta)
end
local function on_receive_fields(pos, formname, fields, player)
if minetest.is_protected(pos, player:get_player_name()) then
return
end
local meta = minetest.get_meta(pos)
local running = meta:get_int("running")
local meta = M(pos)
local filter = minetest.deserialize(meta:get_string("filter"))
if fields.filter1 ~= nil then
filter[1] = fields.filter1 == "true"
@ -327,21 +298,13 @@ local function on_receive_fields(pos, formname, fields, player)
filter_settings(pos)
if fields.button ~= nil then
if running > STOP_STATE then
stop_the_machine(pos)
else
start_the_machine(pos)
end
else
meta:set_string("formspec", distributor_formspec(tubelib.state(running), filter))
end
State:state_button_event(pos, fields)
end
-- tubelib command to turn on/off filter channels
local function change_filter_settings(pos, slot, val)
local slots = {["red"] = 1, ["green"] = 2, ["blue"] = 3, ["yellow"] = 4}
local meta = minetest.get_meta(pos)
local meta = M(pos)
local filter = minetest.deserialize(meta:get_string("filter"))
local num = slots[slot] or 1
if num >= 1 and num <= 4 then
@ -351,8 +314,7 @@ local function change_filter_settings(pos, slot, val)
filter_settings(pos)
local running = meta:get_int("running")
meta:set_string("formspec", distributor_formspec(tubelib.state(running), filter))
meta:set_string("formspec", formspec(pos, meta))
return true
end
@ -369,15 +331,13 @@ minetest.register_node("tubelib:distributor", {
},
after_place_node = function(pos, placer)
local meta = M(pos)
local number = tubelib.add_node(pos, "tubelib:distributor") -- <<=== tubelib
local meta = minetest.get_meta(pos)
local filter = {false,false,false,false}
meta:set_string("filter", minetest.serialize(filter))
State:node_init(pos, number)
meta:set_string("player_name", placer:get_player_name())
local filter = {false,false,false,false}
meta:set_string("formspec", distributor_formspec(tubelib.STOPPED, filter))
meta:set_string("filter", minetest.serialize(filter))
meta:set_string("number", number)
meta:set_string("infotext", "Tubelib Distributor "..number..": stopped")
local inv = meta:get_inventory()
inv:set_size('src', 8)
inv:set_size('yellow', 6)
@ -393,7 +353,7 @@ minetest.register_node("tubelib:distributor", {
if minetest.is_protected(pos, puncher:get_player_name()) then
return
end
local meta = minetest.get_meta(pos)
local meta = M(pos)
local inv = meta:get_inventory()
if inv:is_empty("src") then
minetest.node_dig(pos, node, puncher, pointed_thing)
@ -401,6 +361,10 @@ minetest.register_node("tubelib:distributor", {
end
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
State:after_dig_node(pos, oldnode, oldmetadata, digger)
end,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_take = allow_metadata_inventory_take,
allow_metadata_inventory_move = allow_metadata_inventory_move,
@ -455,6 +419,53 @@ minetest.register_node("tubelib:distributor_active", {
sounds = default.node_sound_wood_defaults(),
})
minetest.register_node("tubelib:distributor_defect", {
description = "Tubelib Distributor",
tiles = {
-- up, down, right, left, back, front
'tubelib_distributor.png',
'tubelib_distributor.png',
'tubelib_distributor_yellow.png^tubelib_defect.png',
'tubelib_distributor_green.png^tubelib_defect.png',
"tubelib_distributor_red.png^tubelib_defect.png",
"tubelib_distributor_blue.png^tubelib_defect.png",
},
after_place_node = function(pos, placer)
local meta = M(pos)
local number = tubelib.add_node(pos, "tubelib:distributor") -- <<=== tubelib
State:node_init(pos, number)
meta:set_string("player_name", placer:get_player_name())
local filter = {false,false,false,false}
meta:set_string("filter", minetest.serialize(filter))
local inv = meta:get_inventory()
inv:set_size('src', 8)
inv:set_size('yellow', 6)
inv:set_size('green', 6)
inv:set_size('red', 6)
inv:set_size('blue', 6)
meta:set_string("item_counter", minetest.serialize({red=0, green=0, blue=0, yellow=0}))
State:defect(pos, meta)
end,
on_receive_fields = on_receive_fields,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_take = allow_metadata_inventory_take,
allow_metadata_inventory_move = allow_metadata_inventory_move,
on_rotate = screwdriver.disallow,
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
groups = {crumbly=0, not_in_creative_inventory=1},
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})
minetest.register_craft({
output = "tubelib:distributor 2",
recipe = {
@ -466,29 +477,19 @@ minetest.register_craft({
--------------------------------------------------------------- tubelib
tubelib.register_node("tubelib:distributor", {"tubelib:distributor_active"}, {
tubelib.register_node("tubelib:distributor",
{"tubelib:distributor_active", "tubelib:distributor_defect"}, {
on_pull_item = function(pos, side)
local meta = minetest.get_meta(pos)
return tubelib.get_item(meta, "src")
return tubelib.get_item(M(pos), "src")
end,
on_push_item = function(pos, side, item)
local meta = minetest.get_meta(pos)
return tubelib.put_item(meta, "src", item)
return tubelib.put_item(M(pos), "src", item)
end,
on_unpull_item = function(pos, side, item)
local meta = minetest.get_meta(pos)
return tubelib.put_item(meta, "src", item)
return tubelib.put_item(M(pos), "src", item)
end,
on_recv_message = function(pos, topic, payload)
if topic == "on" then
return start_the_machine(pos)
elseif topic == "off" then
return stop_the_machine(pos)
elseif topic == "state" then
local meta = minetest.get_meta(pos)
local running = meta:get_int("running")
return tubelib.statestring(running)
elseif topic == "filter" then
if topic == "filter" then
return change_filter_settings(pos, payload.slot, payload.val)
elseif topic == "counter" then
local meta = minetest.get_meta(pos)
@ -497,9 +498,21 @@ tubelib.register_node("tubelib:distributor", {"tubelib:distributor_active"}, {
elseif topic == "clear_counter" then
local meta = minetest.get_meta(pos)
meta:set_string("item_counter", minetest.serialize({red=0, green=0, blue=0, yellow=0}))
else
return "unsupported"
else
local resp = State:on_receive_message(pos, topic, payload)
if resp then
return resp
else
return "unsupported"
end
end
end,
on_node_load = function(pos)
State:on_node_load(pos)
end,
on_node_repair = function(pos)
return State:on_node_repair(pos)
end,
})
--------------------------------------------------------------- tubelib

@ -24,6 +24,7 @@
- new tubing algorithm
- tubelib.pull_stack()/tubelib.get_stack() added
- item counter for pusher/distributor added
2018-12-21 v2.00 Switch to tubelib2, "defect" nodes and "repair kit" added
]]--
@ -32,7 +33,7 @@ tubelib = {
NodeDef = {}, -- node registration info
}
tubelib.version = 1.00
tubelib.version = 2.00
--------------------------- conversion to v0.04
@ -87,14 +88,17 @@ minetest.register_craft({
})
dofile(minetest.get_modpath("tubelib") .. "/tubes1.lua")
dofile(minetest.get_modpath("tubelib") .. "/tubes2.lua")
dofile(minetest.get_modpath("tubelib") .. "/tubes.lua")
dofile(minetest.get_modpath("tubelib") .. "/command.lua")
-- conversion from v1.16 to v2.00
dofile(minetest.get_modpath("tubelib") .. "/migrate.lua")
dofile(minetest.get_modpath("tubelib") .. "/states.lua")
dofile(minetest.get_modpath("tubelib") .. "/node_states.lua")
dofile(minetest.get_modpath("tubelib") .. "/pusher.lua")
dofile(minetest.get_modpath("tubelib") .. "/blackhole.lua")
dofile(minetest.get_modpath("tubelib") .. "/button.lua")
dofile(minetest.get_modpath("tubelib") .. "/lamp.lua")
dofile(minetest.get_modpath("tubelib") .. "/distributor.lua")
dofile(minetest.get_modpath("tubelib") .. "/legacy_nodes.lua")
dofile(minetest.get_modpath("tubelib") .. "/repairkit.lua")

74
tubelib/migrate.lua Normal file

@ -0,0 +1,74 @@
-- for lazy programmers
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local P = minetest.string_to_pos
local M = minetest.get_meta
local Tube = tubelib.Tube
local TubesTranslation = {
["tubelib:tube1"] = {[0]=
{12, "S"},
{21, "S"},
},
["tubelib:tube2"] = {[0]=
{ 4, "S"},
},
["tubelib:tube3"] = {[0]=
{ 5, "A"},
{14, "A"},
{11, "A"},
{ 7, "A"},
},
["tubelib:tube4"] = {[0]=
{ 0, "A"},
{15, "A"},
{ 8, "A"},
{ 3, "A"},
},
["tubelib:tube5"] = {[0]=
{20, "A"},
{13, "A"},
{10, "A"},
{19, "A"},
},
}
minetest.register_lbm({
label = "[Tubelib] tubes migration",
name = "tubelib:migrate",
nodenames = {
"tubelib:tube1",
"tubelib:tube2",
"tubelib:tube3",
"tubelib:tube4",
"tubelib:tube5",
"tubelib_addons3:teleporter",
},
run_at_every_load = true,
action = function(pos, node)
if node.name == "tubelib_addons3:teleporter" then
local meta = M(pos)
local peer = meta:get_string("peer")
if peer ~= "" then
meta:set_string("tele_pos", peer)
local peer_pos = P(peer)
local _,node = Tube:get_node(peer_pos)
local tube_dir = ((3 + (node.param2 % 4)) % 4) + 1
print("migration", peer, tube_dir)
if tube_dir then
meta:set_int("tube_dir", tube_dir)
end
tube_dir = Tube:get_primary_dir(pos)
Tube:tool_repair_tube(Tube:get_pos(pos, tube_dir))
end
else
local items = TubesTranslation[node.name][node.param2]
if items then
local param2, ntype = items[1], items[2]
minetest.set_node(pos, {name = "tubelib:tube"..ntype, param2 = param2})
end
end
end
})
minetest.register_node("tubelib:tube1", minetest.registered_nodes["tubelib:tubeS"])

427
tubelib/node_states.lua Normal file

@ -0,0 +1,427 @@
--[[
Tube Library
============
Copyright (C) 2017 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
node_states.lua:
A state model/class for tubelib nodes.
]]--
--[[
Node states:
+-----------------------------------+ +------------+
| | | |
| V V |
| +---------+ |
| | | |
| +---------| STOPPED | |
| | | | |
| button | +---------+ |
| | ^ |
repair | V | button |
| +---------+ | | button
| | |---------+ |
| | RUNNING | |
| +--------| |---------+ |
| | +---------+ | |
| | ^ | | |
| | | | | |
| V | V V |
| +---------+ +----------+ +---------+ |
| | | | | | | |
+---| DEFECT | | STANDBY/ | | FAULT |----------+
| | | BLOCKED | | |
+---------+ +----------+ +---------+
Node metadata:
"tubelib_number" - string with tubelib number, like "0123"
"tubelib_state" - node state, like "RUNNING"
"tubelib_item_meter" - node item/runtime counter
"tubelib_countdown" - countdown to stadby mode
"tubelib_aging" - aging counter
]]--
-- for lazy programmers
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local P = minetest.string_to_pos
local M = minetest.get_meta
local AGING_VALUE = 10 -- start aging value
local AGING_FACTOR = 3 -- defect random factor
--
-- Local States
--
local STOPPED = tubelib.STOPPED
local RUNNING = tubelib.RUNNING
local STANDBY = tubelib.STANDBY
local FAULT = tubelib.FAULT
local BLOCKED = tubelib.BLOCKED
local DEFECT = tubelib.DEFECT
--
-- NodeStates Class Functions
--
tubelib.NodeStates = {}
local NodeStates = tubelib.NodeStates
function NodeStates:new(attr)
local o = {
-- mandatory
cycle_time = attr.cycle_time, -- for running state
standby_ticks = attr.standby_ticks, -- for standby state
has_item_meter = attr.has_item_meter, -- true/false
-- optional
node_name_passive = attr.node_name_passive,
node_name_active = attr.node_name_active,
node_name_defect = attr.node_name_defect,
infotext_name = attr.infotext_name,
}
if attr.aging_factor then
o.aging_level1 = attr.aging_factor * AGING_VALUE
o.aging_level2 = attr.aging_factor * AGING_VALUE * AGING_FACTOR
end
setmetatable(o, self)
self.__index = self
return o
end
function NodeStates:register_formspec_func(func)
self.formspec_func = func
end
function NodeStates:node_init(pos, number)
local meta = M(pos)
meta:set_int("tubelib_state", STOPPED)
meta:set_string("tubelib_number", number)
if self.infotext_name then
meta:set_string("infotext", self.infotext_name.." "..number..": stopped")
end
if self.has_item_meter then
meta:set_int("tubelib_item_meter", 0)
end
if self.aging_level1 then
meta:set_int("tubelib_aging", 0)
end
if self.formspec_func then
meta:set_string("formspec", self.formspec_func(pos, meta))
end
end
function NodeStates:stop(pos, meta)
if meta:get_int("tubelib_state") ~= DEFECT then
meta:set_int("tubelib_state", STOPPED)
if self.node_name_passive then
local node = minetest.get_node(pos)
node.name = self.node_name_passive
minetest.swap_node(pos, node)
end
if self.infotext_name then
local number = meta:get_string("tubelib_number")
meta:set_string("infotext", self.infotext_name.." "..number..": stopped")
end
if self.formspec_func then
meta:set_string("formspec", self.formspec_func(pos, meta))
end
minetest.get_node_timer(pos):stop()
return true
end
return false
end
function NodeStates:start(pos, meta, called_from_on_timer)
local state = meta:get_int("tubelib_state")
if state == STOPPED or state == STANDBY or state == BLOCKED then
meta:set_int("tubelib_state", RUNNING)
if called_from_on_timer then
-- timer has to be stopped once to be able to be restarted
self.stop_timer = true
end
if self.node_name_active then
local node = minetest.get_node(pos)
node.name = self.node_name_active
minetest.swap_node(pos, node)
end
if self.infotext_name then
local number = meta:get_string("tubelib_number")
meta:set_string("infotext", self.infotext_name.." "..number..": running")
end
if self.formspec_func then
meta:set_string("formspec", self.formspec_func(pos, meta))
end
minetest.get_node_timer(pos):start(self.cycle_time)
return true
end
return false
end
function NodeStates:standby(pos, meta)
if meta:get_int("tubelib_state") == RUNNING then
meta:set_int("tubelib_state", STANDBY)
-- timer has to be stopped once to be able to be restarted
self.stop_timer = true
if self.node_name_passive then
local node = minetest.get_node(pos)
node.name = self.node_name_passive
minetest.swap_node(pos, node)
end
if self.infotext_name then
local number = meta:get_string("tubelib_number")
meta:set_string("infotext", self.infotext_name.." "..number..": standby")
end
if self.formspec_func then
meta:set_string("formspec", self.formspec_func(pos, meta))
end
minetest.get_node_timer(pos):start(self.cycle_time * self.standby_ticks)
return true
end
return false
end
-- special case of standby for pushing nodes
function NodeStates:blocked(pos, meta)
if meta:get_int("tubelib_state") == RUNNING then
meta:set_int("tubelib_state", BLOCKED)
-- timer has to be stopped once to be able to be restarted
self.stop_timer = true
if self.node_name_passive then
local node = minetest.get_node(pos)
node.name = self.node_name_passive
minetest.swap_node(pos, node)
end
if self.infotext_name then
local number = meta:get_string("tubelib_number")
meta:set_string("infotext", self.infotext_name.." "..number..": blocked")
end
if self.formspec_func then
meta:set_string("formspec", self.formspec_func(pos, meta))
end
minetest.get_node_timer(pos):start(self.cycle_time * self.standby_ticks)
return true
end
return false
end
function NodeStates:fault(pos, meta)
if meta:get_int("tubelib_state") == RUNNING then
meta:set_int("tubelib_state", FAULT)
if self.node_name_passive then
local node = minetest.get_node(pos)
node.name = self.node_name_passive
minetest.swap_node(pos, node)
end
if self.infotext_name then
local number = meta:get_string("tubelib_number")
meta:set_string("infotext", self.infotext_name.." "..number..": fault")
end
if self.formspec_func then
meta:set_string("formspec", self.formspec_func(pos, meta))
end
minetest.get_node_timer(pos):stop()
return true
end
return false
end
function NodeStates:defect(pos, meta)
meta:set_int("tubelib_state", DEFECT)
if self.node_name_defect then
local node = minetest.get_node(pos)
node.name = self.node_name_defect
minetest.swap_node(pos, node)
end
if self.infotext_name then
local number = meta:get_string("tubelib_number")
meta:set_string("infotext", self.infotext_name.." "..number..": defect")
end
if self.formspec_func then
meta:set_string("formspec", self.formspec_func(pos, meta))
end
minetest.get_node_timer(pos):stop()
return true
end
function NodeStates:get_state(meta)
return meta:get_int("tubelib_state")
end
function NodeStates:get_state_string(meta)
return tubelib.StateStrings[meta:get_int("tubelib_state")]
end
function NodeStates:is_active(meta)
local state = meta:get_int("tubelib_state")
if self.stop_timer == true then
self.stop_timer = false
return false
end
return state == RUNNING or state == STANDBY or state == BLOCKED
end
-- To be called if node is idle.
-- If countdown reaches zero, the node is set to STANDBY.
function NodeStates:idle(pos, meta)
local countdown = meta:get_int("tubelib_countdown") - 1
meta:set_int("tubelib_countdown", countdown)
if countdown < 0 then
self:standby(pos, meta)
end
end
-- To be called after successful node action to raise the timer
-- and keep the node in state RUNNING
function NodeStates:keep_running(pos, meta, val)
-- set to RUNNING if not already done
self:start(pos, meta, true)
meta:set_int("tubelib_countdown", val)
meta:set_int("tubelib_item_meter", meta:get_int("tubelib_item_meter") + 1)
if self.aging_level1 then
local cnt = meta:get_int("tubelib_aging") + 1
meta:set_int("tubelib_aging", cnt)
if cnt > (self.aging_level1) and math.random(self.aging_level2) == 1 then
self:defect(pos, meta)
end
end
end
-- Start/stop node based on button events.
-- if function returns false, no button was pressed
function NodeStates:state_button_event(pos, fields)
if fields.state_button ~= nil then
local state = self:get_state(M(pos))
if state == STOPPED or state == STANDBY or state == BLOCKED then
self:start(pos, M(pos))
elseif state == RUNNING or state == FAULT then
self:stop(pos, M(pos))
end
return true
end
return false
end
function NodeStates:get_state_button_image(meta)
local state = meta:get_int("tubelib_state")
return tubelib.state_button(state)
end
-- command interface
function NodeStates:on_receive_message(pos, topic, payload)
if topic == "on" then
self:start(pos, M(pos))
return true
elseif topic == "off" then
self:stop(pos, M(pos))
return true
elseif topic == "state" then
local node = minetest.get_node(pos)
if node.name == "ignore" then -- unloaded node?
return "blocked"
end
return self:get_state_string(M(pos))
elseif self.has_item_meter and topic == "counter" then
return M(pos):get_int("tubelib_item_meter")
elseif self.has_item_meter and topic == "clear_counter" then
M(pos):set_int("tubelib_item_meter", 0)
return true
elseif self.aging_level1 and topic == "aging" then
return M(pos):get_int("tubelib_aging")
end
end
-- repair corrupt node data and/or migrate node to state2
function NodeStates:on_node_load(pos)
local meta = minetest.get_meta(pos)
-- legacy node number/state/counter?
local number = meta:get_string("number")
if number ~= "" then
meta:set_string("tubelib_number", number)
meta:set_int("tubelib_state", tubelib.state(meta:get_int("running")))
if self.has_item_meter then
meta:set_int("tubelib_item_meter", meta:get_int("counter"))
end
if self.aging_level1 then
meta:set_int("tubelib_aging", 0)
end
meta:set_string("number", nil)
meta:set_int("running", 0)
meta:set_int("counter", 0)
end
-- node number corrupt?
number = meta:get_string("tubelib_number")
if number == "" then
number = tubelib.add_node(pos, self.node_name_passive)
meta:set_string("tubelib_number", number)
else
local info = tubelib.get_node_info(number)
if not info or info.pos ~= pos then
number = tubelib.add_node(pos, self.node_name_passive)
meta:set_string("tubelib_number", number)
end
end
-- state corrupt?
local state = meta:get_int("tubelib_state")
if state == 0 then
if minetest.get_node_timer(pos):is_started() then
meta:set_int("tubelib_state", RUNNING)
else
meta:set_int("tubelib_state", STOPPED)
end
elseif state == RUNNING then
minetest.get_node_timer(pos):start(self.cycle_time)
elseif state == STANDBY then
minetest.get_node_timer(pos):start(self.cycle_time * self.standby_ticks)
elseif state == BLOCKED then
minetest.get_node_timer(pos):start(self.cycle_time * self.standby_ticks)
end
end
-- Repair of defect (feature!) nodes
function NodeStates:on_node_repair(pos)
local meta = M(pos)
if meta:get_int("tubelib_state") == DEFECT then
meta:set_int("tubelib_state", STOPPED)
if self.node_name_passive then
local node = minetest.get_node(pos)
node.name = self.node_name_passive
minetest.swap_node(pos, node)
end
if self.aging_level1 then
meta:set_int("tubelib_aging", 0)
end
if self.infotext_name then
local number = meta:get_string("tubelib_number")
meta:set_string("infotext", self.infotext_name.." "..number..": stopped")
end
if self.formspec_func then
meta:set_string("formspec", self.formspec_func(pos, meta))
end
return true
end
return false
end
function NodeStates:after_dig_node(pos, oldnode, oldmetadata, digger)
local inv = minetest.get_inventory({type="player", name=digger:get_player_name()})
local cnt = oldmetadata.fields.tubelib_aging and tonumber(oldmetadata.fields.tubelib_aging) or 0
local is_defect = cnt > self.aging_level1 and math.random(self.aging_level2 / cnt) == 1
if self.node_name_defect and is_defect then
inv:add_item("main", ItemStack(self.node_name_defect))
else
inv:add_item("main", ItemStack(self.node_name_passive))
end
end

@ -13,7 +13,7 @@
Simple node for push/pull operation of StackItems from chests or other
inventory/server nodes to tubes or other inventory/server nodes.
The Pusher supports the following messages:
The Pusher is based on the class NodeStates and supports the following messages:
- topic = "on", payload = nil
- topic = "off", payload = nil
- topic = "state", payload = nil,
@ -29,83 +29,48 @@
-- | |/
-- +--------+
local RUNNING_STATE = 10
-- for lazy programmers
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local P = minetest.string_to_pos
local M = minetest.get_meta
local function switch_on(pos, node)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", RUNNING_STATE)
meta:set_string("infotext", "Pusher "..number..": running")
node.name = "tubelib:pusher_active"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):start(2)
return false
end
local STANDBY_TICKS = 5
local COUNTDOWN_TICKS = 5
local CYCLE_TIME = 2
local function switch_off(pos, node)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", tubelib.STATE_STOPPED)
meta:set_string("infotext", "Pusher "..number..": stopped")
node.name = "tubelib:pusher"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):stop()
return false
end
local State = tubelib.NodeStates:new({
node_name_passive = "tubelib:pusher",
node_name_active = "tubelib:pusher_active",
node_name_defect = "tubelib:pusher_defect",
infotext_name = "Tubelib Pusher",
cycle_time = CYCLE_TIME,
standby_ticks = STANDBY_TICKS,
has_item_meter = true,
aging_factor = 10,
})
local function goto_standby(pos, node)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", tubelib.STATE_STANDBY)
meta:set_string("infotext", "Pusher "..number..": standby")
node.name = "tubelib:pusher"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):start(20)
return false
end
local function goto_blocked(pos, node)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", tubelib.STATE_BLOCKED)
meta:set_string("infotext", "Pusher "..number..": blocked")
node.name = "tubelib:pusher"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):start(20)
return false
end
local function keep_running(pos, elapsed)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
local running = meta:get_int("running") - 1
local function pushing(pos, meta)
local player_name = meta:get_string("player_name")
local items = tubelib.pull_items(pos, "L", player_name) -- <<=== tubelib
if items ~= nil then
if tubelib.push_items(pos, "R", items, player_name) == false then -- <<=== tubelib
-- place item back
tubelib.unpull_items(pos, "L", items, player_name) -- <<=== tubelib
local node = minetest.get_node(pos)
return goto_blocked(pos, node)
end
meta:set_int("item_counter", meta:get_int("item_counter") + 1)
if running <= 0 then
local node = minetest.get_node(pos)
return switch_on(pos, node)
else
-- reload running state
running = RUNNING_STATE
end
else
if running <= 0 then
local node = minetest.get_node(pos)
return goto_standby(pos, node)
State:blocked(pos, meta)
return
end
State:keep_running(pos, meta, COUNTDOWN_TICKS)
return
end
meta:set_int("running", running)
return true
State:idle(pos, meta)
end
local function keep_running(pos, elapsed)
local meta = M(pos)
pushing(pos, meta)
return State:is_active(meta)
end
minetest.register_node("tubelib:pusher", {
description = "Tubelib Pusher",
tiles = {
@ -122,24 +87,24 @@ minetest.register_node("tubelib:pusher", {
local meta = minetest.get_meta(pos)
meta:set_string("player_name", placer:get_player_name())
local number = tubelib.add_node(pos, "tubelib:pusher") -- <<=== tubelib
meta:set_string("number", number)
meta:set_string("infotext", "Pusher "..number..": stopped")
meta:set_int("item_counter", 0)
State:node_init(pos, number)
end,
on_rightclick = function(pos, node, clicker)
if not minetest.is_protected(pos, clicker:get_player_name()) then
switch_on(pos, node)
State:start(pos, M(pos))
end
end,
after_dig_node = function(pos)
after_dig_node = function(pos, oldnode, oldmetadata, digger)
tubelib.remove_node(pos) -- <<=== tubelib
State:after_dig_node(pos, oldnode, oldmetadata, digger)
end,
on_timer = keep_running,
on_rotate = screwdriver.disallow,
drop = "",
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
@ -199,7 +164,7 @@ minetest.register_node("tubelib:pusher_active", {
on_rightclick = function(pos, node, clicker)
if not minetest.is_protected(pos, clicker:get_player_name()) then
switch_off(pos, node)
State:stop(pos, M(pos))
end
end,
@ -214,6 +179,42 @@ minetest.register_node("tubelib:pusher_active", {
sounds = default.node_sound_wood_defaults(),
})
minetest.register_node("tubelib:pusher_defect", {
description = "Tubelib Pusher",
tiles = {
-- up, down, right, left, back, front
'tubelib_pusher1.png',
'tubelib_pusher1.png',
'tubelib_outp.png^tubelib_defect.png',
'tubelib_inp.png^tubelib_defect.png',
"tubelib_pusher1.png^[transformR180]^tubelib_defect.png",
"tubelib_pusher1.png^tubelib_defect.png",
},
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos)
meta:set_string("player_name", placer:get_player_name())
local number = tubelib.add_node(pos, "tubelib:pusher") -- <<=== tubelib
State:node_init(pos, number)
State:defect(pos, meta)
end,
after_dig_node = function(pos)
tubelib.remove_node(pos) -- <<=== tubelib
end,
on_timer = keep_running,
on_rotate = screwdriver.disallow,
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
groups = {choppy=2, cracky=2, crumbly=2, not_in_creative_inventory=1},
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})
minetest.register_craft({
output = "tubelib:pusher 2",
recipe = {
@ -224,34 +225,26 @@ minetest.register_craft({
})
--------------------------------------------------------------- tubelib
tubelib.register_node("tubelib:pusher", {"tubelib:pusher_active"}, {
tubelib.register_node("tubelib:pusher",
{"tubelib:pusher_active", "tubelib:pusher_defect"}, {
on_pull_item = nil, -- pusher has no inventory
on_push_item = nil, -- pusher has no inventory
on_unpull_item = nil, -- pusher has no inventory
is_pusher = true, -- is a pulling/pushing node
on_recv_message = function(pos, topic, payload)
local node = minetest.get_node(pos)
if topic == "on" then
return switch_on(pos, node)
elseif topic == "off" then
return switch_off(pos, node)
elseif topic == "state" then
if node.name == "ignore" then -- unloaded pusher?
return "blocked"
end
local meta = minetest.get_meta(pos)
local running = meta:get_int("running") or tubelib.STATE_STOPPED
return tubelib.statestring(running)
elseif topic == "counter" then
local meta = minetest.get_meta(pos)
return meta:get_int("item_counter")
elseif topic == "clear_counter" then
local meta = minetest.get_meta(pos)
return meta:set_int("item_counter", 0)
local resp = State:on_receive_message(pos, topic, payload)
if resp then
return resp
else
return "not supported"
return "unsupported"
end
end,
on_node_load = function(pos)
State:on_node_load(pos)
end,
on_node_repair = function(pos)
return State:on_node_repair(pos)
end,
})
--------------------------------------------------------------- tubelib

82
tubelib/repairkit.lua Normal file

@ -0,0 +1,82 @@
--[[
Tube Library
============
Copyright (C) 2017-2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
repairkit.lua:
]]--
-- for lazy programmers
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local P = minetest.string_to_pos
local M = minetest.get_meta
local function repair_node(itemstack, user, pointed_thing)
local pos = pointed_thing.under
if pos then
if tubelib.repair_node(pos) then
minetest.chat_send_player(user:get_player_name(), "[Tubelib] Node repaired")
itemstack:take_item()
return itemstack
end
end
return
end
local function read_state(itemstack, user, pointed_thing)
local pos = pointed_thing.under
if pos then
local number = tubelib.get_node_number(pos)
if number then
local state = tubelib.send_request(number, "state", nil)
local counter = tubelib.send_request(number, "counter", nil)
local aging = tubelib.send_request(number, "aging", nil)
if state and counter and aging then
minetest.chat_send_player(user:get_player_name(), "[Tubelib] state ="..state..", counter = "..counter..", aging = "..aging)
end
end
end
end
minetest.register_craftitem("tubelib:repairkit", {
description = "Tubelib Repair Kit",
inventory_image = "tubelib_repairkit.png",
wield_image = "tubelib_repairkit.png^[transformR270",
groups = {cracky=1, book=1},
on_use = repair_node,
node_placement_prediction = "",
})
minetest.register_node("tubelib:end_wrench", {
description = "Tubelib End Wrench",
inventory_image = "tubelib_end_wrench.png",
wield_image = "tubelib_end_wrench.png",
groups = {cracky=1, book=1},
on_use = read_state,
node_placement_prediction = "",
})
minetest.register_craft({
output = "tubelib:repairkit",
recipe = {
{"", "basic_materials:gear_steel", ""},
{"", "tubelib:end_wrench", ""},
{"", "basic_materials:oil_extract", ""},
},
})
minetest.register_craft({
output = "tubelib:end_wrench 4",
recipe = {
{"", "", "default:steel_ingot"},
{"", "default:tin_ingot", ""},
{"default:steel_ingot", "", ""},
},
})

@ -15,35 +15,41 @@
]]--
--
-- Inventory Button States
-- Tubelib machine states
--
tubelib.STOPPED = 1 -- not operational
tubelib.RUNNING = 2 -- in normal operation
tubelib.STANDBY = 3 -- nothing to do or blocked anyhow
tubelib.FAULT = 4 -- any fault state, which has to be fixed by the player
tubelib.STOPPED = 1 -- not operational/turned off
tubelib.RUNNING = 2 -- in normal operation/turned on
tubelib.STANDBY = 3 -- nothing to do (e.g. no input items), or blocked anyhow (output jammed),
-- or node (world) not loaded
tubelib.FAULT = 4 -- any fault state (e.g. no fuel), which can be fixed by the player
tubelib.BLOCKED = 5 -- a pushing node is blocked due to a full destination inventory
tubelib.DEFECT = 6 -- a defect (broken), which has to be repaired by the player
tubelib.StatesImg = {
"tubelib_inv_button_off.png",
"tubelib_inv_button_on.png",
"tubelib_inv_button_standby.png",
"tubelib_inv_button_error.png"
"tubelib_inv_button_error.png",
"tubelib_inv_button_error.png",
"tubelib_inv_button_off.png",
}
-- Return state button image for the node inventory
function tubelib.state_button(state)
if state and state < 5 and state > 0 then
if state and state < 7 and state > 0 then
return tubelib.StatesImg[state]
end
return tubelib.StatesImg[tubelib.FAULT]
return "tubelib_inv_button_off.png"
end
-- State string based on button states
tubelib.states = {"stopped", "running", "standby", "fault"}
tubelib.StateStrings = {"stopped", "running", "standby", "fault", "blocked", "defect"}
--
-- 'running' variable States
-- 'running' variable States (deprecated)
--
tubelib.STATE_RUNNING = 1 -- in normal operation

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 B

After

Width:  |  Height:  |  Size: 113 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 470 B

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 486 B

After

Width:  |  Height:  |  Size: 499 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 476 B

After

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 479 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 449 B

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 B

After

Width:  |  Height:  |  Size: 113 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 B

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 B

After

Width:  |  Height:  |  Size: 194 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 B

After

Width:  |  Height:  |  Size: 113 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 B

After

Width:  |  Height:  |  Size: 113 B

130
tubelib/tubes.lua Normal file

@ -0,0 +1,130 @@
--[[
Tubes based on tubelib2
=======================
Copyright (C) 2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
tubes.lua: Node registration and API functions to move items via tubes
]]--
-- used for registered nodes
tubelib.KnownNodes = {
["tubelib:tubeS"] = true,
["tubelib:tubeA"] = true,
}
local Tube = tubelib2.Tube:new({
-- North, East, South, West, Down, Up
dirs_to_check = {1,2,3,4,5,6},
max_tube_length = 200,
show_infotext = false,
primary_node_names = {"tubelib:tubeS", "tubelib:tubeA"},
after_place_tube = function(pos, param2, tube_type, num_tubes, tbl)
minetest.swap_node(pos, {name = "tubelib:tube"..tube_type, param2 = param2})
end,
})
tubelib.Tube = Tube
minetest.register_node("tubelib:tubeS", {
description = "Tubelib Tube",
tiles = { -- Top, base, right, left, front, back
"tubelib_tube.png^[transformR90",
"tubelib_tube.png^[transformR90",
"tubelib_tube.png",
"tubelib_tube.png",
"tubelib_hole.png",
"tubelib_hole.png",
},
after_place_node = function(pos, placer, itemstack, pointed_thing)
if not Tube:after_place_tube(pos, placer, pointed_thing) then
minetest.remove_node(pos)
return true
end
return false
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Tube:after_dig_tube(pos, oldnode, oldmetadata)
end,
paramtype2 = "facedir",
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-2/8, -2/8, -4/8, 2/8, 2/8, 4/8},
},
},
selection_box = {
type = "fixed",
fixed = { -1/4, -1/4, -1/2, 1/4, 1/4, 1/2 },
},
collision_box = {
type = "fixed",
fixed = { -1/4, -1/4, -1/2, 1/4, 1/4, 1/2 },
},
on_rotate = screwdriver.disallow,
paramtype = "light",
sunlight_propagates = true,
is_ground_content = false,
groups = {choppy=2, cracky=3, stone=1},
sounds = default.node_sound_wood_defaults(),
})
minetest.register_node("tubelib:tubeA", {
description = "Tubelib Tube",
tiles = { -- Top, base, right, left, front, back
"tubelib_knee2.png",
"tubelib_hole2.png^[transformR180",
"tubelib_knee.png^[transformR270",
"tubelib_knee.png",
"tubelib_knee2.png",
"tubelib_hole2.png",
},
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Tube:after_dig_tube(pos, oldnode, oldmetadata)
end,
paramtype2 = "facedir",
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-2/8, -4/8, -2/8, 2/8, 2/8, 2/8},
{-2/8, -2/8, -4/8, 2/8, 2/8, -2/8},
},
},
selection_box = {
type = "fixed",
fixed = { -1/4, -1/2, -1/2, 1/4, 1/4, 1/4 },
},
collision_box = {
type = "fixed",
fixed = { -1/4, -1/2, -1/2, 1/4, 1/4, 1/4 },
},
on_rotate = screwdriver.disallow,
paramtype = "light",
sunlight_propagates = true,
is_ground_content = false,
groups = {choppy=2, cracky=3, stone=1, not_in_creative_inventory=1},
sounds = default.node_sound_wood_defaults(),
drop = "tubelib:tubeS",
})
minetest.register_craft({
output = "tubelib:tubeS 4",
recipe = {
{"default:steel_ingot", "", "group:wood"},
{"", "group:wood", ""},
{"group:wood", "", "default:tin_ingot"},
},
})

@ -1,294 +0,0 @@
--[[
Tube Library
============
Copyright (C) 2017-2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
History:
see init.lua
tubes1.lua: Functions to place and remove tubes
]]--
-- debugging
local P = minetest.pos_to_string
local MAX_TUBE_LENGTH = 100
-- Conversion from tube number/param2 (number*10 + param2) to tube hole dirs (view from the inside)
local TubeDirs = {
[10] = {1,3},
[11] = {2,4},
[12] = {1,3},
[13] = {2,4},
[20] = {5,6},
[21] = {5,6},
[22] = {5,6},
[23] = {5,6},
[30] = {3,4},
[31] = {1,4},
[32] = {1,2},
[33] = {2,3},
[40] = {3,5},
[41] = {4,5},
[42] = {1,5},
[43] = {2,5},
[50] = {3,6},
[51] = {4,6},
[52] = {1,6},
[53] = {2,6},
}
-- Conversion from tube dirs (dir1 * 10 + dir2) to tube number/param2
local TubeNodeAttr = {}
for k,v in pairs(TubeDirs) do
local key = v[1] * 10 + v[2]
local number = math.floor(k / 10)
local param2 = k % 10
TubeNodeAttr[key] = {number = number, param2 = param2}
end
-- Convertion of 'dir' (view from the outside to inside and vs)
local Turn180Deg = {3,4,1,2,6,5}
local Turn90Deg = {2,3,4,5,6,1}
local Dir2Offset = {
{x=0, y=0, z=1},
{x=1, y=0, z=0},
{x=0, y=0, z=-1},
{x=-1, y=0, z=0},
{x=0, y=-1, z=0},
{x=0, y=1, z=0}
}
tubelib.TubeNames = {
["tubelib:tube1"] = true,
["tubelib:tube2"] = true,
["tubelib:tube3"] = true,
["tubelib:tube4"] = true,
["tubelib:tube5"] = true,
}
-- used for registered nodes
tubelib.KnownNodes = {
["tubelib:tube1"] = true,
["tubelib:tube2"] = true,
["tubelib:tube3"] = true,
["tubelib:tube4"] = true,
["tubelib:tube5"] = true,
}
-- use Voxel Manipulator to read the node
function tubelib.read_node_with_vm(pos)
local vm = VoxelManip()
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})
return {
name = minetest.get_name_from_content_id(data[area:index(pos.x, pos.y, pos.z)]),
param2 = param2_data[area:index(pos.x, pos.y, pos.z)]
}
end
local function get_tube_number_and_param2(dir1, dir2)
if dir1 == dir2 then
dir2 = Turn180Deg[dir1]
end
if dir1 > dir2 then
dir1, dir2 = dir2, dir1
end
local item = TubeNodeAttr[dir1*10 + dir2]
return item.number, item.param2
end
-- convert 6D-dir to position
local function get_tube_pos(pos, dir)
return vector.add(pos, Dir2Offset[dir])
end
-- Tube open sides
local function get_tube_dirs(pos, node)
if node == nil then
node = minetest.get_node_or_nil(pos) or tubelib.read_node_with_vm(pos)
end
if tubelib.TubeNames[node.name] then
local ttype = (string.byte(node.name, -1) - 48) * 10 + node.param2
return TubeDirs[ttype][1], TubeDirs[ttype][2]
end
return nil, nil
end
function tubelib.get_next_tube(pos, dir)
pos = get_tube_pos(pos, dir)
local dir1, dir2 = get_tube_dirs(pos)
if dir1 then
dir = Turn180Deg[dir]
if dir == dir1 then
return pos, dir2
elseif dir == dir2 then
return pos, dir1
end
end
return pos, nil
end
local function is_known_node(pos, dir)
if dir then
pos = get_tube_pos(pos, dir)
local node = minetest.get_node_or_nil(pos) or tubelib.read_node_with_vm(pos)
if tubelib.KnownNodes[node.name] and not tubelib.TubeNames[node.name] then
return true
end
end
return false
end
-- Walk to the other end of the tube line, starting at 'pos/dir'.
-- Returns: cnt - number of tube nodes
-- pos - the peer tube node
-- dir - dir to the drop position, next after 'pos'
function tubelib.walk_to_peer(pos, dir)
local cnt = 0
while cnt < MAX_TUBE_LENGTH do
local new_pos, new_dir = tubelib.get_next_tube(pos, dir)
if not new_dir then
break
end
cnt = cnt + 1
pos, dir = new_pos, new_dir
end
return cnt, pos, dir
end
-- Delete meta data of the peer node
function tubelib.delete_meta_data(pos, node)
local dir1, dir2 = get_tube_dirs(pos, node)
local cnt1 = 0
local dir, npos
if dir1 then
cnt1, npos, dir = tubelib.walk_to_peer(pos, dir1)
-- delete meta on peer tube
if cnt1 > 0 then
minetest.get_meta(npos):from_table(nil)
end
end
local cnt2 = 0
if dir2 then
cnt2, npos, dir = tubelib.walk_to_peer(pos, dir2)
-- delete meta on peer tube
if cnt2 > 0 then
minetest.get_meta(npos):from_table(nil)
end
end
return cnt1 + cnt2
end
local function swap_node(pos, node_num, param2)
local node = minetest.get_node(pos)
node.name = "tubelib:tube"..node_num
node.param2 = param2
minetest.swap_node(pos, node)
end
local function is_connected(pos, dir)
if dir then
pos = get_tube_pos(pos, dir)
local dir1,dir2 = get_tube_dirs(pos)
-- return true if connected
dir = Turn180Deg[dir]
return dir == dir1 or dir == dir2
end
return false
end
local function is_tubelib_block(pos, dir)
if dir then
pos = get_tube_pos(pos, dir)
local dir1,dir2 = get_tube_dirs(pos)
-- return true if connected
dir = Turn180Deg[dir]
return dir == dir1 or dir == dir2
end
return false
end
local function update_next_tube(dir, pos)
-- test if tube is connected with neighbor tubes
local dir1, dir2 = get_tube_dirs(pos)
local conn1 = is_connected(pos, dir1) or is_known_node(pos, dir1)
local conn2 = is_connected(pos, dir2) or is_known_node(pos, dir2)
-- already connected or no tube arround?
if (conn1 and conn2) or (not dir1 and not dir2) then
return
elseif not conn1 and not conn2 then
if dir1 ~= dir and dir2 ~= dir then
dir1 = Turn90Deg[dir1]
dir2 = Turn180Deg[dir1]
end
elseif conn1 then
dir2 = Turn180Deg[dir]
else
dir1 = Turn180Deg[dir]
end
local node_num, param2 = get_tube_number_and_param2(dir1, dir2)
swap_node(pos, node_num, param2)
end
-- update new placed tube
local function update_tube(pos, dir, force_dir)
local dir1 = nil
local dir2 = nil
-- use the predefined direction?
if force_dir then
dir1 = force_dir
end
-- search on all 6 pos for up to 2 tubes with open holes or
-- other tubelib compatible nodes
for ndir = 1,6 do
if not dir1 and is_connected(pos, ndir) then
dir1 = ndir
elseif not dir2 and is_connected(pos, ndir) and ndir ~= dir1 then
dir2 = ndir
end
end
if not force_dir and (not dir1 or not dir2) then
for ndir = 1,6 do
if not dir1 and is_known_node(pos, ndir) then
dir1 = ndir
elseif not dir2 and is_known_node(pos, ndir) and ndir ~= dir1 then
dir2 = ndir
end
end
end
dir1 = dir1 or dir
dir2 = dir2 or Turn180Deg[dir]
local node_num, param2 = get_tube_number_and_param2(dir1, dir2)
swap_node(pos, node_num, param2)
end
function tubelib.update_tubes(pos, dir, force_dir, straight_ahead)
-- Update all tubes arround the currently placed tube
update_next_tube(1, {x=pos.x , y=pos.y , z=pos.z+1})
update_next_tube(2, {x=pos.x+1, y=pos.y , z=pos.z })
update_next_tube(3, {x=pos.x , y=pos.y , z=pos.z-1})
update_next_tube(4, {x=pos.x-1, y=pos.y , z=pos.z })
update_next_tube(5, {x=pos.x , y=pos.y-1, z=pos.z })
update_next_tube(6, {x=pos.x , y=pos.y+1, z=pos.z })
if not straight_ahead then
-- Update the placed tube
update_tube(pos, dir, force_dir)
end
return tubelib.delete_meta_data(pos, minetest.get_node(pos)) < MAX_TUBE_LENGTH
end

@ -1,230 +0,0 @@
--[[
Tube Library
============
Copyright (C) 2017-2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
History:
see init.lua
tubes2.lua: Node registration and API functions to move items via tubes
]]--
-- Convertion of contact side to facedir
local SideToFacedir = {B=0, R=1, F=2, L=3, D=4, U=5}
-- Calculate the facedir to the other node, based on both node positions
local function dir_to_facedir(my_pos, other_pos)
if my_pos.z ~= other_pos.z then return my_pos.z - other_pos.z + 1 end
if my_pos.x ~= other_pos.x then return my_pos.x - other_pos.x + 2 end
if my_pos.y > other_pos.y then return 5 else return 4 end
end
local function remote_node(pos, dir)
local meta = minetest.get_meta(pos)
local cnt
-- legacy tube?
if meta:get_string("dest_pos2") ~= "" then
meta:from_table(nil)
end
-- data available
local dest_pos = meta:get_string("dest_pos")
if dest_pos ~= "" then
local npos = minetest.string_to_pos(dest_pos)
local facedir = meta:get_int("facedir")
return npos, facedir+1
end
-- determine data and store as meta
cnt, pos, dir = tubelib.walk_to_peer(pos, dir)
local pos1,_ = tubelib.get_next_tube(pos, dir)
meta:set_string("dest_pos", minetest.pos_to_string(pos1))
meta:set_int("facedir", dir - 1)
return pos1, dir
end
local function is_known_node(pointed_thing)
if pointed_thing.type == "node" then
local node = minetest.get_node(pointed_thing.under)
if tubelib.KnownNodes[node.name] then
return pointed_thing.under
end
end
return nil
end
-- Determine neighbor position and own facedir to the node.
-- based on own pos and contact side 'B' - 'U'.
-- Function considers also tube connections.
function tubelib.get_neighbor_pos(pos, side)
local facedir = SideToFacedir[side]
local dir
if facedir < 4 then
local node = minetest.get_node(pos)
dir = ((facedir + node.param2) % 4) + 1
end
local npos, ndir = tubelib.get_next_tube(pos, dir)
local node = minetest.get_node(npos)
if tubelib.TubeNames[node.name] then
if ndir then
npos, ndir = remote_node(npos, ndir)
end
return npos, (ndir or 1) -1
end
return npos, facedir
end
-------------------------------------------------------------------------------
-- Node registration
-------------------------------------------------------------------------------
local DefNodeboxes = {
-- x1 y1 z1 x2 y2 z2
{ -1/4, -1/4, -1/4, 1/4, 1/4, 1/4 },
{ -1/4, -1/4, -1/4, 1/4, 1/4, 1/4 },
}
local DirCorrections = {
{3, 6}, {2, 5}, -- standard tubes
{3, 1}, {3, 2}, {3, 5}, -- knees from front to..
}
local SelectBoxes = {
{ -1/4, -1/4, -1/2, 1/4, 1/4, 1/2 },
{ -1/4, -1/2, -1/4, 1/4, 1/2, 1/4 },
{ -1/2, -1/4, -1/2, 1/4, 1/4, 1/4 },
{ -1/4, -1/2, -1/2, 1/4, 1/4, 1/4 },
{ -1/4, -1/4, -1/2, 1/4, 1/2, 1/4 },
}
local TilesData = {
-- up, down, right, left, back, front
{
"tubelib_tube.png^[transformR90",
"tubelib_tube.png^[transformR90",
"tubelib_tube.png",
"tubelib_tube.png",
"tubelib_hole.png",
"tubelib_hole.png",
},
{
"tubelib_hole.png",
"tubelib_hole.png",
"tubelib_tube.png^[transformR90",
"tubelib_tube.png^[transformR90",
"tubelib_tube.png^[transformR90",
"tubelib_tube.png^[transformR90",
},
{
"tubelib_knee.png^[transformR270",
"tubelib_knee.png^[transformR180",
"tubelib_knee2.png^[transformR270",
"tubelib_hole2.png^[transformR90",
"tubelib_knee2.png^[transformR90",
"tubelib_hole2.png^[transformR270",
},
{
"tubelib_knee2.png",
"tubelib_hole2.png^[transformR180",
"tubelib_knee.png^[transformR270",
"tubelib_knee.png",
"tubelib_knee2.png",
"tubelib_hole2.png",
},
{
"tubelib_hole2.png",
"tubelib_knee2.png^[transformR180",
"tubelib_knee.png^[transformR180",
"tubelib_knee.png^[transformR90",
"tubelib_knee2.png^[transformR180",
"tubelib_hole2.png^[transformR180",
},
}
for idx,pos in ipairs(DirCorrections) do
local node_box_data = table.copy(DefNodeboxes)
node_box_data[1][pos[1]] = node_box_data[1][pos[1]] * 2
node_box_data[2][pos[2]] = node_box_data[2][pos[2]] * 2
local tiles_data = TilesData[idx]
local hidden
if idx == 1 then
hidden = 0
else
hidden = 1
end
minetest.register_node("tubelib:tube"..idx, {
description = "Tubelib Tube",
tiles = tiles_data,
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = node_box_data,
},
selection_box = {
type = "fixed",
fixed = SelectBoxes[idx],
},
collision_box = {
type = "fixed",
fixed = SelectBoxes[idx],
},
after_place_node = function(pos, placer, itemstack, pointed_thing)
local dir1 = nil
local dir2 = nil
local pitch = placer:get_look_pitch()
local known_pos = is_known_node(pointed_thing)
local straight_ahead = placer:get_player_control().sneak and not known_pos
if known_pos and placer:get_player_control().sneak then -- placer pointed to a known node (chest)
dir2 = dir_to_facedir(pos, known_pos) + 1
end
if pitch > 1 then -- up?
dir1 = 6
elseif pitch < -1 then -- down?
dir1 = 5
else
dir1 = minetest.dir_to_facedir(placer:get_look_dir()) + 1
end
if not tubelib.update_tubes(pos, dir1, dir2, straight_ahead) then
tubelib.delete_meta_data(pos, minetest.get_node(pos))
minetest.remove_node(pos)
return itemstack
end
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
tubelib.delete_meta_data(pos, oldnode)
end,
on_rotate = screwdriver.disallow,
paramtype2 = "facedir",
paramtype = "light",
sunlight_propagates = true,
is_ground_content = false,
groups = {choppy=2, cracky=3, stone=1, not_in_creative_inventory=hidden},
drop = "tubelib:tube1",
sounds = default.node_sound_wood_defaults(),
})
end
minetest.register_craft({
output = "tubelib:tube1 4",
recipe = {
{"default:steel_ingot", "", "group:wood"},
{"", "group:wood", ""},
{"group:wood", "", "default:tin_ingot"},
},
})

@ -116,7 +116,7 @@ local function stop_crafter(pos)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number") or ""
meta:set_int("running", 0)
meta:set_int("running", tubelib.STATE_STOPPED)
meta:set_string("formspec",formspec(tubelib.STOPPED))
meta:set_string("infotext", "Tubelib Autocrafter "..number..": stopped")
node.name = "tubelib_addons1:autocrafter"
@ -129,7 +129,7 @@ local function goto_sleep(pos)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number") or ""
meta:set_int("running", -1)
meta:set_int("running", tubelib.STATE_STANDBY)
meta:set_string("formspec",formspec(tubelib.STANDBY))
meta:set_string("infotext", "Tubelib Autocrafter "..number..": standby")
node.name = "tubelib_addons1:autocrafter"
@ -149,7 +149,7 @@ local function run_autocrafter(pos, elapsed)
-- only use crafts that have an actual result
if output_item:is_empty() then
if running <= 0 then
if running <= tubelib.STATE_STOPPED then
return goto_sleep(pos)
end
meta:set_int("running", running)
@ -157,7 +157,7 @@ local function run_autocrafter(pos, elapsed)
end
if not autocraft(inventory, craft) then
if running <= 0 then
if running <= tubelib.STATE_STOPPED then
return goto_sleep(pos)
end
meta:set_int("running", running)
@ -166,7 +166,7 @@ local function run_autocrafter(pos, elapsed)
meta:set_int("item_counter", meta:get_int("item_counter") + output_item:get_count())
if running <= 0 then
if running <= tubelib.STATE_STOPPED then
return start_crafter(pos)
else
running = SLEEP_CNT_START_VAL
@ -351,17 +351,17 @@ local function on_receive_fields(pos, formname, fields, sender)
local meta = minetest.get_meta(pos)
local running = meta:get_int("running")
if fields.button ~= nil then
if running > 0 then
if running > tubelib.STATE_STOPPED then
update_meta(meta, tubelib.STOPPED)
stop_crafter(pos)
meta:set_int("running", 0)
meta:set_int("running", tubelib.STATE_STOPPED)
else
if update_meta(meta, tubelib.RUNNING) then
meta:set_int("running", 1)
meta:set_int("running", tubelib.STATE_RUNNING)
start_crafter(pos)
else
stop_crafter(pos)
meta:set_int("running", 0)
meta:set_int("running", tubelib.STATE_STOPPED)
end
end
end
@ -486,4 +486,11 @@ tubelib.register_node("tubelib_addons1:autocrafter", {"tubelib_addons1:autocraft
return "unsupported"
end
end,
on_server_restart = function(pos)
local meta = minetest.get_meta(pos)
if meta:get_int("running") ~= tubelib.STATE_STOPPED then
meta:set_int("running", tubelib.STATE_STANDBY)
minetest.get_node_timer(pos):start(craft_time*SLEEP_CNT_START_VAL)
end
end,
})

@ -353,4 +353,11 @@ tubelib.register_node("tubelib_addons1:fermenter", {}, {
return "unsupported"
end
end,
on_node_load = function(pos)
local meta = minetest.get_meta(pos)
if meta:get_int("running") ~= STOP_STATE then
meta:set_int("running", STANDBY_STATE)
minetest.get_node_timer(pos):start(CYCLE_TIME * TICKS_TO_SLEEP)
end
end,
})

@ -154,6 +154,10 @@ tubelib.register_node("tubelib_addons1:funnel", {}, {
return "unsupported"
end
end,
on_node_load = function(pos)
minetest.get_node_timer(pos):start(1)
end,
})

@ -14,16 +14,31 @@
]]--
local TICKS_TO_SLEEP = 10
-- for lazy programmers
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local P = minetest.string_to_pos
local M = minetest.get_meta
local STANDBY_TICKS = 4
local COUNTDOWN_TICKS = 4
local CYCLE_TIME = 2
local STOP_STATE = 0
local STANDBY_STATE = -1
local FAULT_STATE = -3
-- Grinder recipes
local Recipes = {}
local function formspec(state)
local State = tubelib.NodeStates:new({
node_name_passive = "tubelib_addons1:grinder",
node_name_active = "tubelib_addons1:grinder_active",
node_name_defect = "tubelib_addons1:grinder_defect",
infotext_name = "Tubelib Grinder",
cycle_time = CYCLE_TIME,
standby_ticks = STANDBY_TICKS,
has_item_meter = true,
aging_factor = 10,
})
local function formspec(pos, meta)
return "size[8,8]"..
default.gui_bg..
default.gui_bg_img..
@ -31,7 +46,7 @@ local function formspec(state)
"list[context;src;0,0;3,3;]"..
"item_image[0,0;1,1;default:cobble]"..
"image[3.5,1;1,1;tubelib_gui_arrow.png]"..
"image_button[3.5,2;1,1;".. tubelib.state_button(state) ..";button;]"..
"image_button[3.5,2;1,1;".. State:get_state_button_image(meta) ..";state_button;]"..
"list[context;dst;5,0;3,3;]"..
"item_image[5,0;1,1;default:gravel]"..
"list[current_player;main;0,4;8,4;]"..
@ -41,23 +56,21 @@ local function formspec(state)
"listring[current_player;main]"
end
State:register_formspec_func(formspec)
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
if listname == "src" then
return stack:get_count()
elseif listname == "dst" then
return 0
local inv = M(pos):get_inventory()
if listname == "src" and State:get_state(M(pos)) == tubelib.STANDBY then
State:start(pos, M(pos))
end
return 0
return stack:get_count()
end
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local inv = M(pos):get_inventory()
local stack = inv:get_stack(from_list, from_index)
return allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
end
@ -69,7 +82,7 @@ local function allow_metadata_inventory_take(pos, listname, index, stack, player
return stack:get_count()
end
local function grinding(inv)
local function grinding(pos, meta, inv)
for _,stack in ipairs(inv:get_list("src")) do
if not stack:is_empty() then
local name = stack:get_name()
@ -78,104 +91,31 @@ local function grinding(inv)
if inv:room_for_item("dst", output) then
inv:add_item("dst", output)
inv:remove_item("src", ItemStack(name))
return true
State:keep_running(pos, meta, COUNTDOWN_TICKS)
else
State:blocked(pos, meta)
end
else
State:fault(pos, meta)
end
return
end
end
return false
end
local function start_the_machine(pos)
local meta = minetest.get_meta(pos)
local node = minetest.get_node(pos)
local number = meta:get_string("number")
meta:set_int("running", TICKS_TO_SLEEP)
meta:set_string("infotext", "Tubelib Grinder "..number..": running")
meta:set_string("formspec", formspec(tubelib.RUNNING))
node.name = "tubelib_addons1:grinder_active"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):start(CYCLE_TIME)
return false
end
local function stop_the_machine(pos)
local meta = minetest.get_meta(pos)
local node = minetest.get_node(pos)
local number = meta:get_string("number")
meta:set_int("running", STOP_STATE)
meta:set_string("infotext", "Tubelib Grinder "..number..": stopped")
meta:set_string("formspec", formspec(tubelib.STOPPED))
node.name = "tubelib_addons1:grinder"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):stop()
return false
end
local function goto_sleep(pos)
local meta = minetest.get_meta(pos)
local node = minetest.get_node(pos)
local number = meta:get_string("number")
meta:set_int("running", STANDBY_STATE)
meta:set_string("infotext", "Tubelib Grinder "..number..": standby")
meta:set_string("formspec", formspec(tubelib.STANDBY))
node.name = "tubelib_addons1:grinder"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):start(CYCLE_TIME * TICKS_TO_SLEEP)
return false
end
local function goto_fault(pos)
local meta = minetest.get_meta(pos)
local node = minetest.get_node(pos)
local number = meta:get_string("number")
meta:set_int("running", FAULT_STATE)
meta:set_string("infotext", "Tubelib Grinder "..number..": fault")
meta:set_string("formspec", formspec(tubelib.FAULT))
node.name = "tubelib_addons1:grinder"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):stop()
return false
State:idle(pos, meta)
end
local function keep_running(pos, elapsed)
local meta = minetest.get_meta(pos)
local running = meta:get_int("running") - 1
--print("running", running)
local meta = M(pos)
local inv = meta:get_inventory()
local busy = grinding(inv)
if busy == true then
if running <= STOP_STATE then
return start_the_machine(pos)
else
running = TICKS_TO_SLEEP
end
elseif not inv:is_empty("src") then
return goto_fault(pos)
else
if running <= STOP_STATE then
return goto_sleep(pos)
end
end
meta:set_int("running", running)
return true
grinding(pos, meta, inv)
return State:is_active(meta)
end
local function on_receive_fields(pos, formname, fields, player)
if minetest.is_protected(pos, player:get_player_name()) then
return
end
local meta = minetest.get_meta(pos)
local running = meta:get_int("running") or 1
if fields.button ~= nil then
if running > STOP_STATE or running == FAULT_STATE then
stop_the_machine(pos)
else
start_the_machine(pos)
end
end
State:state_button_event(pos, fields)
end
minetest.register_node("tubelib_addons1:grinder", {
@ -192,17 +132,15 @@ minetest.register_node("tubelib_addons1:grinder", {
after_place_node = function(pos, placer)
local number = tubelib.add_node(pos, "tubelib_addons1:grinder")
local meta = minetest.get_meta(pos)
State:node_init(pos, number)
local meta = M(pos)
local inv = meta:get_inventory()
inv:set_size('src', 9)
inv:set_size('dst', 9)
meta:set_string("number", number)
meta:set_string("infotext", "Tubelib Grinder "..number..": stopped")
meta:set_string("formspec", formspec(tubelib.STOPPED))
end,
on_dig = function(pos, node, puncher, pointed_thing)
local meta = minetest.get_meta(pos)
local meta = M(pos)
local inv = meta:get_inventory()
if inv:is_empty("dst") and inv:is_empty("src") then
minetest.node_dig(pos, node, puncher, pointed_thing)
@ -210,6 +148,10 @@ minetest.register_node("tubelib_addons1:grinder", {
end
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
State:after_dig_node(pos, oldnode, oldmetadata, digger)
end,
on_rotate = screwdriver.disallow,
on_timer = keep_running,
on_receive_fields = on_receive_fields,
@ -217,6 +159,7 @@ minetest.register_node("tubelib_addons1:grinder", {
allow_metadata_inventory_move = allow_metadata_inventory_move,
allow_metadata_inventory_take = allow_metadata_inventory_take,
drop = "",
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
@ -263,6 +206,49 @@ minetest.register_node("tubelib_addons1:grinder_active", {
sounds = default.node_sound_wood_defaults(),
})
minetest.register_node("tubelib_addons1:grinder_defect", {
description = "Tubelib Grinder",
tiles = {
-- up, down, right, left, back, front
'tubelib_addons1_grinder.png',
'tubelib_front.png^tubelib_defect.png',
'tubelib_front.png^tubelib_defect.png',
'tubelib_front.png^tubelib_defect.png',
"tubelib_front.png^tubelib_defect.png",
"tubelib_front.png^tubelib_defect.png",
},
after_place_node = function(pos, placer)
local number = tubelib.add_node(pos, "tubelib_addons1:grinder")
State:node_init(pos, number)
local meta = M(pos)
local inv = meta:get_inventory()
inv:set_size('src', 9)
inv:set_size('dst', 9)
State:defect(pos, meta)
end,
on_dig = function(pos, node, puncher, pointed_thing)
local meta = M(pos)
local inv = meta:get_inventory()
if inv:is_empty("dst") and inv:is_empty("src") then
minetest.node_dig(pos, node, puncher, pointed_thing)
tubelib.remove_node(pos)
end
end,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_move = allow_metadata_inventory_move,
allow_metadata_inventory_take = allow_metadata_inventory_take,
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
groups = {choppy=2, cracky=2, crumbly=2, not_in_creative_inventory=1},
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})
minetest.register_craft({
output = "tubelib_addons1:grinder",
recipe = {
@ -273,32 +259,33 @@ minetest.register_craft({
})
tubelib.register_node("tubelib_addons1:grinder", {"tubelib_addons1:grinder_active"}, {
tubelib.register_node("tubelib_addons1:grinder",
{"tubelib_addons1:grinder_active", "tubelib_addons1:grinder_defect"}, {
on_pull_item = function(pos, side)
local meta = minetest.get_meta(pos)
return tubelib.get_item(meta, "dst")
return tubelib.get_item(M(pos), "dst")
end,
on_push_item = function(pos, side, item)
local meta = minetest.get_meta(pos)
return tubelib.put_item(meta, "src", item)
return tubelib.put_item(M(pos), "src", item)
end,
on_unpull_item = function(pos, side, item)
local meta = minetest.get_meta(pos)
return tubelib.put_item(meta, "dst", item)
return tubelib.put_item(M(pos), "dst", item)
end,
on_recv_message = function(pos, topic, payload)
if topic == "on" then
start_the_machine(pos)
elseif topic == "off" then
stop_the_machine(pos)
elseif topic == "state" then
local meta = minetest.get_meta(pos)
local running = meta:get_int("running")
return tubelib.statestring(running)
local resp = State:on_receive_message(pos, topic, payload)
if resp then
return resp
else
return "unsupported"
end
end,
on_node_load = function(pos)
print("on_node_load")
return State:on_node_load(pos)
end,
on_node_repair = function(pos)
print("on_node_repair")
return State:on_node_repair(pos)
end,
})

@ -449,6 +449,15 @@ tubelib.register_node("tubelib_addons1:harvester_base", {}, {
return "unsupported"
end
end,
on_node_load = function(pos)
local meta = minetest.get_meta(pos)
local this = minetest.deserialize(meta:get_string("this"))
if this and this.running ~= tubelib.STATE_STOPPED then
this.running = tubelib.STATE_STANDBY
meta:set_string("this", minetest.serialize(this))
minetest.get_node_timer(pos):start(CYCLE_TIME * TICKS_TO_SLEEP)
end
end,
})

@ -304,5 +304,12 @@ tubelib.register_node("tubelib_addons1:liquidsampler", {"tubelib_addons1:liquids
return "not supported"
end
end,
on_node_load = function(pos)
local meta = minetest.get_meta(pos)
if meta:get_int("running") ~= tubelib.STATE_STOPPED then
meta:set_int("running", tubelib.STATE_STANDBY)
minetest.get_node_timer(pos):start(20)
end
end,
})
--------------------------------------------------------------- tubelib

@ -13,7 +13,7 @@
Fast pusher for push/pull operation of StackItems from chests or other
inventory/server nodes to tubes or other inventory/server nodes.
The Pusher supports the following messages:
The Pusher is based on the class NodeStates and supports the following messages:
- topic = "on", payload = nil
- topic = "off", payload = nil
- topic = "state", payload = nil,
@ -29,85 +29,50 @@
-- | |/
-- +--------+
local RUNNING_STATE = 10
-- for lazy programmers
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local P = minetest.string_to_pos
local M = minetest.get_meta
local function switch_on(pos, node)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", RUNNING_STATE)
meta:set_string("infotext", "Fast Pusher "..number..": running")
node.name = "tubelib_addons1:pusher_fast_active"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):start(1)
return false
end
local STANDBY_TICKS = 5
local COUNTDOWN_TICKS = 5
local CYCLE_TIME = 1
local function switch_off(pos, node)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", tubelib.STATE_STOPPED)
meta:set_string("infotext", "Fast Pusher "..number..": stopped")
node.name = "tubelib_addons1:pusher_fast"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):stop()
return false
end
local State = tubelib.NodeStates:new({
node_name_passive = "tubelib_addons1:pusher",
node_name_active = "tubelib_addons1:pusher_active",
node_name_defect = "tubelib_addons1:pusher_defect",
infotext_name = "Fast Pusher",
cycle_time = CYCLE_TIME,
standby_ticks = STANDBY_TICKS,
has_item_meter = true,
aging_factor = 10,
})
local function goto_standby(pos, node)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", tubelib.STATE_STANDBY)
meta:set_string("infotext", "Fast Pusher "..number..": standby")
node.name = "tubelib_addons1:pusher_fast"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):start(20)
return false
end
local function goto_blocked(pos, node)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", tubelib.STATE_BLOCKED)
meta:set_string("infotext", "Fast Pusher "..number..": blocked")
node.name = "tubelib_addons1:pusher_fast"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):start(20)
return false
end
local function keep_running(pos, elapsed)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
local running = meta:get_int("running") - 1
local function pushing(pos, meta)
local player_name = meta:get_string("player_name")
local items = tubelib.pull_items(pos, "L", player_name) -- <<=== tubelib
if items ~= nil then
if tubelib.push_items(pos, "R", items, player_name) == false then -- <<=== tubelib
-- place item back
tubelib.unpull_items(pos, "L", items, player_name) -- <<=== tubelib
local node = minetest.get_node(pos)
return goto_blocked(pos, node)
end
meta:set_int("item_counter", meta:get_int("item_counter") + 1)
if running <= 0 then
local node = minetest.get_node(pos)
return switch_on(pos, node)
else
-- reload running state
running = RUNNING_STATE
end
else
if running <= 0 then
local node = minetest.get_node(pos)
return goto_standby(pos, node)
State:blocked(pos, meta)
return
end
State:keep_running(pos, meta, COUNTDOWN_TICKS)
return
end
meta:set_int("running", running)
return true
State:idle(pos, meta)
end
local function keep_running(pos, elapsed)
local meta = M(pos)
pushing(pos, meta)
return State:is_active(meta)
end
minetest.register_node("tubelib_addons1:pusher_fast", {
description = "Tubelib Fast Pusher",
description = "Fast Pusher",
tiles = {
-- up, down, right, left, back, front
'tubelib_addons1_pusher.png',
@ -121,25 +86,25 @@ minetest.register_node("tubelib_addons1:pusher_fast", {
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos)
meta:set_string("player_name", placer:get_player_name())
local number = tubelib.add_node(pos, "tubelib_addons1:pusher_fast")
meta:set_string("number", number)
meta:set_string("infotext", "Pusher "..number..": stopped")
meta:set_int("item_counter", 0)
local number = tubelib.add_node(pos, "tubelib_addons1:pusher_fast") -- <<=== tubelib
State:node_init(pos, number)
end,
on_rightclick = function(pos, node, clicker)
if not minetest.is_protected(pos, clicker:get_player_name()) then
switch_on(pos, node)
State:start(pos, M(pos))
end
end,
after_dig_node = function(pos)
tubelib.remove_node(pos)
after_dig_node = function(pos, oldnode, oldmetadata, digger)
tubelib.remove_node(pos) -- <<=== tubelib
State:after_dig_node(pos, oldnode, oldmetadata, digger)
end,
on_timer = keep_running,
on_rotate = screwdriver.disallow,
drop = "",
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
@ -150,7 +115,7 @@ minetest.register_node("tubelib_addons1:pusher_fast", {
minetest.register_node("tubelib_addons1:pusher_fast_active", {
description = "Tubelib Fast Pusher",
description = "Fast Pusher",
tiles = {
-- up, down, right, left, back, front
{
@ -199,7 +164,7 @@ minetest.register_node("tubelib_addons1:pusher_fast_active", {
on_rightclick = function(pos, node, clicker)
if not minetest.is_protected(pos, clicker:get_player_name()) then
switch_off(pos, node)
State:stop(pos, M(pos))
end
end,
@ -214,6 +179,42 @@ minetest.register_node("tubelib_addons1:pusher_fast_active", {
sounds = default.node_sound_wood_defaults(),
})
minetest.register_node("tubelib_addons1:pusher_fast_defect", {
description = "Fast Pusher",
tiles = {
-- up, down, right, left, back, front
'tubelib_addons1_pusher.png',
'tubelib_addons1_pusher.png',
'tubelib_outp.png^tubelib_defect.png',
'tubelib_inp.png^tubelib_defect.png',
"tubelib_addons1_pusher.png^[transformR180]^tubelib_defect.png",
"tubelib_addons1_pusher.png^tubelib_defect.png",
},
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos)
meta:set_string("player_name", placer:get_player_name())
local number = tubelib.add_node(pos, "tubelib_addons1:pusher") -- <<=== tubelib
State:node_init(pos, number)
State:defect(pos, meta)
end,
after_dig_node = function(pos)
tubelib.remove_node(pos) -- <<=== tubelib
end,
on_timer = keep_running,
on_rotate = screwdriver.disallow,
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
groups = {choppy=2, cracky=2, crumbly=2, not_in_creative_inventory=1},
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})
minetest.register_craft({
output = "tubelib_addons1:pusher_fast",
recipe = {
@ -224,34 +225,26 @@ minetest.register_craft({
})
--------------------------------------------------------------- tubelib
tubelib.register_node("tubelib_addons1:pusher_fast", {"tubelib_addons1:pusher_fast_active"}, {
tubelib.register_node("tubelib_addons1:pusher_fast",
{"tubelib_addons1:pusher_fast_active", "tubelib_addons1:pusher_fast_defect"}, {
on_pull_item = nil, -- pusher has no inventory
on_push_item = nil, -- pusher has no inventory
on_unpull_item = nil, -- pusher has no inventory
is_pusher = true, -- is a pulling/pushing node
on_recv_message = function(pos, topic, payload)
local node = minetest.get_node(pos)
if topic == "on" then
return switch_on(pos, node)
elseif topic == "off" then
return switch_off(pos, node)
elseif topic == "state" then
if node.name == "ignore" then -- unloaded pusher?
return "blocked"
end
local meta = minetest.get_meta(pos)
local running = meta:get_int("running") or tubelib.STATE_STOPPED
return tubelib.statestring(running)
elseif topic == "counter" then
local meta = minetest.get_meta(pos)
return meta:get_int("item_counter")
elseif topic == "clear_counter" then
local meta = minetest.get_meta(pos)
return meta:set_int("item_counter", 0)
local resp = State:on_receive_message(pos, topic, payload)
if resp then
return resp
else
return "not supported"
return "unsupported"
end
end,
on_node_load = function(pos)
State:on_node_load(pos)
end,
on_node_repair = function(pos)
return State:on_node_repair(pos)
end,
})
--------------------------------------------------------------- tubelib

@ -427,5 +427,12 @@ tubelib.register_node("tubelib_addons1:quarry", {"tubelib_addons1:quarry_active"
return "unsupported"
end
end,
on_node_load = function(pos)
local meta = minetest.get_meta(pos)
if meta:get_int("running") ~= STOP_STATE then
meta:set_int("running", TICKS_TO_SLEEP)
minetest.get_node_timer(pos):start(CYCLE_TIME)
end
end,
})

@ -314,4 +314,11 @@ tubelib.register_node("tubelib_addons1:reformer", {}, {
return "unsupported"
end
end,
on_node_load = function(pos)
local meta = minetest.get_meta(pos)
if meta:get_int("running") ~= STOP_STATE then
meta:set_int("running", STANDBY_STATE)
minetest.get_node_timer(pos):start(CYCLE_TIME * TICKS_TO_SLEEP)
end
end,
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

@ -94,6 +94,7 @@ minetest.register_node("tubelib_addons2:accesscontrol", {
if tubelib.check_numbers(fields.numbers) then
meta:set_string("numbers", fields.numbers)
meta:set_string("code", fields.code)
meta:mark_as_private("code")
meta:set_string("infotext", "Tubelib Access Lock, Enter access code")
meta:set_string("formspec", formspec2(""))
end

@ -111,4 +111,7 @@ tubelib.register_node("tubelib_addons2:repeater", {}, {
return tubelib.send_message(numbers, owner, nil, topic, payload)
end
end,
on_node_load = function(pos)
minetest.get_node_timer(pos):start(1)
end,
})

@ -261,4 +261,11 @@ tubelib.register_node("tubelib_addons2:sequencer", {}, {
meta:set_int("endless", 0)
end
end,
on_node_load = function(pos)
local meta = minetest.get_meta(pos)
if meta:get_int("running") ~= STOP_STATE then
meta:set_int("running", RUNNING_STATE)
minetest.get_node_timer(pos):start(1)
end
end,
})

@ -186,34 +186,14 @@ minetest.register_craft({
},
})
minetest.register_lbm({
label = "[Tubelib] Timer update",
name = "tubelib_addons2:update",
nodenames = {"tubelib_addons2:timer"},
run_at_every_load = true,
action = function(pos, node)
tubelib.register_node("tubelib_addons2:timer", {}, {
on_node_load = function(pos)
local meta = minetest.get_meta(pos)
minetest.get_node_timer(pos):start(CYCLE_TIME)
-- check rules for just loaded areas
local done = {false,false,false,false,false,false}
meta:set_string("done", minetest.serialize(done))
check_rules(pos,0)
local events = minetest.deserialize(meta:get_string("events"))
local numbers = minetest.deserialize(meta:get_string("numbers"))
local actions = {}
for _,a in ipairs(minetest.deserialize(meta:get_string("actions"))) do
if a == "start" then
actions[#actions+1] = "on"
elseif a == "stop" then
actions[#actions+1] = "off"
else
actions[#actions+1] = a
end
end
meta:set_string("actions", minetest.serialize(actions))
meta:set_string("formspec", formspec(events, numbers, actions))
end
end,
})

@ -482,4 +482,11 @@ tubelib.register_node("tubelib_addons3:distributor", {"tubelib_addons3:distribut
return "unsupported"
end
end,
on_node_load = function(pos)
local meta = minetest.get_meta(pos)
if meta:get_int("running") ~= STOP_STATE then
meta:set_int("running", STANDBY_STATE)
minetest.get_node_timer(pos):start(CYCLE_TIME * TICKS_TO_SLEEP)
end
end,
})

@ -14,83 +14,48 @@
]]--
local RUNNING_STATE = 10
-- for lazy programmers
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local P = minetest.string_to_pos
local M = minetest.get_meta
local function switch_on(pos, node)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", RUNNING_STATE)
meta:set_string("infotext", "HighPerf Pusher "..number..": running")
node.name = "tubelib_addons3:pusher_active"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):start(2)
return false
end
local STANDBY_TICKS = 5
local COUNTDOWN_TICKS = 5
local CYCLE_TIME = 2
local function switch_off(pos, node)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", tubelib.STATE_STOPPED)
meta:set_string("infotext", "HighPerf Pusher "..number..": stopped")
node.name = "tubelib_addons3:pusher"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):stop()
return false
end
local State = tubelib.NodeStates:new({
node_name_passive = "tubelib_addons3:pusher",
node_name_active = "tubelib_addons3:pusher_active",
node_name_defect = "tubelib_addons3:pusher_defect",
infotext_name = "HighPerf Pusher",
cycle_time = CYCLE_TIME,
standby_ticks = STANDBY_TICKS,
has_item_meter = true,
aging_factor = 10,
})
local function goto_standby(pos, node)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", tubelib.STATE_STANDBY)
meta:set_string("infotext", "HighPerf Pusher "..number..": standby")
node.name = "tubelib_addons3:pusher"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):start(20)
return false
end
local function goto_blocked(pos, node)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
meta:set_int("running", tubelib.STATE_BLOCKED)
meta:set_string("infotext", "HighPerf Pusher "..number..": blocked")
node.name = "tubelib_addons3:pusher"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):start(20)
return false
end
local function keep_running(pos, elapsed)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
local running = meta:get_int("running") - 1
local function pushing(pos, meta)
local player_name = meta:get_string("player_name")
local items = tubelib.pull_stack(pos, "L", player_name)
if items ~= nil then
if tubelib.push_items(pos, "R", items, player_name) == false then
-- place item back
tubelib.unpull_items(pos, "L", items, player_name)
local node = minetest.get_node(pos)
return goto_blocked(pos, node)
end
meta:set_int("item_counter", meta:get_int("item_counter") + 1)
if running <= 0 then
local node = minetest.get_node(pos)
return switch_on(pos, node)
else
-- reload running state
running = RUNNING_STATE
end
else
if running <= 0 then
local node = minetest.get_node(pos)
return goto_standby(pos, node)
State:blocked(pos, meta)
return
end
State:keep_running(pos, meta, COUNTDOWN_TICKS)
return
end
meta:set_int("running", running)
return true
State:idle(pos, meta)
end
local function keep_running(pos, elapsed)
local meta = M(pos)
pushing(pos, meta)
return State:is_active(meta)
end
minetest.register_node("tubelib_addons3:pusher", {
description = "HighPerf Pusher",
tiles = {
@ -107,24 +72,24 @@ minetest.register_node("tubelib_addons3:pusher", {
local meta = minetest.get_meta(pos)
meta:set_string("player_name", placer:get_player_name())
local number = tubelib.add_node(pos, "tubelib_addons3:pusher")
meta:set_string("number", number)
meta:set_string("infotext", "HighPerf Pusher "..number..": stopped")
meta:set_int("item_counter", 0)
State:node_init(pos, number)
end,
on_rightclick = function(pos, node, clicker)
if not minetest.is_protected(pos, clicker:get_player_name()) then
switch_on(pos, node)
State:start(pos, M(pos))
end
end,
after_dig_node = function(pos)
after_dig_node = function(pos, oldnode, oldmetadata, digger)
tubelib.remove_node(pos)
State:after_dig_node(pos, oldnode, oldmetadata, digger)
end,
on_timer = keep_running,
on_rotate = screwdriver.disallow,
drop = "",
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
@ -184,7 +149,7 @@ minetest.register_node("tubelib_addons3:pusher_active", {
on_rightclick = function(pos, node, clicker)
if not minetest.is_protected(pos, clicker:get_player_name()) then
switch_off(pos, node)
State:stop(pos, M(pos))
end
end,
@ -199,6 +164,42 @@ minetest.register_node("tubelib_addons3:pusher_active", {
sounds = default.node_sound_wood_defaults(),
})
minetest.register_node("tubelib_addons3:pusher_defect", {
description = "HighPerf Pusher",
tiles = {
-- up, down, right, left, back, front
'tubelib_pusher1.png^tubelib_addons3_node_frame4.png',
'tubelib_pusher1.png^tubelib_addons3_node_frame4.png',
'tubelib_outp.png^tubelib_addons3_node_frame4.png^tubelib_defect.png',
'tubelib_inp.png^tubelib_addons3_node_frame4.png^tubelib_defect.png',
"tubelib_pusher1.png^[transformR180]^tubelib_addons3_node_frame4.png^[transformR180]^tubelib_defect.png",
"tubelib_pusher1.png^tubelib_addons3_node_frame4.png^tubelib_defect.png",
},
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos)
meta:set_string("player_name", placer:get_player_name())
local number = tubelib.add_node(pos, "tubelib_addons3:pusher")
State:node_init(pos, number)
State:defect(pos, meta)
end,
after_dig_node = function(pos)
tubelib.remove_node(pos)
end,
on_timer = keep_running,
on_rotate = screwdriver.disallow,
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
groups = {choppy=2, cracky=2, crumbly=2, not_in_creative_inventory=1},
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})
minetest.register_craft({
output = "tubelib_addons3:pusher",
recipe = {
@ -208,30 +209,22 @@ minetest.register_craft({
},
})
tubelib.register_node("tubelib_addons3:pusher", {"tubelib_addons3:pusher_active"}, {
tubelib.register_node("tubelib_addons3:pusher",
{"tubelib_addons3:pusher_active", "tubelib_addons3:pusher_defect"}, {
is_pusher = true, -- is a pulling/pushing node
on_recv_message = function(pos, topic, payload)
local node = minetest.get_node(pos)
if topic == "on" then
return switch_on(pos, node)
elseif topic == "off" then
return switch_off(pos, node)
elseif topic == "state" then
if node.name == "ignore" then -- unloaded pusher?
return "blocked"
end
local meta = minetest.get_meta(pos)
local running = meta:get_int("running") or tubelib.STATE_STOPPED
return tubelib.statestring(running)
elseif topic == "counter" then
local meta = minetest.get_meta(pos)
return meta:get_int("item_counter")
elseif topic == "clear_counter" then
local meta = minetest.get_meta(pos)
return meta:set_int("item_counter", 0)
local resp = State:on_receive_message(pos, topic, payload)
if resp then
return resp
else
return "not supported"
return "unsupported"
end
end,
on_node_load = function(pos)
State:on_node_load(pos)
end,
on_node_repair = function(pos)
return State:on_node_repair(pos)
end,
})

@ -232,4 +232,7 @@ tubelib.register_node("tubelib_addons3:pushing_chest", {}, {
on_recv_message = function(pos, topic, payload)
return "unsupported"
end,
on_node_load = function(pos)
minetest.get_node_timer(pos):start(2)
end,
})

@ -14,38 +14,12 @@
]]--
local PairingList = {}
local Tube = tubelib.Tube
local sForm = "size[7.5,3]"..
local sFormspec = "size[7.5,3]"..
"field[0.5,1;7,1;channel;Enter channel string;]" ..
"button_exit[2,2;3,1;exit;Save]"
local function pairing(pos, channel)
if PairingList[channel] and not vector.equals(pos, PairingList[channel]) then
-- store peer position on both nodes
local meta1 = minetest.get_meta(pos)
local peer = minetest.pos_to_string(PairingList[channel])
meta1:set_string("peer", peer)
meta1:set_string("infotext", "Tubelib Teleporter, connected "..peer)
meta1:set_string("channel", nil)
meta1:set_string("formspec", nil)
local meta2 = minetest.get_meta(PairingList[channel])
local peer = minetest.pos_to_string(pos)
meta2:set_string("peer", peer)
meta2:set_string("infotext", "Tubelib Teleporter, connected "..peer)
meta2:set_string("channel", nil)
meta2:set_string("formspec", nil)
PairingList[channel] = nil
return true
else
PairingList[channel] = pos
minetest.get_meta(pos):set_string("channel", channel)
return false
end
end
minetest.register_node("tubelib_addons3:teleporter", {
description = "Tubelib Teleporter",
tiles = {
@ -59,46 +33,23 @@ minetest.register_node("tubelib_addons3:teleporter", {
},
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos)
tubelib.add_node(pos, "tubelib_addons3:teleporter")
meta:set_string("formspec", sForm)
meta:set_string("infotext", "Tubelib Teleporter, unconfigured")
-- determine the tube side
local tube_dir = ((minetest.dir_to_facedir(placer:get_look_dir()) + 1) % 4) + 1
Tube:prepare_pairing(pos, tube_dir, sFormspec)
Tube:after_place_node(pos, {tube_dir})
end,
on_receive_fields = function(pos, formname, fields, player)
local meta = minetest.get_meta(pos)
if fields.channel ~= nil then
if not pairing(pos, fields.channel) then
meta:set_string("formspec", "size[7.5,3]"..
"field[0.5,1;7,1;channel;Enter channel string;"..fields.channel.."]" ..
"button_exit[2,2;3,1;exit;Save]")
else
local peer_pos = minetest.string_to_pos(meta:get_string("peer"))
minetest.log("action", player:get_player_name()..
" pairs Tubelib Teleporter nodes at "..
minetest.pos_to_string(pos)..
" and at "..minetest.pos_to_string(peer_pos))
end
Tube:pairing(pos, fields.channel)
end
end,
on_destruct = function(pos)
-- unpair peer node
local meta = minetest.get_meta(pos)
local peer = meta:get_string("peer")
if peer ~= "" then
local peer_pos = minetest.string_to_pos(peer)
local peer_meta = minetest.get_meta(peer_pos)
peer_meta:set_string("channel", nil)
peer_meta:set_string("peer", nil)
peer_meta:set_string("formspec", sForm)
peer_meta:set_string("infotext", "Tubelib Teleporter, unconfigured")
else
local channel = meta:get_string("channel")
if channel then
PairingList[channel] = nil
end
end
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Tube:stop_pairing(pos, oldmetadata, sFormspec)
local tube_dir = tonumber(oldmetadata.fields.tube_dir or 0)
Tube:after_dig_node(pos, {tube_dir})
end,
on_rotate = screwdriver.disallow,
@ -120,22 +71,4 @@ minetest.register_craft({
},
})
-- recursion detection
local LastPeerPos = nil
tubelib.register_node("tubelib_addons3:teleporter", {}, {
on_push_item = function(pos, side, item)
-- push on peer side
local meta = minetest.get_meta(pos)
local peer = meta:get_string("peer")
if peer ~= "" and peer ~= LastPeerPos then
LastPeerPos = peer
local res = tubelib.push_items(minetest.string_to_pos(peer), "R", item, nil)
LastPeerPos = nil
return res
end
return false
end,
is_pusher = true,
})
Tube:add_secondary_node_names({"tubelib_addons3:teleporter"})