core: fix building

This commit is contained in:
2026-01-08 19:30:49 +02:00
parent 165913ca51
commit 2381fa124a
9 changed files with 594 additions and 83 deletions

View File

@@ -3,25 +3,61 @@
local TerrainGen = {}
local deflate = require("./TerrainGen/Deflate")
local DSS = game:GetService("DataStoreService")
local WORLDNAME = "DEFAULT"
local WORLDID = "b73bb5a6-297d-4352-b637-daec7e8c8f3e"
local Store = DSS:GetDataStore("BlockscraftWorldV1", WORLDID)
local ChunkManager = require(game:GetService("ReplicatedStorage"):WaitForChild("Shared").ChunkManager)
local Chunk = require(game:GetService("ReplicatedStorage"):WaitForChild("Shared").ChunkManager.Chunk)
TerrainGen.ServerChunkCache = {} :: {[typeof("")]: typeof(Chunk.new(0,0,0))}
local function chunkKeyFromCoords(x: number, y: number, z: number): string
return `{x},{y},{z}`
end
function TerrainGen:UnloadAllChunks(): number
local count = 0
for key in pairs(TerrainGen.ServerChunkCache) do
TerrainGen.ServerChunkCache[key] = nil
count += 1
end
return count
end
local function worldToChunkCoord(v: number): number
return math.floor((v + 16) / 32)
end
function TerrainGen:PreloadNearPlayers(radius: number, yRadius: number?): number
local Players = game:GetService("Players")
local r = radius or 5
local ry = yRadius or 1
local loaded = 0
for _, player in ipairs(Players:GetPlayers()) do
local character = player.Character
local root = character and character:FindFirstChild("HumanoidRootPart")
if root then
local pos = root.Position
local cx = worldToChunkCoord(pos.X)
local cy = worldToChunkCoord(pos.Y)
local cz = worldToChunkCoord(pos.Z)
for y = -ry, ry do
for x = -r, r do
for z = -r, r do
TerrainGen:GetChunk(cx + x, cy + y, cz + z)
loaded += 1
end
end
end
end
end
return loaded
end
-- Load a chunk from the DataStore or generate it if not found
function TerrainGen:GetChunk(x, y, z)
local key = `{x},{y},{z}`
local key = chunkKeyFromCoords(x, y, z)
if TerrainGen.ServerChunkCache[key] then
return TerrainGen.ServerChunkCache[key]
end
-- Generate a new chunk if it doesn't exist
local chunk = Chunk.new(x, y, z)
if y == 1 then
@@ -67,7 +103,6 @@ function TerrainGen:GetFakeChunk(x, y, z)
return chunk
end
TerrainGen.CM = ChunkManager
return TerrainGen

View File

