From 6c8aa85b8b578db03a8c5f0dc0b7e80605592d45 Mon Sep 17 00:00:00 2001 From: fusion32 Date: Mon, 30 Jun 2025 19:23:09 -0300 Subject: `writer.cc` --- Makefile | 8 +- TODO.md | 5 +- reference/enums.hh | 20 - reference/game.c | 2236 -------------------------------------------------- reference/types.hh | 71 -- src/communication.cc | 3 +- src/communication.hh | 3 +- src/connections.cc | 3 +- src/cract.cc | 1 + src/crmain.cc | 3 +- src/crnonpl.cc | 4 +- src/crplayer.cc | 2 + src/houses.cc | 5 +- src/houses.hh | 6 +- src/info.cc | 3 +- src/magic.cc | 4 +- src/magic.hh | 1 + src/main.cc | 12 +- src/map.cc | 1 + src/moveuse.cc | 3 + src/operate.cc | 2 + src/operate.hh | 10 +- src/query.hh | 29 +- src/receiving.cc | 4 +- src/sending.cc | 4 +- src/shm.cc | 3 +- src/stubs.hh | 36 - src/writer.cc | 1045 +++++++++++++++++++++++ src/writer.hh | 155 ++++ 29 files changed, 1279 insertions(+), 2403 deletions(-) create mode 100644 src/writer.cc create mode 100644 src/writer.hh diff --git a/Makefile b/Makefile index dca6a3c..3f8e5b1 100644 --- a/Makefile +++ b/Makefile @@ -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: diff --git a/TODO.md b/TODO.md index bc73f14..baf6a18 100644 --- a/TODO.md +++ b/TODO.md @@ -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. diff --git a/reference/enums.hh b/reference/enums.hh index d54a03f..2f95bfb 100644 --- a/reference/enums.hh +++ b/reference/enums.hh @@ -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, diff --git a/reference/game.c b/reference/game.c index 92c0837..c24661d 100644 --- a/reference/game.c +++ b/reference/game.c @@ -3475,2242 +3475,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority return; } - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void InitProtocol(void) - -{ - ProtocolPointerWrite = 0; - ProtocolPointerRead = 0; - return; -} - - - -// WARNING: Variable defined which should be unmapped: Text_local - -void InsertProtocolOrder(char *ProtocolName,char *Text) - -{ - int iVar1; - char *pcVar2; - char *pcVar3; - bool bVar4; - char *Text_local; - - if (ProtocolName == (char *)0x0) { - ProtocolName = "InsertProtocolOrder: Protokoll-Name nicht angegeben.\n"; - } - else { - if (Text != (char *)0x0) { - bVar4 = ProtocolPointerWrite - ProtocolPointerRead == 999; - if (999 < ProtocolPointerWrite - ProtocolPointerRead) { - iVar1 = 6; - pcVar2 = ProtocolName; - pcVar3 = "error"; - do { - if (iVar1 == 0) break; - iVar1 = iVar1 + -1; - bVar4 = *pcVar2 == *pcVar3; - pcVar2 = pcVar2 + 1; - pcVar3 = pcVar3 + 1; - } while (bVar4); - if (!bVar4) { - error(&DAT_080f5260); - } - } - Semaphore::down(&ProtocolMutex); - Semaphore::down(&ProtocolBufferEmpty); - strcpy(ProtocolBuffer[ProtocolPointerWrite % 1000].ProtocolName,ProtocolName); - strcpy(ProtocolBuffer[ProtocolPointerWrite % 1000].Text,Text); - ProtocolPointerWrite = ProtocolPointerWrite + 1; - Semaphore::up(&ProtocolBufferFull); - Semaphore::up(&ProtocolMutex); - return; - } - ProtocolName = "InsertProtocolOrder: Text nicht angegeben.\n"; - } - error(ProtocolName); - return; -} - - - -void GetProtocolOrder(char *ProtocolName,char *Text) - -{ - Semaphore::down(&ProtocolBufferFull); - strcpy(ProtocolName,ProtocolBuffer[ProtocolPointerRead % 1000].ProtocolName); - strcpy(Text,ProtocolBuffer[ProtocolPointerRead % 1000].Text); - ProtocolPointerRead = ProtocolPointerRead + 1; - Semaphore::up(&ProtocolBufferEmpty); - return; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void WriteProtocol(void) - -{ - FILE *__stream; - int iVar1; - int *piVar2; - FILE *f; - undefined4 in_stack_00000008; - char local_100c [4]; - char FileName [4096]; - - sprintf(local_100c,"%s/%s.log",LOGPATH); - __stream = fopen(local_100c,"at"); - if (__stream != (FILE *)0x0) { - fprintf(__stream,"%s",in_stack_00000008); - iVar1 = fclose(__stream); - if (iVar1 != 0) { - piVar2 = __errno_location(); - error(&DAT_080f5320,*piVar2); - } - } - return; -} - - - -int ProtocolThreadLoop(void *param_1) - -{ - FILE *__stream; - int iVar1; - int *piVar2; - int iVar3; - FILE *f; - undefined8 local_1144; - char local_113c [4]; - char FileName [4096]; - char Text [256]; - char ProtocolName [20]; - - while( true ) { - Semaphore::down(&ProtocolBufferFull); - iVar1 = ProtocolPointerRead; - iVar3 = ProtocolPointerRead >> 0x1f; - strcpy(Text + 0xfc, - ProtocolBuffer[ProtocolPointerRead + ((local_1144._4_4_ >> 6) - iVar3) * -1000]. - ProtocolName); - local_1144 = (longlong)ProtocolPointerRead * 0x10624dd3; - strcpy(FileName + 0xffc, - ProtocolBuffer - [ProtocolPointerRead + - ((iVar1 / 1000 + iVar3) - (ProtocolPointerRead >> 0x1f)) * -1000].Text); - ProtocolPointerRead = ProtocolPointerRead + 1; - Semaphore::up(&ProtocolBufferEmpty); - if (Text[0xfc] == '\0') break; - sprintf(local_113c,"%s/%s.log",LOGPATH,Text + 0xfc); - __stream = fopen(local_113c,"at"); - if (__stream != (FILE *)0x0) { - fprintf(__stream,"%s",FileName + 0xffc); - iVar1 = fclose(__stream); - if (iVar1 != 0) { - piVar2 = __errno_location(); - error(&DAT_080f5320,*piVar2); - } - } - } - return 0; -} - - - -void InitLog(char *ProtocolName) - -{ - FILE *__stream; - char *pcVar1; - FILE *f; - time_t local_1020; - time_t Time; - char FileName [4096]; - - if (ProtocolName == (char *)0x0) { - error("InitLog: Protokoll-Name nicht angegeben.\n"); - } - else { - sprintf((char *)&Time,"%s/%s.log",LOGPATH,ProtocolName); - __stream = fopen((char *)&Time,"at"); - if (__stream == (FILE *)0x0) { - error("InitLog: Kann Protokoll %s nicht anlegen.\n",ProtocolName); - } - else { - time(&local_1020); - fprintf(__stream, - "-------------------------------------------------------------------------------\n" - ); - fprintf(__stream,"Tibia - Graphical Multi-User-Dungeon\n"); - pcVar1 = ctime(&local_1020); - fprintf(__stream,"%s.log - gestartet %s",ProtocolName,pcVar1); - fclose(__stream); - } - } - return; -} - - - -void Log(char *ProtocolName,char *Text,...) - -{ - uint *__dest; - tm *ptVar1; - FILE *__stream; - int *piVar2; - int iVar3; - uint *puVar4; - uint *puVar5; - uint uVar6; - uint uVar7; - bool WriteDate; - char *pcVar8; - char *pcVar9; - bool bVar10; - bool bVar11; - time_t local_1220; - time_t Time; - char FileName [4096]; - char Line [256]; - char Output [256]; - - if ((ProtocolName == (char *)0x0) || (*ProtocolName == '\0')) { - error("Log: Protokoll-Name nicht angegeben.\n"); - } - else { - iVar3 = 10; - bVar11 = false; - bVar10 = true; - pcVar8 = ProtocolName; - pcVar9 = "bugreport"; - do { - if (iVar3 == 0) break; - iVar3 = iVar3 + -1; - bVar10 = *pcVar8 == *pcVar9; - pcVar8 = pcVar8 + 1; - pcVar9 = pcVar9 + 1; - } while (bVar10); - if (!bVar10) { - iVar3 = 0xd; - pcVar8 = ProtocolName; - pcVar9 = "client-error"; - do { - if (iVar3 == 0) break; - iVar3 = iVar3 + -1; - bVar10 = *pcVar8 == *pcVar9; - pcVar8 = pcVar8 + 1; - pcVar9 = pcVar9 + 1; - } while (bVar10); - if (!bVar10) { - iVar3 = 5; - pcVar8 = ProtocolName; - pcVar9 = "load"; - do { - if (iVar3 == 0) break; - iVar3 = iVar3 + -1; - bVar10 = *pcVar8 == *pcVar9; - pcVar8 = pcVar8 + 1; - pcVar9 = pcVar9 + 1; - } while (bVar10); - if (!bVar10) { - bVar11 = true; - } - } - } - pcVar8 = Line + 0xfc; - vsnprintf(pcVar8,0x100,Text,&stack0x0000000c); - if (bVar11) { - print(); - time(&local_1220); - ptVar1 = localtime(&local_1220); - snprintf(FileName + 0xffc,0x100,"%02d.%02d.%04d %02d:%02d:%02d (%ld): %s", - ptVar1->tm_mday,ptVar1->tm_mon + 1,ptVar1->tm_year + 0x76c,ptVar1->tm_hour, - ptVar1->tm_min,ptVar1->tm_sec,RoundNr,pcVar8); - } - else { - strcpy(FileName + 0xffc,pcVar8); - } - __dest = (uint *)(FileName + 0xffc); - Line[0xfa] = '\0'; - puVar5 = __dest; - if (FileName[0xffc] != '\0') { - do { - puVar4 = puVar5; - uVar6 = *puVar4 + 0xfefefeff & ~*puVar4; - uVar7 = uVar6 & 0x80808080; - puVar5 = puVar4 + 1; - } while (uVar7 == 0); - bVar11 = (uVar6 & 0x8080) == 0; - if (bVar11) { - uVar7 = uVar7 >> 0x10; - } - if (bVar11) { - puVar5 = (uint *)((int)puVar4 + 6); - } - if (*(char *)((int)puVar5 + - (int)(FileName + - (-(int)__dest - (uint)CARRY1((byte)uVar7,(byte)uVar7)) + 0xff8)) != - '\n') { - strcat((char *)__dest,"\n"); - } - } - if (ProtocolThread == 0) { - sprintf((char *)&Time,"%s/%s.log",LOGPATH,ProtocolName); - __stream = fopen((char *)&Time,"at"); - if (__stream != (FILE *)0x0) { - fprintf(__stream,"%s",__dest); - iVar3 = fclose(__stream); - if (iVar3 != 0) { - piVar2 = __errno_location(); - error(&DAT_080f5320,*piVar2); - } - } - } - else { - InsertProtocolOrder(ProtocolName,(char *)__dest); - } - } - return; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void InitWriterBuffers(void) - -{ - OrderPointerWrite = 0; - ReplyPointerWrite = 0; - OrderPointerRead = 0; - ReplyPointerRead = 0; - return; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -int GetOrderBufferSpace(void) - -{ - int iVar1; - - if (WriterThread == 0) { - iVar1 = 0x7fffffff; - } - else { - iVar1 = 2000 - (OrderPointerWrite - OrderPointerRead); - } - return iVar1; -} - - - -void InsertOrder(TWriterThreadOrderType OrderType,void *Data) - -{ - if (WriterThread != 0) { - if (1999 < OrderPointerWrite - OrderPointerRead) { - error(&DAT_080f5500); - } - Semaphore::down(&OrderBufferEmpty); - OrderBuffer[OrderPointerWrite % 2000].OrderType = OrderType; - OrderBuffer[OrderPointerWrite % 2000].Data = Data; - OrderPointerWrite = OrderPointerWrite + 1; - Semaphore::up(&OrderBufferFull); - return; - } - return; -} - - - -void GetOrder(TWriterThreadOrderType *OrderType,void **Data) - -{ - int iVar1; - - Semaphore::down(&OrderBufferFull); - iVar1 = OrderPointerRead % 2000; - *OrderType = OrderBuffer[iVar1].OrderType; - OrderPointerRead = OrderPointerRead + 1; - *Data = OrderBuffer[iVar1].Data; - Semaphore::up(&OrderBufferEmpty); - return; -} - - - -void InsertReply(TWriterThreadReplyType ReplyType,void *Data) - -{ - if (ReplyPointerWrite - ReplyPointerRead < 100) { - ReplyBuffer[ReplyPointerWrite % 100].ReplyType = ReplyType; - ReplyBuffer[ReplyPointerWrite % 100].Data = Data; - ReplyPointerWrite = ReplyPointerWrite + 1; - return; - } - error(&DAT_080f5540); - return; -} - - - -void DirectReply(ulong CharacterID,char *Text,...) - -{ - ulong *puVar1; - TDirectReplyData *Data; - char *Text_00; - - if (CharacterID != 0) { - if (Text == (char *)0x0) { - Text_00 = "SendDirectReply: Kein Text angegeben.\n"; - } - else { - puVar1 = (ulong *)operator_new(0x68); - *puVar1 = CharacterID; - vsnprintf((char *)(puVar1 + 1),100,Text,&stack0x0000000c); - if (ReplyPointerWrite - ReplyPointerRead < 100) { - ReplyBuffer[ReplyPointerWrite % 100].Data = puVar1; - ReplyBuffer[ReplyPointerWrite % 100].ReplyType = REPLY_DIRECT; - ReplyPointerWrite = ReplyPointerWrite + 1; - return; - } - Text_00 = &DAT_080f5540; - } - error(Text_00); - } - return; -} - - - -void LogoutReply(char *PlayerName) - -{ - int Length; - size_t sVar1; - char *__dest; - char *Buffer; - - sVar1 = strlen(PlayerName); - __dest = (char *)operator_new__(sVar1 + 1); - strcpy(__dest,PlayerName); - if (ReplyPointerWrite - ReplyPointerRead < 100) { - ReplyBuffer[ReplyPointerWrite % 100].ReplyType = REPLY_LOGOUT; - ReplyBuffer[ReplyPointerWrite % 100].Data = __dest; - ReplyPointerWrite = ReplyPointerWrite + 1; - return; - } - error(&DAT_080f5540); - return; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -bool GetReply(void) - -{ - bool bVar1; - TWriterThreadReplyType *in_stack_00000004; - undefined4 *in_stack_00000008; - - bVar1 = ReplyPointerRead != ReplyPointerWrite; - if (bVar1) { - *in_stack_00000004 = ReplyBuffer[ReplyPointerRead % 100].ReplyType; - *in_stack_00000008 = ReplyBuffer[ReplyPointerRead % 100].Data; - ReplyPointerRead = ReplyPointerRead + 1; - } - return bVar1; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void TerminateWriterOrder(void) - -{ - if (WriterThread != 0) { - if (1999 < OrderPointerWrite - OrderPointerRead) { - error(&DAT_080f5500); - } - Semaphore::down(&OrderBufferEmpty); - OrderBuffer[OrderPointerWrite % 2000].OrderType = ORDER_TERMINATE; - OrderBuffer[OrderPointerWrite % 2000].Data = (void *)0x0; - OrderPointerWrite = OrderPointerWrite + 1; - Semaphore::up(&OrderBufferFull); - } - return; -} - - - -void LogoutOrder(TPlayer *Player) - -{ - int iVar1; - byte bVar2; - ulong *puVar3; - ulong uVar4; - TLogoutOrderData *Data; - - if (Player == (TPlayer *)0x0) { - error(&DAT_080f5680); - return; - } - puVar3 = (ulong *)operator_new(0x34); - *puVar3 = (Player->super_TCreature).ID; - uVar4 = TSkill::Get((Player->super_TCreature).super_TSkillBase.Skills[0]); - puVar3[1] = uVar4; - bVar2 = TPlayer::GetActiveProfession(Player); - puVar3[2] = (uint)bVar2; - if (Player->PlayerData == (TPlayerData *)0x0) { - error("LogoutOrder: PlayerData ist NULL.\n"); - puVar3[3] = 0; - } - else { - puVar3[3] = Player->PlayerData->LastLoginTime; - } - puVar3[4] = Player->TutorActivities; - iVar1 = (Player->super_TCreature).startx; - if (iVar1 == 0x7f89) { - puVar3[5] = 0x6f7a614b; - puVar3[6] = 0x6f6f6472; -LAB_080699b2: - *(undefined2 *)(puVar3 + 7) = 0x6e; - } - else { - if (iVar1 < 0x7f8a) { - if (iVar1 == 0x7e68) { - puVar3[5] = 0x6c726143; - *(undefined2 *)(puVar3 + 6) = 0x6e69; -LAB_0806990d: - *(undefined1 *)((int)puVar3 + 0x1a) = 0; - goto LAB_08069820; - } - if (iVar1 < 0x7e69) { - if (iVar1 == 0x7d61) { - puVar3[5] = 0x6b6f6f52; - puVar3[6] = 0x72616167; - *(undefined2 *)(puVar3 + 7) = 100; - goto LAB_08069820; - } - } - else { - if (iVar1 == 0x7e71) { - puVar3[5] = 0x69616854; - *(undefined2 *)(puVar3 + 6) = 0x73; - goto LAB_08069820; - } - if (iVar1 == 0x7f53) { - puVar3[5] = 0x74726f50; - puVar3[6] = 0x706f4820; - *(undefined2 *)(puVar3 + 7) = 0x65; - goto LAB_08069820; - } - } - } - else { - if (iVar1 == 0x81aa) { - puVar3[5] = 0x726b6e41; - puVar3[6] = 0x756d6861; - goto LAB_080699b2; - } - if (iVar1 < 0x81ab) { - if (iVar1 == 0x7fdc) { - puVar3[5] = 0x44276241; - puVar3[6] = 0x72646e65; - puVar3[7] = 0x6c6569; - goto LAB_08069820; - } - if (iVar1 == 0x80bd) { - puVar3[5] = 0x6f6e6556; - *(undefined2 *)(puVar3 + 6) = 0x6572; - goto LAB_0806990d; - } - } - else { - if (iVar1 == 0x81bd) { - puVar3[5] = 0x61726144; - puVar3[6] = 0x61696873; - *(undefined1 *)(puVar3 + 7) = 0; - goto LAB_08069820; - } - if (iVar1 == 0x81c1) { - puVar3[5] = 0x6f726445; - *(undefined2 *)(puVar3 + 6) = 0x6e; - goto LAB_08069820; - } - } - } - error("LogoutOrder: Unbekannte Startkoordinate [%d,%d,%d] bei Spieler %s.\n",iVar1, - (Player->super_TCreature).starty,(Player->super_TCreature).startz, - (Player->super_TCreature).Name); - puVar3[5] = 0x6e6b6e55; - puVar3[6] = 0x6e776f; - } -LAB_08069820: - if (WriterThread != 0) { - if (1999 < OrderPointerWrite - OrderPointerRead) { - error(&DAT_080f5500); - } - Semaphore::down(&OrderBufferEmpty); - OrderBuffer[OrderPointerWrite % 2000].OrderType = ORDER_LOGOUT; - OrderBuffer[OrderPointerWrite % 2000].Data = puVar3; - OrderPointerWrite = OrderPointerWrite + 1; - Semaphore::up(&OrderBufferFull); - return; - } - return; -} - - - -// WARNING: Variable defined which should be unmapped: NumberOfPlayers_local - -void PlayerlistOrder(int NumberOfPlayers,char *PlayerNames,int *PlayerLevels,int *PlayerProfessions) - -{ - int *piVar1; - TPlayerlistOrderData *Data; - int *PlayerProfessions_local; - int NumberOfPlayers_local; - - if (PlayerNames == (char *)0x0) { - NumberOfPlayers = (int)s_PlayerlistOrder__PlayerNames_ist_080f5740; - } - else if (PlayerLevels == (int *)0x0) { - NumberOfPlayers = (int)s_PlayerlistOrder__PlayerLevels_is_080f5700; - } - else { - if (PlayerProfessions != (int *)0x0) { - piVar1 = (int *)operator_new(0x10); - piVar1[1] = (int)PlayerNames; - piVar1[2] = (int)PlayerLevels; - *piVar1 = NumberOfPlayers; - piVar1[3] = (int)PlayerProfessions; - if (WriterThread != 0) { - if (1999 < OrderPointerWrite - OrderPointerRead) { - error(&DAT_080f5500); - } - Semaphore::down(&OrderBufferEmpty); - OrderBuffer[OrderPointerWrite % 2000].OrderType = ORDER_PLAYERLIST; - OrderBuffer[OrderPointerWrite % 2000].Data = piVar1; - OrderPointerWrite = OrderPointerWrite + 1; - Semaphore::up(&OrderBufferFull); - return; - } - return; - } - NumberOfPlayers = (int)s_PlayerlistOrder__PlayerProfessio_080f56c0; - } - error((char *)NumberOfPlayers); - return; -} - - - -// WARNING: Variable defined which should be unmapped: NumberOfRaces_local - -void KillStatisticsOrder(int NumberOfRaces,char *RaceNames,int *KilledPlayers,int *KilledCreatures) - -{ - int *piVar1; - TKillStatisticsOrderData *Data; - int *KilledCreatures_local; - int NumberOfRaces_local; - - if (RaceNames == (char *)0x0) { - NumberOfRaces = (int)s_KillStatisticsOrder__RaceNames_i_080f5800; - } - else if (KilledPlayers == (int *)0x0) { - NumberOfRaces = (int)s_KillStatisticsOrder__KilledPlaye_080f57c0; - } - else { - if (KilledCreatures != (int *)0x0) { - piVar1 = (int *)operator_new(0x10); - piVar1[1] = (int)RaceNames; - piVar1[2] = (int)KilledPlayers; - *piVar1 = NumberOfRaces; - piVar1[3] = (int)KilledCreatures; - if (WriterThread != 0) { - if (1999 < OrderPointerWrite - OrderPointerRead) { - error(&DAT_080f5500); - } - Semaphore::down(&OrderBufferEmpty); - OrderBuffer[OrderPointerWrite % 2000].OrderType = ORDER_KILLSTATISTICS; - OrderBuffer[OrderPointerWrite % 2000].Data = piVar1; - OrderPointerWrite = OrderPointerWrite + 1; - Semaphore::up(&OrderBufferFull); - return; - } - return; - } - NumberOfRaces = (int)s_KillStatisticsOrder__KilledCreat_080f5780; - } - error((char *)NumberOfRaces); - return; -} - - - -// WARNING: Variable defined which should be unmapped: IPAddress_local - -void PunishmentOrder(TCreature *cr,char *Name,char *IPAddress,int Reason,int Action,char *Comment, - int NumberOfStatements,vector<> *ReportedStatements,ulong StatementID, - bool IPBanishment) - -{ - ulong *puVar1; - ulong uVar2; - char *__src; - TPunishmentOrderData *Data; - bool IPBanishment_local; - ulong StatementID_local; - vector<> *ReportedStatements_local; - int NumberOfStatements_local; - char *Comment_local; - int Action_local; - int Reason_local; - char *IPAddress_local; - - if (Name == (char *)0x0) { - cr = (TCreature *)s_PunishmentOrder__Name_ist_NULL__080f5880; - } - else { - if (Comment != (char *)0x0) { - puVar1 = (ulong *)operator_new(0x130); - uVar2 = 0; - if (cr != (TCreature *)0x0) { - uVar2 = cr->ID; - } - *puVar1 = uVar2; - __src = "automatic"; - if (cr != (TCreature *)0x0) { - __src = cr->Name; - } - strcpy((char *)(puVar1 + 1),__src); - strcpy((char *)((int)puVar1 + 0x22),Name); - if (IPAddress == (char *)0x0) { - *(undefined1 *)(puVar1 + 0x10) = 0; - } - else { - strcpy((char *)(puVar1 + 0x10),IPAddress); - } - puVar1[0x14] = Reason; - puVar1[0x15] = Action; - strcpy((char *)(puVar1 + 0x16),Comment); - puVar1[0x48] = NumberOfStatements; - puVar1[0x49] = (ulong)ReportedStatements; - puVar1[0x4a] = StatementID; - *(bool *)(puVar1 + 0x4b) = IPBanishment; - if (WriterThread != 0) { - if (1999 < OrderPointerWrite - OrderPointerRead) { - error(&DAT_080f5500); - } - Semaphore::down(&OrderBufferEmpty); - OrderBuffer[OrderPointerWrite % 2000].OrderType = ORDER_PUNISHMENT; - OrderBuffer[OrderPointerWrite % 2000].Data = puVar1; - OrderPointerWrite = OrderPointerWrite + 1; - Semaphore::up(&OrderBufferFull); - return; - } - return; - } - cr = (TCreature *)s_PunishmentOrder__Comment_ist_NUL_080f5840; - } - error((char *)cr); - return; -} - - - -// WARNING: Variable defined which should be unmapped: OldLevel_local - -void CharacterDeathOrder(TCreature *cr,int OldLevel,ulong Offender,char *Remark,bool Unjustified) - -{ - ulong *puVar1; - ulong uVar2; - TCharacterDeathOrderData *Data; - ulong Offender_local; - int OldLevel_local; - - if (cr == (TCreature *)0x0) { - cr = (TCreature *)s_CharacterDeathOrder__cr_ist_NULL_080f5900; - } - else { - if (Remark != (char *)0x0) { - puVar1 = (ulong *)operator_new(0x30); - *puVar1 = cr->ID; - puVar1[1] = OldLevel; - puVar1[2] = Offender; - strcpy((char *)(puVar1 + 3),Remark); - *(bool *)((int)puVar1 + 0x2a) = Unjustified; - uVar2 = time((time_t *)0x0); - puVar1[0xb] = uVar2; - if (WriterThread != 0) { - if (1999 < OrderPointerWrite - OrderPointerRead) { - error(&DAT_080f5500); - } - Semaphore::down(&OrderBufferEmpty); - OrderBuffer[OrderPointerWrite % 2000].OrderType = ORDER_CHARACTERDEATH; - OrderBuffer[OrderPointerWrite % 2000].Data = puVar1; - OrderPointerWrite = OrderPointerWrite + 1; - Semaphore::up(&OrderBufferFull); - return; - } - return; - } - cr = (TCreature *)s_CharacterDeathOrder__Remark_ist_N_080f58c0; - } - error((char *)cr); - return; -} - - - -void AddBuddyOrder(TCreature *cr,ulong Buddy) - -{ - _func_int_varargs **pp_Var1; - undefined4 *puVar2; - TBuddyOrderData *Data; - - if (cr == (TCreature *)0x0) { - cr = (TCreature *)s_AddBuddyOrder__cr_ist_NULL__080f51a0; - } - else { - if (cr->Type == PLAYER) { - puVar2 = (undefined4 *)operator_new(8); - pp_Var1 = cr[1]._vptr_TCreature; - puVar2[1] = Buddy; - *puVar2 = pp_Var1; - if (WriterThread != 0) { - if (1999 < OrderPointerWrite - OrderPointerRead) { - error(&DAT_080f5500); - } - Semaphore::down(&OrderBufferEmpty); - OrderBuffer[OrderPointerWrite % 2000].OrderType = ORDER_ADDBUDDY; - OrderBuffer[OrderPointerWrite % 2000].Data = puVar2; - OrderPointerWrite = OrderPointerWrite + 1; - Semaphore::up(&OrderBufferFull); - return; - } - return; - } - cr = (TCreature *)s_AddBuddyOrder__Kreatur_ist_kein_S_080f5940; - } - error((char *)cr); - return; -} - - - -void RemoveBuddyOrder(TCreature *cr,ulong Buddy) - -{ - _func_int_varargs **pp_Var1; - undefined4 *puVar2; - TBuddyOrderData *Data; - - if (cr == (TCreature *)0x0) { - cr = (TCreature *)s_RemoveBuddyOrder__cr_ist_NULL__080f59c0; - } - else { - if (cr->Type == PLAYER) { - puVar2 = (undefined4 *)operator_new(8); - pp_Var1 = cr[1]._vptr_TCreature; - puVar2[1] = Buddy; - *puVar2 = pp_Var1; - if (WriterThread != 0) { - if (1999 < OrderPointerWrite - OrderPointerRead) { - error(&DAT_080f5500); - } - Semaphore::down(&OrderBufferEmpty); - OrderBuffer[OrderPointerWrite % 2000].OrderType = ORDER_REMOVEBUDDY; - OrderBuffer[OrderPointerWrite % 2000].Data = puVar2; - OrderPointerWrite = OrderPointerWrite + 1; - Semaphore::up(&OrderBufferFull); - return; - } - return; - } - cr = (TCreature *)s_RemoveBuddyOrder__Kreatur_ist_ke_080f5980; - } - error((char *)cr); - return; -} - - - -void DecrementIsOnlineOrder(ulong CharacterID) - -{ - if (WriterThread != 0) { - if (1999 < OrderPointerWrite - OrderPointerRead) { - error(&DAT_080f5500); - } - Semaphore::down(&OrderBufferEmpty); - OrderBuffer[OrderPointerWrite % 2000].OrderType = ORDER_DECREMENTISONLINE; - OrderBuffer[OrderPointerWrite % 2000].Data = (void *)CharacterID; - OrderPointerWrite = OrderPointerWrite + 1; - Semaphore::up(&OrderBufferFull); - return; - } - return; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void SavePlayerDataOrder(void) - -{ - if (WriterThread != 0) { - if (1999 < OrderPointerWrite - OrderPointerRead) { - error(&DAT_080f5500); - } - Semaphore::down(&OrderBufferEmpty); - OrderBuffer[OrderPointerWrite % 2000].OrderType = ORDER_SAVEPLAYERDATA; - OrderBuffer[OrderPointerWrite % 2000].Data = (void *)0x0; - OrderPointerWrite = OrderPointerWrite + 1; - Semaphore::up(&OrderBufferFull); - } - return; -} - - - -// WARNING: Variable defined which should be unmapped: HelpProfession - -void ProcessLogoutOrder(void *RawData) - -{ - int iVar1; - undefined4 uVar2; - char *Buffer; - int iVar3; - undefined4 uVar4; - undefined4 uVar5; - char local_2c [4]; - char HelpProfession [30]; - - if (RawData == (void *)0x0) { - error(&DAT_080f5a60); - } - else { - Buffer = local_2c; - GetProfessionName(Buffer,*(int *)((int)RawData + 8),false,true); - if (0 < *(int *)((int)RawData + 0x10)) { - print(); - } - uVar5 = *(undefined4 *)((int)RawData + 0x10); - iVar3 = (int)RawData + 0x14; - uVar4 = *(undefined4 *)((int)RawData + 0xc); - uVar2 = *(undefined4 *)((int)RawData + 4); - iVar1 = TQueryManagerConnection::logoutGame(QueryManagerConnection); - if (iVar1 != 0) { - // WARNING: Load size is inaccurate - error(&DAT_080f5a20,*RawData,uVar2,Buffer,iVar3,uVar4,uVar5); - } - operator_delete(RawData); - } - return; -} - - - -// WARNING: Variable defined which should be unmapped: NewRecord - -void ProcessPlayerlistOrder(void *RawData) - -{ - bool *pbVar1; - int iVar2; - int iVar3; - int iVar4; - void *pvVar5; - uint uVar6; - int i; - int iVar7; - uint *puVar8; - int iVar9; - undefined4 uStack_40; - char *Text; - int local_24; - char_0__30_ *Professions; - int_0_ *Levels; - char___0_ *Names; - bool local_11 [4]; - bool NewRecord; - - if (RawData == (void *)0x0) { - Text = &DAT_080f5b60; -LAB_0806a54b: - uStack_40 = 0x806a550; - error(Text); - } - else { - // WARNING: Load size is inaccurate - iVar9 = *RawData; - if (iVar9 < 1) { - // WARNING: Load size is inaccurate - uStack_40 = 0x806a53c; - iVar9 = TQueryManagerConnection::createPlayerlist - (QueryManagerConnection,*RawData,(char **)0x0,(int *)0x0, - (char (*) [30])0x0,local_11); - puVar8 = (uint *)&stack0xffffffc4; - if (iVar9 != 0) { - Text = "ProcessPlayerlistOrder: Anfrage fehlgeschlagen (1).\n"; - goto LAB_0806a54b; - } - } - else { - Names = &stack0xffffffc4; - uVar6 = (iVar9 + -1) * 4 + 0x13U & 0xfffffff0; - iVar3 = uVar6 * -2; - Levels = (int_0_ *)((int)&local_24 - uVar6); - Professions = (char_0__30_ *)((int)&local_24 + iVar3); - iVar7 = 0; - iVar2 = -((iVar9 + -1) * 0x1e + 0x2dU & 0xfffffff0); - local_24 = (int)&local_24 + iVar2 + iVar3; - if (0 < iVar9) { - iVar9 = 0; - do { - *(int *)(Levels + iVar7 * 4) = *(int *)((int)RawData + 4) + iVar9; - *(undefined4 *)(Professions + iVar7 * 4) = - *(undefined4 *)(*(int *)((int)RawData + 8) + iVar7 * 4); - pbVar1 = local_11 + iVar2 + iVar3 + -0x1f; - pbVar1[0] = true; - pbVar1[1] = false; - pbVar1[2] = false; - pbVar1[3] = false; - *(undefined4 *)(&stack0xffffffcc + iVar2 + iVar3) = 0; - iVar4 = iVar7 * 4; - iVar7 = iVar7 + 1; - *(undefined4 *)(&stack0xffffffc8 + iVar2 + iVar3) = - *(undefined4 *)(*(int *)((int)RawData + 0xc) + iVar4); - iVar4 = local_24 + iVar9; - iVar9 = iVar9 + 0x1e; - *(int *)(&stack0xffffffc4 + iVar2 + iVar3) = iVar4; - *(undefined4 *)((int)&uStack_40 + iVar2 + iVar3) = 0x806a3e2; - GetProfessionName(*(char **)(&stack0xffffffc4 + iVar2 + iVar3), - *(int *)(&stack0xffffffc8 + iVar2 + iVar3), - (bool)(&stack0xffffffcc)[iVar2 + iVar3], - local_11[iVar2 + iVar3 + -0x1f]); - // WARNING: Load size is inaccurate - } while (iVar7 < *RawData); - } - *(bool **)(&stack0xffffffd8 + iVar2 + iVar3) = local_11; - *(int *)(&stack0xffffffd4 + iVar2 + iVar3) = local_24; - *(char_0__30_ **)(local_11 + iVar2 + iVar3 + -0x1f) = Professions; - *(int_0_ **)(&stack0xffffffcc + iVar2 + iVar3) = Levels; - // WARNING: Load size is inaccurate - *(undefined4 *)(&stack0xffffffc8 + iVar2 + iVar3) = *RawData; - *(TQueryManagerConnection **)(&stack0xffffffc4 + iVar2 + iVar3) = QueryManagerConnection - ; - *(undefined4 *)((int)&uStack_40 + iVar2 + iVar3) = 0x806a415; - iVar9 = TQueryManagerConnection::createPlayerlist - (*(TQueryManagerConnection **)(&stack0xffffffc4 + iVar2 + iVar3), - *(int *)(&stack0xffffffc8 + iVar2 + iVar3), - *(char ***)(&stack0xffffffcc + iVar2 + iVar3), - *(int **)(local_11 + iVar2 + iVar3 + -0x1f), - *(char (**) [30])(&stack0xffffffd4 + iVar2 + iVar3), - *(bool **)(&stack0xffffffd8 + iVar2 + iVar3)); - puVar8 = (uint *)Names; - if (iVar9 != 0) { - *(char **)(&stack0xffffffc4 + iVar2 + iVar3) = - "ProcessPlayerlistOrder: Anfrage fehlgeschlagen (2).\n"; - *(undefined4 *)((int)&uStack_40 + iVar2 + iVar3) = 0x806a502; - error(*(char **)(&stack0xffffffc4 + iVar2 + iVar3)); - return; - } - } - if (local_11[0] != false) { - *puVar8 = 100; - puVar8[-1] = 0x806a475; - pvVar5 = operator_new__(*puVar8); - // WARNING: Load size is inaccurate - uVar6 = *RawData; - puVar8[1] = 100; - puVar8[2] = (uint)"New record: %d players are logged in."; - *puVar8 = (uint)pvVar5; - puVar8[3] = uVar6; - puVar8[-1] = 0x806a495; - snprintf((char *)*puVar8,puVar8[1],(char *)puVar8[2]); - if (ReplyPointerWrite - ReplyPointerRead < 100) { - iVar9 = ReplyPointerWrite % 100; - ReplyBuffer[iVar9].Data = pvVar5; - ReplyPointerWrite = ReplyPointerWrite + 1; - ReplyBuffer[iVar9].ReplyType = REPLY_BROADCAST; - } - else { - *puVar8 = (uint)&DAT_080f5540; - puVar8[-1] = 0x806a4f1; - error((char *)*puVar8); - } - } - if (*(int *)((int)RawData + 4) != 0) { - *puVar8 = *(int *)((int)RawData + 4); - puVar8[-1] = 0x806a467; - operator_delete__((void *)*puVar8); - } - if (*(int *)((int)RawData + 8) != 0) { - *puVar8 = *(int *)((int)RawData + 8); - puVar8[-1] = 0x806a45d; - operator_delete__((void *)*puVar8); - } - if (*(int *)((int)RawData + 0xc) != 0) { - *puVar8 = *(int *)((int)RawData + 0xc); - puVar8[-1] = 0x806a453; - operator_delete__((void *)*puVar8); - } - *puVar8 = (uint)RawData; - puVar8[-1] = 0x806a443; - operator_delete((void *)*puVar8); - } - return; -} - - - -void ProcessKillStatisticsOrder(void *RawData) - -{ - int iVar1; - int iVar2; - int iVar3; - int i; - int iVar4; - int iVar5; - uint uVar6; - int_0_ *KilledPlayers; - int iStack_40; - int aiStack_28 [4]; - int_0_ *KilledCreatures; - char___0_ *RaceNames; - - RaceNames = &stack0xffffffc4; - if (RawData == (void *)0x0) { - iStack_40 = 0x806a661; - error(&DAT_080f5be0); - } - else { - // WARNING: Load size is inaccurate - iVar4 = 0; - uVar6 = *RawData * 4 + 0xfU & 0xfffffff0; - iVar1 = uVar6 * -3; - iVar3 = (int)aiStack_28 + uVar6 * -2; - KilledCreatures = (int_0_ *)((int)aiStack_28 - uVar6); - aiStack_28[3] = (int)aiStack_28 + iVar1; - if (0 < *RawData) { - iVar5 = 0; - do { - iVar2 = *(int *)((int)RawData + 4) + iVar5; - iVar5 = iVar5 + 0x1e; - *(int *)(KilledCreatures + iVar4 * 4) = iVar2; - *(undefined4 *)(iVar3 + iVar4 * 4) = - *(undefined4 *)(*(int *)((int)RawData + 8) + iVar4 * 4); - *(undefined4 *)(aiStack_28[3] + iVar4 * 4) = - *(undefined4 *)(*(int *)((int)RawData + 0xc) + iVar4 * 4); - iVar4 = iVar4 + 1; - // WARNING: Load size is inaccurate - } while (iVar4 < *RawData); - } - iVar4 = aiStack_28[3]; - *(int *)(&stack0xffffffd0 + iVar1) = iVar3; - *(int *)(&stack0xffffffd4 + iVar1) = iVar4; - *(int_0_ **)(&stack0xffffffcc + iVar1) = KilledCreatures; - // WARNING: Load size is inaccurate - *(undefined4 *)(&stack0xffffffc8 + iVar1) = *RawData; - *(TQueryManagerConnection **)(&stack0xffffffc4 + iVar1) = QueryManagerConnection; - *(undefined4 *)((int)&iStack_40 + iVar1) = 0x806a5fd; - iVar3 = TQueryManagerConnection::logKilledCreatures - (*(TQueryManagerConnection **)(&stack0xffffffc4 + iVar1), - *(int *)(&stack0xffffffc8 + iVar1),*(char ***)(&stack0xffffffcc + iVar1), - *(int **)(&stack0xffffffd0 + iVar1),*(int **)(&stack0xffffffd4 + iVar1)); - if (iVar3 == 0) { - if (*(int *)((int)RawData + 4) != 0) { - *(int *)(&stack0xffffffc4 + iVar1) = *(int *)((int)RawData + 4); - *(undefined4 *)((int)&iStack_40 + iVar1) = 0x806a645; - operator_delete__(*(void **)(&stack0xffffffc4 + iVar1)); - } - if (*(int *)((int)RawData + 8) != 0) { - *(int *)(&stack0xffffffc4 + iVar1) = *(int *)((int)RawData + 8); - *(undefined4 *)((int)&iStack_40 + iVar1) = 0x806a63b; - operator_delete__(*(void **)(&stack0xffffffc4 + iVar1)); - } - if (*(int *)((int)RawData + 0xc) != 0) { - *(int *)(&stack0xffffffc4 + iVar1) = *(int *)((int)RawData + 0xc); - *(undefined4 *)((int)&iStack_40 + iVar1) = 0x806a631; - operator_delete__(*(void **)(&stack0xffffffc4 + iVar1)); - } - *(void **)(&stack0xffffffc4 + iVar1) = RawData; - *(undefined4 *)((int)&iStack_40 + iVar1) = 0x806a61e; - operator_delete(*(void **)(&stack0xffffffc4 + iVar1)); - } - else { - *(char **)(&stack0xffffffc4 + iVar1) = - "ProcessKillStatisticsOrder: Anfrage fehlgeschlagen.\n"; - *(undefined4 *)((int)&iStack_40 + iVar1) = 0x806a653; - error(*(char **)(&stack0xffffffc4 + iVar1)); - } - } - return; -} - - - -void ProcessPunishmentOrder(void *RawData) - -{ - ulong uVar1; - int iVar2; - int iVar3; - int Length; - char *pcVar4; - int iVar5; - size_t sVar6; - void *pvVar7; - TReportedStatement *pTVar8; - char *pcVar9; - uint uVar10; - int iVar11; - int i; - int iVar12; - int iVar13; - ulong *puVar14; - char_0__30_ *Channels; - char *pcStack_80; - char *local_74; - char *local_70; - char *local_6c; - char *local_68; - int *local_64 [5]; - int aiStack_50 [2]; - undefined4 uStack_48; - undefined8 local_44; - int local_3c; - undefined4 local_38; - char_0__256_ *Texts; - ulong_0_ *CharacterIDs; - ulong_0_ *TimeStamps; - ulong_0_ *StatementIDs; - int local_24; - char local_1e; - char local_1d; - bool ok; - char *pcStack_1c; - bool FinalWarning; - int Days; - ulong BanishmentID; - - if (RawData == (void *)0x0) { - pcStack_80 = (char *)0x806b148; - error(&DAT_080f60e0); - return; - } - local_1e = '\x01'; - Days = 0; - if (*(int *)((int)RawData + 0x54) == 0) { - pcVar4 = (char *)((int)RawData + 0x22); - pcStack_80 = (char *)0x806b091; - local_6c = GetBanishmentReason(*(int *)((int)RawData + 0x50)); - local_70 = (char *)((int)RawData + 0x40); - local_64[0] = &Days; - pcStack_80 = (char *)0x806b0be; - local_74 = pcVar4; - local_68 = (char *)((int)RawData + 0x58); - iVar5 = TQueryManagerConnection::setNotation(QueryManagerConnection); - if (iVar5 == 1) { - pcVar4 = "A player with this name does not exist. Perhaps he/she has been renamed?"; -LAB_0806b0d9: - // WARNING: Load size is inaccurate - pcStack_80 = (char *)0x806b0e3; - DirectReply(*RawData,pcVar4); - local_1e = '\0'; - } - else if (iVar5 < 2) { - if (iVar5 == 0) { - // WARNING: Load size is inaccurate - pcStack_80 = (char *)0x806b10a; - local_74 = pcVar4; - DirectReply(*RawData,"Notation for player %s inserted."); - local_74 = (char *)((int)RawData + 4); - pcStack_80 = (char *)0x806b12d; - local_70 = pcVar4; - local_6c = (char *)((int)RawData + 0x58); - Log("banish","%s notiert zu %s: %s.\n"); - } - } - else if (iVar5 == 2) { - pcVar4 = "You may not report a god or gamemaster."; - goto LAB_0806b0d9; - } - } - puVar14 = (ulong *)&stack0xffffff84; - if (local_1e == '\0') goto LAB_0806a710; - iVar5 = *(int *)((int)RawData + 0x54); - if (((iVar5 != 1) && (iVar5 != 3)) && (iVar5 != 5)) goto switchD_0806b000_default; - pcVar4 = (char *)((int)RawData + 0x22); - pcStack_80 = (char *)0x806afd1; - local_6c = GetBanishmentReason(*(int *)((int)RawData + 0x50)); - local_68 = (char *)((int)RawData + 0x58); - pcStack_80 = (char *)0x806aff7; - local_74 = pcVar4; - local_70 = (char *)((int)RawData + 0x40); - iVar5 = TQueryManagerConnection::setNamelock(QueryManagerConnection); - switch(iVar5) { - case 0: - // WARNING: Load size is inaccurate - pcStack_80 = (char *)0x806b01d; - local_74 = pcVar4; - DirectReply(*RawData,"Player %s reported for renaming."); - local_74 = (char *)((int)RawData + 4); - pcStack_80 = (char *)0x806b03c; - local_70 = pcVar4; - Log("banish",&DAT_080f5f80); - break; - case 1: - pcVar4 = "A player with this name does not exist. Perhaps he/she has already been renamed?"; - goto LAB_0806b049; - case 2: - case 4: - pcVar4 = "This name has already been approved."; -LAB_0806b049: - // WARNING: Load size is inaccurate - pcStack_80 = (char *)0x806b053; - DirectReply(*RawData,pcVar4); - local_1e = '\0'; - break; - case 3: - // WARNING: Load size is inaccurate - pcStack_80 = (char *)0x806b06e; - DirectReply(*RawData,"This player has already been reported."); - } -switchD_0806b000_default: - puVar14 = (ulong *)&stack0xffffff84; - if (local_1e == '\0') goto LAB_0806a710; - if (*(int *)((int)RawData + 0x54) - 2U < 4) { - local_1d = *(int *)((int)RawData + 0x54) - 4U < 2; - pcStack_80 = (char *)0x806ad8c; - local_6c = GetBanishmentReason(*(int *)((int)RawData + 0x50)); - local_64[2] = &Days; - local_70 = (char *)((int)RawData + 0x40); - local_68 = (char *)((int)RawData + 0x58); - pcVar4 = (char *)((int)RawData + 0x22); - pcStack_80 = (char *)0x806adc9; - local_74 = pcVar4; - local_64[0] = (int *)&local_1d; - local_64[1] = (int *)&stack0xffffffe4; - iVar5 = TQueryManagerConnection::banishAccount(QueryManagerConnection); - if (iVar5 == 1) { - pcVar4 = "A player with this name does not exist. Perhaps he/she has been renamed?"; -LAB_0806ae8b: - // WARNING: Load size is inaccurate - pcStack_80 = (char *)0x806ae95; - DirectReply(*RawData,pcVar4); - local_1e = '\0'; - } - else if (iVar5 < 2) { - if (iVar5 == 0) { - if (pcStack_1c == (char *)0xffffffff) { - // WARNING: Load size is inaccurate - pcStack_80 = (char *)0x806afa9; - local_74 = pcVar4; - DirectReply(*RawData,"Account of player %s banished infinitely."); - } - else { - if (local_1d == '\0') { - pcVar9 = "Account of player %s banished for %d days."; - } - else { - pcVar9 = "Account of player %s banished for %d days with final warning."; - } - local_70 = pcStack_1c; - // WARNING: Load size is inaccurate - pcStack_80 = (char *)0x806aed6; - local_74 = pcVar4; - DirectReply(*RawData,pcVar9); - } - pcStack_80 = (char *)0x806aede; - sVar6 = strlen(pcVar4); - pcStack_80 = (char *)0x806aee7; - pcVar9 = (char *)operator_new__(sVar6 + 1); - pcStack_80 = (char *)0x806aef5; - strcpy(pcVar9,pcVar4); - if (ReplyPointerWrite - ReplyPointerRead < 100) { - local_44 = (longlong)ReplyPointerWrite * 0x51eb851f; - local_3c = ReplyPointerWrite / 100; - ReplyBuffer[ReplyPointerWrite % 100].ReplyType = REPLY_LOGOUT; - ReplyBuffer[ReplyPointerWrite % 100].Data = pcVar9; - ReplyPointerWrite = ReplyPointerWrite + 1; - } - else { - pcStack_80 = (char *)0x806af7c; - error(&DAT_080f5540); - } - local_74 = (char *)((int)RawData + 4); - pcStack_80 = (char *)0x806af6b; - local_70 = pcVar4; - Log("banish","%s verbannt Account von Spieler %s.\n"); - } - } - else { - if (iVar5 == 2) { - pcVar4 = "You may not report a god or gamemaster."; - goto LAB_0806ae8b; - } - if (iVar5 == 3) { - // WARNING: Load size is inaccurate - pcStack_80 = (char *)0x806ae03; - local_74 = pcVar4; - DirectReply(*RawData,"Player %s has already been banished."); - pcStack_80 = (char *)0x806ae0b; - sVar6 = strlen(pcVar4); - pcStack_80 = (char *)0x806ae14; - pcVar9 = (char *)operator_new__(sVar6 + 1); - pcStack_80 = (char *)0x806ae22; - strcpy(pcVar9,pcVar4); - if (ReplyPointerWrite - ReplyPointerRead < 100) { - iVar5 = ReplyPointerWrite % 100; - ReplyPointerWrite = ReplyPointerWrite + 1; - ReplyBuffer[iVar5].ReplyType = REPLY_LOGOUT; - ReplyBuffer[iVar5].Data = pcVar9; - } - else { - pcStack_80 = (char *)0x806ae7e; - error(&DAT_080f5540); - } - } - } - } - puVar14 = (ulong *)&stack0xffffff84; - if (local_1e == '\0') goto LAB_0806a710; - puVar14 = (ulong *)&stack0xffffff84; - if (*(int *)((int)RawData + 0x128) == 0) goto LAB_0806a800; - StatementIDs = &stack0xffffff84; - local_24 = *(int *)((int)RawData + 0x120); - if ((local_24 == 0) || (*(int *)((int)RawData + 0x124) == 0)) { - pcStack_80 = (char *)0x806a70d; - error("ProcessPunishmentOrder: Statements existieren nicht.\n"); - puVar14 = (ulong *)&stack0xffffff84; - goto LAB_0806a710; - } - iVar12 = local_24 + -1; - uVar10 = iVar12 * 4 + 0x13U & 0xfffffff0; - iVar3 = uVar10 * -3; - TimeStamps = (ulong_0_ *)((int)&uStack_48 - uVar10); - CharacterIDs = (ulong_0_ *)((int)&uStack_48 + uVar10 * -2); - Texts = (char_0__256_ *)((int)&uStack_48 + iVar3); - iVar2 = -(iVar12 * 0x1e + 0x2dU & 0xfffffff0); - iVar5 = (int)&uStack_48 + iVar2 + iVar3; - iVar12 = -(iVar12 * 0x100 + 0x100); - local_38 = (int)&uStack_48 + iVar12 + iVar2 + iVar3; - iVar13 = 0; - if (0 < local_24) { - do { - *(int *)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14) = iVar13; - *(undefined4 *)(&stack0xffffff84 + iVar12 + iVar2 + iVar3) = - *(undefined4 *)((int)RawData + 0x124); - *(undefined4 *)((int)&pcStack_80 + iVar12 + iVar2 + iVar3) = 0x806a9e2; - pTVar8 = vector<>::operator() - (*(vector<> **)(&stack0xffffff84 + iVar12 + iVar2 + iVar3), - *(int *)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14)); - *(ulong *)(TimeStamps + iVar13 * 4) = pTVar8->StatementID; - *(int *)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14) = iVar13; - *(undefined4 *)(&stack0xffffff84 + iVar12 + iVar2 + iVar3) = - *(undefined4 *)((int)RawData + 0x124); - *(undefined4 *)((int)&pcStack_80 + iVar12 + iVar2 + iVar3) = 0x806a9fc; - pTVar8 = vector<>::operator() - (*(vector<> **)(&stack0xffffff84 + iVar12 + iVar2 + iVar3), - *(int *)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14)); - *(ulong *)(CharacterIDs + iVar13 * 4) = pTVar8->TimeStamp; - *(int *)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14) = iVar13; - *(undefined4 *)(&stack0xffffff84 + iVar12 + iVar2 + iVar3) = - *(undefined4 *)((int)RawData + 0x124); - *(undefined4 *)((int)&pcStack_80 + iVar12 + iVar2 + iVar3) = 0x806aa17; - pTVar8 = vector<>::operator() - (*(vector<> **)(&stack0xffffff84 + iVar12 + iVar2 + iVar3), - *(int *)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14)); - *(ulong *)(Texts + iVar13 * 4) = pTVar8->CharacterID; - *(int *)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14) = iVar13; - *(undefined4 *)(&stack0xffffff84 + iVar12 + iVar2 + iVar3) = - *(undefined4 *)((int)RawData + 0x124); - *(undefined4 *)((int)&pcStack_80 + iVar12 + iVar2 + iVar3) = 0x806aa32; - pTVar8 = vector<>::operator() - (*(vector<> **)(&stack0xffffff84 + iVar12 + iVar2 + iVar3), - *(int *)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14)); - switch(pTVar8->Mode) { - default: - *(int *)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14) = iVar13; - *(undefined4 *)(&stack0xffffff84 + iVar12 + iVar2 + iVar3) = - *(undefined4 *)((int)RawData + 0x124); - *(undefined4 *)((int)&pcStack_80 + iVar12 + iVar2 + iVar3) = 0x806aa9c; - pTVar8 = vector<>::operator() - (*(vector<> **)(&stack0xffffff84 + iVar12 + iVar2 + iVar3), - *(int *)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14)); - iVar11 = pTVar8->Mode; - *(undefined **)(&stack0xffffff84 + iVar12 + iVar2 + iVar3) = &DAT_080f5dc0; - *(int *)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14) = iVar11; - *(undefined4 *)((int)&pcStack_80 + iVar12 + iVar2 + iVar3) = 0x806aaaf; - error(*(char **)(&stack0xffffff84 + iVar12 + iVar2 + iVar3)); - *(undefined4 *)(iVar5 + iVar13 * 0x1e) = 0x6e6b6e55; - *(undefined4 *)((int)&local_44 + iVar13 * 0x1e + iVar2 + iVar3) = 0x6e776f; - break; - case 1: - *(undefined4 *)(iVar5 + iVar13 * 0x1e) = 0x796153; - break; - case 2: - *(undefined4 *)(iVar5 + iVar13 * 0x1e) = 0x73696857; - *(undefined4 *)((int)&local_44 + iVar13 * 0x1e + iVar2 + iVar3) = 0x726570; - break; - case 3: - *(undefined4 *)(iVar5 + iVar13 * 0x1e) = 0x6c6c6559; - *(undefined1 *)((int)&local_44 + iVar13 * 0x1e + iVar2 + iVar3) = 0; - break; - case 4: - case 0xb: - iVar11 = iVar13 * 0x1e; - *(undefined4 *)((int)&local_44 + iVar11 + iVar2 + iVar3) = 0x20657461; - *(undefined4 *)(iVar5 + iVar11) = 0x76697250; - *(undefined4 *)((int)&local_44 + iVar11 + iVar2 + iVar3 + 4) = 0x7373654d; - *(undefined4 *)((int)&local_3c + iVar11 + iVar2 + iVar3) = 0x656761; - break; - case 5: - case 10: - case 0xc: - *(int *)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14) = iVar13; - *(undefined4 *)(&stack0xffffff84 + iVar12 + iVar2 + iVar3) = - *(undefined4 *)((int)RawData + 0x124); - *(undefined4 *)((int)&pcStack_80 + iVar12 + iVar2 + iVar3) = 0x806ac0a; - pTVar8 = vector<>::operator() - (*(vector<> **)(&stack0xffffff84 + iVar12 + iVar2 + iVar3), - *(int *)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14)); - switch(pTVar8->Channel) { - case 0: - *(undefined4 *)(iVar5 + iVar13 * 0x1e) = 0x6c697547; - *(undefined4 *)((int)&local_44 + iVar13 * 0x1e + iVar2 + iVar3) = 0x68432064; - goto LAB_0806ac36; - case 1: - iVar11 = iVar13 * 0x1e; - *(undefined4 *)((int)&local_44 + iVar11 + iVar2 + iVar3) = 0x7473616d; - *(undefined4 *)(iVar5 + iVar11) = 0x656d6147; - *(undefined4 *)((int)&local_44 + iVar11 + iVar2 + iVar3 + 4) = 0x43207265; - *(undefined4 *)((int)&local_3c + iVar11 + iVar2 + iVar3) = 0x6e6e6168; - *(undefined2 *)((int)&local_38 + iVar11 + iVar2 + iVar3) = 0x6c65; - goto LAB_0806ab34; - case 2: - *(undefined4 *)(iVar5 + iVar13 * 0x1e) = 0x6f747554; - *(undefined4 *)((int)&local_44 + iVar13 * 0x1e + iVar2 + iVar3) = 0x68432072; - goto LAB_0806ac36; - default: - iVar11 = iVar13 * 0x1e; - *(undefined4 *)((int)&local_44 + iVar11 + iVar2 + iVar3) = 0x20657461; - *(undefined4 *)((int)&local_44 + iVar11 + iVar2 + iVar3 + 4) = 0x74616843; - *(undefined4 *)(iVar5 + iVar11) = 0x76697250; - *(undefined4 *)((int)&local_3c + iVar11 + iVar2 + iVar3) = 0x61684320; - *(undefined4 *)((int)&local_38 + iVar11 + iVar2 + iVar3) = 0x6c656e6e; - *(undefined1 *)((int)&Texts + iVar11 + iVar2 + iVar3) = 0; - break; - case 4: - *(undefined4 *)(iVar5 + iVar13 * 0x1e) = 0x656d6147; - *(undefined4 *)((int)&local_44 + iVar13 * 0x1e + iVar2 + iVar3) = 0x61684320; - goto LAB_0806abbc; - case 5: - *(undefined4 *)(iVar5 + iVar13 * 0x1e) = 0x64617254; - *(undefined4 *)((int)&local_44 + iVar13 * 0x1e + iVar2 + iVar3) = 0x68432065; -LAB_0806ac36: - *(undefined2 *)((int)&local_3c + iVar13 * 0x1e + iVar2 + iVar3) = 0x6c; - *(undefined4 *)((int)&local_44 + iVar13 * 0x1e + iVar2 + iVar3 + 4) = 0x656e6e61 - ; - break; - case 6: - iVar11 = iVar13 * 0x1e; - *(undefined4 *)(iVar5 + iVar11) = 0x6c616552; - *(undefined4 *)((int)&local_44 + iVar11 + iVar2 + iVar3) = 0x6566696c; - *(undefined4 *)((int)&local_44 + iVar11 + iVar2 + iVar3 + 4) = 0x61684320; - *(undefined2 *)((int)&local_3c + iVar11 + iVar2 + iVar3) = 0x74; - break; - case 7: - iVar11 = iVar13 * 0x1e; - *(undefined4 *)(iVar5 + iVar11) = 0x706c6548; - *(undefined4 *)((int)&local_44 + iVar11 + iVar2 + iVar3) = 0x61684320; - *(undefined4 *)((int)&local_44 + iVar11 + iVar2 + iVar3 + 4) = 0x6c656e6e; - *(undefined1 *)((int)&local_3c + iVar11 + iVar2 + iVar3) = 0; - } - break; - case 6: - iVar11 = iVar13 * 0x1e; - *(undefined4 *)((int)&local_44 + iVar11 + iVar2 + iVar3) = 0x7473616d; - *(undefined4 *)(iVar5 + iVar11) = 0x656d6147; - *(undefined4 *)((int)&local_44 + iVar11 + iVar2 + iVar3 + 4) = 0x52207265; - *(undefined4 *)((int)&local_3c + iVar11 + iVar2 + iVar3) = 0x65757165; - *(undefined2 *)((int)&local_38 + iVar11 + iVar2 + iVar3) = 0x7473; -LAB_0806ab34: - *(undefined1 *)((int)&local_38 + iVar13 * 0x1e + iVar2 + iVar3 + 2) = 0; - break; - case 7: - iVar11 = iVar13 * 0x1e; - *(undefined4 *)((int)&local_44 + iVar11 + iVar2 + iVar3) = 0x7473616d; - *(undefined4 *)(iVar5 + iVar11) = 0x656d6147; - *(undefined4 *)((int)&local_44 + iVar11 + iVar2 + iVar3 + 4) = 0x41207265; - *(undefined4 *)((int)&local_3c + iVar11 + iVar2 + iVar3) = 0x6577736e; - *(undefined2 *)((int)&local_38 + iVar11 + iVar2 + iVar3) = 0x72; - break; - case 8: - iVar11 = iVar13 * 0x1e; - *(undefined4 *)(iVar5 + iVar11) = 0x79616c50; - *(undefined4 *)((int)&local_44 + iVar11 + iVar2 + iVar3) = 0x41207265; - *(undefined4 *)((int)&local_44 + iVar11 + iVar2 + iVar3 + 4) = 0x6577736e; - *(undefined2 *)((int)&local_3c + iVar11 + iVar2 + iVar3) = 0x72; - break; - case 9: - *(undefined4 *)(iVar5 + iVar13 * 0x1e) = 0x616f7242; - *(undefined4 *)((int)&local_44 + iVar13 * 0x1e + iVar2 + iVar3) = 0x73616364; -LAB_0806abbc: - *(undefined2 *)((int)&local_44 + iVar13 * 0x1e + iVar2 + iVar3 + 4) = 0x74; - } - *(int *)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14) = iVar13; - *(undefined4 *)(&stack0xffffff84 + iVar12 + iVar2 + iVar3) = - *(undefined4 *)((int)RawData + 0x124); - *(undefined4 *)((int)&pcStack_80 + iVar12 + iVar2 + iVar3) = 0x806aa62; - pTVar8 = vector<>::operator() - (*(vector<> **)(&stack0xffffff84 + iVar12 + iVar2 + iVar3), - *(int *)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14)); - iVar11 = iVar13 * 0x100; - *(char **)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14) = pTVar8->Text; - iVar13 = iVar13 + 1; - *(int *)(&stack0xffffff84 + iVar12 + iVar2 + iVar3) = iVar11 + local_38; - *(undefined4 *)((int)&pcStack_80 + iVar12 + iVar2 + iVar3) = 0x806aa7c; - strcpy(*(char **)(&stack0xffffff84 + iVar12 + iVar2 + iVar3), - *(char **)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14)); - } while (iVar13 < local_24); - } - *(undefined4 *)(&stack0xffffff84 + iVar12 + iVar2 + iVar3) = - *(undefined4 *)((int)RawData + 0x50); - *(undefined4 *)((int)&pcStack_80 + iVar12 + iVar2 + iVar3) = 0x806a785; - pcVar4 = GetBanishmentReason(*(int *)(&stack0xffffff84 + iVar12 + iVar2 + iVar3)); - iVar13 = local_38; - *(int *)((int)aiStack_50 + iVar12 + iVar2 + iVar3) = iVar5; - *(int *)((int)aiStack_50 + iVar12 + iVar2 + iVar3 + 4) = iVar13; - *(char_0__256_ **)((int)aiStack_50 + iVar12 + iVar2 + iVar3 + -4) = Texts; - *(ulong_0_ **)((int)aiStack_50 + iVar12 + iVar2 + iVar3 + -8) = CharacterIDs; - *(ulong_0_ **)((int)local_64 + iVar12 + iVar2 + iVar3 + 8) = TimeStamps; - *(int *)((int)local_64 + iVar12 + iVar2 + iVar3 + 4) = local_24; - *(undefined4 *)((int)local_64 + iVar12 + iVar2 + iVar3) = *(undefined4 *)((int)RawData + 0x128); - iVar13 = Days; - *(char **)((int)&stack0xffffff90 + iVar12 + iVar2 + iVar3) = pcVar4; - *(int *)((int)&stack0xffffff94 + iVar12 + iVar2 + iVar3) = (int)RawData + 0x58; - iVar5 = (int)RawData + 0x22; - *(int *)((int)&stack0xffffff8c + iVar12 + iVar2 + iVar3) = iVar5; - *(int *)((int)&stack0xffffff98 + iVar12 + iVar2 + iVar3) = iVar13; - // WARNING: Load size is inaccurate - *(undefined4 *)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14) = *RawData; - *(TQueryManagerConnection **)(&stack0xffffff84 + iVar12 + iVar2 + iVar3) = - QueryManagerConnection; - *(undefined4 *)((int)&pcStack_80 + iVar12 + iVar2 + iVar3) = 0x806a7e2; - iVar13 = TQueryManagerConnection::reportStatement - (*(TQueryManagerConnection **)(&stack0xffffff84 + iVar12 + iVar2 + iVar3)); - if (iVar13 == 1) { - if (*(int *)((int)RawData + 0x54) == 6) { - *(char **)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14) = - "A player with this name does not exist. Perhaps he/she has been renamed?"; -LAB_0806a966: - // WARNING: Load size is inaccurate - *(undefined4 *)(&stack0xffffff84 + iVar12 + iVar2 + iVar3) = *RawData; - *(undefined4 *)((int)&pcStack_80 + iVar12 + iVar2 + iVar3) = 0x806a970; - DirectReply(*(ulong *)(&stack0xffffff84 + iVar12 + iVar2 + iVar3), - *(char **)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14)); - } -LAB_0806a955: - local_1e = '\0'; - puVar14 = (ulong *)StatementIDs; - } - else { - puVar14 = (ulong *)StatementIDs; - if (iVar13 < 2) { - if (iVar13 == 0) { - if (*(int *)((int)RawData + 0x54) == 6) { - *(int *)((int)&stack0xffffff8c + iVar12 + iVar2 + iVar3) = iVar5; - *(char **)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14) = - "Statement of %s reported."; - // WARNING: Load size is inaccurate - *(undefined4 *)(&stack0xffffff84 + iVar12 + iVar2 + iVar3) = *RawData; - *(undefined4 *)((int)&pcStack_80 + iVar12 + iVar2 + iVar3) = 0x806a9ba; - DirectReply(*(ulong *)(&stack0xffffff84 + iVar12 + iVar2 + iVar3), - *(char **)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14)); - } - *(int *)((int)&stack0xffffff90 + iVar12 + iVar2 + iVar3) = iVar5; - *(int *)((int)&stack0xffffff8c + iVar12 + iVar2 + iVar3) = (int)RawData + 4; - *(undefined **)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14) = &DAT_080f5d80; - *(char **)(&stack0xffffff84 + iVar12 + iVar2 + iVar3) = "banish"; - *(undefined4 *)((int)&pcStack_80 + iVar12 + iVar2 + iVar3) = 0x806a99f; - Log(*(char **)(&stack0xffffff84 + iVar12 + iVar2 + iVar3), - *(char **)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14)); - puVar14 = (ulong *)StatementIDs; - } - } - else if (iVar13 == 2) { - if (*(int *)((int)RawData + 0x54) == 6) { - *(char **)((int)local_64 + iVar12 + iVar2 + iVar3 + -0x14) = - "Statement has already been reported."; - goto LAB_0806a966; - } - goto LAB_0806a955; - } - } -LAB_0806a800: - if ((local_1e == '\0') || (*(char *)((int)RawData + 300) == '\0')) goto LAB_0806a710; - *puVar14 = *(undefined4 *)((int)RawData + 0x50); - puVar14[-1] = 0x806a828; - pcVar4 = GetBanishmentReason(*puVar14); - puVar14[3] = (int)RawData + 0x40; - puVar14[5] = (int)RawData + 0x58; - uVar1 = (int)RawData + 0x22; - puVar14[4] = (ulong)pcVar4; - puVar14[2] = uVar1; - // WARNING: Load size is inaccurate - puVar14[1] = *RawData; - *puVar14 = (ulong)QueryManagerConnection; - puVar14[-1] = 0x806a84e; - iVar5 = TQueryManagerConnection::banishIPAddress((TQueryManagerConnection *)*puVar14); - if (iVar5 == 1) { - puVar14[1] = (ulong) - "A player with this name does not exist. Perhaps he/she has been renamed?"; - } - else { - if (iVar5 < 2) { - if (iVar5 == 0) { - puVar14[2] = uVar1; - puVar14[1] = (ulong)"IP address of %s banished."; - // WARNING: Load size is inaccurate - *puVar14 = *RawData; - puVar14[-1] = 0x806a89a; - DirectReply(*puVar14,(char *)puVar14[1]); - *puVar14 = uVar1; - puVar14[-1] = 0x806a8a2; - sVar6 = strlen((char *)*puVar14); - *puVar14 = sVar6 + 1; - puVar14[-1] = 0x806a8ab; - pvVar7 = operator_new__(*puVar14); - puVar14[1] = uVar1; - *puVar14 = (ulong)pvVar7; - puVar14[-1] = 0x806a8b9; - strcpy((char *)*puVar14,(char *)puVar14[1]); - if (ReplyPointerWrite - ReplyPointerRead < 100) { - local_44 = (longlong)ReplyPointerWrite * 0x51eb851f; - local_3c = ReplyPointerWrite / 100; - ReplyBuffer[ReplyPointerWrite % 100].ReplyType = REPLY_LOGOUT; - ReplyBuffer[ReplyPointerWrite % 100].Data = pvVar7; - ReplyPointerWrite = ReplyPointerWrite + 1; - } - else { - *puVar14 = (ulong)&DAT_080f5540; - puVar14[-1] = 0x806a940; - error((char *)*puVar14); - } - puVar14[3] = uVar1; - puVar14[2] = (int)RawData + 4; - puVar14[1] = (ulong)"%s sperrt die IP-Adresse von %s.\n"; - *puVar14 = (ulong)"banish"; - puVar14[-1] = 0x806a92f; - Log((char *)*puVar14,(char *)puVar14[1]); - } - goto LAB_0806a710; - } - if (iVar5 != 2) goto LAB_0806a710; - puVar14[1] = (ulong)"You may not report a god or gamemaster."; - } - // WARNING: Load size is inaccurate - *puVar14 = *RawData; - puVar14[-1] = 0x806a877; - DirectReply(*puVar14,(char *)puVar14[1]); -LAB_0806a710: - *puVar14 = (ulong)RawData; - puVar14[-1] = 0x806a718; - operator_delete((void *)*puVar14); - return; -} - - - -void ProcessCharacterDeathOrder(void *RawData) - -{ - int iVar1; - - if (RawData != (void *)0x0) { - // WARNING: Load size is inaccurate - iVar1 = TQueryManagerConnection::logCharacterDeath - (QueryManagerConnection,*RawData,*(int *)((int)RawData + 4), - *(ulong *)((int)RawData + 8),(char *)((int)RawData + 0xc), - *(bool *)((int)RawData + 0x2a),*(time_t *)((int)RawData + 0x2c)); - if (iVar1 != 0) { - error("ProcessCharacterDeathOrder: Protokollierung fehlgeschlagen.\n"); - } - operator_delete(RawData); - return; - } - error(&DAT_080f6160); - return; -} - - - -void ProcessAddBuddyOrder(void *RawData) - -{ - int iVar1; - undefined4 uVar2; - undefined4 uVar3; - - if (RawData != (void *)0x0) { - uVar3 = *(undefined4 *)((int)RawData + 4); - // WARNING: Load size is inaccurate - uVar2 = *RawData; - iVar1 = TQueryManagerConnection::addBuddy(QueryManagerConnection); - if (iVar1 != 0) { - error("ProcessAddBuddyOrder: Aufnahme fehlgeschlagen.\n",uVar2,uVar3); - } - operator_delete(RawData); - return; - } - error(&DAT_080f61e0); - return; -} - - - -void ProcessRemoveBuddyOrder(void *RawData) - -{ - int iVar1; - undefined4 uVar2; - undefined4 uVar3; - - if (RawData != (void *)0x0) { - uVar3 = *(undefined4 *)((int)RawData + 4); - // WARNING: Load size is inaccurate - uVar2 = *RawData; - iVar1 = TQueryManagerConnection::removeBuddy(QueryManagerConnection); - if (iVar1 != 0) { - error("ProcessRemoveBuddyOrder: Entfernen fehlgeschlagen.\n",uVar2,uVar3); - } - operator_delete(RawData); - return; - } - error(&DAT_080f6260); - return; -} - - - -void ProcessDecrementIsOnlineOrder(void *RawData) - -{ - int iVar1; - - iVar1 = TQueryManagerConnection::decrementIsOnline(QueryManagerConnection,(ulong)RawData); - if (iVar1 == 0) { - return; - } - error("ProcessDecrementIsOnlineOrder: Verringerung fehlgeschlagen.\n"); - return; -} - - - -// WARNING: Variable defined which should be unmapped: HelpProfession - -int WriterThreadLoop(void *param_1) - -{ - TWriterThreadOrderType TVar1; - ulong *RawData; - int iVar2; - char *pcVar3; - ulong uVar4; - ulong uVar5; - ulong uVar6; - ulong *puVar7; - char local_2c [4]; - char HelpProfession [30]; - -LAB_0806b310: - Semaphore::down(&OrderBufferFull); - TVar1 = OrderBuffer[OrderPointerRead % 2000].OrderType; - RawData = (ulong *)OrderBuffer[OrderPointerRead % 2000].Data; - OrderPointerRead = OrderPointerRead + 1; - Semaphore::up(&OrderBufferEmpty); - switch(TVar1) { - case ORDER_TERMINATE: - return 0; - case ORDER_LOGOUT: - if (RawData != (ulong *)0x0) { - pcVar3 = local_2c; - GetProfessionName(pcVar3,RawData[2],false,true); - if (0 < (int)RawData[4]) { - print(); - } - uVar6 = RawData[4]; - puVar7 = RawData + 5; - uVar4 = RawData[3]; - uVar5 = RawData[1]; - iVar2 = TQueryManagerConnection::logoutGame(QueryManagerConnection); - if (iVar2 != 0) { - error(&DAT_080f5a20,*RawData,uVar5,pcVar3,puVar7,uVar4,uVar6); - } -LAB_0806b403: - operator_delete(RawData); - goto LAB_0806b310; - } - pcVar3 = &DAT_080f5a60; - break; - case ORDER_PLAYERLIST: - ProcessPlayerlistOrder(RawData); - goto LAB_0806b310; - case ORDER_KILLSTATISTICS: - ProcessKillStatisticsOrder(RawData); - goto LAB_0806b310; - case ORDER_PUNISHMENT: - ProcessPunishmentOrder(RawData); - goto LAB_0806b310; - case ORDER_CHARACTERDEATH: - if (RawData != (ulong *)0x0) { - uVar6 = RawData[1]; - uVar4 = *RawData; - iVar2 = TQueryManagerConnection::logCharacterDeath - (QueryManagerConnection,uVar4,uVar6,RawData[2],(char *)(RawData + 3), - *(bool *)((int)RawData + 0x2a),RawData[0xb]); - if (iVar2 != 0) { - pcVar3 = "ProcessCharacterDeathOrder: Protokollierung fehlgeschlagen.\n"; -LAB_0806b4af: - error(pcVar3,uVar4,uVar6); - } - goto LAB_0806b403; - } - pcVar3 = &DAT_080f6160; - break; - case ORDER_ADDBUDDY: - if (RawData != (ulong *)0x0) { - uVar6 = RawData[1]; - uVar4 = *RawData; - iVar2 = TQueryManagerConnection::addBuddy(QueryManagerConnection); - if (iVar2 != 0) { - pcVar3 = "ProcessAddBuddyOrder: Aufnahme fehlgeschlagen.\n"; - goto LAB_0806b4af; - } - goto LAB_0806b403; - } - pcVar3 = &DAT_080f61e0; - break; - case ORDER_REMOVEBUDDY: - if (RawData != (ulong *)0x0) { - uVar6 = RawData[1]; - uVar4 = *RawData; - iVar2 = TQueryManagerConnection::removeBuddy(QueryManagerConnection); - if (iVar2 != 0) { - pcVar3 = "ProcessRemoveBuddyOrder: Entfernen fehlgeschlagen.\n"; - goto LAB_0806b4af; - } - goto LAB_0806b403; - } - pcVar3 = &DAT_080f6260; - break; - case ORDER_DECREMENTISONLINE: - iVar2 = TQueryManagerConnection::decrementIsOnline(QueryManagerConnection,(ulong)RawData); - if (iVar2 == 0) goto LAB_0806b310; - pcVar3 = "ProcessDecrementIsOnlineOrder: Verringerung fehlgeschlagen.\n"; - break; - case ORDER_SAVEPLAYERDATA: - SavePlayerPoolSlots(); - goto LAB_0806b310; - default: - goto switchD_0806b373_default; - } - error(pcVar3); - goto LAB_0806b310; -switchD_0806b373_default: - error("WriterThreadLoop: Unbekanntes Kommando %d.\n",TVar1); - goto LAB_0806b310; -} - - - -void ProcessBroadcastReply(void *RawData) - -{ - if (RawData != (void *)0x0) { - BroadcastMessage(0x15,(char *)RawData); - operator_delete__(RawData); - return; - } - error(&DAT_080f6320); - return; -} - - - -void ProcessDirectReply(void *RawData) - -{ - TPlayer *pl; - TPlayer *pTVar1; - - if (RawData != (void *)0x0) { - // WARNING: Load size is inaccurate - pTVar1 = GetPlayer(*RawData); - if (pTVar1 != (TPlayer *)0x0) { - SendMessage((pTVar1->super_TCreature).Connection,0x16,"%s",(int)RawData + 4); - } - operator_delete(RawData); - return; - } - error(&DAT_080f6360); - return; -} - - - -void ProcessLogoutReply(void *RawData) - -{ - TPlayer *this; - TPlayer *pl; - Object local_1c [4]; - - if (RawData == (void *)0x0) { - error(&DAT_080f63a0); - } - else { - this = GetPlayer((char *)RawData); - if (this != (TPlayer *)0x0) { - local_1c[0].ObjectID = (this->super_TCreature).CrObject.ObjectID; - GraphicalEffect(local_1c,0xf); - TCreature::StartLogout(&this->super_TCreature,true,true); - } - operator_delete__(RawData); - } - return; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void ProcessWriterThreadReplies(void) - -{ - TWriterThreadReplyType TVar1; - ulong *Text; - TPlayer *pl; - TPlayer *pTVar2; - void *Data; - TWriterThreadReplyType ReplyType; - char *Text_00; - -LAB_0806b6c0: - do { - while( true ) { - if (ReplyPointerRead == ReplyPointerWrite) { - return; - } - TVar1 = ReplyBuffer[ReplyPointerRead % 100].ReplyType; - Text = (ulong *)ReplyBuffer[ReplyPointerRead % 100].Data; - ReplyPointerRead = ReplyPointerRead + 1; - if (TVar1 != REPLY_DIRECT) break; - if (Text == (ulong *)0x0) { - Text_00 = &DAT_080f6360; -LAB_0806b762: - error(Text_00); - } - else { - pTVar2 = GetPlayer(*Text); - if (pTVar2 != (TPlayer *)0x0) { - SendMessage((pTVar2->super_TCreature).Connection,0x16,"%s",Text + 1); - } - operator_delete(Text); - } - } - if ((int)TVar1 < 2) { - if (TVar1 == REPLY_BROADCAST) { - if (Text == (ulong *)0x0) { - Text_00 = &DAT_080f6320; - goto LAB_0806b762; - } - BroadcastMessage(0x15,(char *)Text); - operator_delete__(Text); - } - else { -LAB_0806b783: - error(&DAT_080f63e0,TVar1); - } - goto LAB_0806b6c0; - } - if (TVar1 != REPLY_LOGOUT) goto LAB_0806b783; - ProcessLogoutReply(Text); - } while( true ); -} - - - -// WARNING: Variable defined which should be unmapped: NumberOfAffectedPlayers -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void ClearPlayers(void) - -{ - int iVar1; - int local_8; - int NumberOfAffectedPlayers; - - iVar1 = TQueryManagerConnection::clearIsOnline(QueryManagerConnection,&local_8); - if (iVar1 == 0) { - if (local_8 != 0) { - error("ClearPlayers: %d Spieler waren als eingeloggt markiert.\n",local_8); - } - } - else { - error(&DAT_080f6460); - } - return; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void InitWriter(void) - -{ - TQueryManagerConnection *this; - int iVar1; - undefined4 *puVar2; - int *piVar3; - int local_1c; - int NumberOfAffectedPlayers; - int local_14; - - // try { // try from 0806b846 to 0806b84a has its CatchHandler @ 0806b9f0 - this = (TQueryManagerConnection *)operator_new(0x30); - local_14 = 0x4000; - NumberOfAffectedPlayers = MaxPlayers * 0x42 + 2; - piVar3 = &NumberOfAffectedPlayers; - if (NumberOfAffectedPlayers < 0x4001) { - piVar3 = &local_14; - } - // try { // try from 0806b87f to 0806b883 has its CatchHandler @ 0806b9c0 - TQueryManagerConnection::TQueryManagerConnection(this,*piVar3); - QueryManagerConnection = this; - if (this->Socket < 0) { - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = "cannot connect to query manager"; - } - else { - // try { // try from 0806b8a4 to 0806b9a1 has its CatchHandler @ 0806b9f0 - iVar1 = TQueryManagerConnection::clearIsOnline(this,&local_1c); - if (iVar1 == 0) { - if (local_1c != 0) { - error("ClearPlayers: %d Spieler waren als eingeloggt markiert.\n",local_1c); - } - } - else { - error(&DAT_080f6460); - } - ProtocolPointerWrite = 0; - ProtocolPointerRead = 0; - ProtocolThread = StartThread(ProtocolThreadLoop,(void *)0x0,false); - if (ProtocolThread == 0) { - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = "cannot start protocol thread"; - } - else { - OrderPointerWrite = 0; - OrderPointerRead = 0; - ReplyPointerWrite = 0; - ReplyPointerRead = 0; - WriterThread = StartThread(WriterThreadLoop,(void *)0x0,false); - if (WriterThread != 0) { - return; - } - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = "cannot start writer thread"; - } - } - // WARNING: Subroutine does not return - __cxa_throw(puVar2,char_const*::typeinfo,0); -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void AbortWriter(void) - -{ - if (WriterThread != 0) { - WriterThread = 0; - pthread_cancel(0); - Semaphore::up(&OrderBufferEmpty); - } - return; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void ExitWriter(void) - -{ - TQueryManagerConnection *pTVar1; - undefined *in_stack_ffffffe8; - - if (ProtocolThread != 0) { - in_stack_ffffffe8 = &DAT_080ef15d; - InsertProtocolOrder("",""); - JoinThread(ProtocolThread); - ProtocolThread = 0; - } - if (WriterThread != 0) { - if (1999 < OrderPointerWrite - OrderPointerRead) { - error(&DAT_080f5500); - } - Semaphore::down(&OrderBufferEmpty); - OrderBuffer[OrderPointerWrite % 2000].OrderType = ORDER_TERMINATE; - OrderBuffer[OrderPointerWrite % 2000].Data = (void *)0x0; - OrderPointerWrite = OrderPointerWrite + 1; - Semaphore::up(&OrderBufferFull); - JoinThread(WriterThread); - WriterThread = 0; - } - pTVar1 = QueryManagerConnection; - if (QueryManagerConnection != (TQueryManagerConnection *)0x0) { - TQueryManagerConnection::~TQueryManagerConnection - (QueryManagerConnection,(int)in_stack_ffffffe8); - operator_delete(pTVar1); - } - return; -} - - - void __tcf_0(void *param_1) { diff --git a/reference/types.hh b/reference/types.hh index fc365b4..051c33c 100644 --- a/reference/types.hh +++ b/reference/types.hh @@ -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 *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; diff --git a/src/communication.cc b/src/communication.cc index 799cd42..99c891a 100644 --- a/src/communication.cc +++ b/src/communication.cc @@ -5,8 +5,7 @@ #include "crypto.hh" #include "query.hh" #include "threads.hh" - -#include "stubs.hh" +#include "writer.hh" #include #include diff --git a/src/communication.hh b/src/communication.hh index f466b9e..8d2574b 100644 --- a/src/communication.hh +++ b/src/communication.hh @@ -3,7 +3,8 @@ #include "common.hh" #include "connections.hh" -#include "cr.hh" + +struct TPlayerData; struct TWaitinglistEntry { TWaitinglistEntry *Next; diff --git a/src/connections.cc b/src/connections.cc index 7cf70c7..cef9fa6 100644 --- a/src/connections.cc +++ b/src/connections.cc @@ -2,8 +2,7 @@ #include "cr.hh" #include "info.hh" #include "threads.hh" - -#include "stubs.hh" +#include "writer.hh" #include #include diff --git a/src/cract.cc b/src/cract.cc index 15fdf66..a7bb2fe 100644 --- a/src/cract.cc +++ b/src/cract.cc @@ -1,5 +1,6 @@ #include "cr.hh" #include "config.hh" +#include "houses.hh" #include "info.hh" #include "operate.hh" diff --git a/src/crmain.cc b/src/crmain.cc index c70acb2..96ccc92 100644 --- a/src/crmain.cc +++ b/src/crmain.cc @@ -4,8 +4,7 @@ #include "enums.hh" #include "info.hh" #include "operate.hh" - -#include "stubs.hh" +#include "writer.hh" #include diff --git a/src/crnonpl.cc b/src/crnonpl.cc index 29a5d11..277e2e6 100644 --- a/src/crnonpl.cc +++ b/src/crnonpl.cc @@ -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 diff --git a/src/crplayer.cc b/src/crplayer.cc index 9978527..b8e1926 100644 --- a/src/crplayer.cc +++ b/src/crplayer.cc @@ -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" diff --git a/src/houses.cc b/src/houses.cc index 87f4556..16bc0ee 100644 --- a/src/houses.cc +++ b/src/houses.cc @@ -4,8 +4,7 @@ #include "info.hh" #include "moveuse.hh" #include "query.hh" - -#include "stubs.hh" +#include "writer.hh" static vector HelpDepot(0, 9, 10); static int HelpDepots; @@ -1904,6 +1903,6 @@ void InitHouses(void){ delete QueryManagerConnection; } -void SaveHouses(void){ +void ExitHouses(void){ SaveOwners(); } diff --git a/src/houses.hh b/src/houses.hh index 9326e65..8402bf2 100644 --- a/src/houses.hh +++ b/src/houses.hh @@ -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_ diff --git a/src/info.cc b/src/info.cc index fa01ecb..08433f2 100644 --- a/src/info.cc +++ b/src/info.cc @@ -1,7 +1,6 @@ #include "info.hh" #include "cr.hh" - -#include "stubs.hh" +#include "magic.hh" const char *GetLiquidName(int LiquidType){ const char *LiquidName; diff --git a/src/magic.cc b/src/magic.cc index 1282e5d..ca7aaec 100644 --- a/src/magic.cc +++ b/src/magic.cc @@ -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 #include diff --git a/src/magic.hh b/src/magic.hh index ff14c48..30570b0 100644 --- a/src/magic.hh +++ b/src/magic.hh @@ -3,6 +3,7 @@ #include "common.hh" #include "cr.hh" +#include "map.hh" enum : int { FIELD_TYPE_FIRE = 1, diff --git a/src/main.cc b/src/main.cc index 4b52ab2..c64838a 100644 --- a/src/main.cc +++ b/src/main.cc @@ -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(); diff --git a/src/map.cc b/src/map.cc index 64886bf..90a2c1a 100644 --- a/src/map.cc +++ b/src/map.cc @@ -2,6 +2,7 @@ #include "containers.hh" #include "config.hh" #include "enums.hh" +#include "houses.hh" #include "script.hh" #include "stubs.hh" diff --git a/src/moveuse.cc b/src/moveuse.cc index 9cdcd95..3db2016 100644 --- a/src/moveuse.cc +++ b/src/moveuse.cc @@ -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" diff --git a/src/operate.cc b/src/operate.cc index 8123ba0..a9644c2 100644 --- a/src/operate.cc +++ b/src/operate.cc @@ -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" diff --git a/src/operate.hh b/src/operate.hh index 85cbf9f..6d55416 100644 --- a/src/operate.hh +++ b/src/operate.hh @@ -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); diff --git a/src/query.hh b/src/query.hh index 0db66cc..a69413a 100644 --- a/src/query.hh +++ b/src/query.hh @@ -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, diff --git a/src/receiving.cc b/src/receiving.cc index 1c6ee00..147f085 100644 --- a/src/receiving.cc +++ b/src/receiving.cc @@ -1,7 +1,7 @@ #include "connections.hh" +#include "houses.hh" #include "info.hh" - -#include "stubs.hh" +#include "writer.hh" #include diff --git a/src/sending.cc b/src/sending.cc index 14551da..970439f 100644 --- a/src/sending.cc +++ b/src/sending.cc @@ -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 diff --git a/src/shm.cc b/src/shm.cc index ff5f603..7a63eae 100644 --- a/src/shm.cc +++ b/src/shm.cc @@ -2,8 +2,7 @@ #include "config.hh" #include "enums.hh" #include "threads.hh" - -#include "stubs.hh" +#include "writer.hh" #include diff --git a/src/stubs.hh b/src/stubs.hh index 191c733..4e974d7 100644 --- a/src/stubs.hh +++ b/src/stubs.hh @@ -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 *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_ diff --git a/src/writer.cc b/src/writer.cc new file mode 100644 index 0000000..1b84e98 --- /dev/null +++ b/src/writer.cc @@ -0,0 +1,1045 @@ +#include "writer.hh" +#include "config.hh" +#include "cr.hh" +#include "info.hh" +#include "query.hh" +#include "threads.hh" + +static ThreadHandle ProtocolThread; +static ThreadHandle WriterThread; + +static TProtocolThreadOrder ProtocolBuffer[1000]; +static int ProtocolPointerWrite; +static int ProtocolPointerRead; +static Semaphore ProtocolMutex(1); +static Semaphore ProtocolBufferEmpty(1000); +static Semaphore ProtocolBufferFull(0); + +static TWriterThreadOrder OrderBuffer[2000]; +static int OrderPointerWrite; +static int OrderPointerRead; +static Semaphore OrderBufferEmpty(2000); +static Semaphore OrderBufferFull(0); + +static TWriterThreadReply ReplyBuffer[100]; +static int ReplyPointerWrite; +static int ReplyPointerRead; + +static TQueryManagerConnection *QueryManagerConnection; + +// Protocol Orders +// ============================================================================= +void InitProtocol(void){ + ProtocolPointerWrite = 0; + ProtocolPointerRead = 0; +} + +void InsertProtocolOrder(const char *ProtocolName, const char *Text){ + if(ProtocolName == NULL){ + error("InsertProtocolOrder: Protokoll-Name nicht angegeben.\n"); + return; + } + + if(Text == NULL){ + error("InsertProtocolOrder: Text nicht angegeben.\n"); + return; + } + + int Orders = (ProtocolPointerWrite - ProtocolPointerRead); + if(Orders >= NARRAY(ProtocolBuffer) && strcmp(ProtocolName, "error") != 0){ + error("InsertProtocolOrder: Protokoll-Puffer ist voll => Vergrößern.\n"); + } + + ProtocolMutex.down(); + ProtocolBufferEmpty.down(); + int WritePos = ProtocolPointerWrite % NARRAY(ProtocolBuffer); + strcpy(ProtocolBuffer[WritePos].ProtocolName, ProtocolName); + strcpy(ProtocolBuffer[WritePos].Text, Text); + ProtocolPointerWrite += 1; + ProtocolBufferFull.up(); + ProtocolMutex.up(); +} + +void GetProtocolOrder(TProtocolThreadOrder *Order){ + ProtocolBufferFull.down(); + int ReadPos = ProtocolPointerRead % NARRAY(ProtocolBuffer); + *Order = ProtocolBuffer[ReadPos]; + ProtocolPointerRead += 1; + ProtocolBufferEmpty.up(); +} + +void WriteProtocol(const char *ProtocolName, const char *Text){ + char FileName[4096]; + snprintf(FileName, sizeof(FileName), "%s/%s.log", LOGPATH, ProtocolName); + + FILE *File = fopen(FileName, "at"); + if(File != NULL){ + fprintf(File, "%s", Text); + if(fclose(File) != 0){ + error("WriteProtocol: Fehler %d beim Schließen der Datei.\n", errno); + } + } +} + +int ProtocolThreadLoop(void *Unused){ + TProtocolThreadOrder Order = {}; + while(true){ + GetProtocolOrder(&Order); + if(Order.ProtocolName[0] == 0){ + break; + } + + WriteProtocol(Order.ProtocolName, Order.Text); + } + return 0; +} + +void InitLog(const char *ProtocolName){ + if(ProtocolName == NULL){ + error("InitLog: Protokoll-Name nicht angegeben.\n"); + return; + } + + char FileName[4096]; + snprintf(FileName, sizeof(FileName), "%s/%s.log", LOGPATH, ProtocolName); + + FILE *File = fopen(FileName, "at"); + if(File ==NULL){ + error("InitLog: Kann Protokoll %s nicht anlegen.\n", ProtocolName); + return; + } + + // NOTE(fusion): `ctime` will already add a new line character. + time_t Time = time(NULL); + fprintf(File, "-------------------------------------------------------------------------------\n"); + fprintf(File, "Tibia - Graphical Multi-User-Dungeon\n"); + fprintf(File, "%s.log - gestartet %s", ProtocolName, ctime(&Time)); + fclose(File); +} + +void Log(const char *ProtocolName, const char *Text, ...){ + if(ProtocolName == NULL || ProtocolName[0] == 0){ + error("Log: Protokoll-Name nicht angegeben.\n"); + return; + } + + bool WriteDate = (strcmp(ProtocolName, "bugreport") == 0) + || (strcmp(ProtocolName, "client-error") == 0) + || (strcmp(ProtocolName, "load") == 0); + + char Output[256]; + va_list ap; + va_start(ap, Text); + vsnprintf(Output, sizeof(Output), Text, ap); + va_end(ap); + + char Line[256]; + if(WriteDate){ + print(2, "%s.log: %s", ProtocolName, Output); + struct tm LocalTime = GetLocalTimeTM(time(NULL)); + snprintf(Line, sizeof(Line), "%02d.%02d.%04d %02d:%02d:%02d (%u): %s", + LocalTime.tm_mday, LocalTime.tm_mon + 1, LocalTime.tm_year + 1900, + LocalTime.tm_hour, LocalTime.tm_min, LocalTime.tm_sec, RoundNr, Output); + }else{ + strcpy(Line, Output); + } + + if(Line[0] != 0){ + int LineEnd = (int)strlen(Line); + if(LineEnd < (int)(sizeof(Line) - 1)){ + Line[LineEnd] = '\n'; + Line[LineEnd + 1] = 0; + }else{ + Line[LineEnd - 1] = '\n'; + } + + if(ProtocolThread != INVALID_THREAD_HANDLE){ + InsertProtocolOrder(ProtocolName, Line); + }else{ + WriteProtocol(ProtocolName, Line); + } + } +} + +// Writer Orders +// ============================================================================= +void InitWriterBuffers(void){ + OrderPointerWrite = 0; + ReplyPointerWrite = 0; + OrderPointerRead = 0; + ReplyPointerRead = 0; +} + +int GetOrderBufferSpace(void){ + int Result = INT_MAX; + if(WriterThread != INVALID_THREAD_HANDLE){ + int Orders = (OrderPointerWrite - OrderPointerRead); + Result = NARRAY(OrderBuffer) - Orders; + } + return Result; +} + +void InsertOrder(TWriterThreadOrderType OrderType, const void *Data){ + if(WriterThread != INVALID_THREAD_HANDLE){ + int Orders = (OrderPointerWrite - OrderPointerRead); + if(Orders >= NARRAY(OrderBuffer)){ + error("InsertOrder (Writer): Order-Puffer ist voll => Vergrößern.\n"); + } + + OrderBufferEmpty.down(); + int WritePos = OrderPointerWrite % NARRAY(OrderBuffer); + OrderBuffer[WritePos].OrderType = OrderType; + OrderBuffer[WritePos].Data = Data; + OrderPointerWrite += 1; + OrderBufferFull.up(); + } +} + +void GetOrder(TWriterThreadOrder *Order){ + OrderBufferFull.down(); + int ReadPos = OrderPointerRead % NARRAY(OrderBuffer); + *Order = OrderBuffer[ReadPos]; + OrderPointerRead += 1; + OrderBufferEmpty.up(); +} + +void TerminateWriterOrder(void){ + InsertOrder(ORDER_TERMINATE, NULL); +} + +void LogoutOrder(TPlayer *Player){ + if(Player == NULL){ + error("LogoutOrder: Übergebener Spieler existiert nicht.\n"); + return; + } + + TLogoutOrderData *Data = new TLogoutOrderData; + Data->CharacterID = Player->ID; + Data->Level = Player->Skills[SKILL_LEVEL]->Get(); + Data->Profession = Player->GetActiveProfession(); + if(Player->PlayerData == NULL){ + error("LogoutOrder: PlayerData ist NULL.\n"); + Data->LastLoginTime = 0; + }else{ + Data->LastLoginTime = Player->PlayerData->LastLoginTime; + } + Data->TutorActivities = Player->TutorActivities; + + // TODO(fusion): LOL. + if(Player->startx == 32097){ + strcpy(Data->Residence, "Rookgaard"); + }else if(Player->startx == 32360){ + strcpy(Data->Residence, "Carlin"); + }else if(Player->startx == 32369){ + strcpy(Data->Residence, "Thais"); + }else if(Player->startx == 32595){ + strcpy(Data->Residence, "Port Hope"); + }else if(Player->startx == 32649){ + strcpy(Data->Residence, "Kazordoon"); + }else if(Player->startx == 32732){ + strcpy(Data->Residence, "Ab'Dendriel"); + }else if(Player->startx == 32957){ + strcpy(Data->Residence, "Venore"); + }else if(Player->startx == 33194){ + strcpy(Data->Residence, "Ankrahmun"); + }else if(Player->startx == 33213){ + strcpy(Data->Residence, "Darashia"); + }else if(Player->startx == 33217){ + strcpy(Data->Residence, "Edron"); + }else{ + error("LogoutOrder: Unbekannte Startkoordinate [%d,%d,%d] bei Spieler %s.\n", + Player->startx, Player->starty, Player->startz, Player->Name); + strcpy(Data->Residence, "Unknown"); + } + + InsertOrder(ORDER_LOGOUT, Data); +} + +void PlayerlistOrder(int NumberOfPlayers, const char *PlayerNames, + int *PlayerLevels, int *PlayerProfessions){ + if(PlayerNames == NULL){ + error("PlayerlistOrder: PlayerNames ist NULL.\n"); + return; + } + + if(PlayerLevels == NULL){ + error("PlayerlistOrder: PlayerLevels ist NULL.\n"); + return; + } + + if(PlayerProfessions == NULL){ + error("PlayerlistOrder: PlayerProfessions ist NULL.\n"); + return; + } + + TPlayerlistOrderData *Data = new TPlayerlistOrderData; + Data->NumberOfPlayers = NumberOfPlayers; + Data->PlayerNames = PlayerNames; + Data->PlayerLevels = PlayerLevels; + Data->PlayerProfessions = PlayerProfessions; + + InsertOrder(ORDER_PLAYERLIST, Data); +} + +void KillStatisticsOrder(int NumberOfRaces, const char *RaceNames, + int *KilledPlayers, int *KilledCreatures){ + if(RaceNames == NULL){ + error("KillStatisticsOrder: RaceNames ist NULL.\n"); + return; + } + + if(KilledPlayers == NULL){ + error("KillStatisticsOrder: KilledPlayers ist NULL.\n"); + return; + } + + if(KilledCreatures == NULL){ + error("KillStatisticsOrder: KilledCreatures ist NULL.\n"); + return; + } + + TKillStatisticsOrderData *Data = new TKillStatisticsOrderData; + Data->NumberOfRaces = NumberOfRaces; + Data->RaceNames = RaceNames; + Data->KilledPlayers = KilledPlayers; + Data->KilledCreatures = KilledCreatures; + + InsertOrder(ORDER_KILLSTATISTICS, Data); +} + +void PunishmentOrder(TCreature *Gamemaster, const char *Name, const char *IPAddress, + int Reason, int Action, const char *Comment, int NumberOfStatements, + vector *ReportedStatements, uint32 StatementID, + bool IPBanishment){ + if(Name == NULL){ + error("PunishmentOrder: Name ist NULL.\n"); + return; + } + + if(Comment == NULL){ + error("PunishmentOrder: Comment ist NULL.\n"); + return; + } + + TPunishmentOrderData *Data = new TPunishmentOrderData; + if(Gamemaster != NULL){ + Data->GamemasterID = Gamemaster->ID; + strcpy(Data->GamemasterName, Gamemaster->Name); + }else{ + Data->GamemasterID = 0; + strcpy(Data->GamemasterName, "automatic"); + } + strcpy(Data->CriminalName, Name); + strcpy(Data->CriminalIPAddress, (IPAddress != NULL ? IPAddress : "")); + Data->Reason = Reason; + Data->Action = Action; + strcpy(Data->Comment, Comment); + Data->NumberOfStatements = NumberOfStatements; + Data->ReportedStatements = ReportedStatements; + Data->StatementID = StatementID; + Data->IPBanishment = IPBanishment; + + InsertOrder(ORDER_PUNISHMENT, Data); +} + +void CharacterDeathOrder(TCreature *Creature, int OldLevel, + uint32 OffenderID, const char *Remark, bool Unjustified){ + if(Creature == NULL){ + error("CharacterDeathOrder: cr ist NULL.\n"); + return; + } + + if(Remark == NULL){ + error("CharacterDeathOrder: Remark ist NULL.\n"); + return; + } + + TCharacterDeathOrderData *Data = new TCharacterDeathOrderData; + Data->CharacterID = Creature->ID; + Data->Level = OldLevel; + Data->Offender = OffenderID; + strcpy(Data->Remark, Remark); + Data->Unjustified = Unjustified; + Data->Time = time(NULL); + + InsertOrder(ORDER_CHARACTERDEATH, Data); +} + +void AddBuddyOrder(TCreature *Creature, uint32 BuddyID){ + if(Creature == NULL){ + error("AddBuddyOrder: cr ist NULL.\n"); + return; + } + + if(Creature->Type != PLAYER){ + error("AddBuddyOrder: Kreatur ist kein Spieler.\n"); + return; + } + + TBuddyOrderData *Data = new TBuddyOrderData; + Data->AccountID = ((TPlayer*)Creature)->AccountID; + Data->Buddy = BuddyID; + + InsertOrder(ORDER_ADDBUDDY, Data); +} + +void RemoveBuddyOrder(TCreature *Creature, uint32 BuddyID){ + if(Creature == NULL){ + error("RemoveBuddyOrder: cr ist NULL.\n"); + return; + } + + if(Creature->Type != PLAYER){ + error("RemoveBuddyOrder: Kreatur ist kein Spieler.\n"); + return; + } + + TBuddyOrderData *Data = new TBuddyOrderData; + Data->AccountID = ((TPlayer*)Creature)->AccountID; + Data->Buddy = BuddyID; + + InsertOrder(ORDER_REMOVEBUDDY, Data); +} + +void DecrementIsOnlineOrder(uint32 CharacterID){ + void *Data = (void*)((uintptr)CharacterID); + InsertOrder(ORDER_DECREMENTISONLINE, Data); +} + +void SavePlayerDataOrder(void){ + InsertOrder(ORDER_SAVEPLAYERDATA, NULL); +} + +void ProcessLogoutOrder(TLogoutOrderData *Data){ + if(Data == NULL){ + error("ProcessLogoutOrder: Keine Daten übergeben.\n"); + return; + } + + if(Data->TutorActivities > 0){ + print(3, "%d Tutor-Punkte für Spieler %u.\n", + Data->TutorActivities, Data->CharacterID); + } + + char ProfessionName[30]; + GetProfessionName(ProfessionName, Data->Profession, false, true); + int Ret = QueryManagerConnection->logoutGame(Data->CharacterID, Data->Level, + ProfessionName, Data->Residence, Data->LastLoginTime, Data->TutorActivities); + if(Ret != 0){ + error("ProcessLogoutOrder: Logout für Spieler %u fehlgeschlagen.\n", + Data->CharacterID); + } + + delete Data; +} + +void ProcessPlayerlistOrder(TPlayerlistOrderData *Data){ + if(Data == NULL){ + error("ProcessPlayerlistOrder: Keine Daten übergeben.\n"); + return; + } + + bool NewRecord = false; + if(Data->NumberOfPlayers <= 0){ + int Ret = QueryManagerConnection->createPlayerlist(Data->NumberOfPlayers, + NULL, NULL, NULL, &NewRecord); + if(Ret != 0){ + error("ProcessPlayerlistOrder: Anfrage fehlgeschlagen (1).\n"); + } + }else{ + const char **Names = (const char**)alloca(Data->NumberOfPlayers * sizeof(const char*)); + int *Levels = (int*)alloca(Data->NumberOfPlayers * sizeof(int)); + char (*Professions)[30] = (char(*)[30])alloca(Data->NumberOfPlayers * 30); + for(int PlayerNr = 0; PlayerNr < Data->NumberOfPlayers; PlayerNr += 1){ + Names[PlayerNr] = &Data->PlayerNames[PlayerNr * 30]; + Levels[PlayerNr] = Data->PlayerLevels[PlayerNr]; + GetProfessionName(Professions[PlayerNr], + Data->PlayerProfessions[PlayerNr], false, true); + } + + int Ret = QueryManagerConnection->createPlayerlist(Data->NumberOfPlayers, + Names, Levels, Professions, &NewRecord); + if(Ret != 0){ + error("ProcessPlayerlistOrder: Anfrage fehlgeschlagen (2).\n"); + } + } + + if(NewRecord){ + BroadcastReply("New record: %d players are logged in.", Data->NumberOfPlayers); + } + + delete[] Data->PlayerNames; + delete[] Data->PlayerLevels; + delete[] Data->PlayerProfessions; + delete Data; +} + +void ProcessKillStatisticsOrder(TKillStatisticsOrderData *Data){ + if(Data == NULL){ + error("ProcessKillStatisticsOrder: Keine Daten übergeben.\n"); + return; + } + + const char **RaceNames = (const char**)alloca(Data->NumberOfRaces * sizeof(const char*)); + int *KilledPlayers = (int*)alloca(Data->NumberOfRaces * sizeof(int)); + int *KilledCreatures = (int*)alloca(Data->NumberOfRaces * sizeof(int)); + for(int RaceNr = 0; RaceNr < Data->NumberOfRaces; RaceNr += 1){ + RaceNames[RaceNr] = &Data->RaceNames[RaceNr * 30]; + KilledPlayers[RaceNr] = Data->KilledPlayers[RaceNr]; + KilledCreatures[RaceNr] = Data->KilledCreatures[RaceNr]; + } + + int Ret = QueryManagerConnection->logKilledCreatures(Data->NumberOfRaces, + RaceNames, KilledPlayers, KilledCreatures); + if(Ret != 0){ + error("ProcessKillStatisticsOrder: Anfrage fehlgeschlagen.\n"); + } + + delete[] Data->RaceNames; + delete[] Data->KilledPlayers; + delete[] Data->KilledCreatures; + delete Data; +} + +static const char *GetStatementOutputChannel(int Mode, int Channel){ + const char *Result; + switch(Mode){ + case TALK_SAY: Result = "Say"; break; + case TALK_WHISPER: Result = "Whisper"; break; + case TALK_YELL: Result = "Yell"; break; + case TALK_PRIVATE_MESSAGE: Result = "Private Message"; break; + case TALK_GAMEMASTER_REQUEST: Result = "Gamemaster Request"; break; + case TALK_GAMEMASTER_ANSWER: Result = "Gamemaster Answer"; break; + case TALK_PLAYER_ANSWER: Result = "Player Answer"; break; + case TALK_GAMEMASTER_BROADCAST: Result = "Broadcast"; break; + case TALK_GAMEMASTER_MESSAGE: Result = "Private Message"; break; + + case TALK_CHANNEL_CALL: + case TALK_GAMEMASTER_CHANNELCALL: + case TALK_HIGHLIGHT_CHANNELCALL:{ + switch(Channel){ + case CHANNEL_GUILD: Result = "Guild Channel"; break; + case CHANNEL_GAMEMASTER: Result = "Gamemaster Channel"; break; + case CHANNEL_TUTOR: Result = "Tutor Channel"; break; + case CHANNEL_GAMECHAT: Result = "Game Chat"; break; + case CHANNEL_TRADE: Result = "Trade Channel"; break; + case CHANNEL_RLCHAT: Result = "Reallife Chat"; break; + case CHANNEL_HELP: Result = "Help Channel"; break; + default: Result = "Private Chat Channel"; break; + } + break; + } + + default:{ + error("ProcessPunishmentOrder: Ungültiger Modus %d.\n", Mode); + Result = "Unknown"; + break; + } + } + + return Result; +} + +void ProcessPunishmentOrder(TPunishmentOrderData *Data){ + // TODO(fusion): I feel this it too complex for handling a simple banishment system. + if(Data == NULL){ + error("ProcessPunishmentOrder: Keine Daten übergeben.\n"); + return; + } + + bool Ok = true; + const char *Reason = GetBanishmentReason(Data->Reason); + uint32 BanishmentID = 0; + + if(Ok && Data->Action == 0){ + int Ret = QueryManagerConnection->setNotation(Data->GamemasterID, + Data->CriminalName, Data->CriminalIPAddress, Reason, + Data->Comment, &BanishmentID); + switch(Ret){ + case 0:{ + DirectReply(Data->GamemasterID, "Notation for player %s inserted.", Data->CriminalName); + Log("banish", "%s notiert zu %s: %s.\n", Data->GamemasterName, Data->CriminalName, Data->Comment); + break; + } + + case 1:{ + DirectReply(Data->GamemasterID, "A player with this name does not exist. Perhaps he/she has been renamed?"); + Ok = false; + break; + } + + case 2:{ + DirectReply(Data->GamemasterID, "You may not report a god or gamemaster."); + Ok = false; + break; + } + } + } + + if(Ok && (Data->Action == 1 || Data->Action == 3 || Data->Action == 5)){ + int Ret = QueryManagerConnection->setNamelock(Data->GamemasterID, + Data->CriminalName, Data->CriminalIPAddress, Reason, + Data->Comment); + switch(Ret){ + case 0:{ + DirectReply(Data->GamemasterID, "Player %s reported for renaming.", Data->CriminalName); + Log("banish", "%s meldet %s zur Namensänderung.\n", Data->GamemasterName, Data->CriminalName); + break; + } + + case 3:{ + DirectReply(Data->GamemasterID, "This player has already been reported."); + break; + } + + case 1:{ + DirectReply(Data->GamemasterID, "A player with this name does not exist. Perhaps he/she has already been renamed?"); + Ok = false; + break; + } + + case 2: + case 4:{ + DirectReply(Data->GamemasterID, "This name has already been approved."); + Ok = false; + break; + } + } + } + + if(Ok && (Data->Action == 2 || Data->Action == 3 || Data->Action == 4 || Data->Action == 5)){ + int Days; + bool FinalWarning = (Data->Action == 4 || Data->Action == 5); + int Ret = QueryManagerConnection->banishAccount(Data->GamemasterID, + Data->CriminalName, Data->CriminalIPAddress, Reason, + Data->Comment, &FinalWarning, &Days, &BanishmentID); + switch(Ret){ + case 0:{ + if(Days == -1){ + DirectReply(Data->GamemasterID, "Account of player %s banished infinitely.", Data->CriminalName); + }else if(FinalWarning){ + DirectReply(Data->GamemasterID, "Account of player %s banished for %d days with final warning.", Data->CriminalName, Days); + }else{ + DirectReply(Data->GamemasterID, "Account of player %s banished for %d days.", Data->CriminalName, Days); + } + LogoutReply(Data->CriminalName); + Log("banish", "%s verbannt Account von Spieler %s.\n", Data->GamemasterName, Data->CriminalName); + break; + } + + case 3:{ + DirectReply(Data->GamemasterID, "Player %s has already been banished.", Data->CriminalName); + LogoutReply(Data->CriminalName); + break; + } + + case 1:{ + DirectReply(Data->GamemasterID, "A player with this name does not exist. Perhaps he/she has been renamed?"); + Ok = false; + break; + } + + case 2:{ + DirectReply(Data->GamemasterID, "You may not report a god or gamemaster."); + Ok = false; + break; + } + } + } + + if(Ok && Data->StatementID != 0){ + if(Data->NumberOfStatements > 0 && Data->ReportedStatements != NULL){ + uint32 *StatementIDs = (uint32*)alloca(Data->NumberOfStatements * sizeof(uint32)); + int *TimeStamps = (int*)alloca(Data->NumberOfStatements * sizeof(int)); + uint32 *CharacterIDs = (uint32*)alloca(Data->NumberOfStatements * sizeof(uint32)); + char (*Channels)[30] = (char(*)[30])alloca(Data->NumberOfStatements * 30); + char (*Texts)[256] = (char(*)[256])alloca(Data->NumberOfStatements * 256); + for(int StatementNr = 0; StatementNr < Data->NumberOfStatements; StatementNr += 1){ + TReportedStatement *Statement = Data->ReportedStatements->at(StatementNr); + StatementIDs[StatementNr] = Statement->StatementID; + TimeStamps[StatementNr] = Statement->TimeStamp; + CharacterIDs[StatementNr] = Statement->CharacterID; + strcpy(Channels[StatementNr], GetStatementOutputChannel(Statement->Mode, Statement->Channel)); + strcpy(Texts[StatementNr], Statement->Text); + } + + int Ret = QueryManagerConnection->reportStatement(Data->GamemasterID, + Data->CriminalName, Reason, Data->Comment, BanishmentID, + Data->StatementID, Data->NumberOfStatements, StatementIDs, + TimeStamps, CharacterIDs, Channels, Texts); + switch(Ret){ + case 0:{ + if(Data->Action == 6){ + DirectReply(Data->GamemasterID, "Statement of %s reported.", Data->CriminalName); + } + Log("banish", "%s meldet Äußerung von Spieler %s.\n", Data->GamemasterName, Data->CriminalName); + break; + } + + case 1:{ + if(Data->Action == 6){ + DirectReply(Data->GamemasterID, "A player with this name does not exist. Perhaps he/she has been renamed?"); + } + Ok = false; + break; + } + + case 2:{ + if(Data->Action == 6){ + DirectReply(Data->GamemasterID, "Statement has already been reported."); + } + Ok = false; + break; + } + } + }else{ + error("ProcessPunishmentOrder: Statements existieren nicht.\n"); + } + } + + if(Ok && Data->IPBanishment){ + int Ret = QueryManagerConnection->banishIPAddress(Data->GamemasterID, + Data->CriminalName, Data->CriminalIPAddress, Reason, Data->Comment); + switch(Ret){ + case 0:{ + DirectReply(Data->GamemasterID, "IP address of %s banished.", Data->CriminalName); + LogoutReply(Data->CriminalName); + Log("banish", "%s sperrt die IP-Adresse von %s.\n", Data->GamemasterName, Data->CriminalName); + break; + } + + case 1:{ + DirectReply(Data->GamemasterID, "A player with this name does not exist. Perhaps he/she has been renamed?"); + Ok = false; + break; + } + + case 2:{ + DirectReply(Data->GamemasterID, "You may not report a god or gamemaster."); + Ok = false; + break; + } + } + } + + delete Data->ReportedStatements; + delete Data; +} + +void ProcessCharacterDeathOrder(TCharacterDeathOrderData *Data){ + if(Data == NULL){ + error("ProcessCharacterDeathOrder: Keine Daten übergeben.\n"); + return; + } + + int Ret = QueryManagerConnection->logCharacterDeath(Data->CharacterID, + Data->Level, Data->Offender, Data->Remark, Data->Unjustified, + Data->Time); + if(Ret != 0){ + error("ProcessCharacterDeathOrder: Protokollierung fehlgeschlagen.\n"); + } + + delete Data; +} + +void ProcessAddBuddyOrder(TBuddyOrderData *Data){ + if(Data == NULL){ + error("ProcessAddBuddyOrder: Keine Daten übergeben.\n"); + return; + } + + int Ret = QueryManagerConnection->addBuddy(Data->AccountID, Data->Buddy); + if(Ret != 0){ + error("ProcessAddBuddyOrder: Aufnahme fehlgeschlagen.\n"); + } + + delete Data; +} + +void ProcessRemoveBuddyOrder(TBuddyOrderData *Data){ + if(Data == NULL){ + error("ProcessRemoveBuddyOrder: Keine Daten übergeben.\n"); + return; + } + + int Ret = QueryManagerConnection->removeBuddy(Data->AccountID, Data->Buddy); + if(Ret != 0){ + error("ProcessRemoveBuddyOrder: Entfernen fehlgeschlagen.\n"); + } + + delete Data; +} + +void ProcessDecrementIsOnlineOrder(uint32 CharacterID){ + int Ret = QueryManagerConnection->decrementIsOnline(CharacterID); + if(Ret != 0){ + error("ProcessDecrementIsOnlineOrder: Verringerung fehlgeschlagen.\n"); + } +} + +int WriterThreadLoop(void *Unused){ + TWriterThreadOrder Order = {}; + while(true){ + GetOrder(&Order); + if(Order.OrderType == ORDER_TERMINATE){ + break; + } + + switch(Order.OrderType){ + case ORDER_LOGOUT:{ + ProcessLogoutOrder((TLogoutOrderData*)Order.Data); + break; + } + + case ORDER_PLAYERLIST:{ + ProcessPlayerlistOrder((TPlayerlistOrderData*)Order.Data); + break; + } + + case ORDER_KILLSTATISTICS:{ + ProcessKillStatisticsOrder((TKillStatisticsOrderData*)Order.Data); + break; + } + + case ORDER_PUNISHMENT:{ + ProcessPunishmentOrder((TPunishmentOrderData*)Order.Data); + break; + } + + case ORDER_CHARACTERDEATH:{ + ProcessCharacterDeathOrder((TCharacterDeathOrderData*)Order.Data); + break; + } + + case ORDER_ADDBUDDY:{ + ProcessAddBuddyOrder((TBuddyOrderData*)Order.Data); + break; + } + + case ORDER_REMOVEBUDDY:{ + ProcessRemoveBuddyOrder((TBuddyOrderData*)Order.Data); + break; + } + + case ORDER_DECREMENTISONLINE:{ + uint32 CharacterID = (uint32)((uintptr)Order.Data); + ProcessDecrementIsOnlineOrder(CharacterID); + break; + } + + case ORDER_SAVEPLAYERDATA:{ + SavePlayerPoolSlots(); + break; + } + + default:{ + error("WriterThreadLoop: Unbekanntes Kommando %d.\n", Order.OrderType); + break; + } + } + } + + return 0; +} + +// Writer Replies +// ============================================================================= +void InsertReply(TWriterThreadReplyType ReplyType, const void *Data){ + int Replies = (ReplyPointerWrite - ReplyPointerRead); + if(Replies >= NARRAY(ReplyBuffer)){ + error("InsertReply (Writer): Puffer ist voll; Rückmeldung wird verworfen.\n"); + return; + } + + int WritePos = ReplyPointerWrite % NARRAY(ReplyBuffer); + ReplyBuffer[WritePos].ReplyType = ReplyType; + ReplyBuffer[WritePos].Data = Data; + ReplyPointerWrite += 1; +} + +void BroadcastReply(const char *Text, ...){ + if(Text == NULL){ + error("BroadcastReply: Kein Text angegeben.\n"); + return; + } + + TBroadcastReplyData *Data = new TBroadcastReplyData; + + va_list ap; + va_start(ap, Text); + vsnprintf(Data->Message, sizeof(Data->Message), Text, ap); + va_end(ap); + + InsertReply(REPLY_BROADCAST, Data); +} + +void DirectReply(uint32 CharacterID, const char *Text, ...){ + if(CharacterID == 0){ + return; + } + + if(Text == NULL){ + error("SendDirectReply: Kein Text angegeben.\n"); + return; + } + + TDirectReplyData *Data = new TDirectReplyData; + Data->CharacterID = CharacterID; + + va_list ap; + va_start(ap, Text); + vsnprintf(Data->Message, sizeof(Data->Message), Text, ap); + va_end(ap); + + InsertReply(REPLY_DIRECT, Data); +} + +void LogoutReply(const char *PlayerName){ + if(PlayerName == NULL){ + return; + } + + // TODO(fusion): Probably some string dup function? + char *Data = new char[strlen(PlayerName) + 1]; + strcpy(Data, PlayerName); + InsertReply(REPLY_LOGOUT, Data); +} + +bool GetReply(TWriterThreadReply *Reply){ + bool Result = (ReplyPointerRead < ReplyPointerWrite); + if(Result){ + *Reply = ReplyBuffer[ReplyPointerRead % NARRAY(ReplyBuffer)]; + ReplyPointerRead += 1; + } + return Result; +} + +void ProcessBroadcastReply(TBroadcastReplyData *Data){ + if(Data == NULL){ + error("ProcessBroadcastReply: Keine Daten übergeben.\n"); + return; + } + + BroadcastMessage(TALK_STATUS_MESSAGE, Data->Message); + + delete Data; +} + +void ProcessDirectReply(TDirectReplyData *Data){ + if(Data == NULL){ + error("ProcessDirectReply: Keine Daten übergeben.\n"); + return; + } + + TPlayer *Player = GetPlayer(Data->CharacterID); + if(Player != NULL){ + SendMessage(Player->Connection, TALK_INFO_MESSAGE, "%s", Data->Message); + } + + delete Data; +} + +void ProcessLogoutReply(const char *Name){ + if(Name == NULL){ + error("ProcessLogoutReply: Keine Daten übergeben.\n"); + return; + } + + TPlayer *Player = GetPlayer(Name); + if(Player != NULL){ + GraphicalEffect(Player->CrObject, EFFECT_MAGIC_GREEN); + Player->StartLogout(true, true); + } + + delete[] Name; +} + +void ProcessWriterThreadReplies(void){ + TWriterThreadReply Reply = {}; + while(GetReply(&Reply)){ + switch(Reply.ReplyType){ + case REPLY_BROADCAST:{ + ProcessBroadcastReply((TBroadcastReplyData*)Reply.Data); + break; + } + + case REPLY_DIRECT:{ + ProcessDirectReply((TDirectReplyData*)Reply.Data); + break; + } + + case REPLY_LOGOUT:{ + ProcessLogoutReply((const char*)Reply.Data); + break; + } + + default:{ + error("ProcessWriterThreadReplies: Unbekannte Rückmeldung %d.\n", Reply.ReplyType); + break; + } + } + } +} + +// Writer Initialization +// ============================================================================= +void ClearPlayers(void){ + int NumberOfAffectedPlayers; + int Ret = QueryManagerConnection->clearIsOnline(&NumberOfAffectedPlayers); + if(Ret != 0){ + error("ClearPlayers: Kann IsOnline-Flags nicht löschen.\n"); + }else if(NumberOfAffectedPlayers != 0){ + error("ClearPlayers: %d Spieler waren als eingeloggt markiert.\n", + NumberOfAffectedPlayers); + } +} + +void InitWriter(void){ + // TODO(fusion): No idea what's this about. + int QueryBufferSize = std::max(KB(16), MaxPlayers * 66 + 2); + QueryManagerConnection = new TQueryManagerConnection(QueryBufferSize); + if(!QueryManagerConnection->isConnected()){ + throw "cannot connect to query manager"; + } + + ClearPlayers(); + + InitProtocol(); + ProtocolThread = StartThread(ProtocolThreadLoop, NULL, false); + if(ProtocolThread == INVALID_THREAD_HANDLE){ + throw "cannot start protocol thread"; + } + + InitWriterBuffers(); + WriterThread = StartThread(WriterThreadLoop, NULL, false); + if(WriterThread == INVALID_THREAD_HANDLE){ + throw "cannot start writer thread"; + } +} + +void AbortWriter(void){ + // TODO(fusion): The original function was calling `pthread_cancel` with + // an argument of 0 which is probably wrong?. I feel something is missing + // here. + if(WriterThread != INVALID_THREAD_HANDLE){ + pthread_cancel(WriterThread); + WriterThread = INVALID_THREAD_HANDLE; + OrderBufferEmpty.up(); + } +} + +void ExitWriter(void){ + if(ProtocolThread != INVALID_THREAD_HANDLE){ + InsertProtocolOrder("", ""); + JoinThread(ProtocolThread); + ProtocolThread = INVALID_THREAD_HANDLE; + } + + if(WriterThread != INVALID_THREAD_HANDLE){ + TerminateWriterOrder(); + JoinThread(WriterThread); + WriterThread = INVALID_THREAD_HANDLE; + } + + delete QueryManagerConnection; +} diff --git a/src/writer.hh b/src/writer.hh new file mode 100644 index 0000000..8c87c0f --- /dev/null +++ b/src/writer.hh @@ -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 *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 *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_ -- cgit v1.2.3