Networking Fixes & Updates

This commit is contained in:
JuiceyDev 2026-03-05 20:03:06 +01:00
parent 44b4ba84c2
commit c391d290ec
6 changed files with 64 additions and 16 deletions

View file

@ -1134,6 +1134,15 @@ void ClientConnection::handleTileUpdate(shared_ptr<TileUpdatePacket> packet)
void ClientConnection::handleDisconnect(shared_ptr<DisconnectPacket> packet)
{
#ifdef __linux__
// Linux fix: On local host connections, ignore DisconnectPacket. The singleplayer internal
// server should never disconnect itself. If we see this, it's likely stream desync reading
// garbage data as a DisconnectPacket.
if (connection && connection->getSocket() && connection->getSocket()->isLocal()) {
fprintf(stderr, "[CONN] Ignoring DisconnectPacket on local connection (reason=%d)\n", packet->reason);
return;
}
#endif
connection->close(DisconnectPacket::eDisconnect_Kicked);
done = true;
@ -1607,7 +1616,7 @@ void ClientConnection::handleEntityActionAtPosition(shared_ptr<EntityActionAtPos
void ClientConnection::handlePreLogin(shared_ptr<PreLoginPacket> packet)
{
// printf("Client: handlePreLogin\n");
fprintf(stderr, "[LOGIN-CLI] handlePreLogin entered, isHost=%d, userIdx=%d\n", (int)g_NetworkManager.IsHost(), m_userIndex);
#if 1
// 4J - Check that we can play with all the players already in the game who have Friends-Only UGC set
BOOL canPlay = TRUE;
@ -2049,8 +2058,11 @@ void ClientConnection::handlePreLogin(shared_ptr<PreLoginPacket> packet)
}
BOOL allAllowed, friendsAllowed;
ProfileManager.AllowedPlayerCreatedContent(m_userIndex,true,&allAllowed,&friendsAllowed);
fprintf(stderr, "[LOGIN] Sending LoginPacket: user=%ls netVer=%d userIdx=%d isHost=%d\n",
minecraft->user->name.c_str(), SharedConstants::NETWORK_PROTOCOL_VERSION, m_userIndex, (int)g_NetworkManager.IsHost());
send( shared_ptr<LoginPacket>( new LoginPacket(minecraft->user->name, SharedConstants::NETWORK_PROTOCOL_VERSION, offlineXUID, onlineXUID, (allAllowed!=TRUE && friendsAllowed==TRUE),
packet->m_ugcPlayersVersion, app.GetPlayerSkinId(m_userIndex), app.GetPlayerCapeId(m_userIndex), ProfileManager.IsGuest( m_userIndex ))));
fprintf(stderr, "[LOGIN] LoginPacket sent successfully\n");
if(!g_NetworkManager.IsHost() )
{

View file

@ -60,6 +60,7 @@ void PendingConnection::disconnect(DisconnectPacket::eDisconnectReason reason)
{
// try { // 4J - removed try/catch
// logger.info("Disconnecting " + getName() + ": " + reason);
fprintf(stderr, "[PENDING] disconnect called with reason=%d at tick=%d\n", reason, _tick);
app.DebugPrintf("Pending connection disconnect: %d\n", reason );
connection->send( shared_ptr<DisconnectPacket>( new DisconnectPacket(reason) ) );
connection->sendAndQuit();
@ -139,7 +140,7 @@ void PendingConnection::sendPreLoginResponse()
void PendingConnection::handleLogin(shared_ptr<LoginPacket> packet)
{
// printf("Server: handleLogin\n");
fprintf(stderr, "[LOGIN-SRV] handleLogin called! clientVersion=%d\n", packet->clientVersion);
//name = packet->userName;
if (packet->clientVersion != SharedConstants::NETWORK_PROTOCOL_VERSION)
{

View file

@ -11,7 +11,7 @@ class PendingConnection : public PacketListener
{
private:
static const int FAKE_LAG = 0;
static const int MAX_TICKS_BEFORE_LOGIN = 20 * 30;
static const int MAX_TICKS_BEFORE_LOGIN = 20 * 30 * 10; // 10 minutes instead of 20 sec for Linux theres just no login yet
// public static Logger logger = Logger.getLogger("Minecraft");
static Random *random;

View file

@ -196,7 +196,9 @@ bool Connection::writeTick()
LeaveCriticalSection(&writeLock);
Packet::writePacket(packet, bufferedDos);
#ifdef __linux__
bufferedDos->flush(); // Ensure buffered data reaches socket before any other writes
#endif
#ifndef _CONTENT_PACKAGE
// 4J Added for debugging
@ -230,6 +232,13 @@ bool Connection::writeTick()
// If the shouldDelay flag is still set at this point then we want to write it to QNet as a single packet with priority flags
// Otherwise just buffer the packet with other outgoing packets as the java game did
#ifdef __linux__
// Linux fix: For local connections, always use bufferedDos to avoid byte interleaving between
// the BufferedOutputStream buffer and direct sos writes. The shouldDelay/writeWithFlags path
// writes directly to sos, which can inject bytes BEFORE unflushed bufferedDos data.
Packet::writePacket(packet, bufferedDos);
bufferedDos->flush(); // Ensure data reaches socket immediately for delayed packets
#else
if(packet->shouldDelay)
{
Packet::writePacket(packet, byteArrayDos);
@ -245,6 +254,7 @@ bool Connection::writeTick()
{
Packet::writePacket(packet, bufferedDos);
}
#endif
#ifndef _CONTENT_PACKAGE
// 4J Added for debugging
@ -329,9 +339,9 @@ close("disconnect.genericReason", "Internal exception: " + e.toString());
void Connection::close(DisconnectPacket::eDisconnectReason reason, ...)
{
// printf("Con:0x%x close\n",this);
fprintf(stderr, "[CONN] close called with reason=%d on connection=%p\n", reason, (void*)this);
if (!running) return;
// printf("Con:0x%x close doing something\n",this);
fprintf(stderr, "[CONN] close proceeding (was running) on connection=%p\n", (void*)this);
disconnected = true;
va_list input;

View file

@ -20,10 +20,12 @@ DisconnectPacket::DisconnectPacket(eDisconnectReason reason)
void DisconnectPacket::read(DataInputStream *dis) //throws IOException
{
reason = (eDisconnectReason)dis->readInt();
fprintf(stderr, "[PKT] DisconnectPacket::read reason=%d\n", reason);
}
void DisconnectPacket::write(DataOutputStream *dos) //throws IOException
{
fprintf(stderr, "[PKT] DisconnectPacket::write reason=%d\n", reason);
dos->writeInt((int)reason);
}

View file

@ -347,6 +347,14 @@ unordered_map<int, Packet::PacketStatistics *> Packet::statistics = unordered_ma
shared_ptr<Packet> Packet::readPacket(DataInputStream *dis, bool isServer) // throws IOException TODO 4J JEV, should this declare a throws?
{
// N packet ID
static int s_clientPktHistory[64];
static int s_clientPktIdx = 0;
static int s_serverPktHistory[64];
static int s_serverPktIdx = 0;
static bool s_clientDesyncLogged = false;
static bool s_serverDesyncLogged = false;
int id = 0;
shared_ptr<Packet> packet = nullptr;
@ -358,16 +366,33 @@ shared_ptr<Packet> Packet::readPacket(DataInputStream *dis, bool isServer) // th
if ((isServer && serverReceivedPackets.find(id) == serverReceivedPackets.end()) || (!isServer && clientReceivedPackets.find(id) == clientReceivedPackets.end()))
{
//app.DebugPrintf("Bad packet id %d\n", id);
int *history = isServer ? s_serverPktHistory : s_clientPktHistory;
int idx = isServer ? s_serverPktIdx : s_clientPktIdx;
bool &logged = isServer ? s_serverDesyncLogged : s_clientDesyncLogged;
fprintf(stderr, "[PKT] Bad packet id %d (0x%x) isServer=%d\n", id, id, isServer);
if (!logged) {
logged = true;
fprintf(stderr, "[PKT] === PACKET HISTORY (last %d, newest last) ===\n", 64);
for (int i = 0; i < 64; i++) {
int h = history[(idx + i) % 64];
if (h != 0) fprintf(stderr, "[PKT] pkt %d (0x%x)\n", h, h);
}
fprintf(stderr, "[PKT] === END HISTORY ===\n");
}
__debugbreak();
assert(false);
//assert(false);
return nullptr;
// throw new IOException(wstring(L"Bad packet id ") + _toString<int>(id));
}
// Record successfully read packet ID
if (isServer) { s_serverPktHistory[s_serverPktIdx % 64] = id; s_serverPktIdx++; }
else { s_clientPktHistory[s_clientPktIdx % 64] = id; s_clientPktIdx++; }
packet = getPacket(id);
if (packet == NULL) assert(false);//throw new IOException(wstring(L"Bad packet id ") + _toString<int>(id));
if (packet == NULL) { fprintf(stderr, "[PKT] getPacket(%d) returned NULL\n", id); return nullptr; }
//app.DebugPrintf("%s reading packet %d\n", isServer ? "Server" : "Client", packet->getId());
packet->read(dis);
// }
// catch (EOFException e)
@ -425,15 +450,13 @@ wstring Packet::readUtf(DataInputStream *dis, int maxLength) // throws IOExcepti
short stringLength = dis->readShort();
if (stringLength > maxLength)
{
wstringstream stream;
stream << L"Received string length longer than maximum allowed (" << stringLength << " > " << maxLength << ")";
assert(false);
// throw new IOException( stream.str() );
fprintf(stderr, "[PKT] readUtf: string length %d > max %d (stream desync?)\n", stringLength, maxLength);
return L"";
}
if (stringLength < 0)
{
assert(false);
// throw new IOException(L"Received string length is less than zero! Weird string!");
fprintf(stderr, "[PKT] readUtf: negative string length %d (stream desync?)\n", stringLength);
return L"";
}
wstring builder = L"";