aboutsummaryrefslogtreecommitdiff
path: root/sql/schema.sql
blob: c8a78ecc375f9d5ea405bfa2433e41fcd2484f89 (plain) (blame)
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
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
-- Primary Tables
--==============================================================================
CREATE TABLE IF NOT EXISTS Worlds (
	WorldID INTEGER NOT NULL,
	Name TEXT NOT NULL COLLATE NOCASE,
	Type INTEGER NOT NULL,
	RebootTime INTEGER NOT NULL,
	IPAddress INTEGER NOT NULL,
	Port INTEGER NOT NULL,
	MaxPlayers INTEGER NOT NULL,
	PremiumPlayerBuffer INTEGER NOT NULL,
	MaxNewbies INTEGER NOT NULL,
	PremiumNewbieBuffer INTEGER NOT NULL,
	OnlineRecord INTEGER NOT NULL DEFAULT 0,
	PRIMARY KEY (WorldID),
	UNIQUE (Name)
);

CREATE TABLE IF NOT EXISTS Accounts (
	AccountID INTEGER NOT NULL,
	Email TEXT NOT NULL COLLATE NOCASE,
	Auth BLOB NOT NULL,
	PremiumEnd INTEGER NOT NULL DEFAULT 0,
	PendingPremiumDays INTEGER NOT NULL DEFAULT 0,
	Deleted INTEGER NOT NULL DEFAULT 0,
	PRIMARY KEY (AccountID),
	UNIQUE (Email)
);

CREATE TABLE IF NOT EXISTS Characters (
	WorldID INTEGER NOT NULL,
	CharacterID INTEGER NOT NULL,
	AccountID INTEGER NOT NULL,
	Name TEXT NOT NULL COLLATE NOCASE,
	Sex INTEGER NOT NULL,
	Guild TEXT NOT NULL COLLATE NOCASE DEFAULT '',
	Rank TEXT NOT NULL COLLATE NOCASE DEFAULT '',
	Title TEXT NOT NULL COLLATE NOCASE DEFAULT '',
	Level INTEGER NOT NULL DEFAULT 0,
	Profession TEXT NOT NULL DEFAULT '',
	Residence TEXT NOT NULL DEFAULT '',
	LastLoginTime INTEGER NOT NULL DEFAULT 0,
	TutorActivities INTEGER NOT NULL DEFAULT 0,
	IsOnline INTEGER NOT NULL DEFAULT 0,
	Deleted INTEGER NOT NULL DEFAULT 0,
	PRIMARY KEY (CharacterID),
	UNIQUE (Name)
);
CREATE INDEX IF NOT EXISTS CharactersWorldIndex
		ON Characters(WorldID, IsOnline);
CREATE INDEX IF NOT EXISTS CharactersAccountIndex
		ON Characters(AccountID, IsOnline);
CREATE INDEX IF NOT EXISTS CharactersGuildIndex
		ON Characters(Guild, Rank);

CREATE TABLE IF NOT EXISTS CharacterRights (
	CharacterID INTEGER NOT NULL,
	Right TEXT NOT NULL COLLATE NOCASE,
	PRIMARY KEY(CharacterID, Right)
);

