aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-07-01 20:41:31 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-07-01 20:41:31 -0300
commitaaf198773fd8e041b0976cc0682e83f8acf394d0 (patch)
tree5fcf0b6b1b927dda842ae98b041463cdafd14126
parent11ae3d0e42293d01b4d729ed5b6fceb8f0ec3fa5 (diff)
downloadgame-aaf198773fd8e041b0976cc0682e83f8acf394d0.tar.gz
game-aaf198773fd8e041b0976cc0682e83f8acf394d0.zip
beginning of `query.cc`
-rw-r--r--Makefile2
-rw-r--r--reference/game.c799
-rw-r--r--src/communication.cc10
-rw-r--r--src/crplayer.cc2
-rw-r--r--src/query.cc382
-rw-r--r--src/query.hh39
-rw-r--r--src/stubs.hh16
7 files changed, 422 insertions, 828 deletions
diff --git a/Makefile b/Makefile
index 41c5495..c522f85 100644
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,7 @@ 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)/reader.hh $(SRCDIR)/script.hh $(SRCDIR)/stubs.hh $(SRCDIR)/threads.hh $(SRCDIR)/writer.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)/reader.hh $(SRCDIR)/script.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)/reader.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 $@ $^
diff --git a/reference/game.c b/reference/game.c
index db75c28..9d2bd20 100644
--- a/reference/game.c
+++ b/reference/game.c
@@ -1,805 +1,6 @@
// QUERY.CC
//==============================================================================
-void SetQueryManagerLoginData(int Type,char *Data)
-
-{
- ApplicationType = Type;
- if (Data == (char *)0x0) {
- LoginData[0] = '\0';
- }
- else {
- strncpy(LoginData,Data,0x1e);
- }
- return;
-}
-
-
-
-// DWARF original prototype: void TQueryManagerConnection(TQueryManagerConnection * this, int
-// QueryBufferSize)
-
-void __thiscall
-TQueryManagerConnection::TQueryManagerConnection(TQueryManagerConnection *this,int QueryBufferSize)
-
-{
- uint uVar1;
- uchar *puVar2;
- uint *puVar3;
- sockaddr *__addr;
- socklen_t in_stack_ffffffe0;
- uint local_1c [4];
-
- local_1c[3] = 0x4000;
- puVar3 = local_1c + 3;
- if (0x3fff < QueryBufferSize) {
- puVar3 = (uint *)&QueryBufferSize;
- }
- puVar2 = (uchar *)operator_new__(*puVar3);
- this->Buffer = puVar2;
- local_1c[2] = 0x4000;
- puVar3 = local_1c + 2;
- if (0x3fff < QueryBufferSize) {
- puVar3 = (uint *)&QueryBufferSize;
- }
- TReadBuffer::TReadBuffer(&this->ReadBuffer,this->Buffer,*puVar3);
- local_1c[1] = 0x4000;
- puVar3 = local_1c + 1;
- if (0x3fff < QueryBufferSize) {
- puVar3 = (uint *)&QueryBufferSize;
- }
- __addr = (sockaddr *)*puVar3;
- puVar2 = this->Buffer;
- TWriteBuffer::TWriteBuffer(&this->WriteBuffer,puVar2,(int)__addr);
- local_1c[0] = 0x4000;
- puVar3 = local_1c;
- if (0x3fff < QueryBufferSize) {
- puVar3 = (uint *)&QueryBufferSize;
- }
- uVar1 = *puVar3;
- this->Socket = -1;
- this->QueryOk = false;
- this->BufferSize = uVar1;
- connect(this,(int)puVar2,__addr,in_stack_ffffffe0);
- return;
-}
-
-
-
-// DWARF original prototype: void TQueryManagerConnection(TQueryManagerConnection * this, int
-// QueryBufferSize)
-
-void __thiscall
-TQueryManagerConnection::TQueryManagerConnection(TQueryManagerConnection *this,int QueryBufferSize)
-
-{
- uint uVar1;
- uchar *puVar2;
- uint *puVar3;
- sockaddr *__addr;
- socklen_t in_stack_ffffffe0;
- uint local_1c [4];
-
- local_1c[3] = 0x4000;
- puVar3 = local_1c + 3;
- if (0x3fff < QueryBufferSize) {
- puVar3 = (uint *)&QueryBufferSize;
- }
- puVar2 = (uchar *)operator_new__(*puVar3);
- this->Buffer = puVar2;
- local_1c[2] = 0x4000;
- puVar3 = local_1c + 2;
- if (0x3fff < QueryBufferSize) {
- puVar3 = (uint *)&QueryBufferSize;
- }
- TReadBuffer::TReadBuffer(&this->ReadBuffer,this->Buffer,*puVar3);
- local_1c[1] = 0x4000;
- puVar3 = local_1c + 1;
- if (0x3fff < QueryBufferSize) {
- puVar3 = (uint *)&QueryBufferSize;
- }
- __addr = (sockaddr *)*puVar3;
- puVar2 = this->Buffer;
- TWriteBuffer::TWriteBuffer(&this->WriteBuffer,puVar2,(int)__addr);
- local_1c[0] = 0x4000;
- puVar3 = local_1c;
- if (0x3fff < QueryBufferSize) {
- puVar3 = (uint *)&QueryBufferSize;
- }
- uVar1 = *puVar3;
- this->Socket = -1;
- this->QueryOk = false;
- this->BufferSize = uVar1;
- connect(this,(int)puVar2,__addr,in_stack_ffffffe0);
- return;
-}
-
-
-
-// DWARF original prototype: void ~TQueryManagerConnection(TQueryManagerConnection * this, int
-// __in_chrg)
-
-void __thiscall
-TQueryManagerConnection::~TQueryManagerConnection(TQueryManagerConnection *this,int __in_chrg)
-
-{
- int iVar1;
- int *piVar2;
-
- if (-1 < this->Socket) {
- iVar1 = close(this->Socket);
- if (iVar1 < 0) {
- piVar2 = __errno_location();
- error(&DAT_0810dc00,*piVar2);
- }
- this->Socket = -1;
- }
- if (this->Buffer == (uchar *)0x0) {
- return;
- }
- operator_delete__(this->Buffer);
- return;
-}
-
-
-
-// DWARF original prototype: void ~TQueryManagerConnection(TQueryManagerConnection * this, int
-// __in_chrg)
-
-void __thiscall
-TQueryManagerConnection::~TQueryManagerConnection(TQueryManagerConnection *this,int __in_chrg)
-
-{
- int iVar1;
- int *piVar2;
-
- if (-1 < this->Socket) {
- iVar1 = close(this->Socket);
- if (iVar1 < 0) {
- piVar2 = __errno_location();
- error(&DAT_0810dc00,*piVar2);
- }
- this->Socket = -1;
- }
- if (this->Buffer == (uchar *)0x0) {
- return;
- }
- operator_delete__(this->Buffer);
- return;
-}
-
-
-
-// DWARF original prototype: void connect(TQueryManagerConnection * this)
-
-int __thiscall
-TQueryManagerConnection::connect
- (TQueryManagerConnection *this,int __fd,sockaddr *__addr,socklen_t __len)
-
-{
- ushort uVar1;
- int Result;
- int iVar2;
- int *piVar3;
- char *__cp;
- TWriteBuffer *this_00;
- int Try;
- int iVar4;
- int iVar5;
- hostent *local_858;
- hostent *HostEntAddr;
- int ErrorCode;
- char local_84c [4];
- char Buffer [2048];
- hostent HostEnt;
- undefined1 local_2c [4];
- sockaddr_in QueryManagerAddress;
-
- iVar4 = 0;
- if (0 < NumberOfQueryManagers) {
- do {
- local_2c._0_2_ = 0;
- local_2c[2] = '\0';
- local_2c[3] = '\0';
- QueryManagerAddress.sin_family = 0;
- QueryManagerAddress.sin_port = 0;
- QueryManagerAddress.sin_addr.s_addr = 0;
- QueryManagerAddress.sin_zero[0] = '\0';
- QueryManagerAddress.sin_zero[1] = '\0';
- QueryManagerAddress.sin_zero[2] = '\0';
- QueryManagerAddress.sin_zero[3] = '\0';
- QueryManagerAddress._0_4_ = inet_addr(QUERY_MANAGER[iVar4].Host);
- if (QueryManagerAddress._0_4_ == 0xffffffff) {
- HostEntAddr = (hostent *)0x0;
- iVar2 = gethostbyname_r(QUERY_MANAGER[iVar4].Host,(hostent *)(Buffer + 0x7fc),
- local_84c,0x800,&local_858,(int *)&HostEntAddr);
- if ((iVar2 == 0) && (local_858 != (hostent *)0x0)) {
- __cp = inet_ntoa((in_addr)*(in_addr_t *)*local_858->h_addr_list);
- QueryManagerAddress._0_4_ = inet_addr(__cp);
- goto LAB_080e0505;
- }
-LAB_080e06c8:
- print();
- }
- else {
-LAB_080e0505:
- iVar2 = socket(2,1,0);
- this->Socket = iVar2;
- if (iVar2 < 0) goto LAB_080e06c8;
- uVar1 = (ushort)QUERY_MANAGER[iVar4].Port;
- iVar5 = 0x10;
- ErrorCode._2_2_ = uVar1 >> 8 | uVar1 << 8;
- local_2c._2_2_ = ErrorCode._2_2_;
- local_2c._0_2_ = 2;
- iVar2 = ::connect(this->Socket,(sockaddr *)local_2c,0x10);
- if (iVar2 < 0) {
- print();
- }
- else {
- this_00 = &this->WriteBuffer;
- this->QueryOk = true;
- (this->WriteBuffer).Position = 0;
- // try { // try from 080e0595 to 080e05a9 has its CatchHandler @ 080e0754
- TWriteBuffer::writeWord(this_00,0);
- TWriteBuffer::writeByte(this_00,'\0');
- // try { // try from 080e05b8 to 080e05bc has its CatchHandler @ 080e0791
- TWriteBuffer::writeByte(this_00,(uchar)ApplicationType);
- // try { // try from 080e05d1 to 080e05d5 has its CatchHandler @ 080e07c1
- TWriteStream::writeString
- (&this_00->super_TWriteStream,QUERY_MANAGER[iVar4].Password);
- if (ApplicationType == 1) {
- // try { // try from 080e069d to 080e06a1 has its CatchHandler @ 080e07f1
- TWriteStream::writeString(&this_00->super_TWriteStream,LoginData);
- }
- iVar5 = executeQuery(this,0x1e,false);
- if (iVar5 == 0) {
- return 0;
- }
- print();
- }
- if (-1 < this->Socket) {
- iVar2 = close(this->Socket);
- if (iVar2 < 0) {
- piVar3 = __errno_location();
- error(&DAT_0810dc00,*piVar3,iVar5);
- }
- this->Socket = -1;
- }
- }
- iVar4 = iVar4 + 1;
- } while (iVar4 < NumberOfQueryManagers);
- }
- print();
- this->Socket = -1;
- return (int)this;
-}
-
-
-
-// DWARF original prototype: void disconnect(TQueryManagerConnection * this)
-
-void __thiscall TQueryManagerConnection::disconnect(TQueryManagerConnection *this)
-
-{
- int iVar1;
- int *piVar2;
-
- if (-1 < this->Socket) {
- iVar1 = close(this->Socket);
- if (iVar1 < 0) {
- piVar2 = __errno_location();
- error(&DAT_0810dc00,*piVar2);
- }
- this->Socket = -1;
- }
- return;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: Chances
-// DWARF original prototype: int write(TQueryManagerConnection * this, uchar * Buffer, int Size)
-
-ssize_t __thiscall
-TQueryManagerConnection::write(TQueryManagerConnection *this,int __fd,void *__buf,size_t __n)
-
-{
- ssize_t sVar1;
- int *piVar2;
- int nwritten;
- int nleft;
- void *__n_00;
- int local_14;
- int Chances;
-
- local_14 = 0x32;
- __n_00 = __buf;
- if (0 < (int)__buf) {
- do {
- sVar1 = ::write(this->Socket,(void *)__fd,(size_t)__n_00);
- if (((sVar1 == -1) && (piVar2 = __errno_location(), *piVar2 == 0xb)) && (0 < local_14))
- {
- DelayThread(0,100000);
- local_14 = local_14 + -1;
- }
- else {
- if (sVar1 < 1) {
- return sVar1;
- }
- __n_00 = (void *)((int)__n_00 - sVar1);
- __fd = __fd + sVar1;
- }
- } while (0 < (int)__n_00);
- }
- return (int)__buf - (int)__n_00;
-}
-
-
-
-// DWARF original prototype: int read(TQueryManagerConnection * this, uchar * Buffer, int Size, int
-// Timeout)
-
-ssize_t __thiscall
-TQueryManagerConnection::read(TQueryManagerConnection *this,int __fd,void *__buf,size_t __nbytes)
-
-{
- int iVar1;
- ssize_t sVar2;
- int *piVar3;
- int nread;
- int nleft;
- void *__nbytes_00;
- int local_20;
- int Chances;
- pollfd ufds;
-
- local_20 = 0x32;
- __nbytes_00 = __buf;
- if (0 < (int)__buf) {
- do {
- Chances = this->Socket;
- ufds.fd._0_2_ = 1;
- ufds.fd._2_2_ = 0;
- iVar1 = poll((pollfd *)&Chances,1,__nbytes * 1000);
- if (iVar1 < 1) {
- return -2;
- }
- sVar2 = ::read(this->Socket,(void *)__fd,(size_t)__nbytes_00);
- if (sVar2 == 0) break;
- if (sVar2 < 0) {
- piVar3 = __errno_location();
- if (*piVar3 != 4) {
- if (*piVar3 != 0xb) {
- return sVar2;
- }
- if (__nbytes_00 == __buf) {
- return sVar2;
- }
- if (local_20 == 0) {
- return sVar2;
- }
- local_20 = local_20 + -1;
- DelayThread(0,100000);
- }
- }
- else {
- __nbytes_00 = (void *)((int)__nbytes_00 - sVar2);
- __fd = __fd + sVar2;
- }
- } while (0 < (int)__nbytes_00);
- }
- return (int)__buf - (int)__nbytes_00;
-}
-
-
-
-// DWARF original prototype: void prepareQuery(TQueryManagerConnection * this, int QueryType)
-
-void __thiscall TQueryManagerConnection::prepareQuery(TQueryManagerConnection *this,int QueryType)
-
-{
- this->QueryOk = true;
- (this->WriteBuffer).Position = 0;
- // try { // try from 080e0a08 to 080e0a1c has its CatchHandler @ 080e0a27
- TWriteBuffer::writeWord(&this->WriteBuffer,0);
- TWriteBuffer::writeByte(&this->WriteBuffer,(uchar)QueryType);
- return;
-}
-
-
-
-// DWARF original prototype: void sendFlag(TQueryManagerConnection * this, bool f)
-
-void __thiscall TQueryManagerConnection::sendFlag(TQueryManagerConnection *this,bool f)
-
-{
- TWriteBuffer::writeByte(&this->WriteBuffer,f);
- return;
-}
-
-
-
-// DWARF original prototype: void sendByte(TQueryManagerConnection * this, uchar b)
-
-void __thiscall TQueryManagerConnection::sendByte(TQueryManagerConnection *this,uchar b)
-
-{
- // try { // try from 080e0a9d to 080e0aa1 has its CatchHandler @ 080e0ab0
- TWriteBuffer::writeByte(&this->WriteBuffer,b);
- return;
-}
-
-
-
-// DWARF original prototype: void sendWord(TQueryManagerConnection * this, ushort w)
-
-void __thiscall TQueryManagerConnection::sendWord(TQueryManagerConnection *this,ushort w)
-
-{
- // try { // try from 080e0b0d to 080e0b11 has its CatchHandler @ 080e0b20
- TWriteBuffer::writeWord(&this->WriteBuffer,w);
- return;
-}
-
-
-
-// DWARF original prototype: void sendQuad(TQueryManagerConnection * this, ulong q)
-
-void __thiscall TQueryManagerConnection::sendQuad(TQueryManagerConnection *this,ulong q)
-
-{
- // try { // try from 080e0b7c to 080e0b80 has its CatchHandler @ 080e0b90
- TWriteBuffer::writeQuad(&this->WriteBuffer,q);
- return;
-}
-
-
-
-// DWARF original prototype: void sendString(TQueryManagerConnection * this, char * s)
-
-void __thiscall TQueryManagerConnection::sendString(TQueryManagerConnection *this,char *s)
-
-{
- // try { // try from 080e0bec to 080e0bf0 has its CatchHandler @ 080e0c00
- TWriteStream::writeString(&(this->WriteBuffer).super_TWriteStream,s);
- return;
-}
-
-
-
-// DWARF original prototype: void sendBytes(TQueryManagerConnection * this, uchar * Buffer, int
-// Count)
-
-void __thiscall TQueryManagerConnection::sendBytes(TQueryManagerConnection *this)
-
-{
- uchar *in_stack_00000008;
- int in_stack_0000000c;
-
- // try { // try from 080e0c63 to 080e0c67 has its CatchHandler @ 080e0c72
- TWriteBuffer::writeBytes(&this->WriteBuffer,in_stack_00000008,in_stack_0000000c);
- return;
-}
-
-
-
-// DWARF original prototype: bool getFlag(TQueryManagerConnection * this)
-
-bool __thiscall TQueryManagerConnection::getFlag(TQueryManagerConnection *this)
-
-{
- uchar uVar1;
-
- // try { // try from 080e0cc2 to 080e0cc6 has its CatchHandler @ 080e0cd8
- uVar1 = TReadBuffer::readByte(&this->ReadBuffer);
- return uVar1 != '\0';
-}
-
-
-
-// DWARF original prototype: uchar getByte(TQueryManagerConnection * this)
-
-uchar __thiscall TQueryManagerConnection::getByte(TQueryManagerConnection *this)
-
-{
- uchar uVar1;
-
- // try { // try from 080e0d22 to 080e0d26 has its CatchHandler @ 080e0d31
- uVar1 = TReadBuffer::readByte(&this->ReadBuffer);
- return uVar1;
-}
-
-
-
-// DWARF original prototype: ushort getWord(TQueryManagerConnection * this)
-
-ushort __thiscall TQueryManagerConnection::getWord(TQueryManagerConnection *this)
-
-{
- ushort uVar1;
-
- // try { // try from 080e0d82 to 080e0d86 has its CatchHandler @ 080e0d91
- uVar1 = TReadBuffer::readWord(&this->ReadBuffer);
- return uVar1;
-}
-
-
-
-// DWARF original prototype: ulong getQuad(TQueryManagerConnection * this)
-
-ulong __thiscall TQueryManagerConnection::getQuad(TQueryManagerConnection *this)
-
-{
- ulong uVar1;
-
- // try { // try from 080e0de2 to 080e0de6 has its CatchHandler @ 080e0df0
- uVar1 = TReadBuffer::readQuad(&this->ReadBuffer);
- return uVar1;
-}
-
-
-
-// DWARF original prototype: void getString(TQueryManagerConnection * this, char * Buffer, int
-// MaxLength)
-
-void __thiscall
-TQueryManagerConnection::getString(TQueryManagerConnection *this,char *Buffer,int MaxLength)
-
-{
- // try { // try from 080e0e53 to 080e0e57 has its CatchHandler @ 080e0e62
- TReadStream::readString(&(this->ReadBuffer).super_TReadStream,Buffer,MaxLength);
- return;
-}
-
-
-
-// DWARF original prototype: void getBytes(TQueryManagerConnection * this, uchar * Buffer, int
-// Count)
-
-void __thiscall TQueryManagerConnection::getBytes(TQueryManagerConnection *this)
-
-{
- uchar *in_stack_00000008;
- int in_stack_0000000c;
-
- // try { // try from 080e0ec0 to 080e0ec4 has its CatchHandler @ 080e0ed0
- TReadBuffer::readBytes(&this->ReadBuffer,in_stack_00000008,in_stack_0000000c);
- return;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: Help
-// DWARF original prototype: int executeQuery(TQueryManagerConnection * this, int Timeout, bool
-// AutoReconnect)
-
-int __thiscall
-TQueryManagerConnection::executeQuery(TQueryManagerConnection *this,int Timeout,bool AutoReconnect)
-
-{
- byte bVar1;
- void *pvVar2;
- sockaddr *psVar3;
- ssize_t sVar4;
- int iVar5;
- void *pvVar6;
- int Result;
- TWriteBuffer *this_00;
- int Size;
- int DataSize;
- sockaddr *__buf;
- undefined4 uStackY_40;
- char *Text;
- uchar *puVar7;
- socklen_t in_stack_ffffffd0;
- undefined1 auStack_2c [11];
- char local_21;
- char *pcStack_20;
- bool SecondChance;
- char local_19;
- byte local_18;
- undefined1 local_17 [2];
- bool AutoReconnect_local;
- uchar Help2 [4];
- uchar Help [2];
-
- this_00 = &this->WriteBuffer;
- local_19 = AutoReconnect;
- __buf = (sockaddr *)(this->WriteBuffer).Position;
- (this->WriteBuffer).Position = 0;
- if ((int)__buf < 0xffff) {
- // try { // try from 080e1376 to 080e137a has its CatchHandler @ 080e13ed
- uStackY_40 = 0x80e137b;
- TWriteBuffer::writeWord(this_00,(short)__buf - 2);
- }
- else {
- if (this->BufferSize < (int)(__buf->sa_data + 2)) {
- Text = "TQueryManagerConnection::executeQuery: Puffer zu klein.\n";
- goto LAB_080e0f4d;
- }
- pcStack_20 = __buf[-1].sa_data + 0xc;
- uStackY_40 = 0x80e0f86;
- memmove(this->Buffer + 6,this->Buffer + 2,(size_t)pcStack_20);
- // try { // try from 080e0f91 to 080e0f95 has its CatchHandler @ 080e1380
- uStackY_40 = 0x80e0f96;
- TWriteBuffer::writeWord(this_00,0xffff);
- // try { // try from 080e0fa0 to 080e0fa4 has its CatchHandler @ 080e13bd
- uStackY_40 = 0x80e0fa5;
- TWriteBuffer::writeQuad(this_00,(ulong)pcStack_20);
- __buf = (sockaddr *)(__buf->sa_data + 2);
- }
- local_21 = '\x01';
- if (this->QueryOk != false) {
- do {
- if (this->Socket < 0) {
- if (local_19 == '\0') {
- return 3;
- }
- if ((int)__buf < 0x4000) {
- iVar5 = -((uint)(__buf->sa_data + 0xd) & 0xfffffff0);
- puVar7 = this->Buffer;
- *(sockaddr **)(Help2 + iVar5 + -0x20) = __buf;
- *(uchar **)(&stack0xffffffc8 + iVar5) = puVar7;
- *(undefined1 **)(&stack0xffffffc4 + iVar5) = auStack_2c + iVar5;
- *(undefined4 *)((int)&uStackY_40 + iVar5) = 0x80e1335;
- memcpy(*(void **)(&stack0xffffffc4 + iVar5),*(void **)(&stack0xffffffc8 + iVar5)
- ,*(size_t *)(Help2 + iVar5 + -0x20));
- *(TQueryManagerConnection **)(&stack0xffffffc4 + iVar5) = this;
- *(undefined4 *)((int)&uStackY_40 + iVar5) = 0x80e1340;
- connect(*(TQueryManagerConnection **)(&stack0xffffffc4 + iVar5),
- *(int *)(&stack0xffffffc8 + iVar5),*(sockaddr **)(Help2 + iVar5 + -0x20)
- ,*(socklen_t *)(&stack0xffffffd0 + iVar5));
- puVar7 = this->Buffer;
- *(undefined1 **)(&stack0xffffffc8 + iVar5) = auStack_2c + iVar5;
- *(sockaddr **)(Help2 + iVar5 + -0x20) = __buf;
- *(uchar **)(&stack0xffffffc4 + iVar5) = puVar7;
- *(undefined4 *)((int)&uStackY_40 + iVar5) = 0x80e1356;
- memcpy(*(void **)(&stack0xffffffc4 + iVar5),*(void **)(&stack0xffffffc8 + iVar5)
- ,*(size_t *)(Help2 + iVar5 + -0x20));
- }
- else {
- uStackY_40 = 0x80e0ff6;
- pvVar2 = operator_new__((uint)__buf);
- puVar7 = this->Buffer;
- uStackY_40 = 0x80e100e;
- psVar3 = __buf;
- memcpy(pvVar2,puVar7,(size_t)__buf);
- uStackY_40 = 0x80e1019;
- connect(this,(int)puVar7,psVar3,in_stack_ffffffd0);
- uStackY_40 = 0x80e102f;
- memcpy(this->Buffer,pvVar2,(size_t)__buf);
- if (pvVar2 != (void *)0x0) {
- uStackY_40 = 0x80e103b;
- operator_delete__(pvVar2);
- }
- }
- if (this->Socket < 0) {
- return 3;
- }
- }
- uStackY_40 = 0x80e1069;
- psVar3 = (sockaddr *)write(this,(int)this->Buffer,__buf,in_stack_ffffffd0);
- if (psVar3 == __buf) {
- uStackY_40 = 0x80e1092;
- in_stack_ffffffd0 = Timeout;
- sVar4 = read(this,(int)(Help2 + 2),(void *)0x2,Timeout);
- if (sVar4 == 2) {
- pvVar2 = (void *)((uint)Help2[3] * 0x100 + (uint)Help2[2]);
- if (pvVar2 == (void *)0xffff) {
- uStackY_40 = 0x80e1241;
- sVar4 = read(this,(int)&local_18,(void *)0x4,Timeout);
- if (sVar4 != 4) {
- if (this->Socket < 0) {
- return 3;
- }
- uStackY_40 = 0x80e1263;
- iVar5 = close(this->Socket);
- if (iVar5 < 0) {
- uStackY_40 = 0x80e127b;
- __errno_location();
- uStackY_40 = 0x80e128d;
- error(&DAT_0810dc00);
- }
- this->Socket = -1;
- return 3;
- }
- pvVar2 = (void *)((uint)local_18 + (uint)_local_17 * 0x100);
- }
- if ((pvVar2 == (void *)0x0) || (this->BufferSize < (int)pvVar2)) {
- if (-1 < this->Socket) {
- uStackY_40 = 0x80e114a;
- iVar5 = close(this->Socket);
- if (iVar5 < 0) {
- uStackY_40 = 0x80e115f;
- __errno_location();
- uStackY_40 = 0x80e1171;
- error(&DAT_0810dc00);
- }
- this->Socket = -1;
- }
- uStackY_40 = 0x80e113d;
- error(&DAT_0810e120);
- return 3;
- }
- uStackY_40 = 0x80e1190;
- pvVar6 = (void *)read(this,(int)this->Buffer,pvVar2,Timeout);
- if (pvVar6 == pvVar2) {
- (this->ReadBuffer).Size = (int)pvVar6;
- (this->ReadBuffer).Position = 0;
- // try { // try from 080e11f7 to 080e11fb has its CatchHandler @ 080e1415
- uStackY_40 = 0x80e11fc;
- bVar1 = TReadBuffer::readByte(&this->ReadBuffer);
- if (bVar1 == 3) {
- uStackY_40 = 0x80e121a;
- error("TQueryManagerConnection::executeQuery: Anfrage fehlgeschlagen.\n"
- );
- return 3;
- }
- return (uint)bVar1;
- }
- if (-1 < this->Socket) {
- uStackY_40 = 0x80e11bb;
- iVar5 = close(this->Socket);
- if (iVar5 < 0) {
- uStackY_40 = 0x80e11d0;
- __errno_location();
- uStackY_40 = 0x80e11e2;
- error(&DAT_0810dc00);
- }
- this->Socket = -1;
- }
- Text =
- "TQueryManagerConnection::executeQuery: Fehler beim Auslesen der Daten.\n";
- goto LAB_080e0f4d;
- }
- if (-1 < this->Socket) {
- uStackY_40 = 0x80e10ce;
- iVar5 = close(this->Socket);
- if (iVar5 < 0) {
- uStackY_40 = 0x80e10e3;
- __errno_location();
- uStackY_40 = 0x80e10f5;
- error(&DAT_0810dc00);
- }
- this->Socket = -1;
- }
- if (sVar4 == -2) {
- return 3;
- }
- if (local_21 == '\0') {
- return 3;
- }
- }
- else {
- if (-1 < this->Socket) {
- uStackY_40 = 0x80e12e8;
- iVar5 = close(this->Socket);
- if (iVar5 < 0) {
- uStackY_40 = 0x80e12fd;
- __errno_location();
- uStackY_40 = 0x80e130f;
- error(&DAT_0810dc00);
- }
- this->Socket = -1;
- }
- if (local_21 == '\0') {
- Text =
- "TQueryManagerConnection::executeQuery: Fehler beim Abschicken der Anfrage.\n";
- goto LAB_080e0f4d;
- }
- }
- local_21 = '\0';
- } while( true );
- }
- Text = "TQueryManagerConnection::executeQuery: Fehler beim Zusammenbauen der Anfrage.\n";
-LAB_080e0f4d:
- uStackY_40 = 0x80e0f52;
- error(Text);
- return 3;
-}
-
-
-
// DWARF original prototype: int checkAccountPassword(TQueryManagerConnection * this, ulong
// AccountID, char * Password, char * IPAddress)
diff --git a/src/communication.cc b/src/communication.cc
index 99c891a..bb71327 100644
--- a/src/communication.cc
+++ b/src/communication.cc
@@ -273,11 +273,11 @@ bool WriteToSocket(TConnection *Connection, uint8 *Buffer, int Size){
int BytesToWrite = Size + 2;
uint8 *WritePtr = Buffer;
while(BytesToWrite > 0){
- int ret = (int)write(Connection->GetSocket(), WritePtr, BytesToWrite);
- if(ret > 0){
- BytesToWrite -= ret;
- WritePtr += ret;
- }else if(ret == 0){
+ int BytesWritten = (int)write(Connection->GetSocket(), WritePtr, BytesToWrite);
+ if(BytesWritten > 0){
+ BytesToWrite -= BytesWritten;
+ WritePtr += BytesWritten;
+ }else if(BytesWritten == 0){
// TODO(fusion): Can this even happen without an error?
error("WriteToSocket: Fehler %d beim Senden an Socket %d.\n",
errno, Connection->GetSocket());
diff --git a/src/crplayer.cc b/src/crplayer.cc
index a53e676..e5874be 100644
--- a/src/crplayer.cc
+++ b/src/crplayer.cc
@@ -8,8 +8,6 @@
#include "threads.hh"
#include "writer.hh"
-#include "stubs.hh"
-
static Semaphore PlayerMutex(1);
static vector<TPlayer*> PlayerList(0, 100, 10, NULL);
static int FirstFreePlayer;
diff --git a/src/query.cc b/src/query.cc
index 697a3ce..a31b9b0 100644
--- a/src/query.cc
+++ b/src/query.cc
@@ -1,3 +1,383 @@
#include "query.hh"
+#include "config.hh"
-// TODO
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <poll.h>
+#include <sys/socket.h>
+
+static int ApplicationType;
+static char LoginData[30];
+
+void SetQueryManagerLoginData(int Type, const char *Data){
+ ApplicationType = Type;
+ if(Data != NULL){
+ strncpy(LoginData, Data, sizeof(LoginData));
+ LoginData[sizeof(LoginData) - 1] = 0;
+ }else{
+ LoginData[0] = 0;
+ }
+}
+
+// TODO(fusion): An initializer list executes in the same order fields are
+// declared. This initialization should work as long as `BufferSize` is the
+// first field declared in `TQueryManagerConnection`, which it is.
+TQueryManagerConnection::TQueryManagerConnection(int QueryBufferSize) :
+ BufferSize(std::max<int>(QueryBufferSize, KB(16))),
+ Buffer(new uint8[this->BufferSize]),
+ ReadBuffer(this->Buffer, this->BufferSize),
+ WriteBuffer(this->Buffer, this->BufferSize),
+ Socket(-1),
+ QueryOk(false)
+{
+ this->connect();
+}
+
+TQueryManagerConnection::~TQueryManagerConnection(void){
+ this->disconnect();
+ delete[] this->Buffer;
+}
+
+bool ResolveHostNameAddress(const char *HostName, in_addr_t *OutAddr){
+ // TODO(fusion): Just use `getaddrinfo`?
+ int ErrorCode;
+ hostent HostEnt;
+ hostent *HostEntResult;
+ char Buffer[2048];
+ int Ret = gethostbyname_r(HostName, &HostEnt,
+ Buffer, sizeof(Buffer), &HostEntResult, &ErrorCode);
+ if(Ret != 0 || HostEntResult == NULL){
+ return false;
+ }
+
+ if(OutAddr){
+ *OutAddr = ((in_addr_t)HostEntResult->h_addr_list[0][0] << 24)
+ | ((in_addr_t)HostEntResult->h_addr_list[0][1] << 16)
+ | ((in_addr_t)HostEntResult->h_addr_list[0][2] << 8)
+ | ((in_addr_t)HostEntResult->h_addr_list[0][3] << 0);
+ }
+
+ return true;
+}
+
+void TQueryManagerConnection::connect(void){
+ for(int i = 0; i < NumberOfQueryManagers; i += 1){
+ in_addr_t Addr = inet_addr(QUERY_MANAGER[i].Host);
+ if(Addr == 0xFFFFFFFF && !ResolveHostNameAddress(QUERY_MANAGER[i].Host, &Addr)){
+ print(2, "TQueryManagerConnection::connect: Kann Rechnernamen nicht auflösen.\n");
+ continue;
+ }
+
+ this->Socket = socket(AF_INET, SOCK_STREAM, 0);
+ if(this->Socket == -1){
+ print(2, "TQueryManagerConnection::connect: Kann Socket nicht öffnen.\n");
+ continue;
+ }
+
+ struct sockaddr_in QueryManagerAddress = {};
+ QueryManagerAddress.sin_family = AF_INET;
+ QueryManagerAddress.sin_port = htons(QUERY_MANAGER[i].Port);
+ QueryManagerAddress.sin_addr.s_addr = Addr;
+ if(::connect(this->Socket, (struct sockaddr*)&QueryManagerAddress, sizeof(QueryManagerAddress)) == -1){
+ this->disconnect();
+ continue;
+ }
+
+ this->prepareQuery(0);
+ this->sendByte((uint8)ApplicationType);
+ this->sendString(QUERY_MANAGER[i].Password);
+ if(ApplicationType == 1){
+ this->sendString(LoginData);
+ }
+
+ int Ret = this->executeQuery(30, false);
+ if(Ret != 0){
+ print(2, "TQueryManagerConnection::connect: Anmeldung fehlgeschlagen (%d).\n", Ret);
+ this->disconnect();
+ continue;
+ }
+
+ break;
+ }
+
+ if(!this->isConnected()){
+ print(2, "TQueryManagerConnection::connect: Kein Query-Manager verfügbar.\n");
+ }
+}
+
+void TQueryManagerConnection::disconnect(void){
+ if(this->Socket != -1){
+ if(close(this->Socket) == -1){
+ error("TQueryManagerConnection::disconnect: Fehler %d beim Schließen der Socket.\n", errno);
+ }
+ this->Socket = -1;
+ }
+}
+
+int TQueryManagerConnection::write(const uint8 *Buffer, int Size){
+ int Attempts = 50;
+ int BytesToWrite = Size;
+ const uint8 *WritePtr = Buffer;
+ while(BytesToWrite > 0){
+ int BytesWritten = (int)::write(this->Socket, WritePtr, BytesToWrite);
+ if(BytesWritten > 0){
+ BytesToWrite -= BytesWritten;
+ WritePtr += BytesWritten;
+ }else if(BytesWritten == 0){
+ break;
+ }else{
+ // TODO(fusion): We don't set the socket as non blocking so I don't
+ // think we can even get `EAGAIN` here.
+ if(errno != EAGAIN || Attempts <= 0){
+ return -1;
+ }
+
+ DelayThread(0, 100000);
+ Attempts -= 1;
+ }
+ }
+ return Size - BytesToWrite;
+}
+
+int TQueryManagerConnection::read(uint8 *Buffer, int Size, int Timeout){
+ int Attempts = 50;
+ int BytesToRead = Size;
+ uint8 *ReadPtr = Buffer;
+ while(BytesToRead > 0){
+ struct pollfd pollfd = {};
+ pollfd.fd = this->Socket;
+ pollfd.events = POLLIN;
+ if(poll(&pollfd, 1, Timeout * 1000) != 1){
+ return -2;
+ }
+
+ int BytesRead = ::read(this->Socket, ReadPtr, BytesToRead);
+ if(BytesRead > 0){
+ BytesToRead -= BytesRead;
+ ReadPtr += BytesRead;
+ }else if(BytesRead == 0){
+ break;
+ }else if(errno != EINTR){
+ if(errno != EAGAIN || BytesToRead == Size || Attempts <= 0){
+ return -1;
+ }
+
+ DelayThread(0, 100000);
+ Attempts -= 1;
+ }
+ }
+ return Size - BytesToRead;
+}
+
+void TQueryManagerConnection::prepareQuery(int QueryType){
+ this->QueryOk = true;
+ this->WriteBuffer.Position = 0;
+
+ try{
+ this->WriteBuffer.writeWord(0);
+ this->WriteBuffer.writeByte((uint8)QueryType);
+ }catch(const char *str){
+ error("TQueryManagerConnection::prepareQuery: %s.\n", str);
+ this->QueryOk = false;
+ }
+}
+
+void TQueryManagerConnection::sendFlag(bool Flag){
+ this->sendByte(Flag ? 0x01 : 0x00);
+}
+
+void TQueryManagerConnection::sendByte(uint8 Byte){
+ try{
+ this->WriteBuffer.writeByte(Byte);
+ }catch(const char *str){
+ error("TQueryManagerConnection::sendByte: %s.\n", str);
+ this->QueryOk = false;
+ }
+}
+
+void TQueryManagerConnection::sendWord(uint16 Word){
+ try{
+ this->WriteBuffer.writeWord(Word);
+ }catch(const char *str){
+ error("TQueryManagerConnection::sendWord: %s.\n", str);
+ this->QueryOk = false;
+ }
+}
+
+void TQueryManagerConnection::sendQuad(uint32 Quad){
+ try{
+ this->WriteBuffer.writeQuad(Quad);
+ }catch(const char *str){
+ error("TQueryManagerConnection::sendQuad: %s.\n", str);
+ this->QueryOk = false;
+ }
+}
+
+void TQueryManagerConnection::sendString(const char *String){
+ try{
+ this->WriteBuffer.writeString(String);
+ }catch(const char *str){
+ error("TQueryManagerConnection::sendString: %s.\n", str);
+ this->QueryOk = false;
+ }
+}
+
+void TQueryManagerConnection::sendBytes(const uint8 *Buffer, int Count){
+ try{
+ this->WriteBuffer.writeBytes(Buffer, Count);
+ }catch(const char *str){
+ error("TQueryManagerConnection::sendBytes: %s.\n", str);
+ this->QueryOk = false;
+ }
+}
+
+bool TQueryManagerConnection::getFlag(void){
+ return this->getByte() != 0;
+}
+
+uint8 TQueryManagerConnection::getByte(void){
+ uint8 Result = 0;
+ try{
+ Result = this->ReadBuffer.readByte();
+ }catch(const char *str){
+ error("TQueryManagerConnection::getByte: %s.\n", str);
+ }
+ return Result;
+}
+
+uint16 TQueryManagerConnection::getWord(void){
+ uint16 Result = 0;
+ try{
+ Result = this->ReadBuffer.readWord();
+ }catch(const char *str){
+ error("TQueryManagerConnection::getWord: %s.\n", str);
+ }
+ return Result;
+}
+
+uint32 TQueryManagerConnection::getQuad(void){
+ uint32 Result = 0;
+ try{
+ Result = this->ReadBuffer.readQuad();
+ }catch(const char *str){
+ error("TQueryManagerConnection::getQuad: %s.\n", str);
+ }
+ return Result;
+}
+
+void TQueryManagerConnection::getString(char *Buffer, int MaxLength){
+ try{
+ this->ReadBuffer.readString(Buffer, MaxLength);
+ }catch(const char *str){
+ error("TQueryManagerConnection::getString: %s.\n", str);
+ if(MaxLength > 0){
+ Buffer[0] = 0;
+ }
+ }
+}
+
+void TQueryManagerConnection::getBytes(uint8 *Buffer, int Count){
+ try{
+ this->ReadBuffer.readBytes(Buffer, Count);
+ }catch(const char *str){
+ error("TQueryManagerConnection::getBytes: %s.\n", str);
+ }
+}
+
+int TQueryManagerConnection::executeQuery(int Timeout, bool AutoReconnect){
+ // NOTE(fusion): `prepareQuery` will already leave two extra bytes at the
+ // beginning of the buffer for writing the request's length.
+ int PacketSize = this->WriteBuffer.Position;
+ int PayloadSize = PacketSize - 2;
+ this->WriteBuffer.Position = 0;
+ if(PayloadSize < 0xFFFF){
+ this->sendWord((uint16)PayloadSize);
+ }else{
+ PacketSize += 4;
+ if(PacketSize > this->BufferSize){
+ error("TQueryManagerConnection::executeQuery: Puffer zu klein.\n");
+ return QUERY_FAILED;
+ }
+
+ memmove(&this->Buffer[6], &this->Buffer[2], PayloadSize);
+ this->sendWord(0xFFFF);
+ this->sendQuad((uint32)PayloadSize);
+ }
+
+ if(!this->QueryOk){
+ error("TQueryManagerConnection::executeQuery: Fehler beim Zusammenbauen der Anfrage.\n");
+ return QUERY_FAILED;
+ }
+
+ for(int Attempt = 0; true; Attempt += 1){
+ if(!this->isConnected()){
+ if(!AutoReconnect){
+ return QUERY_FAILED;
+ }
+
+ // TODO(fusion): There was also a "fast" path that allocated on the
+ // stack with variable length arrays. It would be a problem to mimic
+ // that with `alloca` since its memory is only released at the end
+ // of the function and we're in a loop.
+ uint8 *TempBuffer = new uint8[PacketSize];
+ memcpy(TempBuffer, this->Buffer, PacketSize);
+ this->connect();
+ memcpy(this->Buffer, TempBuffer, PacketSize);
+ delete[] TempBuffer;
+
+ if(!this->isConnected()){
+ return QUERY_FAILED;
+ }
+ }
+
+ if(this->write(this->Buffer, PacketSize) != PacketSize){
+ this->disconnect();
+ if(Attempt > 0){
+ error("TQueryManagerConnection::executeQuery: Fehler beim Abschicken der Anfrage.\n");
+ return QUERY_FAILED;
+ }
+ continue;
+ }
+
+ uint8 Help[4];
+ int BytesRead = this->read(Help, 2, Timeout);
+ if(BytesRead != 2){
+ this->disconnect();
+ if(BytesRead == -2 || Attempt > 0){
+ return QUERY_FAILED;
+ }
+ continue;
+ }
+
+ int ResponseSize = ((int)Help[0]) | ((int)Help[1] << 8);
+ if(ResponseSize == 0xFFFF){
+ if(this->read(Help, 4, Timeout) != 4){
+ this->disconnect();
+ return QUERY_FAILED;
+ }
+
+ ResponseSize = ((int)Help[0]) | ((int)Help[1] << 8)
+ | ((int)Help[2] << 16) | ((int)Help[3] << 24);
+ }
+
+ if(ResponseSize <= 0 || ResponseSize > this->BufferSize){
+ this->disconnect();
+ error("TQueryManagerConnection::executeQuery: Ungültige Datengröße %d.\n", ResponseSize);
+ return QUERY_FAILED;
+ }
+
+ if(this->read(this->Buffer, ResponseSize, Timeout) != ResponseSize){
+ this->disconnect();
+ error("TQueryManagerConnection::executeQuery: Fehler beim Auslesen der Daten.\n");
+ return QUERY_FAILED;
+ }
+
+ int Status = this->getByte();
+ if(Status == QUERY_FAILED){
+ error("TQueryManagerConnection::executeQuery: Anfrage fehlgeschlagen.\n");
+ }
+
+ return Status;
+ }
+}
diff --git a/src/query.hh b/src/query.hh
index a69413a..8bdd527 100644
--- a/src/query.hh
+++ b/src/query.hh
@@ -4,8 +4,43 @@
#include "common.hh"
#include "threads.hh"
+enum : int {
+ QUERY_OK = 0,
+ QUERY_ERROR = 1,
+ QUERY_FAILED = 3,
+};
+
struct TQueryManagerConnection{
TQueryManagerConnection(int QueryBufferSize);
+ ~TQueryManagerConnection(void);
+
+ void connect(void);
+ void disconnect(void);
+ int write(const uint8 *Buffer, int Size);
+ int read(uint8 *Buffer, int Size, int Timeout);
+ bool isConnected(void){
+ return this->Socket != -1;
+ }
+
+ void prepareQuery(int QueryType);
+ void sendFlag(bool Flag);
+ void sendByte(uint8 Byte);
+ void sendWord(uint16 Word);
+ void sendQuad(uint32 Quad);
+ void sendString(const char *String);
+ void sendBytes(const uint8 *Buffer, int Count);
+
+ bool getFlag(void);
+ uint8 getByte(void);
+ uint16 getWord(void);
+ uint32 getQuad(void);
+ void getString(char *Buffer, int MaxLength);
+ void getBytes(uint8 *Buffer, int Count);
+
+ int executeQuery(int Timeout, bool AutoReconnect);
+
+//==
+
int loadWorldConfig(int *WorldType, int *RebootTime,
int *IPAddress, int *Port,
int *MaxPlayers, int *PremiumPlayerBuffer,
@@ -71,10 +106,6 @@ struct TQueryManagerConnection{
int insertHouseOwner(uint16 HouseID, uint32 OwnerID, int PaidUntil);
int updateHouseOwner(uint16 HouseID, uint32 OwnerID, int PaidUntil);
- bool isConnected(void){
- return this->Socket >= 0;
- }
-
// DATA
// =================
int BufferSize;
diff --git a/src/stubs.hh b/src/stubs.hh
deleted file mode 100644
index 0be5c77..0000000
--- a/src/stubs.hh
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef TIBIA_STUBS_HH_
-#define TIBIA_STUBS_HH_ 1
-
-#include "common.hh"
-#include "enums.hh"
-#include "cr.hh"
-#include "map.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.
-
-extern void SavePlayerData(TPlayerData *Slot);
-extern bool LoadPlayerData(TPlayerData *Slot);
-extern bool PlayerDataExists(uint32 CharacterID);
-
-#endif //TIBIA_STUBS_HH_