From 7dd3f578e7dc1c49071a6d6786f1454373c5c67b Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 12 Mar 2016 13:41:33 +1100 Subject: [PATCH] Majorly optimise /undo and /redo - less memory and CPU usage, less bandwidth usage, and less likelihood of overloading the server. --- Commands/building/CmdRedo.cs | 7 +++++- Commands/building/CmdUndo.cs | 11 ++++++--- Levels/Block.Permissions.cs | 4 ++-- Levels/BufferedBlockSender.cs | 2 +- Levels/Level.Blocks.cs | 26 ++++++++++----------- Player/Player.Handlers.cs | 43 +++++++++++++++++++---------------- 6 files changed, 53 insertions(+), 40 deletions(-) diff --git a/Commands/building/CmdRedo.cs b/Commands/building/CmdRedo.cs index 48aa9af2a..72d46bd14 100644 --- a/Commands/building/CmdRedo.cs +++ b/Commands/building/CmdRedo.cs @@ -44,6 +44,7 @@ namespace MCGalaxy.Commands { Level lvl = LevelInfo.FindExact(node.MapName); if (lvl == null) { node = node.Prev; continue; } List items = node.Items; + BufferedBlockSender buffer = new BufferedBlockSender(lvl); for (int i = items.Count - 1; i >= 0; i--) { UndoCacheItem item = items[i]; @@ -53,8 +54,12 @@ namespace MCGalaxy.Commands { byte type = lvl.GetTile(x, y, z), extType = 0; if (type == Block.custom_block) extType = lvl.GetExtTile(x, y, z); - lvl.Blockchange(p, x, y, z, item.Type, item.ExtType); + if (lvl.DoBlockchange(p, x, y, z, item.Type, item.ExtType)) { + buffer.Add(lvl.PosToInt(x, y, z), item.Type, item.ExtType); + buffer.CheckIfSend(false); + } } + buffer.CheckIfSend(true); node = node.Prev; } } diff --git a/Commands/building/CmdUndo.cs b/Commands/building/CmdUndo.cs index 9f012e96b..93d99abd4 100644 --- a/Commands/building/CmdUndo.cs +++ b/Commands/building/CmdUndo.cs @@ -169,6 +169,7 @@ namespace MCGalaxy.Commands if (lvl == null) { node = node.Prev; continue; } saveLvl = lvl; List items = node.Items; + BufferedBlockSender buffer = new BufferedBlockSender(lvl); for (int i = items.Count - 1; i >= 0; i--) { UndoCacheItem item = items[i]; @@ -179,11 +180,14 @@ namespace MCGalaxy.Commands byte b = lvl.GetTile(x, y, z); if (b == item.NewType || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) { - Player.UndoPos uP = default(Player.UndoPos); + Player.UndoPos uP = default(Player.UndoPos); uP.newtype = item.Type; uP.newExtType = item.ExtType; byte extType = 0; if (b == Block.custom_block) extType = lvl.GetExtTile(x, y, z); - lvl.Blockchange(p, x, y, z, item.Type, item.ExtType); + if (lvl.DoBlockchange(p, x, y, z, item.Type, item.ExtType)) { + buffer.Add(lvl.PosToInt(x, y, z), item.Type, item.ExtType); + buffer.CheckIfSend(false); + } uP.type = b; uP.extType = extType; uP.x = x; uP.y = y; uP.z = z; @@ -191,8 +195,9 @@ namespace MCGalaxy.Commands time = node.BaseTime.AddSeconds(item.TimeDelta); uP.timeDelta = (int)time.Subtract(Server.StartTime).TotalSeconds; if (p != null) p.RedoBuffer.Add(lvl, uP); - } + } } + buffer.CheckIfSend(true); node = node.Prev; } } diff --git a/Levels/Block.Permissions.cs b/Levels/Block.Permissions.cs index 82df05fca..5da9a4207 100644 --- a/Levels/Block.Permissions.cs +++ b/Levels/Block.Permissions.cs @@ -347,12 +347,12 @@ namespace MCGalaxy public static bool canPlace(Player p, byte type) { Blocks b = BlockList[type]; LevelPermission perm = p.group.Permission; - return (perm >= b.lowestRank || b.allow.Contains(perm)) && !b.disallow.Contains(perm)); + return (perm >= b.lowestRank || b.allow.Contains(perm)) && !b.disallow.Contains(perm); } public static bool canPlace(LevelPermission perm, byte type) { Blocks b = BlockList[type]; - return (perm >= b.lowestRank || b.allow.Contains(perm)) && !b.disallow.Contains(perm)); + return (perm >= b.lowestRank || b.allow.Contains(perm)) && !b.disallow.Contains(perm); } } } diff --git a/Levels/BufferedBlockSender.cs b/Levels/BufferedBlockSender.cs index 99e604ce7..dbc54995b 100644 --- a/Levels/BufferedBlockSender.cs +++ b/Levels/BufferedBlockSender.cs @@ -47,7 +47,7 @@ namespace MCGalaxy { // Different clients support varying types of blocks byte[] packet = null; - if (p.HasCpeExt(CpeExt.BulkBlockUpdate) && p.hasCustomBlocks && p.hasBlockDefs && count >= 1600) { + if (p.HasCpeExt(CpeExt.BulkBlockUpdate) && p.hasCustomBlocks && p.hasBlockDefs && count >= 160) { if (bulk == null) bulk = MakeBulkPacket(); packet = bulk; } else if (p.hasCustomBlocks && p.hasBlockDefs) { diff --git a/Levels/Level.Blocks.cs b/Levels/Level.Blocks.cs index 9635ddb7e..dbb5dff8e 100644 --- a/Levels/Level.Blocks.cs +++ b/Levels/Level.Blocks.cs @@ -299,18 +299,23 @@ namespace MCGalaxy { } public void Blockchange(Player p, ushort x, ushort y, ushort z, byte type, byte extType = 0) { + if (DoBlockchange(p, x, y, z, type, extType)) + Player.GlobalBlockchange(this, x, y, z, type, extType); + } + + internal bool DoBlockchange(Player p, ushort x, ushort y, ushort z, byte type, byte extType = 0) { string errorLocation = "start"; retry: try { //if (x < 0 || y < 0 || z < 0) return; - if (x >= Width || y >= Height || z >= Length) return; + if (x >= Width || y >= Height || z >= Length) return false; byte b = GetTile(x, y, z), extB = 0; if (b == Block.custom_block) extB = GetExtTile(x, y, z); errorLocation = "Permission checking"; if (!CheckAffectPermissions(p, x, y, z, b, type, extType)) { - p.RevertBlock(x, y, z); return; + p.RevertBlock(x, y, z); return false; } if (b == Block.sponge && physics > 0 && type != Block.sponge) @@ -332,20 +337,9 @@ namespace MCGalaxy { p.overallBlocks++; SetTile(x, y, z, type); if (b == Block.custom_block && type != Block.custom_block) - RevertExtTileNoCheck(x, y, z); + RevertExtTileNoCheck(x, y, z); if (type == Block.custom_block) SetExtTileNoCheck(x, y, z, extType); - - errorLocation = "Block sending"; - bool diffBlock = b == Block.custom_block ? extB != extType : - Block.Convert(b) != Block.Convert(type); - if (diffBlock) Player.GlobalBlockchange(this, x, y, z, type, extType); - - errorLocation = "Growing grass"; - if (GetTile(x, (ushort)(y - 1), z) == Block.grass && GrassDestroy - && !Block.LightPass(type, extType, CustomBlockDefs)) { - Blockchange(p, x, (ushort)(y - 1), z, Block.dirt); - } errorLocation = "Adding physics"; if (p.PlayingTntWars && type == Block.smalltnt) AddCheck(PosToInt(x, y, z), false, p); @@ -353,6 +347,9 @@ namespace MCGalaxy { changed = true; backedup = false; + bool diffBlock = b == Block.custom_block ? extB != extType : + Block.Convert(b) != Block.Convert(type); + return diffBlock; } catch (OutOfMemoryException) { Player.SendMessage(p, "Undo buffer too big! Cleared!"); p.UndoBuffer.Clear(); @@ -363,6 +360,7 @@ namespace MCGalaxy { Chat.GlobalMessageOps("Error location: " + errorLocation); Server.s.Log(p.name + " triggered a non-fatal error on " + name); Server.s.Log("Error location: " + errorLocation); + return false; } } diff --git a/Player/Player.Handlers.cs b/Player/Player.Handlers.cs index 18321c0e0..0c10d0051 100644 --- a/Player/Player.Handlers.cs +++ b/Player/Player.Handlers.cs @@ -736,7 +736,7 @@ namespace MCGalaxy { } void DeleteBlock(byte b, ushort x, ushort y, ushort z, byte type, byte extType) { - if ( deleteMode && b != Block.c4det ) { level.Blockchange(this, x, y, z, Block.air); return; } + if ( deleteMode && b != Block.c4det ) { ChangeBlock(x, y, z, Block.air, 0); return; } if ( Block.tDoor(b) ) { RevertBlock(x, y, z); return; } if ( Block.DoorAirs(b) != 0 ) { @@ -748,7 +748,7 @@ namespace MCGalaxy { } if ( Block.odoor(b) != Block.Zero ) { if ( b == Block.odoor8 || b == Block.odoor8_air ) { - level.Blockchange(this, x, y, z, Block.odoor(b)); + ChangeBlock(x, y, z, Block.odoor(b), 0); } else { RevertBlock(x, y, z); } @@ -835,21 +835,19 @@ namespace MCGalaxy { break; default: - level.Blockchange(this, x, y, z, (byte)( Block.air )); + ChangeBlock(x, y, z, Block.air, 0); break; } - if ( (level.physics == 0 || level.physics == 5) && level.GetTile(x, (ushort)( y - 1 ), z) == Block.dirt ) - level.Blockchange(this, x, (ushort)( y - 1 ), z, Block.grass); + if ((level.physics == 0 || level.physics == 5) && level.GetTile(x, (ushort)(y - 1), z) == Block.dirt) + ChangeBlock(x, (ushort)(y - 1), z, Block.grass, 0); } void PlaceBlock(byte b, ushort x, ushort y, ushort z, byte type, byte extType) { if ( Block.odoor(b) != Block.Zero ) { SendMessage("oDoor here!"); return; } if (modeType != 0) { - if (b == modeType) - SendBlockchange(x, y, z, b); - else - level.Blockchange(this, x, y, z, modeType); + if (b == modeType) SendBlockchange(x, y, z, b); + else ChangeBlock(x, y, z, modeType, 0); return; } @@ -861,28 +859,35 @@ namespace MCGalaxy { extAbove = level.GetExtTile(x, (ushort)(y + 1), z); if (Block.LightPass(above, extAbove, level.CustomBlockDefs)) - level.Blockchange(this, x, y, z, (byte)Block.grass); + ChangeBlock(x, y, z, Block.grass, 0); else - level.Blockchange(this, x, y, z, (byte)Block.dirt); + ChangeBlock(x, y, z, Block.dirt, 0); break; - case Block.staircasestep: //stair handler - if ( level.GetTile(x, (ushort)( y - 1 ), z) == Block.staircasestep ) { + case Block.staircasestep: + if (level.GetTile(x, (ushort)(y - 1), z) == Block.staircasestep) { SendBlockchange(x, y, z, Block.air); //send the air block back only to the user. - //level.Blockchange(this, x, y, z, (byte)(Block.air)); - level.Blockchange(this, x, (ushort)( y - 1 ), z, (byte)( Block.staircasefull )); + ChangeBlock(x, (ushort)( y - 1 ), z, Block.staircasefull, 0); break; } - //else - level.Blockchange(this, x, y, z, type, extType); + ChangeBlock(x, y, z, type, extType); break; default: - level.Blockchange(this, x, y, z, type, extType); + ChangeBlock(x, y, z, type, extType); break; } } else { - level.Blockchange(this, x, y, z, type, extType); + ChangeBlock(x, y, z, type, extType); } } + + void ChangeBlock(ushort x, ushort y, ushort z, byte type, byte extType) { + level.Blockchange(this, x, y, z, type, extType); + if (level.GetTile(x, (ushort)(y - 1), z) == Block.grass && level.GrassDestroy + && !Block.LightPass(type, extType, level.CustomBlockDefs)) { + level.Blockchange(this, x, (ushort)(y - 1), z, Block.dirt); + } + } + void HandleMovement(byte[] message) { if ( !loggedIn || trainGrab || following != "" || frozen )