Skip to content

Commit

Permalink
Merge pull request #635 from UnknownShadow200/PreProtocol6
Browse files Browse the repository at this point in the history
Add support for protocols 3-5
  • Loading branch information
UnknownShadow200 committed Oct 1, 2021
2 parents 87dec1a + 5235334 commit 517831d
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 117 deletions.
33 changes: 24 additions & 9 deletions MCGalaxy/Blocks/Block.Convert.cs
Expand Up @@ -80,6 +80,7 @@ public static partial class Block {
internal static byte ConvertLimited(byte block, Player p) {
if (p.hasCustomBlocks) return block;

// protocol version 7 only supports up to Obsidian block
switch (block) {
case CobblestoneSlab: block = Slab; break;
case Rope: block = Mushroom; break;
Expand All @@ -100,17 +101,31 @@ public static partial class Block {
}
if (p.version >= Server.VERSION_0030) return block;

// protocol version 6 only supports up to gold block
// protocol version 6 only supports up to Gold block
switch (block) {
case Iron: return Gold;
case DoubleSlab: return Gray;
case Slab: return Gray;
case Brick: return Red;
case TNT: return Red;
case Bookshelf: return Wood;
case MossyRocks: return Cobblestone;
case Obsidian: return Cobblestone;
case Iron: block = Gold; break;
case DoubleSlab: block = Gray; break;
case Slab: block = Gray; break;
case Brick: block = Red; break;
case TNT: block = Red; break;
case Bookshelf: block = Wood; break;
case MossyRocks: block = Cobblestone; break;
case Obsidian: block = Cobblestone; break;
}
if (p.version >= Server.VERSION_0020) return block;

// protocol version 5 only supports up to Glass block
if (block == Block.Gold) block = Block.Sponge;
if (block >= Block.Dandelion) block = Block.Sapling;
if (block >= Block.Red) block = Block.Sand;
if (p.version >= Server.VERSION_0019) return block;

// protocol version 4 only supports up to Leaves block
if (block == Block.Glass) block = Block.Leaves;
if (block == Block.Sponge) block = Block.GoldOre;

// protocol version 3 seems to have same support
// TODO what even changed between 3 and 4?
return block;
}

Expand Down
5 changes: 3 additions & 2 deletions MCGalaxy/Network/Packets/Packet.cs
Expand Up @@ -29,7 +29,8 @@ public static class Packet
#region Classic

public static byte[] Motd(Player p, string motd) {
byte[] buffer = new byte[131];
bool type = p.version >= Server.VERSION_0020;
byte[] buffer = new byte[130 + (type ? 1 : 0)];
buffer[0] = Opcode.Handshake;
buffer[1] = p.version;

Expand All @@ -41,7 +42,7 @@ public static class Packet
NetUtils.Write(motd, buffer, 66, p.hasCP437);
}

buffer[130] = p.UserType();
if (type) buffer[130] = p.UserType();
return buffer;
}

Expand Down
119 changes: 50 additions & 69 deletions MCGalaxy/Network/Player.Networking.cs
Expand Up @@ -27,68 +27,43 @@ namespace MCGalaxy
{
public partial class Player : IDisposable, INetProtocol
{
public bool hasCpe, finishedCpeLogin;
public string appName;
int extensionCount;

int INetProtocol.ProcessReceived(byte[] buffer, int bufferLen) {
int processedLen = 0;
int read = 0;
try {
while (processedLen < bufferLen) {
int packetLen = PacketSize(buffer[processedLen]);
while (read < bufferLen) {
int packetLen = HandlePacket(buffer, read, bufferLen - read);
// Partial packet received
if (packetLen == 0) break;

// Client was forced disconnected
if (packetLen == -1) return bufferLen;

// Partial packet data received
if (processedLen + packetLen > bufferLen) return processedLen;
HandlePacket(buffer, processedLen);
processedLen += packetLen;
// Packet processed, onto next
read += packetLen;
}
} catch (Exception ex) {
Logger.LogError(ex);
}
return processedLen;
return read;
}

int PacketSize(byte opcode) {
switch (opcode) {
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:
Leave("Unhandled opcode \"" + opcode + "\"!", true);
return -1;
}
}

void HandlePacket(byte[] buffer, int offset) {
int HandlePacket(byte[] buffer, int offset, int left) {
switch (buffer[offset]) {
case Opcode.Ping: break;
case Opcode.Handshake:
HandleLogin(buffer, offset); break;
case Opcode.SetBlockClient:
HandleBlockchange(buffer, offset); break;
case Opcode.EntityTeleport:
HandleMovement(buffer, offset); break;
case Opcode.Message:
HandleChat(buffer, offset); break;
case Opcode.CpeExtInfo:
HandleExtInfo(buffer, offset); break;
case Opcode.CpeExtEntry:
HandleExtEntry(buffer, offset); break;
case Opcode.Ping: return 1;
case Opcode.Handshake: return HandleLogin(buffer, offset, left);
case Opcode.SetBlockClient: return HandleBlockchange(buffer, offset, left);
case Opcode.EntityTeleport: return HandleMovement(buffer, offset, left);
case Opcode.Message: return HandleChat(buffer, offset, left);
case Opcode.CpeExtInfo: return HandleExtInfo(buffer, offset, left);
case Opcode.CpeExtEntry: return HandleExtEntry(buffer, offset, left);
case Opcode.CpePlayerClick: return HandlePlayerClicked(buffer, offset, left);
case Opcode.CpeTwoWayPing: return HandleTwoWayPing(buffer, offset, left);

case Opcode.CpeCustomBlockSupportLevel:
break; // only ever one level
case Opcode.CpePlayerClick:
HandlePlayerClicked(buffer, offset); break;
case Opcode.CpeTwoWayPing:
HandleTwoWayPing(buffer, offset); break;
return left < 2 ? 0 : 2; // only ever one level anyways
default:
Leave("Unhandled opcode \"" + buffer[offset] + "\"!", true);
return -1;
}
}

Expand All @@ -107,28 +82,34 @@ public partial class Player : IDisposable, INetProtocol
#else
BlockID ReadBlock(byte[] buffer, int offset) { return Block.FromRaw(buffer[offset]); }
#endif

int HandleBlockchange(byte[] buffer, int offset, int left) {
int size = 1 + 6 + 1 + (hasExtBlocks ? 2 : 1);
if (left < size) return 0;
if (!loggedIn) return size;

ProcessBlockchange(buffer, offset);
return size;
}

void HandleExtInfo(byte[] buffer, int offset) {
appName = NetUtils.ReadString(buffer, offset + 1);
extensionCount = buffer[offset + 66];
CheckReadAllExtensions(); // in case client supports 0 CPE packets
int HandleMovement(byte[] buffer, int offset, int left) {
int size = 1 + 6 + 2 + (hasExtPositions ? 6 : 0) + (hasExtBlocks ? 2 : 1);
if (left < size) return 0;
if (!loggedIn) return size;

ProcessMovement(buffer, offset);
return size;
}

void HandleExtEntry(byte[] buffer, int offset) {
string extName = NetUtils.ReadString(buffer, offset + 1);
int extVersion = NetUtils.ReadI32(buffer, offset + 65);
AddExtension(extName, extVersion);
extensionCount--;
CheckReadAllExtensions();

int HandleChat(byte[] buffer, int offset, int left) {
const int size = 1 + 1 + 64;
if (left < size) return 0;
if (!loggedIn) return size;

ProcessChat(buffer, offset);
return size;
}

void CheckReadAllExtensions() {
if (extensionCount <= 0 && !finishedCpeLogin) {
CompleteLoginProcess();
finishedCpeLogin = true;
}
}


public void Send(byte[] buffer) { Socket.Send(buffer, SendFlags.None); }
public void Send(byte[] buffer, bool sync) {
Expand Down Expand Up @@ -354,7 +335,7 @@ public partial class Player : IDisposable, INetProtocol
}

void UpdateFallbackTable() {
for (byte b = 0; b < Block.CPE_COUNT; b++)
for (byte b = 0; b < Block.CPE_COUNT; b++)
{
fallback[b] = Block.ConvertLimited(b, this);
}
Expand Down
70 changes: 54 additions & 16 deletions MCGalaxy/Player/Player.CPE.cs
Expand Up @@ -19,8 +19,10 @@
using MCGalaxy.Network;
using BlockID = System.UInt16;

namespace MCGalaxy {
public sealed class CpeExtension {
namespace MCGalaxy
{
public sealed class CpeExtension
{
public string Name;
public byte ClientVersion, ServerVersion = 1;

Expand All @@ -30,7 +32,11 @@ public sealed class CpeExtension {
}
}

public partial class Player {
public partial class Player
{
public bool hasCpe, finishedCpeLogin;
public string appName;
int extensionCount;

public CpeExtension[] Extensions = new CpeExtension[] {
new CpeExtension(CpeExt.ClickDistance), new CpeExtension(CpeExt.CustomBlocks),
Expand Down Expand Up @@ -66,6 +72,44 @@ public partial class Player {
public bool hasCustomBlocks, hasBlockDefs, hasTextColors, hasExtBlocks, hasEmoteFix,
hasChangeModel, hasExtList, hasCP437, hasTwoWayPing, hasBulkBlockUpdate, hasExtTexs;

/// <summary> Whether this player's client supports the given CPE extension at the given version </summary>
public bool Supports(string extName, int version = 1) {
if (!hasCpe) return false;
CpeExtension ext = FindExtension(extName);
return ext != null && ext.ClientVersion == version;
}

public string GetTextureUrl() {
string url = level.Config.TexturePack.Length == 0 ? level.Config.Terrain : level.Config.TexturePack;
if (url.Length == 0) {
url = Server.Config.DefaultTexture.Length == 0 ? Server.Config.DefaultTerrain : Server.Config.DefaultTexture;
}
return url;
}


int HandleExtInfo(byte[] buffer, int offset, int left) {
const int size = 1 + 64 + 2;
if (left < size) return 0;

appName = NetUtils.ReadString(buffer, offset + 1);
extensionCount = buffer[offset + 66];
CheckReadAllExtensions(); // in case client supports 0 CPE packets
return size;
}

int HandleExtEntry(byte[] buffer, int offset, int left) {
const int size = 1 + 64 + 4;
if (left < size) return 0;

string extName = NetUtils.ReadString(buffer, offset + 1);
int extVersion = NetUtils.ReadI32(buffer, offset + 65);
AddExtension(extName, extVersion);
extensionCount--;
CheckReadAllExtensions();
return size;
}

void AddExtension(string extName, int version) {
CpeExtension ext = FindExtension(extName.Trim());
if (ext == null) return;
Expand Down Expand Up @@ -110,13 +154,15 @@ public partial class Player {
}
#endif
}

public bool Supports(string extName, int version = 1) {
if (!hasCpe) return false;
CpeExtension ext = FindExtension(extName);
return ext != null && ext.ClientVersion == version;

void CheckReadAllExtensions() {
if (extensionCount <= 0 && !finishedCpeLogin) {
CompleteLoginProcess();
finishedCpeLogin = true;
}
}


string lastUrl = "";
public void SendCurrentTextures() {
Zone zone = ZoneIn;
Expand Down Expand Up @@ -146,14 +192,6 @@ public partial class Player {
Send(Packet.MapAppearance(url, side, edge, edgeHeight, hasCP437));
}
}

public string GetTextureUrl() {
string url = level.Config.TexturePack.Length == 0 ? level.Config.Terrain : level.Config.TexturePack;
if (url.Length == 0) {
url = Server.Config.DefaultTexture.Length == 0 ? Server.Config.DefaultTerrain : Server.Config.DefaultTexture;
}
return url;
}

public void SendEnvColor(byte type, string hex) {
ColorDesc c;
Expand Down

0 comments on commit 517831d

Please sign in to comment.