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/)
include_directories(${backtrace_SOURCE_DIR})
endif(__include_backtrace__)
endif(__include_backtrace__ AND __compile_backtrace__)
endif()
endif(UNIX)

View File

@ -52,7 +52,7 @@ This project has gone through multiple iterations of coding style. In the code y
### 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.)

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
```
### Windows builds (native) (CURRENTLY BROKEN ONCE COMPILED)
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/).
### 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/). Currently on native Windows the server will only work in Release mode.
**Build the repository**
```batch

View File

@ -21,8 +21,9 @@ dChatFilter::dChatFilter(const std::string& filepath, bool dontGenerateDCF) {
ReadWordlistPlaintext(filepath + ".txt");
if (!m_DontGenerateDCF) ExportWordlistToDCF(filepath + ".dcf");
}
else {
ReadWordlistDCF(filepath + ".dcf");
else if (!ReadWordlistDCF(filepath + ".dcf")) {
ReadWordlistPlaintext(filepath + ".txt");
ExportWordlistToDCF(filepath + ".dcf");
}
//Read player names that are ok as well:
@ -46,24 +47,24 @@ void dChatFilter::ReadWordlistPlaintext(const std::string& filepath) {
if (file) {
std::string 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
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);
if (file) {
fileHeader hdr;
BinaryIO::BinaryRead(file, hdr);
if (hdr.header != header) {
std::cout << "Wrong file header!" << std::endl;
file.close();
return;
return false;
}
if (hdr.formatVersion <= formatVersion) {
if (hdr.formatVersion == formatVersion) {
size_t wordsToRead = 0;
BinaryIO::BinaryRead(file, wordsToRead);
m_Words.reserve(wordsToRead);
@ -73,17 +74,20 @@ void dChatFilter::ReadWordlistDCF(const std::string& filepath) {
BinaryIO::BinaryRead(file, word);
m_Words.push_back(word);
}
return true;
}
else {
std::cout << "Newer file or corrupt" << std::endl;
file.close();
return;
return false;
}
}
return false;
}
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) {
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::header));
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::formatVersion));

View File

@ -6,7 +6,7 @@
namespace dChatFilterDCF {
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 {
uint32_t header;
@ -21,7 +21,7 @@ public:
~dChatFilter();
void ReadWordlistPlaintext(const std::string & filepath);
void ReadWordlistDCF(const std::string & filepath);
bool ReadWordlistDCF(const std::string & filepath);
void ExportWordlistToDCF(const std::string & filepath);
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);
if (m_logToConsole) std::cout << "[" << "timeStr" << "] [" << className << "]: " << message;
mFile << "[" << "timeStr" << "] [" << className << "]: " << message;
if (m_logToConsole) std::cout << "[" << timeStr << "] [" << className << "]: " << message;
mFile << "[" << timeStr << "] [" << className << "]: " << message;
#else
time_t t = time(NULL);
struct tm * time = localtime(&t);

View File

@ -1222,13 +1222,19 @@ void Entity::UpdateXMLDoc(tinyxml2::XMLDocument* doc) {
}
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);
if (m_Timers[i]->GetTime() <= 0) {
const auto timerName = m_Timers[i]->GetName();
delete m_Timers[i];
m_Timers.erase(m_Timers.begin() + i);
do { //sometimes, due to a race condition, m_Timers.erase doesn't actually erase, repeat until it does
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)) {
script->OnTimerDone(this, timerName);

View File

@ -154,25 +154,24 @@ void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, const LWOOB
delete chatmode;
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:
const int reservedSize = 5 * 1024 * 1024;
uint8_t 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<uint8_t>(1); //compressed boolean, true
bitStream.Write<uint8_t>(1); //compressed boolean, true
bitStream.Write<uint32_t>(data.GetNumberOfBytesUsed());
bitStream.Write<uint32_t>(size);
for (size_t i = 0; i < size; i++)
bitStream.Write(compressedData[i]);
/*
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
*/
#endif
PacketUtils::SavePacket("chardata.bin", (const char *)bitStream.GetData(), static_cast<uint32_t>(bitStream.GetNumberOfBytesUsed()));
SEND_PACKET

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 "GeneralUtils.h"
#include "GameMessages.h"
#include "dZoneManager.h"
#include "EntityManager.h"
#include "Game.h"
@ -17,11 +16,6 @@ void AgSpaceStuff::OnStartup(Entity* self) {
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 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)));
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:
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

