diff --git a/CMakeLists.txt b/CMakeLists.txt index 9789aff8..cf7988c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,7 +95,7 @@ if (__include_backtrace__ AND __compile_backtrace__) link_directories(${backtrace_SOURCE_DIR}/.libs/) include_directories(${backtrace_SOURCE_DIR}) -endif(__include_backtrace__ AND __compile_backtrace__) +endif(__include_backtrace__) endif() endif(UNIX) diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 1d31eb8d..c98323a9 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -1222,19 +1222,13 @@ void Entity::UpdateXMLDoc(tinyxml2::XMLDocument* doc) { } void Entity::Update(const float deltaTime) { - int timerSize = m_Timers.size(); - for (int i = 0; i < timerSize; i++) { + for (int i = 0; i < m_Timers.size(); i++) { m_Timers[i]->Update(deltaTime); if (m_Timers[i]->GetTime() <= 0) { const auto timerName = m_Timers[i]->GetName(); - 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 + delete m_Timers[i]; + m_Timers.erase(m_Timers.begin() + i); for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) { script->OnTimerDone(this, timerName); diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index 926168a3..1c73fd22 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -157,10 +157,16 @@ int main(int argc, char** argv) { auto* masterLookupStatement = Database::CreatePreppedStmt("SELECT id FROM `servers` WHERE `name` = 'master'"); auto* result = masterLookupStatement->executeQuery(); + auto master_server_ip = config.GetValue("master_ip"); + + if (master_server_ip == "") { + master_server_ip = Game::server->GetIP(); + } + //If we found a server, update it's IP and port to the current one. if (result->next()) { auto* updateStatement = Database::CreatePreppedStmt("UPDATE `servers` SET `ip` = ?, `port` = ? WHERE `id` = ?"); - updateStatement->setString(1, Game::server->GetIP()); + updateStatement->setString(1, master_server_ip); updateStatement->setInt(2, Game::server->GetPort()); updateStatement->setInt(3, result->getInt("id")); updateStatement->execute(); @@ -169,7 +175,7 @@ int main(int argc, char** argv) { else { //If we didn't find a server, create one. auto* insertStatement = Database::CreatePreppedStmt("INSERT INTO `servers` (`name`, `ip`, `port`, `state`, `version`) VALUES ('master', ?, ?, 0, 171023)"); - insertStatement->setString(1, Game::server->GetIP()); + insertStatement->setString(1, master_server_ip); insertStatement->setInt(2, Game::server->GetPort()); insertStatement->execute(); delete insertStatement; diff --git a/dScripts/AgShipShake.cpp b/dScripts/AgShipShake.cpp deleted file mode 100644 index 643bc695..00000000 --- a/dScripts/AgShipShake.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#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(u"ShakeObject")); - - const auto randomTime = self->GetVar(u"RandomTime"); - auto time = GeneralUtils::GenerateRandomNumber(0, randomTime + 1); - - if (time < randomTime / 2) { - time += randomTime / 2; - } - - self->AddTimer("ShipShakeIdle", static_cast(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(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; -} diff --git a/dScripts/AgShipShake.h b/dScripts/AgShipShake.h deleted file mode 100644 index b1e1b557..00000000 --- a/dScripts/AgShipShake.h +++ /dev/null @@ -1,18 +0,0 @@ -#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); -}; - diff --git a/dScripts/AgSpaceStuff.cpp b/dScripts/AgSpaceStuff.cpp index 1e82237e..2550f001 100644 --- a/dScripts/AgSpaceStuff.cpp +++ b/dScripts/AgSpaceStuff.cpp @@ -1,6 +1,7 @@ #include "AgSpaceStuff.h" #include "GeneralUtils.h" #include "GameMessages.h" +#include "dZoneManager.h" #include "EntityManager.h" #include "Game.h" @@ -16,6 +17,11 @@ 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) { @@ -32,4 +38,72 @@ 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(u"ShakeObject")); + + const auto randomTime = self->GetVar(u"RandomTime"); + auto time = GeneralUtils::GenerateRandomNumber(0, randomTime + 1); + + if (time < randomTime / 2) { + time += randomTime / 2; + } + + self->AddTimer("ShipShakeIdle", static_cast(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(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; } diff --git a/dScripts/AgSpaceStuff.h b/dScripts/AgSpaceStuff.h index 13b29f1c..8d816691 100644 --- a/dScripts/AgSpaceStuff.h +++ b/dScripts/AgSpaceStuff.h @@ -5,4 +5,14 @@ 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); }; + diff --git a/dScripts/CppScripts.cpp b/dScripts/CppScripts.cpp index a07d4f52..99702805 100644 --- a/dScripts/CppScripts.cpp +++ b/dScripts/CppScripts.cpp @@ -15,7 +15,6 @@ //VE / AG scripts: #include "AgShipPlayerDeathTrigger.h" #include "AgShipPlayerShockServer.h" -#include "AgShipShake.h" #include "AgSpaceStuff.h" #include "AgImagSmashable.h" #include "NpcNpSpacemanBob.h" @@ -291,9 +290,7 @@ 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_SHIP_SHAKE.lua") - script = new AgShipShake(); - else if (scriptName == "scripts\\ai\\AG\\L_AG_SPACE_STUFF.lua") + else if (scriptName == "scripts\\ai\\AG\\L_AG_SPACE_STUFF.lua") // Broken, will (sometimes) display all animations at once on initial login script = new AgSpaceStuff(); else if (scriptName == "scripts\\ai\\AG\\L_AG_SHIP_PLAYER_SHOCK_SERVER.lua") script = new AgShipPlayerShockServer(); diff --git a/docker-compose.yml b/docker-compose.yml index c71c8c8f..c49b2e7d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,11 +14,13 @@ services: - EXTERNAL_IP=${EXTERNAL_IP:-darkflame} volumes: - ${CLIENT_PATH:?err}:/client - - ./docker/:/docker/ + - shared_configs:/docker/ database: container_name: DarkflameDatabase - image: mariadb:10.6 + build: + context: . + dockerfile: ./docker/database.Dockerfile environment: - MARIADB_USER=${MARIADB_USER:-darkflame} - MARIADB_PASSWORD=${MARIADB_PASSWORD:-darkflame} @@ -26,7 +28,6 @@ services: - MARIADB_DATABASE=${MARIADB_DATABASE:-darkflame} volumes: - database:/var/lib/mysql - - ./migrations/dlu:/docker-entrypoint-initdb.d networks: - darkflame # You can expose these so that DB management tools can connect (WARNING: INSECURE) @@ -45,7 +46,7 @@ services: - BUILD_VERSION=${BUILD_VERSION:-171022} volumes: - ${CLIENT_PATH:?err}:/client - - ./docker/configs/:/configs + - shared_configs:/shared_configs depends_on: - database ports: @@ -99,3 +100,4 @@ networks: volumes: database: + shared_configs: diff --git a/docker/database.Dockerfile b/docker/database.Dockerfile new file mode 100644 index 00000000..68261e44 --- /dev/null +++ b/docker/database.Dockerfile @@ -0,0 +1,3 @@ +FROM mariadb:10.6 + +COPY ./migrations/dlu /docker-entrypoint-initdb.d \ No newline at end of file diff --git a/docker/setup.sh b/docker/setup.sh index 7bff747d..85776e6f 100755 --- a/docker/setup.sh +++ b/docker/setup.sh @@ -31,6 +31,9 @@ function update_ini_values() { update_ini worldconfig.ini chat_server_port $CHAT_SERVER_PORT update_ini worldconfig.ini max_clients $MAX_CLIENTS + # always use the internal docker hostname + update_ini masterconfig.ini master_ip "darkflame" + update_database_ini_values_for masterconfig.ini update_database_ini_values_for authconfig.ini update_database_ini_values_for chatconfig.ini diff --git a/docker/start_server.sh b/docker/start_server.sh index 6dccad7e..cf22093c 100755 --- a/docker/start_server.sh +++ b/docker/start_server.sh @@ -21,10 +21,10 @@ function symlink_client_files() { function symlink_config_files() { echo "Creating symlinks for config files" rm /app/*.ini - ln -s /configs/authconfig.ini /app/authconfig.ini - ln -s /configs/chatconfig.ini /app/chatconfig.ini - ln -s /configs/masterconfig.ini /app/masterconfig.ini - ln -s /configs/worldconfig.ini /app/worldconfig.ini + ln -s /shared_configs/configs/authconfig.ini /app/authconfig.ini + ln -s /shared_configs/configs/chatconfig.ini /app/chatconfig.ini + ln -s /shared_configs/configs/masterconfig.ini /app/masterconfig.ini + ln -s /shared_configs/configs/worldconfig.ini /app/worldconfig.ini } if [[ ! -f "/app/initialized" ]]; then diff --git a/resources/masterconfig.ini b/resources/masterconfig.ini index 120a3743..531234b6 100644 --- a/resources/masterconfig.ini +++ b/resources/masterconfig.ini @@ -7,6 +7,9 @@ mysql_password= # The public facing IP address. Can be 'localhost' for locally hosted servers external_ip=localhost +# The internal ip of the master server +master_ip=localhost + # Port number port=2000