Skip to content
Menu
SteamAH
  • Cheat
  • Guide
  • Tips
  • Privacy Policy
  • Abuse
SteamAH

Tabletop Simulator: How to Fix XML Input Fields not Synchronizing to All Clients

Posted on March 25, 2024

If your XML UIs aren’t syncing what’s typed to everyone, there’s an easy fix. Also, a generic Boilerplate for XML UI is provided.

 

The Fix

If you want an InputField in your XML UI to synchronize to all clients, it must have an “onValueChanged” handler and an “id” field, e.g.

<InputField id="4" onValueChanged="onValueChanged" />

The Lua code for the object must then implement that handler, and that handler must update the InputField’s “Text” attribute. For example:

function onValueChanged(player, value, id)
    self.UI.setAttribute(id, "Text", value)
end

Note that this is why the element must have an “id”, so that the code can assign back to its attribute. Note also that `setValue` WILL NOT work here, even though you might expect it to.

This behaviour is somewhat unexpected. I’ve filed a bug report for it here, if you wish to upvote it or comment in support: https://tabletopsimulator.nolt.io/2262

Boilerplate for a synchronized, saved XML UI

Attached here is some boilerplate for an XML UI that implements onSave and onLoad, and synchronizes those values above so updates can be seen by all players. It’s essentially the basis of the record sheets for the Gensou Narratograph mod. Feel free to use it as a jumping off point.

XML:

    
    

Lua:

local state = {
    inputs = {},
    toggles = {}
}

function applyState()
    for id, v in pairs(state.inputs) do
        self.UI.setAttribute(id, "Text", v)
        self.UI.setValue(id, v)
    end
    for id, v in pairs(state.toggles) do
        self.UI.setAttribute(id, "isOn", v or nil)
    end
end

function valueChanged(player, value, id)
    state.inputs[id] = value
    self.UI.setValue(id, value)
    -- Updating the value doesn't update the text content because lmao
    self.UI.setAttribute(id, "Text", value)
end

function toggleChanged(player, isOn, id)
    state.toggles[id] = isOn
    self.UI.setAttribute(id, "isOn", isOn or nil)
end

function onLoad(save_state_string)
    if save_state_string ~= "" then
        state = JSON.decode(save_state_string)
        applyState()
    end
end

function onSave()
    return JSON.encode(state)
end

This uses the `Defaults` block to apply these handlers to all input elements by default. Classes defined in `Defaults` blocks can also define `onValueChanged` attributes, which is useful if you have multiple elements that do similar things. Elements or classes that need more or different functionality can of course supply their own onValueChanged handlers that call `valueChanged` to get the saving and syncing.

Happy Hacking! TTS has its share of rough edges but a little scripting can go a long way!


Thanks to Capellan for their excellent guide; all credit belongs to their effort. If this guide helps you, please support and rate it here. Enjoy the game.

MORE GAME GUIDES FOR YOU

Related Posts:

  • Tabletop Simulator: Secret Hitler Guide

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Disclaimer

All content cited is derived from their respective sources. If you think we have used your content without permission, Please go to the Abuse Page to contact us and we will be taking it seriously.

Recent Posts

  • MindsEye: How to Fix Crash Issues on Windows 10 & 11
  • MindsEye: How to Disable Depth of Field for Better Performance
  • Parasite Inside: Full Save + Maps [V0.3.5]
  • Car Dealer Simulator: 100% Achievement Guide
  • Sheepy: A Short Adventure – Save Files for the “SHEEPY STRONG” Achievement
©2025 SteamAH | Powered by SuperbThemes & WordPress