mirror of
https://github.com/CraftyBoss/SuperMarioOdysseyOnline.git
synced 2024-11-24 20:25: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 {
|
struct PACKED GameInf : Packet {
|
||||||
GameInf() : Packet() {this->mType = PacketType::GAMEINF; mPacketSize = sizeof(GameInf) - sizeof(Packet);};
|
GameInf() : Packet() {this->mType = PacketType::GAMEINF; mPacketSize = sizeof(GameInf) - sizeof(Packet);};
|
||||||
bool1 is2D = false;
|
bool1 is2D = false;
|
||||||
u8 scenarioNo = -1;
|
u8 scenarioNo = 255;
|
||||||
char stageName[0x40] = {};
|
char stageName[0x40] = {};
|
||||||
|
|
||||||
bool operator==(const GameInf &rhs) const {
|
bool operator==(const GameInf &rhs) const {
|
||||||
|
|
|
@ -103,6 +103,7 @@ class Client {
|
||||||
static void sendShineCollectPacket(int shineId);
|
static void sendShineCollectPacket(int shineId);
|
||||||
static void sendTagInfPacket();
|
static void sendTagInfPacket();
|
||||||
static void sendCaptureInfPacket(const PlayerActorHakoniwa *player);
|
static void sendCaptureInfPacket(const PlayerActorHakoniwa *player);
|
||||||
|
void resendInitPackets();
|
||||||
|
|
||||||
int getCollectedShinesCount() { return curCollectedShines.size(); }
|
int getCollectedShinesCount() { return curCollectedShines.size(); }
|
||||||
int getShineID(int index) { if (index < curCollectedShines.size()) { return curCollectedShines[index]; } return -1; }
|
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
|
// Backups for our last player/game packets, used for example to re-send them for newly connected clients
|
||||||
PlayerInf lastPlayerInfPacket = PlayerInf();
|
PlayerInf lastPlayerInfPacket = PlayerInf();
|
||||||
GameInf lastGameInfPacket = GameInf();
|
GameInf lastGameInfPacket = GameInf();
|
||||||
|
GameInf emptyGameInfPacket = GameInf();
|
||||||
CostumeInf lastCostumeInfPacket = CostumeInf();
|
CostumeInf lastCostumeInfPacket = CostumeInf();
|
||||||
|
|
||||||
Keyboard* mKeyboard = nullptr; // keyboard for setting server IP
|
Keyboard* mKeyboard = nullptr; // keyboard for setting server IP
|
||||||
|
|
|
@ -20,9 +20,11 @@
|
||||||
|
|
||||||
#include "packets/Packet.h"
|
#include "packets/Packet.h"
|
||||||
|
|
||||||
|
class Client;
|
||||||
|
|
||||||
class SocketClient : public SocketBase {
|
class SocketClient : public SocketBase {
|
||||||
public:
|
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;
|
nn::Result init(const char* ip, u16 port) override;
|
||||||
bool tryReconnect();
|
bool tryReconnect();
|
||||||
bool closeSocket() override;
|
bool closeSocket() override;
|
||||||
|
@ -54,6 +56,7 @@ class SocketClient : public SocketBase {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sead::Heap* mHeap = nullptr;
|
sead::Heap* mHeap = nullptr;
|
||||||
|
Client* client = nullptr;
|
||||||
|
|
||||||
al::AsyncFunctorThread* mRecvThread = nullptr;
|
al::AsyncFunctorThread* mRecvThread = nullptr;
|
||||||
al::AsyncFunctorThread* mSendThread = nullptr;
|
al::AsyncFunctorThread* mSendThread = nullptr;
|
||||||
|
|
|
@ -27,7 +27,7 @@ Client::Client() {
|
||||||
|
|
||||||
mKeyboard = new Keyboard(nn::swkbd::GetRequiredStringBufferSize());
|
mKeyboard = new Keyboard(nn::swkbd::GetRequiredStringBufferSize());
|
||||||
|
|
||||||
mSocket = new SocketClient("SocketClient", mHeap);
|
mSocket = new SocketClient("SocketClient", mHeap, this);
|
||||||
|
|
||||||
mPuppetHolder = new PuppetHolder(maxPuppets);
|
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);
|
Logger::log("Heap Free Size: %f/%f\n", mHeap->getFreeSize() * 0.001f, mHeap->getSize() * 0.001f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief starts client read thread
|
* @brief starts client read thread
|
||||||
*
|
*
|
||||||
|
@ -103,6 +104,7 @@ bool Client::startThread() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief restarts currently active connection to server
|
* @brief restarts currently active connection to server
|
||||||
*
|
*
|
||||||
|
@ -140,6 +142,7 @@ void Client::restartConnection() {
|
||||||
Logger::log("Reconnect Unsuccessful.\n");
|
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.
|
* @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,10 +349,12 @@ void Client::readFunc() {
|
||||||
|
|
||||||
// Send relevant info packets when another client is connected
|
// Send relevant info packets when another client is connected
|
||||||
|
|
||||||
|
if (lastGameInfPacket != emptyGameInfPacket) {
|
||||||
// Assume game packets are empty from first connection
|
// Assume game packets are empty from first connection
|
||||||
if (lastGameInfPacket.mUserID != mUserID)
|
if (lastGameInfPacket.mUserID != mUserID)
|
||||||
lastGameInfPacket.mUserID = mUserID;
|
lastGameInfPacket.mUserID = mUserID;
|
||||||
mSocket->send(&lastGameInfPacket);
|
mSocket->send(&lastGameInfPacket);
|
||||||
|
}
|
||||||
|
|
||||||
// No need to send player/costume packets if they're empty
|
// No need to send player/costume packets if they're empty
|
||||||
if (lastPlayerInfPacket.mUserID == mUserID)
|
if (lastPlayerInfPacket.mUserID == mUserID)
|
||||||
|
@ -479,6 +484,7 @@ void Client::sendPlayerInfPacket(const PlayerActorBase *playerBase, bool isYukim
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief sends info related to player's cap actor to server
|
* @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));
|
strcpy(packet->stageName, GameDataFunction::getCurrentStageName(holder));
|
||||||
|
|
||||||
if(*packet != sInstance->lastGameInfPacket) {
|
if (*packet != sInstance->lastGameInfPacket && *packet != sInstance->emptyGameInfPacket) {
|
||||||
sInstance->lastGameInfPacket = *packet;
|
sInstance->lastGameInfPacket = *packet;
|
||||||
sInstance->mSocket->queuePacket(packet);
|
sInstance->mSocket->queuePacket(packet);
|
||||||
} else {
|
} else {
|
||||||
sInstance->mHeap->free(packet); // free packet if we're not using it
|
sInstance->mHeap->free(packet); // free packet if we're not using it
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
* Sends only stage info to the server.
|
* Sends only stage info to the server.
|
||||||
|
@ -584,10 +590,11 @@ void Client::sendGameInfPacket(GameDataHolderAccessor holder) {
|
||||||
|
|
||||||
strcpy(packet->stageName, GameDataFunction::getCurrentStageName(holder));
|
strcpy(packet->stageName, GameDataFunction::getCurrentStageName(holder));
|
||||||
|
|
||||||
|
if (*packet != sInstance->emptyGameInfPacket) {
|
||||||
sInstance->lastGameInfPacket = *packet;
|
sInstance->lastGameInfPacket = *packet;
|
||||||
|
|
||||||
sInstance->mSocket->queuePacket(packet);
|
sInstance->mSocket->queuePacket(packet);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
|
@ -637,6 +644,8 @@ void Client::sendCostumeInfPacket(const char* body, const char* cap) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(body, "") && !strcmp(cap, "")) { return; }
|
||||||
|
|
||||||
sead::ScopedCurrentHeapSetter setter(sInstance->mHeap);
|
sead::ScopedCurrentHeapSetter setter(sInstance->mHeap);
|
||||||
|
|
||||||
CostumeInf *packet = new CostumeInf(body, cap);
|
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
|
* @brief
|
||||||
*
|
*
|
||||||
|
@ -858,6 +882,7 @@ void Client::updatePlayerConnect(PlayerConnect* packet) {
|
||||||
mConnectCount++;
|
mConnectCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
*
|
*
|
||||||
|
|
|
@ -13,7 +13,9 @@
|
||||||
#include "thread/seadMessageQueue.h"
|
#include "thread/seadMessageQueue.h"
|
||||||
#include "types.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});
|
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});
|
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);
|
send(&initPacket);
|
||||||
|
|
||||||
|
// on a reconnect, resend some maybe missing packets
|
||||||
|
if (initPacket.conType == ConnectionTypes::RECONNECT) {
|
||||||
|
client->resendInitPackets();
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue