Workaround for server software that sends AddEntity then AddExtPlayerName with different player ids.

This caused duplicate tab list entry ids. Only seems to be an issue with MCForge-Redux
This commit is contained in:
UnknownShadow200 2017-02-16 23:30:49 +11:00
parent 32a00ecd88
commit 674609f5ee
5 changed files with 46 additions and 21 deletions

View file

@ -23,7 +23,7 @@ namespace ClassicalSharp.Network {
needD3Fix = false; game.UseCPEBlocks = false;
NetworkProcessor net = (NetworkProcessor)game.Server;
net.ResetProtocols();
net.Reset();
}
/// <summary> Sets fields / updates network handles based on the server

View file

@ -8,6 +8,8 @@ namespace ClassicalSharp.Network {
public partial class NetworkProcessor : IServerConnection {
internal bool addEntityHack = true;
public override void SendChat(string text, bool partial) {
if (String.IsNullOrEmpty(text)) return;
classic.SendChat(text, partial);
@ -70,14 +72,22 @@ namespace ClassicalSharp.Network {
game.Entities[id] = null;
}
// See comment about LegendCraft in HandleAddEntity
// See comment about some servers in HandleAddEntity
int mask = id >> 3, bit = 1 << (id & 0x7);
if ((needRemoveNames[mask] & bit) == 0) return;
game.EntityEvents.RaiseTabEntryRemoved(id);
game.TabList.Entries[id] = null;
if (!addEntityHack || (needRemoveNames[mask] & bit) == 0) return;
RemoveTablistEntry(id);
needRemoveNames[mask] &= (byte)~bit;
}
internal void UpdateLocation(byte playerId, LocationUpdate update, bool interpolate) {
Entity entity = game.Entities[playerId];
if (entity != null) {
entity.SetLocation(update, interpolate);
}
}
internal void AddTablistEntry(byte id, string playerName, string listName,
string groupName, byte groupRank) {
TabListEntry oldInfo = game.TabList.Entries[id];
@ -87,7 +97,7 @@ namespace ClassicalSharp.Network {
if (oldInfo != null) {
// Only redraw the tab list if something changed.
if (info.PlayerName != oldInfo.PlayerName || info.ListName != oldInfo.ListName ||
info.GroupName != oldInfo.GroupName || info.GroupRank != oldInfo.GroupRank) {
info.GroupName != oldInfo.GroupName || info.GroupRank != oldInfo.GroupRank) {
game.EntityEvents.RaiseTabListEntryChanged(id);
}
} else {
@ -95,10 +105,21 @@ namespace ClassicalSharp.Network {
}
}
internal void UpdateLocation(byte playerId, LocationUpdate update, bool interpolate) {
Entity entity = game.Entities[playerId];
if (entity != null) {
entity.SetLocation(update, interpolate);
internal void RemoveTablistEntry(byte id) {
game.EntityEvents.RaiseTabEntryRemoved(id);
game.TabList.Entries[id] = null;
}
internal void DisableAddEntityHack() {
if (!addEntityHack) return;
addEntityHack = false;
for (int id = 0; id < EntityList.MaxCount; id++) {
int mask = id >> 3, bit = 1 << (id & 0x7);
if ((needRemoveNames[mask] & bit) == 0) continue;
RemoveTablistEntry((byte)id);
needRemoveNames[mask] &= (byte)~bit;
}
}
}

View file

@ -164,11 +164,12 @@ namespace ClassicalSharp.Network {
reader.Skip(packetSizes[(byte)opcode] - 1);
}
internal void ResetProtocols() {
internal void Reset() {
UsingExtPlayerList = false;
UsingPlayerClick = false;
SupportsPartialMessages = false;
SupportsFullCP437 = false;
addEntityHack = true;
for (int i = 0; i < handlers.Length; i++)
handlers[i] = null;

View file

@ -125,6 +125,10 @@ namespace ClassicalSharp.Network.Protocols {
string groupName = reader.ReadAsciiString();
byte groupRank = reader.ReadUInt8();
// Some server software will declare they support ExtPlayerList, but send AddEntity then AddPlayerName
// we need to workaround this case by removing all the tab names we added for the AddEntity packets
net.DisableAddEntityHack();
// Workaround for some servers that don't cast signed bytes to unsigned, before converting them to shorts.
if (id < 0) id += 256;
if (id >= 0 && id <= 255)
@ -141,13 +145,11 @@ namespace ClassicalSharp.Network.Protocols {
void HandleExtRemovePlayerName() {
short id = reader.ReadInt16();
// Workaround for some servers that don't cast signed bytes to unsigned, before converting them to shorts.
if (id < 0) id += 256;
if (id >= 0 && id <= 255) {
game.EntityEvents.RaiseTabEntryRemoved((byte)id);
game.TabList.Entries[id] = null;
}
// Workaround for some servers that don't cast signed bytes to unsigned, before converting them to shorts.
if (id < 0) id += 256;
if (id >= 0 && id <= 255)
net.RemoveTablistEntry((byte)id);
}
void HandleMakeSelection() {

View file

@ -172,11 +172,12 @@ namespace ClassicalSharp.Network.Protocols {
byte id = reader.ReadUInt8();
string name = reader.ReadAsciiString();
string skin = name;
net.CheckName(id, ref name, ref skin);
net.CheckName(id, ref name, ref skin);
net.AddEntity(id, name, skin, true);
// Also workaround for LegendCraft as it declares it supports ExtPlayerList but
// doesn't send ExtAddPlayerName packets.
if (!net.addEntityHack) return;
// Workaround for some servers that declare they support ExtPlayerList,
// but doesn't send ExtAddPlayerName packets.
net.AddTablistEntry(id, name, name, "Players", 0);
net.needRemoveNames[id >> 3] |= (byte)(1 << (id & 0x7));
}