writer.cc

This commit is contained in:
fusion32 2025-06-30 19:23:09 -03:00
parent c09d30cb14
commit 6c8aa85b8b
29 changed files with 1279 additions and 2403 deletions

View File

@ -13,9 +13,9 @@ else
CFLAGS += -O2
endif
HEADERS = $(SRCDIR)/common.hh $(SRCDIR)/communication.hh $(SRCDIR)/config.hh $(SRCDIR)/connections.hh $(SRCDIR)/containers.hh $(SRCDIR)/cr.hh $(SRCDIR)/crypto.hh $(SRCDIR)/enums.hh $(SRCDIR)/houses.hh $(SRCDIR)/info.hh $(SRCDIR)/magic.hh $(SRCDIR)/map.hh $(SRCDIR)/moveuse.hh $(SRCDIR)/objects.hh $(SRCDIR)/operate.hh $(SRCDIR)/query.hh $(SRCDIR)/script.hh $(SRCDIR)/stubs.hh $(SRCDIR)/threads.hh
HEADERS = $(SRCDIR)/common.hh $(SRCDIR)/communication.hh $(SRCDIR)/config.hh $(SRCDIR)/connections.hh $(SRCDIR)/containers.hh $(SRCDIR)/cr.hh $(SRCDIR)/crypto.hh $(SRCDIR)/enums.hh $(SRCDIR)/houses.hh $(SRCDIR)/info.hh $(SRCDIR)/magic.hh $(SRCDIR)/map.hh $(SRCDIR)/moveuse.hh $(SRCDIR)/objects.hh $(SRCDIR)/operate.hh $(SRCDIR)/query.hh $(SRCDIR)/script.hh $(SRCDIR)/stubs.hh $(SRCDIR)/threads.hh $(SRCDIR)/writer.hh
$(BUILDDIR)/$(OUTPUTEXE): $(BUILDDIR)/communication.obj $(BUILDDIR)/config.obj $(BUILDDIR)/connections.obj $(BUILDDIR)/cract.obj $(BUILDDIR)/crcombat.obj $(BUILDDIR)/crmain.obj $(BUILDDIR)/crnonpl.obj $(BUILDDIR)/crplayer.obj $(BUILDDIR)/crskill.obj $(BUILDDIR)/crypto.obj $(BUILDDIR)/houses.obj $(BUILDDIR)/info.obj $(BUILDDIR)/magic.obj $(BUILDDIR)/main.obj $(BUILDDIR)/map.obj $(BUILDDIR)/moveuse.obj $(BUILDDIR)/objects.obj $(BUILDDIR)/operate.obj $(BUILDDIR)/query.obj $(BUILDDIR)/receiving.obj $(BUILDDIR)/script.obj $(BUILDDIR)/sending.obj $(BUILDDIR)/shm.obj $(BUILDDIR)/strings.obj $(BUILDDIR)/threads.obj $(BUILDDIR)/time.obj $(BUILDDIR)/utils.obj
$(BUILDDIR)/$(OUTPUTEXE): $(BUILDDIR)/communication.obj $(BUILDDIR)/config.obj $(BUILDDIR)/connections.obj $(BUILDDIR)/cract.obj $(BUILDDIR)/crcombat.obj $(BUILDDIR)/crmain.obj $(BUILDDIR)/crnonpl.obj $(BUILDDIR)/crplayer.obj $(BUILDDIR)/crskill.obj $(BUILDDIR)/crypto.obj $(BUILDDIR)/houses.obj $(BUILDDIR)/info.obj $(BUILDDIR)/magic.obj $(BUILDDIR)/main.obj $(BUILDDIR)/map.obj $(BUILDDIR)/moveuse.obj $(BUILDDIR)/objects.obj $(BUILDDIR)/operate.obj $(BUILDDIR)/query.obj $(BUILDDIR)/receiving.obj $(BUILDDIR)/script.obj $(BUILDDIR)/sending.obj $(BUILDDIR)/shm.obj $(BUILDDIR)/strings.obj $(BUILDDIR)/threads.obj $(BUILDDIR)/time.obj $(BUILDDIR)/utils.obj $(BUILDDIR)/writer.obj
@echo $(CC) $(CFLAGS) $(LFLAGS) -o $@ $^
$(BUILDDIR)/communication.obj: $(SRCDIR)/communication.cc $(HEADERS)
@ -126,6 +126,10 @@ $(BUILDDIR)/utils.obj: $(SRCDIR)/utils.cc $(HEADERS)
@mkdir -p $(@D)
$(CC) -c $(CFLAGS) -o $@ $<
$(BUILDDIR)/writer.obj: $(SRCDIR)/writer.cc $(HEADERS)
@mkdir -p $(@D)
$(CC) -c $(CFLAGS) -o $@ $<
.PHONY: clean
clean:

