diff --git a/imports/zones/server.lua b/imports/zones/server.lua new file mode 100644 index 0000000..1e4c0ec --- /dev/null +++ b/imports/zones/server.lua @@ -0,0 +1,101 @@ +local glm = require 'glm' + +---@type { [number]: CZone } +Zones = {} + +local function removeZone(self) + Zones[self.id] = nil +end + +local glm_polygon_contains = glm.polygon.contains + +local function contains(self, coords) + return glm_polygon_contains(self.polygon, coords, self.thickness / 4) +end + +local function insideSphere(self, coords) + return #(self.coords - coords) < self.radius +end + +local function convertToVector(coords) + local _type = type(coords) + + if _type ~= 'vector3' then + if _type == 'table' or _type == 'vector4' then + return vec3(coords[1] or coords.x, coords[2] or coords.y, coords[3] or coords.z) + end + + error(("expected type 'vector3' or 'table' (received %s)"):format(_type)) + end + + return coords +end + +lib.zones = { + ---@return CZone + poly = function(data) + data.id = #Zones + 1 + data.thickness = data.thickness or 4 + + local pointN = #data.points + local points = table.create(pointN, 0) + + for i = 1, pointN do + points[i] = convertToVector(data.points[i]) + end + + data.polygon = glm.polygon.new(points) + data.coords = data.polygon:centroid() + data.remove = removeZone + data.contains = contains + data.debug = nil + data.inside = nil + data.onEnter = nil + data.onExit = nil + + Zones[data.id] = data + return data + end, + + ---@return CZone + box = function(data) + data.id = #Zones + 1 + data.coords = convertToVector(data.coords) + data.size = data.size and convertToVector(data.size) / 2 or vec3(2) + data.thickness = data.size.z * 2 or 4 + data.rotation = quat(data.rotation or 0, vec3(0, 0, 1)) + data.polygon = (data.rotation * glm.polygon.new({ + vec3(data.size.x, data.size.y, 0), + vec3(-data.size.x, data.size.y, 0), + vec3(-data.size.x, -data.size.y, 0), + vec3(data.size.x, -data.size.y, 0), + }) + data.coords) + data.remove = removeZone + data.contains = contains + data.debug = nil + data.inside = nil + data.onEnter = nil + data.onExit = nil + + Zones[data.id] = data + return data + end, + + ---@return CZone + sphere = function(data) + data.id = #Zones + 1 + data.coords = convertToVector(data.coords) + data.radius = (data.radius or 2) + 0.0 + data.remove = removeZone + data.contains = insideSphere + data.debug = nil + data.inside = nil + data.onEnter = nil + data.onExit = nil + + Zones[data.id] = data + return data + end, +} + +return lib.zones