@ -15,6 +15,7 @@
//VE / AG scripts:
#include "AgShipPlayerDeathTrigger.h"
#include "AgShipPlayerShockServer.h"
#include "AgShipShake.h"
#include "AgSpaceStuff.h"
#include "AgImagSmashable.h"
#include "NpcNpSpacemanBob.h"
@ -290,7 +291,9 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr
script = new AgShipPlayerDeathTrigger();
else if (scriptName == "scripts\\ai\\NP\\L_NPC_NP_SPACEMAN_BOB.lua")
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();
else if (scriptName == "scripts\\ai\\AG\\L_AG_SHIP_PLAYER_SHOCK_SERVER.lua")
script = new AgShipPlayerShockServer();

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,
name VARCHAR(35) NOT NULL UNIQUE,
password TEXT NOT NULL,
@ -10,7 +11,8 @@ CREATE OR REPLACE TABLE accounts (
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,
account_id INT NOT NULL REFERENCES accounts(id),
name VARCHAR(35) NOT NULL,
@ -21,18 +23,21 @@ CREATE OR REPLACE TABLE charinfo (
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),
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,
character_id BIGINT NOT NULL REFERENCES charinfo(id),
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),
friend_id BIGINT NOT NULL REFERENCES charinfo(id),
best_friend BOOLEAN NOT NULL DEFAULT FALSE,
@ -40,7 +45,8 @@ CREATE OR REPLACE TABLE friends (
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,
game_id INT UNSIGNED NOT NULL DEFAULT 0,
last_played TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP(),
@ -49,7 +55,8 @@ CREATE OR REPLACE TABLE leaderboard (
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,
sender_id INT NOT NULL DEFAULT 0,
sender_name VARCHAR(35) NOT NULL DEFAULT '',
@ -65,17 +72,20 @@ CREATE OR REPLACE TABLE mail (
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
);
CREATE OR REPLACE TABLE pet_names (
DROP TABLE IF EXISTS pet_names;
CREATE TABLE pet_names (
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
pet_name TEXT 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,
key_string CHAR(19) NOT NULL UNIQUE,
key_uses INT NOT NULL DEFAULT 1,
@ -83,7 +93,8 @@ CREATE OR REPLACE TABLE play_keys (
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,
owner_id BIGINT NOT NULL REFERENCES charinfo(id),
template_id INT UNSIGNED NOT NULL,
@ -101,17 +112,19 @@ CREATE OR REPLACE TABLE properties (
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,
account_id INT NOT NULL REFERENCES accounts(id),
character_id BIGINT NOT NULL REFERENCES charinfo(id),
is_optimized BOOLEAN NOT NULL DEFAULT FALSE,
lxfml MEDIUMBLOB NOT NULL,
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,
property_id BIGINT NOT NULL REFERENCES properties(id),
ugc_id INT NULL REFERENCES ugc(id),
@ -125,7 +138,8 @@ CREATE OR REPLACE TABLE properties_contents (
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,
character_id BIGINT NOT NULL REFERENCES charinfo(id),
activity INT NOT NULL,
@ -133,7 +147,8 @@ CREATE OR REPLACE TABLE activity_log (
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,
body 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()
);
CREATE OR REPLACE TABLE servers (
DROP TABLE IF EXISTS servers;
CREATE TABLE servers (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name TEXT NOT NULL,
ip TEXT NOT NULL,