From db2b4646ff6b4ae2032d5f281f307e2e36134ee0 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 28 Feb 2016 14:46:15 +1100 Subject: [PATCH] Majorly optimise block physics performance, also reduce memory usage of level physics undo buffer. --- Commands/building/CmdUndo.cs | 4 +- Levels/Level.Blocks.cs | 2 +- Levels/Level.Physics.cs | 164 +++++++++++++++++++---------- Levels/Level.cs | 15 +-- Levels/Physics/DoorPhysics.cs | 8 +- Levels/Physics/ExtLiquidPhysics.cs | 32 +++--- Levels/Physics/ExtraInfoPhysics.cs | 2 +- Levels/Physics/FireworkPhysics.cs | 2 +- Levels/Physics/LiquidPhysics.cs | 71 +++++++------ Levels/Physics/RocketPhysics.cs | 3 +- Starter.csproj | 4 + 11 files changed, 185 insertions(+), 122 deletions(-) diff --git a/Commands/building/CmdUndo.cs b/Commands/building/CmdUndo.cs index 63ba70961..95b374408 100644 --- a/Commands/building/CmdUndo.cs +++ b/Commands/building/CmdUndo.cs @@ -192,8 +192,8 @@ namespace MCGalaxy.Commands bool CheckBlockPhysics(Player p, long seconds, int i, Level.UndoPos undo) { byte b = p.level.GetTile(undo.location); - if (undo.timePerformed.AddSeconds(seconds) < DateTime.Now) - return false; + DateTime time = Server.StartTime.AddSeconds(undo.timeDelta); + if (time.AddSeconds(seconds) < DateTime.UtcNow) return false; if (b == undo.newType || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) { ushort x, y, z; diff --git a/Levels/Level.Blocks.cs b/Levels/Level.Blocks.cs index 055ac89cb..bb88ea9bb 100644 --- a/Levels/Level.Blocks.cs +++ b/Levels/Level.Blocks.cs @@ -392,7 +392,7 @@ namespace MCGalaxy { uP.location = b; uP.newType = type; uP.newExtType = extType; uP.oldType = oldBlock; uP.oldExtType = oldExtType; - uP.timePerformed = DateTime.Now; + uP.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds; if (currentUndo > Server.physUndo) { currentUndo = 0; diff --git a/Levels/Level.Physics.cs b/Levels/Level.Physics.cs index 96fc120b1..9e4ce36d5 100644 --- a/Levels/Level.Physics.cs +++ b/Levels/Level.Physics.cs @@ -128,16 +128,17 @@ namespace MCGalaxy { if (physics == 5) { for (int i = 0; i < ListCheck.Count; i++) { Check C = ListCheck.Items[i]; - try { + IntToPos(C.b, out x, out y, out z); + try { string info = C.data as string; - if (info == null) info = ""; - IntToPos(C.b, out x, out y, out z); + if (info == null) info = ""; if (PhysicsUpdate != null) PhysicsUpdate(x, y, z, C.time, info, this); if (info == "" || ExtraInfoPhysics.DoDoorsOnly(this, C, null)) DoorPhysics.Do(this, C); } catch { + listCheckExists.Set(x, y, z, false); ListCheck.Remove(C); } } @@ -145,23 +146,25 @@ namespace MCGalaxy { Random rand = new Random(); for (int i = 0; i < ListCheck.Count; i++) { Check C = ListCheck.Items[i]; - try { - IntToPos(C.b, out x, out y, out z); + IntToPos(C.b, out x, out y, out z); + try { string info = C.data as string; if (info == null) info = ""; if (PhysicsUpdate != null) PhysicsUpdate(x, y, z, C.time, info, this); - OnPhysicsUpdateEvent.Call(x, y, z, C.time, info, this); + if (OnPhysicsUpdateEvent.events.Count > 0) + OnPhysicsUpdateEvent.Call(x, y, z, C.time, info, this); if (info == "" || ExtraInfoPhysics.DoComplex(this, C, rand)) DoNormalPhysics(x, y, z, rand, C); } catch { + listCheckExists.Set(x, y, z, false); ListCheck.Remove(C); } } - } + } + RemoveExpiredChecks(); - ListCheck.RemoveAll(C => C.time == 255); //Remove all that are finished with 255 time lastUpdate = ListUpdate.Count; for (int i = 0; i < ListUpdate.Count; i++) { Update C = ListUpdate.Items[i]; @@ -173,7 +176,7 @@ namespace MCGalaxy { Server.s.Log("Phys update issue"); } } - ListUpdate.Clear(); + ListUpdate.Clear(); listUpdateExists.Clear(); } catch (Exception e) { Server.s.Log("Level physics error"); Server.ErrorLog(e); @@ -415,7 +418,6 @@ namespace MCGalaxy { ZombiePhysics.Do(this, C, rand); break; case Block.c4: - Server.s.Log("Processing C4"); C4.C4s c4 = C4.Find(this, ((Player)C.data).c4circuitNumber); if (c4 != null) { FillPos pos; pos.X = x; pos.Y = y; pos.Z = z; @@ -425,7 +427,6 @@ namespace MCGalaxy { break; case Block.c4det: - Server.s.Log("Processing C4 det"); C4.C4s c = C4.Find(this, ((Player)C.data).c4circuitNumber); if (c != null) { c.detenator[0] = x; @@ -440,16 +441,25 @@ namespace MCGalaxy { DoorPhysics.Do(this, C); break; } } - + public void AddCheck(int b, bool overRide = false) { AddCheck(b, overRide, ""); } public void AddCheck(int b, bool overRide, object data) { - try { - int index = ListCheck.IndexOf(C => C.b == b); - if (index < 0) { + try { + ushort x, y, z; + IntToPos(b, out x, out y, out z); + if (x >= Width || y >= Height || z >= Length) return; + + if (!listCheckExists.Get(x, y, z)) { ListCheck.Add(new Check(b, data)); //Adds block to list to be updated + listCheckExists.Set(x, y, z, true); } else if (overRide) { - ListCheck.Items[index].data = data; return; + Check[] items = ListCheck.Items; + int count = ListCheck.Count; + for (int i = 0; i < count; i++) { + if (items[i].b != b) continue; + items[i].data = data; return; + } //Dont need to check physics here because if the list is active, then physics is active :) } if (!physicssate && physics > 0) @@ -464,23 +474,25 @@ namespace MCGalaxy { internal bool AddUpdate(int b, int type, bool overRide, object data) { try { - if (overRide) { - ushort x, y, z; - IntToPos(b, out x, out y, out z); - AddCheck(b, true, data); //Dont need to check physics here....AddCheck will do that - + ushort x, y, z; + IntToPos(b, out x, out y, out z); + if (x >= Width || y >= Height || z >= Length) return false; + + if (overRide) { + AddCheck(b, true, data); //Dont need to check physics here....AddCheck will do that string info = data as string; if (info == null) info = ""; Blockchange(x, y, z, (byte)type, true, info); return true; } - if (!ListUpdate.Exists(C => C.b == b)) { + if (!listUpdateExists.Get(x, y, z)) { + listUpdateExists.Set(x, y, z, true); } else if (type == Block.sand || type == Block.gravel) { - ListUpdate.RemoveAll(C => C.b == b); + RemoveUpdatesAtPos(b); } else { return false; - } + } ListUpdate.Add(new Update(b, (byte)type, data)); if (!physicssate && physics > 0) @@ -492,12 +504,41 @@ namespace MCGalaxy { return false; } } - + + void RemoveExpiredChecks() { + Check[] items = ListCheck.Items; + int j = 0, count = ListCheck.Count; + ushort x, y, z; + + for (int i = 0; i < count; i++) { + if (items[i].time == 255) { + IntToPos(items[i].b, out x, out y, out z); + listCheckExists.Set(x, y, z, false); + continue; + } + items[j] = items[i]; j++; + } + ListCheck.Items = items; + ListCheck.Count = j; + } + + void RemoveUpdatesAtPos(int b) { + Update[] items = ListUpdate.Items; + int j = 0, count = ListUpdate.Count; + + for (int i = 0; i < count; i++) { + if (items[j].b == b) continue; + items[j] = items[i]; j++; + } + ListUpdate.Items = items; + ListUpdate.Count = j; + } + public void ClearPhysics() { for (int i = 0; i < ListCheck.Count; i++ ) RevertPhysics(ListCheck.Items[i]); - ListCheck.Clear(); - ListUpdate.Clear(); + ListCheck.Clear(); listCheckExists.Clear(); + ListUpdate.Clear(); listUpdateExists.Clear(); } void RevertPhysics(Check C) { @@ -541,22 +582,21 @@ namespace MCGalaxy { internal void PhysAir(int b) { AirPhysics.PhysAir(this, b); } - internal void PhysWater(int b, byte type) { - if (b == -1) return; - ushort x, y, z; - IntToPos(b, out x, out y, out z); + internal void PhysWater(ushort x, ushort y, ushort z, byte type) { + if (x >= Width || y >= Height || z >= Length) return; if (Server.lava.active && Server.lava.map == this && Server.lava.InSafeZone(x, y, z)) return; - + + int b = x + (z * Width) + (y * Width * Length); switch (blocks[b]) { case Block.air: - if (!PhysSpongeCheck(b)) AddUpdate(b, type); + if (!CheckSpongeWater(x, y, z)) AddUpdate(b, type); break; case Block.lava: case Block.lava_fast: case Block.activedeathlava: - if (!PhysSpongeCheck(b)) AddUpdate(b, Block.rock); + if (!CheckSpongeWater(x, y, z)) AddUpdate(b, Block.rock); break; case Block.shrub: @@ -564,7 +604,7 @@ namespace MCGalaxy { case Block.redflower: case Block.mushroom: case Block.redmushroom: - if (physics > 1 && physics != 5 && !PhysSpongeCheck(b)) + if (physics > 1 && physics != 5 && !CheckSpongeWater(x, y, z)) AddUpdate(b, 0); //Adv physics kills flowers and mushrooms in water break; @@ -577,25 +617,24 @@ namespace MCGalaxy { } } - internal void PhysLava(int b, byte type) { - if (b == -1) return; - ushort x, y, z; - IntToPos(b, out x, out y, out z); + internal void PhysLava(ushort x, ushort y, ushort z, byte type) { + if (x >= Width || y >= Height || z >= Length) return; if (Server.lava.active && Server.lava.map == this && Server.lava.InSafeZone(x, y, z)) return; - if (physics > 1 && physics != 5 && !PhysSpongeCheck(b, true) && blocks[b] >= 21 && blocks[b] <= 36) { + int b = x + Width * (z + y * Length); + if (physics > 1 && physics != 5 && !CheckSpongeLava(x, y, z) && blocks[b] >= 21 && blocks[b] <= 36) { AddUpdate(b, Block.air); return; - } // Adv physics destroys cloth + } // Adv physics destroys cloth switch (blocks[b]) { case Block.air: - if (!PhysSpongeCheck(b, true)) AddUpdate(b, type); + if (!CheckSpongeLava(x, y, z)) AddUpdate(b, type); break; case Block.water: case Block.activedeathwater: - if (!PhysSpongeCheck(b, true)) AddUpdate(b, Block.rock); break; + if (!CheckSpongeLava(x, y, z)) AddUpdate(b, Block.rock); break; case Block.sand: if (physics > 1) { //Adv physics changes sand to glass next to lava @@ -616,7 +655,7 @@ namespace MCGalaxy { case Block.mushroom: case Block.redmushroom: if (physics > 1 && physics != 5) //Adv physics kills flowers and mushrooms plus wood in lava - if (!PhysSpongeCheck(b, true)) AddUpdate(b, Block.air); + if (!CheckSpongeLava(x, y, z)) AddUpdate(b, Block.air); break; default: break; @@ -716,16 +755,33 @@ namespace MCGalaxy { AddUpdate(bBelow, Block.stone); } } - - internal bool PhysSpongeCheck(int b, bool lava = false) { - for (int y = -2; y <= +2; ++y) - for (int z = -2; z <= +2; ++z) - for (int x = -2; x <= +2; ++x) - { - byte block = GetTile(IntOffset(b, x, y, z)); - if (block == Block.Zero) continue; - if ((!lava && block == Block.sponge) || (lava && block == Block.lava_sponge)) - return true; + + internal bool CheckSpongeWater(ushort x, ushort y, ushort z) { + for (int yy = y - 2; yy <= y + 2; ++yy) { + if (yy < 0 || yy >= Height) continue; + for (int zz = z - 2; zz <= z + 2; ++zz) { + if (zz < 0 || zz >= Length) continue; + for (int xx = x - 2; xx <= x + 2; ++xx) { + if (xx < 0 || xx >= Width) continue; + if (blocks[xx + Width * (zz + yy * Length)] == Block.sponge) + return true; + } + } + } + return false; + } + + internal bool CheckSpongeLava(ushort x, ushort y, ushort z) { + for (int yy = y - 2; yy <= y + 2; ++yy) { + if (yy < 0 || yy >= Height) continue; + for (int zz = z - 2; zz <= z + 2; ++zz) { + if (zz < 0 || zz >= Length) continue; + for (int xx = x - 2; xx <= x + 2; ++xx) { + if (xx < 0 || xx >= Width) continue; + if (blocks[xx + Width * (zz + yy * Length)] == Block.lava_sponge) + return true; + } + } } return false; } diff --git a/Levels/Level.cs b/Levels/Level.cs index fed3b5313..a7b906a57 100644 --- a/Levels/Level.cs +++ b/Levels/Level.cs @@ -69,6 +69,7 @@ namespace MCGalaxy public static bool cancelphysics; internal readonly FastList ListCheck = new FastList(); //A list of blocks that need to be updated internal readonly FastList ListUpdate = new FastList(); //A list of block to change after calculation + internal readonly SparseBitSet listCheckExists, listUpdateExists; internal readonly Dictionary leaves = new Dictionary(); // Holds block state for leaf decay @@ -236,6 +237,8 @@ namespace MCGalaxy spawnz = (ushort)(Length / 2); rotx = 0; roty = 0; + listCheckExists = new SparseBitSet(Width, Height, Length); + listUpdateExists = new SparseBitSet(Width, Height, Length); //season = new SeasonsCore(this); } @@ -251,8 +254,8 @@ namespace MCGalaxy Extras.Clear(); liquids.Clear(); leaves.Clear(); - ListCheck.Clear(); - ListUpdate.Clear(); + ListCheck.Clear(); listCheckExists.Clear(); + ListUpdate.Clear(); listUpdateExists.Clear(); UndoBuffer.Clear(); blockCache.Clear(); ZoneList.Clear(); @@ -429,10 +432,8 @@ namespace MCGalaxy // Returns true if ListCheck does not already have an check in the position. // Useful for fireworks, which depend on two physics blocks being checked, one with extraInfo. - public bool CheckClear(ushort x, ushort y, ushort z) - { - int b = PosToInt(x, y, z); - return !ListCheck.Exists(C => C.b == b); + public bool CheckClear(ushort x, ushort y, ushort z) { + return x >= Width || y >= Height || z >= Length || !listCheckExists.Get(x, y, z); } public void Save(bool Override = false, bool clearPhysics = false) @@ -744,7 +745,7 @@ namespace MCGalaxy public int location; public byte newType, newExtType; public byte oldType, oldExtType; - public DateTime timePerformed; + public int timeDelta; } public struct Zone { diff --git a/Levels/Physics/DoorPhysics.cs b/Levels/Physics/DoorPhysics.cs index e02996eee..5fac5aa4f 100644 --- a/Levels/Physics/DoorPhysics.cs +++ b/Levels/Physics/DoorPhysics.cs @@ -151,8 +151,8 @@ namespace MCGalaxy.BlockPhysics { int b1 = lvl.IntOffset(C.b, xx * 3, yy * 3, zz * 3); int b2 = lvl.IntOffset(C.b, xx * 2, yy * 2, zz * 2); bool unblocked = lvl.GetTile(b1) == Block.air && lvl.GetTile(b2) == Block.air && - !lvl.ListUpdate.Exists(u => u.b == b1) && - !lvl.ListUpdate.Exists(u => u.b == b2); + !lvl.listUpdateExists.Get(x + xx * 3, y + yy * 3, z + zz * 3) && + !lvl.listUpdateExists.Get(x + xx * 2, y + yy * 2, z + zz * 2); if (unblocked) { lvl.AddUpdate(b1, Block.rockethead); @@ -166,8 +166,8 @@ namespace MCGalaxy.BlockPhysics { int b1 = lvl.IntOffset(C.b, xx, yy + 1, zz); int b2 = lvl.IntOffset(C.b, xx, yy + 2, zz); bool unblocked = lvl.GetTile(b1) == Block.air && lvl.GetTile(b2) == Block.air && - !lvl.ListUpdate.Exists(u => u.b == b1) && - !lvl.ListUpdate.Exists(u => u.b == b2); + !lvl.listUpdateExists.Get(x + xx, y + yy + 1, z + zz) && + !lvl.listUpdateExists.Get(x + xx, y + yy + 2, z + zz); if (unblocked) { lvl.AddUpdate(b2, Block.firework); diff --git a/Levels/Physics/ExtLiquidPhysics.cs b/Levels/Physics/ExtLiquidPhysics.cs index f8a3a2246..d2a4e4c36 100644 --- a/Levels/Physics/ExtLiquidPhysics.cs +++ b/Levels/Physics/ExtLiquidPhysics.cs @@ -33,10 +33,10 @@ namespace MCGalaxy.BlockPhysics { lvl.AddUpdate(lvl.PosToInt(x, (ushort)(y - 1), z), Block.magma); } else if (below != Block.magma) { byte block = lvl.blocks[C.b]; - lvl.PhysLava(lvl.PosToInt((ushort)(x + 1), y, z), block); - lvl.PhysLava(lvl.PosToInt((ushort)(x - 1), y, z), block); - lvl.PhysLava(lvl.PosToInt(x, y, (ushort)(z + 1)), block); - lvl.PhysLava(lvl.PosToInt(x, y, (ushort)(z - 1)), block); + lvl.PhysLava((ushort)(x + 1), y, z, block); + lvl.PhysLava((ushort)(x - 1), y, z, block); + lvl.PhysLava(x, y, (ushort)(z + 1), block); + lvl.PhysLava(x, y, (ushort)(z - 1), block); } if (lvl.physics <= 1 || C.time <= 10) return; @@ -70,10 +70,10 @@ namespace MCGalaxy.BlockPhysics { lvl.AddUpdate(lvl.PosToInt(x, (ushort)(y - 1), z), Block.geyser); } else if (below != Block.geyser) { byte block = lvl.blocks[C.b]; - lvl.PhysWater(lvl.PosToInt((ushort)(x + 1), y, z), block); - lvl.PhysWater(lvl.PosToInt((ushort)(x - 1), y, z), block); - lvl.PhysWater(lvl.PosToInt(x, y, (ushort)(z + 1)), block); - lvl.PhysWater(lvl.PosToInt(x, y, (ushort)(z - 1)), block); + lvl.PhysWater((ushort)(x + 1), y, z, block); + lvl.PhysWater((ushort)(x - 1), y, z, block); + lvl.PhysWater(x, y, (ushort)(z + 1), block); + lvl.PhysWater(x, y, (ushort)(z - 1), block); } if (lvl.physics <= 1 || C.time <= 10) return; @@ -116,10 +116,10 @@ namespace MCGalaxy.BlockPhysics { break; default: byte block = lvl.blocks[C.b]; - lvl.PhysWater(lvl.PosToInt((ushort)(x + 1), y, z), block); - lvl.PhysWater(lvl.PosToInt((ushort)(x - 1), y, z), block); - lvl.PhysWater(lvl.PosToInt(x, y, (ushort)(z + 1)),block); - lvl.PhysWater(lvl.PosToInt(x, y, (ushort)(z - 1)), block); + lvl.PhysWater((ushort)(x + 1), y, z, block); + lvl.PhysWater((ushort)(x - 1), y, z, block); + lvl.PhysWater(x, y, (ushort)(z + 1),block); + lvl.PhysWater(x, y, (ushort)(z - 1), block); if (!(C.data is string) || !((string)C.data).Contains("wait")) C.time = 255; break; @@ -145,10 +145,10 @@ namespace MCGalaxy.BlockPhysics { break; default: byte block = lvl.blocks[C.b]; - lvl.PhysLava(lvl.PosToInt((ushort)(x + 1), y, z), block); - lvl.PhysLava(lvl.PosToInt((ushort)(x - 1), y, z), block); - lvl.PhysLava(lvl.PosToInt(x, y, (ushort)(z + 1)),block); - lvl.PhysLava(lvl.PosToInt(x, y, (ushort)(z - 1)), block); + lvl.PhysLava((ushort)(x + 1), y, z, block); + lvl.PhysLava((ushort)(x - 1), y, z, block); + lvl.PhysLava(x, y, (ushort)(z + 1),block); + lvl.PhysLava(x, y, (ushort)(z - 1), block); if (!(C.data is string) || !((string)C.data).Contains("wait")) C.time = 255; break; diff --git a/Levels/Physics/ExtraInfoPhysics.cs b/Levels/Physics/ExtraInfoPhysics.cs index 1b23c7ee7..88395fd88 100644 --- a/Levels/Physics/ExtraInfoPhysics.cs +++ b/Levels/Physics/ExtraInfoPhysics.cs @@ -152,7 +152,7 @@ namespace MCGalaxy.BlockPhysics { // Not setting drop = false can cause occasional leftover blocks, since C.extraInfo is emptied, so // drop can generate another block with no dissipate/explode information. if (args.Dissipate && rand.Next(1, 100) <= args.DissipateNum) { - if (!lvl.ListUpdate.Exists(Update => Update.b == C.b)) { + if (!lvl.listUpdateExists.Get(x, y, z)) { lvl.AddUpdate(C.b, Block.air); C.data = ""; args.Drop = false; diff --git a/Levels/Physics/FireworkPhysics.cs b/Levels/Physics/FireworkPhysics.cs index cc9627b2b..9c3237f82 100644 --- a/Levels/Physics/FireworkPhysics.cs +++ b/Levels/Physics/FireworkPhysics.cs @@ -36,7 +36,7 @@ namespace MCGalaxy.BlockPhysics { if (keepGoing) { int bAbove = lvl.PosToInt(x, (ushort)(y + 1), z); - bool unblocked = !lvl.ListUpdate.Exists(u => u.b == bAbove); + bool unblocked = bAbove < 0 || !lvl.listUpdateExists.Get(x, y + 1, z); if (unblocked) { lvl.AddUpdate(bAbove, Block.firework, false); lvl.AddUpdate(C.b, Block.lavastill, false, "wait 1 dissipate 100"); diff --git a/Levels/Physics/LiquidPhysics.cs b/Levels/Physics/LiquidPhysics.cs index 586148df2..5dad21a85 100644 --- a/Levels/Physics/LiquidPhysics.cs +++ b/Levels/Physics/LiquidPhysics.cs @@ -22,6 +22,7 @@ namespace MCGalaxy.BlockPhysics { public static class LiquidPhysics { + const StringComparison comp = StringComparison.Ordinal; public static void DoWater(Level lvl, Check C, Random rand) { if (lvl.finite) { lvl.liquids.Remove(C.b); @@ -65,7 +66,7 @@ namespace MCGalaxy.BlockPhysics { ushort x, y, z; lvl.IntToPos(C.b, out x, out y, out z); - if (!lvl.PhysSpongeCheck(C.b)) { + if (!lvl.CheckSpongeWater(x, y, z)) { if (!lvl.liquids.TryGetValue(C.b, out blocked)) { blocked = new bool[5]; lvl.liquids.Add(C.b, blocked); @@ -77,23 +78,23 @@ namespace MCGalaxy.BlockPhysics { } if (!blocked[0] && rand.Next(4) == 0) { - lvl.PhysWater(lvl.PosToInt((ushort)(x + 1), y, z), block); + lvl.PhysWater((ushort)(x + 1), y, z, block); blocked[0] = true; } if (!blocked[1] && rand.Next(4) == 0) { - lvl.PhysWater(lvl.PosToInt((ushort)(x - 1), y, z), block); + lvl.PhysWater((ushort)(x - 1), y, z, block); blocked[1] = true; } if (!blocked[2] && rand.Next(4) == 0) { - lvl.PhysWater(lvl.PosToInt(x, y, (ushort)(z + 1)), block); + lvl.PhysWater(x, y, (ushort)(z + 1), block); blocked[2] = true; } if (!blocked[3] && rand.Next(4) == 0) { - lvl.PhysWater(lvl.PosToInt(x, y, (ushort)(z - 1)), block); + lvl.PhysWater(x, y, (ushort)(z - 1), block); blocked[3] = true; } if (!blocked[4] && rand.Next(4) == 0) { - lvl.PhysWater(lvl.PosToInt(x, (ushort)(y - 1), z), block); + lvl.PhysWater(x, (ushort)(y - 1), z, block); blocked[4] = true; } @@ -111,11 +112,11 @@ namespace MCGalaxy.BlockPhysics { lvl.liquids.TryGetValue(C.b, out blocked); lvl.AddUpdate(C.b, Block.air); - if (((string)C.data).IndexOf("wait") == -1) + if (((string)C.data).IndexOf("wait", comp) == -1) C.time = 255; } - if (((string)C.data).IndexOf("wait") == -1 && blocked != null) + if (((string)C.data).IndexOf("wait", comp) == -1 && blocked != null) if (blocked[0] && blocked[1] && blocked[2] && blocked[3] && blocked[4]) { lvl.liquids.Remove(C.b); @@ -128,21 +129,21 @@ namespace MCGalaxy.BlockPhysics { ushort x, y, z; lvl.IntToPos(C.b, out x, out y, out z); - if (!lvl.PhysSpongeCheck(C.b)) { + if (!lvl.CheckSpongeWater(x, y, z)) { byte block = lvl.blocks[C.b]; if (lvl.GetTile(x, (ushort)(y + 1), z) != Block.Zero) { lvl.PhysSandCheck(lvl.PosToInt(x, (ushort)(y + 1), z)); } - lvl.PhysWater(lvl.PosToInt((ushort)(x + 1), y, z), block); - lvl.PhysWater(lvl.PosToInt((ushort)(x - 1), y, z), block); - lvl.PhysWater(lvl.PosToInt(x, y, (ushort)(z + 1)), block); - lvl.PhysWater(lvl.PosToInt(x, y, (ushort)(z - 1)), block); - lvl.PhysWater(lvl.PosToInt(x, (ushort)(y - 1), z), block); + lvl.PhysWater((ushort)(x + 1), y, z, block); + lvl.PhysWater((ushort)(x - 1), y, z, block); + lvl.PhysWater(x, y, (ushort)(z + 1), block); + lvl.PhysWater(x, y, (ushort)(z - 1), block); + lvl.PhysWater(x, (ushort)(y - 1), z, block); } else { //was placed near sponge lvl.AddUpdate(C.b, Block.air); } - if (((string)C.data).IndexOf("wait") == -1) + if (((string)C.data).IndexOf("wait", comp) == -1) C.time = 255; } @@ -158,7 +159,7 @@ namespace MCGalaxy.BlockPhysics { case Block.lava: case Block.lava_fast: case Block.activedeathlava: - if (!lvl.PhysSpongeCheck(b)) return false; + if (!lvl.CheckSpongeWater(x, y, z)) return false; break; case Block.shrub: @@ -166,7 +167,7 @@ namespace MCGalaxy.BlockPhysics { case Block.redflower: case Block.mushroom: case Block.redmushroom: - if (lvl.physics > 1 && !lvl.PhysSpongeCheck(b)) return false; + if (lvl.physics > 1 && !lvl.CheckSpongeWater(x, y, z)) return false; break; case Block.sand: @@ -182,7 +183,7 @@ namespace MCGalaxy.BlockPhysics { ushort x, y, z; lvl.IntToPos(C.b, out x, out y, out z); - if (!lvl.PhysSpongeCheck(C.b, true)) { + if (!lvl.CheckSpongeLava(x, y, z)) { C.time = (byte)rand.Next(3); if (!lvl.liquids.TryGetValue(C.b, out blocked)) { blocked = new bool[5]; @@ -191,23 +192,23 @@ namespace MCGalaxy.BlockPhysics { byte block = lvl.blocks[C.b]; if (!blocked[0] && rand.Next(4) == 0) { - lvl.PhysLava(lvl.PosToInt((ushort)(x + 1), y, z), block); + lvl.PhysLava((ushort)(x + 1), y, z, block); blocked[0] = true; } if (!blocked[1] && rand.Next(4) == 0) { - lvl.PhysLava(lvl.PosToInt((ushort)(x - 1), y, z), block); + lvl.PhysLava((ushort)(x - 1), y, z, block); blocked[1] = true; } if (!blocked[2] && rand.Next(4) == 0) { - lvl.PhysLava(lvl.PosToInt(x, y, (ushort)(z + 1)), block); + lvl.PhysLava(x, y, (ushort)(z + 1), block); blocked[2] = true; } if (!blocked[3] && rand.Next(4) == 0) { - lvl.PhysLava(lvl.PosToInt(x, y, (ushort)(z - 1)), block); + lvl.PhysLava(x, y, (ushort)(z - 1), block); blocked[3] = true; } if (!blocked[4] && rand.Next(4) == 0) { - lvl.PhysLava(lvl.PosToInt(x, (ushort)(y - 1), z), block); + lvl.PhysLava(x, (ushort)(y - 1), z, block); blocked[4] = true; } @@ -224,11 +225,11 @@ namespace MCGalaxy.BlockPhysics { } else { //was placed near sponge lvl.liquids.TryGetValue(C.b, out blocked); lvl.AddUpdate(C.b, Block.air); - if (!checkWait || ((string)C.data).IndexOf("wait") == -1) + if (!checkWait || ((string)C.data).IndexOf("wait", comp) == -1) C.time = 255; } - if (blocked != null && (!checkWait || ((string)C.data).IndexOf("wait") == -1)) + if (blocked != null && (!checkWait || ((string)C.data).IndexOf("wait", comp) == -1)) if (blocked[0] && blocked[1] && blocked[2] && blocked[3] && blocked[4]) { lvl.liquids.Remove(C.b); @@ -241,18 +242,18 @@ namespace MCGalaxy.BlockPhysics { ushort x, y, z; lvl.IntToPos(C.b, out x, out y, out z); - if (!lvl.PhysSpongeCheck(C.b, true)) { + if (!lvl.CheckSpongeLava(x, y, z)) { byte block = lvl.blocks[C.b]; - lvl.PhysLava(lvl.PosToInt((ushort)(x + 1), y, z), block); - lvl.PhysLava(lvl.PosToInt((ushort)(x - 1), y, z), block); - lvl.PhysLava(lvl.PosToInt(x, y, (ushort)(z + 1)), block); - lvl.PhysLava(lvl.PosToInt(x, y, (ushort)(z - 1)), block); - lvl.PhysLava(lvl.PosToInt(x, (ushort)(y - 1), z), block); + lvl.PhysLava((ushort)(x + 1), y, z, block); + lvl.PhysLava((ushort)(x - 1), y, z, block); + lvl.PhysLava(x, y, (ushort)(z + 1), block); + lvl.PhysLava(x, y, (ushort)(z - 1), block); + lvl.PhysLava(x, (ushort)(y - 1), z, block); } else { //was placed near sponge lvl.AddUpdate(C.b, Block.air); } - if (!checkWait || ((string)C.data).IndexOf("wait") == -1) + if (!checkWait || ((string)C.data).IndexOf("wait", comp) == -1) C.time = 255; } @@ -264,7 +265,7 @@ namespace MCGalaxy.BlockPhysics { return true; if (lvl.physics > 1 && lvl.blocks[b] >= Block.red && lvl.blocks[b] <= Block.white - && !lvl.PhysSpongeCheck(b, true)) + && !lvl.CheckSpongeLava(x, y, z)) return false; // Adv physics destroys cloth switch (lvl.blocks[b]) { @@ -273,7 +274,7 @@ namespace MCGalaxy.BlockPhysics { case Block.water: case Block.activedeathwater: - if (!lvl.PhysSpongeCheck(b, true)) return false; + if (!lvl.CheckSpongeLava(x, y, z)) return false; break; case Block.sand: @@ -288,7 +289,7 @@ namespace MCGalaxy.BlockPhysics { case Block.redflower: case Block.mushroom: case Block.redmushroom: - if (lvl.physics > 1 && !lvl.PhysSpongeCheck(b, true)) return false; + if (lvl.physics > 1 && !lvl.CheckSpongeLava(x, y, z)) return false; break; } return true; diff --git a/Levels/Physics/RocketPhysics.cs b/Levels/Physics/RocketPhysics.cs index f22b69597..90208dfd2 100644 --- a/Levels/Physics/RocketPhysics.cs +++ b/Levels/Physics/RocketPhysics.cs @@ -38,7 +38,8 @@ namespace MCGalaxy.BlockPhysics { int headIndex = lvl.PosToInt((ushort)(x - cx), (ushort)(y - cy), (ushort)(z - cz)); byte rocketHead = headIndex < 0 ? Block.Zero : lvl.blocks[headIndex]; - bool unblocked = !lvl.ListUpdate.Exists(u => u.b == headIndex || u.b == C.b); + bool unblocked = !lvl.listUpdateExists.Get(x, y, z) && + (headIndex < 0 || !lvl.listUpdateExists.Get(x - cx, y - cy, z - cz)); if (unblocked && (rocketHead == Block.air || rocketHead == Block.rocketstart)) { lvl.AddUpdate(headIndex, Block.rockethead); diff --git a/Starter.csproj b/Starter.csproj index fb37cd206..be11a34de 100644 --- a/Starter.csproj +++ b/Starter.csproj @@ -62,6 +62,10 @@ + + + +