Merge branch 'DarkflameUniverse:main' into main

This commit is contained in:
Nils Bergmann 2021-12-07 23:03:30 +01:00 committed by GitHub
commit 0d910e3307
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 189 additions and 134 deletions

View File

@ -95,7 +95,7 @@ if (__include_backtrace__ AND __compile_backtrace__)
link_directories(${backtrace_SOURCE_DIR}/.libs/) link_directories(${backtrace_SOURCE_DIR}/.libs/)
include_directories(${backtrace_SOURCE_DIR}) include_directories(${backtrace_SOURCE_DIR})
endif(__include_backtrace__) endif(__include_backtrace__ AND __compile_backtrace__)
endif() endif()
endif(UNIX) endif(UNIX)

View File

@ -52,7 +52,7 @@ This project has gone through multiple iterations of coding style. In the code y
### General ### General
Use 4 spaces instead of the tab character. **Never** use spaces instead of tabs. 1 Tab = 4 space character's width by default.
Use typically trailing braces everywhere (if, else, functions, structures, typedefs, class definitions, etc.) Use typically trailing braces everywhere (if, else, functions, structures, typedefs, class definitions, etc.)

View File

@ -80,8 +80,8 @@ sudo ln -s /usr/local/mysql-connector-c++/lib64/libssl.1.1.dylib /path/to/build/
sudo ln -s /usr/local/mysql-connector-c++/lib64/libcrypto.1.1.dylib /path/to/build/folder/libcrypto.1.1.dylib sudo ln -s /usr/local/mysql-connector-c++/lib64/libcrypto.1.1.dylib /path/to/build/folder/libcrypto.1.1.dylib
``` ```
### Windows builds (native) (CURRENTLY BROKEN ONCE COMPILED) ### Windows builds (native)
Ensure that you have either the [MSVC](https://visualstudio.microsoft.com/vs/) or the [Clang](https://github.com/llvm/llvm-project/releases/) (recommended) compiler installed. You will also need to install [CMake](https://cmake.org/download/). Ensure that you have either the [MSVC](https://visualstudio.microsoft.com/vs/) or the [Clang](https://github.com/llvm/llvm-project/releases/) (recommended) compiler installed. You will also need to install [CMake](https://cmake.org/download/). Currently on native Windows the server will only work in Release mode.
**Build the repository** **Build the repository**
```batch ```batch

View File

@ -21,8 +21,9 @@ dChatFilter::dChatFilter(const std::string& filepath, bool dontGenerateDCF) {
ReadWordlistPlaintext(filepath + ".txt"); ReadWordlistPlaintext(filepath + ".txt");
if (!m_DontGenerateDCF) ExportWordlistToDCF(filepath + ".dcf"); if (!m_DontGenerateDCF) ExportWordlistToDCF(filepath + ".dcf");
} }
else { else if (!ReadWordlistDCF(filepath + ".dcf")) {
ReadWordlistDCF(filepath + ".dcf"); ReadWordlistPlaintext(filepath + ".txt");
ExportWordlistToDCF(filepath + ".dcf");
} }
//Read player names that are ok as well: //Read player names that are ok as well:
@ -46,24 +47,24 @@ void dChatFilter::ReadWordlistPlaintext(const std::string& filepath) {
if (file) { if (file) {
std::string line; std::string line;
while (std::getline(file, line)) { while (std::getline(file, line)) {
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase
m_Words.push_back(CalculateHash(line)); m_Words.push_back(CalculateHash(line));
} }
} }
} }
void dChatFilter::ReadWordlistDCF(const std::string& filepath) { bool dChatFilter::ReadWordlistDCF(const std::string& filepath) {
std::ifstream file(filepath, std::ios::binary); std::ifstream file(filepath, std::ios::binary);
if (file) { if (file) {
fileHeader hdr; fileHeader hdr;
BinaryIO::BinaryRead(file, hdr); BinaryIO::BinaryRead(file, hdr);
if (hdr.header != header) { if (hdr.header != header) {
std::cout << "Wrong file header!" << std::endl;
file.close(); file.close();
return; return false;
} }
if (hdr.formatVersion <= formatVersion) { if (hdr.formatVersion == formatVersion) {
size_t wordsToRead = 0; size_t wordsToRead = 0;
BinaryIO::BinaryRead(file, wordsToRead); BinaryIO::BinaryRead(file, wordsToRead);
m_Words.reserve(wordsToRead); m_Words.reserve(wordsToRead);
@ -73,17 +74,20 @@ void dChatFilter::ReadWordlistDCF(const std::string& filepath) {
BinaryIO::BinaryRead(file, word); BinaryIO::BinaryRead(file, word);
m_Words.push_back(word); m_Words.push_back(word);
} }
return true;
} }
else { else {
std::cout << "Newer file or corrupt" << std::endl;
file.close(); file.close();
return; return false;
} }
} }
return false;
} }
void dChatFilter::ExportWordlistToDCF(const std::string& filepath) { void dChatFilter::ExportWordlistToDCF(const std::string& filepath) {
std::ofstream file(filepath, std::ios::binary); std::ofstream file(filepath, std::ios::binary | std::ios_base::out);
if (file) { if (file) {
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::header)); BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::header));
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::formatVersion)); BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::formatVersion));

View File

@ -6,7 +6,7 @@
namespace dChatFilterDCF { namespace dChatFilterDCF {
static const uint32_t header = ('D' + ('C' << 8) + ('F' << 16) + ('B' << 24)); static const uint32_t header = ('D' + ('C' << 8) + ('F' << 16) + ('B' << 24));
static const uint32_t formatVersion = 1; static const uint32_t formatVersion = 2;
struct fileHeader { struct fileHeader {
uint32_t header; uint32_t header;
@ -21,7 +21,7 @@ public:
~dChatFilter(); ~dChatFilter();
void ReadWordlistPlaintext(const std::string & filepath); void ReadWordlistPlaintext(const std::string & filepath);
void ReadWordlistDCF(const std::string & filepath); bool ReadWordlistDCF(const std::string & filepath);
void ExportWordlistToDCF(const std::string & filepath); void ExportWordlistToDCF(const std::string & filepath);
bool IsSentenceOkay(const std::string& message, int gmLevel); bool IsSentenceOkay(const std::string& message, int gmLevel);

View File

@ -92,8 +92,8 @@ void dLogger::Log(const char * className, const char * format, ...) {
va_end(args); va_end(args);
if (m_logToConsole) std::cout << "[" << "timeStr" << "] [" << className << "]: " << message; if (m_logToConsole) std::cout << "[" << timeStr << "] [" << className << "]: " << message;
mFile << "[" << "timeStr" << "] [" << className << "]: " << message; mFile << "[" << timeStr << "] [" << className << "]: " << message;
#else #else
time_t t = time(NULL); time_t t = time(NULL);
struct tm * time = localtime(&t); struct tm * time = localtime(&t);

View File

@ -1222,13 +1222,19 @@ void Entity::UpdateXMLDoc(tinyxml2::XMLDocument* doc) {
} }
void Entity::Update(const float deltaTime) { void Entity::Update(const float deltaTime) {
for (int i = 0; i < m_Timers.size(); i++) { int timerSize = m_Timers.size();
for (int i = 0; i < timerSize; i++) {
m_Timers[i]->Update(deltaTime); m_Timers[i]->Update(deltaTime);
if (m_Timers[i]->GetTime() <= 0) { if (m_Timers[i]->GetTime() <= 0) {
const auto timerName = m_Timers[i]->GetName(); const auto timerName = m_Timers[i]->GetName();
delete m_Timers[i]; do { //sometimes, due to a race condition, m_Timers.erase doesn't actually erase, repeat until it does
m_Timers.erase(m_Timers.begin() + i); if (m_Timers[i]->GetName() != timerName) {
break;
}
delete m_Timers[i];
m_Timers.erase(m_Timers.begin() + i);
} while (m_Timers.size() == timerSize); //timer size indicates whether it's actually successfully been erased or not
for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) { for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
script->OnTimerDone(this, timerName); script->OnTimerDone(this, timerName);

View File

@ -153,27 +153,26 @@ void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, const LWOOB
delete gmlevel; delete gmlevel;
delete chatmode; delete chatmode;
delete name; delete name;
#ifdef _WIN32
bitStream.Write<uint32_t>(data.GetNumberOfBytesUsed() + 1);
bitStream.Write<uint8_t>(0);
bitStream.Write((char*)data.GetData(), data.GetNumberOfBytesUsed());
#else
//Compress the data before sending: //Compress the data before sending:
const int reservedSize = 5 * 1024 * 1024; const int reservedSize = 5 * 1024 * 1024;
uint8_t compressedData[reservedSize]; uint8_t compressedData[reservedSize];
size_t size = ZCompression::Compress(data.GetData(), data.GetNumberOfBytesUsed(), compressedData, reservedSize); size_t size = ZCompression::Compress(data.GetData(), data.GetNumberOfBytesUsed(), compressedData, reservedSize);
bitStream.Write<uint32_t>(size + 9); //size of data + header bytes (8) bitStream.Write<uint32_t>(size + 9); //size of data + header bytes (8)
bitStream.Write<uint8_t>(1); //compressed boolean, true bitStream.Write<uint8_t>(1); //compressed boolean, true
bitStream.Write<uint32_t>(data.GetNumberOfBytesUsed()); bitStream.Write<uint32_t>(data.GetNumberOfBytesUsed());
bitStream.Write<uint32_t>(size); bitStream.Write<uint32_t>(size);
for (size_t i = 0; i < size; i++) for (size_t i = 0; i < size; i++)
bitStream.Write(compressedData[i]); bitStream.Write(compressedData[i]);
#endif
/*
uint32_t dataSize = data.GetNumberOfBytesUsed();
bitStream.Write(dataSize + 8); // The data size
bitStream.Write(static_cast<uint8_t>(0)); // Data is not compressed
bitStream.Write(data); // Write the data
*/
PacketUtils::SavePacket("chardata.bin", (const char *)bitStream.GetData(), static_cast<uint32_t>(bitStream.GetNumberOfBytesUsed())); PacketUtils::SavePacket("chardata.bin", (const char *)bitStream.GetData(), static_cast<uint32_t>(bitStream.GetNumberOfBytesUsed()));
SEND_PACKET SEND_PACKET
Game::logger->Log("WorldPackets", "Sent CreateCharacter for ID: %llu\n", objectID); Game::logger->Log("WorldPackets", "Sent CreateCharacter for ID: %llu\n", objectID);

93
dScripts/AgShipShake.cpp Normal file
View File

@ -0,0 +1,93 @@
#include "AgShipShake.h"
#include "GeneralUtils.h"
#include "GameMessages.h"
#include "dZoneManager.h"
#include "EntityManager.h"
#include "Game.h"
void AgShipShake::OnStartup(Entity* self) {
EntityInfo info{};
info.pos = { -418, 585, -30 };
info.lot = 33;
info.spawnerID = self->GetObjectID();
auto* ref = EntityManager::Instance()->CreateEntity(info);
EntityManager::Instance()->ConstructEntity(ref);
self->SetVar(u"ShakeObject", ref->GetObjectID());
self->AddTimer("ShipShakeIdle", 1.0f);
self->SetVar(u"RandomTime", 10);
}
void AgShipShake::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "ShipShakeExplode") {
DoShake(self, true);
}
else if (timerName == "ShipShakeIdle") {
DoShake(self, false);
}
}
void AgShipShake::DoShake(Entity* self, bool explodeIdle) {
if (!explodeIdle) {
auto* ref = EntityManager::Instance()->GetEntity(self->GetVar<LWOOBJID>(u"ShakeObject"));
const auto randomTime = self->GetVar<int>(u"RandomTime");
auto time = GeneralUtils::GenerateRandomNumber<int>(0, randomTime + 1);
if (time < randomTime / 2) {
time += randomTime / 2;
}
self->AddTimer("ShipShakeIdle", static_cast<float>(time));
if (ref)
GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(ref, FXName, ref->GetObjectID(), 500.0f);
auto* debrisObject = GetEntityInGroup(DebrisFX);
if (debrisObject)
GameMessages::SendPlayFXEffect(debrisObject, -1, u"DebrisFall", "Debris", LWOOBJID_EMPTY, 1.0f, 1.0f, true);
const auto randomFx = GeneralUtils::GenerateRandomNumber<int>(0, 3);
auto* shipFxObject = GetEntityInGroup(ShipFX);
if (shipFxObject) {
std::string effectType = "shipboom" + std::to_string(randomFx);
GameMessages::SendPlayFXEffect(shipFxObject, 559, GeneralUtils::ASCIIToUTF16(effectType), "FX", LWOOBJID_EMPTY, 1.0f, 1.0f, true);
}
self->AddTimer("ShipShakeExplode", 5.0f);
auto* shipFxObject2 = GetEntityInGroup(ShipFX2);
if (shipFxObject2)
GameMessages::SendPlayAnimation(shipFxObject2, u"explosion");
}
else {
auto* shipFxObject = GetEntityInGroup(ShipFX);
auto* shipFxObject2 = GetEntityInGroup(ShipFX2);
if (shipFxObject)
GameMessages::SendPlayAnimation(shipFxObject, u"idle");
if (shipFxObject2)
GameMessages::SendPlayAnimation(shipFxObject2, u"idle");
}
}
Entity* AgShipShake::GetEntityInGroup(const std::string& group) {
auto entities = EntityManager::Instance()->GetEntitiesInGroup(group);
Entity* en = nullptr;
for (auto entity : entities) {
if (entity) {
en = entity;
break;
}
}
return en;
}

18
dScripts/AgShipShake.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include "CppScripts.h"
class AgShipShake : public CppScripts::Script {
public:
void OnStartup(Entity* self);
void OnTimerDone(Entity* self, std::string timerName);
void DoShake(Entity* self, bool explodeIdle);
std::string DebrisFX = "DebrisFX";
std::string ShipFX = "ShipFX";
std::string ShipFX2 = "ShipFX2";
std::u16string FXName = u"camshake-bridge";
private:
Entity* GetEntityInGroup(const std::string& group);
};

View File

@ -1,7 +1,6 @@
#include "AgSpaceStuff.h" #include "AgSpaceStuff.h"
#include "GeneralUtils.h" #include "GeneralUtils.h"
#include "GameMessages.h" #include "GameMessages.h"
#include "dZoneManager.h"
#include "EntityManager.h" #include "EntityManager.h"
#include "Game.h" #include "Game.h"
@ -17,11 +16,6 @@ void AgSpaceStuff::OnStartup(Entity* self) {
auto* ref = EntityManager::Instance()->CreateEntity(info); auto* ref = EntityManager::Instance()->CreateEntity(info);
EntityManager::Instance()->ConstructEntity(ref); EntityManager::Instance()->ConstructEntity(ref);
self->SetVar(u"ShakeObject", ref->GetObjectID());
self->AddTimer("ShipShakeIdle", 1.0f);
self->SetVar(u"RandomTime", 10);
} }
void AgSpaceStuff::OnTimerDone(Entity* self, std::string timerName) { void AgSpaceStuff::OnTimerDone(Entity* self, std::string timerName) {
@ -38,72 +32,4 @@ void AgSpaceStuff::OnTimerDone(Entity* self, std::string timerName) {
GameMessages::SendPlayAnimation(self, u"path_0" + (GeneralUtils::to_u16string(pathType))); GameMessages::SendPlayAnimation(self, u"path_0" + (GeneralUtils::to_u16string(pathType)));
self->AddTimer("FloaterScale", randTime); self->AddTimer("FloaterScale", randTime);
} }
else if (timerName == "ShipShakeExplode") {
DoShake(self, true);
}
else if (timerName == "ShipShakeIdle") {
DoShake(self, false);
}
}
void AgSpaceStuff::DoShake(Entity* self, bool explodeIdle) {
if (!explodeIdle) {
auto* ref = EntityManager::Instance()->GetEntity(self->GetVar<LWOOBJID>(u"ShakeObject"));
const auto randomTime = self->GetVar<int>(u"RandomTime");
auto time = GeneralUtils::GenerateRandomNumber<int>(0, randomTime + 1);
if (time < randomTime / 2) {
time += randomTime / 2;
}
self->AddTimer("ShipShakeIdle", static_cast<float>(time));
if (ref)
GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(ref, FXName, ref->GetObjectID(), 500.0f);
auto* debrisObject = GetEntityInGroup(DebrisFX);
if (debrisObject)
GameMessages::SendPlayFXEffect(debrisObject, -1, u"DebrisFall", "Debris", LWOOBJID_EMPTY, 1.0f, 1.0f, true);
const auto randomFx = GeneralUtils::GenerateRandomNumber<int>(0, 3);
auto* shipFxObject = GetEntityInGroup(ShipFX);
if (shipFxObject) {
std::string effectType = "shipboom" + std::to_string(randomFx);
GameMessages::SendPlayFXEffect(shipFxObject, 559, GeneralUtils::ASCIIToUTF16(effectType), "FX", LWOOBJID_EMPTY, 1.0f, 1.0f, true);
}
self->AddTimer("ShipShakeExplode", 5.0f);
auto* shipFxObject2 = GetEntityInGroup(ShipFX2);
if (shipFxObject2)
GameMessages::SendPlayAnimation(shipFxObject2, u"explosion");
}
else {
auto* shipFxObject = GetEntityInGroup(ShipFX);
auto* shipFxObject2 = GetEntityInGroup(ShipFX2);
if (shipFxObject)
GameMessages::SendPlayAnimation(shipFxObject, u"idle");
if (shipFxObject2)
GameMessages::SendPlayAnimation(shipFxObject2, u"idle");
}
}
Entity* AgSpaceStuff::GetEntityInGroup(const std::string& group) {
auto entities = EntityManager::Instance()->GetEntitiesInGroup(group);
Entity* en = nullptr;
for (auto entity : entities) {
if (entity) {
en = entity;
break;
}
}
return en;
} }

View File

@ -5,14 +5,4 @@ class AgSpaceStuff : public CppScripts::Script {
public: public:
void OnStartup(Entity* self); void OnStartup(Entity* self);
void OnTimerDone(Entity* self, std::string timerName); void OnTimerDone(Entity* self, std::string timerName);
void DoShake(Entity* self, bool explodeIdle);
std::string DebrisFX = "DebrisFX";
std::string ShipFX = "ShipFX";
std::string ShipFX2 = "ShipFX2";
std::u16string FXName = u"camshake-bridge";
private:
Entity* GetEntityInGroup(const std::string& group);
}; };

View File

@ -15,6 +15,7 @@
//VE / AG scripts: //VE / AG scripts:
#include "AgShipPlayerDeathTrigger.h" #include "AgShipPlayerDeathTrigger.h"
#include "AgShipPlayerShockServer.h" #include "AgShipPlayerShockServer.h"
#include "AgShipShake.h"
#include "AgSpaceStuff.h" #include "AgSpaceStuff.h"
#include "AgImagSmashable.h" #include "AgImagSmashable.h"
#include "NpcNpSpacemanBob.h" #include "NpcNpSpacemanBob.h"
@ -290,7 +291,9 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr
script = new AgShipPlayerDeathTrigger(); script = new AgShipPlayerDeathTrigger();
else if (scriptName == "scripts\\ai\\NP\\L_NPC_NP_SPACEMAN_BOB.lua") else if (scriptName == "scripts\\ai\\NP\\L_NPC_NP_SPACEMAN_BOB.lua")
script = new NpcNpSpacemanBob(); script = new NpcNpSpacemanBob();
else if (scriptName == "scripts\\ai\\AG\\L_AG_SPACE_STUFF.lua") // Broken, will (sometimes) display all animations at once on initial login else if (scriptName == "scripts\\ai\\AG\\L_AG_SHIP_SHAKE.lua")
script = new AgShipShake();
else if (scriptName == "scripts\\ai\\AG\\L_AG_SPACE_STUFF.lua")
script = new AgSpaceStuff(); script = new AgSpaceStuff();
else if (scriptName == "scripts\\ai\\AG\\L_AG_SHIP_PLAYER_SHOCK_SERVER.lua") else if (scriptName == "scripts\\ai\\AG\\L_AG_SHIP_PLAYER_SHOCK_SERVER.lua")
script = new AgShipPlayerShockServer(); script = new AgShipPlayerShockServer();

View File

@ -833,7 +833,7 @@ void HandlePacket(Packet* packet) {
} }
if (packet->data[1] != WORLD) return; if (packet->data[1] != WORLD) return;
switch (packet->data[3]) { switch (packet->data[3]) {
case MSG_WORLD_CLIENT_VALIDATION: { case MSG_WORLD_CLIENT_VALIDATION: {
std::string username = PacketUtils::ReadString(0x08, packet, true); std::string username = PacketUtils::ReadString(0x08, packet, true);

View File

@ -1,4 +1,5 @@
CREATE OR REPLACE TABLE accounts ( DROP TABLE IF EXISTS accounts;
CREATE TABLE accounts (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(35) NOT NULL UNIQUE, name VARCHAR(35) NOT NULL UNIQUE,
password TEXT NOT NULL, password TEXT NOT NULL,
@ -10,7 +11,8 @@ CREATE OR REPLACE TABLE accounts (
mute_expire BIGINT UNSIGNED NOT NULL DEFAULT 0 mute_expire BIGINT UNSIGNED NOT NULL DEFAULT 0
); );
CREATE OR REPLACE TABLE charinfo ( DROP TABLE IF EXISTS charinfo;
CREATE TABLE charinfo (
id BIGINT NOT NULL PRIMARY KEY, id BIGINT NOT NULL PRIMARY KEY,
account_id INT NOT NULL REFERENCES accounts(id), account_id INT NOT NULL REFERENCES accounts(id),
name VARCHAR(35) NOT NULL, name VARCHAR(35) NOT NULL,
@ -21,18 +23,21 @@ CREATE OR REPLACE TABLE charinfo (
permission_map BIGINT UNSIGNED NOT NULL DEFAULT 0 permission_map BIGINT UNSIGNED NOT NULL DEFAULT 0
); );
CREATE OR REPLACE TABLE charxml ( DROP TABLE IF EXISTS charxml;
CREATE TABLE charxml (
id BIGINT NOT NULL PRIMARY KEY REFERENCES charinfo(id), id BIGINT NOT NULL PRIMARY KEY REFERENCES charinfo(id),
xml_data LONGTEXT NOT NULL xml_data LONGTEXT NOT NULL
); );
CREATE OR REPLACE TABLE command_log ( DROP TABLE IF EXISTS command_log;
CREATE TABLE command_log (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
character_id BIGINT NOT NULL REFERENCES charinfo(id), character_id BIGINT NOT NULL REFERENCES charinfo(id),
command VARCHAR(256) NOT NULL command VARCHAR(256) NOT NULL
); );
CREATE OR REPLACE TABLE friends ( DROP TABLE IF EXISTS friends;
CREATE TABLE friends (
player_id BIGINT NOT NULL REFERENCES charinfo(id), player_id BIGINT NOT NULL REFERENCES charinfo(id),
friend_id BIGINT NOT NULL REFERENCES charinfo(id), friend_id BIGINT NOT NULL REFERENCES charinfo(id),
best_friend BOOLEAN NOT NULL DEFAULT FALSE, best_friend BOOLEAN NOT NULL DEFAULT FALSE,
@ -40,7 +45,8 @@ CREATE OR REPLACE TABLE friends (
PRIMARY KEY (player_id, friend_id) PRIMARY KEY (player_id, friend_id)
); );
CREATE OR REPLACE TABLE leaderboard ( DROP TABLE IF EXISTS leaderboard;
CREATE TABLE leaderboard (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
game_id INT UNSIGNED NOT NULL DEFAULT 0, game_id INT UNSIGNED NOT NULL DEFAULT 0,
last_played TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP(), last_played TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP(),
@ -49,7 +55,8 @@ CREATE OR REPLACE TABLE leaderboard (
score BIGINT UNSIGNED NOT NULL DEFAULT 0 score BIGINT UNSIGNED NOT NULL DEFAULT 0
); );
CREATE OR REPLACE TABLE mail ( DROP TABLE IF EXISTS mail;
CREATE TABLE mail (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
sender_id INT NOT NULL DEFAULT 0, sender_id INT NOT NULL DEFAULT 0,
sender_name VARCHAR(35) NOT NULL DEFAULT '', sender_name VARCHAR(35) NOT NULL DEFAULT '',
@ -65,17 +72,20 @@ CREATE OR REPLACE TABLE mail (
was_read BOOLEAN NOT NULL DEFAULT FALSE was_read BOOLEAN NOT NULL DEFAULT FALSE
); );
CREATE OR REPLACE TABLE object_id_tracker ( DROP TABLE IF EXISTS object_id_tracker;
CREATE TABLE object_id_tracker (
last_object_id BIGINT UNSIGNED NOT NULL DEFAULT 0 PRIMARY KEY last_object_id BIGINT UNSIGNED NOT NULL DEFAULT 0 PRIMARY KEY
); );
CREATE OR REPLACE TABLE pet_names ( DROP TABLE IF EXISTS pet_names;
CREATE TABLE pet_names (
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
pet_name TEXT NOT NULL, pet_name TEXT NOT NULL,
approved INT UNSIGNED NOT NULL approved INT UNSIGNED NOT NULL
); );
CREATE OR REPLACE TABLE play_keys ( DROP TABLE IF EXISTS play_keys;
CREATE TABLE play_keys (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
key_string CHAR(19) NOT NULL UNIQUE, key_string CHAR(19) NOT NULL UNIQUE,
key_uses INT NOT NULL DEFAULT 1, key_uses INT NOT NULL DEFAULT 1,
@ -83,7 +93,8 @@ CREATE OR REPLACE TABLE play_keys (
active BOOLEAN NOT NULL DEFAULT TRUE active BOOLEAN NOT NULL DEFAULT TRUE
); );
CREATE OR REPLACE TABLE properties ( DROP TABLE IF EXISTS properties;
CREATE TABLE properties (
id BIGINT NOT NULL PRIMARY KEY, id BIGINT NOT NULL PRIMARY KEY,
owner_id BIGINT NOT NULL REFERENCES charinfo(id), owner_id BIGINT NOT NULL REFERENCES charinfo(id),
template_id INT UNSIGNED NOT NULL, template_id INT UNSIGNED NOT NULL,
@ -101,17 +112,19 @@ CREATE OR REPLACE TABLE properties (
zone_id INT NOT NULL zone_id INT NOT NULL
); );
CREATE OR REPLACE TABLE ugc ( DROP TABLE IF EXISTS ugc;
CREATE TABLE ugc (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
account_id INT NOT NULL REFERENCES accounts(id), account_id INT NOT NULL REFERENCES accounts(id),
character_id BIGINT NOT NULL REFERENCES charinfo(id), character_id BIGINT NOT NULL REFERENCES charinfo(id),
is_optimized BOOLEAN NOT NULL DEFAULT FALSE, is_optimized BOOLEAN NOT NULL DEFAULT FALSE,
lxfml MEDIUMBLOB NOT NULL, lxfml MEDIUMBLOB NOT NULL,
bake_ao BOOLEAN NOT NULL DEFAULT FALSE, bake_ao BOOLEAN NOT NULL DEFAULT FALSE,
filename TEXT NOT NULL DEFAULT '' filename TEXT NOT NULL DEFAULT ('')
); );
CREATE OR REPLACE TABLE properties_contents ( DROP TABLE IF EXISTS properties_contents;
CREATE TABLE properties_contents (
id BIGINT NOT NULL PRIMARY KEY, id BIGINT NOT NULL PRIMARY KEY,
property_id BIGINT NOT NULL REFERENCES properties(id), property_id BIGINT NOT NULL REFERENCES properties(id),
ugc_id INT NULL REFERENCES ugc(id), ugc_id INT NULL REFERENCES ugc(id),
@ -125,7 +138,8 @@ CREATE OR REPLACE TABLE properties_contents (
rw FLOAT NOT NULL rw FLOAT NOT NULL
); );
CREATE OR REPLACE TABLE activity_log ( DROP TABLE IF EXISTS activity_log;
CREATE TABLE activity_log (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
character_id BIGINT NOT NULL REFERENCES charinfo(id), character_id BIGINT NOT NULL REFERENCES charinfo(id),
activity INT NOT NULL, activity INT NOT NULL,
@ -133,7 +147,8 @@ CREATE OR REPLACE TABLE activity_log (
map_id INT NOT NULL map_id INT NOT NULL
); );
CREATE OR REPLACE TABLE bug_reports ( DROP TABLE IF EXISTS bug_reports;
CREATE TABLE bug_reports (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
body TEXT NOT NULL, body TEXT NOT NULL,
client_version TEXT NOT NULL, client_version TEXT NOT NULL,
@ -142,7 +157,8 @@ CREATE OR REPLACE TABLE bug_reports (
submitted TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP() submitted TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP()
); );
CREATE OR REPLACE TABLE servers ( DROP TABLE IF EXISTS servers;
CREATE TABLE servers (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name TEXT NOT NULL, name TEXT NOT NULL,
ip TEXT NOT NULL, ip TEXT NOT NULL,