View File

@ -1,8 +1,7 @@
## TODO NEXT
- QUERY.CC
- READER.CC
- WRITER.CC
- DBFUNCS.CC
- QUERY.CC
- Include `x == 0xFFFF` inside `CheckVisibility`?
- The map container uses type id zero but it seems to also be used as a "no type"
@ -21,7 +20,7 @@
instead of relying on `NARRAY`.
## Stack allocations
Any functions that use `alloca` or some other form of dynamic stack allocations will cause decompiled functions to be an absolute mess. It usually shows up in the decompiled code as both a size computation like `-(VAR + CONST & 0xfffffff0)`, followed by some assignment. It doesn't make total sense without looking at the disassembly. I've encountered ~30 such computations and expect the functions containing them to be amongt the most challenging/annoying to be properly decompiled.
Any functions that use `alloca` or some other form of dynamic stack allocations will cause it to be an absolute mess. It usually shows up in the decompiled code as both a size computation like `-(VAR + CONST & 0xfffffff0)`, followed by some assignment. It doesn't make total sense without looking at the disassembly. I've encountered ~30 such computations and expect the functions containing them to be amongt the most challenging/annoying to be properly decompiled.
## Exceptions
It's absolute hell.

View File

@ -1,23 +1,3 @@
enum TWriterThreadReplyType: int {
REPLY_BROADCAST=0,
REPLY_DIRECT=1,
REPLY_LOGOUT=2
};
enum TWriterThreadOrderType: int {
ORDER_TERMINATE=0,
ORDER_LOGOUT=1,
ORDER_PLAYERLIST=2,
ORDER_KILLSTATISTICS=3,
ORDER_PUNISHMENT=4,
ORDER_CHARACTERDEATH=5,
ORDER_ADDBUDDY=6,
ORDER_REMOVEBUDDY=7,
ORDER_DECREMENTISONLINE=8,
ORDER_SAVEPLAYERDATA=9
};
enum CHANNEL: int {
GUILD_CHANNEL=0,
GAMEMASTER_CHANNEL=1,

File diff suppressed because it is too large Load Diff

View File

@ -25,53 +25,6 @@ struct TPreparedQuery {
char *Name;
};
struct TDirectReplyData {
ulong CharacterID;
char Message[100];
};
struct TWriterThreadReply {
enum TWriterThreadReplyType ReplyType;
void *Data;
};
struct TWriterThreadOrder {
enum TWriterThreadOrderType OrderType;
void *Data;
};
struct TPunishmentOrderData {
ulong GamemasterID;
char GamemasterName[30];
char CriminalName[30];
char CriminalIPAddress[16];
int Reason;
int Action;
char Comment[200];
int NumberOfStatements;
struct vector<TReportedStatement> *ReportedStatements;
ulong StatementID;
bool IPBanishment;
};
struct TLogoutOrderData {
ulong CharacterID;
int Level;
int Profession;
time_t LastLoginTime;
int TutorActivities;
char Residence[30];
};
struct TCharacterDeathOrderData {
ulong CharacterID;
int Level;
ulong Offender;
char Remark[30];
bool Unjustified;
time_t Time;
};
struct TNameLockOrderData {
ulong GamemasterID;
char GamemasterName[30];
@ -86,30 +39,6 @@ struct TNotationOrderData {
char Comment[200];
};
struct TProtocolThreadOrder {
char ProtocolName[20];
char Text[256];
};
struct TPlayerlistOrderData {
int NumberOfPlayers;
char *PlayerNames;
int *PlayerLevels;
int *PlayerProfessions;
};
struct TBuddyOrderData {
ulong AccountID;
ulong Buddy;
};
struct TKillStatisticsOrderData {
int NumberOfRaces;
char *RaceNames;
int *KilledPlayers;
int *KilledCreatures;
};
struct TReaderThreadOrder {
enum TReaderThreadOrderType OrderType;
int SectorX;

View File

@ -5,8 +5,7 @@
#include "crypto.hh"
#include "query.hh"
#include "threads.hh"
#include "stubs.hh"
#include "writer.hh"
#include <arpa/inet.h>
#include <fcntl.h>

View File

@ -3,7 +3,8 @@
#include "common.hh"
#include "connections.hh"
#include "cr.hh"
struct TPlayerData;
struct TWaitinglistEntry {
TWaitinglistEntry *Next;

View File

@ -2,8 +2,7 @@
#include "cr.hh"
#include "info.hh"
#include "threads.hh"
#include "stubs.hh"
#include "writer.hh"
#include <arpa/inet.h>
#include <netinet/in.h>

View File

@ -1,5 +1,6 @@
#include "cr.hh"
#include "config.hh"
#include "houses.hh"
#include "info.hh"
#include "operate.hh"

View File

@ -4,8 +4,7 @@
#include "enums.hh"
#include "info.hh"
#include "operate.hh"
#include "stubs.hh"
#include "writer.hh"
#include <dirent.h>

View File

@ -2,9 +2,9 @@
#include "config.hh"
#include "containers.hh"
#include "info.hh"
#include "magic.hh"
#include "operate.hh"
#include "stubs.hh"
#include "writer.hh"
#include <dirent.h>

View File

@ -1,10 +1,12 @@
#include "cr.hh"
#include "config.hh"
#include "houses.hh"
#include "info.hh"
#include "moveuse.hh"
#include "operate.hh"
#include "query.hh"
#include "threads.hh"
#include "writer.hh"
#include "stubs.hh"

View File

@ -4,8 +4,7 @@
#include "info.hh"
#include "moveuse.hh"
#include "query.hh"
#include "stubs.hh"
#include "writer.hh"
static vector<THelpDepot> HelpDepot(0, 9, 10);
static int HelpDepots;
@ -1904,6 +1903,6 @@ void InitHouses(void){
delete QueryManagerConnection;
}
void SaveHouses(void){
void ExitHouses(void){
SaveOwners();
}

View File

@ -3,11 +3,13 @@
#include "common.hh"
#include "containers.hh"
#include "cr.hh"
#include "map.hh"
#define MAX_HOUSE_GUEST_NAME 60
struct TPlayer;
struct TPlayerData;
struct THelpDepot {
uint32 CharacterID;
Object Box;
@ -99,6 +101,6 @@ void LoadOwners(void);
void SaveOwners(void);
void ProcessHouses(void);
void InitHouses(void);
void SaveHouses(void);
void ExitHouses(void);
#endif //TIBIA_HOUSES_HH_

View File

@ -1,7 +1,6 @@
#include "info.hh"
#include "cr.hh"
#include "stubs.hh"
#include "magic.hh"
const char *GetLiquidName(int LiquidType){
const char *LiquidName;

View File

@ -1,9 +1,9 @@
#include "magic.hh"
#include "config.hh"
#include "houses.hh"
#include "info.hh"
#include "operate.hh"
#include "stubs.hh"
#include "writer.hh"
#include <fstream>
#include <sstream>

View File

@ -3,6 +3,7 @@
#include "common.hh"
#include "cr.hh"
#include "map.hh"
enum : int {
FIELD_TYPE_FIRE = 1,

View File

@ -1,6 +1,7 @@
#include "common.hh"
#include "communication.hh"
#include "config.hh"
#include "houses.hh"
#include "info.hh"
#include "map.hh"
#include "magic.hh"
@ -8,6 +9,7 @@
#include "objects.hh"
#include "operate.hh"
#include "query.hh"
#include "writer.hh"
#include "stubs.hh"
@ -217,13 +219,13 @@ static void InitAll(void){
LoadWorldConfig();
InitSHM(!BeADaemon);
LockGame();
//InitLog("game");
InitLog("game");
srand(time(NULL));
InitSignalHandler();
InitConnections();
InitCommunication();
InitStrings();
//InitWriter();
InitWriter();
//InitReader();
InitObjects();
InitMap();
@ -231,7 +233,7 @@ static void InitAll(void){
InitMoveUse();
InitMagic();
InitCr();
//InitHouses();
InitHouses();
InitTime();
ApplyPatches();
}catch(const char *str){
@ -249,11 +251,11 @@ static void ExitAll(void){
ExitMagic();
ExitMoveUse();
ExitInfo();
//ExitHouses();
ExitHouses();
ExitMap(SaveMapOn);
ExitObjects();
//ExitReader();
//ExitWriter();
ExitWriter();
ExitStrings();
ExitCommunication();
ExitConnections();

View File

@ -2,6 +2,7 @@
#include "containers.hh"
#include "config.hh"
#include "enums.hh"
#include "houses.hh"
#include "script.hh"
#include "stubs.hh"

View File

@ -1,7 +1,10 @@
#include "moveuse.hh"
#include "config.hh"
#include "houses.hh"
#include "info.hh"
#include "magic.hh"
#include "operate.hh"
#include "writer.hh"
#include "stubs.hh"

View File

@ -1,6 +1,8 @@
#include "operate.hh"
#include "config.hh"
#include "houses.hh"
#include "info.hh"
#include "magic.hh"
#include "moveuse.hh"
#include "stubs.hh"

View File

@ -97,12 +97,12 @@ struct TListener {
};
struct TReportedStatement {
uint32 StatementID;
uint32 StatementID;
int TimeStamp;
uint32 CharacterID;
int Mode;
int Channel;
char Text[256];
uint32 CharacterID;
int Mode;
int Channel;
char Text[256];
};
void AnnounceMovingCreature(uint32 CreatureID, Object Con);

View File

@ -18,7 +18,34 @@ struct TQueryManagerConnection{
bool GamemasterRequired, uint32 *CharacterID, int *Sex, char *Guild,
char *Rank, char *Title, int *NumberOfBuddies, uint32 *BuddyIDs,
char (*BuddyNames)[30], uint8 *Rights, bool *PremiumAccountActivated);
void decrementIsOnline(uint32 CharacterID);
int logoutGame(uint32 CharacterID, int Level, const char *Profession,
const char *Residence, time_t LastLoginTime, int TutorActivities);
int createPlayerlist(int NumberOfPlayers, const char **Names, int *Levels,
const char (*Professions)[30], bool *NewRecord);
int decrementIsOnline(uint32 CharacterID);
int clearIsOnline(int *NumberOfAffectedPlayers);
int addBuddy(uint32 AccountID, uint32 BuddyID);
int removeBuddy(uint32 AccountID, uint32 BuddyID);
int logKilledCreatures(int NumberOfRaces, const char **Names,
int *KilledPlayers,int *KilledCreatures);
int logCharacterDeath(uint32 CharacterID, int Level, uint32 OffenderID,
const char *Remark, bool Unjustified, time_t Time);
int setNotation(uint32 GamemasterID, const char *PlayerName, const char *IPAddress,
const char *Reason, const char *Comment, uint32 *BanishmentID);
int setNamelock(uint32 GamemasterID, const char *PlayerName, const char *IPAddress,
const char *Reason, const char *Comment);
int banishAccount(uint32 GamemasterID, const char *PlayerName, const char *IPAddress,
const char *Reason, const char *Comment, bool *FinalWarning, int *Days,
uint32 *BanishmentID);
int reportStatement(uint32 ReporterID, const char *PlayerName, const char *Reason,
const char *Comment, uint32 BanishmentID, uint32 StatementID, int NumberOfStatements,
uint32 *StatementIDs, int *TimeStamps, uint32 *CharacterIDs, char (*Channels)[30],
char (*Texts)[256]);
int banishIPAddress(uint32 GamemasterID, const char *PlayerName, const char *IPAddress,
const char *Reason, const char *Comment);
int insertHouses(int NumberOfHouses, uint16 *HouseIDs, char **Names,
int *Rents, char **Descriptions, int *Sizes, int *PositionsX,

View File

@ -1,7 +1,7 @@
#include "connections.hh"
#include "houses.hh"
#include "info.hh"
#include "stubs.hh"
#include "writer.hh"
#include <signal.h>

View File

@ -2,9 +2,9 @@
#include "config.hh"
#include "cr.hh"
#include "info.hh"
#include "magic.hh"
#include "map.hh"
#include "stubs.hh"
#include "writer.hh"
#include <signal.h>

View File

@ -2,8 +2,7 @@
#include "config.hh"
#include "enums.hh"
#include "threads.hh"
#include "stubs.hh"
#include "writer.hh"
#include <sys/shm.h>

View File

@ -3,11 +3,8 @@
#include "common.hh"
#include "enums.hh"
#include "connections.hh"
#include "cr.hh"
#include "magic.hh"
#include "map.hh"
#include "operate.hh"
// IMPORTANT(fusion): These function definitions exist to test compilation. They're
// not yet implemented and will cause the linker to fail with unresolved symbols.
@ -15,45 +12,12 @@
typedef void TRefreshSectorFunction(int SectorX, int SectorY, int SectorZ, const uint8 *Data, int Size);
typedef void TSendMailsFunction(TPlayerData *PlayerData);
extern void AbortWriter(void);
extern void AddBuddyOrder(TCreature *Creature, uint32 CharacterID);
extern void RemoveBuddyOrder(TCreature *Creature, uint32 BuddyID);
extern void ChangeGuests(uint16 HouseID, TPlayer *Player, const char *Text);
extern void ChangeSubowners(uint16 HouseID, TPlayer *Player, const char *Text);
extern void ChangeNameDoor(Object Door, TPlayer *Player, const char *Text);
extern void CharacterDeathOrder(TCreature *Creature, int OldLevel,
uint32 Offender, const char *Remark, bool Unjustified);
extern void CleanHouseField(int x, int y, int z);
extern void DecrementIsOnlineOrder(uint32 CharacterID);
extern void GetExitPosition(uint16 HouseID, int *x, int *y, int *z);
extern int GetOrderBufferSpace(void);
extern const char *GetHouseName(uint16 HouseID);
extern const char *GetHouseOwner(uint16 HouseID);
extern void InitLog(const char *ProtocolName);
extern bool IsInvited(uint16 HouseID, TPlayer *Player, int TimeStamp);
extern bool IsOwner(uint16 HouseID, TPlayer *Player);
extern void KickGuest(uint16 HouseID, TPlayer *Host, TPlayer *Guest);
extern void KillStatisticsOrder(int NumberOfRaces, const char *RaceNames, int *KilledPlayers, int *KilledCreatures);
extern void LoadCharacterOrder(uint32 CharacterID);
extern void LoadSectorOrder(int SectorX, int SectorY, int SectorZ);
extern void Log(const char *ProtocolName, const char *Text, ...) ATTR_PRINTF(2, 3);
extern void LogoutOrder(TPlayer *Player);
extern bool MayOpenDoor(Object Door, TPlayer *Player);
extern void PrepareHouseCleanup(void);
extern void FinishHouseCleanup(void);
extern void PlayerlistOrder(int NumberOfPlayers, char *PlayerNames, int *PlayerLevels, int *PlayerProfessions);
extern void ProcessReaderThreadReplies(TRefreshSectorFunction *RefreshSector, TSendMailsFunction *SendMails);
extern void ProcessWriterThreadReplies(void);
extern void PunishmentOrder(TCreature *Creature, const char *Name, const char *IPAddress,
int Reason, int Action, const char *Comment, int NumberOfStatements,
vector<TReportedStatement> *ReportedStatements, uint32 StatementID,
bool IPBanishment);
extern void SavePlayerData(TPlayerData *Slot);
extern bool LoadPlayerData(TPlayerData *Slot);
extern bool PlayerDataExists(uint32 CharacterID);
extern void SavePlayerDataOrder(void);
extern void ShowGuestList(uint16 HouseID, TPlayer *Player, char *Buffer);
extern void ShowSubownerList(uint16 HouseID, TPlayer *Player, char *Buffer);
extern void ShowNameDoor(Object Door, TPlayer *Player, char *Buffer);
#endif //TIBIA_STUBS_HH_

1045
src/writer.cc Normal file

File diff suppressed because it is too large Load Diff

155
src/writer.hh Normal file
View File

@ -0,0 +1,155 @@
#ifndef TIBIA_WRITER_HH_
#define TIBIA_WRITER_HH_ 1
#include "common.hh"
#include "containers.hh"
#include "operate.hh"
enum TWriterThreadReplyType: int {
REPLY_BROADCAST = 0,
REPLY_DIRECT = 1,
REPLY_LOGOUT = 2,
};
enum TWriterThreadOrderType: int {
ORDER_TERMINATE = 0,
ORDER_LOGOUT = 1,
ORDER_PLAYERLIST = 2,
ORDER_KILLSTATISTICS = 3,
ORDER_PUNISHMENT = 4,
ORDER_CHARACTERDEATH = 5,
ORDER_ADDBUDDY = 6,
ORDER_REMOVEBUDDY = 7,
ORDER_DECREMENTISONLINE = 8,
ORDER_SAVEPLAYERDATA = 9,
};
struct TProtocolThreadOrder{
char ProtocolName[20];
char Text[256];
};
struct TWriterThreadReply{
TWriterThreadReplyType ReplyType;
const void *Data;
};
struct TBroadcastReplyData{
char Message[100];
};
struct TDirectReplyData{
uint32 CharacterID;
char Message[100];
};
struct TWriterThreadOrder{
TWriterThreadOrderType OrderType;
const void *Data;
};
struct TLogoutOrderData{
uint32 CharacterID;
int Level;
int Profession;
time_t LastLoginTime;
int TutorActivities;
char Residence[30];
};
struct TPlayerlistOrderData{
int NumberOfPlayers;
const char *PlayerNames;
int *PlayerLevels;
int *PlayerProfessions;
};
struct TKillStatisticsOrderData{
int NumberOfRaces;
const char *RaceNames;
int *KilledPlayers;
int *KilledCreatures;
};
struct TPunishmentOrderData{
uint32 GamemasterID;
char GamemasterName[30];
char CriminalName[30];
char CriminalIPAddress[16];
int Reason;
int Action;
char Comment[200];
int NumberOfStatements;
vector<TReportedStatement> *ReportedStatements;
uint32 StatementID;
bool IPBanishment;
};
struct TCharacterDeathOrderData{
uint32 CharacterID;
int Level;
uint32 Offender;
char Remark[30];
bool Unjustified;
time_t Time;
};
struct TBuddyOrderData{
uint32 AccountID;
uint32 Buddy;
};
void InitProtocol(void);
void InsertProtocolOrder(const char *ProtocolName, const char *Text);
void GetProtocolOrder(TProtocolThreadOrder *Order);
void WriteProtocol(const char *ProtocolName, const char *Text);
int ProtocolThreadLoop(void *Unused);
void InitLog(const char *ProtocolName);
void Log(const char *ProtocolName, const char *Text, ...) ATTR_PRINTF(2, 3);
void InitWriterBuffers(void);
int GetOrderBufferSpace(void);
void InsertOrder(TWriterThreadOrderType OrderType, const void *Data);
void GetOrder(TWriterThreadOrder *Order);
void TerminateWriterOrder(void);
void LogoutOrder(TPlayer *Player);
void PlayerlistOrder(int NumberOfPlayers, const char *PlayerNames,
int *PlayerLevels, int *PlayerProfessions);
void KillStatisticsOrder(int NumberOfRaces, const char *RaceNames,
int *KilledPlayers, int *KilledCreatures);
void PunishmentOrder(TCreature *Gamemaster, const char *Name, const char *IPAddress,
int Reason, int Action, const char *Comment, int NumberOfStatements,
vector<TReportedStatement> *ReportedStatements, uint32 StatementID,
bool IPBanishment);
void CharacterDeathOrder(TCreature *Creature, int OldLevel,
uint32 OffenderID, const char *Remark, bool Unjustified);
void AddBuddyOrder(TCreature *Creature, uint32 BuddyID);
void RemoveBuddyOrder(TCreature *Creature, uint32 BuddyID);
void DecrementIsOnlineOrder(uint32 CharacterID);
void SavePlayerDataOrder(void);
void ProcessLogoutOrder(TLogoutOrderData *Data);
void ProcessPlayerlistOrder(TPlayerlistOrderData *Data);
void ProcessKillStatisticsOrder(TKillStatisticsOrderData *Data);
void ProcessPunishmentOrder(TPunishmentOrderData *Data);
void ProcessCharacterDeathOrder(TCharacterDeathOrderData *Data);
void ProcessAddBuddyOrder(TBuddyOrderData *Data);
void ProcessRemoveBuddyOrder(TBuddyOrderData *Data);
void ProcessDecrementIsOnlineOrder(uint32 CharacterID);
int WriterThreadLoop(void *Unused);
void InsertReply(TWriterThreadReplyType ReplyType, const void *Data);
void BroadcastReply(const char *Text, ...) ATTR_PRINTF(1, 2);
void DirectReply(uint32 CharacterID, const char *Text, ...) ATTR_PRINTF(2, 3);
void LogoutReply(const char *PlayerName);
bool GetReply(TWriterThreadReply *Reply);
void ProcessBroadcastReply(TBroadcastReplyData *Data);
void ProcessDirectReply(TDirectReplyData *Data);
void ProcessLogoutReply(const char *Name);
void ProcessWriterThreadReplies(void);
void ClearPlayers(void);
void InitWriter(void);
void AbortWriter(void);
void ExitWriter(void);
#endif //TIBIA_WRITER_HH_