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:
Robin C. Ladiges 2022-09-05 03:21:43 +02:00 committed by Sanae
parent 13c873aae0
commit 36f9343f83
5 changed files with 58 additions and 21 deletions

View file

@ -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 {
@ -19,4 +19,4 @@ struct PACKED GameInf : Packet {
bool operator!=(const GameInf& rhs) const { return !operator==(rhs); } bool operator!=(const GameInf& rhs) const { return !operator==(rhs); }
}; };

View file

@ -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

View file

@ -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;
@ -72,4 +75,4 @@ class SocketClient : public SocketBase {
bool stringToIPAddress(const char* str, in_addr* out); bool stringToIPAddress(const char* str, in_addr* out);
}; };
typedef void (SocketClient::*SocketThreadFunc)(void); typedef void (SocketClient::*SocketThreadFunc)(void);

View file

@ -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,16 +349,18 @@ void Client::readFunc() {
// Send relevant info packets when another client is connected // Send relevant info packets when another client is connected
// Assume game packets are empty from first connection if (lastGameInfPacket != emptyGameInfPacket) {
if (lastGameInfPacket.mUserID != mUserID) // Assume game packets are empty from first connection
lastGameInfPacket.mUserID = mUserID; if (lastGameInfPacket.mUserID != mUserID)
mSocket->send(&lastGameInfPacket); lastGameInfPacket.mUserID = mUserID;
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)
mSocket->send(&lastPlayerInfPacket); mSocket->send(&lastPlayerInfPacket);
if (lastCostumeInfPacket.mUserID == mUserID) if (lastCostumeInfPacket.mUserID == mUserID)
mSocket->send(&lastCostumeInfPacket); mSocket->send(&lastCostumeInfPacket);
break; break;
case PacketType::COSTUMEINF: 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 * @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,9 +590,10 @@ void Client::sendGameInfPacket(GameDataHolderAccessor holder) {
strcpy(packet->stageName, GameDataFunction::getCurrentStageName(holder)); strcpy(packet->stageName, GameDataFunction::getCurrentStageName(holder));
sInstance->lastGameInfPacket = *packet; if (*packet != sInstance->emptyGameInfPacket) {
sInstance->lastGameInfPacket = *packet;
sInstance->mSocket->queuePacket(packet); sInstance->mSocket->queuePacket(packet);
}
} }
/** /**
@ -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
* *

View file

@ -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;
} }
@ -357,4 +364,4 @@ void SocketClient::trySendQueue() {
Packet* SocketClient::tryGetPacket(sead::MessageQueue::BlockType blockType) { Packet* SocketClient::tryGetPacket(sead::MessageQueue::BlockType blockType) {
return socket_log_state == SOCKET_LOG_CONNECTED ? (Packet*)mRecvQueue.pop(blockType) : nullptr; return socket_log_state == SOCKET_LOG_CONNECTED ? (Packet*)mRecvQueue.pop(blockType) : nullptr;
} }