1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
|
#ifndef TIBIA_COMMON_HH_
#define TIBIA_COMMON_HH_ 1
#include <ctype.h>
#include <float.h>
#include <limits.h>
#include <stddef.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <algorithm>
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
typedef uintptr_t uintptr;
typedef size_t usize;
#define STATIC_ASSERT(expr) static_assert((expr), "static assertion failed: " #expr)
#define NARRAY(arr) (int)(sizeof(arr) / sizeof(arr[0]))
#define ISPOW2(x) ((x) != 0 && ((x) & ((x) - 1)) == 0)
#define KB(x) ((usize)(x) << 10)
#define MB(x) ((usize)(x) << 20)
#define GB(x) ((usize)(x) << 30)
#if !OS_WINDOWS && !OS_LINUX
# if defined(_WIN32)
# define OS_WINDOWS 1
# elif defined(__linux__) || defined(__gnu_linux__)
# define OS_LINUX 1
# else
# error "Operating system not supported."
# endif
#endif
#if !COMPILER_MSVC && !COMPILER_GCC && !COMPILER_CLANG
# if defined(_MSC_VER)
# define COMPILER_MSVC 1
# elif defined(__GNUC__)
# define COMPILER_GCC 1
# elif defined(__clang__)
# define COMPILER_CLANG 1
# endif
#endif
#if COMPILER_GCC || COMPILER_CLANG
# define ATTR_FALLTHROUGH __attribute__((fallthrough))
# define ATTR_PRINTF(x, y) __attribute__((format(printf, x, y)))
#else
# define ATTR_FALLTHROUGH
# define ATTR_PRINTF(x, y)
#endif
#if COMPILER_MSVC
# define TRAP() __debugbreak()
#elif COMPILER_GCC || COMPILER_CLANG
# define TRAP() __builtin_trap()
#else
# define TRAP() abort()
#endif
#define ASSERT_ALWAYS(expr) if(!(expr)) { TRAP(); }
#if ENABLE_ASSERTIONS
# define ASSERT(expr) ASSERT_ALWAYS(expr)
#else
# define ASSERT(expr) ((void)(expr))
#endif
// NOTE(fusion): The server will only compile on Linux due to a few Linux specific
// features being used. Making it compile on Windows shouldn't be too difficult but
// would require a few design changes.
STATIC_ASSERT(OS_LINUX);
#include <errno.h>
#include <unistd.h>
// NOTE(fusion): This is the member name for the thread id in `struct sigevent`
// when `sigev_notify` is `SIGEV_THREAD_ID` but for whatever reason glibc doesn't
// define it.
#ifndef sigev_notify_thread_id
# define sigev_notify_thread_id _sigev_un._tid
#endif
// Constants
// =============================================================================
// TODO(fusion): There are many constants that are hardcoded as decompilation
// artifacts. We should define them here and use when appropriate. It is not
// as simple because I've been using `NARRAY` in some cases and they're used
// essentially everywhere.
//#define MAX_NAME 30 // used with most short strings (should replace MAX_IDENT_LENGTH too)
//#define MAX_IPADDRESS 16
//#define MAX_BUDDIES 100
//#define MAX_SKILLS 25
//#define MAX_SPELLS 256
//#define MAX_QUESTS 500
#define MAX_DEPOTS 9
//#define MAX_OPEN_CONTAINERS 16
// shm.cc
// =============================================================================
void StartGame(void);
void CloseGame(void);
void EndGame(void);
bool LoginAllowed(void);
bool GameRunning(void);
bool GameStarting(void);
bool GameEnding(void);
pid_t GetGameProcessID(void);
pid_t GetGameThreadID(void);
int GetPrintlogPosition(void);
char *GetPrintlogLine(int Line);
void IncrementObjectCounter(void);
void DecrementObjectCounter(void);
uint32 GetObjectCounter(void);
void IncrementPlayersOnline(void);
void DecrementPlayersOnline(void);
int GetPlayersOnline(void);
void IncrementNewbiesOnline(void);
void DecrementNewbiesOnline(void);
int GetNewbiesOnline(void);
void SetRoundNr(uint32 RoundNr);
uint32 GetRoundNr(void);
void SetCommand(int Command, char *Text);
int GetCommand(void);
char *GetCommandBuffer(void);
void InitSHM(bool Verbose);
void ExitSHM(void);
void InitSHMExtern(bool Verbose);
void ExitSHMExtern(void);
// strings.cc
// =============================================================================
const char *AddStaticString(const char *String);
uint32 AddDynamicString(const char *String);
const char *GetDynamicString(uint32 Number);
void DeleteDynamicString(uint32 Number);
void CleanupDynamicStrings(void);
void InitStrings(void);
void ExitStrings(void);
bool IsCountable(const char *s);
const char *Plural(const char *s, int Count);
const char *SearchForWord(const char *Pattern, const char *Text);
const char *SearchForNumber(int Count, const char *Text);
bool MatchString(const char *Pattern, const char *String);
void AddSlashes(char *Destination, const char *Source);
void Trim(char *Text);
void Trim(char *Destination, const char *Source);
char *Capitals(char *Text);
// time.cc
// =============================================================================
extern uint32 RoundNr;
extern uint32 ServerMilliseconds;
struct tm GetLocalTimeTM(time_t t);
void GetRealTime(int *Hour, int *Minute);
void GetTime(int *Hour, int *Minute);
void GetDate(int *Year, int *Cycle, int *Day);
void GetAmbiente(int *Brightness, int *Color);
uint32 GetRoundAtTime(int Hour, int Minute);
uint32 GetRoundForNextMinute(void);
// utils.cc
// =============================================================================
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);
bool FileExists(const char *FileName);
bool isSpace(int c);
bool isAlpha(int c);
bool isEngAlpha(int c);
bool isDigit(int c);
int toLower(int c);
int toUpper(int c);
char *strLower(char *s);
char *strUpper(char *s);
int stricmp(const char *s1, const char *s2, int Max = INT_MAX);
char *findFirst(char *s, char c);
char *findLast(char *s, char c);
bool CheckBitIndex(int BitSetBytes, int Index);
bool CheckBit(uint8 *BitSet, int Index);
void SetBit(uint8 *BitSet, int Index);
void ClearBit(uint8 *BitSet, int Index);
template<typename T>
void RandomShuffle(T *Buffer, int Size){
if(Buffer == NULL){
error("RandomShuffle: Buffer ist NULL.\n");
return;
}
int Max = Size - 1;
for(int Min = 0; Min < Max; Min += 1){
int Swap = random(Min, Max);
if(Swap != Min){
std::swap(Buffer[Min], Buffer[Swap]);
}
}
}
struct TReadStream {
// VIRTUAL FUNCTIONS
// =================
virtual bool readFlag(void); // VTABLE[0]
virtual uint8 readByte(void) = 0; // VTABLE[1]
virtual uint16 readWord(void); // VTABLE[2]
virtual uint32 readQuad(void); // VTABLE[3]
virtual void readString(char *Buffer, int MaxLength); // VTABLE[4]
virtual void readBytes(uint8 *Buffer, int Count); // VTABLE[5]
virtual bool eof(void) = 0; // VTABLE[6]
virtual void skip(int Count) = 0; // VTABLE[7]
};
struct TReadBuffer: TReadStream {
TReadBuffer(const uint8 *Data, int Size);
// VIRTUAL FUNCTIONS
// =================
uint8 readByte(void) override;
uint16 readWord(void) override;
uint32 readQuad(void) override;
void readBytes(uint8 *Buffer, int Count) override;
bool eof(void) override;
void skip(int Count) override;
// DATA
// =================
const uint8 *Data;
int Size;
int Position;
};
struct TWriteStream {
// VIRTUAL FUNCTIONS
// =================
virtual void writeFlag(bool Flag); // VTABLE[0]
virtual void writeByte(uint8 Byte) = 0; // VTABLE[1]
virtual void writeWord(uint16 Word); // VTABLE[2]
virtual void writeQuad(uint32 Quad); // VTABLE[3]
virtual void writeString(const char *String); // VTABLE[4]
virtual void writeBytes(const uint8 *Buffer, int Count); // VTABLE[5]
};
struct TWriteBuffer: TWriteStream {
TWriteBuffer(uint8 *Data, int Size);
// VIRTUAL FUNCTIONS
// =================
void writeByte(uint8 Byte) override;
void writeWord(uint16 Word) override;
void writeQuad(uint32 Quad) override;
void writeBytes(const uint8 *Buffer, int Count) override;
// DATA
// =================
uint8 *Data;
int Size;
int Position;
};
struct TDynamicWriteBuffer: TWriteBuffer {
TDynamicWriteBuffer(int InitialSize);
void resizeBuffer(void);
// VIRTUAL FUNCTIONS
// =================
void writeByte(uint8 Byte) override;
void writeWord(uint16 Word) override;
void writeQuad(uint32 Quad) override;
void writeBytes(const uint8 *Buffer, int Count) override;
// TODO(fusion): Appended virtual functions. These are not in the base class
// VTABLE which can be problematic if we intend to use polymorphism, although
// that doesn't seem to be case.
virtual ~TDynamicWriteBuffer(void); // VTABLE[6]
// Duplicate destructor that also calls operator delete. // VTABLE[7]
};
#endif //TIBIA_COMMON_HH_
|