mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 02:43:44 +00:00
With new binaries in place, master moves everything onto them while the server keeps running (the dashboard's Live update, /liveupdate or SIGUSR2 to master): - database migrations of the new build first; a failure stops there - UGC finishes the jobs it is running (queued rows stay pending), auth restarts, chat hands its teams to master for the next chat server; master starts the new processes and retries ones that don't come back - once the new chat server is up (CHAT_SERVER_READY) every world connects at once and sends its players again (LoginSessionNotify resync, no login logged) - every world instance is replaced with an instance migration: public worlds and private ones (same password) at once, properties after the old instance saved and froze the property (MIGRATE_PREPARE: no building, claiming or saving there any more), activity zones and character select once their players left or after a wait; empty instances just stop, zones in prestart_worlds get a new one first - the dashboard restarts last and picks the status up again Players land where they stood (position carried in CarriedPlayerState, also on properties and Moon Base). Draining instances get no new players (InstanceMigration::AcceptsNewPlayers) and show as "Moving players" in the world list. The order lives in LiveUpdateMachine.h without master state and is unit tested; master's glue is LiveUpdateCoordinator. Master itself is not replaced. Message IDs are appended only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
105 lines
3.2 KiB
C++
105 lines
3.2 KiB
C++
#pragma once
|
|
#include <map>
|
|
#include "dCommonVars.h"
|
|
#include "RakString.h"
|
|
#include <vector>
|
|
#include "Game.h"
|
|
#include "dServer.h"
|
|
#include <unordered_map>
|
|
#include "ChatPackets.h"
|
|
|
|
enum class eGameMasterLevel : uint8_t;
|
|
|
|
struct TeamData;
|
|
|
|
struct IgnoreData {
|
|
IgnoreData(const std::string& name, const LWOOBJID& id) : playerName{ name }, playerId{ id } {}
|
|
inline bool operator==(const std::string& other) const noexcept {
|
|
return playerName == other;
|
|
}
|
|
|
|
inline bool operator==(const LWOOBJID& other) const noexcept {
|
|
return playerId == other;
|
|
}
|
|
|
|
LWOOBJID playerId = LWOOBJID_EMPTY;
|
|
std::string playerName;
|
|
};
|
|
|
|
struct PlayerData {
|
|
operator bool() const noexcept {
|
|
return playerID != LWOOBJID_EMPTY;
|
|
}
|
|
|
|
bool operator==(const PlayerData& other) const noexcept {
|
|
return playerID == other.playerID;
|
|
}
|
|
|
|
bool GetIsMuted() const {
|
|
return muteExpire == 1 || muteExpire > time(NULL);
|
|
}
|
|
|
|
SystemAddress worldServerSysAddr{};
|
|
LWOZONEID zoneID{};
|
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
|
time_t muteExpire = 0;
|
|
uint8_t countOfBestFriends = 0;
|
|
std::string playerName;
|
|
std::vector<FriendData> friends;
|
|
std::vector<IgnoreData> ignoredPlayers;
|
|
eGameMasterLevel gmLevel = static_cast<eGameMasterLevel>(0); // CIVILLIAN
|
|
bool isFTP = false;
|
|
bool isLogin = false;
|
|
};
|
|
|
|
|
|
struct TeamData {
|
|
TeamData();
|
|
LWOOBJID teamID = LWOOBJID_EMPTY; // Internal use
|
|
LWOOBJID leaderID = LWOOBJID_EMPTY;
|
|
std::vector<LWOOBJID> memberIDs{};
|
|
uint8_t lootFlag = 0;
|
|
bool local = false;
|
|
LWOZONEID zoneId = {};
|
|
};
|
|
|
|
class PlayerContainer {
|
|
public:
|
|
void Initialize();
|
|
void InsertPlayer(const ChatPackets::LoginSessionNotify& notify, const SystemAddress& sysAddr);
|
|
// Live updates: this chat server replaces one that retired; don't log everyone out when it stops
|
|
void SetRetiring(bool retiring) { m_Retiring = retiring; }
|
|
bool IsRetiring() const { return m_Retiring; }
|
|
void ScheduleRemovePlayer(const ChatPackets::UnexpectedDisconnect& notify, const SystemAddress& sysAddr);
|
|
void RemovePlayer(const LWOOBJID playerID);
|
|
void MuteUpdate(const ChatPackets::GMMute& mute, const SystemAddress& sysAddr);
|
|
void BroadcastMuteUpdate(LWOOBJID player, time_t time);
|
|
void Shutdown();
|
|
|
|
const PlayerData& GetPlayerData(const LWOOBJID& playerID);
|
|
const PlayerData& GetPlayerData(const std::string& playerName);
|
|
PlayerData& GetPlayerDataMutable(const LWOOBJID& playerID);
|
|
PlayerData& GetPlayerDataMutable(const std::string& playerName);
|
|
std::u16string GetName(LWOOBJID playerID);
|
|
LWOOBJID GetId(const std::u16string& playerName);
|
|
void Update(const float deltaTime);
|
|
|
|
uint32_t GetPlayerCount() { return m_PlayerCount; };
|
|
uint32_t GetSimCount() { return m_SimCount; };
|
|
const std::map<LWOOBJID, PlayerData>& GetAllPlayers() const { return m_Players; };
|
|
uint32_t GetMaxNumberOfBestFriends() { return m_MaxNumberOfBestFriends; }
|
|
uint32_t GetMaxNumberOfFriends() { return m_MaxNumberOfFriends; }
|
|
bool PlayerBeingRemoved(const LWOOBJID playerID) { return m_PlayersToRemove.contains(playerID); }
|
|
|
|
private:
|
|
std::map<LWOOBJID, PlayerData> m_Players;
|
|
std::unordered_map<LWOOBJID, std::u16string> m_Names;
|
|
std::map<LWOOBJID, float> m_PlayersToRemove;
|
|
uint32_t m_MaxNumberOfBestFriends = 5;
|
|
uint32_t m_MaxNumberOfFriends = 50;
|
|
uint32_t m_PlayerCount = 0;
|
|
uint32_t m_SimCount = 0;
|
|
bool m_Retiring = false;
|
|
};
|
|
|