@@ -139,12 +139,21 @@ local function isBlockInsidePlayer(blockPos: Vector3): boolean
end
local DEBUG_PLACEMENT = true
local function debugPlacementLog(...: any)
if DEBUG_PLACEMENT then
Util.StudioLog(...)
end
end
local function debugPlacementWarn(...: any)
if DEBUG_PLACEMENT then
Util.StudioWarn(...)
end
end
placeRemote.OnServerEvent:Connect(function(player, cx, cy, cz, x, y, z, blockId)
local function reject(reason: string)
if DEBUG_PLACEMENT then
warn("[PLACE][REJECT]", player.Name, reason, "chunk", cx, cy, cz, "block", x, y, z, "id", blockId)
end
debugPlacementWarn("[PLACE][REJECT]", player.Name, reason, "chunk", cx, cy, cz, "block", x, y, z, "id", blockId)
return
end
@@ -178,9 +187,7 @@ placeRemote.OnServerEvent:Connect(function(player, cx, cy, cz, x, y, z, blockId)
if existing and existing.id and existing.id ~= 0 then
if existing.id == resolvedId then
-- same block already there; treat as success without changes
if DEBUG_PLACEMENT then
print("[PLACE][OK][NOOP]", player.Name, "chunk", cx, cy, cz, "block", x, y, z, "id", resolvedId)
end
debugPlacementLog("[PLACE][OK][NOOP]", player.Name, "chunk", cx, cy, cz, "block", x, y, z, "id", resolvedId)
return
end
-- allow replacement when different id: remove then place
@@ -192,9 +199,7 @@ placeRemote.OnServerEvent:Connect(function(player, cx, cy, cz, x, y, z, blockId)
}
chunk:CreateBlock(x, y, z, data)
propogate("B_C", cx, cy, cz, x, y, z, data)
if DEBUG_PLACEMENT then
print("[PLACE][OK]", player.Name, "chunk", cx, cy, cz, "block", x, y, z, "id", resolvedId)
end
debugPlacementLog("[PLACE][OK]", player.Name, "chunk", cx, cy, cz, "block", x, y, z, "id", resolvedId)
end)
breakRemote.OnServerEvent:Connect(function(player, cx, cy, cz, x, y, z)
@@ -219,10 +224,12 @@ breakRemote.OnServerEvent:Connect(function(player, cx, cy, cz, x, y, z)
task.synchronize()
tickRemote:FireClient(player, "C_R", cx, cy, cz, 0, 0, 0, 0)
task.desynchronize()
debugPlacementLog("[BREAK][NOOP]", player.Name, "chunk", cx, cy, cz, "block", x, y, z)
return
end
chunk:RemoveBlock(x, y, z)
propogate("B_D", cx, cy, cz, x, y, z, 0)
debugPlacementLog("[BREAK][OK]", player.Name, "chunk", cx, cy, cz, "block", x, y, z)
end)
task.desynchronize()

View File

@@ -0,0 +1,79 @@
return {
Name = "chunkcull",
Aliases = {"cullchunks", "resetchunks"},
Description = "Unload all server chunk cache instantly, then preload only chunks near players (and force clients to unload/resync).",
Group = "Admin",
Args = {
{
Type = "integer",
Name = "radius",
Description = "Horizontal chunk radius around each player to preload",
Optional = true,
Default = 5,
},
{
Type = "integer",
Name = "yRadius",
Description = "Vertical chunk radius around each player to preload",
Optional = true,
Default = 1,
},
},
Run = function(context, radius, yRadius)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local terrainGen = require(
game:GetService("ServerScriptService")
:WaitForChild("Actor")
:WaitForChild("ServerChunkManager")
:WaitForChild("TerrainGen")
)
local tickRemote = ReplicatedStorage:WaitForChild("Tick")
local r = radius or 5
local ry = yRadius or 1
local unloaded = 0
pcall(function()
unloaded = terrainGen:UnloadAllChunks()
end)
-- Tell all clients to immediately drop their local chunk instances
pcall(function()
tickRemote:FireAllClients("U_ALL", 0, 0, 0, 0, 0, 0, 0)
end)
-- Preload server chunks around players (reduces initial lag spikes after cull)
local preloaded = 0
pcall(function()
preloaded = terrainGen:PreloadNearPlayers(r, ry)
end)
-- Force clients to resync around themselves
local resyncCount = 0
for _, player in ipairs(Players:GetPlayers()) do
local character = player.Character
local root = character and character:FindFirstChild("HumanoidRootPart")
if root then
local pos = root.Position
local cx = math.floor((pos.X + 16) / 32)
local cy = math.floor((pos.Y + 16) / 32)
local cz = math.floor((pos.Z + 16) / 32)
for y = -ry, ry do
for x = -r, r do
for z = -r, r do
tickRemote:FireClient(player, "C_R", cx + x, cy + y, cz + z, 0, 0, 0, 0)
resyncCount += 1
end
end
end
end
end
return (
"chunkcull done | unloaded=%d | preloaded=%d | resyncPackets=%d | radius=%d yRadius=%d"
):format(unloaded, preloaded, resyncCount, r, ry)
end,
}