mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-08-20 09:57:10 +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)
|
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);
|
connection->close(DisconnectPacket::eDisconnect_Kicked);
|
||||||
done = true;
|
done = true;
|
||||||
|
|
||||||
|
|
@ -1607,7 +1616,7 @@ void ClientConnection::handleEntityActionAtPosition(shared_ptr<EntityActionAtPos
|
||||||
|
|
||||||
void ClientConnection::handlePreLogin(shared_ptr<PreLoginPacket> packet)
|
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
|
#if 1
|
||||||
// 4J - Check that we can play with all the players already in the game who have Friends-Only UGC set
|
// 4J - Check that we can play with all the players already in the game who have Friends-Only UGC set
|
||||||
BOOL canPlay = TRUE;
|
BOOL canPlay = TRUE;
|
||||||
|
|
@ -2049,8 +2058,11 @@ void ClientConnection::handlePreLogin(shared_ptr<PreLoginPacket> packet)
|
||||||
}
|
}
|
||||||
BOOL allAllowed, friendsAllowed;
|
BOOL allAllowed, friendsAllowed;
|
||||||
ProfileManager.AllowedPlayerCreatedContent(m_userIndex,true,&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),
|
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 ))));
|
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() )
|
if(!g_NetworkManager.IsHost() )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ void PendingConnection::disconnect(DisconnectPacket::eDisconnectReason reason)
|
||||||
{
|
{
|
||||||
// try { // 4J - removed try/catch
|
// try { // 4J - removed try/catch
|
||||||
// logger.info("Disconnecting " + getName() + ": " + reason);
|
// 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 );
|
app.DebugPrintf("Pending connection disconnect: %d\n", reason );
|
||||||
connection->send( shared_ptr<DisconnectPacket>( new DisconnectPacket(reason) ) );
|
connection->send( shared_ptr<DisconnectPacket>( new DisconnectPacket(reason) ) );
|
||||||
connection->sendAndQuit();
|
connection->sendAndQuit();
|
||||||
|
|
@ -139,7 +140,7 @@ void PendingConnection::sendPreLoginResponse()
|
||||||
|
|
||||||
void PendingConnection::handleLogin(shared_ptr<LoginPacket> packet)
|
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;
|
//name = packet->userName;
|
||||||
if (packet->clientVersion != SharedConstants::NETWORK_PROTOCOL_VERSION)
|
if (packet->clientVersion != SharedConstants::NETWORK_PROTOCOL_VERSION)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ class PendingConnection : public PacketListener
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static const int FAKE_LAG = 0;
|
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");
|
// public static Logger logger = Logger.getLogger("Minecraft");
|
||||||
static Random *random;
|
static Random *random;
|
||||||
|
|
|
||||||
|
|
@ -196,7 +196,9 @@ bool Connection::writeTick()
|
||||||
LeaveCriticalSection(&writeLock);
|
LeaveCriticalSection(&writeLock);
|
||||||
|
|
||||||
Packet::writePacket(packet, bufferedDos);
|
Packet::writePacket(packet, bufferedDos);
|
||||||
|
#ifdef __linux__
|
||||||
|
bufferedDos->flush(); // Ensure buffered data reaches socket before any other writes
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef _CONTENT_PACKAGE
|
#ifndef _CONTENT_PACKAGE
|
||||||
// 4J Added for debugging
|
// 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
|
// 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
|
// 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)
|
if(packet->shouldDelay)
|
||||||
{
|
{
|
||||||
Packet::writePacket(packet, byteArrayDos);
|
Packet::writePacket(packet, byteArrayDos);
|
||||||
|
|
@ -245,6 +254,7 @@ bool Connection::writeTick()
|
||||||
{
|
{
|
||||||
Packet::writePacket(packet, bufferedDos);
|
Packet::writePacket(packet, bufferedDos);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef _CONTENT_PACKAGE
|
#ifndef _CONTENT_PACKAGE
|
||||||
// 4J Added for debugging
|
// 4J Added for debugging
|
||||||
|
|
@ -329,9 +339,9 @@ close("disconnect.genericReason", "Internal exception: " + e.toString());
|
||||||
|
|
||||||
void Connection::close(DisconnectPacket::eDisconnectReason reason, ...)
|
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;
|
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;
|
disconnected = true;
|
||||||
|
|
||||||
va_list input;
|
va_list input;
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,12 @@ DisconnectPacket::DisconnectPacket(eDisconnectReason reason)
|
||||||
void DisconnectPacket::read(DataInputStream *dis) //throws IOException
|
void DisconnectPacket::read(DataInputStream *dis) //throws IOException
|
||||||
{
|
{
|
||||||
reason = (eDisconnectReason)dis->readInt();
|
reason = (eDisconnectReason)dis->readInt();
|
||||||
|
fprintf(stderr, "[PKT] DisconnectPacket::read reason=%d\n", reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisconnectPacket::write(DataOutputStream *dos) //throws IOException
|
void DisconnectPacket::write(DataOutputStream *dos) //throws IOException
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "[PKT] DisconnectPacket::write reason=%d\n", reason);
|
||||||
dos->writeInt((int)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?
|
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;
|
int id = 0;
|
||||||
shared_ptr<Packet> packet = nullptr;
|
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()))
|
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();
|
__debugbreak();
|
||||||
assert(false);
|
//assert(false);
|
||||||
|
return nullptr;
|
||||||
// throw new IOException(wstring(L"Bad packet id ") + _toString<int>(id));
|
// 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);
|
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);
|
packet->read(dis);
|
||||||
// }
|
// }
|
||||||
// catch (EOFException e)
|
// catch (EOFException e)
|
||||||
|
|
@ -425,15 +450,13 @@ wstring Packet::readUtf(DataInputStream *dis, int maxLength) // throws IOExcepti
|
||||||
short stringLength = dis->readShort();
|
short stringLength = dis->readShort();
|
||||||
if (stringLength > maxLength)
|
if (stringLength > maxLength)
|
||||||
{
|
{
|
||||||
wstringstream stream;
|
fprintf(stderr, "[PKT] readUtf: string length %d > max %d (stream desync?)\n", stringLength, maxLength);
|
||||||
stream << L"Received string length longer than maximum allowed (" << stringLength << " > " << maxLength << ")";
|
return L"";
|
||||||
assert(false);
|
|
||||||
// throw new IOException( stream.str() );
|
|
||||||
}
|
}
|
||||||
if (stringLength < 0)
|
if (stringLength < 0)
|
||||||
{
|
{
|
||||||
assert(false);
|
fprintf(stderr, "[PKT] readUtf: negative string length %d (stream desync?)\n", stringLength);
|
||||||
// throw new IOException(L"Received string length is less than zero! Weird string!");
|
return L"";
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring builder = L"";
|
wstring builder = L"";
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue