mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-05-17 04:12:53 +00:00
Networking Fixes & Updates
This commit is contained in:
parent
44b4ba84c2
commit
c391d290ec
|
|
@ -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() )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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"";
|
||||
|
|
|
|||
Loading…
Reference in a new issue