Modding Help Universe-wide storage for mods ?

Discussion in 'Starbound Modding' started by doctortee, Jun 28, 2019.

  1. doctortee

    doctortee Scruffy Nerf-Herder

    Hello !

    I'm actually wondering if someone found a way to store datas available to objects from any world, and non-dependant to players (as it would be broken if the player plays on an other server).

    My mod (WTM) is currently providing an alternative teleporter system, and I'd like to create "pair" teleporters (two teleporters which can only teleport to each other), but it would require (if the two teleporters are on different worlds) to know on which world the two teleporters are. That's why a "universe storage" could be very nice.

    Any idea ?

    Thanks for your answers.
    DoctorTee
     
  2. bk3k

    bk3k Oxygen Tank

    Well lets see. You first need to know where you are. This is from \starbound\doc\lua\celistial.md
    Code:
    ```
    local system = celestial.currentSystem().location
    local location = nil -- Null
    location = {"coordinate", {location = system, planet = 1, satellite = 0}} -- CelestialCoordinate
    location = {"object", "11112222333344445555666677778888"} -- Object (UUID)
    location = {0.0, 0.0} -- Vec2F (position in space)
    celestial.flyShip(system, location)
    ```
    Once one object knows exactly where it is, it could spawn another object that teleports to that location. And maybe that's not enough.

    Then it is probably useful for the object to have a UUID
    Code:
    #### `String` object.uniqueId()
    
    Returns the object's unique entity id, or `nil` if no unique id is set. This should be identical to entity.uniqueId(), so use that instead.
    
    ---
    
    #### `void` object.setUniqueId([`String` uniqueId])
    
    Sets the objects unique entity id, or clears it if unspecified.
    This is also useful to set JSON attributes for the object.
    Code:
    #### `void` object.setConfigParameter(`String` key, `Json` value)
    
    Sets the specified override configuration parameter for the object.
    You said you want to be player independent... I think the way would be to store your information in either the object or within the world data.
    Code:
    #### `Json` world.getProperty(`String` propertyName, [`Json` defaultValue])
    
    Returns the JSON value of the specified world property, or defaultValue or `nil` if it is not set.
    
    ---
    
    #### `void` world.setProperty(`String` propertyName, `Json` value)
    
    Sets the specified world property to the specified value.
    
    And I'm thinking generally the data for different teleporter networks is better stored in the world data.

    Code:
      local identifier = "teleportNetworld-" .. networkID
      local currentNetwork = world.getProperty(identifier)
    
    Something along those lines to retrieve or set stored network information.

    As for the object, I'd have it save the properties in itself to know what teleport network it belongs to, and retrieve the network data from world.getProperty(). I would retrieve this data every time you open the interface, rather than upon init().

    Now you have the issue of changing data, and synchronizing data between worlds. Since after all you can only write to world data where you are standing. And the answer I think is an invisible quest running in the background that synchronizes teleporter network data. It will read the world data for each network, and part of that data will be a version number. Every time you add or remove a teleporter from the network, the version increments by 1. If the current world data's network is of a lower version number, the quest writes the current data. If by chance the world's data is the higher number, then the quest imports the new data - this can happen if another player made a change to the network. Every time you travel to a new world, the data gets checked.

    The last question is how to make any given teleporter join one network or another. And the best answer I think is data cards - an active item imprinted with the network data in its own JSON data. Upon clicking when over a teleporter, it can message the teleporter. The teleporter can then permanently add itself to that network. Or you could do it in a GUI where it checks the data cards the player has in inventory, etc.
     
  3. doctortee

    doctortee Scruffy Nerf-Herder

    Well, as I said, I already have a network working, you should check WTM on Workshop or here.
    The teleporters can only teleport to given set of coordinates that the player must insert using datacards (it's working like this since 2.0, we're currently at 3.2).

    My problem is that with a global storage system, it would be quite easy to make "paired" teleporters, as each teleporter could insert their worldid in a common table (let's say, if their network id is UUID1, then the universe storage would have a tiny JSON object called WTM_UUID1 with in its members the two worldids of the two teleporters), but without it, it's kinda difficult.

    It's still heavily relying on the player. I mean, if at one moment the player manages to remove that quest (or an other mod do), and starts to move the teleporters, it'll make the network totally unstable

    I mean, even using player scripts would be more stable, and I don't see the point of using quests for that... (I didn't really look how player scripts work, but I hope they have access to the world table)
     
  4. bk3k

    bk3k Oxygen Tank

    Not really. I'm talking about using an invisible quest - not a real quest. Nothing the player can actually ever complete. The only purpose is to run a small script in the background to compare version data, and update it when appropriate. But yes it could be done by hooking player scripts too.
     

Share This Page