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);
if (lvl == null) { node = node.Prev; continue; }
List<UndoCacheItem> 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;
}
}

View File

@ -169,6 +169,7 @@ namespace MCGalaxy.Commands
if (lvl == null) { node = node.Prev; continue; }
saveLvl = lvl;
List<UndoCacheItem> 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;
}
}

View File

@ -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);
}
}
}

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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 )