Initial work on ExtBlocks extension

This commit is contained in:
UnknownShadow200 2018-03-08 09:12:07 +11:00
parent f3be330e43
commit c4d43a76da
7 changed files with 100 additions and 67 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -16,6 +16,7 @@
permissions and limitations under the Licenses.
*/
using System;
using BlockID = System.UInt16;
namespace MCGalaxy {
/// <summary> Utility methods for reading/writing big endian integers, and fixed length strings. </summary>
@ -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;

View File

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

View File

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