I’m making a tycoon game where you can build and place custom objects onto your plot. I want to make Sava Data for the game, It saves the object’s positions and rotations and loads them the way I want to. Although, since this is a tycoon, there are multiple plots (4 to exact 100x100 studs each), and I want the items to load relative to the plot’s position so they spawn on the same spot for each plot while each plot is in a different position. If that makes any sense.
Heres my Data Store code so far,
local DataStoreService = game:GetService("DataStoreService")
local GameData = DataStoreService:GetDataStore("GameData0.4")
local function TableToVector3(table)
return Vector3.new(table.X, table.Y, table.Z)
end
local function Vector3ToTable(vector)
return {X = vector.X, Y = vector.Y, Z = vector.Z}
end
-- Convert CFrame to table
local function CFrameToTable(cframe)
local position = Vector3ToTable(cframe.Position)
local rotation = Vector3ToTable(cframe.Orientation)
return {Position = position, Rotation = rotation}
end
-- Convert table to CFrame
local function TableToCFrame(table)
local position = TableToVector3(table.Position)
local rotation = TableToVector3(table.Rotation)
return CFrame.new(position) * CFrame.fromEulerAnglesXYZ(rotation.X, rotation.Y, rotation.Z)
end
local dataTemplate = {
leaderstats = {
Cash = 200,
},
Inventory = {},
Plot = {},
Tools = {},
Workers = {
Lumberjack = 0,
Miner = 0,
Stocker = 0
},
Level = 1,
Xp = 0,
Tutorial = {
ChopATree = false,
PlaceAnItem = false
}
}
local function SaveData(player)
local inventoryData = {}
local plotData = {}
local plot = game.Workspace.Plots[player.Name]
local plotPart = plot.PlotPart
local structures = plot.Structures
for i, item in pairs(player.Inventory:GetChildren()) do
if item:IsA("IntValue") then
inventoryData[item.Name] = item.Value
end
end
for i, item:Model in pairs(structures:GetChildren()) do
local cframe:CFrame,size = item:GetBoundingBox()
local relativePosition = cframe.Position
local relativeOrientation = cframe.Rotation -- assuming the plot doesn't rotate
table.insert(plotData, {
Name = item.Name,
Position = Vector3ToTable(relativePosition),
Orientation = Vector3ToTable(relativeOrientation)
})
print("Saved " .. item.Name)
end
print(plotData)
local success, err = pcall(function()
GameData:SetAsync(player.UserId, {
leaderstats = {
Cash = player.leaderstats.Cash.Value,
},
Inventory = inventoryData,
Plot = plotData,
Tools = {},
Workers = {
Lumberjack = player.Workers.Lumberjack.Value,
Miner = player.Workers.Miner.Value,
Stocker = player.Workers.Stocker.Value
},
Level = player.Level.Value,
Xp = player.Xp.Value,
Tutorial = {
ChopATree = player.Tutorial.ChopATree.Value,
PlaceAnItem = player.Tutorial.PlaceAnItem.Value,
Completed = player.Tutorial.Completed.Value
}
})
end)
if not success then
warn('Could not save data! ' .. err)
else
print(player.Name .. "'s Data Saved!")
print(GameData:GetAsync(player.UserId))
end
end
game.Players.PlayerAdded:Connect(function(player)
wait(2)
local data = GameData:GetAsync(player.UserId)
local plot = game.Workspace.Plots[player.Name]
local plotPart = plot.PlotPart
local structures = plot.Structures
print(data)
if data then
--Load Data
player.leaderstats.Cash.Value = data.leaderstats.Cash
player.Level.Value = data.Level
player.Xp.Value = data.Xp
player.Tutorial.ChopATree.Value = data.Tutorial.ChopATree
player.Tutorial.PlaceAnItem.Value = data.Tutorial.PlaceAnItem
player.Workers.Lumberjack.Value = data.Workers.Lumberjack
player.Workers.Miner.Value = data.Workers.Miner
player.Workers.Stocker.Value = data.Workers.Stocker
player.Tutorial.Completed.Value = data.Tutorial.Completed
for _, itemData in pairs(data.Plot) do
local object = game.ReplicatedStorage.ObjectFolder:FindFirstChild(itemData.Name):Clone()
local relativePosition = TableToVector3(itemData.Position)
local boundingCframe, boundingSize = object:GetBoundingBox()
object:SetPrimaryPartCFrame(CFrame.new(boundingCframe, TableToVector3(itemData.Orientation)))
for _, model in pairs(object:GetChildren()) do
if model:IsA("Model") then
model.Parent = workspace.Plots[player.Name].Structures
object:Destroy()
end
end
print('Loaded ' .. itemData.Name)
end
for itemName, itemQuantity in pairs(data.Inventory) do
local item = Instance.new("IntValue")
item.Name = itemName
item.Value = itemQuantity
item.Parent = player.Inventory
for _, v in pairs(game.ReplicatedStorage.Items:GetChildren()) do
if itemName == v.Name then
game.ReplicatedStorage.RemoteEvents.UpdateItemUI:FireClient(player, v)
end
end
end
print(player.Name .. "'s Data Loaded!")
else
--Save Blank Save
print(player.Name .. "'s Blank Save Saved!")
GameData:SetAsync(player.UserId, dataTemplate)
end
end)
game.Players.PlayerRemoving:Connect(function(player)
SaveData(player)
end)
game:BindToClose(function()
for i, v in pairs(game.Players:GetPlayers()) do
SaveData(v)
end
end)