ClassiCube / MCGalaxy

A Minecraft Classic / ClassiCube server software
GNU General Public License v3.0
160 stars 76 forks source link

[PATCH] Physics fix for "listCheckExists causes dead cells" #765

Open rdebath opened 1 year ago

rdebath commented 1 year ago

Multiple instances of explosions and fire can cause cells to ignore physics operations so (for example) a fire block placed in that cell doesn't burn surrounding cells or disappear.

This small change (in the foundInfo function) doesn't prevent cells dying but does cause them to be refreshed (reset?) if someone places a new block in that cell.

This should not measurably impact performance as it only has an effect when a user is placing a block.

diff --git a/MCGalaxy/Levels/Level.Physics.cs b/MCGalaxy/Levels/Level.Physics.cs
index 2d4479814..b1c5f144c 100644
--- a/MCGalaxy/Levels/Level.Physics.cs
+++ b/MCGalaxy/Levels/Level.Physics.cs
@@ -129,12 +129,14 @@ namespace MCGalaxy {
             int index = PosToInt(x, y, z);
             for (int i = 0; i < ListCheck.Count; i++) {
                 Check C = ListCheck.Items[i];
                 if (C.Index != index) continue;
                 return C.data;
             }
+            // Hmmm, it's set, but there's nothing there
+            listCheckExists.Set(x, y, z, false);
             return default(PhysicsArgs);
         }

         void PhysicsTick() {
             lastCheck = ListCheck.Count;
             const uint mask = PhysicsArgs.TypeMask;
rdebath commented 11 months ago

This seems to be a fix for the actual problem. The problem looks like a classic cellular automata implementation issue where the state of cell (x,y) depends on cell (x-1,y-1) but by the time the (x,y) cell is being calculated the (x-1,y-1) cell has already been updated to the next tick. I'm correcting this by simply regenerating the bitmap from the queue that it's supposed to be optimising when the queue is scanned for RemoveFromChecks flagged entries. This also has the advantage that the bitmap will be reduced back to a small size after a full map flood has completed.

I suggest the previous update is still also included as IMO it's a cheap and effective fallback.

Subject: [PATCH] Physics fix for listCheckExists causes dead cells

---
 MCGalaxy/Levels/Level.Physics.cs | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/MCGalaxy/Levels/Level.Physics.cs b/MCGalaxy/Levels/Level.Physics.cs
index fdb1c5f66..accf3c3b1 100644
--- a/MCGalaxy/Levels/Level.Physics.cs
+++ b/MCGalaxy/Levels/Level.Physics.cs
@@ -307,12 +307,13 @@ namespace MCGalaxy {
             int j = 0, count = ListCheck.Count;
             ushort x, y, z;

+            listCheckExists.Clear();
             for (int i = 0; i < count; i++) {
+                IntToPos(items[i].Index, out x, out y, out z);
                 if (items[i].data.Data == PhysicsArgs.RemoveFromChecks) {
-                    IntToPos(items[i].Index, out x, out y, out z);
-                    listCheckExists.Set(x, y, z, false);
                     continue;
                 }
+                listCheckExists.Set(x, y, z, true);
                 items[j] = items[i]; j++;
             }
             ListCheck.Items = items;
-- 
2.20.1