aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-06-30 19:23:09 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-06-30 19:23:09 -0300
commit6c8aa85b8b578db03a8c5f0dc0b7e80605592d45 (patch)
tree6734cf3d3c0e318a139f7d15d9a524c423833e22
parentc09d30cb144ce421ef0e1a786d2965f9abcde0aa (diff)
downloadgame-6c8aa85b8b578db03a8c5f0dc0b7e80605592d45.tar.gz
game-6c8aa85b8b578db03a8c5f0dc0b7e80605592d45.zip
`writer.cc`
-rw-r--r--Makefile8
-rw-r--r--TODO.md5
-rw-r--r--reference/enums.hh20
-rw-r--r--reference/game.c2236
-rw-r--r--reference/types.hh71
-rw-r--r--src/communication.cc3
-rw-r--r--src/communication.hh3
-rw-r--r--src/connections.cc3
-rw-r--r--src/cract.cc1
-rw-r--r--src/crmain.cc3
-rw-r--r--src/crnonpl.cc4
-rw-r--r--src/crplayer.cc2
-rw-r--r--src/houses.cc5
-rw-r--r--src/houses.hh6
-rw-r--r--src/info.cc3
-rw-r--r--src/magic.cc4
-rw-r--r--src/magic.hh1
-rw-r--r--src/main.cc12
-rw-r--r--src/map.cc1
-rw-r--r--src/moveuse.cc3
-rw-r--r--src/operate.cc2
-rw-r--r--src/operate.hh10
-rw-r--r--src/query.hh29
-rw-r--r--src/receiving.cc4
-rw-r--r--src/sending.cc4
-rw-r--r--src/shm.cc3
-rw-r--r--src/stubs.hh36
-rw-r--r--src/writer.cc1045
-rw-r--r--src/writer.hh155
29 files changed, 1279 insertions, 2403 deletions
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<TReportedStatement> *ReportedStatements;
- ulong StatementID;
- bool IPBanishment;
-};
-
-struct TLogoutOrderData {
- ulong CharacterID;
- int Level;
- int Profession;
- time_t LastLoginTime;
- int TutorActivities;
- char Residence[30];
-};
-
-struct TCharacterDeathOrderData {
- ulong CharacterID;
- int Level;
- ulong Offender;
- char Remark[30];
- bool Unjustified;
- time_t Time;
-};
-
struct TNameLockOrderData {
ulong GamemasterID;
char GamemasterName[30];
@@ -86,30 +39,6 @@ struct TNotationOrderData {
char Comment[200];
};
-struct TProtocolThreadOrder {
- char ProtocolName[20];
- char Text[256];
-};
-
-struct TPlayerlistOrderData {
- int NumberOfPlayers;
- char *PlayerNames;
- int *PlayerLevels;
- int *PlayerProfessions;
-};
-
-struct TBuddyOrderData {
- ulong AccountID;
- ulong Buddy;
-};
-
-struct TKillStatisticsOrderData {
- int NumberOfRaces;
- char *RaceNames;
- int *KilledPlayers;
- int *KilledCreatures;
-};
-
struct TReaderThreadOrder {
enum TReaderThreadOrderType OrderType;
int SectorX;
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 <arpa/inet.h>
#include <fcntl.h>
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 <arpa/inet.h>
#include <netinet/in.h>
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 <dirent.h>
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 <dirent.h>
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<THelpDepot> 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 <fstream>
#include <sstream>
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 <signal.h>
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 <signal.h>
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 <sys/shm.h>
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<TReportedStatement> *ReportedStatements, uint32 StatementID,
- bool IPBanishment);
extern void SavePlayerData(TPlayerData *Slot);
extern bool LoadPlayerData(TPlayerData *Slot);
extern bool PlayerDataExists(uint32 CharacterID);
extern void SavePlayerDataOrder(void);
-extern void ShowGuestList(uint16 HouseID, TPlayer *Player, char *Buffer);
-extern void ShowSubownerList(uint16 HouseID, TPlayer *Player, char *Buffer);
-extern void ShowNameDoor(Object Door, TPlayer *Player, char *Buffer);
#endif //TIBIA_STUBS_HH_
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<TReportedStatement> *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<int>(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<TReportedStatement> *ReportedStatements;
+ uint32 StatementID;
+ bool IPBanishment;
+};
+
+struct TCharacterDeathOrderData{
+ uint32 CharacterID;
+ int Level;
+ uint32 Offender;
+ char Remark[30];
+ bool Unjustified;
+ time_t Time;
+};
+
+struct TBuddyOrderData{
+ uint32 AccountID;
+ uint32 Buddy;
+};
+
+void InitProtocol(void);
+void InsertProtocolOrder(const char *ProtocolName, const char *Text);
+void GetProtocolOrder(TProtocolThreadOrder *Order);
+void WriteProtocol(const char *ProtocolName, const char *Text);
+int ProtocolThreadLoop(void *Unused);
+void InitLog(const char *ProtocolName);
+void Log(const char *ProtocolName, const char *Text, ...) ATTR_PRINTF(2, 3);
+
+void InitWriterBuffers(void);
+int GetOrderBufferSpace(void);
+void InsertOrder(TWriterThreadOrderType OrderType, const void *Data);
+void GetOrder(TWriterThreadOrder *Order);
+void TerminateWriterOrder(void);
+void LogoutOrder(TPlayer *Player);
+void PlayerlistOrder(int NumberOfPlayers, const char *PlayerNames,
+ int *PlayerLevels, int *PlayerProfessions);
+void KillStatisticsOrder(int NumberOfRaces, const char *RaceNames,
+ int *KilledPlayers, int *KilledCreatures);
+void PunishmentOrder(TCreature *Gamemaster, const char *Name, const char *IPAddress,
+ int Reason, int Action, const char *Comment, int NumberOfStatements,
+ vector<TReportedStatement> *ReportedStatements, uint32 StatementID,
+ bool IPBanishment);
+void CharacterDeathOrder(TCreature *Creature, int OldLevel,
+ uint32 OffenderID, const char *Remark, bool Unjustified);
+void AddBuddyOrder(TCreature *Creature, uint32 BuddyID);
+void RemoveBuddyOrder(TCreature *Creature, uint32 BuddyID);
+void DecrementIsOnlineOrder(uint32 CharacterID);
+void SavePlayerDataOrder(void);
+void ProcessLogoutOrder(TLogoutOrderData *Data);
+void ProcessPlayerlistOrder(TPlayerlistOrderData *Data);
+void ProcessKillStatisticsOrder(TKillStatisticsOrderData *Data);
+void ProcessPunishmentOrder(TPunishmentOrderData *Data);
+void ProcessCharacterDeathOrder(TCharacterDeathOrderData *Data);
+void ProcessAddBuddyOrder(TBuddyOrderData *Data);
+void ProcessRemoveBuddyOrder(TBuddyOrderData *Data);
+void ProcessDecrementIsOnlineOrder(uint32 CharacterID);
+int WriterThreadLoop(void *Unused);
+
+void InsertReply(TWriterThreadReplyType ReplyType, const void *Data);
+void BroadcastReply(const char *Text, ...) ATTR_PRINTF(1, 2);
+void DirectReply(uint32 CharacterID, const char *Text, ...) ATTR_PRINTF(2, 3);
+void LogoutReply(const char *PlayerName);
+bool GetReply(TWriterThreadReply *Reply);
+void ProcessBroadcastReply(TBroadcastReplyData *Data);
+void ProcessDirectReply(TDirectReplyData *Data);
+void ProcessLogoutReply(const char *Name);
+void ProcessWriterThreadReplies(void);
+
+void ClearPlayers(void);
+void InitWriter(void);
+void AbortWriter(void);
+void ExitWriter(void);
+
+#endif //TIBIA_WRITER_HH_