Saving what the player has built and loading it in a different location

I’m currently working on my building system and players can place down buildings anywhere (different positions or orientations) on the map and it allows them to place a bunch of different things inside of the buildings. What was built inside the buildings can be saved and loaded in any other building of that type which might be at a different location or orientation. How would I structure my save data for this purpose and load what they built back into the correct orientation and position based off of where the building is?

From what I’ve seen, it’s best grouping everything they did together and then pasting it in the map that way. It might be in the same position except it’d be on top of everything else. Just move it down and then ungroup it.

If it spawns randomly, just move the grouped work to the correct position.

Moving it to the “correct position” is part of what I’m trying to understand. How should I go about getting this position based off of the location and orientation of the building? Also, what would be a good way of structuring this within the player’s data (while staying short)?

Actually, group together what the other player has made and paste the group in your own studio and then, copy the id of the position in properties of the group in the other place. Place the position id into the group you pasted in. It shouldn’t be an issue if both places had the exact same map.

I hope it helps.

2 Likes

I think that I haven’t really explained the mechanic of the buildings that well. They can be placed down anywhere in the map and it 99% of the time will not be in the same position or orientation. I would need to get the position of the parts relative to the building meaning not in world-space and thus an approach like this wouldn’t work.

2 Likes

Ah, my apologies. Scripting isn’t my thing, building is.

I hope you fix this problem soon! <3

3 Likes

Am I right in saying that you want players to save a base, and have their furniture transfer to a base of the same size, but in a different position and rotated? Like this?
image

image

2 Likes

Yes, exactly. The only changing aspects would be the built building’s position and orientation.

2 Likes

I think this link is exactly what you need: Relative Offset

When you want to store the offset for saving, you’ll have to do:
local offset = buildingBase1:toObjectSpace(furniturePart.CFrame)

Then when you want to load the data onto a new base:
furniturePart.CFrame = buildingBase2.CFrame * offset

3 Likes

Would this require having an attachment somewhere in the base to offset all of the furniture from?

1 Like

If all what of the player has built is grouped in a model, you can create an invisible block that covers the entire model and is oriented how the entire model is. Then you can get all of the blocks’ CFrames relative to the invisible block’s CFrame:

local BoxCFrame, BoxSize = model:GetBoundingBox()
local saveTable = {Size = {BoxSize.X, BoxSize.Y, BoxSize.Z}}

-- CFrames can't be saved in the datastore, hence why we need to serialise it
function serialize(cf)
    return {cf:GetComponents()}
end

for _, part in ipairs(model:GetDescendants()) do
    if part:IsA("Part") then
        saveTable[#saveTable + 1] = {["SavedCFrame"] = serialise(part.CFrame:inverse() * BoxCFrame)}
    end
end

When it comes to loading, you’d create the base part with the size and apply offsets to it. The base can be at any chosen position:

local base = Instance.new("Part")
base.Size = Vector3.new( unpack saveTable.Size )

function deserialise(tbl)
    return CFrame.new( unpack tbl )
end

for _, part in ipairs(saveTable) do
    local newpart = -- new part
    newpart.CFrame = base.CFrame * deserialise(part.CFrame)
end

base:Destroy() -- because we don't need it anymore

EDIT: I meant to do BoxCFrame:inverse() * part.CFrame for the serialisation part as mentioned below

6 Likes

What’s the difference between using part.CFrame:inverse() * BoxCFrame and CFrame:toObjectSpace() here? (I’m aware the wiki says they’re the same, so I’ll assume it doesn’t matter)

Wouldn’t this setup work without the use of a bounding box? Ideally, you could just have a randomly placed attachment that all of the items get placed relative to.

1 Like

BoxCFrame:ToObjectSpace(part.CFrame) is the same as BoxCFrame:inverse() * part.CFrame (I meant to do BoxCFrame:inverse() * part.CFrame)

It can work without a bounding box, but you can keep it if you want to not make the building go out-of-bounds at sometimes. A randomly placed attachment could work

1 Like

Why would the usage of a bounding box affect the placement’s ability to go out of the bounds? If you had an attachment and one of your 3 items was outside, it would still load in the same position relative to the attachment, right?

1 Like

Yes, it will, but if the attachment is randomly positioned within the boundaries, for argument’s sake, it’s 20 studs above the bottom boundary and the whole building takes up 60 studs in that direction, some of the building may be out of bounds. I don’t really know your system works but it’s something to consider

1 Like

I’ll keep that in mind when working on the system. Thanks for the help!

1 Like