mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-16 22:46:03 +01:00
feat(grid): add a grid system
Based on mkafrin's grid used by PolyZone's ComboZones.
This commit is contained in:
187
imports/grid/shared.lua
Normal file
187
imports/grid/shared.lua
Normal file
@@ -0,0 +1,187 @@
|
||||
--[[
|
||||
Based on PolyZone's grid system (https://github.com/mkafrin/PolyZone/blob/master/ComboZone.lua)
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019-2021 Michael Afrin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
]]
|
||||
|
||||
local mapMinX = -3700
|
||||
local mapMinY = -4400
|
||||
local mapMaxX = 4500
|
||||
local mapMaxY = 8000
|
||||
local xDelta = (mapMaxX - mapMinX) / 34
|
||||
local yDelta = (mapMaxY - mapMinY) / 50
|
||||
local grid = {}
|
||||
local lastCell = {}
|
||||
local lastNearbyEntries = {}
|
||||
local entrySet = {}
|
||||
|
||||
lib.grid = {}
|
||||
|
||||
---@class GridEntry
|
||||
---@field coords vector
|
||||
---@field length? number
|
||||
---@field width? number
|
||||
---@field radius? number
|
||||
---@field [string] any
|
||||
|
||||
---@param point vector
|
||||
---@param length number
|
||||
---@param width number
|
||||
---@return number, number, number, number
|
||||
local function getGridDimensions(point, length, width)
|
||||
local minX = (point.x - width - mapMinX) // xDelta
|
||||
local maxX = (point.x + width - mapMinX) // xDelta
|
||||
local minY = (point.y - length - mapMinY) // yDelta
|
||||
local maxY = (point.y + length - mapMinY) // yDelta
|
||||
|
||||
return minX, maxX, minY, maxY
|
||||
end
|
||||
|
||||
---@param point vector
|
||||
---@return number, number
|
||||
function lib.grid.getCellPosition(point)
|
||||
local x = (point.x - mapMinX) // xDelta
|
||||
local y = (point.y - mapMinY) // yDelta
|
||||
|
||||
return x, y
|
||||
end
|
||||
|
||||
---@param point vector
|
||||
---@return GridEntry[]
|
||||
function lib.grid.getCell(point)
|
||||
local x, y = lib.grid.getCellPosition(point)
|
||||
|
||||
if lastCell.x ~= x or lastCell.y ~= y then
|
||||
lastCell.x = x
|
||||
lastCell.y = y
|
||||
lastCell.cell = grid[y] and grid[y][x] or {}
|
||||
end
|
||||
|
||||
return lastCell.cell
|
||||
end
|
||||
|
||||
---@param point vector
|
||||
---@return GridEntry[]
|
||||
function lib.grid.getNearbyEntries(point)
|
||||
local minX, maxX, minY, maxY = getGridDimensions(point, xDelta, yDelta)
|
||||
|
||||
if lastNearbyEntries.minX == minX and
|
||||
lastNearbyEntries.maxX == maxX and
|
||||
lastNearbyEntries.minY == minY and
|
||||
lastNearbyEntries.maxY == maxY then
|
||||
return lastNearbyEntries.entries
|
||||
end
|
||||
|
||||
local entries = {}
|
||||
local n = 0
|
||||
|
||||
table.wipe(entrySet)
|
||||
|
||||
for y = minY, maxY do
|
||||
local row = grid[y]
|
||||
|
||||
for x = minX, maxX do
|
||||
local cell = row and row[x]
|
||||
|
||||
if cell then
|
||||
for j = 1, #cell do
|
||||
local entry = cell[j]
|
||||
|
||||
if not entrySet[entry] then
|
||||
n = n + 1
|
||||
entrySet[entry] = true
|
||||
entries[n] = entry
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
lastNearbyEntries.minX = minX
|
||||
lastNearbyEntries.maxX = maxX
|
||||
lastNearbyEntries.minY = minY
|
||||
lastNearbyEntries.maxY = maxY
|
||||
lastNearbyEntries.entries = entries
|
||||
|
||||
return entries
|
||||
end
|
||||
|
||||
---@param entry { coords: vector, length?: number, width?: number, radius?: number, [string]: any }
|
||||
function lib.grid.addEntry(entry)
|
||||
entry.length = entry.length or entry.radius * 2
|
||||
entry.width = entry.width or entry.radius * 2
|
||||
local minX, maxX, minY, maxY = getGridDimensions(entry.coords, entry.length, entry.width)
|
||||
|
||||
for y = minY, maxY do
|
||||
local row = grid[y] or {}
|
||||
|
||||
for x = minX, maxX do
|
||||
local cell = row[x] or {}
|
||||
|
||||
cell[#cell + 1] = entry
|
||||
row[x] = cell
|
||||
end
|
||||
|
||||
grid[y] = row
|
||||
end
|
||||
end
|
||||
|
||||
---@param entry table A table that was added to the grid previously.
|
||||
function lib.grid.removeEntry(entry)
|
||||
local minX, maxX, minY, maxY = getGridDimensions(entry.coords, entry.length, entry.width)
|
||||
local success = false
|
||||
|
||||
for y = minY, maxY do
|
||||
local row = grid[y]
|
||||
|
||||
if not row then goto continue end
|
||||
|
||||
for x = minX, maxX do
|
||||
local cell = row[x]
|
||||
|
||||
if cell then
|
||||
for i = 1, #cell do
|
||||
if cell[i] == entry then
|
||||
table.remove(cell, i)
|
||||
success = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if #cell == 0 then
|
||||
row[x] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not next(row) then
|
||||
grid[y] = nil
|
||||
end
|
||||
|
||||
::continue::
|
||||
end
|
||||
|
||||
return success
|
||||
end
|
||||
|
||||
return lib.grid
|
||||
Reference in New Issue
Block a user