What is the main part to save parts in the game from the client

What do you want to achieve?
A Save of parts, not only in the server, but in the game as such,

What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I searched about this but I only see that they save the parts, and it appears every time the player who created it enters

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!
something similar to this–
https://www.roblox.com/games/8642430697/unnamed

1 Like

Hi, I have taken up your question and solved the main part of it. This script will allow you to save all the parts within the selected domain be saved to a table. This includes their name, class, properties, and children. The format of the table looks like:

local instances = {
	["House Model"] = {
		class = "Model";
		properties = {
			Archivable = true;
			ClassName = "Model";
			Name = "House Model";
			Parent = workspace;
			["Origin Position"] = Vector3.new(0, 0, 0);
			["Origin Orientation"] = Vector3.new(0, 0, 0);
			PrimaryPart = nil;
			["World Pivot Position"] = Vector3.new(0, 0, 0);
			["World Pivot Orientation"] = Vector3.new(0, 0, 0);
		};
		children = {
			-- more instances like house model, with their children too, and so on
		}
	}
}

The code I wrote to make this happen is:
Sorry it’s so long. Roblox doesn’t have a nice and simple function for getting properties.

local instanceTree = searchChildren(workspace)

-- A table of all the roblox classes and their properties
Derived = {
	Instance = { "Name", "Parent", "Archivable", "ClassName", "RobloxLocked", "DataCost", Derived = {
		Accoutrement = { "AttachmentForward", "AttachmentRight", "AttachmentPoint", "AttachmentPos", "AttachmentUp", "BackendAccoutrementState", Derived = {
			Hat = { Derived = {} }
		}},
		Animation = { "AnimationId", Derived = { } },
		AnimationTrack = { Derived = { } },
		Backpack = { Derived = { } },
		BaseScript = { "Disabled", "LinkedSource", Derived = {
			CoreScript = { Derived = { } },
			Script = { "Source", "Disabled", Derived = { 
				LocalScript = { Derived = { } }
			}}
		}},
		BodyAngularVelocity = { "angularvelocity", "P", "maxTorque", Derived = { } },
		BodyColors = { "BodyColor", Derived = { } },
		BodyForce = { "force", Derived = { } },
		BodyGyro = { "D", "P", "cframe", "maxTorque", Derived = { } },
		BodyPosition = { "D", "P", "maxForce", "position", Derived = { } },
		BodyThrust = { "force", "location", Derived = { } },
		BodyVelocity = { "P", "maxForce", "Velocity", Derived = { } },
		BoolValue = { "Value", Derived = { } },
		BrickColorValue = { "Value", Derived = { } },
		Camera = { "CameraSubject", "CameraType", "CoordinateFrame", "Focus", Derived = { } },
		CFrameValue = { "Value", Derived = { } },
		ClickDetector = { "MaxActivationDistance", Derived = { } },
		Clothing = { Derived = {
			Pants = { "PantsTemplate", Derived = { } },
			Shirt = { "ShirtTemplate", Derived = { } }
		}},
		Color3Value = { "Value", Derived = { } },
		Configuration = { Derived = { } },
		Dialog = { "ConversationDistance", "InUse", "InitailPrompt", "Purpose", "Tone", Derived = { } },
		DialogChoice = { "ResponseDialog", "UserDialog", Derived = { } },
		Explosion = { "BlastPressure", "BlastRadius", "Position", Derived = { } },
		Feature = { "FaceId", "InOut", "LeftRight", "TopBottom", Derived = {
			Hole = { Derived = { } },
			MotorFeature = { Derived = { } }
		}},
		Fire = { "Color", "Enabled", "Heat", "SecondaryColor", "Size", Derived = { } },
		ForceField = { Derived = { } },
		GuiBase = { "AbsolutePosition", "AbsoluteSize", Derived = {
			ScreenGui = { Derived = { } },
			GuiObject = { "Active", "BackgroundColor3", "BackgroundTransparency", "BorderColor3", "BorderSizePixel", "Position", "Size", "SizeConstraint", "Visible", "ZIndex", Derived = {
				Frame = { Derived = { } },
				GuiButton = { "AutoButtonColor", "Selected", "Style", Derived = {
					ImageButton = { "Image", Derived = { } },
					TextButton = { "Text", "TextBounds", "TextWrap", "TextColor3", "TextTransparency, TextXAlignment", "TextYAlignment", "FontSize", "Font", Derived = { } }
				}},
				GuiLabel = { Derived = {
					ImageLabel = { "Image", Derived = { } },
					TextLabel = { "Text", "TextBounds", "TextWrap", "TextColor3", "TextTransparency, TextXAlignment", "TextYAlignment", "FontSize", "Font", Derived = { } }
				}},
				TextBox = { "Text", "TextBounds", "TextWrap", "TextColor3", "TextTransparency, TextXAlignment", "TextYAlignment", "FontSize", "Font", Derived = { } }
			}},
			BillboardGui = { "Adornee", "Enabled", "ExtentsOffset", "SizeOffset", "StudsOffset", Derived = { } },
		}},
		GuiBase3d = { "Color", "Transparency", "Visible", Derived = {
			PartAdornment = { "Adornee", Derived = {
				SurfaceSelection = { "TargetSurface", Derived = { } },
			}},
			PVAdornment = { "Adornee", Derived = {
				SelectionBox = { Derived = { } }
			}},
			SelectionLasso = { "Humanoid", Derived = {
				SelectionPartLasso = { "Part", Derived = { } },
				SelectionPointLasso = { "Point", Derived = { } },
			}}
		}},
		Humanoid = { "Health", "Jump", "MaxHealth", "PlatformStand", "RightLeg", "Sit", "TargetPoint", "Torso", "WalkDirection", "WalkSpeed", "WalkToPart", "WalkToPoint", Derived = { } },
		IntValue = { "Value", Derived = { } },
		JointInstance = { "C0", "C1", "Part0", "Part1", Derived = {
			DynamicRotate = { "BaseAngle", Derived = {
				RotateP = { Derived = { } },
				RotateV = { Derived = { } }
			}},
			Glue = { "F0", "F1", "F2", "F3", Derived = { } },
			Motor = { "CurrentAngle", "DesiredAngle", "MaxVelocity", Derived = { } },
			Rotate = { Derived = { } },
			Snap = { Derived = { } },
			VelocityMotor = { "CurrentAngle", "DesiredAngle", "Hole", "MaxVelocity", Derived = { } },
			Weld = { Derived = { } }
		}},
		KeyFrame = { "Time", Derived = { } },
		Message = { "Text", Derived = {
			Hint = { Derived = { } },
		}},
		Mouse = { "Hit", "Icon", "Origin", "Target", "TargetFilter", "TargetSurface", "UnitRay", "ViewSizeX", "ViewSizeY", "X", "Y", Derived = { } },
		NetworkReplicator = { "Port", Derived = { } },
		NumberValue = { "Value", Derived = { } },
		ObjectValue = { "Value", Derived = { } },
		Player = { "AccountAge", "Character", "CharacterAppearance", "DataReady", "Neutral", "MembershipType", "TeamColor", "userId",  Derived = { } },
		Pose = { "CFrame", "MaskWeight", "Weight", Derived = { } },
		PVInstance = { Derived = {
			BasePart = { "Anchored", "BrickColor", "CFrame", "CanCollide", "Elasticity", "Friction", "Locked", "Material", "Position", "Reflectance", "RotVelocity", "Size", "Transparency", "Velocity", "TopParamA", "BottomParamA", "LeftParamA", "RightParamA", "FrontParamA", "BackParamA", "TopParamB", "BottomParamB", "LeftParamB", "RightParamB", "FrontParamB", "BackParamB", "TopSurface", "BottomSurface", "LeftSurface", "RightSurface", "FrontSurface", "BackSurface", "TopSurfaceInput", "BottomSurfaceInput", "LeftSurfaceInput", "RightSurfaceInput", "FrontSurfaceInput", "BackSurfaceInput", Derived = {
				CornerWedgePart = { Derived = { } },
				FormFactorPart = { "FormFactor", Derived = {
					FlagStand = { "TeamColor", Derived = { } },
					Part = { "Shape", Derived = {
						Seat = { Derived = { } },
						SpawnLocation = { "AllowTeamChangeOnTouch", "Duration", "Neutral", "TeamColor", Derived = { } }
					}},
					WedgePart = { Derived = { } },
				}},
				ParallelRampPart = { Derived = { } },
				PrismPart = { "Sides", Derived = { } },
				PyramidPart = { "Sides", Derived = { } },
				RightAngleRampPart = { Derived = { } },
				SkateboardPlatform = { "Controller", "ControllingHumanoid", "Steer", "StickyWheels", "Throttle", Derived = { } },
				TrussPart = { "Style", Derived = { } },
				VehicleSeat = { "AreHingesDetected", "HeadsUpDisplay", "MaxSpeed", "Steer", "Throttle", "Torque", "TurnSpeed", Derived = { } }
			}},
			Model = { "PrimaryPart", Derived = { } }
		}},
		RayValue = { "Value", Derived = { } },
		RocketPropulsion = { "TurnP", "TurnD", "ThrustP", "ThrustD", "TargetRadius", "TargetOffset", "Target", "MaxTorque", "MaxThrust", "MaxSpeed", "CartoonFactor", Derived = { } },
		ScriptContext = { "GarbageCollectionFrequency", "GarbageCollectionLimit", "ScriptsDisabled", Derived = { } },
		ShirtGraphic = { "Graphic", Derived = { } },
		Skin = { "SkinColor", Derived = { } },
		Sky = { "CelestialBodiesShown", "SkyboxBk", "SkyboxDn", "SkyboxFt", "SkyboxRt", "SkyboxUp", "SkyboxCount", Derived = { } },
		Smoke = { "Color", "Enabled", "Opacity", "RiseVelocity", "Size", Derived = { } },
		Sound = { "IsPaused", "IsPlaying", "Looped", "Pitch", "PlayOnRemove", "SoundId", "Volume", Derived = { } },
		Sparkles = { "Enabled", "SparkleColor", Derived = { } },
		StarterGear = { Derived = { } },
		StatsItem = { Derived = {
			ProfilingItem = { Derived = { } },
		},
		StringValue = { "Value", Derived = { } },
		Team = { "AutoAssignable", "AutoColorCharacters", "Score", "TeamColor", Derived = { } },
		Teams = { Derived = { } },
		TouchTransmitter = { "Target", Derived = { } },
		Vector3Value = { "Value", Derived = { } }
		}}}}

