mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-22 20:16:36 -04:00
Initial work on ExtBlocks extension
This commit is contained in:
parent
f3be330e43
commit
c4d43a76da
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user