Data
Patch
Read and write deep paths in nested tables, fill templates, and check that data can be saved to a DataStore.
Getting it
local Patch = Engine:GetPackage("Patch")Overview
Patch works with paths into nested tables. A path is either a dot string such as "Inventory.Weapons.1" (number segments become number keys) or an array of keys such as { "Inventory", "Weapons", 1 }. Unlike TableKit, Patch writes in place, which is what you want when you own the data, such as a player's profile.
local Patch = Engine:GetPackage("Patch")
local data = { Inventory = { Weapons = { "Sword" } } }
local keys = Patch.Parse("Inventory.Weapons")
Patch.Insert(data, keys, nil, "Bow") -- { "Sword", "Bow" }
Patch.Set(data, { "Stats" }, {}) -- every table on a path must exist
Patch.Set(data, Patch.Parse("Stats.Kills"), 3) -- the last key may be new
print(Patch.Get(data, Patch.Parse("Stats.Kills"))) --> 3
local ok, reason, where = Patch.Validate(data)Paths
Parse
Patch.Parse(path: Path): KeysTurns a path into an array of keys. Errors on an empty path.
Format
Patch.Format(keys: Keys): stringTurns keys back into a dot string, for messages and logging.
IsPrefix
Patch.IsPrefix(prefix: Keys, keys: Keys): booleanWhether keys starts with prefix, for example to check whether a change at keys falls inside a watched branch.
Reading and writing
Get
Patch.Get(root: table, keys: Keys, count: number?): anyThe value at the path, or nil if any step is missing. With count, follows only the first count keys.
Set
Patch.Set(root: table, keys: Keys, value: any): anySets the value at the path and returns the previous value. Every table on the path must already exist; only the last key may be new. When a step is missing or is not a table, Set errors with that part of the path (Engine: Patch - Stats does not exist, Engine: Patch - Coins is not a table) and changes nothing.
Insert
Patch.Insert(root: table, keys: Keys, index: number?, value: any): numberInserts into the array at the path, at index or at the end. Returns the index used. Errors if the path is not an array.
Remove
Patch.Remove(root: table, keys: Keys, index: number): anyRemoves and returns the item at index of the array at the path.
Fill
Patch.Fill(target: table, template: table)Adds every string key from template that target does not have, deep-copying tables, and recurses into tables both have. Existing values are never overwritten.
Validation
Validate
Patch.Validate(value: any): (boolean, string?, string?)Checks that a value can be stored in a DataStore. Returns true, or false with the reason and the path of the first problem ("<root>" for the value itself).
It rejects:
- functions, Instances, Vector3s and every other non-plain type (strings, booleans, numbers, buffers and tables are allowed);
NaNand infinite numbers;- keys that are not strings or positive whole numbers;
- tables that mix array and dictionary keys;
- arrays with gaps;
- nesting deeper than 32 levels.
local ok, reason, where = Patch.Validate({ Position = Vector3.zero })
-- false, "Vector3 values cannot be stored", "Position"Types
export type Path = string | { any }
export type Keys = { any }