core: impovements

This commit is contained in:
2026-01-07 20:28:34 +02:00
parent 4a512ceefb
commit a9da63e90e
4 changed files with 175 additions and 67 deletions

View File

@@ -5,7 +5,6 @@ local PlacementManager = {}
local ChunkManager = require("./ChunkManager")
local Util = require("./Util")
local RunService = game:GetService("RunService")
PlacementManager.ChunkFolder = ChunkManager.ChunkFolder
@@ -33,7 +32,56 @@ end
local Mouse: Mouse = nil
local lastNormalId: Enum.NormalId? = nil
local pendingBreakResync = {}
local BREAK_ROLLBACK_TIMEOUT = 0.6
local pendingBreaks = {}
local function makeChunkKey(cx: number, cy: number, cz: number): string
return `{cx},{cy},{cz}`
end
local function makeBlockKey(x: number, y: number, z: number): string
return `{x},{y},{z}`
end
local function getPendingBreak(chunkKey: string, blockKey: string)
local chunkMap = pendingBreaks[chunkKey]
if not chunkMap then
return nil
end
return chunkMap[blockKey]
end
local function clearPendingBreak(chunkKey: string, blockKey: string)
local chunkMap = pendingBreaks[chunkKey]
if not chunkMap then
return
end
chunkMap[blockKey] = nil
if not next(chunkMap) then
pendingBreaks[chunkKey] = nil
end
end
local function clearPendingBreaksForChunk(chunkKey: string)
pendingBreaks[chunkKey] = nil
end
local function scheduleBreakRollback(cx: number, cy: number, cz: number, x: number, y: number, z: number)
task.delay(BREAK_ROLLBACK_TIMEOUT, function()
local chunkKey = makeChunkKey(cx, cy, cz)
local blockKey = makeBlockKey(x, y, z)
local pending = getPendingBreak(chunkKey, blockKey)
if not pending then
return
end
clearPendingBreak(chunkKey, blockKey)
local chunk = ChunkManager:GetChunk(cx, cy, cz)
if pending.data and chunk then
chunk:CreateBlock(x, y, z, pending.data)
end
ChunkManager:RefreshChunk(cx, cy, cz)
end)
end
local function normalIdToOffset(normal: Enum.NormalId): Vector3
if normal == Enum.NormalId.Top then
@@ -83,6 +131,25 @@ local function offsetChunkBlock(chunk: Vector3, block: Vector3, offset: Vector3)
return Vector3.new(cx, cy, cz), Vector3.new(bx, by, bz)
end
local function getPlayerPosition(): Vector3?
local player = game:GetService("Players").LocalPlayer
local character = player and player.Character
if not character then
return nil
end
local root = character:FindFirstChild("HumanoidRootPart")
return root and root.Position or nil
end
local function isWithinReach(cx: number, cy: number, cz: number, x: number, y: number, z: number): boolean
local playerPos = getPlayerPosition()
if not playerPos then
return false
end
local blockPos = Util.ChunkPosToCFrame(Vector3.new(cx, cy, cz), Vector3.new(x, y, z)).Position
return (blockPos - playerPos).Magnitude <= 24
end
-- Gets the block and normalid of the block (and surface) the player is looking at
function PlacementManager:Raycast()
if not Mouse then
@@ -133,29 +200,38 @@ end
-- FIRES REMOTE
function PlacementManager:BreakBlock(cx, cy, cz, x, y, z)
print("[DEBUG] PlacementManager:BreakBlock called - Chunk:", cx, cy, cz, "Block:", x, y, z)
local chunk = ChunkManager:GetChunk(cx, cy, cz)
if chunk and not chunk:GetBlockAt(x, y, z) then
print("[DEBUG] Client missing block; resyncing nearby chunks")
ChunkManager:ResyncAroundChunk(cx, cy, cz, 1)
task.defer(function()
task.synchronize()
RunService.RenderStepped:Wait()
task.desynchronize()
local refreshed = ChunkManager:GetChunk(cx, cy, cz)
if refreshed and refreshed:GetBlockAt(x, y, z) then
task.synchronize()
breakRemote:FireServer(cx, cy, cz, x, y, z)
task.desynchronize()
print("[DEBUG] BreakBlock remote fired to server after resync")
end
end)
if typeof(cx) ~= "number" or typeof(cy) ~= "number" or typeof(cz) ~= "number" then
return
end
if typeof(x) ~= "number" or typeof(y) ~= "number" or typeof(z) ~= "number" then
return
end
if x < 1 or x > 8 or y < 1 or y > 8 or z < 1 or z > 8 then
return
end
if not isWithinReach(cx, cy, cz, x, y, z) then
return
end
local chunk = ChunkManager:GetChunk(cx, cy, cz)
local blockData = chunk and chunk:GetBlockAt(x, y, z) or nil
local chunkKey = makeChunkKey(cx, cy, cz)
local blockKey = makeBlockKey(x, y, z)
if getPendingBreak(chunkKey, blockKey) then
return
end
pendingBreaks[chunkKey] = pendingBreaks[chunkKey] or {}
pendingBreaks[chunkKey][blockKey] = {
data = blockData,
time = tick(),
}
if blockData then
chunk:RemoveBlock(x, y, z)
end
scheduleBreakRollback(cx, cy, cz, x, y, z)
task.synchronize()
breakRemote:FireServer(cx, cy, cz, x, y, z)
task.desynchronize()
print("[DEBUG] BreakBlock remote fired to server")
end
-- CLIENTSIDED: only apply server-validated changes
@@ -166,18 +242,17 @@ end
-- CLIENTSIDED: only apply server-validated changes
local function applyBreakBlockLocal(cx, cy, cz, x, y, z)
print("[DEBUG] PlacementManager:BreakBlockLocal called - Chunk:", cx, cy, cz, "Block:", x, y, z)
local chunk = ChunkManager:GetChunk(cx, cy, cz)
if chunk then
print("[DEBUG] Found chunk, calling RemoveBlock")
if chunk.RemoveBlockSmooth then
chunk:RemoveBlockSmooth(x, y, z)
else
chunk:RemoveBlock(x, y, z)
end
else
print("[DEBUG] Chunk not found at coords:", cx, cy, cz)
if not chunk then
return
end
local chunkKey = makeChunkKey(cx, cy, cz)
local blockKey = makeBlockKey(x, y, z)
if getPendingBreak(chunkKey, blockKey) then
clearPendingBreak(chunkKey, blockKey)
return
end
chunk:RemoveBlock(x, y, z)
end
function PlacementManager:GetBlockAtMouse(): nil | {chunk:Vector3, block: Vector3}
@@ -250,19 +325,9 @@ function PlacementManager:Init()
end
if m == "B_D" then
applyBreakBlockLocal(cx, cy, cz, x, y ,z)
local key = `{cx},{cy},{cz}`
if not pendingBreakResync[key] then
pendingBreakResync[key] = true
task.defer(function()
task.synchronize()
RunService.RenderStepped:Wait()
task.desynchronize()
pendingBreakResync[key] = nil
ChunkManager:ResyncAroundChunk(cx, cy, cz, 1)
end)
end
end
if m == "C_R" then
clearPendingBreaksForChunk(makeChunkKey(cx, cy, cz))
ChunkManager:RefreshChunk(cx, cy, cz)
end
end)