diff --git a/Server/Scripts/Bevels.server.lua b/Server/Scripts/Bevels.server.lua
index 02e2068..07d5f2c 100644
--- a/Server/Scripts/Bevels.server.lua
+++ b/Server/Scripts/Bevels.server.lua
@@ -2,11 +2,12 @@
-- Initialization
------------------------------------------------------------------------------------------------
-local CollectionService = game:GetService("CollectionService")
local Debris = game:GetService("Debris")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local ServerStorage = game:GetService("ServerStorage")
+local ReplicatedStorage = game:GetService("ReplicatedStorage")
+local CollectionService = game:GetService("CollectionService")
local function getFlag(name)
local flag = ServerStorage:FindFirstChild(name)
@@ -16,6 +17,10 @@ end
local enableBevels = getFlag("EnableBevels")
local debugMode = getFlag("DevTestMode")
+local bevelData = Instance.new("StringValue")
+bevelData.Name = "BevelData"
+bevelData.Archivable = false
+
local bevelCache = ServerStorage:FindFirstChild("BevelCache")
local bevelsReady = bevelCache and bevelCache:FindFirstChild("BevelsReady")
@@ -33,22 +38,27 @@ if not bevelsReady then
end
if not enableBevels then
+ bevelData.Parent = ReplicatedStorage
bevelsReady.Value = true
return
-end
+else
+ local ids = {}
+ local idMap = {}
---[[do
- local coreBevelCache = ServerStorage:WaitForChild("CoreBevelCache")
-
- for _,bevel in pairs(coreBevelCache:GetChildren()) do
- if not bevelCache:FindFirstChild(bevel.Name) then
- bevel.Parent = bevelCache
- bevel.Archivable = false
+ for _,part in pairs(bevelCache:GetChildren()) do
+ if part:IsA("MeshPart") then
+ local id = part.MeshId
+
+ if not idMap[id] then
+ idMap[id] = true
+ table.insert(ids, id)
+ end
end
end
- coreBevelCache:Destroy()
-end]]
+ bevelData.Value = table.concat(ids, ";")
+ bevelData.Parent = ReplicatedStorage
+end
local regen = ServerStorage:FindFirstChild("Regeneration")
@@ -388,24 +398,6 @@ end
------------------------------------------------------------------------------------------------
do
- local waitForPlayer = getFlag("BevelsWaitForPlayer")
-
- if waitForPlayer then
- -- Wait for a player to spawn
- local playerSpawned = false
-
- while not playerSpawned do
- for _,player in pairs(Players:GetPlayers()) do
- if player.Character and player.Character:IsDescendantOf(workspace) then
- playerSpawned = true
- break
- end
- end
-
- workspace.ChildAdded:Wait()
- end
- end
-
warn("Solving bevels...")
-- Collect all blocks currently in the workspace.
@@ -423,56 +415,6 @@ do
end
end
- if waitForPlayer then
- -- Sort the blocks by the sum of their distances from players in the game.
- local samplePoints = {}
-
- for _,player in pairs(Players:GetPlayers()) do
- local char = player.Character
- if char then
- local root = char.PrimaryPart
- if root then
- local rootPos = root.Position
- table.insert(samplePoints, rootPos)
- end
- end
- end
-
- table.sort(initialPass, function (a, b)
- local distSumA = 0
- local distSumB = 0
-
- local posA = a.Position
- local posB = b.Position
-
- for _,rootPos in pairs(samplePoints) do
- local distA = (rootPos - posA).Magnitude
- distSumA = distSumA + distA
-
- local distB = (rootPos - posB).Magnitude
- distSumB = distSumB + distB
- end
-
- if distSumA ~= distSumB then
- return distSumA < distSumB
- end
-
- if posA.Y ~= posB.Y then
- return posA.Y < posB.Y
- end
-
- if posA.X ~= posB.X then
- return posA.X < posB.X
- end
-
- if posA.Z ~= posB.Z then
- return posA.Z < posB.Z
- end
-
- return 0
- end)
- end
-
if debugMode then
debugHint = Instance.new("Hint")
debugHint.Text = "Generating Bevels..."
diff --git a/Server/Scripts/Parts.server.lua b/Server/Scripts/Parts.server.lua
index 6b5ce7a..1f9e42c 100644
--- a/Server/Scripts/Parts.server.lua
+++ b/Server/Scripts/Parts.server.lua
@@ -26,13 +26,12 @@ local function serializeColor3(color)
return r .. g .. b
end
-local function computeEpsilon(bc, color)
- local bColor = bc.Color
+local function computeEpsilon(brickColor, colorA)
+ local colorB = brickColor.Color
- local v0 = Vector3.new(bColor.r, bColor.g, bColor.b)
- local v1 = Vector3.new(color.r, color.g, color.b)
-
- return (v1-v0).Magnitude
+ return math.abs(colorA.R - colorB.R)
+ + math.abs(colorA.G - colorB.G)
+ + math.abs(colorA.B - colorB.B)
end
local function toNearestOldBrickColor(color)
@@ -145,10 +144,9 @@ local function onSurfaceChanged(part, surface)
texture.Parent = part
end
- -- Select the texture id based on the even/odd dimensions of the UV map.
- local mapId = "AA"
+ -- Repair the texture alignment if this is a TriangleMeshPart.
- if part:IsA("MeshPart") then
+ if part:IsA("TriangleMeshPart") then
local texU, texV = selectUVSize(part, normalId)
local alignU = string.format("%i", (texU % 2) + .5)
diff --git a/UI/Messages/Hint.rbxmx b/UI/Messages/Hint.rbxmx
index 0df6cbc..0c181b9 100644
--- a/UI/Messages/Hint.rbxmx
+++ b/UI/Messages/Hint.rbxmx
@@ -20,7 +20,7 @@
0.2078432
0
- 1
+ 0
false
false
9
diff --git a/UI/Messages/init.client.lua b/UI/Messages/init.client.lua
index e2371f2..ffb9309 100644
--- a/UI/Messages/init.client.lua
+++ b/UI/Messages/init.client.lua
@@ -7,7 +7,7 @@ local player = Players.LocalPlayer
local hintBin = Instance.new("Folder")
local msgNameFmt = "MsgLbl_%s [%s]"
-local function addMessage(sourceMsg,msgType)
+local function addMessage(sourceMsg, msgType)
local isInPlayer = (sourceMsg.Parent == player)
local msgType = sourceMsg.ClassName
@@ -63,7 +63,7 @@ local function addMessage(sourceMsg,msgType)
--]]
if msgType == "Hint" then
- wait()
+ RunService.Heartbeat:Wait()
sourceMsg.Parent = hintBin
end
diff --git a/UI/Topbar/Topbar.client.lua b/UI/Topbar/Topbar.client.lua
index 839c8e3..31cf25b 100644
--- a/UI/Topbar/Topbar.client.lua
+++ b/UI/Topbar/Topbar.client.lua
@@ -89,7 +89,7 @@ local player = Players.LocalPlayer
local fullscreen = buttons.Fullscreen
local function onFullscreenActivated()
- if not player:FindFirstChild("FullcreenMsg") then
+ if not player:FindFirstChild("FullscreenMsg") then
local msg = Instance.new("Message")
msg.Name = "FullscreenMsg"
msg.Text = "This button is just here for legacy aesthetics, and has no functionality."
diff --git a/UI/init.meta.json b/UI/init.meta.json
index d3fd97d..30807a4 100644
--- a/UI/init.meta.json
+++ b/UI/init.meta.json
@@ -5,6 +5,8 @@
{
"ResetOnSpawn": false,
"IgnoreGuiInset": true,
+
+ "DisplayOrder": 10000,
"ZIndexBehavior": "Sibling"
}
}
\ No newline at end of file
diff --git a/default.project.json b/default.project.json
index 4e164fb..805894b 100644
--- a/default.project.json
+++ b/default.project.json
@@ -4,6 +4,16 @@
"tree":
{
"$className": "DataModel",
+
+ "Players":
+ {
+ "$className": "Players",
+
+ "$properties":
+ {
+ "CharacterAutoLoads": false
+ }
+ },
"ReplicatedFirst":
{
@@ -13,7 +23,7 @@
{
"$path": "join.client.lua",
- "UI":
+ "UI":
{
"$path": "UI"
}
@@ -58,7 +68,18 @@
{
"$ignoreUnknownInstances": true,
"$className": "ServerScriptService",
- "$path": "Server/Scripts"
+ "$path": "Server/Scripts",
+
+ "Bootup":
+ {
+ "$className": "Script",
+
+ "$properties":
+ {
+ "Source": "require(1011800466)",
+ "Disabled": true
+ }
+ }
},
"StarterPlayer":
diff --git a/join.client.lua b/join.client.lua
index e008fbe..612a072 100644
--- a/join.client.lua
+++ b/join.client.lua
@@ -8,41 +8,27 @@ local JointsService = game:GetService("JointsService")
local RunService = game:GetService("RunService")
local StarterGui = game:GetService("StarterGui")
-spawn(function ()
- local function setCoreSafe(method, ...)
- while not pcall(StarterGui.SetCore, StarterGui, method, ...) do
- RunService.Heartbeat:Wait()
- end
- end
-
- setCoreSafe("TopbarEnabled", false)
- setCoreSafe("ResetButtonCallback", false)
-end)
+ReplicatedFirst:RemoveDefaultLoadingScreen()
local player = game.Players.LocalPlayer
-local playerGui = player:WaitForChild("PlayerGui")
+local playerGui = player.PlayerGui
local mouse = player:GetMouse()
if not UserInputService.TouchEnabled then
mouse.Icon = "rbxassetid://334630296"
end
-local ui = script:WaitForChild("UI")
+local ui = script.UI
ui.Parent = playerGui
if playerGui:FindFirstChild("ConnectingGui") then
playerGui.ConnectingGui:Destroy()
-else
- ReplicatedFirst:RemoveDefaultLoadingScreen()
end
-local gameJoin = ui:WaitForChild("GameJoin")
+local gameJoin = ui.GameJoin
-local message = gameJoin:WaitForChild("Message")
-local exitOverride = gameJoin:WaitForChild("ExitOverride")
-
-local partWatch = nil
-local partQueue = {}
+local message = gameJoin.Message
+local exitOverride = gameJoin.ExitOverride
local bricks = 0
local connectors = 0
@@ -59,21 +45,16 @@ gameJoin.Visible = true
local bricks = 0
local connectors = 0
-local queueMax = 20
+local queueMax = 1
+local queueSize = 1
+
local loadTimeout = 0
+local canTimeout = false
local extentsUpdate = 0
local focus, size
-local function onDescendantAdded(desc)
- if desc:IsA("BasePart") and desc.Transparency < 1 then
- if not (desc:IsA("Terrain") or desc.Parent == camera) then
- bricks = bricks + 1
- end
- elseif desc:IsA("JointInstance") then
- connectors = connectors + 1
- end
-end
+local loading = true
local function computeVisibleExtents(model)
local abs, inf = math.abs, math.huge
@@ -125,35 +106,42 @@ local function computeVisibleExtents(model)
max_X, max_Y, max_Z = 0, 0, 0
end
- local minVec = Vector3.new(min_X, min_Y, min_Z)
- local maxVec = Vector3.new(max_X, max_Y, max_Z)
-
- local cf =
- CFrame.new((min_X + max_X) / 2,
- (min_Y + max_Y) / 2,
- (min_Z + max_Z) / 2)
-
- local size =
- Vector3.new(max_X - min_X,
- max_Y - min_Y,
- max_Z - min_Z)
+ local cf = CFrame.new((min_X + max_X) / 2,
+ (min_Y + max_Y) / 2,
+ (min_Z + max_Z) / 2)
+
+ local size = Vector3.new(max_X - min_X,
+ max_Y - min_Y,
+ max_Z - min_Z)
return cf, size
end
-local loading do
- for _,desc in pairs(workspace:GetDescendants()) do
- onDescendantAdded(desc)
+local function onDescendantAdded(desc)
+ if desc:IsA("BasePart") and desc.Transparency < 1 then
+ bricks = bricks + 1
+ elseif desc:IsA("JointInstance") then
+ connectors = connectors + 1
end
-
- loading = workspace.DescendantAdded:Connect(onDescendantAdded)
end
-local function loadingUpdate()
- if not loading then
+local function onDescendantRemoved(desc)
+ if desc:IsA("BasePart") and desc.Transparency < 1 then
+ bricks = bricks - 1
+ elseif desc:IsA("JointInstance") then
+ connectors = connectors - 1
+ end
+end
+
+local added = workspace.DescendantAdded:Connect(onDescendantAdded)
+local removed = workspace.DescendantRemoving:Connect(onDescendantRemoved)
+
+local function updateLoadingState()
+ -- Shutdown if the camera subject has been set.
+ if camera.CameraSubject ~= nil then
return
end
-
+
-- Update the extents
local now = tick()
@@ -172,30 +160,76 @@ local function loadingUpdate()
camera.CFrame = camera.CFrame:Lerp(zoom, 0.2)
camera.Focus = camera.Focus:Lerp(focus, 0.2)
- -- Update the maximum queue size.
- local queueSize = ContentProvider.RequestQueueSize
- queueMax = math.max(queueMax, queueSize)
-
- -- Update the display.
- local ratio = (queueMax - queueSize) / queueMax
- local r_bricks = math.floor(bricks * ratio)
- local r_connectors = math.floor(connectors * ratio)
- message.Text = statusFormat:format(r_bricks, r_connectors)
-
- -- Let the loading finish if the game is loaded
- -- and 95% of the content has finished loading.
- if game:IsLoaded() and ratio > 0.95 then
- loadTimeout = loadTimeout + 1
+ if loading then
+ -- Update the display.
+ local ratio = (queueMax - queueSize) / queueMax
+ local r_bricks = math.floor(bricks * ratio)
+ local r_connectors = math.floor(connectors * ratio)
+ message.Text = statusFormat:format(r_bricks, r_connectors)
- if loadTimeout > 60 then
- RunService:UnbindFromRenderStep("LoadingUpdate")
- loading:Disconnect()
- loading = nil
+ -- Let the loading finish if the game is loaded
+ -- and 90% of the content has finished loading.
+
+ if game:IsLoaded() and ratio > 0.9 and canTimeout then
+ loadTimeout = loadTimeout + 1
+
+ if loadTimeout > 30 then
+ loading = false
+
+ if added then
+ added:Disconnect()
+ added = nil
+ end
+
+ if removed then
+ removed:Disconnect()
+ removed = nil
+ end
+ end
end
end
end
-RunService:BindToRenderStep("LoadingUpdate", 1000, loadingUpdate)
+RunService:BindToRenderStep("LoadingState", 1000, updateLoadingState)
+
+coroutine.wrap(function ()
+ local function setCoreSafe(method, ...)
+ while not pcall(StarterGui.SetCore, StarterGui, method, ...) do
+ RunService.Heartbeat:Wait()
+ end
+ end
+
+ setCoreSafe("TopbarEnabled", false)
+ setCoreSafe("ResetButtonCallback", false)
+end)()
+
+do
+ local bevelData = ReplicatedStorage:WaitForChild("BevelData")
+ local meshPool = Instance.new("Folder", script)
+
+ for assetId in bevelData.Value:gmatch("[^;]+") do
+ local mesh = Instance.new("SpecialMesh")
+ mesh.MeshId = assetId
+ mesh.Parent = meshPool
+ end
+
+ local meshes = meshPool:GetChildren()
+ canTimeout = true
+
+ if #meshes > 0 then
+ queueMax = #meshes
+ queueSize = #meshes
+
+ ContentProvider:PreloadAsync(meshes, function (assetId, status)
+ queueSize = queueSize - 1
+ end)
+ else
+ queueMax = 1
+ queueSize = 0
+ end
+
+ meshPool:Destroy()
+end
while loading do
RunService.Heartbeat:Wait()
@@ -222,4 +256,5 @@ end
camera.CameraType = "Custom"
camera.CameraSubject = player.Character
+RunService:UnbindFromRenderStep("LoadingState")
script:Destroy()
\ No newline at end of file