I think you figured it out, but whatever... in computing, whenever perform some algorithm, some steps of the algorithm are going to rely on results from previous steps. We describe these steps as sequential or "non-parallelizable" (aka, they are "linear"). Some steps however, can be performed separately, and we would say that these steps are "parallelizable" (or "non-linear").
If we were calculating Fibonnacci or something (aka, value[n] = value[n-1]+value[n-2]), then we can't really thread it, because no thread can calculate value[n] until some other thread finishes calculating value[n-1]. We would say, therefore, that this algorithm is not parallelizable (though we can actually calculate the n'th Fibonacci with Bidet Binet's formula, so...).
When loading or updating chunks, while we do have to go through every block within a chunk in one go, we can update/load a chunk whenever we want.
How would one even do pipes without TE's? Block updates are too lazy. Oh wait, you were working on your own coremod for block updating scheduling yeah? Well even so, how would you determine the fluid being pipes when you're only limited to metadata?
Nwooo, not a coremod... I just run some code to update my fluid blocks (using the aforementioned arrays of booleans to see where the updates need to occur) straight out of the server tick event
@Pipes without TE's, the regular scheduling system should be enough... I think... I may have to leave a lot of the data storage to the backing arrays that I already have to use for fluid data though (cue another filthy hack). tl;dr, Tile Entities aren't happening. I refuse. The whole approach that MC takes to TE's makes me want to cry... I mean... wtf? Sledgehammer much?
Rollback Post to RevisionRollBack
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
Oh, by non-linear you mean parallel capable and by linear you mean serial-only? Should have said that to start with Now I get you yeah. EDIT: I don't claim serial/parallel are the correct software terms, I come from a hardware engineering background myself - so yeah that makes sense now that I know what you meant by linear.
Ah right, tick event. Hmm. But... how? Does the tick event scan every loaded chunk for your blocks and then schedule an update something :\ how else would it be done when blocks themselves are updated in a lazy way? Would that really be better than using TE's? If so, then I wouldn't be surprised I guess. I don't know much about the TE technicals but I do know that they're nasty. The fact that they are enforced an update every single tick with no possible configuration for timer resolution made me realize the possibility of how/why having a lot of them can bring any PC to its knees, as I discovered in my pre-modding, self-made-modpack-playing days.
@Linear/nonlinear/etc, yeah, pretty much. There is just a huge mess of terminology surrounding things like this, though in retrospect I should've just said "parallelizable" or something (though where parallelizable operations often have to occur with some kind of sequence or structure; chunk loading and updating is still closer to "we can do it whenever the ^&*# we want").
@Updater
So;
1. Init
I have chunk data objects that store all kinds of bonus information about chunks in a map (chunks to chunk data objects). These maps then get mapped to each world. The chunk data objects contain arrays for fluid content of each block, and flagged updates for each block (data is stored in 16x16x16 regions so that we can eliminate empty parts easily, just like ebs).
2. Marking updates.
When a fluid block needs to be updated in a chunk, I go into my special chunk data object, and set the correct value in the update flag array to true (index is something like x + z << 4 + y & 0xF << 8).
3. Performing updates
In the server tick, I iterate over all of the chunk data objects and their update arrays, then iterating over the update arrays and converting the indices back into xyz coordinates (x = index & 0xF etc), finally retrieving the block and performing an special update tick on it. Of course, much of this work ends up being done in other threads, but it all starts from the server tick. Also, the update sweeps only happen once every few ticks.
I may investigate using maps or sets in future to reduce the need for 4096 iterations per slab of the world. However, I flag updates a lot, and it's much much faster to repeatedly set a boolean to true than it is to repeatedly construct and store duplicate objects/values in a large map or set. I also don't want to risk locking things up... wait... I just thought of something great (use coordinate as address, partnered with a kind of mutilated stack... dammit Dan, now I have to pull an all-nighter to play with this )
@Tile Entities
Hmmmmm, I need to think about this for a bit later... hmmmm.... By "lazy updater", I assume you mean how the block updater can take measures to not lag things (like deferring updates)?
Rollback Post to RevisionRollBack
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
Heh yeah fair enough, whenever I hear "linear" I just instantly think of a straight line, or OpenGL/graphics stuff. Not software architecture. Jargon is like that though, I get you.
@Updates, nice! Sounds pretty fancy. Is this all your own manual handy work or does forge have something like a "Extended Chunk Properties"? Either way, nice. Sounds cleaner than I thought (and I'll bet you'll say, sounds cleaner than it actually is lol).
By lazy updates I mean how the tickrate of blocks is... yeah, lazy. Like you can have a tickrate of 1 or 10 or something small but it can take anywhere between 5-50 seconds or some crap before the scheduler decides to update it (in my tests anyway). If that's what you mean (where "deferring" an update is what the scheduler is doing to cause this delay/irregular i.e. lazy update, then yea).
Keep in mine that I don't dive into core vanilla classes like some people have, so I dunno what actually happens - just what I've observed in my limited experimentation
@Updates, manual handiwork. Forge prolly has something like it maybe, but first of all I don't trust that it is designed in a way to benefit what I'm using it for, and second; good like finding it in Forge documentation. I might look into it later when I get to looking at storing fluid data in NBT... apparently rounding 0-17 million down to 0-7 wasn't the best idea I've ever had lol.
@Lazy updates, that was the first problem I noticed when using it for water. The game wasn't lagging, but the water was updating very very very slowly and irregularly. Observation suggested that it was roughly reliable when handling a small quantity of updates, but most observation was done on a swarming mass of fluid blocks flowing left right and center, so who knows
It should be fine for most things though, right? I mean... if it's deferring the "tile entity" updates like that, then couldn't we assume that it's doing to so prevent lag? Ah... IC2 nuclear reactors... could explode if things were unlucky... hmmm... maybe it does need more thought :|
Rollback Post to RevisionRollBack
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
Manual handiwork is alright, helpers - or hand-holders aren't always good. I was doing manual stuff for my player data before I changed it all to extended entity properties stuff, and there is a lot of crap in the extended properties that I don't want/need, or that just seem excessive/tedious. Chances are I would still be using my old manual way if I figured out how to reliably save/load NBT back then, but I didn't so I changed to something standard and stuck with it. So meh. But yeah, for a newbie like me that's probably a good idea anyway - using Forge helpers is much safer I'm sure. Lol @ the rounding thing. But is having blocks represent fluid level in 8th's of a litre/bucket good enough though? I don't see a problem with that. Obviously the finer granularity for the actual world is nice, to have accurate flow and whatnot but yeah... I'm really tired...
I dunno about Tile Entities, they seem to update every damn tick (extremely frequently anyway).
I remember I tried to do it all in Campfire block without TE at first, and I only had one campfire - tickRate was 5 I believe, after placing I didn't get an update for about 20 seconds. After that it could be between ~5 and 40+ (maybe not that long, I didn't time it but it was AGES) seconds to print again to console. I dunno, but it seemed to suck anyway.
I remember I tried to do it all in Campfire block without TE at first, and I only had one campfire - tickRate was 5 I believe, after placing I didn't get an update for about 20 seconds. After that it could be between ~5 and 40+ (maybe not that long, I didn't time it but it was AGES) seconds to print again to console. I dunno, but it seemed to suck anyway.
Ah, it's because you need to actually schedule the block update (World#ScheuleBlockUpdate or something, yes, the tickRate method and field are almost completely useless ). You were just relying on random ticks (a block receives a random tick a median of once every 40 seconds, and an average of once every 60 seconds)
@rounding, it's bad because I try to simulate viscosity and surface tension. That is, when a fluid block flows into a space, because I am using 16 million fluid levels, I have to make it ~not~ flow unless it has a certain amount of fluid in it (otherwise it spreads functionally infinitely lol). I refer to this as the viscosity of the fluid, and for water is at 1/8 of a block, or 2 million fluid. However, when a new layer of fluid forms, it still uses this viscosity and it looks broken, so when on top of another water block; the viscosity is drastically reduced.
However, because when using 16 million fluid levels, 1 fluid gets rounded off to the same value as ~2 million fluid... well... let's just say that it's prone to making lots of new fluid all the time
Rollback Post to RevisionRollBack
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
Oh that makes sense. But yeah, need to do that scheduling in a tick event. But I suppose having that one tick event check/handle updates is probably better than hundreds of TE's all ticking at the same time!
Fair enough about the rounding. Does it *really* need to be millions of units per block? Is there really a need to have so many units? That's far more than the metric system. 1 cubic metre = 1000 litres = 1 million ml's.
I suppose having that one tick event check/handle updates is probably better than hundreds of TE's all ticking at the same time!
Yeah, something like this. You would schedule when the block is added, then when the block is right clicked, etc. When the block updates, say once every 5 seconds or 100 ticks, then you would have it schedule itself again in 100 ticks time.
For regular TE's like furnaces and hoppers, they could tick once or twice per second, for a 10-20x performance boost AND a system that can slow itself down to accommodate having to much going on at the same time (aka lagstomping).
The only concern is that this may not benefit things which rely on single tick precision between block interactions (such as; hopper places an item in tick 1, and another hopper removes it in tick 2), although I can't actually think of any situations where these things actually happen or are necessary, so...
Does it *really* need to be millions of units per block? Is there really a need to have so many units?
It's because precision, and there's no performance loss in any way shape or form
First => I want to use a power of 2 because it's convenient.
Second => Integers, Bytes, and Shorts (and also booleans lol), all get handled as 32 bit words (and sometimes; as 64 bit words at the native level). There are differences when using arrays, but I deem the overhead to be negligible as of this time (less than 64kb per chunk in deep ocean biome)
Of course, higher precision causes equalization calcs to occur for longer, however the peak load doesn't increase, and the calculations won't cause metadata to change; hence these calcs don't actually lag the system. In other words; if you can use the water without lag, you can use higher precision without lag.
Third => I cannot shift "half of a fluid level" because of integers (1 ÷ 2 = 0). If we liken it to using decimals, the number of fluid levels is like the number of decimal places we can use, where more fluid levels = more decimal places, but without decreasing performance (see #2).
Fourth => I had to migrate to 4 byte integers (from 2 byte shorts) since I've started looking at water pressure again, so back to #2: why not use all of the space my chosen datatype provides?
Rollback Post to RevisionRollBack
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
From what I understand (or was told rather), ticks are realtime priority - that is, a tick can never be skipped or "missed" and instead the game will slow down (as I'm sure you know what with TPS value) - not sure if that has any bearing on what you've just said, but yeah.
Power of 2 makes sense yeah. Yeah I wasn't worried about performance, I have read about the object sizes in Java so yeah. Just seemed excessive to have such a huge number But if having 15 million is no more difficult code-wise than e.g. 2 million then fair enough.
From what I understand (or was told rather), ticks are realtime priority - that is, a tick can never be skipped or "missed" and instead the game will slow down (as I'm sure you know what with TPS value) - not sure if that has any bearing on what you've just said, but yeah.
Ticks are indeed unskippable. The tick loop itself looks something like;
while(true){
long t = System.getCurrentTimeMillis();
//Do all the tick stuff
doTickStuff();
//Sleep for any remaining time in this tick
t = 50 - (System.getCurrentTimeMillis() - t);
if (t > 0){
Thread.sleep(t)
}}
Although there are a few more mechanisms relating to debugging, pretending to skip ticks when running behind, and so on (aka, if we are 250ms behind, then we increase the tick counter by 5 ticks, thus catching up).
What I mean is... if you schedule 10 updates for tick number 2, then they will all happen in tick number 2. However, if you schedule say, 10'000 updates for tick number 2, then the updater might only do 1000 updates per tick until all of the updates are done, meaning that only 10% of the updates will occur at the time they were scheduled.
It behaves like this because, if we performed 10'000 updates at once, there is a chance it would take more than 50ms, hence lowering the TPS. By performing only 1000 updates (or whatever the actual number is) in one tick, it tries to make sure that the tick stuff takes less than 50ms to perform.
While I haven't looked very far into the scheduler, I would imagine that there is also some kind of mechanism to prevent this from flooding the collection (by adding tasks faster than they are removed), for example;
while (totalNumberOfScheduledUpdates > someMaxAmount)
{
//Remove some updates from somewhere in the queue or w/e
}
I personally think that these things probably wouldn't be a problem, but...
Rollback Post to RevisionRollBack
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
Hmm interesting to know. I still make my tick counters check if >= max instead of just = max though, it really makes me cringe if I ignore overflow - dispite it being impossible :\ Old habit I guess.
Anywho, good chat... we're pretty off topic here xD well, *I'm* off topic anyway!
Slightly more off topic, but google says that your CPU (i5-4570) is roughly twice as powerful as mine (i5-3210m). Since my laptop doesn't lag at all while using a very playable range and update speed...
Anyway, I think anyone with anything better than a 1st generation mobile i3 is guaranteed to be able to use this mod, with lesser systems probably still working fairly well (just... small update ranges and stuff).
@Overflow and flooding; object pools ftw (I might end up using these as well... just need to get around to benchmarking some things (like instantiating all of the data objects and stuff).
Update: I may have just made a ~game~ run better on a workstation than on a gaming PC... Thread pooling is now finished (again), hopefully now with much better support for systems with unreasonable numbers of cores.
When I fix lighting issues and make fluids save to NBT (I've never even looked at NBT before, so if anyone has any pointers I would be very grateful), things will at least be SSP playable (aka open alpha ready :D).
EDIT: Actually, maybe add fluid pressure to that list. I'm gonna experiment and see if I can make it work gud
Rollback Post to RevisionRollBack
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
Good news is good enough to warrant a double post, and that is:
Water pressure is seeing its way back into the mod. Blocks are currently able to determine their pressure quite efficiently, though it has no bearing on flow ~yet~. In future, blocks under enough pressure may be able to damage their surroundings (Stopping an ocean with a pane of regular old glass? More like: ocean smashes through glass and the pressure either crushes all your organs, or dissolves nitrogen into your blood causing you to die of narcosis).
Bad news is that it's so addictive I will probably have to pull another all-nighter to keep working on it, which is bad because I pulled one last night as well, so I'm kinda like running on about 50 hours without sleep
Rollback Post to RevisionRollBack
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
Good news is good enough to warrant a double post, and that is:
Water pressure is seeing its way back into the mod. Blocks are currently able to determine their pressure quite efficiently, though it has no bearing on flow ~yet~. In future, blocks under enough pressure may be able to damage their surroundings (Stopping an ocean with a pane of regular old glass? More like: ocean smashes through glass and the pressure either crushes all your organs, or dissolves nitrogen into your blood causing you to die of narcosis).
Bad news is that it's so addictive I will probably have to pull another all-nighter to keep working on it, which is bad because I pulled one last night as well, so I'm kinda like running on about 50 hours without sleep
I just wrote some code that causes lots of glass to smash at the same time, so now when the ocean crushes your windows... well... let's just say you will die a hell of a lot faster http://puu.sh/aV2GP/30d2bddb4b.jpg
I might to look up tensile and shear strengths for regular glass to estimate depth a little better, but currently this effect starts at about 10-15 meters below the surface.
Next up: water breaking through walls of dirt and stuff
Rollback Post to RevisionRollBack
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
Currently it only targets glass blocks because it's massively WIP :D. I have planned behavior for a few other blocks (like high pressure fluids pushing dirt blocks out of the way), while this exact behavior will probably apply to various fragile blocks (with the block material and blast resistance being a good place to start).
The smashing formula itself starts at the "first block", then branches out a few times. First, it looks at the neighbor blocks. If it finds a glass block, it moves to it, breaks it, and looks for another adjacent glass block. After a few steps or when reaching a point with no more glass; it returns to the start and starts a new branch.
Ultimately, I will probably use various factors, including the target block strength and the water pressure that caused the breaking, to determine the number and length of the branches. Currently, these parameters are totally random (within a range).
I also plan to add something resembling reinforced glass, for all your underwater needs
Rollback Post to RevisionRollBack
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
So, pressure is now done in every way except pressurized flow. That is; the pressure of a block can now be calculated very efficiently, although it can take some time for the stuff to... "spread" over the entire body of fluid (as in, a ~5-10 seconds to reach the bottom of a deep ocean after a chunk is loaded). I've also managed to inline the calculations with the actual flow tests, and I've removed diagonal flow because it was bothering me, meaning that pressure AND flow now occur in 6 steps (first below, then to the sides), versus the 9 steps for JUST flow from before, and the 20 steps that I though I was going to need for both.
Now I just gotta make high pressure water flow upwards into lower pressure spaces ~AND THEN~ take water from a higher pressure area to compensate, which is expensive because we have to "swim" through fluid blocks, moving into the highest pressure neighbor each step (though because we effectively only care for areas with p > maxFluid (aka p > 0), we can skip the whole block getting process and get away with mere integer comparison, which makes these steps much much faster than regular flow tests).
Rollback Post to RevisionRollBack
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
I think you figured it out, but whatever... in computing, whenever perform some algorithm, some steps of the algorithm are going to rely on results from previous steps. We describe these steps as sequential or "non-parallelizable" (aka, they are "linear"). Some steps however, can be performed separately, and we would say that these steps are "parallelizable" (or "non-linear").
If we were calculating Fibonnacci or something (aka, value[n] = value[n-1]+value[n-2]), then we can't really thread it, because no thread can calculate value[n] until some other thread finishes calculating value[n-1]. We would say, therefore, that this algorithm is not parallelizable (though we can actually calculate the n'th Fibonacci with
BidetBinet's formula, so...).When loading or updating chunks, while we do have to go through every block within a chunk in one go, we can update/load a chunk whenever we want.
Nwooo, not a coremod... I just run some code to update my fluid blocks (using the aforementioned arrays of booleans to see where the updates need to occur) straight out of the server tick event
@Pipes without TE's, the regular scheduling system should be enough... I think... I may have to leave a lot of the data storage to the backing arrays that I already have to use for fluid data though (cue another filthy hack). tl;dr, Tile Entities aren't happening. I refuse. The whole approach that MC takes to TE's makes me want to cry... I mean... wtf? Sledgehammer much?
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
Oh, by non-linear you mean parallel capable and by linear you mean serial-only? Should have said that to start with Now I get you yeah. EDIT: I don't claim serial/parallel are the correct software terms, I come from a hardware engineering background myself - so yeah that makes sense now that I know what you meant by linear.
Ah right, tick event. Hmm. But... how? Does the tick event scan every loaded chunk for your blocks and then schedule an update something :\ how else would it be done when blocks themselves are updated in a lazy way? Would that really be better than using TE's? If so, then I wouldn't be surprised I guess. I don't know much about the TE technicals but I do know that they're nasty. The fact that they are enforced an update every single tick with no possible configuration for timer resolution made me realize the possibility of how/why having a lot of them can bring any PC to its knees, as I discovered in my pre-modding, self-made-modpack-playing days.
@Updater
So;
1. Init
I have chunk data objects that store all kinds of bonus information about chunks in a map (chunks to chunk data objects). These maps then get mapped to each world. The chunk data objects contain arrays for fluid content of each block, and flagged updates for each block (data is stored in 16x16x16 regions so that we can eliminate empty parts easily, just like ebs).
2. Marking updates.
When a fluid block needs to be updated in a chunk, I go into my special chunk data object, and set the correct value in the update flag array to true (index is something like x + z << 4 + y & 0xF << 8).
3. Performing updates
In the server tick, I iterate over all of the chunk data objects and their update arrays, then iterating over the update arrays and converting the indices back into xyz coordinates (x = index & 0xF etc), finally retrieving the block and performing an special update tick on it. Of course, much of this work ends up being done in other threads, but it all starts from the server tick. Also, the update sweeps only happen once every few ticks.
I may investigate using maps or sets in future to reduce the need for 4096 iterations per slab of the world. However, I flag updates a lot, and it's much much faster to repeatedly set a boolean to true than it is to repeatedly construct and store duplicate objects/values in a large map or set. I also don't want to risk locking things up... wait... I just thought of something great (use coordinate as address, partnered with a kind of mutilated stack... dammit Dan, now I have to pull an all-nighter to play with this )
@Tile Entities
Hmmmmm, I need to think about this for a bit later... hmmmm.... By "lazy updater", I assume you mean how the block updater can take measures to not lag things (like deferring updates)?
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
@Updates, nice! Sounds pretty fancy. Is this all your own manual handy work or does forge have something like a "Extended Chunk Properties"? Either way, nice. Sounds cleaner than I thought (and I'll bet you'll say, sounds cleaner than it actually is lol).
By lazy updates I mean how the tickrate of blocks is... yeah, lazy. Like you can have a tickrate of 1 or 10 or something small but it can take anywhere between 5-50 seconds or some crap before the scheduler decides to update it (in my tests anyway). If that's what you mean (where "deferring" an update is what the scheduler is doing to cause this delay/irregular i.e. lazy update, then yea).
Keep in mine that I don't dive into core vanilla classes like some people have, so I dunno what actually happens - just what I've observed in my limited experimentation
@Lazy updates, that was the first problem I noticed when using it for water. The game wasn't lagging, but the water was updating very very very slowly and irregularly. Observation suggested that it was roughly reliable when handling a small quantity of updates, but most observation was done on a swarming mass of fluid blocks flowing left right and center, so who knows
It should be fine for most things though, right? I mean... if it's deferring the "tile entity" updates like that, then couldn't we assume that it's doing to so prevent lag? Ah... IC2 nuclear reactors... could explode if things were unlucky... hmmm... maybe it does need more thought :|
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
I dunno about Tile Entities, they seem to update every damn tick (extremely frequently anyway).
I remember I tried to do it all in Campfire block without TE at first, and I only had one campfire - tickRate was 5 I believe, after placing I didn't get an update for about 20 seconds. After that it could be between ~5 and 40+ (maybe not that long, I didn't time it but it was AGES) seconds to print again to console. I dunno, but it seemed to suck anyway.
...ok, bed time for me.
Ah, it's because you need to actually schedule the block update (World#ScheuleBlockUpdate or something, yes, the tickRate method and field are almost completely useless ). You were just relying on random ticks (a block receives a random tick a median of once every 40 seconds, and an average of once every 60 seconds)
@rounding, it's bad because I try to simulate viscosity and surface tension. That is, when a fluid block flows into a space, because I am using 16 million fluid levels, I have to make it ~not~ flow unless it has a certain amount of fluid in it (otherwise it spreads functionally infinitely lol). I refer to this as the viscosity of the fluid, and for water is at 1/8 of a block, or 2 million fluid. However, when a new layer of fluid forms, it still uses this viscosity and it looks broken, so when on top of another water block; the viscosity is drastically reduced.
However, because when using 16 million fluid levels, 1 fluid gets rounded off to the same value as ~2 million fluid... well... let's just say that it's prone to making lots of new fluid all the time
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
Fair enough about the rounding. Does it *really* need to be millions of units per block? Is there really a need to have so many units? That's far more than the metric system. 1 cubic metre = 1000 litres = 1 million ml's.
Yeah, something like this. You would schedule when the block is added, then when the block is right clicked, etc. When the block updates, say once every 5 seconds or 100 ticks, then you would have it schedule itself again in 100 ticks time.
For regular TE's like furnaces and hoppers, they could tick once or twice per second, for a 10-20x performance boost AND a system that can slow itself down to accommodate having to much going on at the same time (aka lagstomping).
The only concern is that this may not benefit things which rely on single tick precision between block interactions (such as; hopper places an item in tick 1, and another hopper removes it in tick 2), although I can't actually think of any situations where these things actually happen or are necessary, so...
It's because precision, and there's no performance loss in any way shape or form
First => I want to use a power of 2 because it's convenient.
Second => Integers, Bytes, and Shorts (and also booleans lol), all get handled as 32 bit words (and sometimes; as 64 bit words at the native level). There are differences when using arrays, but I deem the overhead to be negligible as of this time (less than 64kb per chunk in deep ocean biome)
Of course, higher precision causes equalization calcs to occur for longer, however the peak load doesn't increase, and the calculations won't cause metadata to change; hence these calcs don't actually lag the system. In other words; if you can use the water without lag, you can use higher precision without lag.
Third => I cannot shift "half of a fluid level" because of integers (1 ÷ 2 = 0). If we liken it to using decimals, the number of fluid levels is like the number of decimal places we can use, where more fluid levels = more decimal places, but without decreasing performance (see #2).
Fourth => I had to migrate to 4 byte integers (from 2 byte shorts) since I've started looking at water pressure again, so back to #2: why not use all of the space my chosen datatype provides?
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
Power of 2 makes sense yeah. Yeah I wasn't worried about performance, I have read about the object sizes in Java so yeah. Just seemed excessive to have such a huge number But if having 15 million is no more difficult code-wise than e.g. 2 million then fair enough.
Ticks are indeed unskippable. The tick loop itself looks something like;
Although there are a few more mechanisms relating to debugging, pretending to skip ticks when running behind, and so on (aka, if we are 250ms behind, then we increase the tick counter by 5 ticks, thus catching up).
What I mean is... if you schedule 10 updates for tick number 2, then they will all happen in tick number 2. However, if you schedule say, 10'000 updates for tick number 2, then the updater might only do 1000 updates per tick until all of the updates are done, meaning that only 10% of the updates will occur at the time they were scheduled.
It behaves like this because, if we performed 10'000 updates at once, there is a chance it would take more than 50ms, hence lowering the TPS. By performing only 1000 updates (or whatever the actual number is) in one tick, it tries to make sure that the tick stuff takes less than 50ms to perform.
While I haven't looked very far into the scheduler, I would imagine that there is also some kind of mechanism to prevent this from flooding the collection (by adding tasks faster than they are removed), for example;
I personally think that these things probably wouldn't be a problem, but...
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
Anywho, good chat... we're pretty off topic here xD well, *I'm* off topic anyway!
Slightly more off topic, but google says that your CPU (i5-4570) is roughly twice as powerful as mine (i5-3210m). Since my laptop doesn't lag at all while using a very playable range and update speed...
Anyway, I think anyone with anything better than a 1st generation mobile i3 is guaranteed to be able to use this mod, with lesser systems probably still working fairly well (just... small update ranges and stuff).
@Overflow and flooding; object pools ftw (I might end up using these as well... just need to get around to benchmarking some things (like instantiating all of the data objects and stuff).
Update: I may have just made a ~game~ run better on a workstation than on a gaming PC... Thread pooling is now finished (again), hopefully now with much better support for systems with unreasonable numbers of cores.
When I fix lighting issues and make fluids save to NBT (I've never even looked at NBT before, so if anyone has any pointers I would be very grateful), things will at least be SSP playable (aka open alpha ready :D).
EDIT: Actually, maybe add fluid pressure to that list. I'm gonna experiment and see if I can make it work gud
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
Good news is good enough to warrant a double post, and that is:
Water pressure is seeing its way back into the mod. Blocks are currently able to determine their pressure quite efficiently, though it has no bearing on flow ~yet~. In future, blocks under enough pressure may be able to damage their surroundings (Stopping an ocean with a pane of regular old glass? More like: ocean smashes through glass and the pressure either crushes all your organs, or dissolves nitrogen into your blood causing you to die of narcosis).
Bad news is that it's so addictive I will probably have to pull another all-nighter to keep working on it, which is bad because I pulled one last night as well, so I'm kinda like running on about 50 hours without sleep
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
Whoa, calm down there.
I just wrote some code that causes lots of glass to smash at the same time, so now when the ocean crushes your windows... well... let's just say you will die a hell of a lot faster http://puu.sh/aV2GP/30d2bddb4b.jpg
I might to look up tensile and shear strengths for regular glass to estimate depth a little better, but currently this effect starts at about 10-15 meters below the surface.
Next up: water breaking through walls of dirt and stuff
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
The smashing formula itself starts at the "first block", then branches out a few times. First, it looks at the neighbor blocks. If it finds a glass block, it moves to it, breaks it, and looks for another adjacent glass block. After a few steps or when reaching a point with no more glass; it returns to the start and starts a new branch.
Ultimately, I will probably use various factors, including the target block strength and the water pressure that caused the breaking, to determine the number and length of the branches. Currently, these parameters are totally random (within a range).
I also plan to add something resembling reinforced glass, for all your underwater needs
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
Now I just gotta make high pressure water flow upwards into lower pressure spaces ~AND THEN~ take water from a higher pressure area to compensate, which is expensive because we have to "swim" through fluid blocks, moving into the highest pressure neighbor each step (though because we effectively only care for areas with p > maxFluid (aka p > 0), we can skip the whole block getting process and get away with mere integer comparison, which makes these steps much much faster than regular flow tests).
I believe in the Invisible Pink Unicorn, bless her Invisible Pinkness.
- a graphical effect of liquid cascading down the side of a block (like this: https://www.youtube.com/watch? v=Q_TdeGIOOts )
- the direction of flow moves entities (whirlpools would appear to work to the player if it was done right)
- rain makes puddles, underground gasses, fluid movement machines, all like the old finite liquid mod
- snow melts into water
- water can leak through certain blocks at certain speeds (sand, clay, dirt)
- some liquids could have a temperature, changing their flow speed, so lava could cool and set
just some ideas, glad to see a mod like this once again