Skip to content

Commit 2034ef2

Browse files
committed
Gen.Library: move common methods into Cuboid instead Room. LG-2059
1 parent 1227f0d commit 2034ef2

5 files changed

Lines changed: 241 additions & 160 deletions

File tree

.luacheckrc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ read_globals = {
1818
table = { fields = {
1919
--- @deprecated
2020
"getn", -- was in Lua, now deprecated TODO: remove usages
21-
-- MT Builtin:
22-
"copy", "indexof", "insert_all", "key_value_swap",
21+
-- Luanti Builtin:
22+
"copy", "copy_with_metatables", "indexof", "insert_all", "key_value_swap",
23+
"pack", "unpack", "packsize",
2324
-- our Core/helpers:
2425
-- table:
2526
"contains", "has_value", "has_key", "merge", "join", "merge_values",
Lines changed: 218 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,223 @@
1+
local setmetatable, vector_sort, vector_in_area, v
2+
= setmetatable, vector.sort, vector.in_area, vector.new
3+
4+
local WallType = require('map.room.wall.Type')
5+
16

27
--- @class Voxrame.map.Cuboid
3-
--- @field public from PositionVector
4-
--- @field public to PositionVector
5-
local Cuboid = {}
6-
7-
-- TODO:
8-
-- also needed to create cuboids by `Cuboid:new`, and fix creation of child classes
9-
10-
-- --- @param from Position
11-
-- --- @param to Position
12-
-- --- @return self
13-
-- function Cuboid:new(from, to)
14-
-- from, to = vector.sort(from, to)
15-
16-
-- local class = self
17-
-- self = {}
18-
-- self.from = from
19-
-- self.to = to
20-
21-
-- return setmetatable(self, { __index = class })
22-
-- end
23-
24-
-- --- @param position Position
25-
-- --- @return boolean
26-
-- function Cuboid:contains(position)
27-
-- return vector.in_area(position, self.from, self.to)
28-
-- end
8+
local Cuboid = {
9+
--- @type PositionVector
10+
from = nil, --- @diagnostic disable-line: assign-type-mismatch
11+
--- @type PositionVector
12+
to = nil, --- @diagnostic disable-line: assign-type-mismatch
13+
--- @type Voxrame.map.room.Walls
14+
walls = nil, --- @diagnostic disable-line: assign-type-mismatch
15+
}
16+
17+
--- @generic GenericCuboid: Voxrame.map.Cuboid
18+
--- @param child_class GenericCuboid|nil
19+
--- @return GenericCuboid
20+
function Cuboid:extended(child_class)
21+
return setmetatable(child_class or {}, { __index = self })
22+
end
23+
24+
--- @param from Position corner where cuboid starts.
25+
--- @param to Position corner where cuboid ends.
26+
--- @param init_walls? boolean initialize `.walls` property for use methods like `get_wall()`
27+
--- @return self
28+
function Cuboid:new(from, to, init_walls)
29+
from, to = vector_sort(from, to)
30+
init_walls = init_walls or false
31+
32+
local class = self
33+
self = {}
34+
self.from = from
35+
self.to = to
36+
self = setmetatable(self, { __index = class })
37+
38+
if init_walls then
39+
self:init_walls()
40+
end
41+
42+
return self --- @diagnostic disable-line: return-type-mismatch
43+
end
44+
45+
--- Determines whether the position is inside the cuboid. \
46+
--- Sides are inclusive.
47+
--- @param position Position
48+
--- @return boolean
49+
function Cuboid:contains(position)
50+
return vector_in_area(position, self.from, self.to)
51+
end
52+
53+
--- Returns center position of the cuboid.
54+
--- @return PositionVector
55+
function Cuboid:center()
56+
return ((self.from + self.to) / 2):floor()
57+
end
58+
59+
--- Returns normalized direction-vector from given position to the center of the cuboid. \
60+
--- If `length` is specified, the resulting vector is scaled to that length.
61+
--- @param position PositionVector
62+
--- @param length? number
63+
--- @return vector
64+
function Cuboid:to_center_from(position, length)
65+
length = length or 1
66+
67+
return ((self:center() - position):normalize() * length)
68+
end
69+
70+
--- Returns normalized direction-vector from the center of the cuboid to the given position. \
71+
--- If `length` is specified, the resulting vector is scaled to that length.
72+
--- @param position PositionVector
73+
--- @param length? number
74+
--- @return vector
75+
function Cuboid:from_center_to(position, length)
76+
length = length or 1
77+
78+
return ((position - self:center()):normalize() * length)
79+
end
80+
81+
--- @private
82+
--- @return Voxrame.map.room.Walls
83+
function Cuboid:calc_walls()
84+
local f = self.from
85+
local e = self.to
86+
87+
return {
88+
west = Cuboid:new( v(f.x - 1, f.y - 1, f.z - 1), v(f.x - 1, e.y + 1, e.z + 1) ),
89+
east = Cuboid:new( v(e.x + 1, f.y - 1, f.z - 1), v(e.x + 1, e.y + 1, e.z + 1) ),
90+
south = Cuboid:new( v(f.x - 1, f.y - 1, f.z - 1), v(e.x + 1, e.y + 1, f.z - 1) ),
91+
north = Cuboid:new( v(f.x - 1, f.y - 1, e.z + 1), v(e.x + 1, e.y + 1, e.z + 1) ),
92+
floor = Cuboid:new( v(f.x - 1, f.y - 1, f.z - 1), v(e.x + 1, f.y - 1, e.z + 1) ),
93+
ceiling = Cuboid:new( v(f.x - 1, e.y + 1, f.z - 1), v(e.x + 1, e.y + 1, e.z + 1) ),
94+
}
95+
end
96+
97+
--- @protected
98+
--- @return self
99+
function Cuboid:init_walls()
100+
self.walls = self:calc_walls()
101+
102+
return self
103+
end
104+
105+
--- @param name Voxrame.map.room.wall.Type name of wall.
106+
--- @param inside_room boolean? if true, corners will be shifted one node inside the room.
107+
--- @return Voxrame.map.room.Wall
108+
function Cuboid:wall(name, inside_room)
109+
inside_room = inside_room or false
110+
111+
self.walls = self.walls or self:calc_walls()
112+
113+
local wall = self.walls[name]
114+
115+
if inside_room then
116+
wall = table.copy_with_metatables(wall)
117+
wall.from = wall.from + self:to_center_from(wall.from):sign()
118+
wall.to = wall.to + self:to_center_from(wall.to):sign()
119+
end
120+
121+
return wall
122+
end
123+
124+
--- Returns corner positions of specified wall.
125+
--- Requires `.walls` property to be initialized (by calling `:init_walls()`).
126+
--- @param name Voxrame.map.room.wall.Type name of wall.
127+
--- @param inside_room boolean? if true, corners will be shifted one node inside the room.
128+
--- @return PositionVector[]
129+
function Cuboid:get_corners_of(name, inside_room)
130+
inside_room = inside_room or false
131+
132+
--- @type Voxrame.map.room.Wall
133+
local wall = self:wall(name, inside_room)
134+
local from = wall.from
135+
local to = wall.to
136+
137+
local corners = {}
138+
if name == WallType.floor or name == WallType.ceiling then
139+
corners = {
140+
from:copy(),
141+
v(from.x, from.y, to.z),
142+
to:copy(),
143+
v(to.x, from.y, from.z),
144+
}
145+
elseif name == WallType.north or name == WallType.south then
146+
corners = {
147+
from:copy(),
148+
v(to.x, from.y, from.z),
149+
to:copy(),
150+
v(from.x, to.y, from.z),
151+
}
152+
elseif name == WallType.west or name == WallType.east then
153+
corners = {
154+
from:copy(),
155+
v(from.x, from.y, to.z),
156+
to:copy(),
157+
v(from.x, to.y, from.z),
158+
}
159+
end
160+
161+
return corners
162+
end
163+
164+
--- @param wall_type Voxrame.map.room.wall.Type
165+
--- @return PositionVector
166+
function Cuboid:center_of(wall_type)
167+
return self:wall(wall_type):center()
168+
end
169+
170+
--- @param side Voxrame.map.room.wall.Type
171+
--- @return PositionVector
172+
function Cuboid:floor_center_of(side)
173+
local position = self:center_of(side)
174+
position.y = self:floor().from.y + 1
175+
176+
return position
177+
end
178+
179+
-- -----------------------------------------------------------------
180+
181+
-- #region `:floor()`, `:north()`, ...
182+
183+
--- @
184+
--- @param inside_room boolean?
185+
--- @return Voxrame.map.room.Wall
186+
function Cuboid:floor(inside_room)
187+
return self:wall(WallType.floor, inside_room)
188+
end
189+
190+
--- @param inside_room boolean?
191+
--- @return Voxrame.map.room.Wall
192+
function Cuboid:ceiling(inside_room)
193+
return self:wall(WallType.ceiling, inside_room)
194+
end
195+
196+
--- @param inside_room boolean?
197+
--- @return Voxrame.map.room.Wall
198+
function Cuboid:north(inside_room)
199+
return self:wall(WallType.north, inside_room)
200+
end
201+
202+
--- @param inside_room boolean?
203+
--- @return Voxrame.map.room.Wall
204+
function Cuboid:south(inside_room)
205+
return self:wall(WallType.south, inside_room)
206+
end
207+
208+
--- @param inside_room boolean?
209+
--- @return Voxrame.map.room.Wall
210+
function Cuboid:east(inside_room)
211+
return self:wall(WallType.east, inside_room)
212+
end
213+
214+
--- @param inside_room boolean?
215+
--- @return Voxrame.map.room.Wall
216+
function Cuboid:west(inside_room)
217+
return self:wall(WallType.west, inside_room)
218+
end
219+
220+
-- #endregion
29221

30222

31223
return Cuboid

0 commit comments

Comments
 (0)