From c4d43a76da804c2f3780a81e163b0c5ffd298225 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Thu, 8 Mar 2018 09:12:07 +1100 Subject: [PATCH] Initial work on ExtBlocks extension --- MCGalaxy/Blocks/BlockDefinitions.cs | 13 +++--- MCGalaxy/Network/Packets/Opcode.cs | 2 +- MCGalaxy/Network/Packets/Packet.cs | 63 ++++++++++++++++----------- MCGalaxy/Network/Player.Networking.cs | 21 +++++---- MCGalaxy/Network/Utils/NetUtils.cs | 6 +++ MCGalaxy/Player/Player.CPE.cs | 13 ++++-- MCGalaxy/Player/Player.Handlers.cs | 49 +++++++++++++-------- 7 files changed, 100 insertions(+), 67 deletions(-) diff --git a/MCGalaxy/Blocks/BlockDefinitions.cs b/MCGalaxy/Blocks/BlockDefinitions.cs index 76aa8822f..da30cc0a7 100644 --- a/MCGalaxy/Blocks/BlockDefinitions.cs +++ b/MCGalaxy/Blocks/BlockDefinitions.cs @@ -202,7 +202,7 @@ namespace MCGalaxy { if (!pl.hasBlockDefs) continue; if (global && pl.level.CustomBlockDefs[block] != null) continue; - pl.Send(Packet.UndefineBlock(def)); + pl.Send(Packet.UndefineBlock(def, pl.hasExtBlocks)); } Save(global, level); } @@ -210,7 +210,6 @@ namespace MCGalaxy { public static void UpdateOrder(BlockDefinition def, bool global, Level level) { if (def.InventoryOrder == -1) return; BlockID_ block = def.GetBlock(); - byte order = (byte)def.InventoryOrder; Player[] players = PlayerInfo.Online.Items; foreach (Player pl in players) { @@ -218,7 +217,7 @@ namespace MCGalaxy { if (global && pl.level.CustomBlockDefs[block] != GlobalDefs[block]) continue; if (!pl.Supports(CpeExt.InventoryOrder)) continue; - pl.Send(Packet.SetInventoryOrder((BlockRaw)block, order)); + pl.Send(Packet.SetInventoryOrder(def, pl.hasExtBlocks)); } } @@ -254,18 +253,18 @@ namespace MCGalaxy { for (int b = 0; b < defs.Length; b++) { BlockDefinition def = defs[b]; if (def != null && def.InventoryOrder >= 0) { - pl.Send(Packet.SetInventoryOrder((byte)def.BlockID, (byte)def.InventoryOrder)); + pl.Send(Packet.SetInventoryOrder(def, pl.hasExtBlocks)); } } } public byte[] MakeDefinePacket(Player pl) { if (pl.Supports(CpeExt.BlockDefinitionsExt, 2) && Shape != 0) { - return Packet.DefineBlockExt(this, true, pl.hasCP437); + return Packet.DefineBlockExt(this, true, pl.hasCP437, pl.hasExtBlocks); } else if (pl.Supports(CpeExt.BlockDefinitionsExt) && Shape != 0) { - return Packet.DefineBlockExt(this, false, pl.hasCP437); + return Packet.DefineBlockExt(this, false, pl.hasCP437, pl.hasExtBlocks); } else { - return Packet.DefineBlock(this, pl.hasCP437); + return Packet.DefineBlock(this, pl.hasCP437, pl.hasExtBlocks); } } diff --git a/MCGalaxy/Network/Packets/Opcode.cs b/MCGalaxy/Network/Packets/Opcode.cs index f71ba63c1..6ac5082e7 100644 --- a/MCGalaxy/Network/Packets/Opcode.cs +++ b/MCGalaxy/Network/Packets/Opcode.cs @@ -59,7 +59,7 @@ namespace MCGalaxy.Network { public const byte CpeExtAddEntity2 = 33; public const byte CpePlayerClick = 34; public const byte CpeDefineBlock = 35; - public const byte CpeRemoveBlockDefinition = 36; + public const byte CpeUndefineBlock = 36; public const byte CpeDefineBlockExt = 37; public const byte CpeBulkBlockUpdate = 38; public const byte CpeSetTextColor = 39; diff --git a/MCGalaxy/Network/Packets/Packet.cs b/MCGalaxy/Network/Packets/Packet.cs index 648248a17..e7fbab74b 100644 --- a/MCGalaxy/Network/Packets/Packet.cs +++ b/MCGalaxy/Network/Packets/Packet.cs @@ -18,6 +18,7 @@ using System; using MCGalaxy.Blocks; using MCGalaxy.Maths; +using BlockID = System.UInt16; namespace MCGalaxy.Network { @@ -137,14 +138,17 @@ namespace MCGalaxy.Network { } public static byte[] CustomBlockSupportLevel(byte level) { - return new byte[] { Opcode.CpeCustomBlockSupportLevel, level }; + byte[] buffer = new byte[2]; + buffer[0] = Opcode.CpeCustomBlockSupportLevel; + buffer[1] = level; + return buffer; } - public static byte[] HoldThis(byte block, bool locked) { - byte[] buffer = new byte[3]; + public static byte[] HoldThis(BlockID raw, bool locked, bool extBlocks) { + byte[] buffer = new byte[extBlocks ? 4 : 3]; buffer[0] = Opcode.CpeHoldThis; - buffer[1] = block; - buffer[2] = (byte)(locked ? 1 : 0); + NetUtils.WriteBlock(raw, buffer, 1, extBlocks); + buffer[extBlocks ? 3 : 2] = (byte)(locked ? 1 : 0); return buffer; } @@ -225,17 +229,18 @@ namespace MCGalaxy.Network { return buffer; } - public static byte[] BlockPermission(byte block, bool place, bool delete) { - byte[] buffer = new byte[4]; - WriteBlockPermission(block, place, delete, buffer, 0); + public static byte[] BlockPermission(BlockID raw, bool place, bool delete, bool extBlocks) { + byte[] buffer = new byte[extBlocks ? 5 : 4]; + WriteBlockPermission(raw, place, delete, extBlocks, buffer, 0); return buffer; } - public static void WriteBlockPermission(byte block, bool place, bool delete, byte[] buffer, int index) { - buffer[index + 0] = Opcode.CpeSetBlockPermission; - buffer[index + 1] = block; - buffer[index + 2] = place ? (byte)1 : (byte)0; - buffer[index + 3] = delete ? (byte)1 : (byte)0; + public static void WriteBlockPermission(BlockID raw, bool place, bool delete, bool extBlocks, byte[] buffer, int index) { + buffer[index++] = Opcode.CpeSetBlockPermission; + NetUtils.WriteBlock(raw, buffer, index, extBlocks); + index += extBlocks ? 2 : 1; + buffer[index++] = place ? (byte)1 : (byte)0; + buffer[index++] = delete ? (byte)1 : (byte)0; } public static byte[] ChangeModel(byte entityID, string model, bool hasCP437) { @@ -347,8 +352,12 @@ namespace MCGalaxy.Network { return buffer; } - public static byte[] SetInventoryOrder(byte block, byte position) { - return new byte[] { Opcode.CpeSetInventoryOrder, block, position }; + public static byte[] SetInventoryOrder(BlockDefinition def, bool extBlocks) { + byte[] buffer = new byte[extBlocks ? 4 : 3]; + buffer[0] = Opcode.CpeSetInventoryOrder; + NetUtils.WriteBlock(def.BlockID, buffer, 1, extBlocks); + buffer[extBlocks ? 3 : 2] = (byte)def.InventoryOrder; + return buffer; } #endregion @@ -356,25 +365,28 @@ namespace MCGalaxy.Network { #region Block definitions - public static byte[] DefineBlock(BlockDefinition def, bool hasCP437) { - byte[] buffer = new byte[80]; + public static byte[] DefineBlock(BlockDefinition def, bool hasCP437, bool extBlocks) { + byte[] buffer = new byte[extBlocks ? 81 : 80]; int i = 0; buffer[i++] = Opcode.CpeDefineBlock; - MakeDefineBlockStart(def, buffer, ref i, false, hasCP437); + MakeDefineBlockStart(def, buffer, ref i, false, hasCP437, extBlocks); buffer[i++] = def.Shape; MakeDefineBlockEnd(def, ref i, buffer); return buffer; } - public static byte[] UndefineBlock(BlockDefinition def) { - return new byte[] { Opcode.CpeRemoveBlockDefinition, (byte)def.BlockID }; + public static byte[] UndefineBlock(BlockDefinition def, bool extBlocks) { + byte[] buffer = new byte[extBlocks ? 3 : 2]; + buffer[0] = Opcode.CpeUndefineBlock; + NetUtils.WriteBlock(def.BlockID, buffer, 1, extBlocks); + return buffer; } - public static byte[] DefineBlockExt(BlockDefinition def, bool uniqueSideTexs, bool hasCP437) { - byte[] buffer = new byte[uniqueSideTexs ? 88 : 85]; + public static byte[] DefineBlockExt(BlockDefinition def, bool uniqueSideTexs, bool hasCP437, bool extBlocks) { + byte[] buffer = new byte[(extBlocks ? 86 : 85) + (uniqueSideTexs ? 3 : 0)]; int i = 0; buffer[i++] = Opcode.CpeDefineBlockExt; - MakeDefineBlockStart(def, buffer, ref i, uniqueSideTexs, hasCP437); + MakeDefineBlockStart(def, buffer, ref i, uniqueSideTexs, hasCP437, extBlocks); buffer[i++] = def.MinX; buffer[i++] = def.MinZ; buffer[i++] = def.MinY; buffer[i++] = def.MaxX; buffer[i++] = def.MaxZ; buffer[i++] = def.MaxY; MakeDefineBlockEnd(def, ref i, buffer); @@ -382,11 +394,12 @@ namespace MCGalaxy.Network { } static void MakeDefineBlockStart(BlockDefinition def, byte[] buffer, ref int i, - bool uniqueSideTexs, bool hasCP437) { + bool uniqueSideTexs, bool hasCP437, bool extBlocks) { // speed = 2^((raw - 128) / 64); // therefore raw = 64log2(speed) + 128 byte rawSpeed = (byte)(64 * Math.Log(def.Speed, 2) + 128); - buffer[i++] = (byte)def.BlockID; + NetUtils.WriteBlock(def.BlockID, buffer, i, extBlocks); + i += extBlocks ? 2 : 1; NetUtils.Write(def.Name, buffer, i, hasCP437); i += NetUtils.StringSize; buffer[i++] = def.CollideType; diff --git a/MCGalaxy/Network/Player.Networking.cs b/MCGalaxy/Network/Player.Networking.cs index 5f26c1dd7..0dc603deb 100644 --- a/MCGalaxy/Network/Player.Networking.cs +++ b/MCGalaxy/Network/Player.Networking.cs @@ -235,7 +235,7 @@ namespace MCGalaxy { for (int i = 0; i < defs.Length; i++) { BlockDefinition def = defs[i]; if (def == BlockDefinition.GlobalDefs[i]) continue; - Send(Packet.UndefineBlock(def)); + Send(Packet.UndefineBlock(def, hasExtBlocks)); } } @@ -257,29 +257,28 @@ namespace MCGalaxy { //if (x < 0 || y < 0 || z < 0) return; if (x >= level.Width || y >= level.Height || z >= level.Length) return; - byte[] buffer = new byte[8]; + byte[] buffer = new byte[hasExtBlocks ? 9 : 8]; buffer[0] = Opcode.SetBlock; NetUtils.WriteU16(x, buffer, 1); NetUtils.WriteU16(y, buffer, 3); NetUtils.WriteU16(z, buffer, 5); - BlockRaw raw; if (block >= Block.Extended) { - raw = hasBlockDefs ? (BlockRaw)block : level.RawFallback(block); + block = hasBlockDefs ? Block.ToRaw(block) : level.RawFallback(block); } else { - raw = (BlockRaw)Block.Convert(block); + block = Block.Convert(block); // Invalid block physics won't have converted form - if (raw >= Block.CpeCount) raw = Block.Orange; + if (block >= Block.CpeCount) block = Block.Orange; } // Custom block replaced a core block - if (!hasBlockDefs && raw < Block.CpeCount) { - BlockDefinition def = level.CustomBlockDefs[raw]; - if (def != null) raw = def.FallBack; + if (!hasBlockDefs && block < Block.CpeCount) { + BlockDefinition def = level.CustomBlockDefs[block]; + if (def != null) block = def.FallBack; } - if (!hasCustomBlocks) raw = Block.ConvertCPE(raw); // doesn't support CPE blocks - buffer[7] = raw; + if (!hasCustomBlocks) block = Block.ConvertCPE((BlockRaw)block); // doesn't support CPE blocks + NetUtils.WriteBlock(block, buffer, 7, hasExtBlocks); Socket.SendLowPriority(buffer); } diff --git a/MCGalaxy/Network/Utils/NetUtils.cs b/MCGalaxy/Network/Utils/NetUtils.cs index db2fe7183..62a0cc980 100644 --- a/MCGalaxy/Network/Utils/NetUtils.cs +++ b/MCGalaxy/Network/Utils/NetUtils.cs @@ -16,6 +16,7 @@ permissions and limitations under the Licenses. */ using System; +using BlockID = System.UInt16; namespace MCGalaxy { /// Utility methods for reading/writing big endian integers, and fixed length strings. @@ -66,6 +67,11 @@ namespace MCGalaxy { return extPos ? 12 : 6; } + public static void WriteBlock(BlockID raw, byte[] array, int index, bool extBlocks) { + if (extBlocks) { array[index++] = (byte)(raw >> 8); } + array[index++] = (byte)raw; + } + public unsafe static string ReadString(byte[] data, int offset) { int length = 0; diff --git a/MCGalaxy/Player/Player.CPE.cs b/MCGalaxy/Player/Player.CPE.cs index ed4b19515..bdc197259 100644 --- a/MCGalaxy/Player/Player.CPE.cs +++ b/MCGalaxy/Player/Player.CPE.cs @@ -48,7 +48,10 @@ namespace MCGalaxy { new ExtEntry(CpeExt.EnvMapAspect), new ExtEntry(CpeExt.PlayerClick), new ExtEntry(CpeExt.EntityProperty), new ExtEntry(CpeExt.ExtEntityPositions), new ExtEntry(CpeExt.TwoWayPing), new ExtEntry(CpeExt.InventoryOrder), - new ExtEntry(CpeExt.InstantMOTD), + new ExtEntry(CpeExt.InstantMOTD), + #if TEN_BIT_BLOCKS + new ExtEntry(CpeExt.ExtBlocks), + #endif }; ExtEntry FindExtension(string extName) { @@ -59,7 +62,7 @@ namespace MCGalaxy { } // these are checked very frequently, so avoid overhead of HasCpeExt - public bool hasCustomBlocks, hasBlockDefs, hasTextColors, + public bool hasCustomBlocks, hasBlockDefs, hasTextColors, hasExtBlocks, hasChangeModel, hasExtList, hasCP437, hasTwoWayPing, hasBulkBlockUpdate; void AddExtension(string extName, int version) { @@ -149,12 +152,13 @@ namespace MCGalaxy { // Write the block permissions as one bulk TCP packet int count = NumBlockPermissions(); - byte[] bulk = new byte[4 * count]; + byte[] bulk = new byte[count * (hasExtBlocks ? 5 : 4)]; WriteBlockPermissions(bulk); Send(bulk); } int NumBlockPermissions() { + if (hasExtBlocks) return Block.MaxRaw + 1; if (hasBlockDefs) return Block.Count; return hasCustomBlocks ? Block.CpeCount : Block.OriginalCount; } @@ -165,7 +169,7 @@ namespace MCGalaxy { BlockID block = Block.FromRaw((byte)i); bool place = BlockPerms.UsableBy(this, block) && level.CanPlace; bool delete = BlockPerms.UsableBy(this, block) && level.CanDelete; - Packet.WriteBlockPermission((byte)i, place, delete, bulk, i * 4); + Packet.WriteBlockPermission((byte)i, place, delete, hasExtBlocks, bulk, i * 4); } } } @@ -198,6 +202,7 @@ namespace MCGalaxy { public const string TwoWayPing = "TwoWayPing"; public const string InventoryOrder = "InventoryOrder"; public const string InstantMOTD = "InstantMOTD"; + public const string ExtBlocks = "ExtBlocks"; } public enum CpeMessageType : byte { diff --git a/MCGalaxy/Player/Player.Handlers.cs b/MCGalaxy/Player/Player.Handlers.cs index 11349457c..4c4524637 100644 --- a/MCGalaxy/Player/Player.Handlers.cs +++ b/MCGalaxy/Player/Player.Handlers.cs @@ -214,22 +214,16 @@ namespace MCGalaxy { int PacketSize(byte opcode) { switch (opcode) { case (byte)'G': return -1; // HTTP GET, ignore it - case Opcode.Handshake: return 131; - case Opcode.SetBlockClient: - if (!loggedIn) goto default; - return 9; - case Opcode.EntityTeleport: - if (!loggedIn) goto default; - return 10 + (hasExtPositions ? 6 : 0); - case Opcode.Message: - if (!loggedIn) goto default; - return 66; - case Opcode.CpeExtInfo: return 67; - case Opcode.CpeExtEntry: return 69; - case Opcode.CpeCustomBlockSupportLevel: return 2; - case Opcode.CpePlayerClick: return 15; - case Opcode.Ping: return 1; - case Opcode.CpeTwoWayPing: return 4; + case Opcode.Handshake: return 1 + 1 + 64 + 64 + 1; + case Opcode.SetBlockClient: return 1 + 6 + 1 + (hasExtBlocks ? 2 : 1); + case Opcode.EntityTeleport: return 1 + 6 + 2 + (hasExtPositions ? 6 : 0) + (hasExtBlocks ? 2 : 1); + case Opcode.Message: return 1 + 1 + 64; + case Opcode.CpeExtInfo: return 1 + 64 + 2; + case Opcode.CpeExtEntry: return 1 + 64 + 4; + case Opcode.CpeCustomBlockSupportLevel: return 1 + 1; + case Opcode.CpePlayerClick: return 1 + 1 + 1 + 2 + 2 + 1 + 2 + 2 + 2 + 1; + case Opcode.Ping: return 1; + case Opcode.CpeTwoWayPing: return 1 + 1 + 2; default: if (!nonPlayerClient) { @@ -266,6 +260,22 @@ namespace MCGalaxy { HandleTwoWayPing(buffer, offset); break; } } + + #if TEN_BIT_BLOCKS + BlockID ReadBlock(byte[] buffer, int offset) { + BlockID block; + if (hasExtBlocks) { + block = NetUtils.ReadU16(buffer, offset); + } else { + block = buffer[offset]; + } + + if (block > Block.MaxRaw) block = Block.MaxRaw; + return Block.FromRaw(block); + } + #else + BlockID ReadBlock(byte[] buffer, int offset) { return Block.FromRaw(buffer[offset]); } + #endif void HandleBlockchange(byte[] buffer, int offset) { try { @@ -283,7 +293,7 @@ namespace MCGalaxy { LastAction = DateTime.UtcNow; if (IsAfk) CmdAfk.ToggleAfk(this, ""); - BlockID held = Block.FromRaw(buffer[offset + 8]); + BlockID held = ReadBlock(buffer, offset + 8); RawHeldBlock = held; if ((action == 0 || held == Block.Air) && !level.Config.Deletable) { @@ -312,7 +322,8 @@ namespace MCGalaxy { void HandleMovement(byte[] buffer, int offset) { if (!loggedIn || trainGrab || following.Length > 0) { CheckBlocks(Pos); return; } if (Supports(CpeExt.HeldBlock)) { - RawHeldBlock = Block.FromRaw(buffer[offset + 1]); + RawHeldBlock = ReadBlock(buffer, offset + 1); + if (hasExtBlocks) offset++; // corret offset for position later } int x, y, z; @@ -384,7 +395,7 @@ namespace MCGalaxy { if (zone != null && zone.Config.GetEnvProp(i) != Block.Invalid) { value = zone.Config.GetEnvProp(i); } - + if (!hasBlockDefs) value = level.RawFallback((BlockID)value); value = (byte)value; } else {