Client synchronization improvements

This commit is contained in:
gsemaj 2024-06-23 21:04:43 -07:00
parent 6d2f120305
commit 78e4779db6
No known key found for this signature in database
GPG Key ID: 24B96BAA40497929
5 changed files with 28 additions and 27 deletions

View File

@ -30,7 +30,7 @@ static bool playerHasBuddyWithID(Player* plr, int buddyID) {
#pragma endregion #pragma endregion
// Refresh buddy list // Refresh buddy list
void Buddies::refreshBuddyList(CNSocket* sock) { void Buddies::sendBuddyList(CNSocket* sock) {
Player* plr = PlayerManager::getPlayer(sock); Player* plr = PlayerManager::getPlayer(sock);
int buddyCnt = Database::getNumBuddies(plr); int buddyCnt = Database::getNumBuddies(plr);
@ -278,15 +278,6 @@ static void reqFindNameBuddyAccept(CNSocket* sock, CNPacketData* data) {
static void reqPktGetBuddyState(CNSocket* sock, CNPacketData* data) { static void reqPktGetBuddyState(CNSocket* sock, CNPacketData* data) {
Player* plr = PlayerManager::getPlayer(sock); Player* plr = PlayerManager::getPlayer(sock);
/*
* If the buddy list wasn't synced a second time yet, sync it.
* Not sure why we have to do it again for the client not to trip up.
*/
if (!plr->buddiesSynced) {
refreshBuddyList(sock);
plr->buddiesSynced = true;
}
INITSTRUCT(sP_FE2CL_REP_GET_BUDDY_STATE_SUCC, resp); INITSTRUCT(sP_FE2CL_REP_GET_BUDDY_STATE_SUCC, resp);
for (int slot = 0; slot < 50; slot++) { for (int slot = 0; slot < 50; slot++) {

View File

@ -6,5 +6,5 @@ namespace Buddies {
void init(); void init();
// Buddy list // Buddy list
void refreshBuddyList(CNSocket* sock); void sendBuddyList(CNSocket* sock);
} }

View File

@ -908,6 +908,10 @@ static void playerTick(CNServer *serv, time_t currTime) {
Player *plr = pair.second; Player *plr = pair.second;
bool transmit = false; bool transmit = false;
// don't tick players that haven't loaded in yet
if (!plr->initialLoadDone)
continue;
// group ticks // group ticks
if (plr->group != nullptr) if (plr->group != nullptr)
Groups::groupTickInfo(sock); Groups::groupTickInfo(sock);

View File

@ -72,8 +72,8 @@ struct Player : public Entity, public ICombatant {
bool notify = false; bool notify = false;
bool hidden = false; bool hidden = false;
bool unwarpable = false; bool unwarpable = false;
bool initialLoadDone = false;
bool buddiesSynced = false;
int64_t buddyIDs[50] = {}; int64_t buddyIDs[50] = {};
bool isBuddyBlocked[50] = {}; bool isBuddyBlocked[50] = {};

View File

@ -155,10 +155,8 @@ void PlayerManager::sendPlayerTo(CNSocket* sock, int X, int Y, int Z) {
* Nanos the player hasn't unlocked will (and should) be greyed out. Thus, all nanos should be accounted * Nanos the player hasn't unlocked will (and should) be greyed out. Thus, all nanos should be accounted
* for in these packets, even if the player hasn't unlocked them. * for in these packets, even if the player hasn't unlocked them.
*/ */
static void sendNanoBookSubset(CNSocket *sock) { static void sendNanoBookSubset(CNSocket *sock, Player *plr) {
#ifdef ACADEMY #ifdef ACADEMY
Player *plr = getPlayer(sock);
int16_t id = 0; int16_t id = 0;
INITSTRUCT(sP_FE2CL_REP_NANO_BOOK_SUBSET, pkt); INITSTRUCT(sP_FE2CL_REP_NANO_BOOK_SUBSET, pkt);
@ -294,27 +292,23 @@ static void enterPlayer(CNSocket* sock, CNPacketData* data) {
sock->setFEKey(lm->FEKey); sock->setFEKey(lm->FEKey);
sock->setActiveKey(SOCKETKEY_FE); // send all packets using the FE key from now on sock->setActiveKey(SOCKETKEY_FE); // send all packets using the FE key from now on
// Academy builds receive nanos in a separate packet. These need to be sent
// before P_FE2CL_REP_PC_ENTER_SUCC as well as after initial load
// due to a race condition in the client :(
sendNanoBookSubset(sock, plr);
sock->sendPacket(response, P_FE2CL_REP_PC_ENTER_SUCC); sock->sendPacket(response, P_FE2CL_REP_PC_ENTER_SUCC);
// transmit MOTD after entering the game, so the client hopefully changes modes on time // Academy builds receive nanos separately. Need to send this ASAP after P_FE2CL_REP_PC_ENTER_SUCC
Chat::sendServerMessage(sock, settings::MOTDSTRING); // because the client will fail to render equipped nanos if it's sent too late
// transfer ownership of Player object into the shard (still valid in this function though) // transfer ownership of Player object into the shard (still valid in this function though)
addPlayer(sock, plr); addPlayer(sock, plr);
// check if there is an expiring vehicle
Items::checkItemExpire(sock, plr);
// set player equip stats // set player equip stats
Items::setItemStats(plr); Items::setItemStats(plr);
Missions::failInstancedMissions(sock);
sendNanoBookSubset(sock);
// initial buddy sync
Buddies::refreshBuddyList(sock);
for (auto& pair : players) for (auto& pair : players)
if (pair.second->notify) if (pair.second->notify)
Chat::sendServerMessage(pair.first, "[ADMIN]" + getPlayerName(plr) + " has joined."); Chat::sendServerMessage(pair.first, "[ADMIN]" + getPlayerName(plr) + " has joined.");
@ -377,6 +371,18 @@ static void loadPlayer(CNSocket* sock, CNPacketData* data) {
sock->sendPacket(pkt, P_FE2CL_INSTANCE_MAP_INFO); sock->sendPacket(pkt, P_FE2CL_INSTANCE_MAP_INFO);
} }
if (!plr->initialLoadDone) {
// these should be called only once, but not until after
// first load-in or else the client may ignore the packets
Chat::sendServerMessage(sock, settings::MOTDSTRING); // MOTD
Missions::failInstancedMissions(sock); // auto-fail missions
Buddies::sendBuddyList(sock); // buddy list
Items::checkItemExpire(sock, plr); // vehicle expiration
sendNanoBookSubset(sock, plr); // nanos (post-load)
plr->initialLoadDone = true;
}
} }
static void heartbeatPlayer(CNSocket* sock, CNPacketData* data) { static void heartbeatPlayer(CNSocket* sock, CNPacketData* data) {