core: impovements
This commit is contained in:
@@ -158,27 +158,13 @@ function Chunk:CreateBlock(x: number,y: number,z: number,d:BlockData)
|
||||
end
|
||||
|
||||
function Chunk:RemoveBlock(x, y, z)
|
||||
print("[DEBUG] Chunk:RemoveBlock called - Chunk:", self.pos, "Block coords:", x, y, z)
|
||||
local blockKey = keyFromCoords(x, y, z)
|
||||
local existingBlock = self.data[blockKey]
|
||||
if existingBlock then
|
||||
print("[DEBUG] Removing existing block with ID:", existingBlock.id)
|
||||
else
|
||||
print("[DEBUG] No block found at coords", x, y, z)
|
||||
end
|
||||
self.data[blockKey] = nil
|
||||
self:PropogateChanges(x,y,z,0)
|
||||
end
|
||||
|
||||
function Chunk:RemoveBlockSmooth(x, y, z)
|
||||
print("[DEBUG] Chunk:RemoveBlockSmooth called - Chunk:", self.pos, "Block coords:", x, y, z)
|
||||
local blockKey = keyFromCoords(x, y, z)
|
||||
local existingBlock = self.data[blockKey]
|
||||
if existingBlock then
|
||||
print("[DEBUG] Smooth removing existing block with ID:", existingBlock.id)
|
||||
else
|
||||
print("[DEBUG] Smooth remove: no block found at coords", x, y, z)
|
||||
end
|
||||
self.data[blockKey] = nil
|
||||
self.delayedRemoval[blockKey] = true
|
||||
self:PropogateChanges(x,y,z,0)
|
||||
|
||||
@@ -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)
|
||||
|
||||
47
src/ServerScriptService/Actor/PlayerScale.server.lua
Normal file
47
src/ServerScriptService/Actor/PlayerScale.server.lua
Normal file
@@ -0,0 +1,47 @@
|
||||
--!native
|
||||
--!optimize 2
|
||||
|
||||
local Players = game:GetService("Players")
|
||||
|
||||
local SCALE = 1.4
|
||||
|
||||
local function applyScale(character: Model)
|
||||
if character.ScaleTo then
|
||||
pcall(function()
|
||||
character:ScaleTo(SCALE)
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
local humanoid = character:FindFirstChildOfClass("Humanoid")
|
||||
if not humanoid then
|
||||
return
|
||||
end
|
||||
|
||||
if humanoid.RigType == Enum.HumanoidRigType.R15 then
|
||||
for _, name in ipairs({"BodyHeightScale", "BodyWidthScale", "BodyDepthScale", "HeadScale"}) do
|
||||
local scaleValue = humanoid:FindFirstChild(name)
|
||||
if scaleValue then
|
||||
scaleValue.Value = SCALE
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function onCharacterAdded(character: Model)
|
||||
character:WaitForChild("Humanoid", 5)
|
||||
applyScale(character)
|
||||
end
|
||||
|
||||
local function onPlayerAdded(player: Player)
|
||||
player.CharacterAdded:Connect(onCharacterAdded)
|
||||
if player.Character then
|
||||
onCharacterAdded(player.Character)
|
||||
end
|
||||
end
|
||||
|
||||
for _, player in ipairs(Players:GetPlayers()) do
|
||||
onPlayerAdded(player)
|
||||
end
|
||||
|
||||
Players.PlayerAdded:Connect(onPlayerAdded)
|
||||
@@ -1,8 +1,6 @@
|
||||
--!native
|
||||
--!optimize 2
|
||||
|
||||
print("Hello world!")
|
||||
|
||||
task.synchronize()
|
||||
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
@@ -13,6 +11,7 @@ local ModsFolder = ReplicatedStorage:WaitForChild("Mods")
|
||||
|
||||
local Util = require(Shared.Util)
|
||||
local TG = require("./ServerChunkManager/TerrainGen")
|
||||
local Players = game:GetService("Players")
|
||||
|
||||
do
|
||||
local workspaceModFolder = game:GetService("Workspace"):WaitForChild("mods")
|
||||
@@ -127,6 +126,22 @@ local function getServerChunk(cx: number, cy: number, cz: number)
|
||||
return chunk
|
||||
end
|
||||
|
||||
local function isBlockInsidePlayer(blockPos: Vector3): boolean
|
||||
for _, player in ipairs(Players:GetPlayers()) do
|
||||
local character = player.Character
|
||||
if character then
|
||||
local cf, size = character:GetBoundingBox()
|
||||
local localPos = cf:PointToObjectSpace(blockPos)
|
||||
if math.abs(localPos.X) <= size.X * 0.5
|
||||
and math.abs(localPos.Y) <= size.Y * 0.5
|
||||
and math.abs(localPos.Z) <= size.Z * 0.5 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
placeRemote.OnServerEvent:Connect(function(player, cx, cy, cz, x, y, z, blockId)
|
||||
--print("place",player, cx, cy, cz, x, y, z, blockData)
|
||||
|
||||
@@ -150,6 +165,11 @@ placeRemote.OnServerEvent:Connect(function(player, cx, cy, cz, x, y, z, blockId)
|
||||
return
|
||||
end
|
||||
|
||||
local blockPos = Util.ChunkPosToCFrame(Vector3.new(cx, cy, cz), Vector3.new(x, y, z)).Position
|
||||
if isBlockInsidePlayer(blockPos) then
|
||||
return
|
||||
end
|
||||
|
||||
local chunk = getServerChunk(cx, cy, cz)
|
||||
if chunk:GetBlockAt(x, y, z) then
|
||||
return
|
||||
@@ -163,41 +183,31 @@ placeRemote.OnServerEvent:Connect(function(player, cx, cy, cz, x, y, z, blockId)
|
||||
end)
|
||||
|
||||
breakRemote.OnServerEvent:Connect(function(player, cx, cy, cz, x, y, z)
|
||||
print("[DEBUG] Server breakRemote received - Player:", player.Name, "Chunk:", cx, cy, cz, "Block:", x, y, z)
|
||||
|
||||
if typeof(cx) ~= "number" or typeof(cy) ~= "number" or typeof(cz) ~= "number" then
|
||||
print("[DEBUG] Invalid chunk coordinate types")
|
||||
return
|
||||
end
|
||||
if typeof(x) ~= "number" or typeof(y) ~= "number" or typeof(z) ~= "number" then
|
||||
print("[DEBUG] Invalid block coordinate types")
|
||||
return
|
||||
end
|
||||
if x < 1 or x > 8 or y < 1 or y > 8 or z < 1 or z > 8 then
|
||||
print("[DEBUG] Block coordinates out of range:", x, y, z)
|
||||
return
|
||||
end
|
||||
if math.abs(cx) > MAX_CHUNK_DIST or math.abs(cy) > MAX_CHUNK_DIST or math.abs(cz) > MAX_CHUNK_DIST then
|
||||
print("[DEBUG] Chunk coordinates out of range:", cx, cy, cz)
|
||||
return
|
||||
end
|
||||
if not isWithinReach(player, cx, cy, cz, x, y, z) then
|
||||
print("[DEBUG] Block not within player reach")
|
||||
return
|
||||
end
|
||||
|
||||
local chunk = getServerChunk(cx, cy, cz)
|
||||
if not chunk:GetBlockAt(x, y, z) then
|
||||
print("[DEBUG] No block found at specified location")
|
||||
task.synchronize()
|
||||
tickRemote:FireClient(player, "C_R", cx, cy, cz, 0, 0, 0, 0)
|
||||
task.desynchronize()
|
||||
return
|
||||
end
|
||||
print("[DEBUG] All validations passed, removing block")
|
||||
chunk:RemoveBlock(x, y, z)
|
||||
propogate("B_D", cx, cy, cz, x, y, z, 0)
|
||||
print("[DEBUG] Block removal propagated to clients")
|
||||
end)
|
||||
|
||||
task.desynchronize()
|
||||
|
||||
Reference in New Issue
Block a user