mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/LCE-Revelations.git
synced 2026-05-23 02:27:29 +00:00
fix: player list no longer limited by render distance
The previous IQNet cleanup in handleRemoveEntity fired on every entity despawn, which happens both when a player goes out of tracking range and when they disconnect. This caused players to vanish from the Tab list whenever they moved beyond render distance. Introduce two custom payload channels (MC|ForkHello, MC|ForkPLeave) so the client can distinguish "out of range" from "actually left": - Server sends MC|ForkHello during login to identify itself as a fork - Server sends MC|ForkPLeave with the player's gamertag on disconnect - Client skips IQNet cleanup in handleRemoveEntity on fork servers - Client cleans up IQNet only when MC|ForkPLeave arrives Fully backwards-compatible: no existing packet wire formats changed. Upstream clients ignore the unknown channels, fork clients on upstream servers fall back to the old entity-tracking-based cleanup.
This commit is contained in:
@@ -135,6 +135,7 @@ ClientConnection::ClientConnection(Minecraft *minecraft, Socket *socket, int iUs
|
||||
started = false;
|
||||
savedDataStorage = new SavedDataStorage(nullptr);
|
||||
maxPlayers = 20;
|
||||
m_isForkServer = false;
|
||||
|
||||
this->minecraft = minecraft;
|
||||
|
||||
@@ -1141,7 +1142,11 @@ void ClientConnection::handleMoveEntitySmall(shared_ptr<MoveEntityPacketSmall> p
|
||||
void ClientConnection::handleRemoveEntity(shared_ptr<RemoveEntitiesPacket> packet)
|
||||
{
|
||||
#ifdef _WINDOWS64
|
||||
if (!g_NetworkManager.IsHost())
|
||||
// On fork servers, IQNet cleanup is handled by the MC|ForkPLeave custom
|
||||
// payload so players stay in Tab regardless of render distance. On
|
||||
// upstream servers (no MC|ForkHello received), fall back to the old
|
||||
// behaviour of cleaning up IQNet here.
|
||||
if (!m_isForkServer && !g_NetworkManager.IsHost())
|
||||
{
|
||||
for (int i = 0; i < packet->ids.length; i++)
|
||||
{
|
||||
@@ -1151,7 +1156,6 @@ void ClientConnection::handleRemoveEntity(shared_ptr<RemoveEntitiesPacket> packe
|
||||
shared_ptr<Player> player = dynamic_pointer_cast<Player>(entity);
|
||||
if (player != nullptr)
|
||||
{
|
||||
// Match by gamertag in the IQNet array (XUID may be 0 on dedicated servers)
|
||||
for (int s = 1; s < MINECRAFT_NET_MAX_PLAYERS; ++s)
|
||||
{
|
||||
IQNetPlayer* qp = &IQNet::m_player[s];
|
||||
@@ -3900,6 +3904,44 @@ void ClientConnection::handleCustomPayload(shared_ptr<CustomPayloadPacket> custo
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Fork server identification: enables render-distance-independent player list
|
||||
if (CustomPayloadPacket::FORK_HELLO_CHANNEL.compare(customPayloadPacket->identifier) == 0)
|
||||
{
|
||||
m_isForkServer = true;
|
||||
app.DebugPrintf("Client: Connected to fork server\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Fork server player leave: clean up IQNet slot so player leaves Tab list
|
||||
if (CustomPayloadPacket::FORK_PLAYER_LEAVE_CHANNEL.compare(customPayloadPacket->identifier) == 0)
|
||||
{
|
||||
if (customPayloadPacket->data.data != nullptr && customPayloadPacket->length > 0)
|
||||
{
|
||||
int nameLen = customPayloadPacket->length / static_cast<int>(sizeof(wchar_t));
|
||||
wstring leavingName(reinterpret_cast<const wchar_t*>(customPayloadPacket->data.data), nameLen);
|
||||
|
||||
for (int s = 1; s < MINECRAFT_NET_MAX_PLAYERS; ++s)
|
||||
{
|
||||
IQNetPlayer* qp = &IQNet::m_player[s];
|
||||
if (qp->GetCustomDataValue() != 0 &&
|
||||
_wcsicmp(qp->m_gamertag, leavingName.c_str()) == 0)
|
||||
{
|
||||
extern CPlatformNetworkManagerStub* g_pPlatformNetworkManager;
|
||||
g_pPlatformNetworkManager->NotifyPlayerLeaving(qp);
|
||||
qp->m_smallId = 0;
|
||||
qp->m_isRemote = false;
|
||||
qp->m_isHostPlayer = false;
|
||||
qp->m_resolvedXuid = INVALID_XUID;
|
||||
qp->m_gamertag[0] = 0;
|
||||
qp->SetCustomDataValue(0);
|
||||
app.DebugPrintf("Client: Player \"%ls\" left fork server, cleared IQNet slot %d\n", leavingName.c_str(), s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (CustomPayloadPacket::TRADER_LIST_PACKET.compare(customPayloadPacket->identifier) == 0)
|
||||
|
||||
Reference in New Issue
Block a user