diff options
| author | fusion32 <marcopuzziello@gmail.com> | 2025-06-17 20:10:41 -0300 |
|---|---|---|
| committer | fusion32 <marcopuzziello@gmail.com> | 2025-06-17 20:10:41 -0300 |
| commit | b912ba995c2175b00393f95388ae2ec1afd0494b (patch) | |
| tree | 20c9eae485c1a365e83db0bcce45f6c691bd4b54 /src | |
| parent | 56bdec57609cd00d7827a3008a9c6b06707097ca (diff) | |
| download | game-b912ba995c2175b00393f95388ae2ec1afd0494b.tar.gz game-b912ba995c2175b00393f95388ae2ec1afd0494b.zip | |
TPlayer constructor and destructor
Diffstat (limited to 'src')
| -rw-r--r-- | src/common.hh | 2 | ||||
| -rw-r--r-- | src/connection.hh | 2 | ||||
| -rw-r--r-- | src/cr.hh | 65 | ||||
| -rw-r--r-- | src/crmain.cc | 19 | ||||
| -rw-r--r-- | src/crplayer.cc | 363 | ||||
| -rw-r--r-- | src/operate.cc | 1 | ||||
| -rw-r--r-- | src/stubs.hh | 14 | ||||
| -rw-r--r-- | src/time.cc | 8 |
8 files changed, 435 insertions, 39 deletions
diff --git a/src/common.hh b/src/common.hh index 9800e6a..4737c54 100644 --- a/src/common.hh +++ b/src/common.hh @@ -9,6 +9,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <time.h> #include <algorithm> @@ -139,6 +140,7 @@ char *Capitals(char *Text); // ============================================================================= extern uint32 RoundNr; extern uint32 ServerMilliseconds; +struct tm GetLocalTimeTM(time_t t); void GetRealTime(int *Hour, int *Minute); void GetTime(int *Hour, int *Minute); void GetDate(int *Year, int *Cycle, int *Day); diff --git a/src/connection.hh b/src/connection.hh index 44b7360..4a5e544 100644 --- a/src/connection.hh +++ b/src/connection.hh @@ -18,6 +18,8 @@ struct TConnection { TPlayer *GetPlayer(void); void Logout(int Delay, bool StopFight); bool IsVisible(int x, int y, int z); + void EnterGame(void); + const char *GetIPAddress(void); // DATA // ================= @@ -433,6 +433,12 @@ struct TFindCreatures { // TCreature // ============================================================================= +enum : int { + LOSE_INVENTORY_NONE = 0, + LOSE_INVENTORY_SOME = 1, + LOSE_INVENTORY_ALL = 2, +}; + struct TToDoEntry { ToDoType Code; union{ @@ -707,7 +713,11 @@ struct TPlayerIndexLeafNode: TPlayerIndexNode { }; struct TPlayer: TCreature { - //TPlayer(void); + TPlayer(TConnection *Connection, uint32 CharacterID); + void SetInList(void); + void DelInList(void); + +//== // TODO(fusion): Eventually sort these out when we implement player functions. uint8 GetRealProfession(void); @@ -716,22 +726,16 @@ struct TPlayer: TCreature { bool GetActivePromotion(void); void ClearProfession(void); void SetProfession(uint8 Profession); - int GetQuestValue(int Number); void SetQuestValue(int Number, int Value); - void JoinParty(uint32 Leader); void LeaveParty(void); uint32 GetPartyLeader(bool CheckFormer); - bool SpellKnown(int SpellNr); - bool IsAttackJustified(uint32 Victim); void RecordAttack(uint32 Victim); void RecordMurder(uint32 Victim); - void CheckState(void); - void ClearPlayerkillingMarks(void); void SaveInventory(void); Object GetOpenContainer(int ContainerNr); @@ -741,10 +745,16 @@ struct TPlayer: TCreature { int CheckForMuting(void); int RecordTalk(void); int RecordMessage(uint32 Addressee); + void LoadData(void); + void SaveData(void); + void CheckOutfit(void); + void Regenerate(void); + void LoadInventory(bool SetDefaultInventory); + void SendBuddies(void); // VIRTUAL FUNCTIONS // ================= - // TODO + ~TPlayer(void) override; // DATA // ================= @@ -843,6 +853,45 @@ void ExitNonplayer(); // crplayer.cc // ============================================================================= +int GetNumberOfPlayers(void); +TPlayer *GetPlayer(uint32 CharacterID); +TPlayer *GetPlayer(const char *Name); +bool IsPlayerOnline(const char *Name); +int IdentifyPlayer(const char *Name, bool ExactMatch, bool IgnoreGamemasters, TPlayer **OutPlayer); +void LogoutAllPlayers(void); +void CloseProcessedRequests(uint32 CharacterID); +void NotifyBuddies(uint32 CharacterID, const char *Name, bool Login); +void CreatePlayerList(bool Online); +void PrintPlayerPositions(void); +void LoadDepot(TPlayerData *PlayerData, int DepotNr, Object Con); +void SaveDepot(TPlayerData *PlayerData, int DepotNr, Object Con); +void GetProfessionName(char *Buffer, int Profession, bool Article, bool Capitals); +void SendExistingRequests(TConnection *Connection); + +void SavePlayerPoolSlot(TPlayerData *Slot); +void FreePlayerPoolSlot(TPlayerData *Slot); +TPlayerData *GetPlayerPoolSlot(uint32 CharacterID); +TPlayerData *AssignPlayerPoolSlot(uint32 CharacterID, bool DontWait); +TPlayerData *AttachPlayerPoolSlot(uint32 CharacterID, bool DontWait); +void AttachPlayerPoolSlot(TPlayerData *Slot, bool DontWait); +void IncreasePlayerPoolSlotSticky(TPlayerData *Slot); +void DecreasePlayerPoolSlotSticky(TPlayerData *Slot); +void DecreasePlayerPoolSlotSticky(uint32 CharacterID); +void ReleasePlayerPoolSlot(TPlayerData *Slot); +void SavePlayerPoolSlots(void); +void InitPlayerPool(void); +void ExitPlayerPool(void); + +int GetPlayerIndexEntryNumber(const char *Name, int Position); +void InsertPlayerIndex(TPlayerIndexInternalNode *Node, + int Position, const char *Name, uint32 CharacterID); +TPlayerIndexEntry *SearchPlayerIndex(const char *Name); +bool PlayerExists(const char *Name); +uint32 GetCharacterID(const char *Name); +const char *GetCharacterName(const char *Name); +void InitPlayerIndex(void); +void ExitPlayerIndex(void); + void InitPlayer(void); void ExitPlayer(void); diff --git a/src/crmain.cc b/src/crmain.cc index f29a992..ddf5393 100644 --- a/src/crmain.cc +++ b/src/crmain.cc @@ -7,7 +7,6 @@ #include "stubs.hh" #include <dirent.h> -#include <time.h> TRaceData RaceData[MAX_RACES]; priority_queue<uint32, uint32> ToDoQueue(5000, 1000); @@ -135,7 +134,7 @@ TCreature::TCreature(void) : this->Direction = 0; this->Radius = INT_MAX; this->IsDead = false; - this->LoseInventory = 2; + this->LoseInventory = LOSE_INVENTORY_ALL; this->LoggingOut = false; this->LogoutAllowed = false; this->EarliestLogoutRound = 0; @@ -226,7 +225,7 @@ TCreature::~TCreature(void){ Change(Corpse, TEXTSTRING, AddDynamicString(Help)); } - if(this->LoseInventory != 0){ // LOSE_INVENTORY_NONE ? + if(this->LoseInventory != LOSE_INVENTORY_NONE){ for(int Position = INVENTORY_FIRST; Position <= INVENTORY_LAST; Position += 1){ @@ -235,17 +234,15 @@ TCreature::~TCreature(void){ continue; } - if(this->LoseInventory != 2 // LOSE_INVENTORY_ALL ? - && !Item.getObjectType().getFlag(CONTAINER) - && random(0, 9) != 0){ - continue; + if(this->LoseInventory == LOSE_INVENTORY_ALL + || Item.getObjectType().getFlag(CONTAINER) + || random(0, 9) == 0){ + ::Move(0, Item, Corpse, -1, false, NONE); } - - ::Move(0, Item, Corpse, -1, false, NONE); } } - if(this->Type == PLAYER && this->LoseInventory != 2){ // LOSE_INVENTORY_ALL ? + if(this->Type == PLAYER && this->LoseInventory != LOSE_INVENTORY_ALL){ ((TPlayer*)this)->SaveInventory(); } }catch(RESULT r){ @@ -757,7 +754,7 @@ int TCreature::Damage(TCreature *Attacker, int Damage, int DamageType){ ObjectType AmuletOfLossType = GetNewObjectType(77, 12); if(ObjType == AmuletOfLossType){ Log("game", "%s stirbt mit Amulett of Loss.\n", this->Name); - this->LoseInventory = 0; + this->LoseInventory = LOSE_INVENTORY_NONE; try{ Delete(Obj, -1); // TODO(fusion): Shouldn't we break here? We could also diff --git a/src/crplayer.cc b/src/crplayer.cc index 3205e46..67ff996 100644 --- a/src/crplayer.cc +++ b/src/crplayer.cc @@ -19,6 +19,355 @@ static store<TPlayerIndexLeafNode, 100> PlayerIndexLeafNodes; // TPlayer // ============================================================================= +TPlayer::TPlayer(TConnection *Connection, uint32 CharacterID): + TCreature(), + AttackedPlayers(0, 10, 10), + FormerAttackedPlayers(0, 10, 10) +{ + this->Type = PLAYER; + this->LoseInventory = LOSE_INVENTORY_SOME; + this->Profession = PROFESSION_NONE; + this->AccountID = 0; + this->Guild[0] = 0; + this->Rank[0] = 0; + this->Title[0] = 0; + this->IPAddress[0] = 0; + this->Depot = NONE; + this->DepotNr = 0; + this->DepotSpace = 0; + this->ConstructError = NOERROR; + this->PlayerData = NULL; + this->TradeObject = NONE; + this->TradePartner = 0; + this->TradeAccepted = false; + this->OldState = 0; + this->Request = 0; + this->RequestTimestamp = 0; + this->RequestProcessingGamemaster = 0; + this->TutorActivities = 0; + this->NumberOfAttackedPlayers = 0; + this->Aggressor = false; + this->NumberOfFormerAttackedPlayers = 0; + this->FormerAggressor = false; + this->FormerLogoutRound = 0; + this->PartyLeader = 0; + this->PartyLeavingRound = 0; + this->TalkBufferFullTime = 0; + this->MutingEndRound = 0; + this->NumberOfMutings = 0; + + memset(this->Rights, 0, sizeof(this->Rights)); + + for(int SpellNr = 0; + SpellNr < NARRAY(this->SpellList); + SpellNr += 1){ + this->SpellList[SpellNr] = 0; + } + + for(int QuestNr = 0; + QuestNr < NARRAY(this->QuestValues); + QuestNr += 1){ + this->QuestValues[QuestNr] = 0; + } + + for(int ContainerNr = 0; + ContainerNr < NARRAY(this->OpenContainer); + ContainerNr += 1){ + this->OpenContainer[ContainerNr] = NONE; + } + + STATIC_ASSERT(NARRAY(this->Addressees) == NARRAY(this->AddresseesTimes)); + for(int AddresseeNr = 0; + AddresseeNr < NARRAY(this->Addressees); + AddresseeNr += 1){ + this->Addressees[AddresseeNr] = 0; + this->AddresseesTimes[AddresseeNr] = 0; + } + + TPlayerData *Slot = AttachPlayerPoolSlot(CharacterID, false); + if(Slot == NULL){ + error("TPlayer::TPlayer: PlayerData-Slot nicht gefunden.\n"); + this->ConstructError = ERROR; + return; + } + + SendMails(Slot); + + this->PlayerData = Slot; + this->Connection = Connection; + strcpy(this->Name, Slot->Name); + this->SetID(CharacterID); + + InsertPlayerIndex(&PlayerIndexHead, 0, this->Name, CharacterID); + this->LoadData(); + this->AccountID = Slot->AccountID; + strcpy(this->IPAddress, Connection->GetIPAddress()); + + STATIC_ASSERT(sizeof(this->Rights) == sizeof(Slot->Rights)); + memcpy(this->Rights, Slot->Rights, sizeof(this->Rights)); + + this->Sex = Slot->Sex; + strcpy(this->Guild, Slot->Guild); + strcpy(this->Rank, Slot->Rank); + strcpy(this->Title, Slot->Title); + + if(Slot->PlayerkillerEnd < (int)time(NULL)){ + Slot->PlayerkillerEnd = 0; + } + + this->CheckOutfit(); + this->SetInList(); + + // NOTE(fusion): Soul regen. Could be some inlined function `CheckSoul`. + { + TSkill *Soul = this->Skills[SKILL_SOUL]; + Soul->Max = (this->GetActivePromotion() ? 200 : 100); + Soul->Check(); + + // TODO(fusion): We're rounding up to an extra regen cycle here but I'm + // not sure it is correct. + int Timer = Soul->TimerValue(); + if(Timer >= 15){ + int Interval = (this->GetActivePromotion() ? 15 : 120); + int Cycle = (Timer + Interval - 1) / Interval; + int Count = (Timer + Interval - 1) % Interval; + this->SetTimer(SKILL_SOUL, Cycle, Count, Interval, -1); + } + } + + // TODO(fusion): Handle login after death? + if(this->Skills[SKILL_HITPOINTS]->Get() <= 0){ + for(int SkillNr = 0; + SkillNr < NARRAY(this->Skills); + SkillNr += 1){ + this->DelTimer(SkillNr); + this->Skills[SkillNr]->SetMDAct(0); + this->Skills[SkillNr]->DAct = 0; + } + + this->Skills[SKILL_HITPOINTS]->Set(this->Skills[SKILL_HITPOINTS]->Max); + this->Skills[SKILL_MANA ]->Set(this->Skills[SKILL_MANA ]->Max); + this->Outfit = this->OrgOutfit; + this->posx = this->startx; + this->posy = this->starty; + this->posz = this->startz; + } + + if(Slot->LastLoginTime == 0 && CheckRight(CharacterID, GAMEMASTER_OUTFIT)){ + Log("game", "Gamemaster-Charakter %s loggt zum ersten Mal ein -> Level 2 setzen.\n", this->Name); + this->Skills[SKILL_LEVEL]->Act = 2; + this->Skills[SKILL_LEVEL]->Exp = 100; + this->Skills[SKILL_LEVEL]->LastLevel = 100; + this->Skills[SKILL_LEVEL]->NextLevel = 200; + } + + if(CoordinateFlag(this->posx, this->posy, this->posz, BED)){ + this->Regenerate(); + } + + uint16 HouseID = GetHouseID(this->posx, this->posy, this->posz); + if(HouseID != 0 + && !IsInvited(HouseID, this, Slot->LastLogoutTime) + && !CheckRight(CharacterID, ENTER_HOUSES)){ + GetExitPosition(HouseID, &this->posx, &this->posy, &this->posz); + } + + if(!CheckRight(CharacterID, PREMIUM_ACCOUNT)){ + if(IsPremiumArea(this->startx, this->starty, this->startz)){ + Log("game", "Spieler %s wird aus PayArea-Stadt ausgebürgert und erhält neue Heimatstadt.\n", this->Name); + GetStartPosition(&this->startx, &this->starty, &this->startz, (this->Profession == PROFESSION_NONE)); + } + + if(IsPremiumArea(this->posx, this->posy, this->posz)){ + Log("game", "Spieler %s wird aus PayArea geworfen und in seine Heimatstadt gesetzt.\n", this->Name); + this->posx = this->startx; + this->posy = this->starty; + this->posz = this->startz; + } + }else{ + Log("game", "Spieler besitzt Premium Account.\n"); + } + + this->SetOnMap(); + Connection->EnterGame(); + SendInitGame(Connection, CharacterID); + SendRights(Connection); + SendFullScreen(Connection); + GraphicalEffect(this->CrObject, EFFECT_ENERGY); + this->LoadInventory(Slot->LastLoginTime == 0); + this->NotifyChangeInventory(); + SendAmbiente(Connection); + AnnounceChangedCreature(CharacterID, CREATURE_LIGHT_CHANGED); + SendPlayerSkills(Connection); + this->CheckState(); + this->SendBuddies(); + + if(Slot->LastLoginTime != 0){ + char TimeString[100]; + struct tm LastLogin = GetLocalTimeTM(Slot->LastLoginTime); + strftime(TimeString, sizeof(TimeString), "%d. %b %Y %X %Z", &LastLogin); + SendMessage(Connection, TALK_LOGIN_MESSAGE, + "Your last visit in Tibia: %s.", TimeString); + }else if(!CheckRight(this->ID, GAMEMASTER_OUTFIT)){ + Log("game", "Spieler %s loggt zum ersten Mal ein -> Outfitwahl.\n", this->Name); + SendMessage(Connection, TALK_LOGIN_MESSAGE, + "Welcome to Tibia! Please choose your outfit."); + SendOutfit(Connection); + } + + Slot->LastLoginTime = time(NULL); +} + +TPlayer::~TPlayer(void){ + LogoutOrder(this); + if(this->ConstructError != NOERROR){ + this->DelInList(); + return; + } + + ASSERT(this->PlayerData); + TPlayerData *Slot = this->PlayerData; + Slot->LastLogoutTime = time(NULL); + this->SaveData(); + + if(!this->IsDead){ + Log("game", "Spieler %s loggt aus.\n", this->Name); + GraphicalEffect(this->posx, this->posy, this->posz, EFFECT_POFF); + this->SaveInventory(); + }else{ + Log("game", "Spieler %s ist gestorben.\n", this->Name); + + // NOTE(fusion): This is a disaster. We're deleting the slot's inventory + // here so `~TCreature` can handle dropping loot and then re-generate it + // with `SaveInventory` if `LoseInventory` is not `LOSE_INVENTORY_ALL`, + // which makes sense but is poorly executed. + delete[] Slot->Inventory; + Slot->Inventory = NULL; + + bool ResetCharacter = false; + if(this->Profession != PROFESSION_NONE && this->Skills[SKILL_LEVEL]->Get() <= 5){ + Log("game", "Setze Spieler %s komplett zurück wegen Level.\n", this->Name); + ResetCharacter = true; + }else if(this->Skills[SKILL_HITPOINTS]->Max <= 0){ + Log("game", "Setze Spieler %s komplett zurück wegen MaxHitpoints.\n", this->Name); + ResetCharacter = true; + } + + if(ResetCharacter){ + Slot->CurrentOutfit = Slot->OriginalOutfit; + Slot->startx = 0; + Slot->starty = 0; + Slot->startz = 0; + Slot->posx = 0; + Slot->posy = 0; + Slot->posz = 0; + Slot->Profession = PROFESSION_NONE; + + for(int SpellNr = 0; + SpellNr < NARRAY(Slot->SpellList); + SpellNr += 1){ + Slot->SpellList[SpellNr] = 0; + } + + for(int QuestNr = 0; + QuestNr < NARRAY(Slot->QuestValues); + QuestNr += 1){ + Slot->QuestValues[QuestNr] = 0; + } + + // TODO(fusion): This one looks sketchy. + for(int SkillNr = 0; + SkillNr < NARRAY(Slot->Minimum); + SkillNr += 1){ + Slot->Minimum[SkillNr] = INT_MIN; + } + + this->LoseInventory = LOSE_INVENTORY_ALL; + } + + if(Slot->PlayerkillerEnd != 0){ + this->LoseInventory = LOSE_INVENTORY_ALL; + } + + if(CheckRight(this->ID, KEEP_INVENTORY)){ + this->LoseInventory = LOSE_INVENTORY_NONE; + } + } + + if(CheckRight(this->ID, READ_GAMEMASTER_CHANNEL)){ + CloseProcessedRequests(this->ID); + } + + if(this->Request != 0){ + if(this->RequestProcessingGamemaster == 0){ + DeleteGamemasterRequest(this->Name); + }else{ + TCreature *Gamemaster = GetCreature(this->RequestProcessingGamemaster); + if(Gamemaster != NULL){ + if(Gamemaster->Type == PLAYER){ + SendFinishRequest(Gamemaster->Connection, this->Name); + }else{ + error("GetPlayer: Kreatur ist kein Spieler.\n"); + } + } + } + this->Request = 0; + } + + LeaveAllChannels(this->ID); + + if(this->GetPartyLeader(false) != 0){ + ::LeaveParty(this->ID, true); + } + + this->ClearPlayerkillingMarks(); + this->DelInList(); + + Slot->Dirty = true; + // TODO(fusion): Something is telling me that `Slot->Sticky` is also poorly managed. + DecreasePlayerPoolSlotSticky(Slot); + ReleasePlayerPoolSlot(Slot); +} + +void TPlayer::SetInList(void){ + this->SetInCrList(); + + PlayerMutex.down(); + *PlayerList.at(FirstFreePlayer) = this; + FirstFreePlayer += 1; + PlayerMutex.up(); + + NotifyBuddies(this->ID, this->Name, true); + IncrementPlayersOnline(); + if(this->Profession == PROFESSION_NONE){ + IncrementNewbiesOnline(); + } +} + +void TPlayer::DelInList(void){ + NotifyBuddies(this->ID, this->Name, false); + + for(int Index = 0; Index < FirstFreePlayer; Index += 1){ + if(*PlayerList.at(Index) == this){ + // TODO(fusion): This can't be right? If the player at `Index` changes + // before entering the critical section, we could end up removing the + // wrong player from the list.. + PlayerMutex.down(); + FirstFreePlayer -= 1; + *PlayerList.at(Index) = *PlayerList.at(FirstFreePlayer); + *PlayerList.at(FirstFreePlayer) = NULL; + PlayerMutex.up(); + + DecrementPlayersOnline(); + if(this->Profession == PROFESSION_NONE){ + DecrementNewbiesOnline(); + } + + break; + } + } +} + uint8 TPlayer::GetRealProfession(void){ return this->Profession; } @@ -202,8 +551,10 @@ void CloseProcessedRequests(uint32 CharacterID){ continue; } - SendCloseRequest(Player->Connection); - Player->Request = 0; + if(Player->Request != 0 && Player->RequestProcessingGamemaster == CharacterID){ + SendCloseRequest(Player->Connection); + Player->Request = 0; + } } } @@ -930,8 +1281,8 @@ void InitPlayerIndex(void){ // be hardcoded. uint32 CharacterIDs[10000]; char Names[10000][30]; - TQueryManagerConnection *QueryManager = new TQueryManagerConnection(360007); - if(!QueryManager->isConnected()){ + TQueryManagerConnection QueryManager(360007); + if(!QueryManager.isConnected()){ error("InitPlayerIndex: Kann nicht zum Query-Manager verbinden.\n"); return; } @@ -939,7 +1290,7 @@ void InitPlayerIndex(void){ int MinimumCharacterID = 0; while(true){ int NumberOfPlayers; - int Ret = QueryManager->loadPlayers(MinimumCharacterID, + int Ret = QueryManager.loadPlayers(MinimumCharacterID, &NumberOfPlayers, Names, CharacterIDs); if(Ret != 0){ error("InitPlayerIndex: Kann Spielerdaten nicht ermitteln.\n"); @@ -956,8 +1307,6 @@ void InitPlayerIndex(void){ MinimumCharacterID = CharacterIDs[9999] + 1; } - - delete QueryManager; } void ExitPlayerIndex(void){ diff --git a/src/operate.cc b/src/operate.cc index 18829a3..7dc1fef 100644 --- a/src/operate.cc +++ b/src/operate.cc @@ -5,7 +5,6 @@ #include "stubs.hh" #include <dirent.h> -#include <time.h> static fifo<TStatement> Statements(1024); static fifo<TListener> Listeners(1024); diff --git a/src/stubs.hh b/src/stubs.hh index 719f88d..9c251ef 100644 --- a/src/stubs.hh +++ b/src/stubs.hh @@ -23,24 +23,20 @@ extern void CleanHouseField(int x, int y, int z); extern void ConvinceMonster(TCreature *Master, TCreature *Slave); extern void ChallengeMonster(TCreature *Challenger, TCreature *Monster); extern TCreature *CreateMonster(int Race, int x, int y, int z, int Home, uint32 Master, bool ShowEffect); -extern void CreatePlayerList(bool Online); -extern uint32 GetCharacterID(const char *Name); -extern const char *GetCharacterName(const char *Name); +extern void DeleteGamemasterRequest(const char *Name); extern void GetExitPosition(uint16 HouseID, int *x, int *y, int *z); extern TConnection *GetFirstConnection(void); extern TConnection *GetNextConnection(void); extern const char *GetHouseName(uint16 HouseID); extern const char *GetHouseOwner(uint16 HouseID); -extern TPlayer *GetPlayer(uint32 CreatureID); -extern void GetProfessionName(char *Buffer, int Profession, bool Article, bool Capitals); -extern int IdentifyPlayer(const char *Name, bool ExactMatch, bool IgnoreGamemasters, TPlayer **Player); extern void InitLog(const char *ProtocolName); +extern bool IsInvited(uint16 HouseID, TPlayer *Player, int TimeStamp); extern void KickGuest(uint16 HouseID, TPlayer *Host, TPlayer *Guest); extern void KillStatisticsOrder(int NumberOfRaces, const char *RaceNames, int *KilledPlayers, int *KilledCreatures); extern bool LagDetected(void); extern void LoadSectorOrder(int SectorX, int SectorY, int SectorZ); extern void Log(const char *ProtocolName, const char *Text, ...) ATTR_PRINTF(2, 3); -extern void LogoutAllPlayers(void); +extern void LogoutOrder(TPlayer *Player); extern void NetLoadCheck(void); extern void NetLoadSummary(void); extern void PrepareHouseCleanup(void); @@ -80,8 +76,12 @@ extern void SendChangeInContainer(TConnection *Connection, int ContainerNr, Obje extern void SendDeleteInventory(TConnection *Connection, int Position); extern void SendSetInventory(TConnection *Connection, int Position, Object Obj); extern void SendEditList(TConnection *Connection, uint8 ListType, uint32 ID, const char *Text); +extern void SendFinishRequest(TConnection *Connection, const char *Name); extern void SendFullScreen(TConnection *Connection); extern void SendFloors(TConnection *Connection, bool Up); +extern void SendInitGame(TConnection *Connection, uint32 CharacterID); +extern void SendRights(TConnection *Connection); +extern void SendOutfit(TConnection *Connection); extern void SendGraphicalEffect(TConnection *Connection, int x, int y, int z, int Type); extern void SendTextualEffect(TConnection *Connection, int x, int y, int z, int Color, const char *Text); extern void SendMissileEffect(TConnection *Connection, int OrigX, int OrigY, int OrigZ, int DestX, int DestY, int DestZ, int Type); diff --git a/src/time.cc b/src/time.cc index 0003c39..ad42c47 100644 --- a/src/time.cc +++ b/src/time.cc @@ -1,7 +1,5 @@ #include "common.hh" -#include <time.h> - // IMPORTANT(fusion): `RoundNr` is just the number of seconds since startup which // is why `GetRoundAtTime` and `GetRoundForNextMinute` straight up uses it as // seconds. It is incremented every 1 second inside `AdvanceGame`. @@ -12,12 +10,12 @@ uint32 ServerMilliseconds = 0; // NOTE(fusion): This isn't strictly required because each server process is // single threaded and don't share static memory, which is what the result of // the regular `localtime` function uses. -static struct tm GetLocalTimeTM(time_t timer){ +struct tm GetLocalTimeTM(time_t t){ struct tm result; #if COMPILER_MSVC - localtime_s(&result, &timer); + localtime_s(&result, &t); #else - localtime_r(&timer, &result); + localtime_r(&t, &result); #endif return result; } |
