Organic Growth Simulation Timing Event

ahoehma

New Member
Contributor
hi folks,

first: happy new year :)

then an short question ... i'm playing with https://github.com/cfkurtz/TerasologyTrees and https://github.com/ddr2/Terasology/commit/868ef931a1c5b202209a41b5dfe9a2d5669fc2a4. now i would like trigger the plant growing with an "timeing event" from the core engine? how could this be done? i'm looking at the liquid simulation stuff and the background sound trigger in worldrenderer but i think this is not the way :)

how could this be done for growing trees/flowers/cactus/etc. any ideas in this direction right now?

andreas
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Moving my post I was writing in the organic growth incubator thread over here then :D

I think this feature need a "timer component" from the core system.
Absolutely agreed and I've got some other ideas that need similar stuff. You've already found the WorldTimeEventManager and LiquidSimulator I take it, with the first one being independent and the second one being integrated with / based on the ES stuff.

I'm not sure if something independent would be best or if we'd gain a lot by backing a scheduler with the ES ( Immortius - any thoughts?). I used the UpdateSubscriberSystem for the Portal's SpawnerSystem but really would rather have something that can schedule execution every x period of time. Would it make sense to build a SchedulerSystem on top of the UpdateSubscriberSystem that other things can schedule stuff through? Then every game loop execution it looks for stuff that's ready to fire.

Could test it with a primitive growth simulator akin to what you're talking about over here and metouto over here and just do some sort of simple chunk scanner that finds Cotton plants and upgrades them by one size every x minutes :)

Want to try making that sort of a framework? Spin up an Incubator thread for it if so, just tagged you with the Contributor badge so you should be able to :geek: Or we can just use this one, actually.
 

ahoehma

New Member
Contributor
Then every game loop execution it looks for stuff that's ready to fire.
Maybe we can have something like "Quartz" ... for some features parallel asynchronous running task(s) would be better for the game performance.

I don't know if the good old "main loop" is outdated for such "simulation" stuff. I would go more in the multitasking (threads) direction ... with all the cool synchronization questions :D, i.e.
  • what happens if an TeraTask (i.e. TreeGrowingTask) change blocks in the world outside the current user WorldView (Singleplayer) - should the Task then stop working or should he ask the core system for "more world", I guess tree's should not stop growing o_O or a fire should not stop burning things down :laugh:
  • whats happens in an multiplayer environment
Some ideas for "TeraTasks":
  1. we should have AsyncTeraTasks and SyncTeraTasks
  2. an Task can change internal data (whole blocks, block properties) "anytime", an TaskManager have to do the synchronization
  3. Such changes must also synchronized with user inputs (local and remote) and other Tasks
  4. an Task must always have access to the "whole" world (a) the currently loaded and (b) he can make requests to load more world to continue his work
  5. an TeraTask can have a starttime (now, +N ms), a endtime, a duration (N ms, infinitly), maybe an startevent, maybe an stopevent, a priority, more?
 

dei

Java Priest
Contributor
Design
Art
With multiplayer, vertical chunks etc. finding their way more and more into the code we should define a basic interface for simulators, you're right. (There is some older thread about that, perhaps Cervator knows where you find it)

When you try to load missing world-chunks to simulate them, you'll run into the problem that there are infinite chunks (we have an infinite world). And you can't simply limit growth to a certain number of them --> :mad:
Futhermore in multiplayer you would have to distribute all changes to all clients who have the changed chunks loaded. --> huge amount of data transferred... :mad:

Because plant-growth based on grammars or simpler rules is highly deterministic and local anyway you can calculate each plant's state out of the surrounding 4 blocks and the time it already exists.
This way the game can reconstruct the missing time between loading and unloading of the containing chunk(s). A multiplayer client could even precalculate plant-growth aproximately before he gets full data from the server.

A simulator would have the following parameters: influencing world environment, current time (with the last-updated-time it holds, the simulator can calculate the timeDelta) If a simulator is in a loaded part of the world it is called in a regular time interval, else on loading of a new chunk.

