-
Notifications
You must be signed in to change notification settings - Fork 4
/
digilines.lua
129 lines (107 loc) · 4.41 KB
/
digilines.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
--[[
Copyright (C) 2021 Jude Melton-Houghton
This file is part of area_containers. It implements digiline functionality.
area_containers is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
area_containers is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with area_containers. If not, see <https://www.gnu.org/licenses/>.
]]
--[[
OVERVIEW
Digilines messages can pass unaltered between the container and the digiline
node inside. Forwarding takes one game step. The digiline node is assumed to
be on the floor. Digiline messages are assumed to be serializable. This
assumption seems completely reasonable, since digilines are a simulation of
serial communication lines.
See also container.lua and nodes.lua.
]]
local use = ...
local get_random_id, get_node_maybe_load,
CONTAINER_NAME_PREFIX, DIGILINE_OFFSET = use("misc", {
"get_random_id", "get_node_maybe_load",
"CONTAINER_NAME_PREFIX", "DIGILINE_OFFSET"
})
local get_related_container, get_related_inside,
get_params_from_inside = use("relation", {
"get_related_container", "get_related_inside",
"get_params_from_inside",
})
local exports = {}
exports.container = {}
exports.digiline = {}
if not minetest.global_exists("digilines") then return exports end
assert(minetest.global_exists("mesecon"),
"mesecons is now required to use use digilines with area_containers")
-- The connection rules (relative positions to link to) for the digiline node.
local DIGILINE_NODE_RULES = {
{x = 1, y = 1, z = 0},
{x = 0, y = 1, z = 1},
{x = -1, y = 1, z = 0},
{x = 0, y = 1, z = -1},
}
-- Returns the digiline ID of a container. This is a number unique among other
-- IDs that exist in the past, present, or future. If the node at the position
-- is not a container, nil is returned.
local function get_digiline_id(container_pos)
local meta = minetest.get_meta(container_pos)
local id = meta:get("area_containers:digiline_id")
if not id then
local node = get_node_maybe_load(container_pos)
local prefix = string.sub(node.name, 1, #CONTAINER_NAME_PREFIX)
if prefix == CONTAINER_NAME_PREFIX then
-- It's a container; get the ID for the first use.
id = get_random_id()
meta:set_string("area_containers:digiline_id", id)
end
end
return id
end
-- Sends a message into a container given its position and ID.
local function send_in(pos, id, channel, msg)
if get_digiline_id(pos) ~= id then return end
local node = get_node_maybe_load(pos)
local inside_pos = get_related_inside(node.param1, node.param2)
local digiline_pos = vector.add(inside_pos, DIGILINE_OFFSET)
digilines.receptor_send(digiline_pos, DIGILINE_NODE_RULES, channel, msg)
end
mesecon.queue:add_function("area_containers:digiline_in", send_in)
-- Sends a message out of a container given its position and ID.
local function send_out(pos, id, channel, msg)
if get_digiline_id(pos) ~= id then return end
digilines.receptor_send(pos, digilines.rules.default, channel, msg)
end
mesecon.queue:add_function("area_containers:digiline_out", send_out)
exports.container.digilines = {
effector = {},
receptor = {},
}
-- Forwards messages to the inside.
function exports.container.digilines.effector.action(pos, _node, channel, msg)
local id = get_digiline_id(pos)
if not id then return end
mesecon.queue:add_action(pos, "area_containers:digiline_in",
{id, channel, msg})
end
exports.digiline.digilines = {
effector = {rules = DIGILINE_NODE_RULES},
receptor = {rules = DIGILINE_NODE_RULES},
}
-- Forwards digiline messages to the container.
function exports.digiline.digilines.effector.action(pos, _node, channel, msg)
local inside_pos = vector.subtract(pos, DIGILINE_OFFSET)
local param1, param2 = get_params_from_inside(inside_pos)
if not param1 then return end
local container_pos = get_related_container(param1, param2)
if not container_pos then return end
local id = get_digiline_id(container_pos)
if not id then return end
mesecon.queue:add_action(container_pos, "area_containers:digiline_out",
{id, channel, msg})
end
return exports