aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-06-17 20:10:41 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-06-17 20:10:41 -0300
commitb912ba995c2175b00393f95388ae2ec1afd0494b (patch)
tree20c9eae485c1a365e83db0bcce45f6c691bd4b54 /src
parent56bdec57609cd00d7827a3008a9c6b06707097ca (diff)
downloadgame-b912ba995c2175b00393f95388ae2ec1afd0494b.tar.gz
game-b912ba995c2175b00393f95388ae2ec1afd0494b.zip
TPlayer constructor and destructor
Diffstat (limited to 'src')
-rw-r--r--src/common.hh2
-rw-r--r--src/connection.hh2
-rw-r--r--src/cr.hh65
-rw-r--r--src/crmain.cc19
-rw-r--r--src/crplayer.cc363
-rw-r--r--src/operate.cc1
-rw-r--r--src/stubs.hh14
-rw-r--r--src/time.cc8
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
// =================
diff --git a/src/cr.hh b/src/cr.hh
index 20371ad..83ab647 100644
--- a/src/cr.hh
+++ b/src/cr.hh
@@ -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;
}