Modding Discussion Is this idea feasible or completely insane?

Discussion in 'Starbound Modding' started by jakecool19, Jun 16, 2019.

  1. jakecool19

    jakecool19 Pangalactic Porcupine

    TL;DR Can I run the functions of many objects in one object?

    Hello there I've been away for a little while and now that 1.4 is released I have a new idea that I'm not sure will work in the current game system. For background, a few months before the 1.4 update I learned basic Lua and JSON so that I could overhaul the colony system to make a much bigger part of player progression and add lots of automation as well. I was able to make several different automatic devices and change rent, tenant stats, tenant rent, and tenant equipment. The big problem was that there is no way to keep another world loaded while the player is gone. So I made it so that the machines and the colony deeds can just save the time and calculated what should have been done while they were unloaded and do it.


    Problem solved right? Wrong! Although this works perfectly if the machine is just collecting resources or doing simple crafting solo (Ex: Idle Factories) unfortunately I was planning there being multiple interactions between machines in which they won't be able to communicate unloaded, meaning they will do there own calculations and of course if they are loaded at the same time, the machines needing input will have already ran their calculations before they can get the resources from their producers meaning a serious loss of time especially if the crafting time was particularly high. For example this is would need to happen to make a bandage.


    So after hearing of 1.4 coming and just simply burning myself out I decided to stop until 1.4. Now hear comes the insane idea, instead of having all the machines do all these tasks independently, why not have one object do all the real calculations and the machines just be visual/physical placeholders. As a part of my original plan I have an object called, the Colony Console, which acts as a sort of manager hub for all the machines, deeds, and tenants allowing the player to watch and alter things from afar and all the objects being connected to it by wires. My plan is basically to have the colony console do all of the work, for example craft items, gather resources, generate power and food, while the machines would just simply let it know whether or not it still exists, still connected, its position in the world, and what items it "contains". My fear with this is that this object would cause massive amounts of lag the moment the player got near it since all the functions would be happening in one object instead of spread out to several. Also would it even be able to run that many functions without it crashing?
     
  2. Catherine Franz

    Catherine Franz Spaceman Spiff

    Well I found a mod that makes ores on it's own w/o that much lag sooo maybe it would work?
     
  3. projectmayhem

    projectmayhem Spaceman Spiff

    I'm not great with lua, but shouldnt you be able to make it a wired object, with multiple nodes, and it it checks each nodes to make sure the other machine is present and wired to it? That way they arent just visual placeholders, they serve the function of having to be wired to the master machine
     
  4. jakecool19

    jakecool19 Pangalactic Porcupine

    All the objects already have to be wired to the master, or within the boundary of a factory/workplace.
     
  5. bk3k

    bk3k Oxygen Tank

    There would be more than one way to do it. One question being "do these processes happen in series, or concurrently? Namely is the farm still running while the cloth maker is making cloth from the existing fibers? For the sake of example, I'll say only one thing happens at a time.

    Code:
    timeCost = {
      farm = 10,
      cloth = 3,
      bandage = 5
    }
    
    --assumed functions for production
    taskFunction = {
      farm = run_farm,
      cloth = run_clothMaker,
      bandage = run_bandageMaker
    }
    
    tasklist = {}
    
    --I'll assume a function exists connected() which tells if other objects are connected.
    set_tasks = function()
      tasklist = {}  --clearing list
      if connected("farm") then
        tasklist [#tasklist + 1] = "farm"
        if connected("clothMaker") then
          tasklist [#tasklist + 1] = "cloth"
          if connected("bandageMaker") then
            tasklist [#tasklist + 1] = "cloth"
          end
        end
      end
    end
    
    
    makeup_production = function(makeupTime)
      --makeupTIme is how long the chunks or the world has been unloaded
      while makeupTime > 0 do
        for _, task in ipairs(tasklist) do
          if not (makeupTime > 0) then
            break
          end
       
          local usedTime
          local tc = timeCost[task]
          usedTime = taskFunction[task](tc)
          --the functions should return the time sent if production was successful
          --or false otherwise (such as no materials/fuel/etc)
          if usedTime then
            makeupTime = makeupTime - usedTime
          else
            makeupTime = 0
            break
          end
        end
      end
    end
    
    This is clearly incomplete code just to give you ideas. Hopefully without silly errors too. It could be made more efficient, but could be harder to read if so. I'm guessing you already have the other aspects down such as calculating time elapsed.

    Another method is using the messaging system while each object runs their own production code. That might be better in the case everything happen in parallel. For example -
    1. The main controller tell the farm so much time has elapsed.
    2. The farm calculates how much it produced in that time, and messages that back.
    3. The controller then tells the clothMaker how much time has passed, and how many plant fibers are available. The controller will subtract those plant fibers from it's own tally.
    4. The clothmaker messages back how many cloths it produced in that time (limited by either time, or available materials) and how many plant fibers remain. Those are added to the controller's tally for each. The clothMaker could send separate messages for each item, as that probably makes for cleaner code on both ends.
    5. The controller messages the bandageMaker how much time has passed, and how many cloths are available. The cloths will be subtracted from the controller's own tally.

    And when I say tally - if the controller is also a container - then I'd remove them from inventory when "sending" them to a machine, and add them to inventory when "receiving" from a machine.
     
    jakecool19 likes this.
  6. The | Suit

    The | Suit Agent S. Forum Moderator

    The trick is Algorithmic calculations and extrapolations.
    You never want unnecessary information to run in the background.

    1. First store the time the object began its "Active" state. It does not need to actually run
    2. Second store the time when it is unloaded from memory
    3. When it loaded into memory the first thing it needs to check is if anything was stored previously - if not start new storage
    4. If something was stored calculate the time difference between when it "Started" \ "stored last" to the current time

    This results in the exact same behaviour as running a script in the background with much less computation overhead. The player would not be able to tell the difference.

    Honestly there is never really a good reason to keep objects constantly running - and computers can run massive calculations in miliseconds. Which means having the object calculate all that on interaction instead of constantly on the background is usually the best option for any object that doesn't interact with the environment around it.
     
    Last edited: Jun 23, 2019
    GeekyRaptor, bk3k and jakecool19 like this.

Share This Page