Majorly optimise /undo and /redo - less memory and CPU usage, less bandwidth usage, and less likelihood of overloading the server.

This commit is contained in:
UnknownShadow200 2016-03-12 13:41:33 +11:00
parent fe0b16b33f
commit 7dd3f578e7
6 changed files with 53 additions and 40 deletions

View File

@ -44,6 +44,7 @@ namespace MCGalaxy.Commands {
Level lvl = LevelInfo.FindExact(node.MapName); Level lvl = LevelInfo.FindExact(node.MapName);
if (lvl == null) { node = node.Prev; continue; } if (lvl == null) { node = node.Prev; continue; }
List<UndoCacheItem> items = node.Items; List<UndoCacheItem> items = node.Items;
BufferedBlockSender buffer = new BufferedBlockSender(lvl);
for (int i = items.Count - 1; i >= 0; i--) { for (int i = items.Count - 1; i >= 0; i--) {
UndoCacheItem item = items[i]; UndoCacheItem item = items[i];
@ -53,8 +54,12 @@ namespace MCGalaxy.Commands {
byte type = lvl.GetTile(x, y, z), extType = 0; byte type = lvl.GetTile(x, y, z), extType = 0;
if (type == Block.custom_block) if (type == Block.custom_block)
extType = lvl.GetExtTile(x, y, z); 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; node = node.Prev;
} }
} }

View File

@ -169,6 +169,7 @@ namespace MCGalaxy.Commands
if (lvl == null) { node = node.Prev; continue; } if (lvl == null) { node = node.Prev; continue; }
saveLvl = lvl; saveLvl = lvl;
List<UndoCacheItem> items = node.Items; List<UndoCacheItem> items = node.Items;
BufferedBlockSender buffer = new BufferedBlockSender(lvl);
for (int i = items.Count - 1; i >= 0; i--) { for (int i = items.Count - 1; i >= 0; i--) {
UndoCacheItem item = items[i]; UndoCacheItem item = items[i];
@ -179,11 +180,14 @@ namespace MCGalaxy.Commands
byte b = lvl.GetTile(x, y, z); byte b = lvl.GetTile(x, y, z);
if (b == item.NewType || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) { 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; uP.newtype = item.Type; uP.newExtType = item.ExtType;
byte extType = 0; byte extType = 0;
if (b == Block.custom_block) extType = lvl.GetExtTile(x, y, z); 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.type = b; uP.extType = extType;
uP.x = x; uP.y = y; uP.z = z; uP.x = x; uP.y = y; uP.z = z;
@ -191,8 +195,9 @@ namespace MCGalaxy.Commands
time = node.BaseTime.AddSeconds(item.TimeDelta); time = node.BaseTime.AddSeconds(item.TimeDelta);
uP.timeDelta = (int)time.Subtract(Server.StartTime).TotalSeconds; uP.timeDelta = (int)time.Subtract(Server.StartTime).TotalSeconds;
if (p != null) p.RedoBuffer.Add(lvl, uP); if (p != null) p.RedoBuffer.Add(lvl, uP);
} }
} }
buffer.CheckIfSend(true);
node = node.Prev; node = node.Prev;
} }
} }

View File

@ -347,12 +347,12 @@ namespace MCGalaxy
public static bool canPlace(Player p, byte type) { public static bool canPlace(Player p, byte type) {
Blocks b = BlockList[type]; Blocks b = BlockList[type];
LevelPermission perm = p.group.Permission; 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) { public static bool canPlace(LevelPermission perm, byte type) {
Blocks b = BlockList[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);
} }
} }
} }

View File

