diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/common.hh | 4 | ||||
| -rw-r--r-- | src/config.cc | 2 | ||||
| -rw-r--r-- | src/cract.cc | 2 | ||||
| -rw-r--r-- | src/crcombat.cc | 2 | ||||
| -rw-r--r-- | src/crskill.cc | 2 | ||||
| -rw-r--r-- | src/main.cc | 3 | ||||
| -rw-r--r-- | src/map.cc | 2 | ||||
| -rw-r--r-- | src/moveuse.cc | 3 | ||||
| -rw-r--r-- | src/objects.cc | 2 | ||||
| -rw-r--r-- | src/operate.cc | 5 | ||||
| -rw-r--r-- | src/reader.cc | 273 | ||||
| -rw-r--r-- | src/reader.hh | 47 | ||||
| -rw-r--r-- | src/stubs.hh | 7 | ||||
| -rw-r--r-- | src/utils.cc | 35 | ||||
| -rw-r--r-- | src/writer.cc | 23 |
15 files changed, 371 insertions, 41 deletions
diff --git a/src/common.hh b/src/common.hh index 57c7745..b97de3c 100644 --- a/src/common.hh +++ b/src/common.hh @@ -153,6 +153,10 @@ typedef void TErrorFunction(const char *Text); typedef void TPrintFunction(int Level, const char *Text); void SetErrorFunction(TErrorFunction *Function); void SetPrintFunction(TPrintFunction *Function); +void SilentHandler(const char *Text); +void SilentHandler(int Level, const char *Text); +void LogFileHandler(const char *Text); +void LogFileHandler(int Level, const char *Text); void error(const char *Text, ...) ATTR_PRINTF(1, 2); void print(int Level, const char *Text, ...) ATTR_PRINTF(2, 3); int random(int Min, int Max); diff --git a/src/config.cc b/src/config.cc index d08b791..257985b 100644 --- a/src/config.cc +++ b/src/config.cc @@ -1,8 +1,6 @@ #include "config.hh" #include "script.hh" -#include "stubs.hh" - char BINPATH[4096]; char DATAPATH[4096]; char LOGPATH[4096]; diff --git a/src/cract.cc b/src/cract.cc index a7bb2fe..8397d79 100644 --- a/src/cract.cc +++ b/src/cract.cc @@ -4,8 +4,6 @@ #include "info.hh" #include "operate.hh" -#include "stubs.hh" - // TShortway // ============================================================================= struct TShortwayPoint { diff --git a/src/crcombat.cc b/src/crcombat.cc index 43c3f76..f942332 100644 --- a/src/crcombat.cc +++ b/src/crcombat.cc @@ -4,8 +4,6 @@ #include "magic.hh" #include "operate.hh" -#include "stubs.hh" - TCombat::TCombat(void){ this->Master = NULL; this->EarliestAttackTime = 0; diff --git a/src/crskill.cc b/src/crskill.cc index 923c0ab..e12e9c6 100644 --- a/src/crskill.cc +++ b/src/crskill.cc @@ -1,8 +1,6 @@ #include "cr.hh" #include "operate.hh" -#include "stubs.hh" - #include <math.h> // TSkill REGULAR FUNCTIONS diff --git a/src/main.cc b/src/main.cc index c64838a..2875e94 100644 --- a/src/main.cc +++ b/src/main.cc @@ -9,10 +9,9 @@ #include "objects.hh" #include "operate.hh" #include "query.hh" +#include "reader.hh" #include "writer.hh" -#include "stubs.hh" - #include <signal.h> #include <sys/stat.h> #include <sys/time.h> @@ -5,8 +5,6 @@ #include "houses.hh" #include "script.hh" -#include "stubs.hh" - #include <dirent.h> int SectorXMin; diff --git a/src/moveuse.cc b/src/moveuse.cc index 3db2016..6c83dcc 100644 --- a/src/moveuse.cc +++ b/src/moveuse.cc @@ -4,10 +4,9 @@ #include "info.hh" #include "magic.hh" #include "operate.hh" +#include "reader.hh" #include "writer.hh" -#include "stubs.hh" - static vector<TMoveUseCondition> MoveUseConditions(1, 1000, 1000); static int NumberOfMoveUseConditions; diff --git a/src/objects.cc b/src/objects.cc index 5231fc8..94edca4 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -3,8 +3,6 @@ #include "containers.hh" #include "script.hh" -#include "stubs.hh" - #include <fstream> static vector<TObjectType> ObjectTypes(0, 5000, 1000); diff --git a/src/operate.cc b/src/operate.cc index 7099cc1..7827d0d 100644 --- a/src/operate.cc +++ b/src/operate.cc @@ -4,8 +4,7 @@ #include "info.hh" #include "magic.hh" #include "moveuse.hh" - -#include "stubs.hh" +#include "reader.hh" #include <dirent.h> @@ -2876,7 +2875,7 @@ void RefreshMap(void){ } char FileName[4096]; - snprintf(FileName, sizeof(FileName), "%s/%04u-%04u-%02u.sec", + snprintf(FileName, sizeof(FileName), "%s/%04d-%04d-%02d.sec", ORIGMAPPATH, SectorX, SectorY, SectorZ); if(!FileExists(FileName)){ continue; diff --git a/src/reader.cc b/src/reader.cc index f2da968..09d739b 100644 --- a/src/reader.cc +++ b/src/reader.cc @@ -1,6 +1,277 @@ #include "reader.hh" +#include "config.hh" +#include "cr.hh" +#include "map.hh" #include "threads.hh" -static Semaphore OrderBufferEmpty(200); +static ThreadHandle ReaderThread; + +static TReaderThreadOrder OrderBuffer[200]; +static int OrderPointerWrite; +static int OrderPointerRead; +static Semaphore OrderBufferEmpty(NARRAY(OrderBuffer)); static Semaphore OrderBufferFull(0); + +static TReaderThreadReply ReplyBuffer[200]; +static int ReplyPointerWrite; +static int ReplyPointerRead; + static TDynamicWriteBuffer HelpBuffer(KB(64)); + +// Reader Orders +// ============================================================================= +void InitReaderBuffers(void){ + OrderPointerWrite = 0; + OrderPointerRead = 0; + ReplyPointerWrite = 0; + ReplyPointerRead = 0; +} + +void InsertOrder(TReaderThreadOrderType OrderType, + int SectorX, int SectorY, int SectorZ, uint32 CharacterID){ + int Orders = (OrderPointerWrite - OrderPointerRead); + if(Orders >= NARRAY(OrderBuffer)){ + error("InsertOrder (Reader): Order-Puffer ist voll => Vergrößern.\n"); + } + + OrderBufferEmpty.down(); + int WritePos = OrderPointerWrite % NARRAY(OrderBuffer); + OrderBuffer[WritePos].OrderType = OrderType; + OrderBuffer[WritePos].SectorX = SectorX; + OrderBuffer[WritePos].SectorY = SectorY; + OrderBuffer[WritePos].SectorZ = SectorZ; + OrderBuffer[WritePos].CharacterID = CharacterID; + OrderPointerWrite += 1; + OrderBufferFull.up(); +} + +void GetOrder(TReaderThreadOrder *Order){ + OrderBufferFull.down(); + *Order = OrderBuffer[OrderPointerRead % NARRAY(OrderBuffer)]; + OrderPointerRead += 1; + OrderBufferEmpty.up(); +} + +void TerminateReaderOrder(void){ + InsertOrder(READER_ORDER_TERMINATE, 0, 0, 0, 0); +} + +void LoadSectorOrder(int SectorX, int SectorY, int SectorZ){ + InsertOrder(READER_ORDER_LOADSECTOR, SectorX, SectorY, SectorZ, 0); +} + +void LoadCharacterOrder(uint32 CharacterID){ + InsertOrder(READER_ORDER_LOADCHARACTER, 0, 0, 0, CharacterID); +} + +void ProcessLoadSectorOrder(int SectorX, int SectorY, int SectorZ){ + // TODO(fusion): We parsed sector files way too many times now. And there + // is also a drop in loader quality. + char FileName[4096]; + snprintf(FileName, sizeof(FileName), "%s/%04d-%04d-%02d.sec", + ORIGMAPPATH, SectorX, SectorY, SectorZ); + if(!FileExists(FileName)){ + return; + } + + int OffsetX = -1; + int OffsetY = -1; + bool Refreshable = false; + HelpBuffer.Position = 0; + + TReadScriptFile Script; + Script.open(FileName); + while(true){ + Script.nextToken(); + if(Script.Token == ENDOFFILE){ + Script.close(); + break; + } + + if(Script.Token == SPECIAL && Script.getSpecial() == ','){ + continue; + } + + if(Script.Token == BYTES){ + uint8 *Offset = Script.getBytesequence(); + OffsetX = (int)Offset[0]; + OffsetY = (int)Offset[1]; + Refreshable = false; + Script.readSymbol(':'); + }else if(Script.Token == IDENTIFIER){ + if(OffsetX == -1 || OffsetY == -1){ + Script.error("coordinate expected"); + } + + const char *Identifier = Script.getIdentifier(); + if(strcmp(Identifier, "refresh") == 0){ + Refreshable = true; + }else if(strcmp(Identifier, "content") == 0){ + Script.readSymbol('='); + + if(Refreshable){ + HelpBuffer.writeByte((uint8)OffsetX); + HelpBuffer.writeByte((uint8)OffsetY); + } + + LoadObjects(&Script, &HelpBuffer, !Refreshable); + } + } + } + + int Size = HelpBuffer.Position; + if(Size > 0){ + uint8 *Data = new uint8[Size]; + memcpy(Data, HelpBuffer.Data, Size); + SectorReply(SectorX, SectorY, SectorZ, Data, Size); + } +} + +void ProcessLoadCharacterOrder(uint32 CharacterID){ + while(true){ + TPlayerData *Slot = AssignPlayerPoolSlot(CharacterID, true); + if(Slot == NULL){ + error("ProcessLoadCharacterOrder: Kann keinen Slot für Spielerdaten zuweisen.\n"); + break; + } + + if(Slot->Locked == GetGameThreadPID()){ + break; + } + + if(Slot->Locked == getpid()){ + IncreasePlayerPoolSlotSticky(Slot); + ReleasePlayerPoolSlot(Slot); + CharacterReply(CharacterID); + break; + } + + DelayThread(1, 0); + } +} + +int ReaderThreadLoop(void *Unused){ + TReaderThreadOrder Order = {}; + while(true){ + GetOrder(&Order); + if(Order.OrderType == READER_ORDER_TERMINATE){ + break; + } + + switch(Order.OrderType){ + case READER_ORDER_LOADSECTOR:{ + ProcessLoadSectorOrder(Order.SectorX, Order.SectorY, Order.SectorZ); + break; + } + + case READER_ORDER_LOADCHARACTER:{ + ProcessLoadCharacterOrder(Order.CharacterID); + break; + } + + default:{ + error("ReaderThreadLoop: Unbekanntes Kommando %d.\n", Order.OrderType); + break; + } + } + } + + return 0; +} + +// Reader Replies +// ============================================================================= +void InsertReply(TReaderThreadReplyType ReplyType, + int SectorX, int SectorY, int SectorZ, uint8 *Data, int Size){ + int Replies = (ReplyPointerWrite - ReplyPointerRead); + while(Replies > NARRAY(ReplyBuffer)){ + error("InsertReply (Reader): Puffer ist voll; warte...\n"); + DelayThread(5, 0); + } + + int WritePos = ReplyPointerWrite % NARRAY(ReplyBuffer); + ReplyBuffer[WritePos].ReplyType = ReplyType; + ReplyBuffer[WritePos].SectorX = SectorX; + ReplyBuffer[WritePos].SectorY = SectorY; + ReplyBuffer[WritePos].SectorZ = SectorZ; + ReplyBuffer[WritePos].Data = Data; + ReplyBuffer[WritePos].Size = Size; + ReplyPointerWrite += 1; +} + +bool GetReply(TReaderThreadReply *Reply){ + bool Result = (ReplyPointerRead < ReplyPointerWrite); + if(Result){ + *Reply = ReplyBuffer[ReplyPointerRead % NARRAY(ReplyBuffer)]; + ReplyPointerRead += 1; + } + return Result; +} + +void SectorReply(int SectorX, int SectorY, int SectorZ, uint8 *Data, int Size){ + InsertReply(READER_REPLY_SECTORDATA, SectorX, SectorY, SectorZ, Data, Size); +} + +void CharacterReply(uint32 CharacterID){ + InsertReply(READER_REPLY_CHARACTERDATA, 0, 0, 0, NULL, (int)CharacterID); +} + +void ProcessSectorReply(TRefreshSectorFunction *RefreshSector, + int SectorX, int SectorY, int SectorZ, uint8 *Data, int Size){ + RefreshSector(SectorX, SectorY, SectorZ, Data, Size); + delete[] Data; +} + +void ProcessCharacterReply(TSendMailsFunction *SendMails, uint32 CharacterID){ + TPlayerData *Slot = AttachPlayerPoolSlot(CharacterID, true); + if(Slot == NULL){ + DecreasePlayerPoolSlotSticky(Slot); + return; + } + + SendMails(Slot); + DecreasePlayerPoolSlotSticky(Slot); + ReleasePlayerPoolSlot(Slot); +} + +void ProcessReaderThreadReplies(TRefreshSectorFunction *RefreshSector, TSendMailsFunction *SendMails){ + TReaderThreadReply Reply = {}; + while(GetReply(&Reply)){ + switch(Reply.ReplyType){ + case READER_REPLY_SECTORDATA:{ + ProcessSectorReply(RefreshSector, + Reply.SectorX, Reply.SectorY, Reply.SectorZ, + Reply.Data, Reply.Size); + break; + } + + case READER_REPLY_CHARACTERDATA:{ + ProcessCharacterReply(SendMails, (uint32)Reply.Size); + break; + } + + default:{ + error("ProcessReaderThreadReplies: Unbekannte Rückmeldung %d.\n", Reply.ReplyType); + break; + } + } + } +} + +// Initialization +// ============================================================================= +void InitReader(void){ + InitReaderBuffers(); + ReaderThread = StartThread(ReaderThreadLoop, NULL, false); + if(ReaderThread == INVALID_THREAD_HANDLE){ + throw "cannot start reader thread"; + } +} + +void ExitReader(void){ + if(ReaderThread != INVALID_THREAD_HANDLE){ + TerminateReaderOrder(); + JoinThread(ReaderThread); + ReaderThread = INVALID_THREAD_HANDLE; + } +} diff --git a/src/reader.hh b/src/reader.hh index 2dbf02f..7db1ca7 100644 --- a/src/reader.hh +++ b/src/reader.hh @@ -3,6 +3,12 @@ #include "common.hh" +struct TPlayerData; + +typedef void TRefreshSectorFunction(int SectorX, int SectorY, int SectorZ, + const uint8 *Data, int Size); +typedef void TSendMailsFunction(TPlayerData *PlayerData); + enum TReaderThreadOrderType: int { READER_ORDER_TERMINATE = 0, READER_ORDER_LOADSECTOR = 1, @@ -14,4 +20,45 @@ enum TReaderThreadReplyType: int { READER_REPLY_CHARACTERDATA = 1, }; +struct TReaderThreadOrder { + TReaderThreadOrderType OrderType; + int SectorX; + int SectorY; + int SectorZ; + uint32 CharacterID; +}; + +struct TReaderThreadReply { + TReaderThreadReplyType ReplyType; + int SectorX; + int SectorY; + int SectorZ; + uint8 *Data; + int Size; +}; + +void InitReaderBuffers(void); +void InsertOrder(TReaderThreadOrderType OrderType, + int SectorX, int SectorY, int SectorZ, uint32 CharacterID); +void GetOrder(TReaderThreadOrder *Order); +void TerminateReaderOrder(void); +void LoadSectorOrder(int SectorX, int SectorY, int SectorZ); +void LoadCharacterOrder(uint32 CharacterID); +void ProcessLoadSectorOrder(int SectorX, int SectorY, int SectorZ); +void ProcessLoadCharacterOrder(uint32 CharacterID); +int ReaderThreadLoop(void *Unused); + +void InsertReply(TReaderThreadReplyType ReplyType, + int SectorX, int SectorY, int SectorZ, uint8 *Data, int Size); +bool GetReply(TReaderThreadReply *Reply); +void SectorReply(int SectorX, int SectorY, int SectorZ, uint8 *Data, int Size); +void CharacterReply(uint32 CharacterID); +void ProcessSectorReply(TRefreshSectorFunction *RefreshSector, + int SectorX, int SectorY, int SectorZ, uint8 *Data, int Size); +void ProcessCharacterReply(TSendMailsFunction *SendMails, uint32 CharacterID); +void ProcessReaderThreadReplies(TRefreshSectorFunction *RefreshSector, TSendMailsFunction *SendMails); + +void InitReader(void); +void ExitReader(void); + #endif //TIBIA_READER_HH diff --git a/src/stubs.hh b/src/stubs.hh index 4e974d7..0be5c77 100644 --- a/src/stubs.hh +++ b/src/stubs.hh @@ -9,15 +9,8 @@ // IMPORTANT(fusion): These function definitions exist to test compilation. They're // not yet implemented and will cause the linker to fail with unresolved symbols. -typedef void TRefreshSectorFunction(int SectorX, int SectorY, int SectorZ, const uint8 *Data, int Size); -typedef void TSendMailsFunction(TPlayerData *PlayerData); - -extern void LoadCharacterOrder(uint32 CharacterID); -extern void LoadSectorOrder(int SectorX, int SectorY, int SectorZ); -extern void ProcessReaderThreadReplies(TRefreshSectorFunction *RefreshSector, TSendMailsFunction *SendMails); extern void SavePlayerData(TPlayerData *Slot); extern bool LoadPlayerData(TPlayerData *Slot); extern bool PlayerDataExists(uint32 CharacterID); -extern void SavePlayerDataOrder(void); #endif //TIBIA_STUBS_HH_ diff --git a/src/utils.cc b/src/utils.cc index 4a3523b..11aa048 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -2,8 +2,9 @@ #include <sys/stat.h> -static void (*ErrorFunction)(const char *Text) = NULL; -static void (*PrintFunction)(int Level, const char *Text) = NULL; +static TErrorFunction *ErrorFunction; +static TPrintFunction *PrintFunction; +static char StandardLogFile[4096]; void SetErrorFunction(TErrorFunction *Function){ ErrorFunction = Function; @@ -13,6 +14,36 @@ void SetPrintFunction(TPrintFunction *Function){ PrintFunction = Function; } +void SetStandardLogFile(const char *FileName){ + strcpy(StandardLogFile, FileName); +} + +void SilentHandler(const char *Text){ + // no-op +} + +void SilentHandler(int Level, const char *Text){ + // no-op +} + +void LogFileHandler(const char *Text){ + if(StandardLogFile[0] == 0){ + return; + } + + FILE *File = fopen(StandardLogFile, "at"); + if(File != NULL){ + fprintf(File, "%s", Text); + if(fclose(File) != 0){ + error("LogfileHandler: Fehler %d beim Schließen der Datei.\n", errno); + } + } +} + +void LogFileHandler(int Level, const char *Text){ + LogFileHandler(Text); +} + void error(const char *Text, ...){ char s[1024]; diff --git a/src/writer.cc b/src/writer.cc index f4d5589..dbe0cb0 100644 --- a/src/writer.cc +++ b/src/writer.cc @@ -197,8 +197,7 @@ void InsertOrder(TWriterThreadOrderType OrderType, const void *Data){ void GetOrder(TWriterThreadOrder *Order){ OrderBufferFull.down(); - int ReadPos = OrderPointerRead % NARRAY(OrderBuffer); - *Order = OrderBuffer[ReadPos]; + *Order = OrderBuffer[OrderPointerRead % NARRAY(OrderBuffer)]; OrderPointerRead += 1; OrderBufferEmpty.up(); } @@ -857,6 +856,15 @@ void InsertReply(TWriterThreadReplyType ReplyType, const void *Data){ ReplyPointerWrite += 1; } +bool GetReply(TWriterThreadReply *Reply){ + bool Result = (ReplyPointerRead < ReplyPointerWrite); + if(Result){ + *Reply = ReplyBuffer[ReplyPointerRead % NARRAY(ReplyBuffer)]; + ReplyPointerRead += 1; + } + return Result; +} + void BroadcastReply(const char *Text, ...){ if(Text == NULL){ error("BroadcastReply: Kein Text angegeben.\n"); @@ -905,15 +913,6 @@ void LogoutReply(const char *PlayerName){ InsertReply(WRITER_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"); @@ -981,7 +980,7 @@ void ProcessWriterThreadReplies(void){ } } -// Writer Initialization +// Initialization // ============================================================================= void ClearPlayers(void){ int NumberOfAffectedPlayers; |
