i have made a saving system for my game which saves all items player has placed down on their base. but sometimes, it reverts the rotation of some items.
here is an example:
i have built a structure that looks like this:
when i rejoin, it looks like this:

and when i rejoin again, it looks like this, again:
Here is the script, also dont mind PlotsDS, its a different datastore i use to save different things
local PlotsDS = game:GetService("DataStoreService"):GetDataStore("Plots2")
local StructureDS = game:GetService("DataStoreService"):GetDataStore("Structures2")
local itemsmodule = require(game.ServerScriptService.ItemsModule)
game.Players.PlayerAdded:Connect(function(plr)
local plots = PlotsDS:GetAsync(plr.UserId)
local structures = StructureDS:GetAsync(plr.UserId)
local foundplot = false
local spawnpart
for i,v in pairs(workspace.Plots:GetChildren()) do
if v.Owner.Value == "No Owner" then
v.Owner.Value = plr.Name
spawnpart = v.SpawnPos
foundplot = true
for i,b in pairs(game.ServerStorage.BaseExpansions:FindFirstChild(v.Name):GetChildren()) do
if table.find(plots,b.Name) then
b.Parent = v.BaseParts
for i,c in pairs(b:GetChildren()) do
if c.Name == "BuildArea" then
c.Parent = v.BuildAreas
end
end
end
end
for i,g in pairs(structures) do
local structure = itemsmodule.ItemFromTable(plr,g[1])
structure.Parent = v.Structures
local scframe = CFrame.new(v.Middle.Position + Vector3.new(-g[2][1],g[2][2],-g[2][3])) * CFrame.Angles(math.rad(g[3][1]),math.rad(g[3][2]),math.rad(g[3][3]))
structure.Parts:SetPrimaryPartCFrame(scframe)
end
break
end
end
if foundplot == false then
plr:Kick("Sorry, The Server Is Full. Please Rejoin.")
end
plr.CharacterAdded:Connect(function(char)
char:SetPrimaryPartCFrame(spawnpart.CFrame)
end)
end)
game.Players.PlayerRemoving:Connect(function(plr)
local plots = {}
local structuretable = {}
local foundbase = false
for i,v in pairs(game.Workspace.Plots:GetChildren()) do
if v.Owner.Value == plr.Name then
v.Owner.Value = "No Owner"
for i,g in pairs(v.Structures:GetChildren()) do
local infotable = {}
local iteminfotable = itemsmodule.ItemToTable(g)
table.insert(infotable,iteminfotable)
local posX = -(g.Parts.PrimaryPart.Position.X - v.Middle.Position.X)
local posY = g.Parts.PrimaryPart.Position.Y - v.Middle.Position.Y
local posZ = -(g.Parts.PrimaryPart.Position.Z - v.Middle.Position.Z)
local vector3V2 = g.Parts.PrimaryPart.Orientation
table.insert(infotable,{posX,posY,posZ})
table.insert(infotable,{vector3V2.X,vector3V2.Y,vector3V2.Z})
table.insert(structuretable,infotable)
g:Destroy()
end
v.Structures:ClearAllChildren()
for i,b in pairs(v.BaseParts:GetChildren()) do
if b.Name ~= "BasePart1" then
table.insert(plots,b.Name)
b.Parent = game.ServerStorage.BaseExpansions:FindFirstChild(v.Name)
for i,c in pairs(v.BuildAreas:GetChildren()) do
if c.BaseNumber.Value == b.BaseNumber.Value then
c.Parent = b
end
end
end
end
foundbase = true
break
end
end
if foundbase == true then
local s,e = pcall(function()
PlotsDS:SetAsync(plr.UserId,plots)
end)
if s then
print("zapisano dzialki")
else
warn(e)
print("nie zapisano dzialek")
end
local s2,e2 = pcall(function()
StructureDS:SetAsync(plr.UserId,structuretable)
end)
if s2 then
print("zapisano struktury")
else
warn(e2)
print("nie zapisano struktur")
end
end
end)
in case you cant find the lines that save and load orientation, here they are:
saving:
local vector3V2 = g.Parts.PrimaryPart.Orientation
table.insert(infotable,{vector3V2.X,vector3V2.Y,vector3V2.Z})
loading:
local structures = StructureDS:GetAsync(plr.UserId)
local structure = itemsmodule.ItemFromTable(plr,g[1]) -- g[1] is a table with item info, which can be used to load the item from a table
structure.Parent = v.Structures
local scframe = CFrame.new(v.Middle.Position + Vector3.new(-g[2][1],g[2][2],-g[2][3])) * CFrame.Angles(math.rad(g[3][1]),math.rad(g[3][2]),math.rad(g[3][3])) -- g[3] is the orientation
structure.Parts:SetPrimaryPartCFrame(scframe)

