xiao.config New
Read and change every client setting by a dotted key such as misc.hit_sound.volume, and load, save and list the configs of the Configs tab.
At a glance
The keys are the paths of the JSON a config file holds: {"misc":{"hit_sound":{"volume":45}}} is the key misc.hit_sound.volume. The list is never written by hand, it is read from the same serializer as the config files, so a new setting in the menu is a new key here.
A set acts exactly like a change in the menu: the feature uses the new value at once, the menu shows it, and the autosave writes it to the active config. Only the key you set changes.
Every function raises an error on failure (unknown key, wrong type, missing file), like xiao.fs. Wrap a call in pcall when a failure is expected. Before the menu is ready, every function raises settings are not ready: the menu is not initialized yet.
Not inside a packet hook or a cmd hook
Every xiao.config function raises xiao.config is not available inside a packet hook or a cmd hook when called from a packet hook or a cmd hook: they run outside the render thread and the settings belong to the render thread. Read what you need from think into an upvalue. See Execution contexts.
Types
- Colors come back as the same table as
xiao.paint.color.rgba: fieldsr,g,b,afrom 0 to 255.settakes{r = 255, g = 0, b = 0, a = 128}(adefaults to 255),{255, 0, 0},{255, 0, 0, 128}or axiao.paint.colorvalue. Channels are rounded to the nearest integer, a channel outside 0 to 255 is an error. The ESP layout keys store colors from 0 to 1: the conversion is done for you. - Multi is a selection of ids:
{["minecraft:creeper"] = true, ["minecraft:zombie"] = true}.settakes the same table (keys withfalseare ignored) or an array{"minecraft:creeper", "minecraft:zombie"}, and replaces the whole selection. Duplicates are merged. Ids are 1 to 128 bytes. - Numbers are clamped to the bounds of the setting, as the menu slider does:
setreturns the value really stored, so compare it when the bounds matter. Anintkey refuses2.5and integers past 2^53, afloatkey refuses NaN and infinity. - Strings that are a choice (
misc.hit_sound.sound,misc.fast_mine.method,*.bind.mode) refuse a value outside the list: the error saysrejected the valueand the setting keeps its previous value.
Keys that are not listed
HUD positions (hud.watermark.x, hud.watermark.y...) are listed: they are plain numbers. -1 means automatic placement, a position needs x and y both at 0 or more. A set of x sends the current y with it, and the other way round.
Settings
xiao.config.get(key: string): value
xiao.config.get(key: string): value
Returns the value of a setting.
Returns: a boolean, a number, a string, a color table or a multi table, by the
Errors: unknown config key 'x'.
local volume = xiao.config.get("misc.hit_sound.volume")
local accent = xiao.config.get("theme.accent")
print(volume, accent.r, accent.g, accent.b, accent.a)
xiao.config.set(key: string, value: any): value
xiao.config.set(key: string, value: any): value
Changes a setting as if you changed it in the menu, and returns the value now stored (after clamping).
Returns: the stored value, same shape as get. A value equal to the stored one changes nothing.
Errors:
xiao.config.set("misc.hit_sound.enabled", true)
xiao.config.set("misc.hit_sound.sound", "pop_can")
print(xiao.config.set("misc.hit_sound.volume", 150))
xiao.config.set("visual.chams.color", {r = 0, g = 192, b = 255})
xiao.config.set("visual.entities.targets.ids", {"minecraft:creeper", "minecraft:zombie"})
print shows 100: the volume slider goes from 0 to 100.
xiao.config.type(key: string): string | nil
xiao.config.type(key: string): string | nil
Returns the type of a key.
Returns: "bool", "int", "float", "color", "multi" or "string", or nil when the key does not exist.
Errors: none for an unknown key; only the hook and not ready errors.
if xiao.config.type("misc.reach.range") == "float" then
xiao.config.set("misc.reach.range", 4.5)
end
Configs
The configs are the files of the Configs tab, <name>.json in the config folder. A name is 1 to 31 letters, digits, spaces and - _ . ( ), given without the .json extension. Names are matched without case: save("pvp") overwrites PvP.json. The library holds 64 configs at most.
xiao.config.load(name: string): string
xiao.config.load(name: string): string
Applies a saved config, exactly like Load in the Configs tab: every setting of the file is applied and the config becomes the active one (the autosave target).
Returns: the name of the config as stored on disk.
Errors:
local ok, message = pcall(xiao.config.load, "pvp")
if not ok then print(message) end
xiao.config.save(name: string): string
xiao.config.save(name: string): string
Saves the current settings as a config, like Save in the Configs tab: the file is created when missing (the folder too), overwritten otherwise, and the config becomes the active one.
Returns: the name of the config as stored on disk.
Errors:
xiao.config.set("misc.hit_sound.volume", 60)
xiao.config.save("quiet")
xiao.config.list(): string[]
xiao.config.list(): string[]
Returns: the names of the configs saved in the folder, sorted, without the extension. Files whose name is not a valid config name are left out; a missing folder gives an empty array.
Errors: the config folder is unavailable, configs are kept in memory.
for index, name in ipairs(xiao.config.list()) do
print(index, name)
end
xiao.config.directory(): string
xiao.config.directory(): string
Returns: the absolute path of the config folder, C:\xiaohook\configs by default.
Errors: the config folder is unavailable, configs are kept in memory when the client could not create any folder.
print("configs in " .. xiao.config.directory())
Key list
xiao.config.names(): string[]
xiao.config.names(): string[]
Returns every key in the order of the config file, and writes config_names.txt again in the config folder when its content changed.
Returns: an array of keys.
local keys = xiao.config.names()
print(#keys .. " settings")
The menu writes config_names.txt when it starts, then again on each names() call whose list differs from the file. One line per key, separated by tabs:
misc.hit_sound.volume float 70
misc.hit_sound.sound string bell
automation.auto_fish.enabled bool false
visual.chams.color color #FF4D4DFF
visual.players.targets.ids multi
The third column is the factory value, read before the last config is loaded. A multi key has no third column. Colors are written #RRGGBBAA.
Speed
A set of a visual key also refreshes esp (the box style is shared), and a set of an interface key refreshes every section (a new menu key can release a key bind). A set that stores the value already stored does nothing. Thousands of get and a hundred set fit in one frame.
Complete example
Flip the hit sound, switch the menu theme, and load the pvp config each time you join a world:
local config = xiao.config
local function flip(key)
return config.set(key, not config.get(key))
end
local dark = {accent = {240, 194, 80}, background = {5, 6, 7}, panels = {17, 18, 19}}
local function apply_theme(theme)
for name, rgb in pairs(theme) do
config.set("theme." .. name, rgb)
end
end
local last_session
xiao.signal.add("world_change", "profiles", function(old, new, reason)
if reason ~= "enter" or new.session == last_session then return end
last_session = new.session
local names = {}
for _, name in ipairs(config.list()) do names[name] = true end
if names.pvp then
print("loaded " .. config.load("pvp"))
end
end)
print("hit sound", flip("misc.hit_sound.enabled"))
apply_theme(dark)
print("configs in " .. config.directory())