Skip to content

Commit

Permalink
Fix drawops disconnecting preclassic client when using block ids > gold
Browse files Browse the repository at this point in the history
  • Loading branch information
UnknownShadow200 committed Sep 27, 2021
1 parent fad58cd commit a79a177
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 66 deletions.
49 changes: 23 additions & 26 deletions MCGalaxy/Blocks/Block.Convert.cs
Expand Up @@ -76,10 +76,29 @@ public static partial class Block {
}


/// <summary> Converts a block &lt; CPE_COUNT into a suitable block for given protocol </summary>
internal static byte ConvertClassic(byte block, byte version) {
block = ConvertCPE(block);
if (version >= Server.VERSION_0030) return block;
/// <summary> Converts a block &lt; CPE_COUNT into a suitable block for client </summary>
internal static byte ConvertLimited(byte block, Player p) {
if (p.hasCustomBlocks) return block;

switch (block) {
case CobblestoneSlab: block = Slab; break;
case Rope: block = Mushroom; break;
case Sandstone: block = Sand; break;
case Snow: block = Air; break;
case Fire: block = Lava; break;
case LightPink: block = Pink; break;
case ForestGreen: block = Green; break;
case Brown: block = Dirt; break;
case DeepBlue: block = Blue; break;
case Turquoise: block = Cyan; break;
case Ice: block = Glass; break;
case CeramicTile: block = Iron; break;
case MagmaBlock: block = Obsidian; break;
case Pillar: block = White; break;
case Crate: block = Wood; break;
case StoneBrick: block = Stone; break;
}
if (p.version >= Server.VERSION_0030) return block;

// protocol version 6 only supports up to gold block
switch (block) {
Expand All @@ -95,28 +114,6 @@ public static partial class Block {
return block;
}

public static byte ConvertCPE(byte block) {
switch (block) {
case CobblestoneSlab: return Slab;
case Rope: return Mushroom;
case Sandstone: return Sand;
case Snow: return Air;
case Fire: return Lava;
case LightPink: return Pink;
case ForestGreen: return Green;
case Brown: return Dirt;
case DeepBlue: return Blue;
case Turquoise: return Cyan;
case Ice: return Glass;
case CeramicTile: return Iron;
case MagmaBlock: return Obsidian;
case Pillar: return White;
case Crate: return Wood;
case StoneBrick: return Stone;
default: return block;
}
}

public static BlockID Convert(BlockID block) {
switch (block) {
case FlagBase: return Mushroom;
Expand Down
16 changes: 12 additions & 4 deletions MCGalaxy/Network/Player.Networking.cs
Expand Up @@ -23,10 +23,11 @@
using BlockID = System.UInt16;
using BlockRaw = System.Byte;

namespace MCGalaxy {
public partial class Player : IDisposable, INetProtocol {

public bool hasCpe, finishedCpeLogin = false;
namespace MCGalaxy
{
public partial class Player : IDisposable, INetProtocol
{
public bool hasCpe, finishedCpeLogin;
public string appName;
int extensionCount;

Expand Down Expand Up @@ -351,5 +352,12 @@ public partial class Player : IDisposable, INetProtocol {
if (!hasCustomBlocks) raw = fallback[(BlockRaw)raw];
return raw;
}

void UpdateFallbackTable() {
for (byte b = 0; b < Block.CPE_COUNT; b++)
{
fallback[b] = Block.ConvertLimited(b, this);
}
}
}
}
48 changes: 17 additions & 31 deletions MCGalaxy/Network/Utils/BufferedBlockSender.cs
Expand Up @@ -67,27 +67,27 @@ public sealed class BufferedBlockSender {
}

void SendLevel() {
byte[] bulk = null, normal = null, noBlockDefs = null, original = null, ext = null, extBulk = null;
byte[] bulk = null, normal = null, noBlockDefs = null, classic = null, ext = null, extBulk = null;
Player[] players = PlayerInfo.Online.Items;
foreach (Player p in players) {
if (p.level != level) continue;
byte[] packet = MakePacket(p, ref bulk, ref normal,
ref noBlockDefs, ref original, ref ext, ref extBulk);
ref noBlockDefs, ref classic, ref ext, ref extBulk);
p.Socket.Send(packet, SendFlags.LowPriority);
}
}

void SendPlayer() {
byte[] bulk = null, normal = null, noBlockDefs = null, original = null, ext = null, extBulk = null;
byte[] bulk = null, normal = null, noBlockDefs = null, classic = null, ext = null, extBulk = null;
byte[] packet = MakePacket(player, ref bulk, ref normal,
ref noBlockDefs, ref original, ref ext, ref extBulk);
ref noBlockDefs, ref classic, ref ext, ref extBulk);
player.Socket.Send(packet, SendFlags.LowPriority);
}

#region Packet construction

byte[] MakePacket(Player p, ref byte[] bulk, ref byte[] normal,
ref byte[] noBlockDefs, ref byte[] original, ref byte[] ext, ref byte[] extBulk) {
ref byte[] noBlockDefs, ref byte[] classic, ref byte[] ext, ref byte[] extBulk) {
#if TEN_BIT_BLOCKS
if (p.hasExtBlocks) {
if (p.hasBulkBlockUpdate && count >= 150) {
Expand All @@ -101,18 +101,21 @@ public sealed class BufferedBlockSender {
#endif

// Different clients support varying types of blocks
if (p.hasBulkBlockUpdate && p.hasCustomBlocks && p.hasBlockDefs && count >= 160) {
if (p.hasBulkBlockUpdate && p.hasBlockDefs && count >= 160) {
if (bulk == null) bulk = MakeBulk();
return bulk;
} else if (p.hasCustomBlocks && p.hasBlockDefs) {
} else if (p.hasBlockDefs) {
// supports all 255 blocks (classicube enhanced client)
if (normal == null) normal = MakeNormal();
return normal;
} else if (p.hasCustomBlocks) {
if (noBlockDefs == null) noBlockDefs = MakeNoBlockDefs();
return noBlockDefs;
} else if (!p.hasCustomBlocks && p.version == Server.VERSION_0030) {
// support original 45 blocks (classic client)
if (classic == null) classic = MakeLimited(p.fallback);
return classic;
} else {
if (original == null) original = MakeOriginalOnly();
return original;
// other support combination (CPE only, preclassic, etc)
// don't bother trying to optimise for this case
return MakeLimited(p.fallback);
}
}

Expand Down Expand Up @@ -206,7 +209,7 @@ public sealed class BufferedBlockSender {
return data;
}

byte[] MakeNoBlockDefs() {
byte[] MakeLimited(byte[] fallback) {
byte[] data = new byte[count * 8];
for (int i = 0, j = 0; i < count; i++) {
int index = indices[i];
Expand All @@ -218,24 +221,7 @@ public sealed class BufferedBlockSender {
data[j++] = (byte)(x >> 8); data[j++] = (byte)x;
data[j++] = (byte)(y >> 8); data[j++] = (byte)y;
data[j++] = (byte)(z >> 8); data[j++] = (byte)z;
data[j++] = level.GetFallback(blocks[i]);
}
return data;
}

byte[] MakeOriginalOnly() {
byte[] data = new byte[count * 8];
for (int i = 0, j = 0; i < count; i++) {
int index = indices[i];
int x = (index % level.Width);
int y = (index / level.Width) / level.Length;
int z = (index / level.Width) % level.Length;

data[j++] = Opcode.SetBlock;
data[j++] = (byte)(x >> 8); data[j++] = (byte)x;
data[j++] = (byte)(y >> 8); data[j++] = (byte)y;
data[j++] = (byte)(z >> 8); data[j++] = (byte)z;
data[j++] = Block.ConvertCPE(level.GetFallback(blocks[i]));
data[j++] = fallback[level.GetFallback(blocks[i])];
}
return data;
}
Expand Down
2 changes: 2 additions & 0 deletions MCGalaxy/Player/Player.CPE.cs
Expand Up @@ -74,6 +74,8 @@ public partial class Player {
if (ext.Name == CpeExt.CustomBlocks) {
if (version == 1) Send(Packet.CustomBlockSupportLevel(1));
hasCustomBlocks = true;

UpdateFallbackTable();
if (MaxRawBlock < Block.CPE_MAX_BLOCK) MaxRawBlock = Block.CPE_MAX_BLOCK;
} else if (ext.Name == CpeExt.ChangeModel) {
hasChangeModel = true;
Expand Down
2 changes: 1 addition & 1 deletion MCGalaxy/Player/Player.Fields.cs
Expand Up @@ -225,7 +225,7 @@ public partial class Player : IDisposable {
bool gotSQLData;

internal byte version; // protocol version
byte[] fallback = new byte[256]; // fallback for classic+CPE block IDs
internal byte[] fallback = new byte[256]; // fallback for classic+CPE block IDs


public bool cancelcommand, cancelchat, cancelmove;
Expand Down
5 changes: 1 addition & 4 deletions MCGalaxy/Player/Player.Login.cs
Expand Up @@ -52,10 +52,7 @@ public partial class Player : IDisposable
Loading = true;
if (Socket.Disconnected) return;

for (byte b = 0; b < Block.CPE_COUNT; b++) {
fallback[b] = Block.ConvertClassic(b, version);
}

UpdateFallbackTable();
if (hasCpe) { SendCpeExtensions(); }
else { CompleteLoginProcess(); }
}
Expand Down

0 comments on commit a79a177

Please sign in to comment.