PlaceFile
A whole place or Model as Roblox instances you can walk, change and save back, in either format.
Find an instance by a dotted or slash path with FindInstance, set its properties and attributes, then SaveAsync. Kind comes from the file name's ending and Format from its first bytes. A place's tree is DataModel; a Model's roots are in Instances. A few derived properties can't be read inside a file: use RobloxFileService:GetWorldCFrame for an Attachment and part.CFrame.Position for a part's position. GetPivot works.
Call RobloxFileService:OpenAsync, FromBuffer or New.
Example
--!strict
-- A place built in memory: add a folder, find it by path, copy the file, write it as XML and read it back.
local RobloxFileService = require("@shotsystem/RobloxFileService")
-- a Model's bytes in XML: a Shop folder holding an Apple
local kit = assert(RobloxFileService:FromBuffer([[<roblox version="4">
<Item class="Folder" referent="A"><Properties><string name="Name">Shop</string></Properties>
<Item class="StringValue" referent="B"><Properties><string name="Name">Apple</string><string name="Value">red</string></Properties></Item>
</Item></roblox>]], "Model"))
local place = RobloxFileService:New("Place")
print("new:", place.Kind, place.Format, place.Path, place.ReadOnly, #place.Instances)
kit.Instances[1]:Clone().Parent = assert(place.DataModel):GetService("ReplicatedStorage")
local function apple(file : PlaceFile) : any -- the Apple, by a dotted path from game
return assert(file:FindInstance("ReplicatedStorage.Shop.Apple"))
end
print("dotted path:", apple(place).Value, "slash path:", assert(place:FindInstance("ReplicatedStorage/Shop/Apple")).Name)
print("not there:", place:FindInstance("ReplicatedStorage.Shop.Pear"))
-- a Clone is a file of its own: changing it leaves the original alone
local copy = place:Clone()
apple(copy).Value = "green"
print("copy:", apple(copy).Value, "original:", apple(place).Value)
local xml = place:ToBuffer("Xml")
local back = assert(RobloxFileService:FromBuffer(xml, "Place"))
print("XML read back:", buffer.readstring(xml, 0, 7), back.Format, apple(back).Value)
for _, file in { kit, place, copy, back } do
file:Close()
end
local ok, why = pcall(function() return place.DataModel end)
print("after Close:", ok, (string.gsub(tostring(why), "^.-:%d+: ", "")))new: Place Binary nil false 0 dotted path: red slash path: Apple not there: nil copy: green original: red XML read back: <roblox Xml red after Close: false PlaceFile "Place" was destroyed
Properties
| Name | Type | Default | Description |
|---|---|---|---|
| Path | string? | read-only | The file it was opened from or last saved to; nil for one made by New, FromBuffer or Clone until it is saved. |
| Kind | "Place" | "Model" | "Place" read-only | Place or Model, taken from the file name's ending only; New and FromBuffer take it from their argument. |
| Format | "Binary" | "Xml" | "Binary" read-only | Binary or Xml, read from the file's first bytes rather than its name, and changed by each SaveAsync to the format written. |
| DataModel | RobloxInstance? | read-only | The place's whole instance tree when Kind is Place, else nil; Close destroys it. |
| Instances | { RobloxInstance } | read-only | A Model's top-level instances, a live list you can add to with table.insert; for a place it is empty, use DataModel. |
| GameName | string? | read-only | |
| ReadOnly | boolean | false read-only | True when opened with { ReadOnly = true }: SaveAsync then returns false and why, and the property itself can't be set. |
Methods
| Name | Arguments | Returns | Description |
|---|---|---|---|
| FindInstance | (path: string) | RobloxInstance? | An instance by a dotted path (ReplicatedStorage.Shared.Config) or a slash path, else nil; a Model's paths start at a top-level instance. |
| ToBuffer | (format: ("Binary" | "Xml")?) | buffer | The file's bytes in the format given, else in its own Format; any format but Binary or Xml is an error. |
| SaveAsync yields | (path: string?, format: ("Binary" | "Xml")?) | (boolean, string?) | Waits until the file is written to path, else its own Path, through a temporary file; the format given, else the path's ending's, else Format. |
| Close | () | () | Destroys the file and its DataModel; a Model's instances go only while still top level, so ones you moved elsewhere survive. |
| Clone | () | PlaceFile | A new open PlaceFile holding a copy of the tree, as saving and reopening would give, cross references kept; its Path is nil. |
From ShotInstance 33
ClassNameNameParentAncestryChangedAttributeChangedChangedChildAddedChildRemovedDestroyingAddTagClearAllChildrenCloneDestroyFindFirstAncestorFindFirstAncestorOfClassFindFirstAncestorWhichIsAFindFirstChildFindFirstChildOfClassFindFirstChildWhichIsAGetAttributeGetAttributeChangedSignalGetAttributesGetChildrenGetDescendantsGetFullNameGetPropertyChangedSignalGetTagsHasTagIsAIsAncestorOfIsDescendantOfRemoveTagSetAttribute
