chore: init
This commit is contained in:
180
src/ReplicatedStorage/Shared/ChunkManager/Chunk.lua
Normal file
180
src/ReplicatedStorage/Shared/ChunkManager/Chunk.lua
Normal file
@@ -0,0 +1,180 @@
|
||||
local Chunk = {}
|
||||
Chunk.__index = Chunk
|
||||
|
||||
Chunk.UpdateBlockBindable = Instance.new("BindableEvent") :: BindableEvent
|
||||
|
||||
Chunk.AllChunks = {} :: {[typeof("")]: typeof(Chunk.new(0,0,0))}
|
||||
|
||||
local RunService = game:GetService("RunService")
|
||||
|
||||
local function Swait(l)
|
||||
for i = 1,l do
|
||||
RunService.Stepped:Wait()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
export type BlockData = {
|
||||
id: number,
|
||||
state: {
|
||||
[typeof("")]: string | boolean | number
|
||||
}
|
||||
}
|
||||
|
||||
function Chunk.new(x,y,z)
|
||||
local self = setmetatable({}, Chunk)
|
||||
self.pos = Vector3.new(x,y,z)
|
||||
|
||||
-- Tick ONLY in a 5 chunk distance of LP's char
|
||||
self.inhabitedTime = tick()
|
||||
self.instance = Instance.new("Folder")
|
||||
self.unloadChunkHook = function() end
|
||||
self.UpdateBlockBindableL = Instance.new("BindableEvent") :: BindableEvent
|
||||
|
||||
self.loaded = false
|
||||
self.loading = false
|
||||
|
||||
self.data = {} :: {[typeof("")]: BlockData} -- "X,Y,Z": BlockData ("-1,-1,1": BlockData)
|
||||
return self
|
||||
end
|
||||
|
||||
function Chunk.from(x,y,z,data)
|
||||
local self = setmetatable({}, Chunk)
|
||||
self.pos = Vector3.new(x,y,z)
|
||||
|
||||
-- Tick ONLY in a 5 chunk distance of LP's char
|
||||
self.inhabitedTime = tick()
|
||||
self.instance = Instance.new("Folder")
|
||||
self.unloadChunkHook = function() end
|
||||
self.UpdateBlockBindableL = Instance.new("BindableEvent") :: BindableEvent
|
||||
|
||||
self.data = data :: {[typeof("")]: BlockData} -- "X,Y,Z": BlockData ("-1,-1,1": BlockData)
|
||||
return self
|
||||
end
|
||||
|
||||
function Chunk:DoesNeighboringBlockExist(rx, ry, rz, gx, gy, gz, offsetX, offsetY, offsetZ)
|
||||
task.desynchronize()
|
||||
-- Calculate the local position of the neighboring block
|
||||
local neighborRX, neighborRY, neighborRZ = rx + offsetX, ry + offsetY, rz + offsetZ
|
||||
local neighborGX, neighborGY, neighborGZ = gx, gy, gz
|
||||
|
||||
-- Adjust for chunk boundaries
|
||||
if neighborRX < 1 then
|
||||
neighborRX = 8
|
||||
neighborGX = gx - 1
|
||||
elseif neighborRX > 8 then
|
||||
neighborRX = 1
|
||||
neighborGX = gx + 1
|
||||
end
|
||||
|
||||
if neighborRY < 1 then
|
||||
neighborRY = 8
|
||||
neighborGY = gy - 1
|
||||
elseif neighborRY > 8 then
|
||||
neighborRY = 1
|
||||
neighborGY = gy + 1
|
||||
end
|
||||
|
||||
if neighborRZ < 1 then
|
||||
neighborRZ = 8
|
||||
neighborGZ = gz - 1
|
||||
elseif neighborRZ > 8 then
|
||||
neighborRZ = 1
|
||||
neighborGZ = gz + 1
|
||||
end
|
||||
|
||||
if neighborGY < 0 then
|
||||
return true
|
||||
end
|
||||
|
||||
-- Get the neighboring chunk
|
||||
local neighborChunk = Chunk.AllChunks[`{neighborGX},{neighborGY},{neighborGZ}`]
|
||||
if not neighborChunk then
|
||||
return false -- Treat unloaded chunks as empty so edges render
|
||||
end
|
||||
|
||||
-- Check if the block exists in the neighboring chunk
|
||||
return neighborChunk:GetBlockAt(neighborRX, neighborRY, neighborRZ) ~= nil
|
||||
end
|
||||
|
||||
function Chunk:IsBlockRenderable(rx, ry, rz)
|
||||
task.desynchronize()
|
||||
local gx, gy, gz = self.pos.X, self.pos.Y, self.pos.Z
|
||||
-- Check all six neighboring blocks
|
||||
local d = not (
|
||||
self:DoesNeighboringBlockExist(rx, ry, rz, gx, gy, gz, 1, 0, 0) and
|
||||
self:DoesNeighboringBlockExist(rx, ry, rz, gx, gy, gz, -1, 0, 0) and
|
||||
self:DoesNeighboringBlockExist(rx, ry, rz, gx, gy, gz, 0, 1, 0) and
|
||||
self:DoesNeighboringBlockExist(rx, ry, rz, gx, gy, gz, 0, -1, 0) and
|
||||
self:DoesNeighboringBlockExist(rx, ry, rz, gx, gy, gz, 0, 0, 1) and
|
||||
self:DoesNeighboringBlockExist(rx, ry, rz, gx, gy, gz, 0, 0, -1)
|
||||
)
|
||||
return d
|
||||
end
|
||||
|
||||
|
||||
function Chunk:Tick()
|
||||
self.inhabitedTime = tick()
|
||||
end
|
||||
|
||||
function Chunk:PropogateChanges(x: number,y: number,z: number,d:BlockData)
|
||||
self.UpdateBlockBindableL:Fire(x,y,z,d)
|
||||
end
|
||||
|
||||
function Chunk:GetBlockAt(x,y,z)
|
||||
task.desynchronize()
|
||||
if not self.data[`{tostring(x)},{tostring(y)},{tostring(z)}`] then
|
||||
return nil
|
||||
end
|
||||
return self.data[`{tostring(x)},{tostring(y)},{tostring(z)}`]
|
||||
end
|
||||
|
||||
function Chunk:CreateBlock(x: number,y: number,z: number,d:BlockData)
|
||||
self.data[`{tostring(x)},{tostring(y)},{tostring(z)}`] = d
|
||||
self:PropogateChanges(x,y,z,d)
|
||||
return self:GetBlockAt(x,y,z)
|
||||
end
|
||||
|
||||
function Chunk:RemoveBlock(x, y, z)
|
||||
self.data[x .. "," .. y .. "," .. z] = nil
|
||||
self:PropogateChanges(x,y,z,0)
|
||||
end
|
||||
|
||||
-- unsure why this exists
|
||||
function Chunk:Load()
|
||||
end
|
||||
|
||||
function Chunk:Unload()
|
||||
|
||||
task.synchronize()
|
||||
self.loaded = false
|
||||
|
||||
-- SLOWCLEAR
|
||||
|
||||
task.defer(function()
|
||||
local g = 0
|
||||
for _,v in pairs(self.instance:GetChildren()) do
|
||||
pcall(function()
|
||||
v:Destroy()
|
||||
end)
|
||||
g += 1
|
||||
if g == 30 then
|
||||
g = 0
|
||||
Swait(2)
|
||||
end
|
||||
end
|
||||
|
||||
task.synchronize()
|
||||
self.instance.Parent = nil
|
||||
self.instance:Destroy()
|
||||
self.unloadChunkHook()
|
||||
task.desynchronize()
|
||||
end)
|
||||
end
|
||||
|
||||
-- DO NOT INTERACT WITH CHUNK AFTER CALLING THIS
|
||||
function Chunk:Destroy()
|
||||
self.data = {}
|
||||
end
|
||||
|
||||
return Chunk :: typeof(Chunk)
|
||||
Reference in New Issue
Block a user