function AddToTable(a, b)
	local r = { }
	for i,v in next, a do
		if type(v) == "string" then
			r[#r+1] = v
		end
	end
	for i,v in next, b do
		if type(v) == "string" then
			r[#r+1] = v
		end
	end
	return r
end

function Properties(obj, fenv)
	fenv = fenv or getfenv()
	for i,v in next, fenv.Derived do
		if obj:IsA(i) then
			return AddToTable(v, Properties(obj, v) or { })
		end
	end
end

function GetProperties(obj)
	local tab = Properties(obj)
	for i,v in next, tab do
		if type(v) == "table" then
			table.remove(tab, i)
		end
	end
	return tab
end

-- Our main function
function searchChildren(parent, path)
	local children = {}
	for _, instance in next, parent:GetChildren() do
		local path = path or {game}
		table.insert(path, parent.Name)
		
		local obj = {
			class = instance.ClassName;
			properties = (function()
				local tab = {}
				for _, property in next, GetProperties(instance) do
					pcall(function()
						tab[property] = instance[property]
					end)
				end
				return tab
			end)();
			children = searchChildren(instance, path)
		}
		
		children[instance.Name] = obj
	end
	return children
end

For you to implement this into saving a game, you may want to implement datastoreservice with this.

1 Like

Most of the properties of a “Model” instance are unscriptable.

The point of what I wrote is to save the data in the workspace, not to set it

By unscriptable that means you can’t index those properties from within scripts.

Ah okay, well I’m not sure why it didn’t throw any errors for me

image

print(workspace.Baseplate["Origin Position"])

Saving parts (so when you leave and rejoin, they are still there) can be a challenging task for a beginner.

To do this, you must serialize (and possibly compress) the data of the part in question (like properties, attributes, and any custom data) and then you must store it in a Datastore.

Then, when the player connects to the game, you must read from the Datastore, convert the serialized strings/substrings back into the parts with the right data added to them.

Like I said, this is a bit advanced for a beginner, but you can read a good how-to guide on Datastores here.

1 Like