@ -47,7 +47,7 @@ namespace MCGalaxy {
// Different clients support varying types of blocks // Different clients support varying types of blocks
byte[] packet = null; 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(); if (bulk == null) bulk = MakeBulkPacket();
packet = bulk; packet = bulk;
} else if (p.hasCustomBlocks && p.hasBlockDefs) { } else if (p.hasCustomBlocks && p.hasBlockDefs) {

View File

@ -299,18 +299,23 @@ namespace MCGalaxy {
} }
public void Blockchange(Player p, ushort x, ushort y, ushort z, byte type, byte extType = 0) { 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"; string errorLocation = "start";
retry: retry:
try try
{ {
//if (x < 0 || y < 0 || z < 0) return; //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; byte b = GetTile(x, y, z), extB = 0;
if (b == Block.custom_block) extB = GetExtTile(x, y, z); if (b == Block.custom_block) extB = GetExtTile(x, y, z);
errorLocation = "Permission checking"; errorLocation = "Permission checking";
if (!CheckAffectPermissions(p, x, y, z, b, type, extType)) { 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) if (b == Block.sponge && physics > 0 && type != Block.sponge)
@ -332,20 +337,9 @@ namespace MCGalaxy {
p.overallBlocks++; p.overallBlocks++;
SetTile(x, y, z, type); SetTile(x, y, z, type);
if (b == Block.custom_block && type != Block.custom_block) if (b == Block.custom_block && type != Block.custom_block)
RevertExtTileNoCheck(x, y, z); RevertExtTileNoCheck(x, y, z);
if (type == Block.custom_block) if (type == Block.custom_block)
SetExtTileNoCheck(x, y, z, extType); 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"; errorLocation = "Adding physics";
if (p.PlayingTntWars && type == Block.smalltnt) AddCheck(PosToInt(x, y, z), false, p); if (p.PlayingTntWars && type == Block.smalltnt) AddCheck(PosToInt(x, y, z), false, p);
@ -353,6 +347,9 @@ namespace MCGalaxy {
changed = true; changed = true;
backedup = false; backedup = false;
bool diffBlock = b == Block.custom_block ? extB != extType :
Block.Convert(b) != Block.Convert(type);
return diffBlock;
} catch (OutOfMemoryException) { } catch (OutOfMemoryException) {
Player.SendMessage(p, "Undo buffer too big! Cleared!"); Player.SendMessage(p, "Undo buffer too big! Cleared!");
p.UndoBuffer.Clear(); p.UndoBuffer.Clear();
@ -363,6 +360,7 @@ namespace MCGalaxy {
Chat.GlobalMessageOps("Error location: " + errorLocation); Chat.GlobalMessageOps("Error location: " + errorLocation);
Server.s.Log(p.name + " triggered a non-fatal error on " + name); Server.s.Log(p.name + " triggered a non-fatal error on " + name);
Server.s.Log("Error location: " + errorLocation); Server.s.Log("Error location: " + errorLocation);
return false;
} }
} }

View File

@ -736,7 +736,7 @@ namespace MCGalaxy {
} }
void DeleteBlock(byte b, ushort x, ushort y, ushort z, byte type, byte extType) { 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.tDoor(b) ) { RevertBlock(x, y, z); return; }
if ( Block.DoorAirs(b) != 0 ) { if ( Block.DoorAirs(b) != 0 ) {
@ -748,7 +748,7 @@ namespace MCGalaxy {
} }
if ( Block.odoor(b) != Block.Zero ) { if ( Block.odoor(b) != Block.Zero ) {
if ( b == Block.odoor8 || b == Block.odoor8_air ) { 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 { } else {
RevertBlock(x, y, z); RevertBlock(x, y, z);
} }
@ -835,21 +835,19 @@ namespace MCGalaxy {
break; break;
default: default:
level.Blockchange(this, x, y, z, (byte)( Block.air )); ChangeBlock(x, y, z, Block.air, 0);
break; break;
} }
if ( (level.physics == 0 || level.physics == 5) && level.GetTile(x, (ushort)( y - 1 ), z) == Block.dirt ) 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); ChangeBlock(x, (ushort)(y - 1), z, Block.grass, 0);
} }
void PlaceBlock(byte b, ushort x, ushort y, ushort z, byte type, byte extType) { 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 ( Block.odoor(b) != Block.Zero ) { SendMessage("oDoor here!"); return; }
if (modeType != 0) { if (modeType != 0) {
if (b == modeType) if (b == modeType) SendBlockchange(x, y, z, b);
SendBlockchange(x, y, z, b); else ChangeBlock(x, y, z, modeType, 0);
else
level.Blockchange(this, x, y, z, modeType);
return; return;
} }
@ -861,28 +859,35 @@ namespace MCGalaxy {
extAbove = level.GetExtTile(x, (ushort)(y + 1), z); extAbove = level.GetExtTile(x, (ushort)(y + 1), z);
if (Block.LightPass(above, extAbove, level.CustomBlockDefs)) if (Block.LightPass(above, extAbove, level.CustomBlockDefs))
level.Blockchange(this, x, y, z, (byte)Block.grass); ChangeBlock(x, y, z, Block.grass, 0);
else else
level.Blockchange(this, x, y, z, (byte)Block.dirt); ChangeBlock(x, y, z, Block.dirt, 0);
break; break;
case Block.staircasestep: //stair handler case Block.staircasestep:
if ( level.GetTile(x, (ushort)( y - 1 ), z) == 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. SendBlockchange(x, y, z, Block.air); //send the air block back only to the user.
//level.Blockchange(this, x, y, z, (byte)(Block.air)); ChangeBlock(x, (ushort)( y - 1 ), z, Block.staircasefull, 0);
level.Blockchange(this, x, (ushort)( y - 1 ), z, (byte)( Block.staircasefull ));
break; break;
} }
//else ChangeBlock(x, y, z, type, extType);
level.Blockchange(this, x, y, z, type, extType);
break; break;
default: default:
level.Blockchange(this, x, y, z, type, extType); ChangeBlock(x, y, z, type, extType);
break; break;
} }
} else { } 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) { void HandleMovement(byte[] message) {
if ( !loggedIn || trainGrab || following != "" || frozen ) if ( !loggedIn || trainGrab || following != "" || frozen )