mirror of
https://github.com/CraftyBoss/SuperMarioOdysseyOnline.git
synced 2024-12-22 08:20:18 +00:00
don't send empty GameInf and CostumeInf packets and resend them on reconnect
Resend because: on server restarts the server will lose the stage and costume information. If only one client is connected to the server, the packets currently aren't resent, so the server doesn't know in which stage the client is and what costume it wears (which I'd like to display on the website). With more then one client connected it already works, because when another client joins the server, the client will send both packets.
This commit is contained in:
parent
13c873aae0
commit
36f9343f83
5 changed files with 58 additions and 21 deletions
|
@ -6,7 +6,7 @@
|
|||
struct PACKED GameInf : Packet {
|
||||
GameInf() : Packet() {this->mType = PacketType::GAMEINF; mPacketSize = sizeof(GameInf) - sizeof(Packet);};
|
||||
bool1 is2D = false;
|
||||
u8 scenarioNo = -1;
|
||||
u8 scenarioNo = 255;
|
||||
char stageName[0x40] = {};
|
||||
|
||||
bool operator==(const GameInf &rhs) const {
|
||||
|
@ -19,4 +19,4 @@ struct PACKED GameInf : Packet {
|
|||
|
||||
bool operator!=(const GameInf& rhs) const { return !operator==(rhs); }
|
||||
|
||||
};
|
||||
};
|
||||
|
|
|
@ -103,6 +103,7 @@ class Client {
|
|||
static void sendShineCollectPacket(int shineId);
|
||||
static void sendTagInfPacket();
|
||||
static void sendCaptureInfPacket(const PlayerActorHakoniwa *player);
|
||||
void resendInitPackets();
|
||||
|
||||
int getCollectedShinesCount() { return curCollectedShines.size(); }
|
||||
int getShineID(int index) { if (index < curCollectedShines.size()) { return curCollectedShines[index]; } return -1; }
|
||||
|
@ -226,6 +227,7 @@ class Client {
|
|||
// Backups for our last player/game packets, used for example to re-send them for newly connected clients
|
||||
PlayerInf lastPlayerInfPacket = PlayerInf();
|
||||
GameInf lastGameInfPacket = GameInf();
|
||||
GameInf emptyGameInfPacket = GameInf();
|
||||
CostumeInf lastCostumeInfPacket = CostumeInf();
|
||||
|
||||
Keyboard* mKeyboard = nullptr; // keyboard for setting server IP
|
||||
|
|
|
@ -20,9 +20,11 @@
|
|||
|
||||
#include "packets/Packet.h"
|
||||
|
||||
class Client;
|
||||
|
||||
class SocketClient : public SocketBase {
|
||||
public:
|
||||
SocketClient(const char *name, sead::Heap *heap);
|
||||
SocketClient(const char* name, sead::Heap* heap, Client* client);
|
||||
nn::Result init(const char* ip, u16 port) override;
|
||||
bool tryReconnect();
|
||||
bool closeSocket() override;
|
||||
|
@ -54,6 +56,7 @@ class SocketClient : public SocketBase {
|
|||
|
||||
private:
|
||||
sead::Heap* mHeap = nullptr;
|
||||
Client* client = nullptr;
|
||||
|
||||
al::AsyncFunctorThread* mRecvThread = nullptr;
|
||||
al::AsyncFunctorThread* mSendThread = nullptr;
|
||||
|
@ -72,4 +75,4 @@ class SocketClient : public SocketBase {
|
|||
bool stringToIPAddress(const char* str, in_addr* out);
|
||||
};
|
||||
|
||||
typedef void (SocketClient::*SocketThreadFunc)(void);
|
||||
typedef void (SocketClient::*SocketThreadFunc)(void);
|
||||
|
|
|
@ -27,7 +27,7 @@ Client::Client() {
|
|||
|
||||
mKeyboard = new Keyboard(nn::swkbd::GetRequiredStringBufferSize());
|
||||
|
||||
mSocket = new SocketClient("SocketClient", mHeap);
|
||||
mSocket = new SocketClient("SocketClient", mHeap, this);
|
||||
|
||||
mPuppetHolder = new PuppetHolder(maxPuppets);
|
||||
|
||||
|
@ -87,6 +87,7 @@ void Client::init(al::LayoutInitInfo const &initInfo, GameDataHolderAccessor hol
|
|||
|
||||
Logger::log("Heap Free Size: %f/%f\n", mHeap->getFreeSize() * 0.001f, mHeap->getSize() * 0.001f);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief starts client read thread
|
||||
*
|
||||
|
@ -103,6 +104,7 @@ bool Client::startThread() {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief restarts currently active connection to server
|
||||
*
|
||||
|
@ -140,6 +142,7 @@ void Client::restartConnection() {
|
|||
Logger::log("Reconnect Unsuccessful.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief starts a connection using client's TCP socket class, pulling up the software keyboard for user inputted IP if save file does not have one saved.
|
||||
*
|
||||
|
@ -346,16 +349,18 @@ void Client::readFunc() {
|
|||
|
||||
// Send relevant info packets when another client is connected
|
||||
|
||||
// Assume game packets are empty from first connection
|
||||
if (lastGameInfPacket.mUserID != mUserID)
|
||||
lastGameInfPacket.mUserID = mUserID;
|
||||
mSocket->send(&lastGameInfPacket);
|
||||
if (lastGameInfPacket != emptyGameInfPacket) {
|
||||
// Assume game packets are empty from first connection
|
||||
if (lastGameInfPacket.mUserID != mUserID)
|
||||
lastGameInfPacket.mUserID = mUserID;
|
||||
mSocket->send(&lastGameInfPacket);
|
||||
}
|
||||
|
||||
// No need to send player/costume packets if they're empty
|
||||
if (lastPlayerInfPacket.mUserID == mUserID)
|
||||
mSocket->send(&lastPlayerInfPacket);
|
||||
if (lastCostumeInfPacket.mUserID == mUserID)
|
||||
mSocket->send(&lastCostumeInfPacket);
|
||||
// No need to send player/costume packets if they're empty
|
||||
if (lastPlayerInfPacket.mUserID == mUserID)
|
||||
mSocket->send(&lastPlayerInfPacket);
|
||||
if (lastCostumeInfPacket.mUserID == mUserID)
|
||||
mSocket->send(&lastCostumeInfPacket);
|
||||
|
||||
break;
|
||||
case PacketType::COSTUMEINF:
|
||||
|
@ -479,6 +484,7 @@ void Client::sendPlayerInfPacket(const PlayerActorBase *playerBase, bool isYukim
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sends info related to player's cap actor to server
|
||||
*
|
||||
|
@ -553,14 +559,14 @@ void Client::sendGameInfPacket(const PlayerActorHakoniwa* player, GameDataHolder
|
|||
|
||||
strcpy(packet->stageName, GameDataFunction::getCurrentStageName(holder));
|
||||
|
||||
if(*packet != sInstance->lastGameInfPacket) {
|
||||
if (*packet != sInstance->lastGameInfPacket && *packet != sInstance->emptyGameInfPacket) {
|
||||
sInstance->lastGameInfPacket = *packet;
|
||||
sInstance->mSocket->queuePacket(packet);
|
||||
} else {
|
||||
sInstance->mHeap->free(packet); // free packet if we're not using it
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Sends only stage info to the server.
|
||||
|
@ -584,9 +590,10 @@ void Client::sendGameInfPacket(GameDataHolderAccessor holder) {
|
|||
|
||||
strcpy(packet->stageName, GameDataFunction::getCurrentStageName(holder));
|
||||
|
||||
sInstance->lastGameInfPacket = *packet;
|
||||
|
||||
sInstance->mSocket->queuePacket(packet);
|
||||
if (*packet != sInstance->emptyGameInfPacket) {
|
||||
sInstance->lastGameInfPacket = *packet;
|
||||
sInstance->mSocket->queuePacket(packet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -637,6 +644,8 @@ void Client::sendCostumeInfPacket(const char* body, const char* cap) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(body, "") && !strcmp(cap, "")) { return; }
|
||||
|
||||
sead::ScopedCurrentHeapSetter setter(sInstance->mHeap);
|
||||
|
||||
CostumeInf *packet = new CostumeInf(body, cap);
|
||||
|
@ -674,6 +683,21 @@ void Client::sendCaptureInfPacket(const PlayerActorHakoniwa* player) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
void Client::resendInitPackets() {
|
||||
// CostumeInfPacket
|
||||
if (lastCostumeInfPacket.mUserID == mUserID) {
|
||||
mSocket->queuePacket(&lastCostumeInfPacket);
|
||||
}
|
||||
|
||||
// GameInfPacket
|
||||
if (lastGameInfPacket != emptyGameInfPacket) {
|
||||
mSocket->queuePacket(&lastGameInfPacket);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
|
@ -858,6 +882,7 @@ void Client::updatePlayerConnect(PlayerConnect* packet) {
|
|||
mConnectCount++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
#include "thread/seadMessageQueue.h"
|
||||
#include "types.h"
|
||||
|
||||
SocketClient::SocketClient(const char* name, sead::Heap* heap) : mHeap(heap), SocketBase(name) {
|
||||
SocketClient::SocketClient(const char* name, sead::Heap* heap, Client* client) : mHeap(heap), SocketBase(name) {
|
||||
|
||||
this->client = client;
|
||||
|
||||
mRecvThread = new al::AsyncFunctorThread("SocketRecvThread", al::FunctorV0M<SocketClient*, SocketThreadFunc>(this, &SocketClient::recvFunc), 0, 0x1000, {0});
|
||||
mSendThread = new al::AsyncFunctorThread("SocketSendThread", al::FunctorV0M<SocketClient*, SocketThreadFunc>(this, &SocketClient::sendFunc), 0, 0x1000, {0});
|
||||
|
@ -99,6 +101,11 @@ nn::Result SocketClient::init(const char* ip, u16 port) {
|
|||
|
||||
send(&initPacket);
|
||||
|
||||
// on a reconnect, resend some maybe missing packets
|
||||
if (initPacket.conType == ConnectionTypes::RECONNECT) {
|
||||
client->resendInitPackets();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
@ -357,4 +364,4 @@ void SocketClient::trySendQueue() {
|
|||
|
||||
Packet* SocketClient::tryGetPacket(sead::MessageQueue::BlockType blockType) {
|
||||
return socket_log_state == SOCKET_LOG_CONNECTED ? (Packet*)mRecvQueue.pop(blockType) : nullptr;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue