From d7510b1d0569b55d61df1d1643db543773b66db2 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Wed, 26 Apr 2023 02:11:55 +0530 Subject: [PATCH 01/46] Start --- engine/source/game/net/serverQuery.cpp | 25 +++++++++++++++++++++++++ engine/source/sim/netInterface.cpp | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index e22f8d71..9d2f5225 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -2064,6 +2064,31 @@ static void handleMasterServerArrangedConnectResponse(BitStream* stream, U32 /*k { Con::printf("Received arranged connect response from the master server."); + Vector possibleAddresses; + + U8 possibleAddressCount; + stream->read(&possibleAddressCount); + for (int i = 0; i < possibleAddressCount; i++) { + U8 ipbits[4]; + U16 port; + stream->read(&ipbits[0]); + stream->read(&ipbits[1]); + stream->read(&ipbits[2]); + stream->read(&ipbits[3]); + stream->read(&port); + NetAddress* addr = new NetAddress(); + addr->port = port; + addr->netNum[0] = ipbits[0]; + addr->netNum[1] = ipbits[1]; + addr->netNum[2] = ipbits[2]; + addr->netNum[3] = ipbits[3]; + possibleAddresses.push_back(addr); + } + + GameConnection* conn = new GameConnection(); + conn->connectArranged(possibleAddresses, false); + + // TODO: If not hosting then reject the connection // TODO: Implement arranged connection diff --git a/engine/source/sim/netInterface.cpp b/engine/source/sim/netInterface.cpp index 1f67354a..f31589ce 100644 --- a/engine/source/sim/netInterface.cpp +++ b/engine/source/sim/netInterface.cpp @@ -638,7 +638,7 @@ void NetInterface::sendArrangedConnectRequest(NetConnection *conn) // } out->writeFlag(theParams.mDebugObjectSizes); //out->write(conn->getInitialSendSequence()); - out->write(conn->getSequence()); + //out->write(conn->getSequence()); conn->writeConnectRequest(out); // if(innerEncryptPos) From edeabe7b4a89a5964f7d14670eeaba2d70068c04 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Wed, 26 Apr 2023 21:58:56 +0530 Subject: [PATCH 02/46] make connecting actually work? --- engine/source/game/gameConnection.cpp | 12 +- engine/source/game/net/serverQuery.cpp | 64 ++++++-- engine/source/sim/netInterface.cpp | 196 +++++++------------------ engine/source/sim/netInterface.h | 8 +- 4 files changed, 114 insertions(+), 166 deletions(-) diff --git a/engine/source/game/gameConnection.cpp b/engine/source/game/gameConnection.cpp index 14524b1c..f39d221f 100644 --- a/engine/source/game/gameConnection.cpp +++ b/engine/source/game/gameConnection.cpp @@ -149,8 +149,10 @@ void GameConnection::onConnectionEstablished(bool isInitiator) { setGhostFrom(false); setGhostTo(true); - setSendingEvents(true); - setTranslatesStrings(true); + if (!isEstablished()) { + setSendingEvents(true); + setTranslatesStrings(true); + } setIsConnectionToServer(); mServerConnection = this; Con::printf("Connection established %d", getId()); @@ -160,8 +162,10 @@ void GameConnection::onConnectionEstablished(bool isInitiator) { setGhostFrom(true); setGhostTo(false); - setSendingEvents(true); - setTranslatesStrings(true); + if (!isEstablished()) { + setSendingEvents(true); + setTranslatesStrings(true); + } Sim::getClientGroup()->addObject(this); mTotalServerTicks = ServerTicksUninitialized; diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 9d2f5225..3fb136b6 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -536,7 +536,7 @@ static void sendMasterArrangedConnectRequest(NetAddress* address) // Send a request to the master server to set up an arranged connection: BitStream* out = BitStream::getPacketStream(); - out->write(U8(NetInterface::MasterServerArrangedConnectRequest)); + out->write(U8(NetInterface::MasterServerRequestArrangedConnection)); //char addr[256]; //Net::addressToString(address, addr); @@ -552,14 +552,17 @@ static void sendMasterArrangedConnectRequest(NetAddress* address) } } -ConsoleFunction(arrangeConnection, void, 2, 2, "arrangeConnection(ip);") +NetConnection* arrangeNetConnection = NULL; + +ConsoleMethod(NetConnection, arrangeConnection, void, 3, 3, "NetConnection.arrangeConnection(ip);") { + arrangeNetConnection = object; argc; NetAddress addr; char* addrText; - addrText = dStrdup(argv[1]); + addrText = dStrdup(argv[2]); Net::stringToAddress(addrText, &addr); sendMasterArrangedConnectRequest(&addr); @@ -2060,12 +2063,14 @@ static void handleGameInfoResponse(const NetAddress* address, BitStream* stream, } #ifdef TORQUE_NET_HOLEPUNCHING -static void handleMasterServerArrangedConnectResponse(BitStream* stream, U32 /*key*/, U8 /*flags*/) +static void handleMasterServerClientRequestedArrangedConnection(const NetAddress* address, BitStream* stream, U32 /*key*/, U8 /*flags*/) { - Con::printf("Received arranged connect response from the master server."); - + Con::printf("Received MasterServerClientRequestedArrangedConnection"); Vector possibleAddresses; + U16 clientId; + stream->read(&clientId); + U8 possibleAddressCount; stream->read(&possibleAddressCount); for (int i = 0; i < possibleAddressCount; i++) { @@ -2085,9 +2090,16 @@ static void handleMasterServerArrangedConnectResponse(BitStream* stream, U32 /*k possibleAddresses.push_back(addr); } - GameConnection* conn = new GameConnection(); - conn->connectArranged(possibleAddresses, false); - + BitStream* out = BitStream::getPacketStream(); + out->write(U8(NetInterface::MasterServerAcceptArrangedConnection)); + out->write(clientId); + BitStream::sendPacketStream(address); + + // Do connectArranged to client + NetConnection* conn = dynamic_cast(Sim::findObject("ServerConnection")); + if (conn != NULL) { + conn->connectArranged(possibleAddresses, false); + } // TODO: If not hosting then reject the connection @@ -2131,10 +2143,34 @@ static void handleMasterServerArrangedConnectResponse(BitStream* stream, U32 /*k }*/ } -static void handleMasterServerAcceptArrangedConnectResponse(BitStream* stream, U32 /*key*/, U8 /*flags*/) +static void handleMasterServerArrangedConnectionAccepted(const NetAddress* address, BitStream* stream, U32 /*key*/, U8 /*flags*/) { + Vector possibleAddresses; + Con::printf("Received accept arranged connect response from the master server."); + U8 possibleAddressCount; + stream->read(&possibleAddressCount); + for (int i = 0; i < possibleAddressCount; i++) { + U8 ipbits[4]; + U16 port; + stream->read(&ipbits[0]); + stream->read(&ipbits[1]); + stream->read(&ipbits[2]); + stream->read(&ipbits[3]); + stream->read(&port); + NetAddress* addr = new NetAddress(); + addr->port = port; + addr->netNum[0] = ipbits[0]; + addr->netNum[1] = ipbits[1]; + addr->netNum[2] = ipbits[2]; + addr->netNum[3] = ipbits[3]; + possibleAddresses.push_back(addr); + } + + // Do connectArranged to server + arrangeNetConnection->connectArranged(possibleAddresses, true); + // TODO: Implement accepted arranged connection /*if(!gIsServer && requestId == mCurrentQueryId && connectionData->getBufferSize() >= Nonce::NonceSize * 2 + SymmetricCipher::KeySize * 2) @@ -2219,11 +2255,11 @@ void DemoNetInterface::handleInfoPacket(const NetAddress* address, U8 packetType break; #ifdef TORQUE_NET_HOLEPUNCHING - case MasterServerArrangedConnectResponse: - handleMasterServerArrangedConnectResponse(stream, key, flags); + case MasterServerClientRequestedArrangedConnection: + handleMasterServerClientRequestedArrangedConnection(address, stream, key, flags); break; - case MasterServerAcceptArrangedConnectResponse: - handleMasterServerAcceptArrangedConnectResponse(stream, key, flags); + case MasterServerArrangedConnectionAccepted: + handleMasterServerArrangedConnectionAccepted(address, stream, key, flags); break; case MasterServerRejectArrangedConnectResponse: handleMasterServerRejectArrangedConnectResponse(stream, key, flags); diff --git a/engine/source/sim/netInterface.cpp b/engine/source/sim/netInterface.cpp index f31589ce..f02168a8 100644 --- a/engine/source/sim/netInterface.cpp +++ b/engine/source/sim/netInterface.cpp @@ -96,7 +96,7 @@ void NetInterface::processPacketReceiveEvent(PacketReceiveEvent* prEvent) pStream.read(&packetType); NetAddress* addr = &prEvent->sourceAddress; - if (packetType <= GameHeartbeat) + if (packetType <= GameHeartbeat || packetType >= MasterServerRequestArrangedConnection) handleInfoPacket(addr, packetType, &pStream); #ifdef GGC_PLUGIN else if (packetType == GGCPacket) @@ -449,38 +449,9 @@ void NetInterface::sendPunchPackets(NetConnection *conn) //PacketStream out; out->write(U8(Punch)); - //if(theParams.mIsInitiator) - // theParams.mNonce.write(&out); - //else - // theParams.mServerNonce.write(&out); - - //U32 encryptPos = out.getBytePosition(); - //out->setBytePosition(encryptPos); - - //if(theParams.mIsInitiator) - // theParams.mServerNonce.write(&out); - //else - //{ - // theParams.mNonce.write(&out); -// if(out->writeFlag(mRequiresKeyExchange || (theParams.mRequestKeyExchange && !mPrivateKey.isNull()))) -// { -// if(out->writeFlag(theParams.mRequestCertificate && !mCertificate.isNull())) -// out->write(mCertificate); -// else -// out->write(mPrivateKey->getPublicKey()); -// } - //} - //SymmetricCipher theCipher(theParams.mArrangedSecret); - //out->hashAndEncrypt(NetConnection::MessageSignatureBytes, encryptPos, &theCipher); - for(S32 i = 0; i < theParams.mPossibleAddresses.size(); i++) { BitStream::sendPacketStream(theParams.mPossibleAddresses[i]); - -// TNLLogMessageV(LogNetInterface, ("Sending punch packet (%s, %s) to %s", -// ByteBuffer(theParams.mNonce.data, Nonce::NonceSize).encodeBase64()->getBuffer(), -// ByteBuffer(theParams.mServerNonce.data, Nonce::NonceSize).encodeBase64()->getBuffer(), -// theParams.mPossibleAddresses[i].toString())); } conn->mConnectSendCount++; conn->mConnectLastSendTime = Platform::getVirtualMilliseconds(); //getCurrentTime(); @@ -493,13 +464,6 @@ void NetInterface::handlePunch(const NetAddress* theAddress, BitStream *stream) S32 i, j; NetConnection *conn; - //Nonce firstNonce; - //firstNonce.read(stream); - - //ByteBuffer b(firstNonce.data, Nonce::NonceSize); - - //TNLLogMessageV(LogNetInterface, ("Received punch packet from %s - %s", theAddress.toString(), b.encodeBase64()->getBuffer())); - //Con::printf("Received punch packet from %d.%d.%d.%d:%d", theAddress->netNum[0], theAddress->netNum[1], theAddress->netNum[2], theAddress->netNum[3], theAddress->port); char addr[256]; Net::addressToString(theAddress, addr); Con::printf("Received punch packet from %s", addr); @@ -512,10 +476,6 @@ void NetInterface::handlePunch(const NetAddress* theAddress, BitStream *stream) if(conn->getConnectionState() != NetConnection::SendingPunchPackets) continue; -// if((theParams.mIsInitiator && firstNonce != theParams.mServerNonce) || -// (!theParams.mIsInitiator && firstNonce != theParams.mNonce)) -// continue; - // first see if the address is in the possible addresses list: for(j = 0; j < theParams.mPossibleAddresses.size(); j++) @@ -560,46 +520,8 @@ void NetInterface::handlePunch(const NetAddress* theAddress, BitStream *stream) return; ConnectionParameters &theParams = conn->getConnectionParameters(); -// SymmetricCipher theCipher(theParams.mArrangedSecret); -// if(!stream->decryptAndCheckHash(NetConnection::MessageSignatureBytes, stream->getBytePosition(), &theCipher)) -// return; -// -// Nonce nextNonce; -// nextNonce.read(stream); -// -// if(nextNonce != theParams.mNonce) -// return; - // see if the connection needs to be authenticated or uses key exchange -// if(stream->readFlag()) -// { -// if(stream->readFlag()) -// { -// theParams.mCertificate = new Certificate(stream); -// if(!theParams.mCertificate->isValid() || !conn->validateCertficate(theParams.mCertificate, true)) -// return; -// theParams.mPublicKey = theParams.mCertificate->getPublicKey(); -// } -// else -// { -// theParams.mPublicKey = new AsymmetricKey(stream); -// if(!theParams.mPublicKey->isValid() || !conn->validatePublicKey(theParams.mPublicKey, true)) -// return; -// } -// if(mPrivateKey.isNull() || mPrivateKey->getKeySize() != theParams.mPublicKey->getKeySize()) -// { -// // we don't have a private key, so generate one for this connection -// theParams.mPrivateKey = new AsymmetricKey(theParams.mPublicKey->getKeySize()); -// } -// else -// theParams.mPrivateKey = mPrivateKey; -// theParams.mSharedSecret = theParams.mPrivateKey->computeSharedSecretKey(theParams.mPublicKey); -// //logprintf("shared secret (client) %s", theParams.mSharedSecret->encodeBase64()->getBuffer()); -// Random::read(theParams.mSymmetricKey, SymmetricCipher::KeySize); -// theParams.mUsingCrypto = true; -// } conn->setNetAddress(theAddress); - //TNLLogMessageV(LogNetInterface, ("Punch from %s matched nonces - connecting...", theAddress.toString())); Con::printf("Punch from %s matched nonces - connecting...", addr); conn->setConnectionState(NetConnection::AwaitingConnectResponse); @@ -613,41 +535,14 @@ void NetInterface::sendArrangedConnectRequest(NetConnection *conn) { // TODO: The following code is from OpenTNL, it needs to be updated to work with Torque/OpenMBU - //TNLLogMessageV(LogNetInterface, ("Sending Arranged Connect Request")); Con::printf("Sending Arranged Connect Request"); BitStream* out = BitStream::getPacketStream(); - //PacketStream out; ConnectionParameters &theParams = conn->getConnectionParameters(); out->write(U8(ArrangedConnectRequest)); out->write(conn->getSequence()); - //theParams.mNonce.write(&out); - //U32 encryptPos = out.getBytePosition(); - //U32 innerEncryptPos = 0; - - //out.setBytePosition(encryptPos); - - //theParams.mServerNonce.write(&out); -// if(out.writeFlag(theParams.mUsingCrypto)) -// { -// out.write(theParams.mPrivateKey->getPublicKey()); -// innerEncryptPos = out.getBytePosition(); -// out.setBytePosition(innerEncryptPos); -// out.write(SymmetricCipher::KeySize, theParams.mSymmetricKey); -// } out->writeFlag(theParams.mDebugObjectSizes); - //out->write(conn->getInitialSendSequence()); - //out->write(conn->getSequence()); - conn->writeConnectRequest(out); - -// if(innerEncryptPos) -// { -// SymmetricCipher theCipher(theParams.mSharedSecret); -// out.hashAndEncrypt(NetConnection::MessageSignatureBytes, innerEncryptPos, &theCipher); -// } -// SymmetricCipher theCipher(theParams.mArrangedSecret); -// out.hashAndEncrypt(NetConnection::MessageSignatureBytes, encryptPos, &theCipher); conn->mConnectSendCount++; conn->mConnectLastSendTime = Platform::getVirtualMilliseconds();//getCurrentTime(); @@ -667,27 +562,11 @@ void NetInterface::handleArrangedConnectRequest(const NetAddress* theAddress, Bi U32 connectSequence; stream->read(&connectSequence); - // see if the connection is in the main connection table. - // If the connection is in the connection table and it has - // the same initiatorSequence, we'll just resend the connect - // acceptance packet, assuming that the last time we sent it - // it was dropped. - //NetConnection *oldConnection = findConnection(theAddress); - NetConnection* connect = NetConnection::lookup(theAddress); - if (connect && connect->getSequence() == connectSequence) - { - sendConnectAccept(connect); - return; - } - for(i = 0; i < mPendingConnections.size(); i++) { conn = mPendingConnections[i]; ConnectionParameters &theParams = conn->getConnectionParameters(); - if(conn->getConnectionState() != NetConnection::SendingPunchPackets || theParams.mIsInitiator) - continue; - //if(nonce != theParams.mNonce) // continue; @@ -737,35 +616,51 @@ void NetInterface::handleArrangedConnectRequest(const NetAddress* theAddress, Bi //stream->read(&connectSequence); //TNLLogMessageV(LogNetInterface, ("Received Arranged Connect Request")); Con::printf("Received Arranged Connect Request"); + conn->setConnectionState(NetConnection::Connected); - if(connect) + if (theParams.mIsInitiator) { + removePendingConnection(conn); + conn->connect(theAddress); + } + else { - //connect->disconnect(NetConnection::ReasonSelfDisconnect, ""); + // Send connect request to *client* + BitStream* out = BitStream::getPacketStream(); - connect->onDisconnect("SelfDisconnect"); - connect->deleteObject(); + out->write(U8(ArrangedConnectRequest)); + out->write(conn->getSequence()); + + BitStream::sendPacketStream(theAddress); } - conn->setNetAddress(theAddress); - //conn->setInitialRecvSequence(connectSequence); + //if(connect) + //{ + // //connect->disconnect(NetConnection::ReasonSelfDisconnect, ""); - conn->setConnectSequence(connectSequence); - //if(theParams.mUsingCrypto) - // conn->setSymmetricCipher(new SymmetricCipher(theParams.mSymmetricKey, theParams.mInitVector)); + // connect->onDisconnect("SelfDisconnect"); + // connect->deleteObject(); + //} - const char *errorString = NULL; - if(!conn->readConnectRequest(stream, &errorString)) - { - //sendConnectReject(&theParams, theAddress);//, errorString); - sendConnectReject(conn, errorString); - removePendingConnection(conn); - return; - } - //addConnection(conn); - removePendingConnection(conn); - conn->setConnectionState(NetConnection::Connected); - conn->onConnectionEstablished(theParams.mIsInitiator); - sendConnectAccept(conn); + //conn->setNetAddress(theAddress); + ////conn->setInitialRecvSequence(connectSequence); + + //conn->setConnectSequence(connectSequence); + ////if(theParams.mUsingCrypto) + //// conn->setSymmetricCipher(new SymmetricCipher(theParams.mSymmetricKey, theParams.mInitVector)); + + //const char *errorString = NULL; + //if(!conn->readConnectRequest(stream, &errorString)) + //{ + // //sendConnectReject(&theParams, theAddress);//, errorString); + // sendConnectReject(conn, errorString); + // removePendingConnection(conn); + // return; + //} + ////addConnection(conn); + //removePendingConnection(conn); + //conn->setConnectionState(NetConnection::Connected); + //conn->onConnectionEstablished(theParams.mIsInitiator); + //sendConnectAccept(conn); } #endif // TORQUE_NET_HOLEPUNCHING @@ -865,6 +760,19 @@ void NetInterface::checkTimeouts() else sendConnectRequest(pending); } + else if (pending->getConnectionState() == NetConnection::SendingPunchPackets && + time > pending->mConnectLastSendTime + ConnectRetryTime) + { + if (pending->mConnectSendCount > ConnectRetryCount) + { + pending->onConnectTimedOut(); + removePendingConnection(pending); + pending->deleteObject(); + continue; + } + else + sendPunchPackets(pending); + } i++; } mLastTimeoutCheckTime = time; diff --git a/engine/source/sim/netInterface.h b/engine/source/sim/netInterface.h index 09f89308..5307eecf 100644 --- a/engine/source/sim/netInterface.h +++ b/engine/source/sim/netInterface.h @@ -38,10 +38,10 @@ class NetInterface Punch = 40, ArrangedConnectRequest = 42, - MasterServerArrangedConnectRequest = 46, - MasterServerArrangedConnectResponse = 48, - MasterServerAcceptArrangedConnectRequest = 50, - MasterServerAcceptArrangedConnectResponse = 52, + MasterServerRequestArrangedConnection = 46, + MasterServerClientRequestedArrangedConnection = 48, + MasterServerAcceptArrangedConnection = 50, + MasterServerArrangedConnectionAccepted = 52, MasterServerRejectArrangedConnectRequest = 54, MasterServerRejectArrangedConnectResponse = 56, #endif // TORQUE_NET_HOLEPUNCHING From f868ba17b3032145cd435aa26b9ba21060e562bd Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Wed, 26 Apr 2023 21:59:38 +0530 Subject: [PATCH 03/46] Temporarily change it to use arrangeConnection --- game/marble/client/init.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/game/marble/client/init.cs b/game/marble/client/init.cs index f5d97c93..19b4c662 100644 --- a/game/marble/client/init.cs +++ b/game/marble/client/init.cs @@ -471,6 +471,7 @@ function connectManual(%address, %invited) // connect to a server. if address is empty a local connect is assumed function connectToServer(%address,%invited) { + echo("CONNECT TO SERVER" SPC %address SPC %invited); if (isObject(ServerConnection)) ServerConnection.delete(); @@ -509,7 +510,8 @@ function connectToServer(%address,%invited) } $Client::connectedMultiplayer = true; $Game::SPGemHunt = false; - %conn.connect(%address); + echo("CONNECT ARRANGED??"); + %conn.arrangeConnection(%address); } clearClientGracePeroid(); @@ -546,6 +548,7 @@ function connectToPreviewServer() // connect to a server. if address is empty a local connect is assumed function establishConnection(%address, %mp, %invited) { + echo("ESTABLISH CONNECTION" SPC %address SPC %mp SPC %invited); if (isObject(ServerConnection)) ServerConnection.delete(); @@ -588,7 +591,7 @@ function establishConnection(%address, %mp, %invited) } $Client::connectedMultiplayer = true; $Game::SPGemHunt = false; - %conn.connect(%address); + %conn.arrangeConnection(%address); } clearClientGracePeroid(); From 528f65b94c8c543adc3aec8bb7297271a2300cd9 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Thu, 27 Apr 2023 01:51:55 +0530 Subject: [PATCH 04/46] Handle rejection --- engine/source/game/net/serverQuery.cpp | 14 +++++++++++--- engine/source/sim/netInterface.cpp | 10 ++++++++-- engine/source/sim/netInterface.h | 4 ++-- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 3fb136b6..b95ba3f1 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -2198,10 +2198,18 @@ static void handleMasterServerArrangedConnectionAccepted(const NetAddress* addre }*/ } -static void handleMasterServerRejectArrangedConnectResponse(BitStream* stream, U32 /*key*/, U8 /*flags*/) +static void handleMasterServerArrangedConnectionRejected(const NetAddress* address, BitStream* stream, U32 /*key*/, U8 /*flags*/) { Con::printf("Received reject arranged connect response from the master server."); + U8 reason; + stream->read(&reason); + + // Reject?? + if (reason == 0) + arrangeNetConnection->onConnectionRejected("No such server"); + if (reason == 1) + arrangeNetConnection->onConnectionRejected("Server rejected"); // TODO: Implement rejected arranged connection /*if(!gIsServer && requestId == mCurrentQueryId) @@ -2261,8 +2269,8 @@ void DemoNetInterface::handleInfoPacket(const NetAddress* address, U8 packetType case MasterServerArrangedConnectionAccepted: handleMasterServerArrangedConnectionAccepted(address, stream, key, flags); break; - case MasterServerRejectArrangedConnectResponse: - handleMasterServerRejectArrangedConnectResponse(stream, key, flags); + case MasterServerArrangedConnectionRejected: + handleMasterServerArrangedConnectionRejected(address, stream, key, flags); break; #endif } diff --git a/engine/source/sim/netInterface.cpp b/engine/source/sim/netInterface.cpp index f02168a8..02af9f65 100644 --- a/engine/source/sim/netInterface.cpp +++ b/engine/source/sim/netInterface.cpp @@ -765,9 +765,15 @@ void NetInterface::checkTimeouts() { if (pending->mConnectSendCount > ConnectRetryCount) { - pending->onConnectTimedOut(); + if (pending->mConnectionParameters.mIsInitiator) { + pending->onConnectTimedOut(); + pending->deleteObject(); + } + else + { + pending->setConnectionState(NetConnection::NotConnected); + } removePendingConnection(pending); - pending->deleteObject(); continue; } else diff --git a/engine/source/sim/netInterface.h b/engine/source/sim/netInterface.h index 5307eecf..98dd370a 100644 --- a/engine/source/sim/netInterface.h +++ b/engine/source/sim/netInterface.h @@ -42,8 +42,8 @@ class NetInterface MasterServerClientRequestedArrangedConnection = 48, MasterServerAcceptArrangedConnection = 50, MasterServerArrangedConnectionAccepted = 52, - MasterServerRejectArrangedConnectRequest = 54, - MasterServerRejectArrangedConnectResponse = 56, + MasterServerRejectArrangedConnection = 54, + MasterServerArrangedConnectionRejected = 56, #endif // TORQUE_NET_HOLEPUNCHING }; protected: From ba9266c67406202fc633de5ed4dba7ca7a47c290 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Fri, 28 Apr 2023 00:53:04 +0530 Subject: [PATCH 05/46] Relay pings and infos --- engine/source/game/net/serverQuery.cpp | 66 ++++++++++++++++++++++++++ engine/source/sim/netInterface.h | 4 ++ 2 files changed, 70 insertions(+) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index b95ba3f1..029eaee1 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -1288,6 +1288,19 @@ static void processPingsAndQueries(U32 session, bool schedule) else Con::printf("Pinging Server %s (%d)...", addressString, p.tryCount); sendPacket(NetInterface::GamePingRequest, &p.address, p.key, p.session, flags); + + BitStream* out = BitStream::getPacketStream(); + out->write(U8(NetInterface::MasterServerGamePingRequest)); + out->write(p.address.netNum[0]); + out->write(p.address.netNum[1]); + out->write(p.address.netNum[2]); + out->write(p.address.netNum[3]); + out->write(p.key); + out->write(p.session); + out->write(flags); + for (int i = 0; i < gMasterServerList.size(); i++) + BitStream::sendPacketStream(&gMasterServerList[i].address); + i++; } } @@ -1328,6 +1341,19 @@ static void processPingsAndQueries(U32 session, bool schedule) Con::printf("Querying Server %s (%d)...", addressString, p.tryCount); sendPacket(NetInterface::GameInfoRequest, &p.address, p.key, p.session, flags); + + BitStream* out = BitStream::getPacketStream(); + out->write(U8(NetInterface::MasterServerGameInfoRequest)); + out->write(p.address.netNum[0]); + out->write(p.address.netNum[1]); + out->write(p.address.netNum[2]); + out->write(p.address.netNum[3]); + out->write(p.key); + out->write(p.session); + out->write(flags); + for (int i = 0; i < gMasterServerList.size(); i++) + BitStream::sendPacketStream(&gMasterServerList[i].address); + if (!si->isQuerying()) { si->status |= ServerInfo::Status_Querying; @@ -2219,6 +2245,40 @@ static void handleMasterServerArrangedConnectionRejected(const NetAddress* addre startGameTypesQuery(); }*/ } + +static void handleMasterServerGamePingResponse(const NetAddress* address, BitStream* stream) { + NetAddress theAddress; + stream->read(&theAddress.netNum[0]); + stream->read(&theAddress.netNum[1]); + stream->read(&theAddress.netNum[2]); + stream->read(&theAddress.netNum[3]); + stream->read(&theAddress.port); + U8 cmd; + stream->read(&cmd); + U8 flags; + U32 key; + + stream->read(&flags); + stream->read(&key); + handleGamePingResponse(&theAddress, stream, key, flags); +} + +static void handleMasterServerGameInfoResponse(const NetAddress* address, BitStream* stream) { + NetAddress theAddress; + stream->read(&theAddress.netNum[0]); + stream->read(&theAddress.netNum[1]); + stream->read(&theAddress.netNum[2]); + stream->read(&theAddress.netNum[3]); + stream->read(&theAddress.port); + U8 cmd; + stream->read(&cmd); + U8 flags; + U32 key; + + stream->read(&flags); + stream->read(&key); + handleGameInfoResponse(&theAddress, stream, key, flags); +} #endif //----------------------------------------------------------------------------- @@ -2272,6 +2332,12 @@ void DemoNetInterface::handleInfoPacket(const NetAddress* address, U8 packetType case MasterServerArrangedConnectionRejected: handleMasterServerArrangedConnectionRejected(address, stream, key, flags); break; + case MasterServerGamePingResponse: + handleMasterServerGamePingResponse(address, stream); + break; + case MasterServerGameInfoResponse: + handleMasterServerGameInfoResponse(address, stream); + break; #endif } } diff --git a/engine/source/sim/netInterface.h b/engine/source/sim/netInterface.h index 98dd370a..5c6c3932 100644 --- a/engine/source/sim/netInterface.h +++ b/engine/source/sim/netInterface.h @@ -44,6 +44,10 @@ class NetInterface MasterServerArrangedConnectionAccepted = 52, MasterServerRejectArrangedConnection = 54, MasterServerArrangedConnectionRejected = 56, + MasterServerGamePingRequest = 58, + MasterServerGamePingResponse = 60, + MasterServerGameInfoRequest = 62, + MasterServerGameInfoResponse = 64 #endif // TORQUE_NET_HOLEPUNCHING }; protected: From 5bbfd7dfa25bf585160a4d429051a504511e4fa2 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Fri, 28 Apr 2023 01:27:43 +0530 Subject: [PATCH 06/46] ...Fix this --- engine/source/game/net/serverQuery.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 029eaee1..f7e84026 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -1295,9 +1295,8 @@ static void processPingsAndQueries(U32 session, bool schedule) out->write(p.address.netNum[1]); out->write(p.address.netNum[2]); out->write(p.address.netNum[3]); - out->write(p.key); - out->write(p.session); out->write(flags); + out->write((p.session << 16) | (p.key & 0xFFFF)); for (int i = 0; i < gMasterServerList.size(); i++) BitStream::sendPacketStream(&gMasterServerList[i].address); @@ -1348,9 +1347,9 @@ static void processPingsAndQueries(U32 session, bool schedule) out->write(p.address.netNum[1]); out->write(p.address.netNum[2]); out->write(p.address.netNum[3]); - out->write(p.key); - out->write(p.session); out->write(flags); + out->write((p.session << 16) | (p.key & 0xFFFF)); + for (int i = 0; i < gMasterServerList.size(); i++) BitStream::sendPacketStream(&gMasterServerList[i].address); From a4e026b0ccaa3244a936cd7561dd9b8b52d1be0b Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Fri, 28 Apr 2023 01:59:43 +0530 Subject: [PATCH 07/46] Make relay thing work --- engine/source/game/net/serverQuery.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index f7e84026..5e4bdbb8 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -2247,6 +2247,7 @@ static void handleMasterServerArrangedConnectionRejected(const NetAddress* addre static void handleMasterServerGamePingResponse(const NetAddress* address, BitStream* stream) { NetAddress theAddress; + theAddress.type = 0; stream->read(&theAddress.netNum[0]); stream->read(&theAddress.netNum[1]); stream->read(&theAddress.netNum[2]); @@ -2264,6 +2265,7 @@ static void handleMasterServerGamePingResponse(const NetAddress* address, BitStr static void handleMasterServerGameInfoResponse(const NetAddress* address, BitStream* stream) { NetAddress theAddress; + theAddress.type = 0; stream->read(&theAddress.netNum[0]); stream->read(&theAddress.netNum[1]); stream->read(&theAddress.netNum[2]); From a23713c73ea97569ec577f2471cc76b0de481b14 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Fri, 28 Apr 2023 13:01:00 +0530 Subject: [PATCH 08/46] Don't relay when LAN --- engine/source/game/net/serverQuery.cpp | 46 ++++++++++++++------------ 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 5e4bdbb8..1528a171 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -1289,16 +1289,18 @@ static void processPingsAndQueries(U32 session, bool schedule) Con::printf("Pinging Server %s (%d)...", addressString, p.tryCount); sendPacket(NetInterface::GamePingRequest, &p.address, p.key, p.session, flags); - BitStream* out = BitStream::getPacketStream(); - out->write(U8(NetInterface::MasterServerGamePingRequest)); - out->write(p.address.netNum[0]); - out->write(p.address.netNum[1]); - out->write(p.address.netNum[2]); - out->write(p.address.netNum[3]); - out->write(flags); - out->write((p.session << 16) | (p.key & 0xFFFF)); - for (int i = 0; i < gMasterServerList.size(); i++) - BitStream::sendPacketStream(&gMasterServerList[i].address); + if (!p.broadcast) { + BitStream* out = BitStream::getPacketStream(); + out->write(U8(NetInterface::MasterServerGamePingRequest)); + out->write(p.address.netNum[0]); + out->write(p.address.netNum[1]); + out->write(p.address.netNum[2]); + out->write(p.address.netNum[3]); + out->write(flags); + out->write((p.session << 16) | (p.key & 0xFFFF)); + for (int i = 0; i < gMasterServerList.size(); i++) + BitStream::sendPacketStream(&gMasterServerList[i].address); + } i++; } @@ -1341,17 +1343,19 @@ static void processPingsAndQueries(U32 session, bool schedule) Con::printf("Querying Server %s (%d)...", addressString, p.tryCount); sendPacket(NetInterface::GameInfoRequest, &p.address, p.key, p.session, flags); - BitStream* out = BitStream::getPacketStream(); - out->write(U8(NetInterface::MasterServerGameInfoRequest)); - out->write(p.address.netNum[0]); - out->write(p.address.netNum[1]); - out->write(p.address.netNum[2]); - out->write(p.address.netNum[3]); - out->write(flags); - out->write((p.session << 16) | (p.key & 0xFFFF)); - - for (int i = 0; i < gMasterServerList.size(); i++) - BitStream::sendPacketStream(&gMasterServerList[i].address); + if (!p.broadcast) { + BitStream* out = BitStream::getPacketStream(); + out->write(U8(NetInterface::MasterServerGameInfoRequest)); + out->write(p.address.netNum[0]); + out->write(p.address.netNum[1]); + out->write(p.address.netNum[2]); + out->write(p.address.netNum[3]); + out->write(flags); + out->write((p.session << 16) | (p.key & 0xFFFF)); + + for (int i = 0; i < gMasterServerList.size(); i++) + BitStream::sendPacketStream(&gMasterServerList[i].address); + } if (!si->isQuerying()) { From efb55b9a29f0535295357991539837256baa18bd Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Fri, 28 Apr 2023 14:28:30 +0530 Subject: [PATCH 09/46] make it ACTUALLY work for locally found servers --- engine/source/game/net/serverQuery.cpp | 10 +++++++++- engine/source/game/net/serverQuery.h | 2 ++ game/marble/client/init.cs | 11 +++++++---- game/marble/client/ui/findGameGui.gui | 11 +++++++---- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 1528a171..3668c537 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -135,6 +135,7 @@ struct Ping U32 time; U32 tryCount; bool broadcast; + bool isLocal; }; static Ping gMasterServerPing; @@ -751,6 +752,7 @@ ConsoleFunction(setServerInfo, bool, 2, 2, "setServerInfo(index);") Con::setBoolVariable("ServerInfo::Favorite", info.isFavorite); Con::setBoolVariable("ServerInfo::Dedicated", info.isDedicated()); Con::setBoolVariable("ServerInfo::Password", info.isPassworded()); + Con::setBoolVariable("ServerInfo::IsLocal", info.isLocal); return true; } return false; @@ -904,6 +906,7 @@ static void pushPingRequest(const NetAddress* addr) p.time = 0; p.tryCount = gPingRetryCount; p.broadcast = false; + p.isLocal = false; gPingList.push_back(p); gServerPingCount++; } @@ -922,6 +925,7 @@ static void pushPingBroadcast(const NetAddress* addr) p.time = 0; p.tryCount = 1; // only try this once p.broadcast = true; + p.isLocal = true; gPingList.push_back(p); // Don't increment gServerPingCount, broadcasts are not // counted as requests. @@ -1752,8 +1756,11 @@ static void handleGamePingResponse(const NetAddress* address, BitStream* stream, { // an anonymous ping response - if it's not already timed // out or finished, ping it. Probably from a broadcast - if (!addressFinished(address)) + if (!addressFinished(address)) { pushPingRequest(address); + S32 index = findPingEntry(gPingList, address); + gPingList[index].isLocal = true; + } return; } Ping& p = gPingList[index]; @@ -1864,6 +1871,7 @@ static void handleGamePingResponse(const NetAddress* address, BitStream* stream, si = findOrCreateServerInfo(address); si->ping = ping; si->version = temp32; + si->isLocal = p.isLocal; // Get the server name: stream->readString(buf); diff --git a/engine/source/game/net/serverQuery.h b/engine/source/game/net/serverQuery.h index 5d781c5a..e844743a 100644 --- a/engine/source/game/net/serverQuery.h +++ b/engine/source/game/net/serverQuery.h @@ -69,6 +69,7 @@ struct ServerInfo U32 cpuSpeed; bool isFavorite; BitSet32 status; + bool isLocal; ServerInfo() { @@ -86,6 +87,7 @@ struct ServerInfo cpuSpeed = 0; isFavorite = false; status = Status_New; + isLocal = false; } ~ServerInfo(); diff --git a/game/marble/client/init.cs b/game/marble/client/init.cs index 19b4c662..f42d4bc8 100644 --- a/game/marble/client/init.cs +++ b/game/marble/client/init.cs @@ -445,7 +445,7 @@ function waitForPreviewLevel() } // Manually connect to server by ip -function connectManual(%address, %invited) +function connectManual(%address, %local, %invited) { $disconnectGui = RootGui.contentGui; @@ -463,7 +463,7 @@ function connectManual(%address, %invited) RootGui.setContent(MissionLoadingGui); if ($EnableFMS) - establishConnection(%address, true, %invited); + establishConnection(%address, true, %local, %invited); else connectToServer(%address, %invited); } @@ -546,7 +546,7 @@ function connectToPreviewServer() } // connect to a server. if address is empty a local connect is assumed -function establishConnection(%address, %mp, %invited) +function establishConnection(%address, %mp, %isLocal, %invited) { echo("ESTABLISH CONNECTION" SPC %address SPC %mp SPC %invited); if (isObject(ServerConnection)) @@ -591,7 +591,10 @@ function establishConnection(%address, %mp, %invited) } $Client::connectedMultiplayer = true; $Game::SPGemHunt = false; - %conn.arrangeConnection(%address); + if (%isLocal) + %conn.connect(%address); + else + %conn.arrangeConnection(%address); } clearClientGracePeroid(); diff --git a/game/marble/client/ui/findGameGui.gui b/game/marble/client/ui/findGameGui.gui index 1da82cfd..ff1d97ab 100644 --- a/game/marble/client/ui/findGameGui.gui +++ b/game/marble/client/ui/findGameGui.gui @@ -730,9 +730,12 @@ function FindGameGui::joinGame(%this, %index, %invited) %this.joiningGame = true; RootGui.setContent(MissionLoadingGui); - if ($EnableFMS) - establishConnection($ServerInfo::Address, true); - else + if ($EnableFMS) { + if ($ServerInfo::IsLocal) + establishConnection($ServerInfo::Address, true, true); + else + establishConnection($ServerInfo::Address, true); + } else connectToServer($ServerInfo::Address); return; } @@ -796,7 +799,7 @@ function FindGameGui::onConnectComplete(%this) RootGui.setContent(MissionLoadingGui); if ($EnableFMS) - establishConnection($XBLive::secureHostAddress, true, $Client::Invited); + establishConnection($XBLive::secureHostAddress, true, false, $Client::Invited); else connectToServer($XBLive::secureHostAddress, $Client::Invited); } From 0e25f9b2ad332db365b8072757ad70b161f6bf88 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Fri, 28 Apr 2023 19:00:08 +0530 Subject: [PATCH 10/46] Fix crash when switching server-client roles --- engine/source/game/net/serverQuery.cpp | 67 -------------------------- engine/source/sim/netInterface.cpp | 12 +++-- 2 files changed, 9 insertions(+), 70 deletions(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 3668c537..7e4dad81 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -2137,47 +2137,6 @@ static void handleMasterServerClientRequestedArrangedConnection(const NetAddress if (conn != NULL) { conn->connectArranged(possibleAddresses, false); } - - // TODO: If not hosting then reject the connection - - // TODO: Implement arranged connection - - /*if(!gIsServer || Random::readF() > 0.75) - { - // We reject connections about 75% of the time... - - logprintf("Rejecting arranged connection from %s", Address(possibleAddresses[0]).toString()); - c2mRejectArrangedConnection(requestId, connectionParameters); - } - else - { - // Ok, let's do the arranged connection! - - U8 data[Nonce::NonceSize * 2 + SymmetricCipher::KeySize * 2]; - Random::read(data, sizeof(data)); - IPAddress localAddress = getInterface()->getFirstBoundInterfaceAddress().toIPAddress(); - - ByteBufferPtr b = new ByteBuffer(data, sizeof(data)); - b->takeOwnership(); - c2mAcceptArrangedConnection(requestId, localAddress, b); - GameConnection *conn = new GameConnection(); - - Vector
fullPossibleAddresses; - for(S32 i = 0; i < possibleAddresses.size(); i++) - fullPossibleAddresses.push_back(Address(possibleAddresses[i])); - - logprintf("Accepting arranged connection from %s", Address(fullPossibleAddresses[0]).toString()); - - logprintf(" Generated shared secret data: %s", b->encodeBase64()->getBuffer()); - - ByteBufferPtr theSharedData = new ByteBuffer(data + 2 * Nonce::NonceSize, sizeof(data) - 2 * Nonce::NonceSize); - theSharedData->takeOwnership(); - Nonce nonce(data); - Nonce serverNonce(data + Nonce::NonceSize); - - conn->connectArranged(getInterface(), fullPossibleAddresses, - nonce, serverNonce, theSharedData,false); - }*/ } static void handleMasterServerArrangedConnectionAccepted(const NetAddress* address, BitStream* stream, U32 /*key*/, U8 /*flags*/) @@ -2207,32 +2166,6 @@ static void handleMasterServerArrangedConnectionAccepted(const NetAddress* addre // Do connectArranged to server arrangeNetConnection->connectArranged(possibleAddresses, true); - - // TODO: Implement accepted arranged connection - - /*if(!gIsServer && requestId == mCurrentQueryId && connectionData->getBufferSize() >= Nonce::NonceSize * 2 + SymmetricCipher::KeySize * 2) - { - logprintf("Remote host accepted arranged connection."); - logprintf(" Shared secret data: %s", connectionData->encodeBase64()->getBuffer()); - GameConnection *conn = new GameConnection(); - - Vector
fullPossibleAddresses; - for(S32 i = 0; i < possibleAddresses.size(); i++) - fullPossibleAddresses.push_back(Address(possibleAddresses[i])); - - ByteBufferPtr theSharedData = - new ByteBuffer( - (U8 *) connectionData->getBuffer() + Nonce::NonceSize * 2, - connectionData->getBufferSize() - Nonce::NonceSize * 2 - ); - theSharedData->takeOwnership(); - - Nonce nonce(connectionData->getBuffer()); - Nonce serverNonce(connectionData->getBuffer() + Nonce::NonceSize); - - conn->connectArranged(getInterface(), fullPossibleAddresses, - nonce, serverNonce, theSharedData,true); - }*/ } static void handleMasterServerArrangedConnectionRejected(const NetAddress* address, BitStream* stream, U32 /*key*/, U8 /*flags*/) diff --git a/engine/source/sim/netInterface.cpp b/engine/source/sim/netInterface.cpp index 02af9f65..46ec3348 100644 --- a/engine/source/sim/netInterface.cpp +++ b/engine/source/sim/netInterface.cpp @@ -452,6 +452,12 @@ void NetInterface::sendPunchPackets(NetConnection *conn) for(S32 i = 0; i < theParams.mPossibleAddresses.size(); i++) { BitStream::sendPacketStream(theParams.mPossibleAddresses[i]); + Con::printf("Sending punch packets to %d.%d.%d.%d:%d", + theParams.mPossibleAddresses[i]->netNum[0], + theParams.mPossibleAddresses[i]->netNum[1], + theParams.mPossibleAddresses[i]->netNum[2], + theParams.mPossibleAddresses[i]->netNum[3], + theParams.mPossibleAddresses[i]->port); } conn->mConnectSendCount++; conn->mConnectLastSendTime = Platform::getVirtualMilliseconds(); //getCurrentTime(); @@ -615,11 +621,11 @@ void NetInterface::handleArrangedConnectRequest(const NetAddress* theAddress, Bi theParams.mDebugObjectSizes = stream->readFlag(); //stream->read(&connectSequence); //TNLLogMessageV(LogNetInterface, ("Received Arranged Connect Request")); - Con::printf("Received Arranged Connect Request"); + Con::printf("Received Arranged Connect Request: Initiator: %d", theParams.mIsInitiator); conn->setConnectionState(NetConnection::Connected); - + removePendingConnection(conn); + if (theParams.mIsInitiator) { - removePendingConnection(conn); conn->connect(theAddress); } else From 8986f319288dd2f05464e4407876dcaf20a30634 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sat, 29 Apr 2023 01:05:28 +0530 Subject: [PATCH 11/46] Add relay support --- engine/source/game/net/serverQuery.cpp | 50 ++++++++++++++++++++++++++ engine/source/sim/netInterface.h | 4 ++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 7e4dad81..2eaa7600 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -568,6 +568,23 @@ ConsoleMethod(NetConnection, arrangeConnection, void, 3, 3, "NetConnection.arran sendMasterArrangedConnectRequest(&addr); } + +NetConnection* relayNetConnection = NULL; +static void getRelayServer(const NetAddress* address); + +ConsoleMethod(NetConnection, relayConnection, void, 3, 3, "NetConnection.relayConnection(ip);") +{ + relayNetConnection = object; + argc; + + NetAddress addr; + char* addrText; + + addrText = dStrdup(argv[2]); + Net::stringToAddress(addrText, &addr); + + getRelayServer(&addr); +} #endif //----------------------------------------------------------------------------- @@ -2100,6 +2117,36 @@ static void handleGameInfoResponse(const NetAddress* address, BitStream* stream, } #ifdef TORQUE_NET_HOLEPUNCHING + +static void getRelayServer(const NetAddress* address) +{ + BitStream* stream = BitStream::getPacketStream(); + stream->write(U8(NetInterface::MasterServerRelayRequest)); + stream->write(address->netNum[0]); + stream->write(address->netNum[1]); + stream->write(address->netNum[2]); + stream->write(address->netNum[3]); + + for (int i = 0; i < gMasterServerList.size(); i++) + { + BitStream::sendPacketStream(&gMasterServerList[i].address); + } +} + +static void handleMasterServerRelayResponse(const NetAddress* address, BitStream* stream) +{ + Con::printf("Received MasterServerRelayResponse"); + NetAddress theAddress; + theAddress.type = 0; + stream->read(&theAddress.netNum[0]); + stream->read(&theAddress.netNum[1]); + stream->read(&theAddress.netNum[2]); + stream->read(&theAddress.netNum[3]); + stream->read(&theAddress.port); + + relayNetConnection->connect(&theAddress); +} + static void handleMasterServerClientRequestedArrangedConnection(const NetAddress* address, BitStream* stream, U32 /*key*/, U8 /*flags*/) { Con::printf("Received MasterServerClientRequestedArrangedConnection"); @@ -2284,6 +2331,9 @@ void DemoNetInterface::handleInfoPacket(const NetAddress* address, U8 packetType case MasterServerGameInfoResponse: handleMasterServerGameInfoResponse(address, stream); break; + case MasterServerRelayResponse: + handleMasterServerRelayResponse(address, stream); + break; #endif } } diff --git a/engine/source/sim/netInterface.h b/engine/source/sim/netInterface.h index 5c6c3932..ead0e0ac 100644 --- a/engine/source/sim/netInterface.h +++ b/engine/source/sim/netInterface.h @@ -47,7 +47,9 @@ class NetInterface MasterServerGamePingRequest = 58, MasterServerGamePingResponse = 60, MasterServerGameInfoRequest = 62, - MasterServerGameInfoResponse = 64 + MasterServerGameInfoResponse = 64, + MasterServerRelayRequest = 66, + MasterServerRelayResponse = 68, #endif // TORQUE_NET_HOLEPUNCHING }; protected: From b929ca95c5c618dca7d18e336bababd5411829c2 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sat, 29 Apr 2023 01:19:00 +0530 Subject: [PATCH 12/46] Fix defines --- engine/source/game/net/serverQuery.cpp | 4 ++++ engine/source/sim/netInterface.cpp | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 2eaa7600..f3abdcd0 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -1310,6 +1310,7 @@ static void processPingsAndQueries(U32 session, bool schedule) Con::printf("Pinging Server %s (%d)...", addressString, p.tryCount); sendPacket(NetInterface::GamePingRequest, &p.address, p.key, p.session, flags); +#ifdef TORQUE_NET_HOLEPUNCHING if (!p.broadcast) { BitStream* out = BitStream::getPacketStream(); out->write(U8(NetInterface::MasterServerGamePingRequest)); @@ -1322,6 +1323,7 @@ static void processPingsAndQueries(U32 session, bool schedule) for (int i = 0; i < gMasterServerList.size(); i++) BitStream::sendPacketStream(&gMasterServerList[i].address); } +#endif i++; } @@ -1364,6 +1366,7 @@ static void processPingsAndQueries(U32 session, bool schedule) Con::printf("Querying Server %s (%d)...", addressString, p.tryCount); sendPacket(NetInterface::GameInfoRequest, &p.address, p.key, p.session, flags); +#ifdef TORQUE_NET_HOLEPUNCHING if (!p.broadcast) { BitStream* out = BitStream::getPacketStream(); out->write(U8(NetInterface::MasterServerGameInfoRequest)); @@ -1377,6 +1380,7 @@ static void processPingsAndQueries(U32 session, bool schedule) for (int i = 0; i < gMasterServerList.size(); i++) BitStream::sendPacketStream(&gMasterServerList[i].address); } +#endif if (!si->isQuerying()) { diff --git a/engine/source/sim/netInterface.cpp b/engine/source/sim/netInterface.cpp index 46ec3348..8eff11c4 100644 --- a/engine/source/sim/netInterface.cpp +++ b/engine/source/sim/netInterface.cpp @@ -95,8 +95,11 @@ void NetInterface::processPacketReceiveEvent(PacketReceiveEvent* prEvent) U8 packetType; pStream.read(&packetType); NetAddress* addr = &prEvent->sourceAddress; - +#ifdef TORQUE_NET_HOLEPUNCHING if (packetType <= GameHeartbeat || packetType >= MasterServerRequestArrangedConnection) +#else + if (packetType <= GameHeartbeat) +#endif handleInfoPacket(addr, packetType, &pStream); #ifdef GGC_PLUGIN else if (packetType == GGCPacket) @@ -766,6 +769,7 @@ void NetInterface::checkTimeouts() else sendConnectRequest(pending); } +#ifdef TORQUE_NET_HOLEPUNCHING else if (pending->getConnectionState() == NetConnection::SendingPunchPackets && time > pending->mConnectLastSendTime + ConnectRetryTime) { @@ -785,6 +789,7 @@ void NetInterface::checkTimeouts() else sendPunchPackets(pending); } +#endif i++; } mLastTimeoutCheckTime = time; From 6f6a79b226adaea0b17dc7e571098a79d32d9c6a Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sat, 29 Apr 2023 01:30:53 +0530 Subject: [PATCH 13/46] debug connection func --- game/marble/client/init.cs | 55 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/game/marble/client/init.cs b/game/marble/client/init.cs index f42d4bc8..9ae280cf 100644 --- a/game/marble/client/init.cs +++ b/game/marble/client/init.cs @@ -444,6 +444,61 @@ function waitForPreviewLevel() $Client::GameLoaded = true; } + +// Connect to a server using a chosen %method +// Methods: +// 0: Direct Connect +// 1: Arranged Connect through NAT hole punching +// 2: Relay Connect using a relay server +function connectUsing(%address, %method) +{ + $disconnectGui = RootGui.contentGui; + GameMissionInfo.setMode(GameMissionInfo.MPMode); + + if ($EnableFMS) + { + %missionIndex = GameMissionInfo.getCurrentIndex(); + if (%missionIndex == -1) + %missionIndex = 0; + + GameMissionInfo.selectMission(%missionIndex); + } + RootGui.setContent(MissionLoadingGui); + + echo("ESTABLISH CONNECTION" SPC %address SPC %mp SPC %invited); + if (isObject(ServerConnection)) + ServerConnection.delete(); + + // clear the scores gui here so that our the client id from the preview server doesn't + // show up in the scores list. + PlayerListGui.clear(); + // reset client Id since we are connecting to a different server + $Player::ClientId = 0; + + %conn = new GameConnection(ServerConnection); + RootGroup.add(ServerConnection); + + %xbLiveVoice = 0; // XBLiveGetVoiceStatus(); + + // we expect $Player:: variables to be properly populated at this point + %isDemoLaunch = isDemoLaunch(); + %conn.setConnectArgs($Player::Name, $Player::XBLiveId, %xbLiveVoice, %invited, %isDemoLaunch); + %conn.setJoinPassword($Client::Password); + + $Client::connectedMultiplayer = true; + $Game::SPGemHunt = false; + + if (%method == 0) { + %conn.connect(%address); + } else if (%method == 1) { + %conn.arrangeConnection(%address); + } else if (%method == 2) { + %conn.relayConnection(%address); + } + + clearClientGracePeroid(); +} + // Manually connect to server by ip function connectManual(%address, %local, %invited) { From 1a92e2be1d0b864ab41db1ca9cbdcbbb5e4969cf Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Wed, 3 May 2023 20:02:52 +0530 Subject: [PATCH 14/46] make relaying work --- engine/source/game/net/serverQuery.cpp | 28 ++++++++++++++++++++++---- engine/source/sim/netInterface.h | 1 + 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index f3abdcd0..c91598fc 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -2131,24 +2131,41 @@ static void getRelayServer(const NetAddress* address) stream->write(address->netNum[2]); stream->write(address->netNum[3]); - for (int i = 0; i < gMasterServerList.size(); i++) + Vector* serverList = getMasterServerList(); + + for (int i = 0; i < serverList->size(); i++) { - BitStream::sendPacketStream(&gMasterServerList[i].address); + BitStream::sendPacketStream(&(*serverList)[i].address); } } static void handleMasterServerRelayResponse(const NetAddress* address, BitStream* stream) { Con::printf("Received MasterServerRelayResponse"); + + bool isHost; + stream->read(&isHost); + NetAddress theAddress; - theAddress.type = 0; + theAddress.type = NetAddress::IPAddress; stream->read(&theAddress.netNum[0]); stream->read(&theAddress.netNum[1]); stream->read(&theAddress.netNum[2]); stream->read(&theAddress.netNum[3]); stream->read(&theAddress.port); + + // Attempt connection to relay + BitStream* out = BitStream::getPacketStream(); + out->write(isHost); + BitStream::sendPacketStream(&theAddress); - relayNetConnection->connect(&theAddress); + // relayNetConnection->connect(&theAddress); +} + +static void handleMasterServerRelayReady(const NetAddress* address) +{ + // Connect to it! + relayNetConnection->connect(address); } static void handleMasterServerClientRequestedArrangedConnection(const NetAddress* address, BitStream* stream, U32 /*key*/, U8 /*flags*/) @@ -2338,6 +2355,9 @@ void DemoNetInterface::handleInfoPacket(const NetAddress* address, U8 packetType case MasterServerRelayResponse: handleMasterServerRelayResponse(address, stream); break; + case MasterServerRelayReady: + handleMasterServerRelayReady(address); + break; #endif } } diff --git a/engine/source/sim/netInterface.h b/engine/source/sim/netInterface.h index ead0e0ac..0c3709c3 100644 --- a/engine/source/sim/netInterface.h +++ b/engine/source/sim/netInterface.h @@ -50,6 +50,7 @@ class NetInterface MasterServerGameInfoResponse = 64, MasterServerRelayRequest = 66, MasterServerRelayResponse = 68, + MasterServerRelayReady = 72, #endif // TORQUE_NET_HOLEPUNCHING }; protected: From 322f30cedd887a2ae4efdfdb856f6d5b1a7a127b Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Wed, 3 May 2023 21:03:24 +0530 Subject: [PATCH 15/46] support port when searching --- engine/source/game/net/serverQuery.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index c91598fc..ed8b37f0 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -547,7 +547,7 @@ static void sendMasterArrangedConnectRequest(NetAddress* address) out->write(address->netNum[1]); out->write(address->netNum[2]); out->write(address->netNum[3]); - //out->write(address->port); + out->write(address->port); BitStream::sendPacketStream(&(*masterList)[i].address); } @@ -1318,6 +1318,7 @@ static void processPingsAndQueries(U32 session, bool schedule) out->write(p.address.netNum[1]); out->write(p.address.netNum[2]); out->write(p.address.netNum[3]); + out->write(p.address.port); out->write(flags); out->write((p.session << 16) | (p.key & 0xFFFF)); for (int i = 0; i < gMasterServerList.size(); i++) @@ -1374,6 +1375,7 @@ static void processPingsAndQueries(U32 session, bool schedule) out->write(p.address.netNum[1]); out->write(p.address.netNum[2]); out->write(p.address.netNum[3]); + out->write(p.address.port); out->write(flags); out->write((p.session << 16) | (p.key & 0xFFFF)); @@ -2130,6 +2132,7 @@ static void getRelayServer(const NetAddress* address) stream->write(address->netNum[1]); stream->write(address->netNum[2]); stream->write(address->netNum[3]); + stream->write(address->port); Vector* serverList = getMasterServerList(); From 1416c068227eefe950f1d818c31ee9cf944a4c5f Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Wed, 3 May 2023 22:22:36 +0530 Subject: [PATCH 16/46] fallback to relay if all fails --- engine/source/game/net/serverQuery.cpp | 5 +- engine/source/game/net/serverQuery.h | 2 + engine/source/sim/netConnection.h | 2 + engine/source/sim/netInterface.cpp | 139 +++++++++++-------------- engine/source/sim/netInterface.h | 6 ++ 5 files changed, 72 insertions(+), 82 deletions(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index ed8b37f0..1c8bb3b7 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -566,6 +566,9 @@ ConsoleMethod(NetConnection, arrangeConnection, void, 3, 3, "NetConnection.arran addrText = dStrdup(argv[2]); Net::stringToAddress(addrText, &addr); + ConnectionParameters& params = arrangeNetConnection->getConnectionParameters(); + params.mToConnectAddress = addr; + sendMasterArrangedConnectRequest(&addr); } @@ -2168,7 +2171,7 @@ static void handleMasterServerRelayResponse(const NetAddress* address, BitStream static void handleMasterServerRelayReady(const NetAddress* address) { // Connect to it! - relayNetConnection->connect(address); + GNet->startRelayConnection(arrangeNetConnection, address); } static void handleMasterServerClientRequestedArrangedConnection(const NetAddress* address, BitStream* stream, U32 /*key*/, U8 /*flags*/) diff --git a/engine/source/game/net/serverQuery.h b/engine/source/game/net/serverQuery.h index e844743a..d3b0cc0d 100644 --- a/engine/source/game/net/serverQuery.h +++ b/engine/source/game/net/serverQuery.h @@ -107,6 +107,7 @@ struct ServerInfo extern Vector gServerList; extern bool gServerBrowserDirty; +extern NetConnection* relayNetConnection; extern void clearServerList(bool clearServerInfo = true); extern void queryLanServers(U32 port, U8 flags, const char* gameType, const char* missionType, U8 minPlayers, U8 maxPlayers, U8 maxBots, U32 regionMask, U32 maxPing, U16 minCPU, @@ -119,6 +120,7 @@ extern void queryFavoriteServers(U8 flags); extern void querySingleServer(const NetAddress* addr, U8 flags); extern void startHeartbeat(); extern void sendHeartbeat(U8 flags); +extern Vector* getMasterServerList(); #ifdef TORQUE_DEBUG extern void addFakeServers(S32 howMany); diff --git a/engine/source/sim/netConnection.h b/engine/source/sim/netConnection.h index b122cc31..c5007f86 100644 --- a/engine/source/sim/netConnection.h +++ b/engine/source/sim/netConnection.h @@ -327,6 +327,7 @@ struct ConnectionParameters //bool mIsLocal; ///< True if this is a connectLocal connection. //ByteBufferPtr mArrangedSecret; ///< The shared secret as arranged by the connection intermediary. bool mDebugObjectSizes; ///< This connection's initiator requested debugging size information during packet writes. + NetAddress mToConnectAddress; ConnectionParameters() { @@ -659,6 +660,7 @@ class NetConnection : public ConnectionProtocol, public SimGroup Connected, ///< We've accepted a connect request, or we've received a connect response accept. #ifdef TORQUE_NET_HOLEPUNCHING SendingPunchPackets, + TryingRelay #endif // TORQUE_NET_HOLEPUNCHING }; diff --git a/engine/source/sim/netInterface.cpp b/engine/source/sim/netInterface.cpp index 8eff11c4..7991f54d 100644 --- a/engine/source/sim/netInterface.cpp +++ b/engine/source/sim/netInterface.cpp @@ -15,6 +15,7 @@ #include "GGCNatTunnel.h" extern void HandleGGCPacket(NetAddress* addr, unsigned char* data, U32 dataSize); #endif +#include NetInterface* GNet = NULL; @@ -430,14 +431,44 @@ void NetInterface::handleConnectReject(const NetAddress* address, BitStream* str // NetInterface arranged connection process //----------------------------------------------------------------------------- +void NetInterface::sendRelayPackets(NetConnection* conn) +{ + relayNetConnection = conn; + BitStream* out = BitStream::getPacketStream(); + + ConnectionParameters& params = conn->getConnectionParameters(); + + out->write(U8(NetInterface::MasterServerRelayRequest)); + out->write(params.mToConnectAddress.netNum[0]); + out->write(params.mToConnectAddress.netNum[1]); + out->write(params.mToConnectAddress.netNum[2]); + out->write(params.mToConnectAddress.netNum[3]); + out->write(params.mToConnectAddress.port); + + Vector* serverList = getMasterServerList(); + + for (int i = 0; i < serverList->size(); i++) + { + BitStream::sendPacketStream(&(*serverList)[i].address); + } + + conn->mConnectSendCount++; + conn->mConnectLastSendTime = Platform::getVirtualMilliseconds(); //getCurrentTime(); +} + +void NetInterface::startRelayConnection(NetConnection* conn, const NetAddress* theAddress) +{ + conn->setConnectionState(NetConnection::NotConnected); + removePendingConnection(conn); // Remove this pls + + conn->connect(theAddress); // Just do it *normally* +} + void NetInterface::startArrangedConnection(NetConnection *conn) { conn->setConnectionState(NetConnection::SendingPunchPackets); addPendingConnection(conn); conn->mConnectSendCount = 0; - - // TODO: Figure out which to use - //conn->setConnectSequence(Platform::getVirtualMilliseconds()); conn->mConnectLastSendTime = Platform::getVirtualMilliseconds(); sendPunchPackets(conn); @@ -445,11 +476,8 @@ void NetInterface::startArrangedConnection(NetConnection *conn) void NetInterface::sendPunchPackets(NetConnection *conn) { - // TODO: The following code is from OpenTNL, it needs to be updated to work with Torque/OpenMBU - ConnectionParameters &theParams = conn->getConnectionParameters(); BitStream* out = BitStream::getPacketStream(); - //PacketStream out; out->write(U8(Punch)); for(S32 i = 0; i < theParams.mPossibleAddresses.size(); i++) @@ -468,8 +496,6 @@ void NetInterface::sendPunchPackets(NetConnection *conn) void NetInterface::handlePunch(const NetAddress* theAddress, BitStream *stream) { - // TODO: The following code is from OpenTNL, it needs to be updated to work with Torque/OpenMBU - S32 i, j; NetConnection *conn; @@ -542,8 +568,6 @@ void NetInterface::handlePunch(const NetAddress* theAddress, BitStream *stream) void NetInterface::sendArrangedConnectRequest(NetConnection *conn) { - // TODO: The following code is from OpenTNL, it needs to be updated to work with Torque/OpenMBU - Con::printf("Sending Arranged Connect Request"); BitStream* out = BitStream::getPacketStream(); @@ -562,12 +586,8 @@ void NetInterface::sendArrangedConnectRequest(NetConnection *conn) void NetInterface::handleArrangedConnectRequest(const NetAddress* theAddress, BitStream *stream) { - // TODO: The following code is from OpenTNL, it needs to be updated to work with Torque/OpenMBU - S32 i, j; NetConnection *conn; - //Nonce nonce, serverNonce; - //nonce.read(stream); U32 connectSequence; stream->read(&connectSequence); @@ -576,9 +596,6 @@ void NetInterface::handleArrangedConnectRequest(const NetAddress* theAddress, Bi conn = mPendingConnections[i]; ConnectionParameters &theParams = conn->getConnectionParameters(); - //if(nonce != theParams.mNonce) - // continue; - for(j = 0; j < theParams.mPossibleAddresses.size(); j++) if(Net::compareAddresses(theAddress, theParams.mPossibleAddresses[j])) break; @@ -589,41 +606,8 @@ void NetInterface::handleArrangedConnectRequest(const NetAddress* theAddress, Bi return; ConnectionParameters &theParams = conn->getConnectionParameters(); -// SymmetricCipher theCipher(theParams.mArrangedSecret); -// if(!stream->decryptAndCheckHash(NetConnection::MessageSignatureBytes, stream->getBytePosition(), &theCipher)) -// return; -// -// stream->setBytePosition(stream->getBytePosition()); -// -// serverNonce.read(stream); -// if(serverNonce != theParams.mServerNonce) -// return; - -// if(stream->readFlag()) -// { -// if(mPrivateKey.isNull()) -// return; -// theParams.mUsingCrypto = true; -// theParams.mPublicKey = new AsymmetricKey(stream); -// theParams.mPrivateKey = mPrivateKey; -// -// U32 decryptPos = stream->getBytePosition(); -// stream->setBytePosition(decryptPos); -// theParams.mSharedSecret = theParams.mPrivateKey->computeSharedSecretKey(theParams.mPublicKey); -// SymmetricCipher theCipher(theParams.mSharedSecret); -// -// if(!stream->decryptAndCheckHash(NetConnection::MessageSignatureBytes, decryptPos, &theCipher)) -// return; -// -// // now read the first part of the connection's session (symmetric) key -// stream->read(SymmetricCipher::KeySize, theParams.mSymmetricKey); -// Random::read(theParams.mInitVector, SymmetricCipher::KeySize); -// } - //U32 connectSequence; theParams.mDebugObjectSizes = stream->readFlag(); - //stream->read(&connectSequence); - //TNLLogMessageV(LogNetInterface, ("Received Arranged Connect Request")); Con::printf("Received Arranged Connect Request: Initiator: %d", theParams.mIsInitiator); conn->setConnectionState(NetConnection::Connected); removePendingConnection(conn); @@ -641,35 +625,6 @@ void NetInterface::handleArrangedConnectRequest(const NetAddress* theAddress, Bi BitStream::sendPacketStream(theAddress); } - - //if(connect) - //{ - // //connect->disconnect(NetConnection::ReasonSelfDisconnect, ""); - - // connect->onDisconnect("SelfDisconnect"); - // connect->deleteObject(); - //} - - //conn->setNetAddress(theAddress); - ////conn->setInitialRecvSequence(connectSequence); - - //conn->setConnectSequence(connectSequence); - ////if(theParams.mUsingCrypto) - //// conn->setSymmetricCipher(new SymmetricCipher(theParams.mSymmetricKey, theParams.mInitVector)); - - //const char *errorString = NULL; - //if(!conn->readConnectRequest(stream, &errorString)) - //{ - // //sendConnectReject(&theParams, theAddress);//, errorString); - // sendConnectReject(conn, errorString); - // removePendingConnection(conn); - // return; - //} - ////addConnection(conn); - //removePendingConnection(conn); - //conn->setConnectionState(NetConnection::Connected); - //conn->onConnectionEstablished(theParams.mIsInitiator); - //sendConnectAccept(conn); } #endif // TORQUE_NET_HOLEPUNCHING @@ -772,6 +727,28 @@ void NetInterface::checkTimeouts() #ifdef TORQUE_NET_HOLEPUNCHING else if (pending->getConnectionState() == NetConnection::SendingPunchPackets && time > pending->mConnectLastSendTime + ConnectRetryTime) + { + if (pending->mConnectSendCount > ConnectRetryCount) + { + // Try relay + if (pending->mConnectionParameters.mIsInitiator) { + pending->setConnectionState(NetConnection::TryingRelay); + pending->mConnectSendCount = 0; + pending->mConnectLastSendTime = time; + sendRelayPackets(pending); + } + else + { + pending->setConnectionState(NetConnection::NotConnected); + removePendingConnection(pending); + continue; + } + } + else + sendPunchPackets(pending); + } + else if (pending->getConnectionState() == NetConnection::TryingRelay && + time > pending->mConnectLastSendTime + ConnectRetryTime) { if (pending->mConnectSendCount > ConnectRetryCount) { @@ -779,7 +756,7 @@ void NetInterface::checkTimeouts() pending->onConnectTimedOut(); pending->deleteObject(); } - else + else { pending->setConnectionState(NetConnection::NotConnected); } @@ -787,7 +764,7 @@ void NetInterface::checkTimeouts() continue; } else - sendPunchPackets(pending); + sendRelayPackets(pending); } #endif i++; diff --git a/engine/source/sim/netInterface.h b/engine/source/sim/netInterface.h index 0c3709c3..7f746e6c 100644 --- a/engine/source/sim/netInterface.h +++ b/engine/source/sim/netInterface.h @@ -103,6 +103,9 @@ class NetInterface /// Begins the connection handshaking process for an arranged connection. void startArrangedConnection(NetConnection *conn); + /// Begins connecting to the relay server. + void startRelayConnection(NetConnection* conn, const NetAddress* theAddress); + protected: /// Sends Punch packets to each address in the possible connection address list. void sendPunchPackets(NetConnection *conn); @@ -116,6 +119,9 @@ class NetInterface /// Handles an incoming connect request from an arranged connection. void handleArrangedConnectRequest(const NetAddress* theAddress, BitStream *stream); + /// Sends relay requests + void sendRelayPackets(NetConnection* conn); + #endif // TORQUE_NET_HOLEPUNCHING void handleDisconnect(const NetAddress* address, BitStream* stream); From edc69a54ae9dc038808a2a559f801646a046c89a Mon Sep 17 00:00:00 2001 From: Human Gamer <39096122+HumanGamer@users.noreply.github.com> Date: Thu, 4 May 2023 00:58:58 -0500 Subject: [PATCH 17/46] Fixed Relay Connections --- engine/source/core/torqueConfig.h | 2 +- engine/source/game/net/serverQuery.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/engine/source/core/torqueConfig.h b/engine/source/core/torqueConfig.h index 456c5cf6..dbecb1f3 100644 --- a/engine/source/core/torqueConfig.h +++ b/engine/source/core/torqueConfig.h @@ -46,7 +46,7 @@ #define TORQUE_HIFI_NET /// Define me to enable Torque Hole Punching support -//#define TORQUE_NET_HOLEPUNCHING +#define TORQUE_NET_HOLEPUNCHING /// Define me to enable shader caching support (Unfinished and really only needed for some versions of Wine or Proton) //#define TORQUE_SHADER_CACHING diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 1c8bb3b7..656ab5f9 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -2171,7 +2171,10 @@ static void handleMasterServerRelayResponse(const NetAddress* address, BitStream static void handleMasterServerRelayReady(const NetAddress* address) { // Connect to it! - GNet->startRelayConnection(arrangeNetConnection, address); + if (relayNetConnection) + GNet->startRelayConnection(relayNetConnection, address); + else if (arrangeNetConnection) + GNet->startRelayConnection(arrangeNetConnection, address); } static void handleMasterServerClientRequestedArrangedConnection(const NetAddress* address, BitStream* stream, U32 /*key*/, U8 /*flags*/) From f669f31bc93fa8a20522d6d1e14a20641caa01d7 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Thu, 4 May 2023 12:40:20 +0530 Subject: [PATCH 18/46] fix memory leak --- engine/source/game/net/serverQuery.cpp | 28 +++++++++++++------------- engine/source/sim/netConnection.cpp | 2 +- engine/source/sim/netConnection.h | 4 ++-- engine/source/sim/netInterface.cpp | 20 +++++++++--------- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 656ab5f9..0a56a2d3 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -2180,7 +2180,7 @@ static void handleMasterServerRelayReady(const NetAddress* address) static void handleMasterServerClientRequestedArrangedConnection(const NetAddress* address, BitStream* stream, U32 /*key*/, U8 /*flags*/) { Con::printf("Received MasterServerClientRequestedArrangedConnection"); - Vector possibleAddresses; + Vector possibleAddresses; U16 clientId; stream->read(&clientId); @@ -2195,12 +2195,12 @@ static void handleMasterServerClientRequestedArrangedConnection(const NetAddress stream->read(&ipbits[2]); stream->read(&ipbits[3]); stream->read(&port); - NetAddress* addr = new NetAddress(); - addr->port = port; - addr->netNum[0] = ipbits[0]; - addr->netNum[1] = ipbits[1]; - addr->netNum[2] = ipbits[2]; - addr->netNum[3] = ipbits[3]; + NetAddress addr; + addr.port = port; + addr.netNum[0] = ipbits[0]; + addr.netNum[1] = ipbits[1]; + addr.netNum[2] = ipbits[2]; + addr.netNum[3] = ipbits[3]; possibleAddresses.push_back(addr); } @@ -2218,7 +2218,7 @@ static void handleMasterServerClientRequestedArrangedConnection(const NetAddress static void handleMasterServerArrangedConnectionAccepted(const NetAddress* address, BitStream* stream, U32 /*key*/, U8 /*flags*/) { - Vector possibleAddresses; + Vector possibleAddresses; Con::printf("Received accept arranged connect response from the master server."); @@ -2232,12 +2232,12 @@ static void handleMasterServerArrangedConnectionAccepted(const NetAddress* addre stream->read(&ipbits[2]); stream->read(&ipbits[3]); stream->read(&port); - NetAddress* addr = new NetAddress(); - addr->port = port; - addr->netNum[0] = ipbits[0]; - addr->netNum[1] = ipbits[1]; - addr->netNum[2] = ipbits[2]; - addr->netNum[3] = ipbits[3]; + NetAddress addr; + addr.port = port; + addr.netNum[0] = ipbits[0]; + addr.netNum[1] = ipbits[1]; + addr.netNum[2] = ipbits[2]; + addr.netNum[3] = ipbits[3]; possibleAddresses.push_back(addr); } diff --git a/engine/source/sim/netConnection.cpp b/engine/source/sim/netConnection.cpp index 4a944fef..894bd020 100644 --- a/engine/source/sim/netConnection.cpp +++ b/engine/source/sim/netConnection.cpp @@ -1032,7 +1032,7 @@ void NetConnection::connect(const NetAddress* address) } #ifdef TORQUE_NET_HOLEPUNCHING -void NetConnection::connectArranged(const Vector &possibleAddresses, bool isInitiator) +void NetConnection::connectArranged(const Vector &possibleAddresses, bool isInitiator) { //mConnectionParameters.mRequestKeyExchange = requestsKeyExchange; //mConnectionParameters.mRequestCertificate = requestsCertificate; diff --git a/engine/source/sim/netConnection.h b/engine/source/sim/netConnection.h index c5007f86..08ec62cc 100644 --- a/engine/source/sim/netConnection.h +++ b/engine/source/sim/netConnection.h @@ -322,7 +322,7 @@ struct ConnectionParameters //bool mRequestCertificate; ///< The client is requesting a certificate //U8 mSymmetricKey[SymmetricCipher::KeySize]; ///< The symmetric key for the connection, generated by the client //U8 mInitVector[SymmetricCipher::KeySize]; ///< The init vector, generated by the server - Vector mPossibleAddresses; ///< List of possible addresses for the remote host in an arranged connection. + Vector mPossibleAddresses; ///< List of possible addresses for the remote host in an arranged connection. bool mIsInitiator; ///< True if this host initiated the arranged connection. //bool mIsLocal; ///< True if this is a connectLocal connection. //ByteBufferPtr mArrangedSecret; ///< The shared secret as arranged by the connection intermediary. @@ -460,7 +460,7 @@ class NetConnection : public ConnectionProtocol, public SimGroup void connect(const NetAddress* address); #ifdef TORQUE_NET_HOLEPUNCHING - void connectArranged(const Vector &possibleAddresses, bool isInitiator); + void connectArranged(const Vector &possibleAddresses, bool isInitiator); #endif //---------------------------------------------------------------- diff --git a/engine/source/sim/netInterface.cpp b/engine/source/sim/netInterface.cpp index 7991f54d..95bc8be2 100644 --- a/engine/source/sim/netInterface.cpp +++ b/engine/source/sim/netInterface.cpp @@ -482,13 +482,13 @@ void NetInterface::sendPunchPackets(NetConnection *conn) for(S32 i = 0; i < theParams.mPossibleAddresses.size(); i++) { - BitStream::sendPacketStream(theParams.mPossibleAddresses[i]); + BitStream::sendPacketStream(&theParams.mPossibleAddresses[i]); Con::printf("Sending punch packets to %d.%d.%d.%d:%d", - theParams.mPossibleAddresses[i]->netNum[0], - theParams.mPossibleAddresses[i]->netNum[1], - theParams.mPossibleAddresses[i]->netNum[2], - theParams.mPossibleAddresses[i]->netNum[3], - theParams.mPossibleAddresses[i]->port); + theParams.mPossibleAddresses[i].netNum[0], + theParams.mPossibleAddresses[i].netNum[1], + theParams.mPossibleAddresses[i].netNum[2], + theParams.mPossibleAddresses[i].netNum[3], + theParams.mPossibleAddresses[i].port); } conn->mConnectSendCount++; conn->mConnectLastSendTime = Platform::getVirtualMilliseconds(); //getCurrentTime(); @@ -514,7 +514,7 @@ void NetInterface::handlePunch(const NetAddress* theAddress, BitStream *stream) // first see if the address is in the possible addresses list: for(j = 0; j < theParams.mPossibleAddresses.size(); j++) - if(theAddress == theParams.mPossibleAddresses[j]) + if(theAddress == &theParams.mPossibleAddresses[j]) break; // if there was an exact match, just exit the loop, or @@ -533,7 +533,7 @@ void NetInterface::handlePunch(const NetAddress* theAddress, BitStream *stream) // as only the port is not an exact match: for(j = 0; j < theParams.mPossibleAddresses.size(); j++) - if(Net::compareAddresses(theAddress, theParams.mPossibleAddresses[j])) + if(Net::compareAddresses(theAddress, &theParams.mPossibleAddresses[j])) break; // if the address wasn't even partially in the list, just exit out @@ -543,7 +543,7 @@ void NetInterface::handlePunch(const NetAddress* theAddress, BitStream *stream) // otherwise, as long as we don't have too many ping addresses, // add this one to the list: if(theParams.mPossibleAddresses.size() < 5) - theParams.mPossibleAddresses.push_back(theAddress); + theParams.mPossibleAddresses.push_back(*theAddress); // if this is the initiator of the arranged connection, then // process the punch packet from the remote host by issueing a @@ -597,7 +597,7 @@ void NetInterface::handleArrangedConnectRequest(const NetAddress* theAddress, Bi ConnectionParameters &theParams = conn->getConnectionParameters(); for(j = 0; j < theParams.mPossibleAddresses.size(); j++) - if(Net::compareAddresses(theAddress, theParams.mPossibleAddresses[j])) + if(Net::compareAddresses(theAddress, &theParams.mPossibleAddresses[j])) break; if(j != theParams.mPossibleAddresses.size()) break; From 01e5df0d5025bdef40336860ec17c099ab100e38 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Thu, 4 May 2023 12:42:51 +0530 Subject: [PATCH 19/46] set default search port to 0 if not specified --- engine/source/game/net/serverQuery.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 0a56a2d3..3d568b05 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -566,6 +566,9 @@ ConsoleMethod(NetConnection, arrangeConnection, void, 3, 3, "NetConnection.arran addrText = dStrdup(argv[2]); Net::stringToAddress(addrText, &addr); + if (!dStrchr(addrText, ':')) + addr.port = 0; + ConnectionParameters& params = arrangeNetConnection->getConnectionParameters(); params.mToConnectAddress = addr; @@ -583,6 +586,9 @@ ConsoleMethod(NetConnection, relayConnection, void, 3, 3, "NetConnection.relayCo NetAddress addr; char* addrText; + if (!dStrchr(addrText, ':')) + addr.port = 0; + addrText = dStrdup(argv[2]); Net::stringToAddress(addrText, &addr); From 93a45c58361292d4a9070cb08ee3d89a000526ce Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Thu, 4 May 2023 18:27:05 +0530 Subject: [PATCH 20/46] fallback to LAN only if no master servers found --- game/marble/client/ui/findGameGui.gui | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/game/marble/client/ui/findGameGui.gui b/game/marble/client/ui/findGameGui.gui index ff1d97ab..9948ac5c 100644 --- a/game/marble/client/ui/findGameGui.gui +++ b/game/marble/client/ui/findGameGui.gui @@ -122,6 +122,11 @@ function onServerQueryStatus(%status, %msg, %value) { if (%status !$= "done" && %status !$= "error") return; + + if (%value == 0) // No master servers found + $queryOffline = true; + else + $queryOffline = false; eval($pcsearchcallback); } @@ -440,7 +445,7 @@ function FindGameGui::onSearchComplete(%this,%type) if (isPCBuild() || !$Client::UseXBLiveMatchMaking) { %sc = getServerCount(); - if (%sc == 0 && %this.useMaster) + if ($queryOffline && %this.useMaster) { %this.useMaster = false; @@ -461,7 +466,10 @@ function FindGameGui::onSearchComplete(%this,%type) // for testing //%ping = 120; %gameIcon = ""; - %rowText = %playerStr TAB %gameIcon TAB %ping TAB "1" TAB %i TAB "\c1" @ "LAN:" SPC $ServerInfo::Name; // 1 == is pc result + if ($ServerInfo::IsLocal) + %rowText = %playerStr TAB %gameIcon TAB %ping TAB "1" TAB %i TAB "\c1" @ "LAN:" SPC $ServerInfo::Name; // 1 == is pc result + else + %rowText = %playerStr TAB %gameIcon TAB %ping TAB "1" TAB %i TAB "\c1" @ $ServerInfo::Name; // 1 == is pc result FindGameServerList.addRow(%count, %rowText); %this.updatePingIcon(%count); %count++; From 2f576281664c3ed7b2aee61446bbdc6f28fcdd5c Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Thu, 4 May 2023 19:26:48 +0530 Subject: [PATCH 21/46] Fix leaks, and connect locally --- engine/source/game/net/serverQuery.cpp | 59 ++++++++++++++++++++++++-- game/marble/client/init.cs | 2 +- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 3d568b05..c8ebfca7 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -94,6 +94,7 @@ // This is basically the server query protocol version now: static const char* versionString = "VER1"; +Vector localNetAddresses; Vector gServerList(__FILE__, __LINE__); static Vector gMasterServerList(__FILE__, __LINE__); static Vector gFinishedList(__FILE__, __LINE__); // timed out servers and finished servers go here @@ -569,6 +570,8 @@ ConsoleMethod(NetConnection, arrangeConnection, void, 3, 3, "NetConnection.arran if (!dStrchr(addrText, ':')) addr.port = 0; + dFree(addrText); + ConnectionParameters& params = arrangeNetConnection->getConnectionParameters(); params.mToConnectAddress = addr; @@ -586,16 +589,36 @@ ConsoleMethod(NetConnection, relayConnection, void, 3, 3, "NetConnection.relayCo NetAddress addr; char* addrText; + addrText = dStrdup(argv[2]); + + Net::stringToAddress(addrText, &addr); + if (!dStrchr(addrText, ':')) addr.port = 0; - addrText = dStrdup(argv[2]); - Net::stringToAddress(addrText, &addr); + dFree(addrText); getRelayServer(&addr); } #endif +ConsoleFunction(isLocalAddress, bool, 2, 2, "isLocalAddress(addr);") +{ + NetAddress addr; + Net::stringToAddress(argv[1], &addr); + + bool found = false; + for (U32 i = 0; i < localNetAddresses.size(); i++) + { + if (Net::compareAddresses(&localNetAddresses[i], &addr)) + { + found = true; + break; + } + } + return found; +} + //----------------------------------------------------------------------------- ConsoleFunction(querySingleServer, void, 3, 3, "querySingleServer(address, flags);") @@ -610,6 +633,9 @@ ConsoleFunction(querySingleServer, void, 3, 3, "querySingleServer(address, flags Net::stringToAddress(addrText, &addr); + + dFree(addrText); + querySingleServer(&addr, flags); } @@ -898,6 +924,7 @@ void clearServerList(bool clearServerInfo) gPingList.clear(); gQueryList.clear(); gServerPingCount = gServerQueryCount = 0; + localNetAddresses.clear(); gPingSession++; } @@ -1074,6 +1101,25 @@ static void removeServerInfo(const NetAddress* addr) //----------------------------------------------------------------------------- +static void addLocalAddress(const NetAddress* addr) +{ + bool found = false; + for (U32 i = 0; i < localNetAddresses.size(); i++) + { + if (Net::compareAddresses(addr, &localNetAddresses[i])) + { + found = true; + break; + } + } + if (!found) + { + localNetAddresses.push_back(*addr); + } +} + +//----------------------------------------------------------------------------- + #if defined(TORQUE_DEBUG) // This function is solely for testing the functionality of the server browser // with more servers in the list. @@ -1575,7 +1621,7 @@ static void handleMasterServerGameTypesResponse(BitStream* stream, U32 /*key*/, //----------------------------------------------------------------------------- -static void handleMasterServerListResponse(BitStream* stream, U32 key, U8 /*flags*/) +static void handleMasterServerListResponse(BitStream* stream, U32 key, U8 flags) { U8 packetIndex, packetTotal; U32 i; @@ -1619,6 +1665,13 @@ static void handleMasterServerListResponse(BitStream* stream, U32 key, U8 /*flag dSprintf(addressBuffer, sizeof(addressBuffer), "IP:%d.%d.%d.%d:%d", netNum[0], netNum[1], netNum[2], netNum[3], port); Net::stringToAddress(addressBuffer, &addr); + + if (flags) + { + // This is *our* own public IP + addLocalAddress(&addr); + } + pushPingRequest(&addr); } diff --git a/game/marble/client/init.cs b/game/marble/client/init.cs index 9ae280cf..07bdc8eb 100644 --- a/game/marble/client/init.cs +++ b/game/marble/client/init.cs @@ -646,7 +646,7 @@ function establishConnection(%address, %mp, %isLocal, %invited) } $Client::connectedMultiplayer = true; $Game::SPGemHunt = false; - if (%isLocal) + if (%isLocal || isLocalAddress(%address)) %conn.connect(%address); else %conn.arrangeConnection(%address); From 953f721f6ffc76de411c4eb64650a4389635cab0 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Fri, 5 May 2023 01:07:11 +0530 Subject: [PATCH 22/46] Initial private games support --- engine/source/game/net/serverQuery.cpp | 2 ++ engine/source/game/net/serverQuery.h | 1 + game/common/local/englishStrings.inf | 1 + game/marble/client/ui/createGameGui.gui | 10 +++++++--- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index c8ebfca7..498e92de 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -1756,6 +1756,8 @@ static void handleGameMasterInfoRequest(const NetAddress* address, U32 key, U8 f temp8 |= ServerInfo::Status_Dedicated; if (dStrlen(Con::getVariable("Pref::Server::Password")) > 0) temp8 |= ServerInfo::Status_Passworded; + if (Con::getBoolVariable("Server::IsPrivate")) + temp8 |= ServerInfo::Status_Private; out->write(temp8); temp8 = U8(Con::getIntVariable("Server::BotCount")); out->write(temp8); diff --git a/engine/source/game/net/serverQuery.h b/engine/source/game/net/serverQuery.h index d3b0cc0d..446fa18e 100644 --- a/engine/source/game/net/serverQuery.h +++ b/engine/source/game/net/serverQuery.h @@ -45,6 +45,7 @@ struct ServerInfo Status_Dedicated = BIT(0), Status_Passworded = BIT(1), Status_Linux = BIT(2), + Status_Private = BIT(3), // Status flags: Status_New = 0, diff --git a/game/common/local/englishStrings.inf b/game/common/local/englishStrings.inf index 40dae33c..28ac54ac 100644 --- a/game/common/local/englishStrings.inf +++ b/game/common/local/englishStrings.inf @@ -259,6 +259,7 @@ $Text::FGG_Players = "Players"; $Text::Mission = "Level"; $Text::MaxPlayers = "Max Players"; $Text::PrivateSlots = "Private Slots"; +$Text::IsPrivate = "Private Game"; ;------------------------------------------------------------------------------- ; Leaderboard Select Menu diff --git a/game/marble/client/ui/createGameGui.gui b/game/marble/client/ui/createGameGui.gui index 673f6b4d..4bbd0ce7 100644 --- a/game/marble/client/ui/createGameGui.gui +++ b/game/marble/client/ui/createGameGui.gui @@ -9,8 +9,8 @@ new GuiControl(CreateGameGui) { new GuiXboxOptionListCtrl(CreateGameOptionList) { profile = isWidescreen()? "TextOptionListProfile" : "TextOptionListSmallWideProfile"; - position = isWidescreen()? "360 373" : "-20 195"; - extent = isWidescreen()? "835 400" : "660 250"; + position = isWidescreen()? "360 323" : "-20 145"; + extent = isWidescreen()? "835 430" : "660 280"; horizSizing = isWidescreen()? "right" : "left"; vertSizing = isWidescreen()? "bottom" : "top"; // there can only be two columns; these values are percentages of total extent @@ -74,11 +74,14 @@ function CreateGameGui::show(%this,%backGui) %this.missionIndex = 0; %this.maxPlayersIndex = 1; %this.privateSlotsIndex = 2; + %this.privateGameIndex = 3; CreateGameOptionList.addRow($Text::Mission, GameMissionInfo.getMissionDisplayNameList(), 18); CreateGameOptionList.addRow($Text::MaxPlayers, GetOptionListRangeText(%this.maxPlayersMin, $Server::AbsMaxPlayers), 8); if( allowPrivateSlots() ) CreateGameOptionList.addRow($Text::PrivateSlots, $Text::None TAB GetOptionListRangeText(1, $Server::AbsMaxPlayers), 8); + + CreateGameOptionList.addRow($Text::IsPrivate, $Text::No TAB $Text::Yes, 8); //CreateGameOptionList.addRow($Text::GM23, $Text::S40 TAB GetOptionListRangeText(1, $Server::AbsMaxBots)); //CreateGameOptionList.addRow($Text::GM29, GetOptionListRangeText(5, 15, 5)); @@ -310,7 +313,8 @@ function CreateGameGui::createGame(%this) $pref::Server::missionId = $Server::MissionId; $pref::Server::MaxPlayers = CreateGameOptionList.getOptionIndex(%this.maxPlayersIndex) + CreateGameGui.maxPlayersMin; - + $Server::IsPrivate = CreateGameOptionList.getOptionIndex(%this.privateGameIndex); + if( allowPrivateSlots() ) $pref::Server::PrivateSlots = CreateGameOptionList.getOptionIndex(%this.privateSlotsIndex); else From 05c08aee38b5ad4cc333aeedd1326594f0e48a37 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sat, 6 May 2023 02:04:09 +0530 Subject: [PATCH 23/46] UI for joining games (not functional yet) --- .../gui/controls/guiXboxOptionListCtrl.cpp | 6 +- game/common/local/englishStrings.inf | 2 + game/common/server/clientConnection.cs | 5 + game/marble/client/init.cs | 1 + game/marble/client/ui/GamePauseGui.gui | 4 + game/marble/client/ui/createGameGui.gui | 13 + game/marble/client/ui/defaultGameProfiles.cs | 21 ++ game/marble/client/ui/joinGameGui.gui | 245 ++++++++++++++++++ game/marble/client/ui/lobbyGui.gui | 4 +- game/marble/client/ui/multiPlayerGui.gui | 6 +- 10 files changed, 303 insertions(+), 4 deletions(-) create mode 100644 game/marble/client/ui/joinGameGui.gui diff --git a/engine/source/gui/controls/guiXboxOptionListCtrl.cpp b/engine/source/gui/controls/guiXboxOptionListCtrl.cpp index 2b10dd65..47c82038 100644 --- a/engine/source/gui/controls/guiXboxOptionListCtrl.cpp +++ b/engine/source/gui/controls/guiXboxOptionListCtrl.cpp @@ -500,7 +500,8 @@ void GuiXboxOptionListCtrl::onRender(Point2I offset, const RectI& updateRect) rect.extent.set(bitmapArrowWidth, bitmapArrowHeight); } - GFX->drawBitmapStretchSR(mProfile->mTextureObject, rect, mProfile->mBitmapArrayRects[leftArrowIndex]); + if (mButtonsEnabled) + GFX->drawBitmapStretchSR(mProfile->mTextureObject, rect, mProfile->mBitmapArrayRects[leftArrowIndex]); } S32 rightArrowIndex = unselectedRightArrowIndex; @@ -563,7 +564,8 @@ void GuiXboxOptionListCtrl::onRender(Point2I offset, const RectI& updateRect) rect.extent.set(bitmapArrowWidth, bitmapArrowHeight); } - GFX->drawBitmapStretchSR(mProfile->mTextureObject, rect, mProfile->mBitmapArrayRects[rightArrowIndex]); + if (mButtonsEnabled) + GFX->drawBitmapStretchSR(mProfile->mTextureObject, rect, mProfile->mBitmapArrayRects[rightArrowIndex]); } #ifndef MBO_UNTOUCHED_MENUS diff --git a/game/common/local/englishStrings.inf b/game/common/local/englishStrings.inf index 28ac54ac..bd98f91e 100644 --- a/game/common/local/englishStrings.inf +++ b/game/common/local/englishStrings.inf @@ -230,6 +230,7 @@ $Text::Select = "Select"; $Text::QuickMatch = "Quick Match"; $Text::OptiMatch = "Custom Match"; $Text::CreateMatch = "Create Match"; +$Text::JoinMatch = "Join Match"; $Text::Players = "Players"; $Text::Ready = "Ready"; $Text::ExitGame = "Exit"; @@ -274,6 +275,7 @@ $Text::LobbyHostName = "Host:"; $Text::LobbyHostLevel = "Level:"; $Text::LobbyHostPrivateSlots = "Private Slots"; $Text::LobbyHostPublicSlots = "Public Slots"; +$Text::LobbyHostInviteCode = "Invite Code"; ; separators $Text::Colon = ":"; diff --git a/game/common/server/clientConnection.cs b/game/common/server/clientConnection.cs index 82ee88c2..6a43d9e9 100644 --- a/game/common/server/clientConnection.cs +++ b/game/common/server/clientConnection.cs @@ -83,6 +83,11 @@ function updateServerParams() return "CR_DEMOREJECT"; } } + + if (%invited !$= "" && %invited !$= $Server::InviteCode) + { + return "CHR_PASSWORD"; + } // kick any players with this xblive id //if (%xbLiveId !$= "") // TODO: uncomment when this is set up in the engine diff --git a/game/marble/client/init.cs b/game/marble/client/init.cs index 07bdc8eb..963bd303 100644 --- a/game/marble/client/init.cs +++ b/game/marble/client/init.cs @@ -134,6 +134,7 @@ function initClient() exec("./ui/GameEndGui.gui"); exec("./ui/StartupErrorGui.gui"); exec("./ui/controlerDisplayGui.gui"); + exec("./ui/joinGameGui.gui"); //exec("./ui/AboutGui.gui"); //exec("./ui/LevelScoresGui.gui"); diff --git a/game/marble/client/ui/GamePauseGui.gui b/game/marble/client/ui/GamePauseGui.gui index 1b6deb5f..02a4fab4 100644 --- a/game/marble/client/ui/GamePauseGui.gui +++ b/game/marble/client/ui/GamePauseGui.gui @@ -70,6 +70,10 @@ function GamePauseGui::onWake(%this) LevelTitle.setText(%level); RootGui.setTitle($Text::Paused); + + if ($Server::Hosting) + LevelTitle.setText($Text::LobbyHostInviteCode @ $Text::Colon SPC $Server::InviteCode); + if ($pref::UI::LegacyUI) { RootGui.setA($Text::Go); diff --git a/game/marble/client/ui/createGameGui.gui b/game/marble/client/ui/createGameGui.gui index 4bbd0ce7..d2402410 100644 --- a/game/marble/client/ui/createGameGui.gui +++ b/game/marble/client/ui/createGameGui.gui @@ -294,6 +294,17 @@ function CreateGameGui::onGameCreated(%this) RootGui.setContent(LobbyGui); } +function generateInviteCode() +{ + %availableChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + %code = ""; + for (%i = 0; %i < 6; %i++) + { + %code = %code @ getSubStr(%availableChars, getRandom(0, 35), 1); + } + return %code; +} + function CreateGameGui::createGame(%this) { %this.creatingGame = true; @@ -314,6 +325,8 @@ function CreateGameGui::createGame(%this) $pref::Server::missionId = $Server::MissionId; $pref::Server::MaxPlayers = CreateGameOptionList.getOptionIndex(%this.maxPlayersIndex) + CreateGameGui.maxPlayersMin; $Server::IsPrivate = CreateGameOptionList.getOptionIndex(%this.privateGameIndex); + + $Server::InviteCode = generateInviteCode(); if( allowPrivateSlots() ) $pref::Server::PrivateSlots = CreateGameOptionList.getOptionIndex(%this.privateSlotsIndex); diff --git a/game/marble/client/ui/defaultGameProfiles.cs b/game/marble/client/ui/defaultGameProfiles.cs index e51b8af0..fbe433f3 100644 --- a/game/marble/client/ui/defaultGameProfiles.cs +++ b/game/marble/client/ui/defaultGameProfiles.cs @@ -182,6 +182,27 @@ hitArea = "20 76"; }; +new GuiControlProfile(TextEditProfile) +{ + fontType = "Arial Bold"; + opaque = true; + fillColor = "0 0 0 0"; + fillColorHL = "0 0 0 0"; + border = false; + borderThickness = 2; + borderColor = "0 0 0"; + fontColor = $XBOX::MenuTextColor; + fontColorHL = $XBOX::MenuTextColorSelected; + fontColorNA = $XBOX::MenuTextColorDisabled; + textOffset = "0 2"; + autoSizeWidth = false; + autoSizeHeight = true; + tab = true; + canKeyFocus = true; + + fontSize = 24; +}; + new GuiControlProfile(TextMenuListSmallProfile : TextMenuListProfile) { fontSize = 24; diff --git a/game/marble/client/ui/joinGameGui.gui b/game/marble/client/ui/joinGameGui.gui new file mode 100644 index 00000000..bdffea2f --- /dev/null +++ b/game/marble/client/ui/joinGameGui.gui @@ -0,0 +1,245 @@ +//--- OBJECT WRITE BEGIN --- +new GuiControl(JoinGameGui) { + profile = "GuiDefaultProfile"; + horizSizing = "width"; + vertSizing = "height"; + extent = "640 480"; + minExtent = "8 8"; + position = "0 0"; + + new GuiXboxOptionListCtrl(InviteCodeMenuCtrl) { + profile = isWidescreen()? "TextOptionListProfile" : "TextOptionListSmallWideProfile"; + position = isWidescreen()? "360 211" : "-30 100"; + extent = isWidescreen()? "835 400" : "672 250"; + horizSizing = isWidescreen()? "right" : "left"; + vertSizing = "center"; + // there can only be two columns; these values are percentages of total extent + columns = isWidescreen()? "40 60" : "49 51"; + // each column can have a left and right margin, specified here. order is + // C1L C1R C2L C2R. amount is in pixels + columnMargins = isWidescreen()? "0 0 3 35" : "0 0 2 25"; + // for debugging, show the region update rect and column rects (with margins) + showRects = 0; + + // data is dynamically added to this option list in the show() function + + new GuiTextCtrl(InviteCodeInput) { + Profile = "TextEditProfile"; + HorizSizing = "right"; + VertSizing = "top"; + position = "640 33"; + Extent = "235 18"; + MinExtent = "8 2"; + Visible = "1"; + text = ""; + }; + + new GuiControl(NumpadCtrl) { + profile = "GuiDefaultProfile"; + horizSizing = "right"; + vertSizing = "top"; + extent = "800 300"; + minExtent = "8 8"; + position = "0 60"; + + new GuiXboxButtonCtrl(Numpad1) { + profile = "TextMenuButtonProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "240 150"; + extent = "120 94"; + minExtent = "8 2"; + bitmap = ""; + bitmapAlign = "right"; + text = "1"; + command = "JoinGameGui.textInput(1);"; + visible = "1"; + }; + + new GuiXboxButtonCtrl(Numpad2) { + profile = "TextMenuButtonProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "320 150"; + extent = "120 94"; + minExtent = "8 2"; + bitmap = ""; + bitmapAlign = "right"; + text = "2"; + command = "JoinGameGui.textInput(2);"; + visible = "1"; + }; + + new GuiXboxButtonCtrl(Numpad3) { + profile = "TextMenuButtonProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "400 150"; + extent = "120 94"; + minExtent = "8 2"; + bitmap = ""; + bitmapAlign = "right"; + text = "3"; + command = "JoinGameGui.textInput(3);"; + visible = "1"; + }; + + new GuiXboxButtonCtrl(Numpad4) { + profile = "TextMenuButtonProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "240 80"; + extent = "120 94"; + minExtent = "8 2"; + bitmap = ""; + bitmapAlign = "right"; + text = "4"; + command = "JoinGameGui.textInput(4);"; + visible = "1"; + }; + + new GuiXboxButtonCtrl(Numpad5) { + profile = "TextMenuButtonProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "320 80"; + extent = "120 94"; + minExtent = "8 2"; + bitmap = ""; + bitmapAlign = "right"; + text = "5"; + command = "JoinGameGui.textInput(5);"; + visible = "1"; + }; + + new GuiXboxButtonCtrl(Numpad6) { + profile = "TextMenuButtonProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "400 80"; + extent = "120 94"; + minExtent = "8 2"; + bitmap = ""; + bitmapAlign = "right"; + text = "6"; + command = "JoinGameGui.textInput(6);"; + visible = "1"; + }; + + new GuiXboxButtonCtrl(Numpad7) { + profile = "TextMenuButtonProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "240 10"; + extent = "120 94"; + minExtent = "8 2"; + bitmap = ""; + bitmapAlign = "right"; + text = "7"; + command = "JoinGameGui.textInput(7);"; + visible = "1"; + }; + + new GuiXboxButtonCtrl(Numpad8) { + profile = "TextMenuButtonProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "320 10"; + extent = "120 94"; + minExtent = "8 2"; + bitmap = ""; + bitmapAlign = "right"; + text = "8"; + command = "JoinGameGui.textInput(8);"; + visible = "1"; + }; + + new GuiXboxButtonCtrl(Numpad9) { + profile = "TextMenuButtonProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "400 10"; + extent = "120 94"; + minExtent = "8 2"; + bitmap = ""; + bitmapAlign = "right"; + text = "9"; + command = "JoinGameGui.textInput(9);"; + visible = "1"; + }; + + new GuiXboxButtonCtrl(Numpad0) { + profile = "TextMenuButtonProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "240 220"; + extent = "120 94"; + minExtent = "8 2"; + bitmap = ""; + bitmapAlign = "right"; + text = "0"; + command = "JoinGameGui.textInput(0);"; + visible = "1"; + }; + + new GuiXboxButtonCtrl(NumpadDel) { + profile = "TextMenuButtonProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "400 220"; + extent = "120 94"; + minExtent = "8 2"; + bitmap = ""; + bitmapAlign = "right"; + text = "Delete"; + command = "JoinGameGui.textInput(D);"; + visible = "1"; + }; + }; + }; +}; + +function JoinGameGui::show(%this) +{ + RootGui.setTitle($Text::JoinGame); + RootGui.setB($Text::Back); + RootGui.setA($Text::Go); + + JoinGameGui.inviteCode = ""; + InviteCodeInput.setText(JoinGameGui.inviteCode); + + InviteCodeMenuCtrl.clear(); + InviteCodeMenuCtrl.addRow("Invite Code", "", 8); + InviteCodeMenuCtrl.setButtonsEnabled(false); +} + +function JoinGameGui::onA(%this) +{ +} + +function JoinGameGui::onB(%this) +{ + sfxPlay( AudioButtonDown ); + %this.exit(); + return true; +} + +function JoinGameGui::exit(%this) +{ + RootGui.setContent(MultiPlayerGui); +} + +function JoinGameGui::textInput(%this, %chr) +{ + if (%chr !$= "D") + { + if (strlen(JoinGameGui.inviteCode) < 6) + JoinGameGui.inviteCode = JoinGameGui.inviteCode @ %chr; + } + else + { + if (strlen(JoinGameGui.inviteCode) > 0) + JoinGameGui.inviteCode = getSubStr(JoinGameGui.inviteCode, 0, strlen(JoinGameGui.inviteCode) - 1); + } + InviteCodeInput.setText(JoinGameGui.inviteCode); +} \ No newline at end of file diff --git a/game/marble/client/ui/lobbyGui.gui b/game/marble/client/ui/lobbyGui.gui index d7924594..725f7f7d 100644 --- a/game/marble/client/ui/lobbyGui.gui +++ b/game/marble/client/ui/lobbyGui.gui @@ -704,7 +704,9 @@ function LobbyGui::setHostInfo(%this, %hostName, %gameMode, %mapname, %priSlotsU "" @ $Text::LobbyHostPrivateSlots @ $Text::Colon SPC %priSlotsUsed @ $Text::Slash @ %priSlotsFree + %priSlotsUsed @ $Text::Comma SPC $Text::LobbyHostPublicSlots @ $Text::Colon SPC - %pubSlotsUsed @ $Text::Slash @ %pubSlotsFree + %pubSlotsUsed @ " "); + %pubSlotsUsed @ $Text::Slash @ %pubSlotsFree + %pubSlotsUsed @ + $Text::Comma SPC $Text::LobbyHostInviteCode @ $Text::Colon SPC + $Server::InviteCode @ " "); LobbyGuiSelection.clear(); LobbyGuiSelection.setButtonsEnabled(%this.hosting); diff --git a/game/marble/client/ui/multiPlayerGui.gui b/game/marble/client/ui/multiPlayerGui.gui index 4abf198d..b76230b2 100644 --- a/game/marble/client/ui/multiPlayerGui.gui +++ b/game/marble/client/ui/multiPlayerGui.gui @@ -49,10 +49,13 @@ function MultiPlayerGui::onA(%this) } RootGui.setContent(CreateGameGui); + case 3: + RootGui.setContent(JoinGameGui); + case 4: // Auto enter the MP leaderboards RootGui.setContent( LevelScoresGui, GameMissionInfo.MPMode, $Leaderboard::MPScrumOverall, %this ); - case 4: + case 5: // Show marketplace UI, this is kinda hacked since it's not a demo launch clientShowMarketplaceUI(); $PDLCMarketView = true; @@ -133,6 +136,7 @@ function MultiPlayerGui::show(%this) MultiPlayerMenu.addRow($Text::QuickMatch, "", 0, 2); MultiPlayerMenu.addRow($Text::OptiMatch, "", 0, 2); MultiPlayerMenu.addRow($Text::CreateMatch, "", 0, 2); + MultiPlayerMenu.addRow($Text::JoinMatch, "", 0, 2); MultiPlayerMenu.addRow($Text::LeaderBoards, "", 0, 6); RootGui.setTitle($Text::MultiplayerMenu); From 607cd354a2424b2d8ac41b765c5427a4d31624ae Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sat, 6 May 2023 13:47:53 +0530 Subject: [PATCH 24/46] join game gui numpad finish --- .../source/gui/controls/guiXboxButtonCtrl.cpp | 20 +++++ .../source/gui/controls/guiXboxButtonCtrl.h | 1 + game/marble/client/ui/createGameGui.gui | 4 +- game/marble/client/ui/joinGameGui.gui | 80 ++++++++++++++++++- 4 files changed, 101 insertions(+), 4 deletions(-) diff --git a/engine/source/gui/controls/guiXboxButtonCtrl.cpp b/engine/source/gui/controls/guiXboxButtonCtrl.cpp index 9f10827f..b6c53984 100644 --- a/engine/source/gui/controls/guiXboxButtonCtrl.cpp +++ b/engine/source/gui/controls/guiXboxButtonCtrl.cpp @@ -89,6 +89,12 @@ ConsoleMethod(GuiXboxButtonCtrl, getText, const char*, 2, 2, "() - returns the t return object->getText(); } +ConsoleMethod(GuiXboxButtonCtrl, setHover, void, 3, 3, "(hover) - sets the button hover state.") +{ + argc; argv; + object->setButtonHover(atoi(argv[2])); +} + //-------------------------------------------------------- // Misc //-------------------------------------------------------- @@ -104,6 +110,20 @@ ConsoleMethod(GuiXboxButtonCtrl, getText, const char*, 2, 2, "() - returns the t // } //} +void GuiXboxButtonCtrl::setButtonHover(bool hover) +{ + if (hover) + { + mButtonState = Hover; + mHovering = true; + } + else + { + mButtonState = Normal; + mHovering = false; + } +} + void GuiXboxButtonCtrl::setText(const char* text) { // Hacky workaround to make hover not persist between guis diff --git a/engine/source/gui/controls/guiXboxButtonCtrl.h b/engine/source/gui/controls/guiXboxButtonCtrl.h index 0441f005..abefe997 100644 --- a/engine/source/gui/controls/guiXboxButtonCtrl.h +++ b/engine/source/gui/controls/guiXboxButtonCtrl.h @@ -32,6 +32,7 @@ class GuiXboxButtonCtrl : public GuiControl static void initPersistFields(); //void setVisible(bool value) override; + void setButtonHover(bool hover); void setText(const char* text); void setTextID(S32 id); void setTextID(const char* id); diff --git a/game/marble/client/ui/createGameGui.gui b/game/marble/client/ui/createGameGui.gui index d2402410..06116e8b 100644 --- a/game/marble/client/ui/createGameGui.gui +++ b/game/marble/client/ui/createGameGui.gui @@ -296,11 +296,11 @@ function CreateGameGui::onGameCreated(%this) function generateInviteCode() { - %availableChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + %availableChars = "0123456789"; %code = ""; for (%i = 0; %i < 6; %i++) { - %code = %code @ getSubStr(%availableChars, getRandom(0, 35), 1); + %code = %code @ getSubStr(%availableChars, getRandom(0, 9), 1); } return %code; } diff --git a/game/marble/client/ui/joinGameGui.gui b/game/marble/client/ui/joinGameGui.gui index bdffea2f..ccca11d4 100644 --- a/game/marble/client/ui/joinGameGui.gui +++ b/game/marble/client/ui/joinGameGui.gui @@ -182,6 +182,20 @@ new GuiControl(JoinGameGui) { visible = "1"; }; + new GuiXboxButtonCtrl(NumpadOK) { + profile = "TextMenuButtonProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "320 220"; + extent = "120 94"; + minExtent = "8 2"; + bitmap = ""; + bitmapAlign = "right"; + text = "Ok"; + command = "JoinGameGui.joinGame();"; + visible = "1"; + }; + new GuiXboxButtonCtrl(NumpadDel) { profile = "TextMenuButtonProfile"; horizSizing = "right"; @@ -203,18 +217,38 @@ function JoinGameGui::show(%this) { RootGui.setTitle($Text::JoinGame); RootGui.setB($Text::Back); - RootGui.setA($Text::Go); - + JoinGameGui.inviteCode = ""; InviteCodeInput.setText(JoinGameGui.inviteCode); InviteCodeMenuCtrl.clear(); InviteCodeMenuCtrl.addRow("Invite Code", "", 8); InviteCodeMenuCtrl.setButtonsEnabled(false); + + $NumpadGrid[0, -1] = Numpad0; + $NumpadGrid[0, 0] = Numpad1; + $NumpadGrid[1, 0] = Numpad2; + $NumpadGrid[2, 0] = Numpad3; + $NumpadGrid[0, 1] = Numpad4; + $NumpadGrid[1, 1] = Numpad5; + $NumpadGrid[2, 1] = Numpad6; + $NumpadGrid[0, 2] = Numpad7; + $NumpadGrid[1, 2] = Numpad8; + $NumpadGrid[2, 2] = Numpad9; + $NumpadGrid[2, -1] = NumpadDel; + $NumpadGrid[1, -1] = NumpadOk; + + $NumpadCoordX = 0; + $NumpadCoordY = 0; + + $NumpadCtrl = Numpad1; } function JoinGameGui::onA(%this) { + sfxPlay( AudioButtonDown ); + eval($NumpadCtrl.command); + return true; } function JoinGameGui::onB(%this) @@ -229,6 +263,11 @@ function JoinGameGui::exit(%this) RootGui.setContent(MultiPlayerGui); } +function JoinGameGui::joinGame(%this) +{ + echo("Joining game with invite code " @ JoinGameGui.inviteCode); +} + function JoinGameGui::textInput(%this, %chr) { if (%chr !$= "D") @@ -242,4 +281,41 @@ function JoinGameGui::textInput(%this, %chr) JoinGameGui.inviteCode = getSubStr(JoinGameGui.inviteCode, 0, strlen(JoinGameGui.inviteCode) - 1); } InviteCodeInput.setText(JoinGameGui.inviteCode); +} + +function JoinGameGui::moveDir(%this, %x, %y) +{ + $NumpadCoordX += %x; + $NumpadCoordY += %y; + if ($NumpadCoordX > 2) $NumpadCoordX = 0; + if ($NumpadCoordX < 0) $NumpadCoordX = 2; + if ($NumpadCoordY > 2) $NumpadCoordY = -1; + if ($NumpadCoordY < -1) $NumpadCoordY = 2; + $NumpadCtrl.setHover(false); + $NumpadCtrl = $NumpadGrid[$NumpadCoordX, $NumpadCoordY]; + $NumpadCtrl.setHover(true); +} + +function InviteCodeInput::onLeft(%this, %pressed) +{ + JoinGameGui.moveDir(-1, 0); + return true; +} + +function InviteCodeInput::onRight(%this, %pressed) +{ + JoinGameGui.moveDir(1, 0); + return true; +} + +function InviteCodeInput::onUp(%this, %pressed) +{ + JoinGameGui.moveDir(0, 1); + return true; +} + +function InviteCodeInput::onDown(%this, %pressed) +{ + JoinGameGui.moveDir(0, -1); + return true; } \ No newline at end of file From cf5cf995b5fce31cd738ac72ec7a4723519aead7 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sat, 6 May 2023 14:38:03 +0530 Subject: [PATCH 25/46] support join via invite code --- engine/source/game/net/serverQuery.cpp | 61 ++++++++++++++++++++++++++ game/marble/client/ui/joinGameGui.gui | 16 +++++++ 2 files changed, 77 insertions(+) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 498e92de..8006ad63 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -1742,6 +1742,7 @@ static void handleGameMasterInfoRequest(const NetAddress* address, U32 key, U8 f writeCString(out, Con::getVariable("Server::GameType")); writeCString(out, Con::getVariable("Server::MissionType")); + writeCString(out, Con::getVariable("Server::InviteCode")); temp8 = U8(Con::getIntVariable("Pref::Server::MaxPlayers")); out->write(temp8); temp32 = Con::getIntVariable("Server::RegionMask");//"Pref::Server::RegionMask"); @@ -2188,6 +2189,35 @@ static void handleGameInfoResponse(const NetAddress* address, BitStream* stream, #ifdef TORQUE_NET_HOLEPUNCHING +static char* joinGameAcceptCb = NULL; +static char* joinGameRejectCb = NULL; + +static void joinGameByInvite(const char* inviteCode) +{ + BitStream* stream = BitStream::getPacketStream(); + stream->write(U8(NetInterface::MasterServerJoinInvite)); + writeCString(stream, inviteCode); + + Vector* serverList = getMasterServerList(); + + for (int i = 0; i < serverList->size(); i++) + { + BitStream::sendPacketStream(&(*serverList)[i].address); + } +} + +ConsoleFunction(joinGameByInvite, void, 4, 4, "joinGameByInvite(inviteCode, acceptCb(%ip), rejectCb)") +{ + if (joinGameAcceptCb) + dFree(joinGameAcceptCb); + if (joinGameRejectCb) + dFree(joinGameRejectCb); + + joinGameAcceptCb = dStrdup(argv[2]); + joinGameRejectCb = dStrdup(argv[3]); + joinGameByInvite(argv[1]); +} + static void getRelayServer(const NetAddress* address) { BitStream* stream = BitStream::getPacketStream(); @@ -2363,6 +2393,35 @@ static void handleMasterServerGameInfoResponse(const NetAddress* address, BitStr stream->read(&key); handleGameInfoResponse(&theAddress, stream, key, flags); } + +static void handleMasterServerJoinInviteResponse(const NetAddress* address, BitStream* stream) { + U8 found; + stream->read(&found); + if (found) + { + NetAddress theAddress; + theAddress.type = NetAddress::IPAddress; + stream->read(&theAddress.netNum[0]); + stream->read(&theAddress.netNum[1]); + stream->read(&theAddress.netNum[2]); + stream->read(&theAddress.netNum[3]); + stream->read(&theAddress.port); + + char evalbuf[128]; + dSprintf(evalbuf, 128, "%s(\"%d.%d.%d.%d:%d\");", joinGameAcceptCb, theAddress.netNum[0], theAddress.netNum[1], theAddress.netNum[2], theAddress.netNum[3], theAddress.port); + Con::evaluatef(evalbuf); + } + else + { + char evalbuf[64]; + dSprintf(evalbuf, 64, "%s();", joinGameRejectCb); + Con::evaluatef(evalbuf); + } + dFree(joinGameAcceptCb); + dFree(joinGameRejectCb); + joinGameAcceptCb = NULL; + joinGameRejectCb = NULL; +} #endif //----------------------------------------------------------------------------- @@ -2428,6 +2487,8 @@ void DemoNetInterface::handleInfoPacket(const NetAddress* address, U8 packetType case MasterServerRelayReady: handleMasterServerRelayReady(address); break; + case MasterServerJoinInviteResponse: + handleMasterServerJoinInviteResponse(address, stream); #endif } } diff --git a/game/marble/client/ui/joinGameGui.gui b/game/marble/client/ui/joinGameGui.gui index ccca11d4..6ff06cd3 100644 --- a/game/marble/client/ui/joinGameGui.gui +++ b/game/marble/client/ui/joinGameGui.gui @@ -266,6 +266,22 @@ function JoinGameGui::exit(%this) function JoinGameGui::joinGame(%this) { echo("Joining game with invite code " @ JoinGameGui.inviteCode); + joinGameByInvite(JoinGameGui.inviteCode, "joinGameFound", "joinGameNotFound"); + cancel(JoinGameGui.joinTimeout); + JoinGameGui.joinTimeout = schedule(5000, 0, "joinGameNotFound"); + RootGui.setContent(MissionLoadingGui); +} + +function joinGameFound(%ip) +{ + cancel(JoinGameGui.joinTimeout); + establishConnection(%ip, true, false, JoinGameGui.inviteCode); +} + +function joinGameNotFound() +{ + echo("Not Found"); + RootGui.setContent(JoinGameGui); } function JoinGameGui::textInput(%this, %chr) From 5b38719586f099b64381e3f4ac0389d97553275c Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sat, 6 May 2023 19:10:30 +0530 Subject: [PATCH 26/46] fix connections not working --- engine/source/game/net/serverQuery.cpp | 7 +++++-- engine/source/sim/netInterface.h | 2 ++ game/marble/client/init.cs | 5 +---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 8006ad63..8e38928c 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -1743,6 +1743,7 @@ static void handleGameMasterInfoRequest(const NetAddress* address, U32 key, U8 f writeCString(out, Con::getVariable("Server::GameType")); writeCString(out, Con::getVariable("Server::MissionType")); writeCString(out, Con::getVariable("Server::InviteCode")); + temp8 = U8(Con::getIntVariable("Pref::Server::MaxPlayers")); out->write(temp8); temp32 = Con::getIntVariable("Server::RegionMask");//"Pref::Server::RegionMask"); @@ -2287,6 +2288,7 @@ static void handleMasterServerClientRequestedArrangedConnection(const NetAddress stream->read(&ipbits[3]); stream->read(&port); NetAddress addr; + addr.type = NetAddress::IPAddress; addr.port = port; addr.netNum[0] = ipbits[0]; addr.netNum[1] = ipbits[1]; @@ -2324,6 +2326,7 @@ static void handleMasterServerArrangedConnectionAccepted(const NetAddress* addre stream->read(&ipbits[3]); stream->read(&port); NetAddress addr; + addr.type = NetAddress::IPAddress; addr.port = port; addr.netNum[0] = ipbits[0]; addr.netNum[1] = ipbits[1]; @@ -2360,7 +2363,7 @@ static void handleMasterServerArrangedConnectionRejected(const NetAddress* addre static void handleMasterServerGamePingResponse(const NetAddress* address, BitStream* stream) { NetAddress theAddress; - theAddress.type = 0; + theAddress.type = NetAddress::IPAddress; stream->read(&theAddress.netNum[0]); stream->read(&theAddress.netNum[1]); stream->read(&theAddress.netNum[2]); @@ -2378,7 +2381,7 @@ static void handleMasterServerGamePingResponse(const NetAddress* address, BitStr static void handleMasterServerGameInfoResponse(const NetAddress* address, BitStream* stream) { NetAddress theAddress; - theAddress.type = 0; + theAddress.type = NetAddress::IPAddress; stream->read(&theAddress.netNum[0]); stream->read(&theAddress.netNum[1]); stream->read(&theAddress.netNum[2]); diff --git a/engine/source/sim/netInterface.h b/engine/source/sim/netInterface.h index 7f746e6c..ae5c6491 100644 --- a/engine/source/sim/netInterface.h +++ b/engine/source/sim/netInterface.h @@ -51,6 +51,8 @@ class NetInterface MasterServerRelayRequest = 66, MasterServerRelayResponse = 68, MasterServerRelayReady = 72, + MasterServerJoinInvite = 74, + MasterServerJoinInviteResponse = 76, #endif // TORQUE_NET_HOLEPUNCHING }; protected: diff --git a/game/marble/client/init.cs b/game/marble/client/init.cs index 963bd303..8c2a10fe 100644 --- a/game/marble/client/init.cs +++ b/game/marble/client/init.cs @@ -647,10 +647,7 @@ function establishConnection(%address, %mp, %isLocal, %invited) } $Client::connectedMultiplayer = true; $Game::SPGemHunt = false; - if (%isLocal || isLocalAddress(%address)) - %conn.connect(%address); - else - %conn.arrangeConnection(%address); + %conn.arrangeConnection(%address); } clearClientGracePeroid(); From 42d345dfd1618e591b68ec7c772377be804ac7af Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sun, 7 May 2023 12:14:54 +0530 Subject: [PATCH 27/46] fix public/private slot logic --- game/common/server/clientConnection.cs | 22 +++++++++++++++------- game/marble/client/ui/joinGameGui.gui | 1 + game/marble/server/scripts/gameCommands.cs | 2 +- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/game/common/server/clientConnection.cs b/game/common/server/clientConnection.cs index 6a43d9e9..c8b58335 100644 --- a/game/common/server/clientConnection.cs +++ b/game/common/server/clientConnection.cs @@ -51,9 +51,13 @@ function updateServerParams() { echo("Connect request from: " @ %netAddress); - if($Server::PlayerCount >= $pref::Server::MaxPlayers) + if(%invited $= "" && $Server::PlayerCount >= ($pref::Server::MaxPlayers - $Pref::Server::PrivateSlots)) return "CR_SERVERFULL"; - + + if (%invited !$= "" && $Server::PrivatePlayerCount >= $Pref::Server::PrivateSlots) + return "CR_SERVERFULL"; + + %banEntry = $banlist[%xbLiveId]; if (%banEntry !$= "") { @@ -150,8 +154,6 @@ function updateServerParams() // note the time that this client joined %client.joinTime = getSimTime(); %client.joinInProgress = $Game::State $= "play"; - - $Server::PlayerCount++; // the client was invited and we have a free private slot for them, stick them into it if (%client.invited && $Server::PrivatePlayerCount < $Pref::Server::PrivateSlots) @@ -159,6 +161,10 @@ function updateServerParams() %client.usingPrivateSlot = true; $Server::PrivatePlayerCount++; } + else + { + $Server::PlayerCount++; + } } // Inform all clients of server global parameters - need to do this early, so that the information is available @@ -350,13 +356,15 @@ function isNameUnique(%name) echo("CDROP: " @ %client @ " " @ %client.getAddress()); - $Server::PlayerCount--; + if (%client.usingPrivateSlot) $Server::PrivatePlayerCount--; - + else + $Server::PlayerCount--; + // Reset the server if everyone has left the game - if( $Server::PlayerCount == 0 && $Server::Dedicated) + if ($Server::PlayerCount == 0 && $Server::Dedicated) schedule(0, 0, "resetServerDefaults"); // If everyone has left game, destroy it diff --git a/game/marble/client/ui/joinGameGui.gui b/game/marble/client/ui/joinGameGui.gui index 6ff06cd3..ec3176f0 100644 --- a/game/marble/client/ui/joinGameGui.gui +++ b/game/marble/client/ui/joinGameGui.gui @@ -275,6 +275,7 @@ function JoinGameGui::joinGame(%this) function joinGameFound(%ip) { cancel(JoinGameGui.joinTimeout); + setNetPort(0); // Get random port pls establishConnection(%ip, true, false, JoinGameGui.inviteCode); } diff --git a/game/marble/server/scripts/gameCommands.cs b/game/marble/server/scripts/gameCommands.cs index 340101dc..5e359042 100644 --- a/game/marble/server/scripts/gameCommands.cs +++ b/game/marble/server/scripts/gameCommands.cs @@ -29,7 +29,7 @@ function serverAreAllPlayersReady() function serverGetPublicSlotsUsed() { - return $Server::PlayerCount - $Server::PrivatePlayerCount; + return $Server::PlayerCount; } function serverGetPrivateSlotsUsed() From 137af91a5b9b791c8fbc058d33777e633073cd6d Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sun, 7 May 2023 12:17:04 +0530 Subject: [PATCH 28/46] Fix this schedule logic --- game/marble/client/ui/joinGameGui.gui | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/game/marble/client/ui/joinGameGui.gui b/game/marble/client/ui/joinGameGui.gui index ec3176f0..5b714d0a 100644 --- a/game/marble/client/ui/joinGameGui.gui +++ b/game/marble/client/ui/joinGameGui.gui @@ -261,6 +261,7 @@ function JoinGameGui::onB(%this) function JoinGameGui::exit(%this) { RootGui.setContent(MultiPlayerGui); + cancel(JoinGameGui.joinTimeout); } function JoinGameGui::joinGame(%this) @@ -282,7 +283,8 @@ function joinGameFound(%ip) function joinGameNotFound() { echo("Not Found"); - RootGui.setContent(JoinGameGui); + if (RootGui.contentGui == MissionLoadingGui) + RootGui.setContent(JoinGameGui); } function JoinGameGui::textInput(%this, %chr) From 6e0078b72ac5262dcfc4e93d01c2376b85052588 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sun, 7 May 2023 12:32:53 +0530 Subject: [PATCH 29/46] proper handling of free player slots --- engine/source/game/net/serverQuery.cpp | 1 + game/marble/client/ui/lobbyGui.gui | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 8e38928c..759315f4 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -1745,6 +1745,7 @@ static void handleGameMasterInfoRequest(const NetAddress* address, U32 key, U8 f writeCString(out, Con::getVariable("Server::InviteCode")); temp8 = U8(Con::getIntVariable("Pref::Server::MaxPlayers")); + temp8 -= U8(Con::getIntVariable("Pref::Server::PrivateSlots")); // Actual count out->write(temp8); temp32 = Con::getIntVariable("Server::RegionMask");//"Pref::Server::RegionMask"); out->write(temp32); diff --git a/game/marble/client/ui/lobbyGui.gui b/game/marble/client/ui/lobbyGui.gui index 725f7f7d..54237eb2 100644 --- a/game/marble/client/ui/lobbyGui.gui +++ b/game/marble/client/ui/lobbyGui.gui @@ -705,8 +705,8 @@ function LobbyGui::setHostInfo(%this, %hostName, %gameMode, %mapname, %priSlotsU %priSlotsUsed @ $Text::Slash @ %priSlotsFree + %priSlotsUsed @ $Text::Comma SPC $Text::LobbyHostPublicSlots @ $Text::Colon SPC %pubSlotsUsed @ $Text::Slash @ %pubSlotsFree + %pubSlotsUsed @ - $Text::Comma SPC $Text::LobbyHostInviteCode @ $Text::Colon SPC - $Server::InviteCode @ " "); + ($Server::Hosting ? ($Text::Comma SPC $Text::LobbyHostInviteCode @ $Text::Colon SPC + $Server::InviteCode @ " ") : "")); LobbyGuiSelection.clear(); LobbyGuiSelection.setButtonsEnabled(%this.hosting); From 7051eb619024a44e7b16b40e9bc5bc293b3136b8 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sun, 7 May 2023 14:09:27 +0530 Subject: [PATCH 30/46] proper LAN discovery alongside master server discovery --- engine/source/game/net/serverQuery.cpp | 40 +++++++++++++++----------- engine/source/game/net/serverQuery.h | 2 +- game/marble/client/init.cs | 5 +++- game/marble/client/ui/findGameGui.gui | 20 ++----------- 4 files changed, 30 insertions(+), 37 deletions(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 759315f4..7a391ddf 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -343,7 +343,7 @@ void queryLanServers(U32 port, U8 flags, const char* gameType, const char* missi U8 filterFlags, bool clearServerInfo, bool useFilters) { sgServerQueryActive = true; - clearServerList(clearServerInfo); + // clearServerList(clearServerInfo); pushServerFavorites(); sActiveFilter.type = useFilters ? ServerFilter::OfflineFiltered : ServerFilter::Offline; @@ -380,7 +380,7 @@ void queryLanServers(U32 port, U8 flags, const char* gameType, const char* missi #endif Con::executef(4, "onServerQueryStatus", "start", "Querying LAN servers", "0"); - processPingsAndQueries(gPingSession); + // processPingsAndQueries(gPingSession); } //----------------------------------------------------------------------------- @@ -408,6 +408,8 @@ ConsoleFunction(queryLanServers, void, 13, 14, "queryLanServers(...);") if (argc >= 14) useFilters = dAtoi(argv[13]) != 0; + clearServerList(); + queryLanServers(lanPort, flags, gameType, missionType, minPlayers, maxPlayers, maxBots, regionMask, maxPing, minCPU, filterFlags, clearServerInfo, useFilters); @@ -431,14 +433,14 @@ void queryMasterGameTypes() //----------------------------------------------------------------------------- -void queryMasterServer(U8 flags, const char* gameType, const char* missionType, +void queryMasterServer(U16 lanPort, U8 flags, const char* gameType, const char* missionType, U8 minPlayers, U8 maxPlayers, U8 maxBots, U32 regionMask, U32 maxPing, U16 minCPU, U8 filterFlags, U8 buddyCount, U32* buddyList) { // Reset the list packet flag: gGotFirstListPacket = false; sgServerQueryActive = true; - clearServerList(); + // clearServerList(); Con::executef(4, "onServerQueryStatus", "start", "Querying master server", "0"); @@ -470,6 +472,7 @@ void queryMasterServer(U8 flags, const char* gameType, const char* missionType, sActiveFilter.buddyCount = buddyCount; dFree(sActiveFilter.buddyList); sActiveFilter.buddyList = NULL; + queryLanServers(lanPort, flags, gameType, missionType, minPlayers, maxPlayers, maxBots, regionMask, maxPing, minCPU, filterFlags, false, false); } else { @@ -496,28 +499,31 @@ void queryMasterServer(U8 flags, const char* gameType, const char* missionType, processMasterServerQuery(gPingSession); } -ConsoleFunction(queryMasterServer, void, 11, 11, "queryMasterServer(...);") +ConsoleFunction(queryMasterServer, void, 12, 12, "queryMasterServer(...);") { argc; - U8 flags = dAtoi(argv[1]); + U16 lanPort = dAtoi(argv[1]); + U8 flags = dAtoi(argv[2]); // It's not a good idea to hold onto args, recursive calls to // console exec will trash them. - char* gameType = dStrdup(argv[2]); - char* missionType = dStrdup(argv[3]); - - U8 minPlayers = dAtoi(argv[4]); - U8 maxPlayers = dAtoi(argv[5]); - U8 maxBots = dAtoi(argv[6]); - U32 regionMask = dAtoi(argv[7]); - U32 maxPing = dAtoi(argv[8]); - U16 minCPU = dAtoi(argv[9]); - U8 filterFlags = dAtoi(argv[10]); + char* gameType = dStrdup(argv[3]); + char* missionType = dStrdup(argv[4]); + + U8 minPlayers = dAtoi(argv[5]); + U8 maxPlayers = dAtoi(argv[6]); + U8 maxBots = dAtoi(argv[7]); + U32 regionMask = dAtoi(argv[8]); + U32 maxPing = dAtoi(argv[9]); + U16 minCPU = dAtoi(argv[10]); + U8 filterFlags = dAtoi(argv[11]); U8 buddyCount = 0; U32 buddyList = 0; - queryMasterServer(flags, gameType, missionType, minPlayers, maxPlayers, + clearServerList(); + + queryMasterServer(lanPort, flags, gameType, missionType, minPlayers, maxPlayers, maxBots, regionMask, maxPing, minCPU, filterFlags, 0, &buddyList); dFree(gameType); diff --git a/engine/source/game/net/serverQuery.h b/engine/source/game/net/serverQuery.h index 446fa18e..f3c3138b 100644 --- a/engine/source/game/net/serverQuery.h +++ b/engine/source/game/net/serverQuery.h @@ -114,7 +114,7 @@ extern void queryLanServers(U32 port, U8 flags, const char* gameType, const char U8 minPlayers, U8 maxPlayers, U8 maxBots, U32 regionMask, U32 maxPing, U16 minCPU, U8 filterFlags, bool clearServerInfo, bool useFilters); extern void queryMasterGameTypes(); -extern void queryMasterServer(U8 flags, const char* gameType, const char* missionType, +extern void queryMasterServer(U16 port, U8 flags, const char* gameType, const char* missionType, U8 minPlayers, U8 maxPlayers, U8 maxBots, U32 regionMask, U32 maxPing, U16 minCPU, U8 filterFlags, U8 buddyCount, U32* buddyList); extern void queryFavoriteServers(U8 flags); diff --git a/game/marble/client/init.cs b/game/marble/client/init.cs index 8c2a10fe..12cc427e 100644 --- a/game/marble/client/init.cs +++ b/game/marble/client/init.cs @@ -647,7 +647,10 @@ function establishConnection(%address, %mp, %isLocal, %invited) } $Client::connectedMultiplayer = true; $Game::SPGemHunt = false; - %conn.arrangeConnection(%address); + if (%isLocal) + %conn.connect(%address); + else + %conn.arrangeConnection(%address); } clearClientGracePeroid(); diff --git a/game/marble/client/ui/findGameGui.gui b/game/marble/client/ui/findGameGui.gui index 9948ac5c..af2126e6 100644 --- a/game/marble/client/ui/findGameGui.gui +++ b/game/marble/client/ui/findGameGui.gui @@ -165,14 +165,7 @@ function PC_XBLiveSearchForMatches(%gamemodefilter, %missionfilter, %maxplayersf if (%mis $= "-1") %mis = "any"; - if (FindGameGui.useMaster) - { - queryMasterServer(0, "any", %mis, 0, 100, 100, 2, 1000, 0, %filterFlags); - } - else - { - queryLanServers(1000, 0, "any", %mis, 0, 100, 100, 2, 1000, 0, %filterFlags, 1, $pcsearchusefilters); - } + queryMasterServer(1000, 0, "any", %mis, 0, 100, 100, 2, 1000, 0, %filterFlags); } // ---------------------------------------------------------------------------- @@ -445,16 +438,7 @@ function FindGameGui::onSearchComplete(%this,%type) if (isPCBuild() || !$Client::UseXBLiveMatchMaking) { %sc = getServerCount(); - if ($queryOffline && %this.useMaster) - { - %this.useMaster = false; - - %this.pcSearchActive = true; - PC_XBLiveSearchForMatches(%this.gamemodefilter, %this.missionfilter, - %this.maxplayersfilter, -1, "FindGameGui.onSearchComplete(pc);"); - return; - } - echo(%sc @ " games returned from LAN search."); + echo(%sc @ " games returned from search."); for (%i = 0; %i < %sc; %i++) { // no filtering in PC build, we just add everything From 55e18f2645a9d193aa9b934c8f108d1a07858110 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Mon, 8 May 2023 19:19:50 +0530 Subject: [PATCH 31/46] Don't show filled servers in LAN and add callbacks --- engine/source/game/net/serverQuery.cpp | 6 ++++++ engine/source/sim/netInterface.cpp | 6 ++++++ game/marble/client/scripts/serverConnection.cs | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 7a391ddf..2c070252 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -1811,6 +1811,12 @@ static void handleGamePingRequest(const NetAddress* address, U32 key, U8 flags) if (flags & ServerFilter::OfflineQuery) return; + int maxCount = Con::getIntVariable("Pref::Server::MaxPlayers"); + maxCount -= Con::getIntVariable("Pref::Server::PrivateSlots"); // Actual count + + if (Con::getIntVariable("Server::PlayerCount") >= maxCount) + return; // Don't reply + // some banning code here (?) BitStream* out = BitStream::getPacketStream(); diff --git a/engine/source/sim/netInterface.cpp b/engine/source/sim/netInterface.cpp index 95bc8be2..12c406df 100644 --- a/engine/source/sim/netInterface.cpp +++ b/engine/source/sim/netInterface.cpp @@ -433,6 +433,7 @@ void NetInterface::handleConnectReject(const NetAddress* address, BitStream* str void NetInterface::sendRelayPackets(NetConnection* conn) { + Con::executef(conn, 2, "onConnectStatus", Con::getIntArg(4)); relayNetConnection = conn; BitStream* out = BitStream::getPacketStream(); @@ -476,6 +477,8 @@ void NetInterface::startArrangedConnection(NetConnection *conn) void NetInterface::sendPunchPackets(NetConnection *conn) { + Con::executef(conn, 2, "onConnectStatus", Con::getIntArg(1)); + ConnectionParameters &theParams = conn->getConnectionParameters(); BitStream* out = BitStream::getPacketStream(); out->write(U8(Punch)); @@ -559,6 +562,8 @@ void NetInterface::handlePunch(const NetAddress* theAddress, BitStream *stream) conn->setNetAddress(theAddress); Con::printf("Punch from %s matched nonces - connecting...", addr); + Con::executef(conn, 2, "onConnectStatus", Con::getIntArg(2)); + conn->setConnectionState(NetConnection::AwaitingConnectResponse); conn->mConnectSendCount = 0; conn->mConnectLastSendTime = Platform::getVirtualMilliseconds();//getCurrentTime(); @@ -613,6 +618,7 @@ void NetInterface::handleArrangedConnectRequest(const NetAddress* theAddress, Bi removePendingConnection(conn); if (theParams.mIsInitiator) { + Con::executef(conn, 2, "onConnectStatus", Con::getIntArg(3)); conn->connect(theAddress); } else diff --git a/game/marble/client/scripts/serverConnection.cs b/game/marble/client/scripts/serverConnection.cs index f74df047..99a9340d 100644 --- a/game/marble/client/scripts/serverConnection.cs +++ b/game/marble/client/scripts/serverConnection.cs @@ -385,3 +385,21 @@ function enterPreviewMode(%clientDropCode) RootGui.setContent($disconnectGui); } } + +function GameConnection::onConnectStatus(%this, %statusCode) +{ + if (RootGui.contentGui == MissionLoadingGui && !$Server::Hosting) + { + switch (%statusCode) + { + case 1: + RootGui.setCenterText("Punching hole in NAT."); + case 2: + RootGui.setCenterText("Hole punching successful, trying to connect."); + case 3: + RootGui.setCenterText("Connecting.."); + case 4: + RootGui.setCenterText("Trying relay."); + } + } +} \ No newline at end of file From c7abc3aed3d823768704e77141bb76ed8bf8d9c6 Mon Sep 17 00:00:00 2001 From: Human Gamer <39096122+HumanGamer@users.noreply.github.com> Date: Mon, 8 May 2023 17:56:55 -0500 Subject: [PATCH 32/46] Set default port to 28000 --- game/marble/server/defaults.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game/marble/server/defaults.cs b/game/marble/server/defaults.cs index 1a457f87..398fdd21 100644 --- a/game/marble/server/defaults.cs +++ b/game/marble/server/defaults.cs @@ -26,7 +26,7 @@ // The network port is also defined by the client, this value // overrides pref::net::port for dedicated servers -$Pref::Server::Port = 1000; +$Pref::Server::Port = 28000; // If the password is set, clients must provide it in order // to connect to the server From 99cbca4bd6587c0502b6661212c6b7512275b129 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Tue, 9 May 2023 13:14:03 +0530 Subject: [PATCH 33/46] fix some bugs --- engine/source/game/net/serverQuery.cpp | 3 ++- game/common/server/clientConnection.cs | 2 +- game/marble/client/scripts/default.bind.cs | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 2c070252..004e21d1 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -1309,7 +1309,8 @@ static void processMasterServerQuery(U32 session) else { Con::errorf("There are no more master servers to try!"); - Con::executef(4, "onServerQueryStatus", "done", "No master servers found.", "0"); + // Con::executef(4, "onServerQueryStatus", "done", "No master servers found.", "0"); + processPingsAndQueries(gPingSession); // Do the LAN ping query?? } } } diff --git a/game/common/server/clientConnection.cs b/game/common/server/clientConnection.cs index c8b58335..8ec2e186 100644 --- a/game/common/server/clientConnection.cs +++ b/game/common/server/clientConnection.cs @@ -54,7 +54,7 @@ function updateServerParams() if(%invited $= "" && $Server::PlayerCount >= ($pref::Server::MaxPlayers - $Pref::Server::PrivateSlots)) return "CR_SERVERFULL"; - if (%invited !$= "" && $Server::PrivatePlayerCount >= $Pref::Server::PrivateSlots) + if ((%invited !$= "" && %invited != 0) && $Server::PrivatePlayerCount >= $Pref::Server::PrivateSlots) return "CR_SERVERFULL"; diff --git a/game/marble/client/scripts/default.bind.cs b/game/marble/client/scripts/default.bind.cs index 6b692b59..b27dd715 100644 --- a/game/marble/client/scripts/default.bind.cs +++ b/game/marble/client/scripts/default.bind.cs @@ -114,8 +114,10 @@ function pauseToggle(%defaultItem) enterPreviewMode(); } // client's just disconnect - else if ($Client::connectedMultiplayer) // this is also true for hosts so we check hosting first + else if ($Client::connectedMultiplayer) { // this is also true for hosts so we check hosting first disconnect(); + RootGui.setContent(MultiPlayerGui); + } // if play gui is awake, return to Level Preview. Otherwise Quit else if (PlayGui.isAwake() || MissionLoadingGui.isAwake()) { From 39d037926c6417cfb8a195b72a49156003de5307 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Mon, 15 May 2023 19:43:22 +0530 Subject: [PATCH 34/46] handle LAN join invites --- engine/source/game/net/serverQuery.cpp | 63 ++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 004e21d1..413efc75 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -2219,6 +2219,26 @@ static void joinGameByInvite(const char* inviteCode) { BitStream::sendPacketStream(&(*serverList)[i].address); } + + int netPort = Con::getIntVariable("pref::Net::Port"); + + // Now for LAN + BitStream* stream = BitStream::getPacketStream(); + stream->write(U8(NetInterface::MasterServerJoinInvite)); + U8 flags = 0; + U32 key = 0; + + stream->write(flags); + stream->write(key); + writeCString(stream, inviteCode); + + + NetAddress addr; + char addrText[256]; + dSprintf(addrText, sizeof(addrText), "IP:BROADCAST:%d", netPort); + Net::stringToAddress(addrText, &addr); + + BitStream::sendPacketStream(&addr); } ConsoleFunction(joinGameByInvite, void, 4, 4, "joinGameByInvite(inviteCode, acceptCb(%ip), rejectCb)") @@ -2411,6 +2431,38 @@ static void handleMasterServerGameInfoResponse(const NetAddress* address, BitStr handleGameInfoResponse(&theAddress, stream, key, flags); } +static void handleMasterServerJoinInvite(const NetAddress* address, BitStream* stream) { + char inv[32]; + readCString(stream, (char*) &inv); + const char* ourInv = Con::getVariable("Server::InviteCode"); + if (strcmp(ourInv, inv) == 0) { + // RESPOND + U16 netPort = Con::getIntVariable("pref::Net::Port"); + + BitStream* stream = BitStream::getPacketStream(); + stream->write(U8(NetInterface::MasterServerJoinInviteResponse)); + U8 flags = 0; + U32 key = 0; + + stream->write(flags); + stream->write(key); + + // We just replace the netNum with 255.255.255.255 and filter that out on client side + NetAddress theAddress; + theAddress.netNum[0] = 255; + theAddress.netNum[1] = 255; + theAddress.netNum[2] = 255; + theAddress.netNum[3] = 255; + stream->write(theAddress.netNum[0]); + stream->write(theAddress.netNum[1]); + stream->write(theAddress.netNum[2]); + stream->write(theAddress.netNum[3]); + stream->write(netPort); + + BitStream::sendPacketStream(address); + } +} + static void handleMasterServerJoinInviteResponse(const NetAddress* address, BitStream* stream) { U8 found; stream->read(&found); @@ -2424,6 +2476,13 @@ static void handleMasterServerJoinInviteResponse(const NetAddress* address, BitS stream->read(&theAddress.netNum[3]); stream->read(&theAddress.port); + if (theAddress.netNum[0] == 255 && theAddress.netNum[1] == 255 && theAddress.netNum[2] == 255 && theAddress.netNum[3] == 255) { + theAddress.netNum[0] = address->netNum[0]; + theAddress.netNum[1] = address->netNum[1]; + theAddress.netNum[2] = address->netNum[2]; + theAddress.netNum[3] = address->netNum[3]; + } + char evalbuf[128]; dSprintf(evalbuf, 128, "%s(\"%d.%d.%d.%d:%d\");", joinGameAcceptCb, theAddress.netNum[0], theAddress.netNum[1], theAddress.netNum[2], theAddress.netNum[3], theAddress.port); Con::evaluatef(evalbuf); @@ -2504,8 +2563,12 @@ void DemoNetInterface::handleInfoPacket(const NetAddress* address, U8 packetType case MasterServerRelayReady: handleMasterServerRelayReady(address); break; + case MasterServerJoinInvite: + handleMasterServerJoinInvite(address, stream); + break; case MasterServerJoinInviteResponse: handleMasterServerJoinInviteResponse(address, stream); + break; #endif } } From 7ee2dd54916d31f81fe353c6a64a2aa75aa6277a Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Tue, 16 May 2023 01:34:58 +0530 Subject: [PATCH 35/46] fix typo bruh --- engine/source/game/net/serverQuery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 413efc75..110ebf29 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -2223,7 +2223,7 @@ static void joinGameByInvite(const char* inviteCode) int netPort = Con::getIntVariable("pref::Net::Port"); // Now for LAN - BitStream* stream = BitStream::getPacketStream(); + stream = BitStream::getPacketStream(); stream->write(U8(NetInterface::MasterServerJoinInvite)); U8 flags = 0; U32 key = 0; From 424e2379d83d7914c77b3ca62126536941b5a942 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Tue, 16 May 2023 01:50:24 +0530 Subject: [PATCH 36/46] fix joining in certain conditions --- game/common/server/clientConnection.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/game/common/server/clientConnection.cs b/game/common/server/clientConnection.cs index 8ec2e186..8d737b27 100644 --- a/game/common/server/clientConnection.cs +++ b/game/common/server/clientConnection.cs @@ -51,10 +51,15 @@ function updateServerParams() { echo("Connect request from: " @ %netAddress); - if(%invited $= "" && $Server::PlayerCount >= ($pref::Server::MaxPlayers - $Pref::Server::PrivateSlots)) + %flag = $Server::PlayerCount >= ($pref::Server::MaxPlayers - $Pref::Server::PrivateSlots); + + if (%invited $= "" && %flag) + return "CR_SERVERFULL"; + + if ((%invited !$= "" && %invited != 0) && $Server::PrivatePlayerCount >= $Pref::Server::PrivateSlots && %flag) return "CR_SERVERFULL"; - if ((%invited !$= "" && %invited != 0) && $Server::PrivatePlayerCount >= $Pref::Server::PrivateSlots) + if (%invited $= "" && $Server::IsPrivate) return "CR_SERVERFULL"; From 8c19409628e8cb0d87b34955cac9937cc87c3cb2 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sun, 28 May 2023 20:45:18 +0530 Subject: [PATCH 37/46] invite code toggling --- game/common/local/englishStrings.inf | 2 ++ game/marble/client/defaults.cs | 1 + game/marble/client/ui/GamePauseGui.gui | 2 +- game/marble/client/ui/RootGui.gui | 2 +- game/marble/client/ui/lobbyGui.gui | 33 +++++++++++++++++++----- game/marble/client/ui/miscOptionsGui.gui | 8 ++++++ 6 files changed, 39 insertions(+), 9 deletions(-) diff --git a/game/common/local/englishStrings.inf b/game/common/local/englishStrings.inf index bd98f91e..3c3417cc 100644 --- a/game/common/local/englishStrings.inf +++ b/game/common/local/englishStrings.inf @@ -276,6 +276,7 @@ $Text::LobbyHostLevel = "Level:"; $Text::LobbyHostPrivateSlots = "Private Slots"; $Text::LobbyHostPublicSlots = "Public Slots"; $Text::LobbyHostInviteCode = "Invite Code"; +$Text::LobbyHostInviteVisibility = "Invite Visibility"; ; separators $Text::Colon = ":"; @@ -336,6 +337,7 @@ $Text::FramerateOptions = "Unlimited\tVsync\t30\t60\t75\t120\t200\tCustom"; $Text::MarbleSkin = "Marble Type"; $Text::UIStyle = "UI Style"; $Text::UIStyleOptions = "Mouse/Keyboard\tXbox 360"; +$Text::InviteVisibilityOptions = "Hidden\tVisible"; ;This string is no longer used $Text::MarbleOptions = "one\ttwo\tthree\tfour\tfive\tsix\tseven\teight\tnine\tten\televen\ttwelve\tthirteen\tfourteen\tfifteen\tsixteen\tseventeen\teighteen\tnineteen\ttwenty"; ;$Text::MarbleColor = "Marble Color"; diff --git a/game/marble/client/defaults.cs b/game/marble/client/defaults.cs index 02769589..f29a8055 100644 --- a/game/marble/client/defaults.cs +++ b/game/marble/client/defaults.cs @@ -48,6 +48,7 @@ $pref::OpenGL::forcePalettedTexture = "0"; $pref::OpenGL::maxHardwareLights = 3; $pref::VisibleDistanceMod = 1.0; +$pref::Lobby::InviteVisibility = true; /// The sound provider to select at startup. Typically /// this is DirectSound, OpenAL, or XACT. There is also diff --git a/game/marble/client/ui/GamePauseGui.gui b/game/marble/client/ui/GamePauseGui.gui index 02a4fab4..dc839a83 100644 --- a/game/marble/client/ui/GamePauseGui.gui +++ b/game/marble/client/ui/GamePauseGui.gui @@ -71,7 +71,7 @@ function GamePauseGui::onWake(%this) RootGui.setTitle($Text::Paused); - if ($Server::Hosting) + if ($Server::Hosting && $pref::Lobby::InviteVisibility) LevelTitle.setText($Text::LobbyHostInviteCode @ $Text::Colon SPC $Server::InviteCode); if ($pref::UI::LegacyUI) diff --git a/game/marble/client/ui/RootGui.gui b/game/marble/client/ui/RootGui.gui index 5126f054..f2df9d9a 100644 --- a/game/marble/client/ui/RootGui.gui +++ b/game/marble/client/ui/RootGui.gui @@ -417,7 +417,7 @@ new GuiControl(RootCenterCtrl) { profile = "GuiDefaultProfile"; horizSizing = "right"; vertSizing = "top"; - position = isWidescreen()? "262 50" : "102 34"; + position = isWidescreen()? "235 5" : "95 4"; extent = "500 60"; minExtent = "8 2"; bitmap = "./xbox/roundedBG"; diff --git a/game/marble/client/ui/lobbyGui.gui b/game/marble/client/ui/lobbyGui.gui index 54237eb2..00c5fb15 100644 --- a/game/marble/client/ui/lobbyGui.gui +++ b/game/marble/client/ui/lobbyGui.gui @@ -293,8 +293,10 @@ function LobbyGui::updateHostingStatus(%this) } //} - if (%this.hosting && !isDemoLaunch() && !XBLiveIsRanked()) + if (%this.hosting && !isDemoLaunch() && !XBLiveIsRanked()) { RootGui.setLS($Text::ChangeLevels); + RootGui.setX($Text::LobbyHostInviteVisibility); + } } } @@ -698,16 +700,21 @@ function LobbyGui::setHostInfo(%this, %hostName, %gameMode, %mapname, %priSlotsU //%gamemodetag = (isEnglish()) ? $text::LM7 @ " " : ""; // hide " %gamemodetag = $Text::LobbyHostName; - LobbyGuiHostGameInfo.setText( - "" @ %gamemodetag SPC %hostName @ "\n" @ + + LobbyGuiHostGameInfo.beforeText = "" @ %gamemodetag SPC %hostName @ "\n" @ $Text::LobbyHostLevel SPC %missionName @ "\n" @ "" @ $Text::LobbyHostPrivateSlots @ $Text::Colon SPC %priSlotsUsed @ $Text::Slash @ %priSlotsFree + %priSlotsUsed @ $Text::Comma SPC $Text::LobbyHostPublicSlots @ $Text::Colon SPC - %pubSlotsUsed @ $Text::Slash @ %pubSlotsFree + %pubSlotsUsed @ - ($Server::Hosting ? ($Text::Comma SPC $Text::LobbyHostInviteCode @ $Text::Colon SPC - $Server::InviteCode @ " ") : "")); - + %pubSlotsUsed @ $Text::Slash @ %pubSlotsFree + %pubSlotsUsed; + + if ($pref::Lobby::InviteVisibility) + LobbyGuiHostGameInfo.setText(LobbyGuiHostGameInfo.beforeText @ + ($Server::Hosting ? ($Text::Comma SPC $Text::LobbyHostInviteCode @ $Text::Colon SPC + $Server::InviteCode @ " ") : "")); + else + LobbyGuiHostGameInfo.setText(LobbyGuiHostGameInfo.beforeText); + LobbyGuiSelection.clear(); LobbyGuiSelection.setButtonsEnabled(%this.hosting); LobbyGuiSelection.addRow($Text::Level, %mapname, 18); @@ -958,6 +965,18 @@ function LobbyGuiPlayerList::onSelect( %this, %id, %text ) RootGui.setY( $Text::SelectPlayer ); } +function LobbyGui::onX(%this) +{ + $pref::Lobby::InviteVisibility = !$pref::Lobby::InviteVisibility; + + if ($pref::Lobby::InviteVisibility) + LobbyGuiHostGameInfo.setText(LobbyGuiHostGameInfo.beforeText @ + ($Server::Hosting ? ($Text::Comma SPC $Text::LobbyHostInviteCode @ $Text::Colon SPC + $Server::InviteCode @ " ") : "")); + else + LobbyGuiHostGameInfo.setText(LobbyGuiHostGameInfo.beforeText); +} + function LobbyGui::onY(%this) { if (%this.isLoading()) diff --git a/game/marble/client/ui/miscOptionsGui.gui b/game/marble/client/ui/miscOptionsGui.gui index 5d718f0c..5bf7591b 100644 --- a/game/marble/client/ui/miscOptionsGui.gui +++ b/game/marble/client/ui/miscOptionsGui.gui @@ -69,6 +69,11 @@ function miscOptionsGui::show(%this, %backGui) miscOptionsList.setOptionIndex(1, %uiStyleIndex); + // Invite visibility + + miscOptionsList.addRow($Text::LobbyHostInviteCode, $Text::InviteVisibilityOptions, 8); + miscOptionsList.setOptionIndex(2, $pref::Lobby::InviteVisibility); + RootGui.setA( $Text::OK ); RootGui.setTitle( strupr($Text::HOMiscOptions) ); } @@ -90,6 +95,9 @@ function miscOptionsList::onOptionChange(%this, %increase) // ui style $pref::UI::LegacyUI = %val; echo("UIStyle = " @ $pref::UI::LegacyUI); + case 2: + $pref::Lobby::InviteVisibility = %val; + echo("InviteVisibility = " @ $pref::Lobby::InviteVisibility); } } From f2b1eaa94c32961bf5c0b5df62470624ed7aaab8 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Fri, 2 Jun 2023 23:38:15 +0530 Subject: [PATCH 38/46] fix wrong query port --- game/marble/client/ui/findGameGui.gui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game/marble/client/ui/findGameGui.gui b/game/marble/client/ui/findGameGui.gui index af2126e6..0bf16bd1 100644 --- a/game/marble/client/ui/findGameGui.gui +++ b/game/marble/client/ui/findGameGui.gui @@ -165,7 +165,7 @@ function PC_XBLiveSearchForMatches(%gamemodefilter, %missionfilter, %maxplayersf if (%mis $= "-1") %mis = "any"; - queryMasterServer(1000, 0, "any", %mis, 0, 100, 100, 2, 1000, 0, %filterFlags); + queryMasterServer(28000, 0, "any", %mis, 0, 100, 100, 2, 1000, 0, %filterFlags); } // ---------------------------------------------------------------------------- From c8d7322bfe5a2c348ac1757232aa49ee2eddf422 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sat, 3 Jun 2023 00:15:00 +0530 Subject: [PATCH 39/46] query properly atleast --- game/marble/client/init.cs | 2 +- game/marble/client/ui/findGameGui.gui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/game/marble/client/init.cs b/game/marble/client/init.cs index 12cc427e..b2b39a4a 100644 --- a/game/marble/client/init.cs +++ b/game/marble/client/init.cs @@ -45,7 +45,7 @@ function initClient() // Make sure this variable reflects the correct state. $Server::Dedicated = false; // Game information used to query the master server - $Client::GameTypeQuery = "Marble Game"; + $Client::GameTypeQuery = "OpenMBU"; $Client::MissionTypeQuery = "Any"; // Default level qualification if (!$pref::QualifiedLevel["Beginner"]) diff --git a/game/marble/client/ui/findGameGui.gui b/game/marble/client/ui/findGameGui.gui index 0bf16bd1..35c27a2d 100644 --- a/game/marble/client/ui/findGameGui.gui +++ b/game/marble/client/ui/findGameGui.gui @@ -165,7 +165,7 @@ function PC_XBLiveSearchForMatches(%gamemodefilter, %missionfilter, %maxplayersf if (%mis $= "-1") %mis = "any"; - queryMasterServer(28000, 0, "any", %mis, 0, 100, 100, 2, 1000, 0, %filterFlags); + queryMasterServer(28000, 0, "OpenMBU", %mis, 0, %maxplayersfilter, 100, 2, 1000, 0, %filterFlags); } // ---------------------------------------------------------------------------- From c628fcd946b1e8674b80f12f316761d1a4c531f2 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sat, 3 Jun 2023 00:23:38 +0530 Subject: [PATCH 40/46] filter correct --- game/marble/client/ui/findGameGui.gui | 2 ++ game/marble/server/scripts/game.cs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/game/marble/client/ui/findGameGui.gui b/game/marble/client/ui/findGameGui.gui index 35c27a2d..c89c693f 100644 --- a/game/marble/client/ui/findGameGui.gui +++ b/game/marble/client/ui/findGameGui.gui @@ -164,6 +164,8 @@ function PC_XBLiveSearchForMatches(%gamemodefilter, %missionfilter, %maxplayersf %mis = %missionfilter; if (%mis $= "-1") %mis = "any"; + + %filterFlags |= 1 << 7; // Current version only queryMasterServer(28000, 0, "OpenMBU", %mis, 0, %maxplayersfilter, 100, 2, 1000, 0, %filterFlags); } diff --git a/game/marble/server/scripts/game.cs b/game/marble/server/scripts/game.cs index 04fdf2da..e2fbbfed 100644 --- a/game/marble/server/scripts/game.cs +++ b/game/marble/server/scripts/game.cs @@ -91,7 +91,7 @@ function onServerCreated() { // Server::GameType is sent to the master server. // This variable should uniquely identify your game and/or mod. - $Server::GameType = "Marble Game"; + $Server::GameType = "OpenMBU"; // Server::MissionType sent to the master server. Clients can // filter servers based on mission type. From 3855f0ca60bf56fec565379be89fb08ab0662d83 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sat, 3 Jun 2023 00:37:35 +0530 Subject: [PATCH 41/46] add fallback variable and also use player's name for server name instead --- game/marble/client/defaults.cs | 1 + game/marble/client/init.cs | 8 +++++--- game/marble/client/ui/createGameGui.gui | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/game/marble/client/defaults.cs b/game/marble/client/defaults.cs index f29a8055..dc71ffc5 100644 --- a/game/marble/client/defaults.cs +++ b/game/marble/client/defaults.cs @@ -16,6 +16,7 @@ $pref::HudMessageLogSize = 40; $pref::ChatHudLength = 1; $pref::useStencilShadows = true; +$pref::forceDirectConnect = false; $pref::Input::LinkMouseSensitivity = 1; // DInput keyboard, mouse, and joystick prefs $pref::displayMPHelpText = false; diff --git a/game/marble/client/init.cs b/game/marble/client/init.cs index b2b39a4a..d06db056 100644 --- a/game/marble/client/init.cs +++ b/game/marble/client/init.cs @@ -566,8 +566,10 @@ function connectToServer(%address,%invited) } $Client::connectedMultiplayer = true; $Game::SPGemHunt = false; - echo("CONNECT ARRANGED??"); - %conn.arrangeConnection(%address); + if ($pref::forceDirectConnect) + %conn.connect(%address); + else + %conn.arrangeConnection(%address); } clearClientGracePeroid(); @@ -647,7 +649,7 @@ function establishConnection(%address, %mp, %isLocal, %invited) } $Client::connectedMultiplayer = true; $Game::SPGemHunt = false; - if (%isLocal) + if (%isLocal || $pref::forceDirectConnect) %conn.connect(%address); else %conn.arrangeConnection(%address); diff --git a/game/marble/client/ui/createGameGui.gui b/game/marble/client/ui/createGameGui.gui index 06116e8b..e70bd967 100644 --- a/game/marble/client/ui/createGameGui.gui +++ b/game/marble/client/ui/createGameGui.gui @@ -340,7 +340,7 @@ function CreateGameGui::createGame(%this) //$Game::Duration = $pref::Server::TimeLimit * 60; //$Server::StayMission = true; $Server::ReturnToLobby = true; - $pref::Server::Name = XBLiveGetUserName(); + $pref::Server::Name = $pref::Player::Name @ "'s Server"; // XBLiveGetUserName(); //MissionSequence.buildMissionSequence(); //MissionSequence.setCurrentMission($Server::PostLobbyMissionFile); From 80bba07d0b1d968c491cac96e8b8f99eb1d79a0f Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Sat, 3 Jun 2023 00:42:37 +0530 Subject: [PATCH 42/46] ports increment by triples please, so to avoid collisions --- game/common/server/server.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game/common/server/server.cs b/game/common/server/server.cs index 7fbc53f6..179bb428 100644 --- a/game/common/server/server.cs +++ b/game/common/server/server.cs @@ -11,7 +11,7 @@ function portInit(%port) %failCount = 0; while(%failCount < 10 && !setNetPort(%port)) { echo("Port init failed on port " @ %port @ " trying next port."); - %port++; %failCount++; + %port += 3; %failCount++; } } From c8787d0a285c262d0a1520772b85a034666d3d04 Mon Sep 17 00:00:00 2001 From: Human Gamer <39096122+HumanGamer@users.noreply.github.com> Date: Fri, 2 Jun 2023 16:03:41 -0500 Subject: [PATCH 43/46] Use correct player name variable --- game/marble/client/ui/createGameGui.gui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game/marble/client/ui/createGameGui.gui b/game/marble/client/ui/createGameGui.gui index e70bd967..0fdd963e 100644 --- a/game/marble/client/ui/createGameGui.gui +++ b/game/marble/client/ui/createGameGui.gui @@ -340,7 +340,7 @@ function CreateGameGui::createGame(%this) //$Game::Duration = $pref::Server::TimeLimit * 60; //$Server::StayMission = true; $Server::ReturnToLobby = true; - $pref::Server::Name = $pref::Player::Name @ "'s Server"; // XBLiveGetUserName(); + $pref::Server::Name = $Player::Name @ "'s Server"; // XBLiveGetUserName(); //MissionSequence.buildMissionSequence(); //MissionSequence.setCurrentMission($Server::PostLobbyMissionFile); From 94927eaa13ef6c42075f3af976978ff2fcdb0096 Mon Sep 17 00:00:00 2001 From: Human Gamer <39096122+HumanGamer@users.noreply.github.com> Date: Fri, 2 Jun 2023 16:06:07 -0500 Subject: [PATCH 44/46] Increase version number --- engine/source/core/torqueConfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/source/core/torqueConfig.h b/engine/source/core/torqueConfig.h index dbecb1f3..5c79dbd4 100644 --- a/engine/source/core/torqueConfig.h +++ b/engine/source/core/torqueConfig.h @@ -20,7 +20,7 @@ /// Version number is major * 1000 + minor * 100 + revision * 10. /// Different engines (TGE, T2D, etc.) will have different version numbers. -#define TORQUE_VERSION 900 // version 0.9 +#define TORQUE_VERSION 901 // version 0.9 /// What engine are we running? The presence and value of this define are /// used to determine what engine (TGE, T2D, etc.) and version thereof we're From 95f4b69ef7e04ffdf50e95254fb88f7d421dcbde Mon Sep 17 00:00:00 2001 From: Human Gamer <39096122+HumanGamer@users.noreply.github.com> Date: Fri, 2 Jun 2023 17:16:00 -0500 Subject: [PATCH 45/46] Fixed joining via invite code --- engine/source/game/net/serverQuery.cpp | 27 +++++++++++++++++--------- game/MBU.torsion.exports | 20 +++++++++++++++++++ game/marble/client/ui/joinGameGui.gui | 12 ++++++++++-- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 110ebf29..5a633f23 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -1284,7 +1284,8 @@ static void processMasterServerQuery(U32 session) out->write(sActiveFilter.minPlayers); out->write(sActiveFilter.maxPlayers); out->write(sActiveFilter.regionMask); - U32 version = (sActiveFilter.filterFlags & ServerFilter::CurrentVersion) ? getVersionNumber() : 0; + //U32 version = (sActiveFilter.filterFlags & ServerFilter::CurrentVersion) ? getVersionNumber() : 0; + U32 version = getVersionNumber(); out->write(version); out->write(sActiveFilter.filterFlags); out->write(sActiveFilter.maxBots); @@ -1955,9 +1956,10 @@ static void handleGamePingResponse(const NetAddress* address, BitStream* stream, // Get the server build version: stream->read(&temp32); - if (applyFilter - && (sActiveFilter.filterFlags & ServerFilter::CurrentVersion) - && (temp32 != getVersionNumber())) +// if (applyFilter +// && (sActiveFilter.filterFlags & ServerFilter::CurrentVersion) +// && (temp32 != getVersionNumber())) + if (temp32 != getVersionNumber()) { Con::printf("Server %s filtered out by version number.", addrString); gFinishedList.push_back(*address); @@ -2220,7 +2222,7 @@ static void joinGameByInvite(const char* inviteCode) BitStream::sendPacketStream(&(*serverList)[i].address); } - int netPort = Con::getIntVariable("pref::Net::Port"); + int netPort = Con::getIntVariable("pref::Server::Port"); // Now for LAN stream = BitStream::getPacketStream(); @@ -2437,16 +2439,19 @@ static void handleMasterServerJoinInvite(const NetAddress* address, BitStream* s const char* ourInv = Con::getVariable("Server::InviteCode"); if (strcmp(ourInv, inv) == 0) { // RESPOND - U16 netPort = Con::getIntVariable("pref::Net::Port"); + U16 netPort = Con::getIntVariable("pref::Server::Port"); BitStream* stream = BitStream::getPacketStream(); stream->write(U8(NetInterface::MasterServerJoinInviteResponse)); U8 flags = 0; U32 key = 0; + U8 found = 1; stream->write(flags); stream->write(key); + stream->write(found); + // We just replace the netNum with 255.255.255.255 and filter that out on client side NetAddress theAddress; theAddress.netNum[0] = 255; @@ -2464,7 +2469,7 @@ static void handleMasterServerJoinInvite(const NetAddress* address, BitStream* s } static void handleMasterServerJoinInviteResponse(const NetAddress* address, BitStream* stream) { - U8 found; + U8 found = true; stream->read(&found); if (found) { @@ -2476,18 +2481,22 @@ static void handleMasterServerJoinInviteResponse(const NetAddress* address, BitS stream->read(&theAddress.netNum[3]); stream->read(&theAddress.port); + bool isLocal = false; if (theAddress.netNum[0] == 255 && theAddress.netNum[1] == 255 && theAddress.netNum[2] == 255 && theAddress.netNum[3] == 255) { theAddress.netNum[0] = address->netNum[0]; theAddress.netNum[1] = address->netNum[1]; theAddress.netNum[2] = address->netNum[2]; theAddress.netNum[3] = address->netNum[3]; + + isLocal = true; } + char evalbuf[128]; - dSprintf(evalbuf, 128, "%s(\"%d.%d.%d.%d:%d\");", joinGameAcceptCb, theAddress.netNum[0], theAddress.netNum[1], theAddress.netNum[2], theAddress.netNum[3], theAddress.port); + dSprintf(evalbuf, 128, "%s(\"%d.%d.%d.%d:%d\",%s);", joinGameAcceptCb, theAddress.netNum[0], theAddress.netNum[1], theAddress.netNum[2], theAddress.netNum[3], theAddress.port, isLocal ? "true" : "false"); Con::evaluatef(evalbuf); } - else + else { char evalbuf[64]; dSprintf(evalbuf, 64, "%s();", joinGameRejectCb); diff --git a/game/MBU.torsion.exports b/game/MBU.torsion.exports index aaaf7dd4..28d4eb9d 100644 --- a/game/MBU.torsion.exports +++ b/game/MBU.torsion.exports @@ -3135,6 +3135,10 @@ More of a helper function than anything. If console access to the field list i getText - returns the text of the button. + setHover + hover + - sets the button hover state. + setText string text - sets the text of the button to the string. @@ -3900,6 +3904,9 @@ More of a helper function than anything. If console access to the field list i NetConnection SimGroup + arrangeConnection + ip + checkMaxRate clearPaths @@ -3927,6 +3934,9 @@ More of a helper function than anything. If console access to the field list i getXnAddr + relayConnection + ip + resolveGhostID S32 ghostID Convert a ghost id from this connection to a real id. @@ -5814,6 +5824,9 @@ More of a helper function than anything. If console access to the field list i DRLTarget float DRLTarget + shadowColor + ColorF shadowColor + useBloom bool useBloom @@ -7272,6 +7285,9 @@ Sim time is time since the game started. isKoreanBuild + isLocalAddress + addr + isObject object @@ -7304,6 +7320,10 @@ Sim time is time since the game started. isXInputConnected int controllerID + joinGameByInvite + inviteCode, acceptCb(%ip + , rejectCb) + lightScene script_function completeCallback=NULL, string mode="" Relight the scene. diff --git a/game/marble/client/ui/joinGameGui.gui b/game/marble/client/ui/joinGameGui.gui index 5b714d0a..129a90b5 100644 --- a/game/marble/client/ui/joinGameGui.gui +++ b/game/marble/client/ui/joinGameGui.gui @@ -217,6 +217,12 @@ function JoinGameGui::show(%this) { RootGui.setTitle($Text::JoinGame); RootGui.setB($Text::Back); + + if (GameMissionInfo.getMode() !$= GameMissionInfo.MPMode) + { + GameMissionInfo.setMode(GameMissionInfo.MPMode); + GameMissionInfo.setDefaultMission(); + } JoinGameGui.inviteCode = ""; InviteCodeInput.setText(JoinGameGui.inviteCode); @@ -273,15 +279,16 @@ function JoinGameGui::joinGame(%this) RootGui.setContent(MissionLoadingGui); } -function joinGameFound(%ip) +function joinGameFound(%ip, %isLocal) { cancel(JoinGameGui.joinTimeout); setNetPort(0); // Get random port pls - establishConnection(%ip, true, false, JoinGameGui.inviteCode); + establishConnection(%ip, true, %isLocal, JoinGameGui.inviteCode); } function joinGameNotFound() { + cancel(JoinGameGui.joinTimeout); echo("Not Found"); if (RootGui.contentGui == MissionLoadingGui) RootGui.setContent(JoinGameGui); @@ -289,6 +296,7 @@ function joinGameNotFound() function JoinGameGui::textInput(%this, %chr) { + cancel(JoinGameGui.joinTimeout); if (%chr !$= "D") { if (strlen(JoinGameGui.inviteCode) < 6) From bdfa96fcbf1c2da9d8100c11ed3b7280ba86f66c Mon Sep 17 00:00:00 2001 From: Human Gamer <39096122+HumanGamer@users.noreply.github.com> Date: Fri, 2 Jun 2023 17:58:20 -0500 Subject: [PATCH 46/46] Fixed join by invite sometimes not working. --- engine/source/game/net/serverQuery.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/engine/source/game/net/serverQuery.cpp b/engine/source/game/net/serverQuery.cpp index 5a633f23..69def015 100644 --- a/engine/source/game/net/serverQuery.cpp +++ b/engine/source/game/net/serverQuery.cpp @@ -2502,10 +2502,10 @@ static void handleMasterServerJoinInviteResponse(const NetAddress* address, BitS dSprintf(evalbuf, 64, "%s();", joinGameRejectCb); Con::evaluatef(evalbuf); } - dFree(joinGameAcceptCb); - dFree(joinGameRejectCb); - joinGameAcceptCb = NULL; - joinGameRejectCb = NULL; + //dFree(joinGameAcceptCb); + //dFree(joinGameRejectCb); + //joinGameAcceptCb = NULL; + //joinGameRejectCb = NULL; } #endif