So if you're implementing a simulator right now, feel free, but beware of using non-deterministic inputs as random numbers, play-time, character-position etc and only rely on parameters as local as possible (surrounding blocks, world-seed and ground-block position, ...) else there will be difficulties to make it work for multiplayer and to optimize it for huge-world performance.
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
My thoughts:

I have had in mind that ComponentSystems would be able to "subscribe" to time based events beyond the every-tick update method (I say tick rather than frame because a headless server would not have frames). It should be clarified these at least some of these events are based on ingame time, not clock time, so they might be called on, say, dawn, midday, dusk and midnight, or every "hour", or so forth. This can be done in a similar way to the current UpdateSubscriberSystem interface - perhaps an interface with onDawn(), etc methods.

For system methods subscribing to various granualities of time passing (i.e. for methods that are called every minute, 10 minutes, 1 hour of time) I would suggest an annotation approach to hook these methods into a centralised time manager. This would still be based on the passage of ingame time though, not real time (if the game is paused time should not tick forwards and these methods should not be called). But these are real-time quantities, not based on an ingame day (confusing).

The progress towards these events should survive world saving/loading - if you are 9 minutes into a world, save it and then restart and load it, the 10 minute events should occur after 1 more minute.

The third type of time event is for individual entities to subscribe for temporal events - an example would be the current Lifespan component, which allows entities to be destroyed after a time period. Ideally systems should be able to create an event to send against an entity, but have its propagation delayed until a period of time has passed. This means that these events would need to be saved and loaded with the world as well - the work I have been doing around event serialization for multiplayer will help here.

I'm not overly familiar with quartz, but unless it is able to schedule around a virtual clock it won't be useful for this.

For world simulators... these will only run on the server, so multiplayer shouldn't matter to them (plant growth would be an example of this). In this case I consider a simulator to be anything changing with time, as opposed to lighting which is derived purely from block data (and thus can be done client-side). I guess I disagree with dei on this point - I feel requiring all simulators to be purely deterministic to be too limiting, and probably unmanagable due to edge cases (specifically the edge of loaded chunk-space, which can differ between client and server).

As long as they go through the WorldProvider system, then changes to the world should be thread safe, so they can be run on background threads - changes to entities are not thread safe at the moment and should only be done on the main thread.

Control of which chunks are available is completely under control of the ChunkProvider, based on the concept of certain entities having regions around them that are relevant. Simulators should work with this, and simply run on loaded chunks (and specifically complete chunks surrounded by complete chunks, so that any light propagation they trigger will work correctly). When a chunk is unloaded, the world time should be stored with the chunk, and then when a chunk is created/loaded simulators should be informed and this world time can be used for simulators to do rapid updates. This is currently missing functionality - along with having a chunk waiting on simulators to finish updating it on load. (Basically, what dei said).

dei said:
Because plant-growth based on grammars or simpler rules is highly deterministic and local anyway you can calculate each plant's state out of the surrounding 4 blocks and the time it already exists.
The reason I believe this won't be deterministic is because of chunk boundaries. Assuming we have a 5x5 square of chunks loaded. Obviously the outer layer of blocks cannot be simulated as some of their surrounding blocks are missing. So the outer layer of chunks probably should not be simulated. The next layer of chunks can be simulated, but the outer layer of blocks are frozen in the past and not being updated. So the simulation of the next layer will be different to what would have happened if the outer layer was being simulated. If the inner blocks are all exposed dirt, and the outer blocks are grass with a 1-block think layer of dirt around the inside, then until the outer chunks are simulated none of that vegetation can propagate into the middle.
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
dei - most the old threads are still in the dev portal and awaiting review to be put into incubators or what not. Any clearer idea of what you're thinking about?

As for Quartz - I've seen it in code where I work, although I'm not sure it is in use anymore - we're using Flux nowadays. Both are more business enterprise style than what we need, and yeah, I'm pretty sure Quartz solely works on the normal system timer. Although for really advanced multi-node server clusters some of the functionality there could be nice, including persistence. Both coordinate tasks through a database though and may be more suited for larger batch tasks.
 
Top