Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[ hi i think this script is works very well
- bc it never failed to save and load
- ]]
- local DataStoreService = game:GetService("DataStoreService")
- local ReplicatedStorage = game:GetService("ReplicatedStorage")
- local ServerScriptService = game:GetService("ServerScriptService")
- local Players = game:GetService("Players")
- local HttpService = game:GetService("HttpService")
- local remoteload = ReplicatedStorage:WaitForChild("LoadSign")
- -- Constants
- local MAX_DATA_SIZE = 3900000 -- ~3.9MB (slightly under DataStore's 4MB limit)
- local MAX_DATASTORES = 1000
- local MAX_CHUNKS_PER_STORE = 5
- local isMapLoading = false
- local saveQueue = {}
- local mapFullyLoaded = false
- -- Helper functions for data conversion
- local function vector3ToTable(vec)
- return {vec.X, vec.Y, vec.Z}
- end
- local function tableToVector3(tbl)
- return Vector3.new(tbl[1], tbl[2], tbl[3])
- end
- local function color3ToTable(color)
- return {color.R, color.G, color.B}
- end
- local function tableToColor3(tbl)
- return Color3.new(tbl[1], tbl[2], tbl[3])
- end
- local function udim2ToTable(udim)
- return {
- {udim.X.Scale, udim.X.Offset},
- {udim.Y.Scale, udim.Y.Offset}
- }
- end
- local function tableToUDim2(tbl)
- return UDim2.new(tbl[1][1], tbl[1][2], tbl[2][1], tbl[2][2])
- end
- local function verifyPartAnchoring()
- local parts = {}
- local unanchoredCount = 0
- for _, obj in ipairs(workspace:GetDescendants()) do
- if obj:IsA("BasePart") and not obj:IsDescendantOf(game:GetService("Players")) then
- table.insert(parts, obj)
- end
- end
- for _, part in ipairs(parts) do
- if not part.Anchored and not part:GetAttribute("Physics") and part:GetAttribute("ShouldBeAnchored") then
- part.Anchored = true
- unanchoredCount += 1
- end
- end
- if unanchoredCount > 0 then
- print(`-- Fixed {unanchoredCount} unanchored parts`)
- end
- end
- local function serializeGuiObject(obj)
- if obj:IsA("TextLabel") then
- return {
- ClassName = "TextLabel",
- Name = obj.Name,
- Text = obj.Text,
- TextColor3 = color3ToTable(obj.TextColor3),
- BackgroundColor3 = color3ToTable(obj.BackgroundColor3),
- TextSize = obj.TextSize,
- Font = obj.Font.Name,
- Position = udim2ToTable(obj.Position),
- Size = udim2ToTable(obj.Size),
- BackgroundTransparency = obj.BackgroundTransparency,
- TextTransparency = obj.TextTransparency,
- TextXAlignment = obj.TextXAlignment.Name,
- TextYAlignment = obj.TextYAlignment.Name,
- TextWrapped = obj.TextWrapped,
- TextScaled = obj.TextScaled,
- BorderSizePixel = obj.BorderSizePixel,
- BorderColor3 = color3ToTable(obj.BorderColor3),
- Visible = obj.Visible,
- Children = {}
- }
- elseif obj:IsA("Frame") then
- local frameData = {
- ClassName = "Frame",
- Name = obj.Name,
- BackgroundColor3 = color3ToTable(obj.BackgroundColor3),
- Position = udim2ToTable(obj.Position),
- Size = udim2ToTable(obj.Size),
- BackgroundTransparency = obj.BackgroundTransparency,
- BorderSizePixel = obj.BorderSizePixel,
- BorderColor3 = color3ToTable(obj.BorderColor3),
- Visible = obj.Visible,
- Children = {}
- }
- for _, child in ipairs(obj:GetChildren()) do
- local childData = serializeGuiObject(child)
- if childData then
- table.insert(frameData.Children, childData)
- end
- end
- return frameData
- elseif obj:IsA("ImageLabel") then
- return {
- ClassName = "ImageLabel",
- Name = obj.Name,
- Image = obj.Image,
- ImageColor3 = color3ToTable(obj.ImageColor3),
- BackgroundColor3 = color3ToTable(obj.BackgroundColor3),
- Position = udim2ToTable(obj.Position),
- Size = udim2ToTable(obj.Size),
- BackgroundTransparency = obj.BackgroundTransparency,
- ImageTransparency = obj.ImageTransparency,
- BorderSizePixel = obj.BorderSizePixel,
- BorderColor3 = color3ToTable(obj.BorderColor3),
- ScaleType = obj.ScaleType.Name,
- Visible = obj.Visible,
- Children = {}
- }
- end
- return nil
- end
- local function serializeSurfaceGui(gui)
- local guiData = {
- ClassName = "SurfaceGui",
- Name = gui.Name,
- Face = gui.Face.Name,
- Enabled = gui.Enabled,
- SizingMode = gui.SizingMode.Name,
- PixelsPerStud = gui.PixelsPerStud,
- Children = {}
- }
- for _, child in ipairs(gui:GetChildren()) do
- local childData = serializeGuiObject(child)
- if childData then
- table.insert(guiData.Children, childData)
- end
- end
- return guiData
- end
- local function serializeChildInstance(child)
- if child:IsA("Decal") then
- return {
- ClassName = "Decal",
- Name = child.Name,
- Texture = child.Texture,
- Transparency = child.Transparency,
- Face = child.Face.Name
- }
- elseif child:IsA("PointLight") then
- return {
- ClassName = "PointLight",
- Name = child.Name,
- Brightness = child.Brightness,
- Range = child.Range,
- Color = color3ToTable(child.Color),
- Shadows = child.Shadows,
- Enabled = child.Enabled
- }
- elseif child:IsA("Fire") then
- return {
- ClassName = "Fire",
- Name = child.Name,
- Heat = child.Heat,
- Size = child.Size,
- Color = color3ToTable(child.Color),
- SecondaryColor = color3ToTable(child.SecondaryColor),
- Enabled = child.Enabled
- }
- elseif child:IsA("Smoke") then
- return {
- ClassName = "Smoke",
- Name = child.Name,
- Size = child.Size,
- Opacity = child.Opacity,
- Color = color3ToTable(child.Color),
- Enabled = child.Enabled
- }
- elseif child:IsA("SurfaceGui") then
- return serializeSurfaceGui(child)
- elseif child:IsA("Texture") then
- return {
- ClassName = "Texture",
- Name = child.Name,
- Texture = child.Texture,
- Transparency = child.Transparency,
- Face = child.Face.Name,
- StudsPerTileU = child.StudsPerTileU,
- StudsPerTileV = child.StudsPerTileV
- }
- end
- return nil
- end
- local function splitDataIntoChunks(data)
- local chunks = {}
- local chunkIndex = 1
- local currentChunk = {}
- local currentSize = 0
- for i, part in ipairs(data) do
- local partData = HttpService:JSONEncode(part)
- local partSize = #partData
- if partSize > MAX_DATA_SIZE then
- warn(`Part {i} ({part.Name}) is too large ({partSize} bytes) - skipped!`)
- continue
- end
- if currentSize + partSize > MAX_DATA_SIZE then
- chunks[chunkIndex] = currentChunk
- chunkIndex += 1
- currentChunk = {}
- currentSize = 0
- end
- table.insert(currentChunk, part)
- currentSize += partSize
- end
- if #currentChunk > 0 then
- chunks[chunkIndex] = currentChunk
- end
- print(`Split data into {chunkIndex} chunks`)
- return chunks, chunkIndex
- end
- local function saveGlobalMap()
- -- Check if the game is running in a private or VIP server
- if game.PrivateServerId ~= "" then
- print("This is a private or VIP server. Skipping map saving.")
- return
- end
- -- Any other code you want to run when it's NOT a private/VIP server
- print("This is not a private/VIP server. Continuing with the script...")
- if isMapLoading then
- warn("-- Map save requested while loading. Queued.")
- table.insert(saveQueue, true)
- return false
- end
- print("-- Starting map save...")
- local buildParts = {}
- for _, obj in ipairs(workspace:GetDescendants()) do
- if obj:IsA("BasePart") and not obj:IsDescendantOf(Players) then
- local partData = {
- ClassName = obj.ClassName,
- Name = obj.Name,
- Position = vector3ToTable(obj.Position),
- Size = vector3ToTable(obj.Size),
- Color = color3ToTable(obj.Color),
- Orientation = vector3ToTable(obj.Orientation),
- Anchored = obj.Anchored,
- Transparency = obj.Transparency,
- Material = obj.Material.Name,
- CanCollide = obj.CanCollide,
- Reflectance = obj.Reflectance,
- Locked = obj.Locked,
- TopSurface = obj.TopSurface.Name,
- BottomSurface = obj.BottomSurface.Name,
- LeftSurface = obj.LeftSurface.Name,
- RightSurface = obj.RightSurface.Name,
- FrontSurface = obj.FrontSurface.Name,
- BackSurface = obj.BackSurface.Name,
- Shape = obj:IsA("Part") and obj.Shape.Name or nil,
- Children = {},
- }
- for _, child in ipairs(obj:GetChildren()) do
- local childData = serializeChildInstance(child)
- if childData then
- table.insert(partData.Children, childData)
- end
- end
- table.insert(buildParts, partData)
- end
- end
- local chunks, totalChunks = splitDataIntoChunks(buildParts)
- local mapMetadata = {
- totalChunks = totalChunks,
- lastSaveTime = os.time(),
- version = 2
- }
- -- Save metadata
- local metadataStore = DataStoreService:GetDataStore("GlobalMapStore_Meta")
- local success, err = pcall(function()
- metadataStore:SetAsync("MapMetadata", mapMetadata)
- end)
- if not success then
- warn(`Metadata save failed: {err}`)
- return false
- end
- -- Save chunks
- local chunksSaved = 0
- local storeIndex = 1
- while storeIndex <= MAX_DATASTORES and chunksSaved < totalChunks do
- local store = DataStoreService:GetDataStore("GlobalMapStore" .. storeIndex)
- local maxThisStore = math.min(MAX_CHUNKS_PER_STORE, totalChunks - chunksSaved)
- for i = 1, maxThisStore do
- local globalChunkIndex = chunksSaved + 1
- local chunkKey = "GlobalMap_Chunk" .. globalChunkIndex
- local success, err = pcall(function()
- store:SetAsync(chunkKey, chunks[globalChunkIndex])
- end)
- if success then
- print(`Saved chunk {globalChunkIndex} to store {storeIndex}`)
- chunksSaved += 1
- else
- warn(`Failed to save chunk {globalChunkIndex}: {err}`)
- end
- end
- storeIndex += 1
- end
- if chunksSaved == totalChunks then
- print(`Map saved successfully across {storeIndex} stores with {totalChunks} chunks`)
- return true
- else
- warn(`Failed to save all chunks. Saved {chunksSaved}/{totalChunks}`)
- return false
- end
- end
- local function createGuiObjects(parent, children)
- for _, childData in ipairs(children or {}) do
- local childInstance = Instance.new(childData.ClassName)
- childInstance.Name = childData.Name
- if childInstance:IsA("TextLabel") then
- childInstance.Text = childData.Text
- childInstance.TextColor3 = tableToColor3(childData.TextColor3)
- childInstance.BackgroundColor3 = tableToColor3(childData.BackgroundColor3)
- childInstance.TextSize = childData.TextSize
- childInstance.Font = Enum.Font[childData.Font]
- childInstance.Position = tableToUDim2(childData.Position)
- childInstance.Size = tableToUDim2(childData.Size)
- childInstance.BackgroundTransparency = childData.BackgroundTransparency
- childInstance.TextTransparency = childData.TextTransparency
- childInstance.TextXAlignment = Enum.TextXAlignment[childData.TextXAlignment]
- childInstance.TextYAlignment = Enum.TextYAlignment[childData.TextYAlignment]
- childInstance.TextWrapped = childData.TextWrapped
- childInstance.TextScaled = childData.TextScaled
- childInstance.BorderSizePixel = childData.BorderSizePixel
- childInstance.BorderColor3 = tableToColor3(childData.BorderColor3)
- childInstance.Visible = childData.Visible
- elseif childInstance:IsA("Frame") then
- childInstance.BackgroundColor3 = tableToColor3(childData.BackgroundColor3)
- childInstance.Position = tableToUDim2(childData.Position)
- childInstance.Size = tableToUDim2(childData.Size)
- childInstance.BackgroundTransparency = childData.BackgroundTransparency
- childInstance.BorderSizePixel = childData.BorderSizePixel
- childInstance.BorderColor3 = tableToColor3(childData.BorderColor3)
- childInstance.Visible = childData.Visible
- createGuiObjects(childInstance, childData.Children)
- elseif childInstance:IsA("ImageLabel") then
- childInstance.Image = childData.Image
- childInstance.ImageColor3 = tableToColor3(childData.ImageColor3)
- childInstance.BackgroundColor3 = tableToColor3(childData.BackgroundColor3)
- childInstance.Position = tableToUDim2(childData.Position)
- childInstance.Size = tableToUDim2(childData.Size)
- childInstance.BackgroundTransparency = childData.BackgroundTransparency
- childInstance.ImageTransparency = childData.ImageTransparency
- childInstance.BorderSizePixel = childData.BorderSizePixel
- childInstance.BorderColor3 = tableToColor3(childData.BorderColor3)
- childInstance.ScaleType = Enum.ScaleType[childData.ScaleType]
- childInstance.Visible = childData.Visible
- end
- childInstance.Parent = parent
- end
- end
- local function loadGlobalMap()
- print("-- Loading map...")
- isMapLoading = true
- mapFullyLoaded = false
- saveQueue = {}
- local metadataStore = DataStoreService:GetDataStore("GlobalMapStore_Meta")
- local success, mapMetadata = pcall(function()
- return metadataStore:GetAsync("MapMetadata")
- end)
- if not success or not mapMetadata then
- warn("-- No metadata found. Trying legacy load...")
- local legacyStore = DataStoreService:GetDataStore("GlobalMapStore")
- local success, data = pcall(function()
- return legacyStore:GetAsync("GlobalMap_All")
- end)
- if success and data then
- print("-- Legacy map loaded")
- createPartsFromData(data)
- isMapLoading = false
- mapFullyLoaded = true
- saveGlobalMap()
- return true
- else
- warn("-- No map data found. Creating new map...")
- isMapLoading = false
- mapFullyLoaded = true
- saveGlobalMap()
- return false
- end
- end
- print(`-- Loading {mapMetadata.totalChunks} chunks from metadata v{mapMetadata.version}`)
- local allParts = {}
- local chunksLoaded = 0
- local storeIndex = 1
- while storeIndex <= MAX_DATASTORES and chunksLoaded < mapMetadata.totalChunks do
- local store = DataStoreService:GetDataStore("GlobalMapStore" .. storeIndex)
- local maxThisStore = math.min(MAX_CHUNKS_PER_STORE, mapMetadata.totalChunks - chunksLoaded)
- for i = 1, maxThisStore do
- local globalChunkIndex = chunksLoaded + 1
- local chunkKey = "GlobalMap_Chunk" .. globalChunkIndex
- local success, chunkData = pcall(function()
- return store:GetAsync(chunkKey)
- end)
- if success and chunkData then
- print(`Loaded chunk {globalChunkIndex} from store {storeIndex}`)
- for _, part in ipairs(chunkData) do
- table.insert(allParts, part)
- end
- chunksLoaded += 1
- else
- warn(`Failed to load chunk {globalChunkIndex} from store {storeIndex}`)
- end
- end
- storeIndex += 1
- end
- if chunksLoaded == mapMetadata.totalChunks then
- print(`All {chunksLoaded} chunks loaded successfully`)
- createPartsFromData(allParts)
- task.delay(2, verifyPartAnchoring)
- isMapLoading = false
- mapFullyLoaded = true
- if #saveQueue > 0 then
- print(`Processing {#saveQueue} queued saves`)
- saveGlobalMap()
- saveQueue = {}
- end
- return true
- else
- warn(`Loaded {chunksLoaded}/{mapMetadata.totalChunks} chunks`)
- isMapLoading = false
- return false
- end
- end
- function createPartsFromData(partData)
- print(`-- Creating {#partData} parts...`)
- local createdParts = {}
- local failed = 0
- for i, part in ipairs(partData) do
- local success, err = pcall(function()
- local newPart = Instance.new(part.ClassName)
- newPart.Name = part.Name
- newPart:SetAttribute("ShouldBeAnchored", part.Anchored)
- newPart.Position = tableToVector3(part.Position)
- newPart.Size = tableToVector3(part.Size)
- newPart.Color = tableToColor3(part.Color)
- newPart.Orientation = tableToVector3(part.Orientation)
- newPart.Transparency = part.Transparency
- newPart.Material = Enum.Material[part.Material]
- newPart.CanCollide = part.CanCollide
- newPart.Reflectance = part.Reflectance
- newPart.Locked = part.Locked
- pcall(function()
- newPart.TopSurface = Enum.SurfaceType[part.TopSurface]
- newPart.BottomSurface = Enum.SurfaceType[part.BottomSurface]
- newPart.LeftSurface = Enum.SurfaceType[part.LeftSurface]
- newPart.RightSurface = Enum.SurfaceType[part.RightSurface]
- newPart.FrontSurface = Enum.SurfaceType[part.FrontSurface]
- newPart.BackSurface = Enum.SurfaceType[part.BackSurface]
- end)
- if part.Shape and newPart:IsA("Part") then
- pcall(function()
- newPart.Shape = Enum.PartType[part.Shape]
- end)
- end
- newPart.Anchored = part.Anchored
- newPart.Parent = workspace
- table.insert(createdParts, newPart)
- -- Handle non-GUI children
- local hasGui = false
- for _, childData in ipairs(part.Children or {}) do
- if childData.ClassName == "SurfaceGui" then
- hasGui = true
- else
- pcall(function()
- local child = Instance.new(childData.ClassName)
- child.Name = childData.Name
- if child:IsA("Decal") then
- child.Texture = childData.Texture
- child.Transparency = childData.Transparency
- child.Face = Enum.NormalId[childData.Face]
- elseif child:IsA("Fire") then
- child.Heat = childData.Heat
- child.Size = childData.Size
- child.Color = tableToColor3(childData.Color)
- child.SecondaryColor = tableToColor3(childData.SecondaryColor)
- child.Enabled = childData.Enabled
- elseif child:IsA("Smoke") then
- child.Size = childData.Size
- child.Opacity = childData.Opacity
- child.Color = tableToColor3(childData.Color)
- child.Enabled = childData.Enabled
- elseif child:IsA("PointLight") then
- child.Brightness = childData.Brightness
- child.Range = childData.Range
- child.Color = tableToColor3(childData.Color)
- child.Shadows = childData.Shadows
- child.Enabled = childData.Enabled
- elseif child:IsA("Texture") then
- child.Texture = childData.Texture
- child.Transparency = childData.Transparency
- child.Face = Enum.NormalId[childData.Face]
- child.StudsPerTileU = childData.StudsPerTileU
- child.StudsPerTileV = childData.StudsPerTileV
- end
- child.Parent = newPart
- end)
- end
- end
- -- Handle GUI children
- if hasGui then
- for _, childData in ipairs(part.Children or {}) do
- if childData.ClassName == "SurfaceGui" then
- pcall(function()
- local gui = Instance.new("SurfaceGui")
- gui.Name = childData.Name
- gui.Face = Enum.NormalId[childData.Face]
- gui.Enabled = childData.Enabled
- gui.SizingMode = Enum.SurfaceGuiSizingMode[childData.SizingMode]
- gui.PixelsPerStud = childData.PixelsPerStud
- gui.Parent = newPart
- createGuiObjects(gui, childData.Children)
- end)
- end
- end
- end
- if i % 50 == 0 then
- task.wait()
- end
- end)
- if not success then
- failed += 1
- warn(`Failed part {i}: {err}`)
- end
- end
- print(`Created {#partData - failed}/{#partData} parts`)
- task.spawn(function()
- task.wait(1)
- for _, part in ipairs(workspace:GetDescendants()) do
- if part:IsA("BasePart") and not part:IsDescendantOf(Players) then
- part.CastShadow = false
- if part.Anchored == false and part:GetAttribute("ShouldBeAnchored") == true then
- for _, createdPart in ipairs(createdParts) do
- if createdPart == part then
- part.Anchored = true
- break
- end
- end
- end
- end
- end
- end)
- end
- local function setupCommandSystem()
- local Commands = {}
- Commands.savemap = function(player)
- if player.UserId == game.CreatorId or player:GetRankInGroup(game.CreatorId) >= 255 then
- print(`Map save requested by {player.Name}`)
- local success = saveGlobalMap()
- pcall(function()
- player.PlayerGui:SetCore("ChatMakeSystemMessage", {
- Text = success and "Map saved!" or "Save failed",
- Color = success and Color3.new(0, 1, 0) or Color3.new(1, 0, 0),
- Font = Enum.Font.SourceSansBold
- })
- end)
- return true
- else
- pcall(function()
- player.PlayerGui:SetCore("ChatMakeSystemMessage", {
- Text = "No permission",
- Color = Color3.new(1, 0, 0),
- Font = Enum.Font.SourceSansBold
- })
- end)
- return false
- end
- end
- local function onPlayerChatted(player, message)
- local split = string.split(message, " ")
- local command = string.lower(split[1])
- if string.sub(command, 1, 1) == "/" then
- command = string.sub(command, 2)
- if Commands[command] then
- Commands[command](player, split)
- end
- end
- end
- local success, textChatService = pcall(function()
- return game:GetService("TextChatService")
- end)
- if success and textChatService then
- textChatService.MessageReceived:Connect(function(msg)
- local player = Players:FindFirstChild(msg.TextSource.Name)
- if player then
- onPlayerChatted(player, msg.Text)
- end
- end)
- else
- local chatEvents = ReplicatedStorage:FindFirstChild("DefaultChatSystemChatEvents")
- if chatEvents and chatEvents:FindFirstChild("OnMessageDoneFiltering") then
- chatEvents.OnMessageDoneFiltering.OnClientEvent:Connect(function(data)
- local player = Players:FindFirstChild(data.FromSpeaker)
- if player then
- onPlayerChatted(player, data.Message)
- end
- end)
- else
- Players.PlayerAdded:Connect(function(player)
- pcall(function()
- player.Chatted:Connect(function(msg)
- onPlayerChatted(player, msg)
- end)
- end)
- end)
- for _, player in ipairs(Players:GetPlayers()) do
- pcall(function()
- player.Chatted:Connect(function(msg)
- onPlayerChatted(player, msg)
- end)
- end)
- end
- end
- end
- end
- game:BindToClose(function()
- print("Saving on shutdown...")
- if not isMapLoading and mapFullyLoaded then
- saveGlobalMap()
- else
- warn("Skipping save: Map not fully loaded")
- end
- end)
- local function setupAutoSave()
- local AUTO_SAVE_INTERVAL = 900 -- 15 minutes
- while true do
- task.wait(AUTO_SAVE_INTERVAL)
- if not isMapLoading and mapFullyLoaded then
- print("Auto-saving map...")
- saveGlobalMap()
- else
- warn("Auto-save skipped: Map busy")
- table.insert(saveQueue, true)
- end
- end
- end
- local function initialize()
- print("Initializing map system...")
- task.spawn(function()
- local success = loadGlobalMap()
- print(success and "Map loaded!" or "Load failed")
- remoteload:FireAllClients()
- end)
- setupCommandSystem()
- task.spawn(setupAutoSave)
- print("Map system initialized!")
- end
- Players.PlayerAdded:Connect(function(player)
- player.Chatted:Connect(function(message)
- if message == "/savemap" then
- saveGlobalMap()
- end
- end)
- end)
- Players.PlayerAdded:Connect(function(plr)
- if isMapLoading == false then
- remoteload:FireClient(plr)
- end
- end)
- initialize()
Advertisement
Add Comment
Please, Sign In to add comment