CREATE TABLE IF NOT EXISTS CharacterDeaths (
	CharacterID INTEGER NOT NULL,
	Level INTEGER NOT NULL,
	OffenderID INTEGER NOT NULL,
	Remark TEXT NOT NULL,
	Unjustified INTEGER NOT NULL,
	Timestamp INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS CharacterDeathsCharacterIndex
		ON CharacterDeaths(CharacterID, Level);
CREATE INDEX IF NOT EXISTS CharacterDeathsOffenderIndex
		ON CharacterDeaths(OffenderID, Unjustified);

CREATE TABLE IF NOT EXISTS Buddies (
	WorldID INTEGER NOT NULL,
	AccountID INTEGER NOT NULL,
	BuddyID INTEGER NOT NULL,
	PRIMARY KEY (WorldID, AccountID, BuddyID)
);

CREATE TABLE IF NOT EXISTS WorldInvitations (
	WorldID INTEGER NOT NULL,
	CharacterID INTEGER NOT NULL,
	PRIMARY KEY (WorldID, CharacterID)
);

CREATE TABLE IF NOT EXISTS LoginAttempts (
	AccountID INTEGER NOT NULL,
	IPAddress INTEGER NOT NULL,
	Timestamp INTEGER NOT NULL,
	Failed INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS LoginAttemptsAccountIndex
		ON LoginAttempts(AccountID, Timestamp);
CREATE INDEX IF NOT EXISTS LoginAttemptsAddressIndex
		ON LoginAttempts(IPAddress, Timestamp);

-- House Tables
--==============================================================================
CREATE TABLE IF NOT EXISTS Houses (
	WorldID INTEGER NOT NULL,
	HouseID INTEGER NOT NULL,
	Name TEXT NOT NULL,
	Rent INTEGER NOT NULL,
	Description TEXT NOT NULL,
	Size INTEGER NOT NULL,
	PositionX INTEGER NOT NULL,
	PositionY INTEGER NOT NULL,
	PositionZ INTEGER NOT NULL,
	Town TEXT NOT NULL,
	GuildHouse INTEGER NOT NULL,
	PRIMARY KEY (WorldID, HouseID)
);

CREATE TABLE IF NOT EXISTS HouseOwners (
	WorldID INTEGER NOT NULL,
	HouseID INTEGER NOT NULL,
	OwnerID INTEGER NOT NULL,
	PaidUntil INTEGER NOT NULL,
	PRIMARY KEY (WorldID, HouseID)
);

-- NOTE(fusion): An auction would have a non null `FinishTime` but it doesn't make
-- sense to finish an auction just to restart it afterwards so it should only be
-- set after the first bid, along with `BidderID` and `BidAmount`.
CREATE TABLE IF NOT EXISTS HouseAuctions (
	WorldID INTEGER NOT NULL,
	HouseID INTEGER NOT NULL,
	BidderID INTEGER DEFAULT NULL,
	BidAmount INTEGER DEFAULT NULL,
	FinishTime INTEGER DEFAULT NULL,
	PRIMARY KEY (WorldID, HouseID)
);

CREATE TABLE IF NOT EXISTS HouseTransfers (
	WorldID INTEGER NOT NULL,
	HouseID INTEGER NOT NULL,
	NewOwnerID INTEGER NOT NULL,
	Price INTEGER NOT NULL,
	PRIMARY KEY (WorldID, HouseID)
);

CREATE TABLE IF NOT EXISTS HouseAuctionExclusions (
	CharacterID INTEGER NOT NULL,
	Issued INTEGER NOT NULL,
	Until INTEGER NOT NULL,
	BanishmentID INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS HouseAuctionExclusionsIndex
		ON HouseAuctionExclusions(CharacterID, Until);

CREATE TABLE IF NOT EXISTS HouseAssignments (
	WorldID INTEGER NOT NULL,
	HouseID INTEGER NOT NULL,
	OwnerID INTEGER NOT NULL,
	Price INTEGER NOT NULL,
	Timestamp INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS HouseAssignmentsHouseIndex
		ON HouseAssignments(WorldID, HouseID);
CREATE INDEX IF NOT EXISTS HouseAssignmentsTimeIndex
		ON HouseAssignments(WorldID, Timestamp);
CREATE INDEX IF NOT EXISTS HouseAssignmentsOwnerIndex
		ON HouseAssignments(OwnerID);

-- Banishment Tables
--==============================================================================
CREATE TABLE IF NOT EXISTS Banishments (
	BanishmentID INTEGER NOT NULL,
	AccountID INTEGER NOT NULL,
	IPAddress INTEGER NOT NULL,
	GamemasterID INTEGER NOT NULL,
	Reason TEXT NOT NULL,
	Comment TEXT NOT NULL,
	FinalWarning INTEGER NOT NULL,
	Issued INTEGER NOT NULL,
	Until INTEGER NOT NULL,
	PRIMARY KEY (BanishmentID)
);
CREATE INDEX IF NOT EXISTS BanishmentsAccountIndex
		ON Banishments(AccountID, Until, FinalWarning);

CREATE TABLE IF NOT EXISTS IPBanishments (
	CharacterID INTEGER NOT NULL,
	IPAddress INTEGER NOT NULL,
	GamemasterID INTEGER NOT NULL,
	Reason TEXT NOT NULL,
	Comment TEXT NOT NULL,
	Issued INTEGER NOT NULL,
	Until INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS IPBanishmentsAddressIndex
		ON IPBanishments(IPAddress);
CREATE INDEX IF NOT EXISTS IPBanishmentsCharacterIndex
		ON IPBanishments(CharacterID);

CREATE TABLE IF NOT EXISTS Namelocks (
	CharacterID INTEGER NOT NULL,
	IPAddress INTEGER NOT NULL,
	GamemasterID INTEGER NOT NULL,
	Reason TEXT NOT NULL,
	Comment TEXT NOT NULL,
	Attempts INTEGER NOT NULL DEFAULT 0,
	Approved INTEGER NOT NULL DEFAULT 0,
	PRIMARY KEY (CharacterID)
);

CREATE TABLE IF NOT EXISTS Notations (
	CharacterID INTEGER NOT NULL,
	IPAddress INTEGER NOT NULL,
	GamemasterID INTEGER NOT NULL,
	Reason TEXT NOT NULL,
	Comment TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS NotationsCharacterIndex
		ON Notations(CharacterID);

CREATE TABLE IF NOT EXISTS Statements (
	WorldID INTEGER NOT NULL,
	Timestamp INTEGER NOT NULL,
	StatementID INTEGER NOT NULL,
	CharacterID INTEGER NOT NULL,
	Channel TEXT NOT NULL,
	Text TEXT NOT NULL,
	PRIMARY KEY (WorldID, Timestamp, StatementID)
);
CREATE INDEX IF NOT EXISTS StatementsCharacterIndex
		ON Statements(CharacterID, Timestamp);

CREATE TABLE IF NOT EXISTS ReportedStatements (
	WorldID INTEGER NOT NULL,
	Timestamp INTEGER NOT NULL,
	StatementID INTEGER NOT NULL,
	CharacterID INTEGER NOT NULL,
	BanishmentID INTEGER NOT NULL,
	ReporterID INTEGER NOT NULL,
	Reason TEXT NOT NULL,
	Comment TEXT NOT NULL,
	PRIMARY KEY (WorldID, Timestamp, StatementID)
);
CREATE INDEX IF NOT EXISTS ReportedStatementsCharacterIndex
		ON ReportedStatements(CharacterID, Timestamp);
CREATE INDEX IF NOT EXISTS ReportedStatementsBanishmentIndex
		ON ReportedStatements(BanishmentID);

-- Info Tables
--==============================================================================
CREATE TABLE IF NOT EXISTS KillStatistics (
	WorldID INTEGER NOT NULL,
	RaceName TEXT NOT NULL COLLATE NOCASE,
	TimesKilled INTEGER NOT NULL,
	PlayersKilled INTEGER NOT NULL,
	PRIMARY KEY (WorldID, RaceName)
);

CREATE TABLE IF NOT EXISTS OnlineCharacters (
	WorldID INTEGER NOT NULL,
	Name TEXT NOT NULL COLLATE NOCASE,
	Level INTEGER NOT NULL,
	Profession TEXT NOT NULL,
	PRIMARY KEY (WorldID, Name)
);

-- REMOVE(fusion): Testing Data.
--==============================================================================
INSERT INTO Worlds (WorldID, Name, Type, RebootTime, IPAddress, Port, MaxPlayers,
					PremiumPlayerBuffer, MaxNewbies, PremiumNewbieBuffer)
	VALUES (1, 'Zanera', 0, 5, 0x7F000001, 7172, 1000, 100, 300, 100);

-- 111111/tibia
INSERT INTO Accounts (AccountID, Email, Auth)
	VALUES (111111, '@tibia', X'206699cbc2fae1683118c873d746aa376049cb5923ef0980298bb7acbba527ec9e765668f7a338dffea34acf61a20efb654c1e9c62d35148dba2aeeef8dc7788');

INSERT INTO Characters (WorldID, CharacterID, AccountID, Name, Sex)
	VALUES (1, 1, 111111, 'Gamemaster', 1), (1, 2, 111111, 'Player', 1);

INSERT INTO CharacterRights (CharacterID, Right)
	VALUES
		(1, 'NOTATION'),
		(1, 'NAMELOCK'),
		(1, 'STATEMENT_REPORT'),
		(1, 'BANISHMENT'),
		(1, 'FINAL_WARNING'),
		(1, 'IP_BANISHMENT'),
		(1, 'KICK'),
		(1, 'HOME_TELEPORT'),
		(1, 'GAMEMASTER_BROADCAST'),
		(1, 'ANONYMOUS_BROADCAST'),
		(1, 'NO_BANISHMENT'),
		(1, 'ALLOW_MULTICLIENT'),
		(1, 'LOG_COMMUNICATION'),
		(1, 'READ_GAMEMASTER_CHANNEL'),
		(1, 'READ_TUTOR_CHANNEL'),
		(1, 'HIGHLIGHT_HELP_CHANNEL'),
		(1, 'SEND_BUGREPORTS'),
		(1, 'NAME_INSULTING'),
		(1, 'NAME_SENTENCE'),
		(1, 'NAME_NONSENSICAL_LETTERS'),
		(1, 'NAME_BADLY_FORMATTED'),
		(1, 'NAME_NO_PERSON'),
		(1, 'NAME_CELEBRITY'),
		(1, 'NAME_COUNTRY'),
		(1, 'NAME_FAKE_IDENTITY'),
		(1, 'NAME_FAKE_POSITION'),
		(1, 'STATEMENT_INSULTING'),
		(1, 'STATEMENT_SPAMMING'),
		(1, 'STATEMENT_ADVERT_OFFTOPIC'),
		(1, 'STATEMENT_ADVERT_MONEY'),
		(1, 'STATEMENT_NON_ENGLISH'),
		(1, 'STATEMENT_CHANNEL_OFFTOPIC'),
		(1, 'STATEMENT_VIOLATION_INCITING'),
		(1, 'CHEATING_BUG_ABUSE'),
		(1, 'CHEATING_GAME_WEAKNESS'),
		(1, 'CHEATING_MACRO_USE'),
		(1, 'CHEATING_MODIFIED_CLIENT'),
		(1, 'CHEATING_HACKING'),
		(1, 'CHEATING_MULTI_CLIENT'),
		(1, 'CHEATING_ACCOUNT_TRADING'),
		(1, 'CHEATING_ACCOUNT_SHARING'),
		(1, 'GAMEMASTER_THREATENING'),
		(1, 'GAMEMASTER_PRETENDING'),
		(1, 'GAMEMASTER_INFLUENCE'),
		(1, 'GAMEMASTER_FALSE_REPORTS'),
		(1, 'KILLING_EXCESSIVE_UNJUSTIFIED'),
		(1, 'DESTRUCTIVE_BEHAVIOUR'),
		(1, 'SPOILING_AUCTION'),
		(1, 'INVALID_PAYMENT'),
		(1, 'TELEPORT_TO_CHARACTER'),
		(1, 'TELEPORT_TO_MARK'),
		(1, 'TELEPORT_VERTICAL'),
		(1, 'TELEPORT_TO_COORDINATE'),
		(1, 'LEVITATE'),
		(1, 'SPECIAL_MOVEUSE'),
		(1, 'MODIFY_GOSTRENGTH'),
		(1, 'SHOW_COORDINATE'),
		(1, 'RETRIEVE'),
		(1, 'ENTER_HOUSES'),
		(1, 'OPEN_NAMEDOORS'),
		(1, 'INVULNERABLE'),
		(1, 'UNLIMITED_MANA'),
		(1, 'KEEP_INVENTORY'),
		(1, 'ALL_SPELLS'),
		(1, 'UNLIMITED_CAPACITY'),
		(1, 'ATTACK_EVERYWHERE'),
		(1, 'NO_LOGOUT_BLOCK'),
		(1, 'GAMEMASTER_OUTFIT'),
		(1, 'ILLUMINATE'),
		(1, 'CHANGE_PROFESSION'),
		(1, 'IGNORED_BY_MONSTERS'),
		(1, 'SHOW_KEYHOLE_NUMBERS'),
		(1, 'CREATE_OBJECTS'),
		(1, 'CREATE_MONEY'),
		(1, 'CREATE_MONSTERS'),
		(1, 'CHANGE_SKILLS'),
		(1, 'CLEANUP_FIELDS'),
		(1, 'NO_STATISTICS');