mirror of
https://github.com/joe7575/tubelib2.git
synced 2025-02-16 08:32:27 +01:00
first commit
This commit is contained in:
20
README.md
Normal file
20
README.md
Normal file
@ -0,0 +1,20 @@
|
||||
# Tube Library 2 [tubelib2]
|
||||
|
||||
A library for mods which need connecting tubes / pipes / cables or similar.
|
||||
|
||||
Browse on: ![GitHub](https://github.com/joe7575/tubelib2)
|
||||
|
||||
Download: ![GitHub](https://github.com/joe7575/tubelib2/archive/master.zip)
|
||||
|
||||
|
||||
## Dependencies
|
||||
default
|
||||
|
||||
# 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
|
||||
|
1
depends.txt
Normal file
1
depends.txt
Normal file
@ -0,0 +1 @@
|
||||
default
|
2
description.txt
Normal file
2
description.txt
Normal file
@ -0,0 +1,2 @@
|
||||
A library for mods which need connecting tubes / pipes / cables or similar.
|
||||
|
57
design.txt
Normal file
57
design.txt
Normal file
@ -0,0 +1,57 @@
|
||||
View to the north
|
||||
|
||||
|
||||
dir1/dir2: axis dir:
|
||||
6
|
||||
A 1
|
||||
| / 0
|
||||
+--|-----+ A 1
|
||||
/ o /| | /
|
||||
+--------+ | |/
|
||||
4 <----| |o----> 2 4 <-------+-------> 3
|
||||
| o | | /|
|
||||
| / | + / |
|
||||
| / |/ 2 V
|
||||
+-/------+ 5
|
||||
/ |
|
||||
3 |
|
||||
V
|
||||
5
|
||||
|
||||
+------+
|
||||
| |
|
||||
+------+ +---+------+---+ +------+
|
||||
|XXXXXX| | | | | | |
|
||||
|XXXXXX| | | | | | |
|
||||
+------+ +---+------+---+ +------+
|
||||
| |
|
||||
+------+
|
||||
dir1/dir2 1/3 2/4 5/6
|
||||
axis/rot 3/0 5/1 1/0
|
||||
|
||||
+------+ +---+------+ +------+ +------+---+
|
||||
|XXXXXX| | | | | | | | |
|
||||
|XXXXXX| | | | | | | | |
|
||||
+------+ +---+------+ +------+ +------+---+
|
||||
| | | | | | | |
|
||||
+------+ +------+ +------+ +------+
|
||||
dir1/dir2 3/5 4/5 1/5 2/5
|
||||
axis/rot 0/0 3/3 2/0 0/3
|
||||
|
||||
+------+ +------+ +------+ +------+
|
||||
| | | | | | | |
|
||||
+------+ +---+------+ +------+ +------+---+
|
||||
|XXXXXX| | | | | | | | |
|
||||
|XXXXXX| | | | | | | | |
|
||||
+------+ +---+------+ +------+ +------+---+
|
||||
axis/rot 3/6 4/6 1/6 2/6
|
||||
dir1/dir2 5/0 3/1 2/2 4/3
|
||||
|
||||
+------+---+ +---+------+ +------+---+ +---+------+
|
||||
| | | | | | |XXXXXX| | | |XXXXXX|
|
||||
| | | | | | |XXXXXX| | | |XXXXXX|
|
||||
+------+---+ +---+------+ +------+---+ +---+------+
|
||||
dir1/dir2 1/2 1/4 2/3 3/4
|
||||
axis/rot 2/3 3/2 1/3 1/1
|
||||
|
||||
|
5
init.lua
Normal file
5
init.lua
Normal file
@ -0,0 +1,5 @@
|
||||
tubelib2 = {}
|
||||
|
||||
dofile(minetest.get_modpath("tubelib2") .. "/tube_api.lua")
|
||||
dofile(minetest.get_modpath("tubelib2") .. "/internal.lua")
|
||||
dofile(minetest.get_modpath("tubelib2") .. "/tube_test.lua")
|
406
internal.lua
Normal file
406
internal.lua
Normal file
@ -0,0 +1,406 @@
|
||||
--[[
|
||||
|
||||
Tube Library 2
|
||||
==============
|
||||
|
||||
Copyright (C) 2018 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
internal.lua
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P = minetest.pos_to_string
|
||||
local S = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
|
||||
|
||||
--
|
||||
-- Tubelib2 specific 6D directions (1 = North, 2 = East, 3 = South, 4 = West, 5 = Down, 6 = Up)
|
||||
--
|
||||
-- All 6D dirs are the view from the node to the outer side
|
||||
-- Tubes are based on two node types, "angled" and "straight" tubes.
|
||||
--
|
||||
-- +-------+
|
||||
-- / /| +-------+
|
||||
-- +-------+ | / /|
|
||||
-- | | | / / |
|
||||
-- | | | +-------+ |
|
||||
-- | | | | | |
|
||||
-- | | | | |/ |
|
||||
-- | | + +-------+| +
|
||||
-- | |/ | |/
|
||||
-- +-------+ +------+
|
||||
--
|
||||
-- All other nodes are build by means of axis/rotation variants based on param2
|
||||
-- (paramtype2 == "facedir").
|
||||
|
||||
|
||||
local Turn180Deg = {3,4,1,2,6,5}
|
||||
|
||||
-- To calculate param2 based on dir6d information
|
||||
local DirToParam2 = {
|
||||
-- dir1 / dir2 ==> param2 / type (Angled/Straight)
|
||||
[12] = {11, "A"},
|
||||
[13] = {12, "S"},
|
||||
[14] = {14, "A"},
|
||||
[15] = { 8, "A"},
|
||||
[16] = {10, "A"},
|
||||
[23] = { 7, "A"},
|
||||
[24] = {21, "S"},
|
||||
[25] = { 3, "A"},
|
||||
[26] = {19, "A"},
|
||||
[34] = { 5, "A"},
|
||||
[35] = { 0, "A"},
|
||||
[36] = {20, "A"},
|
||||
[45] = {15, "A"},
|
||||
[46] = {13, "A"},
|
||||
[56] = { 4, "S"},
|
||||
}
|
||||
|
||||
-- To retrieve dir6d values from the nodes param2
|
||||
local Param2ToDir = {}
|
||||
for k,item in pairs(DirToParam2) do
|
||||
Param2ToDir[item[1]] = k
|
||||
end
|
||||
|
||||
-- For neighbour position calculation
|
||||
local Dir6dToVector = {
|
||||
{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},
|
||||
}
|
||||
|
||||
local VectorToDir6d = {
|
||||
[{x=0, y=0, z=1}] = 1,
|
||||
[{x=1, y=0, z=0}] = 2,
|
||||
[{x=0, y=0, z=-1}] = 3,
|
||||
[{x=-1, y=0, z=0}] = 4,
|
||||
[{x=0, y=-1, z=0}] = 5,
|
||||
[{x=0, y=1, z=0}] = 6,
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
-- Local Functions
|
||||
--
|
||||
|
||||
local function Tbl(list)
|
||||
local tbl = {}
|
||||
for _,item in ipairs(list) do
|
||||
tbl[item] = true
|
||||
end
|
||||
return tbl
|
||||
end
|
||||
|
||||
local function range(val, min, max)
|
||||
if val > max then return max end
|
||||
if val < min then return min end
|
||||
return val
|
||||
end
|
||||
|
||||
local function get_node_lvm(pos)
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
if node then
|
||||
return node
|
||||
end
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local MinEdge, MaxEdge = vm:read_from_map(pos, pos)
|
||||
local data = vm:get_data()
|
||||
local param2_data = vm:get_param2_data()
|
||||
local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge})
|
||||
local idx = area:index(pos.x, pos.y, pos.z)
|
||||
node = {
|
||||
name = minetest.get_name_from_content_id(data[idx]),
|
||||
param2 = param2_data[idx]
|
||||
}
|
||||
return node
|
||||
end
|
||||
|
||||
-- Return node next to pos in direction 'dir'
|
||||
local function get_next_node(pos, dir)
|
||||
if dir and Dir6dToVector[dir] then
|
||||
local npos = vector.add(pos, Dir6dToVector[dir])
|
||||
return npos, get_node_lvm(npos)
|
||||
end
|
||||
return pos, get_node_lvm(pos)
|
||||
end
|
||||
|
||||
--
|
||||
-- Tubelib2 Methods
|
||||
--
|
||||
|
||||
local Tube = tubelib2.Tube
|
||||
|
||||
-- check if node has a connection on the given dir
|
||||
function Tube:connected(pos, dir)
|
||||
local _, node = get_next_node(pos, dir)
|
||||
return self.primary_node_names[node.name] or self.secondary_node_names[node.name]
|
||||
end
|
||||
|
||||
-- The 3 free bits or param2 are used to store the number of connections.
|
||||
-- return param2 and tube type
|
||||
function Tube:encode_param2(dir1, dir2, num_conn)
|
||||
if dir1 > dir2 then
|
||||
dir1, dir2 = dir2, dir1
|
||||
end
|
||||
local param2, _type = unpack(DirToParam2[dir1 * 10 + dir2] or {0, "S"})
|
||||
return (num_conn * 32) + param2, _type
|
||||
end
|
||||
|
||||
-- return dir1, dir2, num_conn
|
||||
function Tube:decode_param2(param2)
|
||||
local val = Param2ToDir[param2 % 32]
|
||||
if val then
|
||||
local dir1, dir2 = math.floor(val / 10), val % 10
|
||||
local num_conn = math.floor(param2 / 32)
|
||||
return dir1, dir2, num_conn
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- return pos for a primary_node and true if num_conn < 2, else false
|
||||
function Tube:friendly_primary_node(pos, dir)
|
||||
-- read node
|
||||
local npos, node = get_next_node(pos, dir)
|
||||
-- tube node with max one connection?
|
||||
local _,_,num_conn = self:decode_param2(node.param2)
|
||||
if self.primary_node_names[node.name] then
|
||||
return npos, num_conn < 2
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function Tube:secondary_node(pos, dir)
|
||||
-- read node
|
||||
local npos, node = get_next_node(pos, dir)
|
||||
if self.secondary_node_names[node.name] then
|
||||
return npos
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function Tube:fdir(player)
|
||||
local pitch = player:get_look_pitch()
|
||||
if pitch > 1.1 then -- up?
|
||||
return 6
|
||||
elseif pitch < -1.1 then -- down?
|
||||
return 5
|
||||
else
|
||||
return minetest.dir_to_facedir(player:get_look_dir()) + 1
|
||||
end
|
||||
end
|
||||
|
||||
function Tube:get_player_data(placer, pointed_thing)
|
||||
if placer and pointed_thing and pointed_thing.type == "node" then
|
||||
if placer:get_player_control().sneak then
|
||||
return pointed_thing.under, Tube:fdir(placer)
|
||||
else
|
||||
return nil, Tube:fdir(placer)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Check all 6 possible positions for known nodes considering preferred_pos
|
||||
-- and the players fdir and return dir1, dir2 and the number of tubes to connect to (0..2).
|
||||
function Tube:determine_tube_dirs(pos, preferred_pos, fdir)
|
||||
local tbl = {}
|
||||
local allowed = table.copy(self.allowed_6d_dirs)
|
||||
|
||||
-- Check for primary nodes (tubes)
|
||||
for dir = 1,6 do
|
||||
if allowed[dir] then
|
||||
local npos, friendly = self:friendly_primary_node(pos, dir)
|
||||
if npos then
|
||||
if not friendly then
|
||||
allowed[dir] = false
|
||||
else
|
||||
if preferred_pos and vector.equals(npos, preferred_pos) then
|
||||
preferred_pos = nil
|
||||
table.insert(tbl, 1, dir)
|
||||
else
|
||||
table.insert(tbl, dir)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- If no tube around the pointed pos and player prefers a position,
|
||||
-- then the new tube shall point to the player.
|
||||
if #tbl == 0 and preferred_pos and fdir and allowed[Turn180Deg[fdir]] then
|
||||
tbl[1] = Turn180Deg[fdir]
|
||||
-- Already 2 dirs found?
|
||||
elseif #tbl >= 2 then
|
||||
return tbl[1], tbl[2], 2
|
||||
end
|
||||
|
||||
-- Check for secondary nodes (chests and so on)
|
||||
for dir = 1,6 do
|
||||
if allowed[dir] then
|
||||
local npos = self:secondary_node(pos, dir)
|
||||
if npos then
|
||||
if preferred_pos and vector.equals(npos, preferred_pos) then
|
||||
preferred_pos = nil
|
||||
table.insert(tbl, 2, dir)
|
||||
else
|
||||
table.insert(tbl, dir)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- player pointed to an unknown node to force the tube orientation?
|
||||
if preferred_pos and fdir then
|
||||
if tbl[1] == Turn180Deg[fdir] and allowed[fdir] then
|
||||
tbl[2] = fdir
|
||||
elseif allowed[Turn180Deg[fdir]] then
|
||||
tbl[2] = Turn180Deg[fdir]
|
||||
end
|
||||
end
|
||||
|
||||
-- dir1, dir2 still unknown?
|
||||
if fdir then
|
||||
if #tbl == 0 and allowed[Turn180Deg[fdir]] then
|
||||
tbl[1] = Turn180Deg[fdir]
|
||||
end
|
||||
if #tbl == 1 and allowed[Turn180Deg[tbl[1]]] then
|
||||
tbl[2] = Turn180Deg[tbl[1]]
|
||||
elseif #tbl == 1 and tbl[1] ~= Turn180Deg[fdir] and allowed[Turn180Deg[fdir]] then
|
||||
tbl[2] = Turn180Deg[fdir]
|
||||
end
|
||||
end
|
||||
|
||||
if #tbl >= 2 and tbl[1] ~= tbl[2] then
|
||||
local num_tubes = (self:connected(pos, tbl[1]) and 1 or 0) +
|
||||
(self:connected(pos, tbl[2]) and 1 or 0)
|
||||
return tbl[1], tbl[2], math.min(2, num_tubes)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Tube:tube_data_to_table(pos, dir1, dir2, num_tubes)
|
||||
local param2, ttype = self:encode_param2(dir1, dir2, num_tubes)
|
||||
return {pos = pos, param2 = param2, type = ttype, num_tubes = num_tubes}
|
||||
end
|
||||
|
||||
|
||||
function Tube:add_tube_dir(pos, dir)
|
||||
local npos, node = get_next_node(pos, dir)
|
||||
if self.primary_node_names[node.name] then
|
||||
local d1, d2, num = self:decode_param2(node.param2)
|
||||
-- not already connected to the new tube?
|
||||
dir = Turn180Deg[dir]
|
||||
if d1 ~= dir and dir ~= d2 then
|
||||
if num == 0 then
|
||||
d1 = dir
|
||||
elseif num == 1 then
|
||||
-- determine, which of d1, d2 has already a connection
|
||||
if self:connected(npos, d1) then
|
||||
d2 = dir
|
||||
else
|
||||
d1 = dir
|
||||
end
|
||||
end
|
||||
end
|
||||
return npos, d1, d2, math.min(num + 1, 2)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Tube:del_tube_dir(pos, dir)
|
||||
local npos, node = get_next_node(pos, dir)
|
||||
if self.primary_node_names[node.name] then
|
||||
local d1, d2, num = self:decode_param2(node.param2)
|
||||
return npos, d1, d2, math.max(num - 1, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function Tube:get_tube_dirs(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if self.primary_node_names[node.name] then
|
||||
local d1, d2 = self:decode_param2(node.param2)
|
||||
return d1, d2
|
||||
end
|
||||
end
|
||||
|
||||
function Tube:get_next_tube(pos, dir)
|
||||
local npos, node = get_next_node(pos, dir)
|
||||
local dir1, dir2, num = self:decode_param2(node.param2)
|
||||
if self.primary_node_names[node.name] then
|
||||
if Turn180Deg[dir] == dir1 then
|
||||
return npos, dir2
|
||||
else
|
||||
return npos, dir1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Tube:find_tube_head(pos)
|
||||
local cnt = 0
|
||||
local dir = nil
|
||||
while cnt <= self.max_tube_length do
|
||||
local new_pos, new_dir = self:get_next_tube(pos, dir)
|
||||
if not new_dir then break end
|
||||
pos, dir = new_pos, new_dir
|
||||
cnt = cnt + 1
|
||||
end
|
||||
return pos, dir
|
||||
end
|
||||
|
||||
|
||||
-- Do a correction of param2, delete meta data and
|
||||
-- return the new pos, dir
|
||||
function Tube:repair_next_tube(pos, dir)
|
||||
local npos, node = get_next_node(pos, dir)
|
||||
if self.primary_node_names[node.name] then
|
||||
local dir1, dir2, num = self:decode_param2(node.param2)
|
||||
if num ~= 2 then
|
||||
node.param2 = self:encode_param2(dir1, dir2, 2)
|
||||
minetest.set_node(npos, node)
|
||||
end
|
||||
M(npos):from_table(nil)
|
||||
if Turn180Deg[dir] == dir1 then
|
||||
return npos, dir2
|
||||
else
|
||||
return npos, dir1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Tube:repair_tube_line(pos, dir)
|
||||
local cnt = 0
|
||||
if not dir then return pos, cnt end
|
||||
while cnt <= self.max_tube_length do
|
||||
local new_pos, new_dir = self:repair_next_tube(pos, dir)
|
||||
if not new_dir then break end
|
||||
pos, dir = new_pos, new_dir
|
||||
cnt = cnt + 1
|
||||
end
|
||||
return pos, cnt
|
||||
end
|
||||
|
||||
-- update meta data and set number of connections to 1 or 0
|
||||
function Tube:update_head_tube(pos1, pos2, num_tubes)
|
||||
local _, node = get_next_node(pos1)
|
||||
local dir1, dir2, num = self:decode_param2(node.param2)
|
||||
num = (self:connected(pos1, dir1) and 1 or 0) + (self:connected(pos1, dir2) and 1 or 0)
|
||||
node.param2 = self:encode_param2(dir1, dir2, num)
|
||||
minetest.set_node(pos1, node)
|
||||
if self.show_infotext then
|
||||
M(pos1):set_string("infotext", P(pos2).." / "..num_tubes.." tubes")
|
||||
end
|
||||
M(pos1):set_string("peer_pos", P(pos2))
|
||||
end
|
||||
|
||||
function Tube:add_meta(pos1, pos2, num_tubes)
|
||||
self:update_head_tube(pos1, pos2, num_tubes)
|
||||
self:update_head_tube(pos2, pos1, num_tubes)
|
||||
end
|
BIN
screenshot.png
Normal file
BIN
screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 322 KiB |
BIN
textures/tubelib2_hole.png
Normal file
BIN
textures/tubelib2_hole.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 200 B |
BIN
textures/tubelib2_tool.png
Normal file
BIN
textures/tubelib2_tool.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 395 B |
BIN
textures/tubelib2_tube.png
Normal file
BIN
textures/tubelib2_tube.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 202 B |
149
tube_api.lua
Normal file
149
tube_api.lua
Normal file
@ -0,0 +1,149 @@
|
||||
--[[
|
||||
|
||||
Tube Library 2
|
||||
==============
|
||||
|
||||
Copyright (C) 2017-2018 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
tube_api.lua
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P = minetest.pos_to_string
|
||||
local S = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
|
||||
|
||||
local function Tbl(list)
|
||||
local tbl = {}
|
||||
for _,item in ipairs(list) do
|
||||
tbl[item] = true
|
||||
end
|
||||
return tbl
|
||||
end
|
||||
|
||||
--
|
||||
-- API Functions
|
||||
--
|
||||
|
||||
-- Tubelib2 Class
|
||||
tubelib2.Tube = {}
|
||||
local Tube = tubelib2.Tube
|
||||
|
||||
function Tube:new(attr)
|
||||
local o = {
|
||||
allowed_6d_dirs = attr.allowed_6d_dirs or {true, true, true, true, true, true},
|
||||
max_tube_length = attr.max_tube_length or 1000,
|
||||
primary_node_names = Tbl(attr.primary_node_names or {}),
|
||||
secondary_node_names = Tbl(attr.secondary_node_names or {}),
|
||||
show_infotext = attr.show_infotext or false,
|
||||
}
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
-- Register (foreign) tubelib compatible nodes
|
||||
function Tube:add_secondary_node_names(names)
|
||||
for _,name in ipairs(names) do
|
||||
self.secondary_node_names[name] = true
|
||||
end
|
||||
end
|
||||
|
||||
-- From node to node via tube
|
||||
-- Used for item transportation via tubes
|
||||
function Tube:get_connected_node_pos(pos, dir)
|
||||
-- update_meta
|
||||
return pos, dir
|
||||
end
|
||||
|
||||
-- From tube head to tube head
|
||||
function Tube:get_tube_end_pos(pos)
|
||||
local spos = M(pos):get_string("peer_pos")
|
||||
if spos then
|
||||
return S(spos)
|
||||
end
|
||||
local npos, num = self:find_tube_head(pos)
|
||||
self:update_head_tube(pos, npos, num)
|
||||
return pos
|
||||
end
|
||||
|
||||
|
||||
-- To be called after a tube node is placed
|
||||
function Tube:update_tubes_after_place_node(pos, placer, pointed_thing)
|
||||
local preferred_pos, fdir = self:get_player_data(placer, pointed_thing)
|
||||
local dir1, dir2, num_tubes = self:determine_tube_dirs(pos, preferred_pos, fdir)
|
||||
if dir1 == nil then
|
||||
return {}
|
||||
end
|
||||
|
||||
local tbl = {self:tube_data_to_table(pos, dir1, dir2, num_tubes)}
|
||||
|
||||
if num_tubes >= 1 then
|
||||
local npos, d1, d2, num = self:add_tube_dir(pos, dir1)
|
||||
if npos then
|
||||
--print("update_tubes_after_place_node: d1, d2, num", d1, d2, num)
|
||||
tbl[#tbl+1] = self:tube_data_to_table(npos, d1, d2, num)
|
||||
end
|
||||
end
|
||||
|
||||
if num_tubes >= 2 then
|
||||
local npos, d1, d2, num = self:add_tube_dir(pos, dir2)
|
||||
if npos then
|
||||
--print("update_tubes_after_place_node: d1, d2, num", d1, d2, num)
|
||||
tbl[#tbl+1] = self:tube_data_to_table(npos, d1, d2, num)
|
||||
end
|
||||
end
|
||||
|
||||
return tbl
|
||||
end
|
||||
|
||||
|
||||
-- To be called after a tube node is removed
|
||||
function Tube:update_tubes_after_dig_node(pos, oldnode)
|
||||
local dir1, dir2, num_tubes = self:decode_param2(oldnode.param2)
|
||||
local tbl = {}
|
||||
|
||||
local npos, d1, d2, num = self:del_tube_dir(pos, dir1)
|
||||
if npos then
|
||||
tbl[#tbl+1] = self:tube_data_to_table(npos, d1, d2, num)
|
||||
end
|
||||
|
||||
npos, d1, d2, num = self:del_tube_dir(pos, dir2)
|
||||
if npos then
|
||||
tbl[#tbl+1] = self:tube_data_to_table(npos, d1, d2, num)
|
||||
end
|
||||
|
||||
return tbl
|
||||
end
|
||||
|
||||
-- To be called from a repair tool
|
||||
function Tube:repair_tubes(pos)
|
||||
local dir1, dir2 = self:get_tube_dirs(pos)
|
||||
self:repair_next_tube(pos)
|
||||
local npos1, cnt1 = self:repair_tube_line(pos, dir1)
|
||||
local npos2, cnt2 = self:repair_tube_line(pos, dir2)
|
||||
self:add_meta(npos1, npos2, cnt1+cnt2+1)
|
||||
return npos1, npos2, cnt1, cnt2
|
||||
end
|
||||
|
||||
-- To be called from a repair tool
|
||||
function Tube:remove_tube(pos, sound)
|
||||
local dir1, dir2 = self:get_tube_dirs(pos)
|
||||
if dir1 and dir2 then
|
||||
minetest.sound_play({
|
||||
name=sound},{
|
||||
gain=1,
|
||||
max_hear_distance=5,
|
||||
loop=false})
|
||||
local npos1 = self:friendly_primary_node(pos, dir1)
|
||||
local npos2 = self:friendly_primary_node(pos, dir2)
|
||||
minetest.remove_node(pos)
|
||||
if npos1 then self:repair_tubes(npos1) end
|
||||
if npos2 then self:repair_tubes(npos2) end
|
||||
end
|
||||
end
|
208
tube_test.lua
Normal file
208
tube_test.lua
Normal file
@ -0,0 +1,208 @@
|
||||
--[[
|
||||
|
||||
Tube Library 2
|
||||
==============
|
||||
|
||||
Copyright (C) 2017-2018 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
tube_test.lua
|
||||
|
||||
THIS FILE IS ONLY FOR TESTING PURPOSES
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P = minetest.pos_to_string
|
||||
local S = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
|
||||
-- Test tubes
|
||||
|
||||
local Tube = tubelib2.Tube:new({
|
||||
max_tube_length = 1000,
|
||||
show_infotext = true,
|
||||
primary_node_names = {"tubelib2:tubeS", "tubelib2:tubeA"},
|
||||
secondary_node_names = {"default:chest", "default:chest_open"},
|
||||
})
|
||||
|
||||
minetest.register_node("tubelib2:tubeS", {
|
||||
description = "Tubelib2 Test tube",
|
||||
tiles = { -- Top, base, right, left, front, back
|
||||
"tubelib2_tube.png",
|
||||
"tubelib2_tube.png",
|
||||
"tubelib2_tube.png",
|
||||
"tubelib2_tube.png",
|
||||
"tubelib2_hole.png",
|
||||
"tubelib2_hole.png",
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
local nodes = Tube:update_tubes_after_place_node(pos, placer, pointed_thing)
|
||||
--print("nodes"..dump(nodes))
|
||||
if #nodes > 0 then
|
||||
for _,item in ipairs(nodes) do
|
||||
--print("after_place_node", item.type, item.param2)
|
||||
minetest.set_node(item.pos, {name = "tubelib2:tube"..item.type, param2 = item.param2})
|
||||
end
|
||||
return false
|
||||
else
|
||||
minetest.remove_node(pos)
|
||||
return true
|
||||
end
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
for _,item in ipairs(Tube:update_tubes_after_dig_node(pos, oldnode)) do
|
||||
--print("after_dig_node", item.type, item.param2)
|
||||
minetest.set_node(item.pos, {name = "tubelib2:tube"..item.type, param2 = item.param2})
|
||||
end
|
||||
end,
|
||||
|
||||
paramtype2 = "facedir", -- important!
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-2/8, -2/8, -4/8, 2/8, 2/8, 4/8},
|
||||
},
|
||||
},
|
||||
node_placement_prediction = "", -- important!
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
groups = {crumbly = 3, cracky = 3, snappy = 3},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("tubelib2:tubeA", {
|
||||
description = "Tubelib2 Test tube",
|
||||
tiles = { -- Top, base, right, left, front, back
|
||||
"tubelib2_tube.png",
|
||||
"tubelib2_hole.png",
|
||||
"tubelib2_tube.png",
|
||||
"tubelib2_tube.png",
|
||||
"tubelib2_tube.png",
|
||||
"tubelib2_hole.png",
|
||||
},
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
for _,item in ipairs(Tube:update_tubes_after_dig_node(pos, oldnode)) do
|
||||
--print("after_dig_node", item.type, item.param2)
|
||||
minetest.set_node(item.pos, {name = "tubelib2:tube"..item.type, param2 = item.param2})
|
||||
end
|
||||
end,
|
||||
|
||||
paramtype2 = "facedir", -- important!
|
||||
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},
|
||||
},
|
||||
},
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
groups = {crumbly = 3, cracky = 3, snappy = 3, not_in_creative_inventory=1},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
drop = "tubelib2:tubeS",
|
||||
})
|
||||
|
||||
local function read_test_type(itemstack, placer, pointed_thing)
|
||||
local param2
|
||||
if pointed_thing.type == "node" then
|
||||
local node = minetest.get_node(pointed_thing.under)
|
||||
param2 = node.param2
|
||||
else
|
||||
param2 = 0
|
||||
end
|
||||
local num = math.floor(param2/32)
|
||||
local axis = math.floor(param2/4) % 8
|
||||
local rot = param2 % 4
|
||||
minetest.chat_send_player(placer:get_player_name(), "[Tubelib2] param2 = "..param2.."/"..num.."/"..axis.."/"..rot)
|
||||
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local function TEST_determine_tube_dirs(itemstack, placer, pointed_thing)
|
||||
if pointed_thing.type == "node" then
|
||||
local pos = pointed_thing.above
|
||||
local preferred_pos = pointed_thing.under
|
||||
local fdir = Tube:fdir(placer)
|
||||
local dir1, dir2, num_tubes = Tube:determine_tube_dirs(pos, preferred_pos, fdir)
|
||||
print("num_tubes="..num_tubes.." dir1="..(dir1 or "nil").." dir2="..(dir2 or "nil"))
|
||||
end
|
||||
end
|
||||
|
||||
local function TEST_update_tubes_after_place_node(itemstack, placer, pointed_thing)
|
||||
if pointed_thing.type == "node" then
|
||||
local pos = pointed_thing.above
|
||||
local nodes = Tube:update_tubes_after_place_node(pos, placer, pointed_thing)
|
||||
print("nodes"..dump(nodes))
|
||||
end
|
||||
end
|
||||
|
||||
local function TEST_add_tube_dir(itemstack, placer, pointed_thing)
|
||||
read_test_type(itemstack, placer, pointed_thing)
|
||||
if pointed_thing.type == "node" then
|
||||
local pos = pointed_thing.above
|
||||
local fdir = Tube:fdir(placer)
|
||||
local npos, d1, d2, num = Tube:add_tube_dir(pos, fdir)
|
||||
print("npos, d1, d2, num", npos and P(npos), d1, d2, num)
|
||||
end
|
||||
end
|
||||
|
||||
local function TEST_del_tube_dir(itemstack, placer, pointed_thing)
|
||||
read_test_type(itemstack, placer, pointed_thing)
|
||||
if pointed_thing.type == "node" then
|
||||
local pos = pointed_thing.above
|
||||
local fdir = Tube:fdir(placer)
|
||||
local npos, d1, d2, num = Tube:del_tube_dir(pos, fdir)
|
||||
print("npos, d1, d2, num", npos and P(npos), d1, d2, num)
|
||||
end
|
||||
end
|
||||
|
||||
local function read_param2(pos, player)
|
||||
local node = minetest.get_node(pos)
|
||||
local num = math.floor(node.param2/32)
|
||||
local axis = math.floor(node.param2/4) % 8
|
||||
local rot = node.param2 % 4
|
||||
minetest.chat_send_player(player:get_player_name(), "[Tubelib2] param2 = "..node.param2.."/"..num.."/"..axis.."/"..rot)
|
||||
end
|
||||
|
||||
local function repair_tubes(itemstack, placer, pointed_thing)
|
||||
if pointed_thing.type == "node" then
|
||||
local pos = pointed_thing.under
|
||||
local pos1, pos2, cnt1, cnt2 = Tube:repair_tubes(pos)
|
||||
minetest.chat_send_player(placer:get_player_name(), "[Tubelib2] 1: "..P(pos1).." / "..cnt1.." tubes")
|
||||
minetest.chat_send_player(placer:get_player_name(), "[Tubelib2] 2: "..P(pos2).." / "..cnt2.." tubes")
|
||||
end
|
||||
end
|
||||
|
||||
local function remove_tube(itemstack, placer, pointed_thing)
|
||||
if pointed_thing.type == "node" then
|
||||
local pos = pointed_thing.under
|
||||
if placer:get_player_control().sneak then
|
||||
read_param2(pos, placer)
|
||||
else
|
||||
Tube:remove_tube(pos, "default_break_glass")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Tool for tube workers to crack a tube line
|
||||
minetest.register_node("tubelib2:tool", {
|
||||
description = "Tubelib2 Tool",
|
||||
inventory_image = "tubelib2_tool.png",
|
||||
wield_image = "tubelib2_tool.png",
|
||||
use_texture_alpha = true,
|
||||
groups = {cracky=1, book=1},
|
||||
on_use = remove_tube,
|
||||
on_place = repair_tubes,
|
||||
node_placement_prediction = "",
|
||||
})
|
||||
|
Reference in New Issue
Block a user