mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-17 20:14:31 -06:00
Compare commits
7 Commits
ecs-experi
...
unique-ptr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90e2b5c6b7 | ||
|
|
42367deeca | ||
|
|
fced6d753a | ||
|
|
15dc5feeb5 | ||
|
|
a60865cd19 | ||
|
|
77b42daca1 | ||
|
|
ba364800fe |
@@ -7,8 +7,16 @@ NET_VERSION=171022
|
||||
ACCOUNT_MANAGER_SECRET=
|
||||
# Should be the externally facing IP of your server host
|
||||
EXTERNAL_IP=localhost
|
||||
|
||||
# The database type that will be used.
|
||||
# Acceptable values are `sqlite`, `mysql`, `mariadb`, `maria`.
|
||||
# Case insensitive.
|
||||
DATABASE_TYPE=mariadb
|
||||
SQLITE_DATABASE_PATH=resServer/dlu.sqlite
|
||||
|
||||
# Database values
|
||||
# Be careful with special characters here. It is more safe to use normal characters and/or numbers.
|
||||
MARIADB_USER=darkflame
|
||||
MARIADB_PASSWORD=
|
||||
MARIADB_DATABASE=darkflame
|
||||
SKIP_ACCOUNT_CREATION=1
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -4,10 +4,8 @@ RelWithDebInfo/
|
||||
docker/configs
|
||||
|
||||
# Third party libraries
|
||||
thirdparty/magic_enum
|
||||
thirdparty/mysql/
|
||||
thirdparty/mysql_linux/
|
||||
CMakeVariables.txt
|
||||
|
||||
# Build folders
|
||||
build/
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -14,3 +14,6 @@
|
||||
path = thirdparty/mariadb-connector-cpp
|
||||
url = https://github.com/mariadb-corporation/mariadb-connector-cpp.git
|
||||
ignore = dirty
|
||||
[submodule "thirdparty/magic_enum"]
|
||||
path = thirdparty/magic_enum
|
||||
url = https://github.com/Neargye/magic_enum.git
|
||||
|
||||
@@ -110,23 +110,6 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
find_package(MariaDB)
|
||||
|
||||
# Fetch third party dependencies
|
||||
set(DLU_THIRDPARTY_SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty)
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
magic_enum
|
||||
SYSTEM
|
||||
# SOURCE_DIR ${DLU_THIRDPARTY_SOURCE_DIR}/magic_enum
|
||||
GIT_REPOSITORY https://github.com/Neargye/magic_enum.git
|
||||
GIT_TAG v0.9.7
|
||||
)
|
||||
FetchContent_MakeAvailable(magic_enum)
|
||||
|
||||
include(CMakePrintHelpers)
|
||||
cmake_print_properties(TARGETS magic_enum::magic_enum PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES)
|
||||
|
||||
# Create a /resServer directory
|
||||
make_directory(${CMAKE_BINARY_DIR}/resServer)
|
||||
|
||||
@@ -192,16 +175,18 @@ foreach(resource_file ${RESOURCE_FILES})
|
||||
list(GET line_split 0 variable_name)
|
||||
|
||||
if(NOT ${parsed_current_file_contents} MATCHES ${variable_name})
|
||||
message(STATUS "Adding missing config option " ${variable_name} " to " ${resource_file})
|
||||
set(line_to_add ${line_to_add} ${line})
|
||||
# For backwards compatibility with older setup versions, dont add this option.
|
||||
if(NOT ${variable_name} MATCHES "database_type")
|
||||
message(STATUS "Adding missing config option " ${variable_name} " to " ${resource_file})
|
||||
set(line_to_add ${line_to_add} ${line})
|
||||
|
||||
foreach(line_to_append ${line_to_add})
|
||||
file(APPEND ${DLU_CONFIG_DIR}/${resource_file} "\n" ${line_to_append})
|
||||
endforeach()
|
||||
foreach(line_to_append ${line_to_add})
|
||||
file(APPEND ${DLU_CONFIG_DIR}/${resource_file} "\n" ${line_to_append})
|
||||
endforeach()
|
||||
|
||||
file(APPEND ${DLU_CONFIG_DIR}/${resource_file} "\n")
|
||||
file(APPEND ${DLU_CONFIG_DIR}/${resource_file} "\n")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(line_to_add "")
|
||||
else()
|
||||
set(line_to_add ${line_to_add} ${line})
|
||||
@@ -231,21 +216,8 @@ foreach(file ${VANITY_FILES})
|
||||
endforeach()
|
||||
|
||||
# Move our migrations for MasterServer to run
|
||||
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/migrations/dlu/)
|
||||
file(GLOB SQL_FILES ${CMAKE_SOURCE_DIR}/migrations/dlu/*.sql)
|
||||
|
||||
foreach(file ${SQL_FILES})
|
||||
get_filename_component(file ${file} NAME)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/migrations/dlu/${file} ${PROJECT_BINARY_DIR}/migrations/dlu/${file})
|
||||
endforeach()
|
||||
|
||||
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/migrations/cdserver/)
|
||||
file(GLOB SQL_FILES ${CMAKE_SOURCE_DIR}/migrations/cdserver/*.sql)
|
||||
|
||||
foreach(file ${SQL_FILES})
|
||||
get_filename_component(file ${file} NAME)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/migrations/cdserver/${file} ${PROJECT_BINARY_DIR}/migrations/cdserver/${file})
|
||||
endforeach()
|
||||
file(REMOVE_RECURSE ${PROJECT_BINARY_DIR}/migrations)
|
||||
file(COPY ${CMAKE_SOURCE_DIR}/migrations DESTINATION ${CMAKE_BINARY_DIR})
|
||||
|
||||
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
|
||||
if (APPLE)
|
||||
@@ -269,6 +241,7 @@ include_directories(
|
||||
"tests/dGameTests/dComponentsTests"
|
||||
|
||||
SYSTEM
|
||||
"thirdparty/magic_enum/include/magic_enum"
|
||||
"thirdparty/raknet/Source"
|
||||
"thirdparty/tinyxml2"
|
||||
"thirdparty/recastnavigation"
|
||||
@@ -319,7 +292,6 @@ file(
|
||||
# Add our library subdirectories for creation of the library object
|
||||
add_subdirectory(dCommon)
|
||||
add_subdirectory(dDatabase)
|
||||
add_subdirectory(dECS)
|
||||
add_subdirectory(dChatFilter)
|
||||
add_subdirectory(dNet)
|
||||
add_subdirectory(dScripts) # Add for dGame to use
|
||||
@@ -330,7 +302,7 @@ add_subdirectory(dPhysics)
|
||||
add_subdirectory(dServer)
|
||||
|
||||
# Create a list of common libraries shared between all binaries
|
||||
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "magic_enum::magic_enum")
|
||||
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "magic_enum")
|
||||
|
||||
# Add platform specific common libraries
|
||||
if(UNIX)
|
||||
|
||||
37
README.md
37
README.md
@@ -13,21 +13,33 @@ Darkflame Universe is licensed under AGPLv3, please read [LICENSE](LICENSE). Som
|
||||
* You must disclose any changes you make to the code when you distribute it
|
||||
* Hosting a server for others counts as distribution
|
||||
|
||||
## Disclaimers
|
||||
### Setup difficulty
|
||||
Throughout the entire build and setup process a level of familiarity with the command line and preferably a Unix-like development environment is greatly advantageous.
|
||||
|
||||
### Hosting a server
|
||||
We do not recommend hosting public servers. Darkflame Universe is intended for small scale deployment, for example within a group of friends. It has not been tested for large scale deployment which comes with additional security risks.
|
||||
|
||||
### Supply of resource files
|
||||
Darkflame Universe is a server emulator and does not distribute any LEGO® Universe files. A separate game client is required to setup this server emulator and play the game, which we cannot supply. Users are strongly suggested to refer to the safe checksums listed [here](#verifying-your-client-files) to see if a client will work.
|
||||
|
||||
## Step by step walkthrough for a single-player server
|
||||
If you would like a setup for a single player server only on a Windows machine, use the [Native Windows Setup Guide by HailStorm](https://gist.github.com/HailStorm32/169df65a47a104199b5cc57d10fa57de) and skip this README.
|
||||
## Setting up a single player server
|
||||
* If you don't know what WSL is, skip this warning.
|
||||
Warning: WSL version 1 does NOT support using sqlite as a database due to how it handles filesystem synchronization.
|
||||
You must use Version 2 if you must run the server under WSL. Not doing so will result in save data loss.
|
||||
* Single player installs now no longer require building the server from source or installing development tools.
|
||||
* Download the [latest windows release](https://github.com/DarkflameUniverse/DarkflameServer/releases) (or whichever release you need) and extract the files into a folder inside your client. Note that this setup is expecting that when double clicking the folder that you put in the same folder as `legouniverse.exe`, the file `MasterServer.exe` is in there.
|
||||
* You should be able to see the folder with the server files in the same folder as `legouniverse.exe`.
|
||||
* Go into the server files folder and open `sharedconfig.ini`. Find the line that says `client_location` and put `..` after it so the line reads `client_location=..`.
|
||||
* To run the server, double-click `MasterServer.exe`.
|
||||
* You will be asked to create an account the first time you run the server. After you have created the account, the server will shutdown and need to be restarted.
|
||||
* To connect to the server, either delete the file `boot.cfg` which is found in your LEGO Universe client, rename the file `boot.cfg` to something else or follow the steps [here](#allowing-a-user-to-connect-to-your-server) if you wish to keep the file.
|
||||
* When shutting down the server, it is highly recommended to click the `MasterServer.exe` window and hold `ctrl` while pressing `c` to stop the server.
|
||||
* We are working on a way to make it so when you close the game, the server stops automatically alongside when you open the game, the server starts automatically.
|
||||
|
||||
## Steps to setup server
|
||||
<font size="32">**If you are not planning on hosting a server for others, working in the codebase or wanting to use MariaDB for a database, you can stop reading here.**</font>
|
||||
|
||||
If you would like to use a MariaDB as a database instead of the default of sqlite, follow the steps [here](#database-setup).
|
||||
|
||||
# Steps to setup a development environment
|
||||
* [Clone this repository](#clone-the-repository)
|
||||
* [Setting up a development environment](#setting-up-a-development-environment)
|
||||
* [Install dependencies](#install-dependencies)
|
||||
* [Database setup](#database-setup)
|
||||
* [Build the server](#build-the-server)
|
||||
@@ -39,6 +51,13 @@ If you would like a setup for a single player server only on a Windows machine,
|
||||
* [User Guide](#user-guide)
|
||||
* [Docker](#docker)
|
||||
|
||||
## Disclaimers
|
||||
### Setup difficulty
|
||||
Throughout the entire build and setup process a level of familiarity with the command line and preferably a Unix-like development environment is greatly advantageous.
|
||||
|
||||
## Step by step walkthrough for building a single-player Windows server from source
|
||||
If you would like a setup for a single player server only on a Windows machine built from source, use the [Native Windows Setup Guide by HailStorm](https://gist.github.com/HailStorm32/169df65a47a104199b5cc57d10fa57de) and skip this README.
|
||||
|
||||
## Clone the repository
|
||||
If you are on Windows, you will need to download and install git from [here](https://git-scm.com/download/win)
|
||||
|
||||
@@ -266,8 +285,8 @@ systemctl stop darkflame.service
|
||||
journalctl -xeu darkflame.service
|
||||
```
|
||||
|
||||
### First admin user
|
||||
Run `MasterServer -a` to get prompted to create an admin account. This method is only intended for the system administrator as a means to get started, do NOT use this method to create accounts for other users!
|
||||
### First user or adding more users.
|
||||
The first time you run `MasterServer`, you will be prompted to create an account. To create more accounts from the command line, `MasterServer -a` to get prompted to create an admin account. This method is only intended for the system administrator as a means to get started, do NOT use this method to create accounts for other users!
|
||||
|
||||
### Account management tool (Nexus Dashboard)
|
||||
**If you are just using this server for yourself, you can skip setting up Nexus Dashboard**
|
||||
|
||||
@@ -37,7 +37,6 @@ target_include_directories(dCommon
|
||||
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase"
|
||||
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase/ITables"
|
||||
"${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase"
|
||||
"${PROJECT_SOURCE_DIR}/thirdparty/mariadb-connector-cpp/include"
|
||||
)
|
||||
|
||||
if (UNIX)
|
||||
@@ -70,6 +69,5 @@ else ()
|
||||
endif ()
|
||||
|
||||
target_link_libraries(dCommon
|
||||
PUBLIC magic_enum::magic_enum
|
||||
PRIVATE ZLIB::ZLIB bcrypt tinyxml2
|
||||
INTERFACE dDatabase)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
#include <magic_enum/magic_enum.hpp>
|
||||
#include "magic_enum.hpp"
|
||||
|
||||
namespace MessageType {
|
||||
enum class Game : uint16_t {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
#include <magic_enum/magic_enum.hpp>
|
||||
#include "magic_enum.hpp"
|
||||
|
||||
namespace MessageType {
|
||||
enum class World : uint32_t {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define __STRINGIFIEDENUM_H__
|
||||
|
||||
#include <string>
|
||||
#include <magic_enum/magic_enum.hpp>
|
||||
#include "magic_enum.hpp"
|
||||
|
||||
namespace StringifiedEnum {
|
||||
template<typename T>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <magic_enum/magic_enum.hpp>
|
||||
#include "magic_enum.hpp"
|
||||
|
||||
static const uint8_t NUMBER_OF_INVENTORIES = 17;
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,12 @@ add_subdirectory(CDClientDatabase)
|
||||
add_subdirectory(GameDatabase)
|
||||
|
||||
add_library(dDatabase STATIC "MigrationRunner.cpp")
|
||||
|
||||
add_custom_target(conncpp_dylib
|
||||
${CMAKE_COMMAND} -E copy $<TARGET_FILE:MariaDB::ConnCpp> ${PROJECT_BINARY_DIR})
|
||||
|
||||
add_dependencies(dDatabase conncpp_dylib)
|
||||
|
||||
target_include_directories(dDatabase PUBLIC ".")
|
||||
target_link_libraries(dDatabase
|
||||
PUBLIC magic_enum::magic_enum dDatabaseCDClient dDatabaseGame)
|
||||
PUBLIC dDatabaseCDClient dDatabaseGame)
|
||||
|
||||
@@ -8,6 +8,12 @@ foreach(file ${DDATABSE_DATABSES_MYSQL_SOURCES})
|
||||
set(DDATABASE_GAMEDATABASE_SOURCES ${DDATABASE_GAMEDATABASE_SOURCES} "MySQL/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(SQLite)
|
||||
|
||||
foreach(file ${DDATABSE_DATABSES_SQLITE_SOURCES})
|
||||
set(DDATABASE_GAMEDATABASE_SOURCES ${DDATABASE_GAMEDATABASE_SOURCES} "SQLite/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(TestSQL)
|
||||
|
||||
foreach(file ${DDATABSE_DATABSES_TEST_SQL_SOURCES})
|
||||
@@ -16,13 +22,14 @@ endforeach()
|
||||
|
||||
add_library(dDatabaseGame STATIC ${DDATABASE_GAMEDATABASE_SOURCES})
|
||||
target_include_directories(dDatabaseGame PUBLIC "."
|
||||
"ITables" PRIVATE "MySQL" "TestSQL"
|
||||
"ITables" PRIVATE "MySQL" "SQLite" "TestSQL"
|
||||
"${PROJECT_SOURCE_DIR}/dCommon"
|
||||
"${PROJECT_SOURCE_DIR}/dCommon/dEnums"
|
||||
)
|
||||
|
||||
target_link_libraries(dDatabaseGame
|
||||
PUBLIC MariaDB::ConnCpp
|
||||
INTERFACE dCommon)
|
||||
INTERFACE dCommon
|
||||
PRIVATE sqlite3 MariaDB::ConnCpp)
|
||||
|
||||
# Glob together all headers that need to be precompiled
|
||||
file(
|
||||
|
||||
@@ -2,22 +2,46 @@
|
||||
#include "Game.h"
|
||||
#include "dConfig.h"
|
||||
#include "Logger.h"
|
||||
#include "MySQLDatabase.h"
|
||||
#include "DluAssert.h"
|
||||
|
||||
#include "SQLiteDatabase.h"
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#pragma warning (disable:4251) //Disables SQL warnings
|
||||
|
||||
namespace {
|
||||
GameDatabase* database = nullptr;
|
||||
}
|
||||
|
||||
std::string Database::GetMigrationFolder() {
|
||||
const std::set<std::string> validMysqlTypes = { "mysql", "mariadb", "maria" };
|
||||
auto databaseType = Game::config->GetValue("database_type");
|
||||
std::ranges::transform(databaseType, databaseType.begin(), ::tolower);
|
||||
if (databaseType == "sqlite") return "sqlite";
|
||||
else if (validMysqlTypes.contains(databaseType)) return "mysql";
|
||||
else {
|
||||
LOG("No database specified, using MySQL");
|
||||
return "mysql";
|
||||
}
|
||||
}
|
||||
|
||||
void Database::Connect() {
|
||||
if (database) {
|
||||
LOG("Tried to connect to database when it's already connected!");
|
||||
return;
|
||||
}
|
||||
|
||||
database = new MySQLDatabase();
|
||||
const auto databaseType = GetMigrationFolder();
|
||||
|
||||
if (databaseType == "sqlite") database = new SQLiteDatabase();
|
||||
else if (databaseType == "mysql") database = new MySQLDatabase();
|
||||
else {
|
||||
LOG("Invalid database type specified in config, using MySQL");
|
||||
database = new MySQLDatabase();
|
||||
}
|
||||
|
||||
database->Connect();
|
||||
}
|
||||
|
||||
|
||||
@@ -12,4 +12,6 @@ namespace Database {
|
||||
// Used for assigning a test database as the handler for database logic.
|
||||
// Do not use in production code.
|
||||
void _setDatabase(GameDatabase* const db);
|
||||
|
||||
std::string GetMigrationFolder();
|
||||
};
|
||||
|
||||
@@ -26,13 +26,8 @@
|
||||
#include "IBehaviors.h"
|
||||
#include "IUgcModularBuild.h"
|
||||
|
||||
namespace sql {
|
||||
class Statement;
|
||||
class PreparedStatement;
|
||||
};
|
||||
|
||||
#ifdef _DEBUG
|
||||
# define DLU_SQL_TRY_CATCH_RETHROW(x) do { try { x; } catch (sql::SQLException& ex) { LOG("SQL Error: %s", ex.what()); throw; } } while(0)
|
||||
# define DLU_SQL_TRY_CATCH_RETHROW(x) do { try { x; } catch (std::exception& ex) { LOG("SQL Error: %s", ex.what()); throw; } } while(0)
|
||||
#else
|
||||
# define DLU_SQL_TRY_CATCH_RETHROW(x) x
|
||||
#endif // _DEBUG
|
||||
@@ -50,7 +45,6 @@ public:
|
||||
virtual void Connect() = 0;
|
||||
virtual void Destroy(std::string source = "") = 0;
|
||||
virtual void ExecuteCustomQuery(const std::string_view query) = 0;
|
||||
virtual sql::PreparedStatement* CreatePreppedStmt(const std::string& query) = 0;
|
||||
virtual void Commit() = 0;
|
||||
virtual bool GetAutoCommit() = 0;
|
||||
virtual void SetAutoCommit(bool value) = 0;
|
||||
|
||||
@@ -36,6 +36,8 @@ public:
|
||||
|
||||
// Update the GameMaster level of an account.
|
||||
virtual void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) = 0;
|
||||
|
||||
virtual uint32_t GetAccountCount() = 0;
|
||||
};
|
||||
|
||||
#endif //!__IACCOUNTS__H__
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace {
|
||||
};
|
||||
|
||||
void MySQLDatabase::Connect() {
|
||||
LOG("Using MySQL database");
|
||||
driver = sql::mariadb::get_driver_instance();
|
||||
|
||||
// The mariadb connector is *supposed* to handle unix:// and pipe:// prefixes to hostName, but there are bugs where
|
||||
@@ -67,7 +68,7 @@ void MySQLDatabase::ExecuteCustomQuery(const std::string_view query) {
|
||||
|
||||
sql::PreparedStatement* MySQLDatabase::CreatePreppedStmt(const std::string& query) {
|
||||
if (!con) {
|
||||
Connect();
|
||||
Database::Get()->Connect();
|
||||
LOG("Trying to reconnect to MySQL");
|
||||
}
|
||||
|
||||
@@ -76,7 +77,7 @@ sql::PreparedStatement* MySQLDatabase::CreatePreppedStmt(const std::string& quer
|
||||
|
||||
con = nullptr;
|
||||
|
||||
Connect();
|
||||
Database::Get()->Connect();
|
||||
LOG("Trying to reconnect to MySQL from invalid or closed connection");
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ public:
|
||||
void Connect() override;
|
||||
void Destroy(std::string source = "") override;
|
||||
|
||||
sql::PreparedStatement* CreatePreppedStmt(const std::string& query) override;
|
||||
void Commit() override;
|
||||
bool GetAutoCommit() override;
|
||||
void SetAutoCommit(bool value) override;
|
||||
@@ -125,6 +124,8 @@ public:
|
||||
void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) override;
|
||||
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) override;
|
||||
void DeleteUgcBuild(const LWOOBJID bigId) override;
|
||||
sql::PreparedStatement* CreatePreppedStmt(const std::string& query);
|
||||
uint32_t GetAccountCount() override;
|
||||
private:
|
||||
|
||||
// Generic query functions that can be used for any query.
|
||||
|
||||
@@ -39,3 +39,8 @@ void MySQLDatabase::InsertNewAccount(const std::string_view username, const std:
|
||||
void MySQLDatabase::UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) {
|
||||
ExecuteUpdate("UPDATE accounts SET gm_level = ? WHERE id = ?;", static_cast<int32_t>(gmLevel), accountId);
|
||||
}
|
||||
|
||||
uint32_t MySQLDatabase::GetAccountCount() {
|
||||
auto res = ExecuteSelect("SELECT COUNT(*) as count FROM accounts;");
|
||||
return res->next() ? res->getUInt("count") : 0;
|
||||
}
|
||||
|
||||
11
dDatabase/GameDatabase/SQLite/CMakeLists.txt
Normal file
11
dDatabase/GameDatabase/SQLite/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
SET(DDATABSE_DATABSES_SQLITE_SOURCES
|
||||
"SQLiteDatabase.cpp"
|
||||
)
|
||||
|
||||
add_subdirectory(Tables)
|
||||
|
||||
foreach(file ${DDATABASES_DATABASES_SQLITE_TABLES_SOURCES})
|
||||
set(DDATABSE_DATABSES_SQLITE_SOURCES ${DDATABSE_DATABSES_SQLITE_SOURCES} "Tables/${file}")
|
||||
endforeach()
|
||||
|
||||
set(DDATABSE_DATABSES_SQLITE_SOURCES ${DDATABSE_DATABSES_SQLITE_SOURCES} PARENT_SCOPE)
|
||||
73
dDatabase/GameDatabase/SQLite/SQLiteDatabase.cpp
Normal file
73
dDatabase/GameDatabase/SQLite/SQLiteDatabase.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
#include "Database.h"
|
||||
#include "Game.h"
|
||||
#include "dConfig.h"
|
||||
#include "Logger.h"
|
||||
#include "dPlatforms.h"
|
||||
|
||||
// Static Variables
|
||||
|
||||
// Status Variables
|
||||
namespace {
|
||||
CppSQLite3DB* con = nullptr;
|
||||
bool isConnected = false;
|
||||
};
|
||||
|
||||
void SQLiteDatabase::Connect() {
|
||||
LOG("Using SQLite database");
|
||||
con = new CppSQLite3DB();
|
||||
con->open(Game::config->GetValue("sqlite_database_path").c_str());
|
||||
isConnected = true;
|
||||
|
||||
// Make sure wal is enabled for the database.
|
||||
con->execQuery("PRAGMA journal_mode = WAL;");
|
||||
}
|
||||
|
||||
void SQLiteDatabase::Destroy(std::string source) {
|
||||
if (!con) return;
|
||||
|
||||
if (source.empty()) LOG("Destroying SQLite connection!");
|
||||
else LOG("Destroying SQLite connection from %s!", source.c_str());
|
||||
|
||||
con->close();
|
||||
delete con;
|
||||
con = nullptr;
|
||||
}
|
||||
|
||||
void SQLiteDatabase::ExecuteCustomQuery(const std::string_view query) {
|
||||
con->compileStatement(query.data()).execDML();
|
||||
}
|
||||
|
||||
CppSQLite3Statement SQLiteDatabase::CreatePreppedStmt(const std::string& query) {
|
||||
return con->compileStatement(query.c_str());
|
||||
}
|
||||
|
||||
void SQLiteDatabase::Commit() {
|
||||
if (!con->IsAutoCommitOn()) con->compileStatement("COMMIT;").execDML();
|
||||
}
|
||||
|
||||
bool SQLiteDatabase::GetAutoCommit() {
|
||||
return con->IsAutoCommitOn();
|
||||
}
|
||||
|
||||
void SQLiteDatabase::SetAutoCommit(bool value) {
|
||||
if (value) {
|
||||
if (GetAutoCommit()) con->compileStatement("BEGIN;").execDML();
|
||||
} else {
|
||||
if (!GetAutoCommit()) con->compileStatement("COMMIT;").execDML();
|
||||
}
|
||||
}
|
||||
|
||||
void SQLiteDatabase::DeleteCharacter(const uint32_t characterId) {
|
||||
ExecuteDelete("DELETE FROM charxml WHERE id=?;", characterId);
|
||||
ExecuteDelete("DELETE FROM command_log WHERE character_id=?;", characterId);
|
||||
ExecuteDelete("DELETE FROM friends WHERE player_id=? OR friend_id=?;", characterId, characterId);
|
||||
ExecuteDelete("DELETE FROM leaderboard WHERE character_id=?;", characterId);
|
||||
ExecuteDelete("DELETE FROM properties_contents WHERE property_id IN (SELECT id FROM properties WHERE owner_id=?);", characterId);
|
||||
ExecuteDelete("DELETE FROM properties WHERE owner_id=?;", characterId);
|
||||
ExecuteDelete("DELETE FROM ugc WHERE character_id=?;", characterId);
|
||||
ExecuteDelete("DELETE FROM activity_log WHERE character_id=?;", characterId);
|
||||
ExecuteDelete("DELETE FROM mail WHERE receiver_id=?;", characterId);
|
||||
ExecuteDelete("DELETE FROM charinfo WHERE id=?;", characterId);
|
||||
}
|
||||
270
dDatabase/GameDatabase/SQLite/SQLiteDatabase.h
Normal file
270
dDatabase/GameDatabase/SQLite/SQLiteDatabase.h
Normal file
@@ -0,0 +1,270 @@
|
||||
#ifndef SQLITEDATABASE_H
|
||||
#define SQLITEDATABASE_H
|
||||
|
||||
#include "CppSQLite3.h"
|
||||
|
||||
#include "GameDatabase.h"
|
||||
|
||||
using PreppedStmtRef = CppSQLite3Statement&;
|
||||
|
||||
// Purposefully no definition for this to provide linker errors in the case someone tries to
|
||||
// bind a parameter to a type that isn't defined.
|
||||
template<typename ParamType>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const ParamType param);
|
||||
|
||||
// This is a function to set each parameter in a prepared statement.
|
||||
// This is accomplished with a combination of parameter packing and Fold Expressions.
|
||||
// The constexpr if statement is used to prevent the compiler from trying to call SetParam with 0 arguments.
|
||||
template<typename... Args>
|
||||
void SetParams(PreppedStmtRef stmt, Args&&... args) {
|
||||
if constexpr (sizeof...(args) != 0) {
|
||||
int i = 1;
|
||||
(SetParam(stmt, i++, args), ...);
|
||||
}
|
||||
}
|
||||
|
||||
class SQLiteDatabase : public GameDatabase {
|
||||
public:
|
||||
void Connect() override;
|
||||
void Destroy(std::string source = "") override;
|
||||
|
||||
void Commit() override;
|
||||
bool GetAutoCommit() override;
|
||||
void SetAutoCommit(bool value) override;
|
||||
void ExecuteCustomQuery(const std::string_view query) override;
|
||||
|
||||
// Overloaded queries
|
||||
std::optional<IServers::MasterInfo> GetMasterInfo() override;
|
||||
|
||||
std::vector<std::string> GetApprovedCharacterNames() override;
|
||||
|
||||
std::vector<FriendData> GetFriendsList(uint32_t charID) override;
|
||||
|
||||
std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) override;
|
||||
void SetBestFriendStatus(const uint32_t playerAccountId, const uint32_t friendAccountId, const uint32_t bestFriendStatus) override;
|
||||
void AddFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
||||
void RemoveFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
||||
void UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) override;
|
||||
void DeleteUgcModelData(const LWOOBJID& modelId) override;
|
||||
void UpdateUgcModelData(const LWOOBJID& modelId, std::istringstream& lxfml) override;
|
||||
std::vector<IUgc::Model> GetAllUgcModels() override;
|
||||
void CreateMigrationHistoryTable() override;
|
||||
bool IsMigrationRun(const std::string_view str) override;
|
||||
void InsertMigration(const std::string_view str) override;
|
||||
std::optional<ICharInfo::Info> GetCharacterInfo(const uint32_t charId) override;
|
||||
std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view charId) override;
|
||||
std::string GetCharacterXml(const uint32_t accountId) override;
|
||||
void UpdateCharacterXml(const uint32_t characterId, const std::string_view lxfml) override;
|
||||
std::optional<IAccounts::Info> GetAccountInfo(const std::string_view username) override;
|
||||
void InsertNewCharacter(const ICharInfo::Info info) override;
|
||||
void InsertCharacterXml(const uint32_t accountId, const std::string_view lxfml) override;
|
||||
std::vector<uint32_t> GetAccountCharacterIds(uint32_t accountId) override;
|
||||
void DeleteCharacter(const uint32_t characterId) override;
|
||||
void SetCharacterName(const uint32_t characterId, const std::string_view name) override;
|
||||
void SetPendingCharacterName(const uint32_t characterId, const std::string_view name) override;
|
||||
void UpdateLastLoggedInCharacter(const uint32_t characterId) override;
|
||||
void SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) override;
|
||||
std::optional<IPetNames::Info> GetPetNameInfo(const LWOOBJID& petId) override;
|
||||
std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) override;
|
||||
void UpdatePropertyModerationInfo(const IProperty::Info& info) override;
|
||||
void UpdatePropertyDetails(const IProperty::Info& info) override;
|
||||
void InsertNewProperty(const IProperty::Info& info, const uint32_t templateId, const LWOZONEID& zoneId) override;
|
||||
std::vector<IPropertyContents::Model> GetPropertyModels(const LWOOBJID& propertyId) override;
|
||||
void RemoveUnreferencedUgcModels() override;
|
||||
void InsertNewPropertyModel(const LWOOBJID& propertyId, const IPropertyContents::Model& model, const std::string_view name) override;
|
||||
void UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array<std::pair<int32_t, std::string>, 5>& behaviors) override;
|
||||
void RemoveModel(const LWOOBJID& modelId) override;
|
||||
void UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) override;
|
||||
void InsertNewBugReport(const IBugReports::Info& info) override;
|
||||
void InsertCheatDetection(const IPlayerCheatDetections::Info& info) override;
|
||||
void InsertNewMail(const IMail::MailInfo& mail) override;
|
||||
void InsertNewUgcModel(
|
||||
std::istringstream& sd0Data,
|
||||
const uint32_t blueprintId,
|
||||
const uint32_t accountId,
|
||||
const uint32_t characterId) override;
|
||||
std::vector<IMail::MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override;
|
||||
std::optional<IMail::MailInfo> GetMail(const uint64_t mailId) override;
|
||||
uint32_t GetUnreadMailCount(const uint32_t characterId) override;
|
||||
void MarkMailRead(const uint64_t mailId) override;
|
||||
void DeleteMail(const uint64_t mailId) override;
|
||||
void ClaimMailItem(const uint64_t mailId) override;
|
||||
void InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) override;
|
||||
void UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) override;
|
||||
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
||||
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
||||
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
||||
void SetMasterIp(const std::string_view ip, const uint32_t port) override;
|
||||
std::optional<uint32_t> GetCurrentPersistentId() override;
|
||||
void InsertDefaultPersistentId() override;
|
||||
void UpdatePersistentId(const uint32_t id) override;
|
||||
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
||||
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
||||
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
||||
void AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
||||
void RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
||||
std::vector<IIgnoreList::Info> GetIgnoreList(const uint32_t playerId) override;
|
||||
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
||||
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
||||
void AddBehavior(const IBehaviors::Info& info) override;
|
||||
std::string GetBehavior(const int32_t behaviorId) override;
|
||||
void RemoveBehavior(const int32_t characterId) override;
|
||||
void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override;
|
||||
std::optional<IProperty::PropertyEntranceResult> GetProperties(const IProperty::PropertyLookup& params) override;
|
||||
std::vector<ILeaderboard::Entry> GetDescendingLeaderboard(const uint32_t activityId) override;
|
||||
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) override;
|
||||
std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) override;
|
||||
std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) override;
|
||||
void SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
||||
void UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
||||
std::optional<ILeaderboard::Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) override;
|
||||
void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) override;
|
||||
void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) override;
|
||||
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) override;
|
||||
void DeleteUgcBuild(const LWOOBJID bigId) override;
|
||||
uint32_t GetAccountCount() override;
|
||||
private:
|
||||
CppSQLite3Statement CreatePreppedStmt(const std::string& query);
|
||||
|
||||
// Generic query functions that can be used for any query.
|
||||
// Return type may be different depending on the query, so it is up to the caller to check the return type.
|
||||
// The first argument is the query string, and the rest are the parameters to bind to the query.
|
||||
// The return type is a unique_ptr to the result set, which is deleted automatically when it goes out of scope
|
||||
template<typename... Args>
|
||||
inline std::pair<CppSQLite3Statement, CppSQLite3Query> ExecuteSelect(const std::string& query, Args&&... args) {
|
||||
std::pair<CppSQLite3Statement, CppSQLite3Query> toReturn;
|
||||
toReturn.first = CreatePreppedStmt(query);
|
||||
SetParams(toReturn.first, std::forward<Args>(args)...);
|
||||
DLU_SQL_TRY_CATCH_RETHROW(toReturn.second = toReturn.first.execQuery());
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline void ExecuteDelete(const std::string& query, Args&&... args) {
|
||||
auto preppedStmt = CreatePreppedStmt(query);
|
||||
SetParams(preppedStmt, std::forward<Args>(args)...);
|
||||
DLU_SQL_TRY_CATCH_RETHROW(preppedStmt.execDML());
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline int32_t ExecuteUpdate(const std::string& query, Args&&... args) {
|
||||
auto preppedStmt = CreatePreppedStmt(query);
|
||||
SetParams(preppedStmt, std::forward<Args>(args)...);
|
||||
DLU_SQL_TRY_CATCH_RETHROW(return preppedStmt.execDML());
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline int ExecuteInsert(const std::string& query, Args&&... args) {
|
||||
auto preppedStmt = CreatePreppedStmt(query);
|
||||
SetParams(preppedStmt, std::forward<Args>(args)...);
|
||||
DLU_SQL_TRY_CATCH_RETHROW(return preppedStmt.execDML());
|
||||
}
|
||||
};
|
||||
|
||||
// Below are each of the definitions of SetParam for each supported type.
|
||||
|
||||
template<>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const std::string_view param) {
|
||||
LOG("%s", param.data());
|
||||
stmt.bind(index, param.data());
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const char* param) {
|
||||
LOG("%s", param);
|
||||
stmt.bind(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const std::string param) {
|
||||
LOG("%s", param.c_str());
|
||||
stmt.bind(index, param.c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const int8_t param) {
|
||||
LOG("%u", param);
|
||||
stmt.bind(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const uint8_t param) {
|
||||
LOG("%d", param);
|
||||
stmt.bind(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const int16_t param) {
|
||||
LOG("%u", param);
|
||||
stmt.bind(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const uint16_t param) {
|
||||
LOG("%d", param);
|
||||
stmt.bind(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const uint32_t param) {
|
||||
LOG("%u", param);
|
||||
stmt.bind(index, static_cast<int32_t>(param));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const int32_t param) {
|
||||
LOG("%d", param);
|
||||
stmt.bind(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const int64_t param) {
|
||||
LOG("%llu", param);
|
||||
stmt.bind(index, static_cast<sqlite_int64>(param));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const uint64_t param) {
|
||||
LOG("%llu", param);
|
||||
stmt.bind(index, static_cast<sqlite_int64>(param));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const float param) {
|
||||
LOG("%f", param);
|
||||
stmt.bind(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const double param) {
|
||||
LOG("%f", param);
|
||||
stmt.bind(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const bool param) {
|
||||
LOG("%d", param);
|
||||
stmt.bind(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const std::istream* param) {
|
||||
LOG("Blob");
|
||||
// This is the one time you will ever see me use const_cast.
|
||||
std::stringstream stream;
|
||||
stream << param->rdbuf();
|
||||
stmt.bind(index, reinterpret_cast<const unsigned char*>(stream.str().c_str()), stream.str().size());
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(PreppedStmtRef stmt, const int index, const std::optional<uint32_t> param) {
|
||||
if (param) {
|
||||
LOG("%d", param.value());
|
||||
stmt.bind(index, static_cast<int>(param.value()));
|
||||
} else {
|
||||
LOG("Null");
|
||||
stmt.bindNull(index);
|
||||
}
|
||||
}
|
||||
|
||||
#endif //!SQLITEDATABASE_H
|
||||
49
dDatabase/GameDatabase/SQLite/Tables/Accounts.cpp
Normal file
49
dDatabase/GameDatabase/SQLite/Tables/Accounts.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
#include "eGameMasterLevel.h"
|
||||
#include "Database.h"
|
||||
|
||||
std::optional<IAccounts::Info> SQLiteDatabase::GetAccountInfo(const std::string_view username) {
|
||||
auto [_, result] = ExecuteSelect("SELECT * FROM accounts WHERE name = ? LIMIT 1", username);
|
||||
|
||||
if (result.eof()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
IAccounts::Info toReturn;
|
||||
toReturn.id = result.getIntField("id");
|
||||
toReturn.maxGmLevel = static_cast<eGameMasterLevel>(result.getIntField("gm_level"));
|
||||
toReturn.bcryptPassword = result.getStringField("password");
|
||||
toReturn.banned = result.getIntField("banned");
|
||||
toReturn.locked = result.getIntField("locked");
|
||||
toReturn.playKeyId = result.getIntField("play_key_id");
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) {
|
||||
ExecuteUpdate("UPDATE accounts SET mute_expire = ? WHERE id = ?;", timeToUnmute, accountId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdateAccountBan(const uint32_t accountId, const bool banned) {
|
||||
ExecuteUpdate("UPDATE accounts SET banned = ? WHERE id = ?;", banned, accountId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) {
|
||||
ExecuteUpdate("UPDATE accounts SET password = ? WHERE id = ?;", bcryptpassword, accountId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) {
|
||||
ExecuteInsert("INSERT INTO accounts (name, password, gm_level) VALUES (?, ?, ?);", username, bcryptpassword, static_cast<int32_t>(eGameMasterLevel::OPERATOR));
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) {
|
||||
ExecuteUpdate("UPDATE accounts SET gm_level = ? WHERE id = ?;", static_cast<int32_t>(gmLevel), accountId);
|
||||
}
|
||||
|
||||
uint32_t SQLiteDatabase::GetAccountCount() {
|
||||
auto [_, res] = ExecuteSelect("SELECT COUNT(*) as count FROM accounts;");
|
||||
if (res.eof()) return 0;
|
||||
|
||||
return res.getIntField("count");
|
||||
}
|
||||
17
dDatabase/GameDatabase/SQLite/Tables/AccountsRewardCodes.cpp
Normal file
17
dDatabase/GameDatabase/SQLite/Tables/AccountsRewardCodes.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
void SQLiteDatabase::InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) {
|
||||
ExecuteInsert("INSERT OR IGNORE INTO accounts_rewardcodes (account_id, rewardcode) VALUES (?, ?);", account_id, reward_code);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> SQLiteDatabase::GetRewardCodesByAccountID(const uint32_t account_id) {
|
||||
auto [_, result] = ExecuteSelect("SELECT rewardcode FROM accounts_rewardcodes WHERE account_id = ?;", account_id);
|
||||
|
||||
std::vector<uint32_t> toReturn;
|
||||
while (!result.eof()) {
|
||||
toReturn.push_back(result.getIntField("rewardcode"));
|
||||
result.nextRow();
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
6
dDatabase/GameDatabase/SQLite/Tables/ActivityLog.cpp
Normal file
6
dDatabase/GameDatabase/SQLite/Tables/ActivityLog.cpp
Normal file
@@ -0,0 +1,6 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
void SQLiteDatabase::UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
||||
ExecuteInsert("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);",
|
||||
characterId, static_cast<uint32_t>(activityType), static_cast<uint32_t>(time(NULL)), mapId);
|
||||
}
|
||||
19
dDatabase/GameDatabase/SQLite/Tables/Behaviors.cpp
Normal file
19
dDatabase/GameDatabase/SQLite/Tables/Behaviors.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "IBehaviors.h"
|
||||
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
void SQLiteDatabase::AddBehavior(const IBehaviors::Info& info) {
|
||||
ExecuteInsert(
|
||||
"INSERT INTO behaviors (behavior_info, character_id, behavior_id) VALUES (?, ?, ?) ON CONFLICT(behavior_id) DO UPDATE SET behavior_info = ?",
|
||||
info.behaviorInfo, info.characterId, info.behaviorId, info.behaviorInfo
|
||||
);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::RemoveBehavior(const int32_t behaviorId) {
|
||||
ExecuteDelete("DELETE FROM behaviors WHERE behavior_id = ?", behaviorId);
|
||||
}
|
||||
|
||||
std::string SQLiteDatabase::GetBehavior(const int32_t behaviorId) {
|
||||
auto [_, result] = ExecuteSelect("SELECT behavior_info FROM behaviors WHERE behavior_id = ?", behaviorId);
|
||||
return !result.eof() ? result.getStringField("behavior_info") : "";
|
||||
}
|
||||
6
dDatabase/GameDatabase/SQLite/Tables/BugReports.cpp
Normal file
6
dDatabase/GameDatabase/SQLite/Tables/BugReports.cpp
Normal file
@@ -0,0 +1,6 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
void SQLiteDatabase::InsertNewBugReport(const IBugReports::Info& info) {
|
||||
ExecuteInsert("INSERT INTO `bug_reports`(body, client_version, other_player_id, selection, reporter_id) VALUES (?, ?, ?, ?, ?)",
|
||||
info.body, info.clientVersion, info.otherPlayer, info.selection, info.characterId);
|
||||
}
|
||||
26
dDatabase/GameDatabase/SQLite/Tables/CMakeLists.txt
Normal file
26
dDatabase/GameDatabase/SQLite/Tables/CMakeLists.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
set(DDATABASES_DATABASES_SQLITE_TABLES_SOURCES
|
||||
"Accounts.cpp"
|
||||
"AccountsRewardCodes.cpp"
|
||||
"ActivityLog.cpp"
|
||||
"Behaviors.cpp"
|
||||
"BugReports.cpp"
|
||||
"CharInfo.cpp"
|
||||
"CharXml.cpp"
|
||||
"CommandLog.cpp"
|
||||
"Friends.cpp"
|
||||
"IgnoreList.cpp"
|
||||
"Leaderboard.cpp"
|
||||
"Mail.cpp"
|
||||
"MigrationHistory.cpp"
|
||||
"ObjectIdTracker.cpp"
|
||||
"PetNames.cpp"
|
||||
"PlayerCheatDetections.cpp"
|
||||
"PlayKeys.cpp"
|
||||
"Property.cpp"
|
||||
"PropertyContents.cpp"
|
||||
"Servers.cpp"
|
||||
"Ugc.cpp"
|
||||
"UgcModularBuild.cpp"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
79
dDatabase/GameDatabase/SQLite/Tables/CharInfo.cpp
Normal file
79
dDatabase/GameDatabase/SQLite/Tables/CharInfo.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
std::vector<std::string> SQLiteDatabase::GetApprovedCharacterNames() {
|
||||
auto [_, result] = ExecuteSelect("SELECT name FROM charinfo;");
|
||||
|
||||
std::vector<std::string> toReturn;
|
||||
|
||||
while (!result.eof()) {
|
||||
toReturn.push_back(result.getStringField("name"));
|
||||
result.nextRow();
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
std::optional<ICharInfo::Info> CharInfoFromQueryResult(CppSQLite3Query stmt) {
|
||||
if (stmt.eof()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
ICharInfo::Info toReturn;
|
||||
|
||||
toReturn.id = stmt.getIntField("id");
|
||||
toReturn.name = stmt.getStringField("name");
|
||||
toReturn.pendingName = stmt.getStringField("pending_name");
|
||||
toReturn.needsRename = stmt.getIntField("needs_rename");
|
||||
toReturn.cloneId = stmt.getInt64Field("prop_clone_id");
|
||||
toReturn.accountId = stmt.getIntField("account_id");
|
||||
toReturn.permissionMap = static_cast<ePermissionMap>(stmt.getIntField("permission_map"));
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
std::optional<ICharInfo::Info> SQLiteDatabase::GetCharacterInfo(const uint32_t charId) {
|
||||
return CharInfoFromQueryResult(
|
||||
ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE id = ? LIMIT 1;", charId).second
|
||||
);
|
||||
}
|
||||
|
||||
std::optional<ICharInfo::Info> SQLiteDatabase::GetCharacterInfo(const std::string_view name) {
|
||||
return CharInfoFromQueryResult(
|
||||
ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE name = ? LIMIT 1;", name).second
|
||||
);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> SQLiteDatabase::GetAccountCharacterIds(const uint32_t accountId) {
|
||||
auto [_, result] = ExecuteSelect("SELECT id FROM charinfo WHERE account_id = ? ORDER BY last_login DESC LIMIT 4;", accountId);
|
||||
|
||||
std::vector<uint32_t> toReturn;
|
||||
while (!result.eof()) {
|
||||
toReturn.push_back(result.getIntField("id"));
|
||||
result.nextRow();
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
void SQLiteDatabase::InsertNewCharacter(const ICharInfo::Info info) {
|
||||
ExecuteInsert(
|
||||
"INSERT INTO `charinfo`(`id`, `account_id`, `name`, `pending_name`, `needs_rename`, `last_login`, `prop_clone_id`) VALUES (?,?,?,?,?,?,(SELECT IFNULL(MAX(`prop_clone_id`), 0) + 1 FROM `charinfo`))",
|
||||
info.id,
|
||||
info.accountId,
|
||||
info.name,
|
||||
info.pendingName,
|
||||
false,
|
||||
static_cast<uint32_t>(time(NULL)));
|
||||
}
|
||||
|
||||
void SQLiteDatabase::SetCharacterName(const uint32_t characterId, const std::string_view name) {
|
||||
ExecuteUpdate("UPDATE charinfo SET name = ?, pending_name = '', needs_rename = 0, last_login = ? WHERE id = ?;", name, static_cast<uint32_t>(time(NULL)), characterId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::SetPendingCharacterName(const uint32_t characterId, const std::string_view name) {
|
||||
ExecuteUpdate("UPDATE charinfo SET pending_name = ?, needs_rename = 0, last_login = ? WHERE id = ?;", name, static_cast<uint32_t>(time(NULL)), characterId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdateLastLoggedInCharacter(const uint32_t characterId) {
|
||||
ExecuteUpdate("UPDATE charinfo SET last_login = ? WHERE id = ?;", static_cast<uint32_t>(time(NULL)), characterId);
|
||||
}
|
||||
19
dDatabase/GameDatabase/SQLite/Tables/CharXml.cpp
Normal file
19
dDatabase/GameDatabase/SQLite/Tables/CharXml.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
std::string SQLiteDatabase::GetCharacterXml(const uint32_t charId) {
|
||||
auto [_, result] = ExecuteSelect("SELECT xml_data FROM charxml WHERE id = ? LIMIT 1;", charId);
|
||||
|
||||
if (result.eof()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return result.getStringField("xml_data");
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdateCharacterXml(const uint32_t charId, const std::string_view lxfml) {
|
||||
ExecuteUpdate("UPDATE charxml SET xml_data = ? WHERE id = ?;", lxfml, charId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::InsertCharacterXml(const uint32_t characterId, const std::string_view lxfml) {
|
||||
ExecuteInsert("INSERT INTO `charxml` (`id`, `xml_data`) VALUES (?,?)", characterId, lxfml);
|
||||
}
|
||||
5
dDatabase/GameDatabase/SQLite/Tables/CommandLog.cpp
Normal file
5
dDatabase/GameDatabase/SQLite/Tables/CommandLog.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
void SQLiteDatabase::InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) {
|
||||
ExecuteInsert("INSERT INTO command_log (character_id, command) VALUES (?, ?);", characterId, command);
|
||||
}
|
||||
73
dDatabase/GameDatabase/SQLite/Tables/Friends.cpp
Normal file
73
dDatabase/GameDatabase/SQLite/Tables/Friends.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
std::vector<FriendData> SQLiteDatabase::GetFriendsList(const uint32_t charId) {
|
||||
auto [_, friendsList] = ExecuteSelect(
|
||||
R"QUERY(
|
||||
SELECT fr.requested_player AS player, best_friend AS bff, ci.name AS name FROM
|
||||
(
|
||||
SELECT CASE
|
||||
WHEN player_id = ? THEN friend_id
|
||||
WHEN friend_id = ? THEN player_id
|
||||
END AS requested_player, best_friend FROM friends
|
||||
) AS fr
|
||||
JOIN charinfo AS ci ON ci.id = fr.requested_player
|
||||
WHERE fr.requested_player IS NOT NULL AND fr.requested_player != ?;
|
||||
)QUERY", charId, charId, charId);
|
||||
|
||||
std::vector<FriendData> toReturn;
|
||||
|
||||
while (!friendsList.eof()) {
|
||||
FriendData fd;
|
||||
fd.friendID = friendsList.getIntField("player");
|
||||
fd.isBestFriend = friendsList.getIntField("bff") == 3; // 0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
||||
fd.friendName = friendsList.getStringField("name");
|
||||
|
||||
toReturn.push_back(fd);
|
||||
friendsList.nextRow();
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
std::optional<IFriends::BestFriendStatus> SQLiteDatabase::GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
||||
auto [_, result] = ExecuteSelect("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
||||
playerCharacterId,
|
||||
friendCharacterId,
|
||||
friendCharacterId,
|
||||
playerCharacterId
|
||||
);
|
||||
|
||||
if (result.eof()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
IFriends::BestFriendStatus toReturn;
|
||||
toReturn.playerCharacterId = result.getIntField("player_id");
|
||||
toReturn.friendCharacterId = result.getIntField("friend_id");
|
||||
toReturn.bestFriendStatus = result.getIntField("best_friend");
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
void SQLiteDatabase::SetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId, const uint32_t bestFriendStatus) {
|
||||
ExecuteUpdate("UPDATE friends SET best_friend = ? WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?);",
|
||||
bestFriendStatus,
|
||||
playerCharacterId,
|
||||
friendCharacterId,
|
||||
friendCharacterId,
|
||||
playerCharacterId
|
||||
);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::AddFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
||||
ExecuteInsert("INSERT OR IGNORE INTO friends (player_id, friend_id, best_friend) VALUES (?, ?, 0);", playerCharacterId, friendCharacterId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::RemoveFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
||||
ExecuteDelete("DELETE FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?);",
|
||||
playerCharacterId,
|
||||
friendCharacterId,
|
||||
friendCharacterId,
|
||||
playerCharacterId
|
||||
);
|
||||
}
|
||||
22
dDatabase/GameDatabase/SQLite/Tables/IgnoreList.cpp
Normal file
22
dDatabase/GameDatabase/SQLite/Tables/IgnoreList.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
std::vector<IIgnoreList::Info> SQLiteDatabase::GetIgnoreList(const uint32_t playerId) {
|
||||
auto [_, result] = ExecuteSelect("SELECT ci.name AS name, il.ignored_player_id AS ignore_id FROM ignore_list AS il JOIN charinfo AS ci ON il.ignored_player_id = ci.id WHERE il.player_id = ?", playerId);
|
||||
|
||||
std::vector<IIgnoreList::Info> ignoreList;
|
||||
|
||||
while (!result.eof()) {
|
||||
ignoreList.push_back(IIgnoreList::Info{ result.getStringField("name"), static_cast<uint32_t>(result.getIntField("ignore_id")) });
|
||||
result.nextRow();
|
||||
}
|
||||
|
||||
return ignoreList;
|
||||
}
|
||||
|
||||
void SQLiteDatabase::AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
||||
ExecuteInsert("INSERT OR IGNORE INTO ignore_list (player_id, ignored_player_id) VALUES (?, ?)", playerId, ignoredPlayerId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
||||
ExecuteDelete("DELETE FROM ignore_list WHERE player_id = ? AND ignored_player_id = ?", playerId, ignoredPlayerId);
|
||||
}
|
||||
91
dDatabase/GameDatabase/SQLite/Tables/Leaderboard.cpp
Normal file
91
dDatabase/GameDatabase/SQLite/Tables/Leaderboard.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
#include "Game.h"
|
||||
#include "Logger.h"
|
||||
#include "dConfig.h"
|
||||
|
||||
std::optional<uint32_t> SQLiteDatabase::GetDonationTotal(const uint32_t activityId) {
|
||||
auto [_, donation_total] = ExecuteSelect("SELECT SUM(primaryScore) as donation_total FROM leaderboard WHERE game_id = ?;", activityId);
|
||||
|
||||
if (donation_total.eof()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return donation_total.getIntField("donation_total");
|
||||
}
|
||||
|
||||
std::vector<ILeaderboard::Entry> ProcessQuery(CppSQLite3Query& rows) {
|
||||
std::vector<ILeaderboard::Entry> entries;
|
||||
|
||||
while (!rows.eof()) {
|
||||
auto& entry = entries.emplace_back();
|
||||
|
||||
entry.charId = rows.getIntField("character_id");
|
||||
entry.lastPlayedTimestamp = rows.getIntField("lp_unix");
|
||||
entry.primaryScore = rows.getFloatField("primaryScore");
|
||||
entry.secondaryScore = rows.getFloatField("secondaryScore");
|
||||
entry.tertiaryScore = rows.getFloatField("tertiaryScore");
|
||||
entry.numWins = rows.getIntField("numWins");
|
||||
entry.numTimesPlayed = rows.getIntField("timesPlayed");
|
||||
entry.name = rows.getStringField("char_name");
|
||||
// entry.ranking is never set because its calculated in leaderboard in code.
|
||||
rows.nextRow();
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
std::vector<ILeaderboard::Entry> SQLiteDatabase::GetDescendingLeaderboard(const uint32_t activityId) {
|
||||
auto [_, result] = ExecuteSelect("SELECT *, CAST(strftime('%s', last_played) as INT) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY primaryscore DESC, secondaryscore DESC, tertiaryScore DESC, last_played ASC;", activityId);
|
||||
return ProcessQuery(result);
|
||||
}
|
||||
|
||||
std::vector<ILeaderboard::Entry> SQLiteDatabase::GetAscendingLeaderboard(const uint32_t activityId) {
|
||||
auto [_, result] = ExecuteSelect("SELECT *, CAST(strftime('%s', last_played) as INT) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY primaryscore ASC, secondaryscore ASC, tertiaryScore ASC, last_played ASC;", activityId);
|
||||
return ProcessQuery(result);
|
||||
}
|
||||
|
||||
std::vector<ILeaderboard::Entry> SQLiteDatabase::GetAgsLeaderboard(const uint32_t activityId) {
|
||||
auto query = Game::config->GetValue("classic_survival_scoring") != "1" ?
|
||||
"SELECT *, CAST(strftime('%s', last_played) as INT) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY primaryscore DESC, secondaryscore DESC, tertiaryScore DESC, last_played ASC;" :
|
||||
"SELECT *, CAST(strftime('%s', last_played) as INT) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY secondaryscore DESC, primaryscore DESC, tertiaryScore DESC, last_played ASC;";
|
||||
auto [_, result] = ExecuteSelect(query, activityId);
|
||||
return ProcessQuery(result);
|
||||
}
|
||||
|
||||
std::vector<ILeaderboard::Entry> SQLiteDatabase::GetNsLeaderboard(const uint32_t activityId) {
|
||||
auto [_, result] = ExecuteSelect("SELECT *, CAST(strftime('%s', last_played) as INT) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY primaryscore DESC, secondaryscore ASC, tertiaryScore DESC, last_played ASC;", activityId);
|
||||
return ProcessQuery(result);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
|
||||
ExecuteInsert("INSERT INTO leaderboard (primaryScore, secondaryScore, tertiaryScore, character_id, game_id, last_played) VALUES (?,?,?,?,?,CURRENT_TIMESTAMP) ;",
|
||||
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
|
||||
ExecuteInsert("UPDATE leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, timesPlayed = timesPlayed + 1, last_played = CURRENT_TIMESTAMP WHERE character_id = ? AND game_id = ?;",
|
||||
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
||||
}
|
||||
|
||||
std::optional<ILeaderboard::Score> SQLiteDatabase::GetPlayerScore(const uint32_t playerId, const uint32_t gameId) {
|
||||
std::optional<ILeaderboard::Score> toReturn = std::nullopt;
|
||||
auto [_, res] = ExecuteSelect("SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
||||
if (!res.eof()) {
|
||||
toReturn = ILeaderboard::Score{
|
||||
.primaryScore = static_cast<float>(res.getFloatField("primaryScore")),
|
||||
.secondaryScore = static_cast<float>(res.getFloatField("secondaryScore")),
|
||||
.tertiaryScore = static_cast<float>(res.getFloatField("tertiaryScore"))
|
||||
};
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
void SQLiteDatabase::IncrementNumWins(const uint32_t playerId, const uint32_t gameId) {
|
||||
ExecuteUpdate("UPDATE leaderboard SET numWins = numWins + 1, last_played = CURRENT_TIMESTAMP WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) {
|
||||
ExecuteUpdate("UPDATE leaderboard SET timesPlayed = timesPlayed + 1, last_played = CURRENT_TIMESTAMP WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
||||
}
|
||||
83
dDatabase/GameDatabase/SQLite/Tables/Mail.cpp
Normal file
83
dDatabase/GameDatabase/SQLite/Tables/Mail.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
void SQLiteDatabase::InsertNewMail(const IMail::MailInfo& mail) {
|
||||
ExecuteInsert(
|
||||
"INSERT INTO `mail` "
|
||||
"(`sender_id`, `sender_name`, `receiver_id`, `receiver_name`, `time_sent`, `subject`, `body`, `attachment_id`, `attachment_lot`, `attachment_subkey`, `attachment_count`, `was_read`)"
|
||||
" VALUES (?,?,?,?,?,?,?,?,?,?,?,0)",
|
||||
mail.senderId,
|
||||
mail.senderUsername,
|
||||
mail.receiverId,
|
||||
mail.recipient,
|
||||
static_cast<uint32_t>(time(NULL)),
|
||||
mail.subject,
|
||||
mail.body,
|
||||
mail.itemID,
|
||||
mail.itemLOT,
|
||||
0,
|
||||
mail.itemCount);
|
||||
}
|
||||
|
||||
std::vector<IMail::MailInfo> SQLiteDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) {
|
||||
auto [_, res] = ExecuteSelect(
|
||||
"SELECT id, subject, body, sender_name, attachment_id, attachment_lot, attachment_subkey, attachment_count, was_read, time_sent"
|
||||
" FROM mail WHERE receiver_id=? limit ?;",
|
||||
characterId, numberOfMail);
|
||||
|
||||
std::vector<IMail::MailInfo> toReturn;
|
||||
|
||||
while (!res.eof()) {
|
||||
IMail::MailInfo mail;
|
||||
mail.id = res.getInt64Field("id");
|
||||
mail.subject = res.getStringField("subject");
|
||||
mail.body = res.getStringField("body");
|
||||
mail.senderUsername = res.getStringField("sender_name");
|
||||
mail.itemID = res.getIntField("attachment_id");
|
||||
mail.itemLOT = res.getIntField("attachment_lot");
|
||||
mail.itemSubkey = res.getIntField("attachment_subkey");
|
||||
mail.itemCount = res.getIntField("attachment_count");
|
||||
mail.timeSent = res.getInt64Field("time_sent");
|
||||
mail.wasRead = res.getIntField("was_read");
|
||||
|
||||
toReturn.push_back(std::move(mail));
|
||||
res.nextRow();
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
std::optional<IMail::MailInfo> SQLiteDatabase::GetMail(const uint64_t mailId) {
|
||||
auto [_, res] = ExecuteSelect("SELECT attachment_lot, attachment_count FROM mail WHERE id=? LIMIT 1;", mailId);
|
||||
|
||||
if (res.eof()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
IMail::MailInfo toReturn;
|
||||
toReturn.itemLOT = res.getIntField("attachment_lot");
|
||||
toReturn.itemCount = res.getIntField("attachment_count");
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
uint32_t SQLiteDatabase::GetUnreadMailCount(const uint32_t characterId) {
|
||||
auto [_, res] = ExecuteSelect("SELECT COUNT(*) AS number_unread FROM mail WHERE receiver_id=? AND was_read=0;", characterId);
|
||||
|
||||
if (res.eof()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return res.getIntField("number_unread");
|
||||
}
|
||||
|
||||
void SQLiteDatabase::MarkMailRead(const uint64_t mailId) {
|
||||
ExecuteUpdate("UPDATE mail SET was_read=1 WHERE id=?;", mailId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::ClaimMailItem(const uint64_t mailId) {
|
||||
ExecuteUpdate("UPDATE mail SET attachment_lot=0 WHERE id=?;", mailId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::DeleteMail(const uint64_t mailId) {
|
||||
ExecuteDelete("DELETE FROM mail WHERE id=?;", mailId);
|
||||
}
|
||||
13
dDatabase/GameDatabase/SQLite/Tables/MigrationHistory.cpp
Normal file
13
dDatabase/GameDatabase/SQLite/Tables/MigrationHistory.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
void SQLiteDatabase::CreateMigrationHistoryTable() {
|
||||
ExecuteInsert("CREATE TABLE IF NOT EXISTS migration_history (name TEXT NOT NULL, date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP);");
|
||||
}
|
||||
|
||||
bool SQLiteDatabase::IsMigrationRun(const std::string_view str) {
|
||||
return !ExecuteSelect("SELECT name FROM migration_history WHERE name = ?;", str).second.eof();
|
||||
}
|
||||
|
||||
void SQLiteDatabase::InsertMigration(const std::string_view str) {
|
||||
ExecuteInsert("INSERT INTO migration_history (name) VALUES (?);", str);
|
||||
}
|
||||
17
dDatabase/GameDatabase/SQLite/Tables/ObjectIdTracker.cpp
Normal file
17
dDatabase/GameDatabase/SQLite/Tables/ObjectIdTracker.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
std::optional<uint32_t> SQLiteDatabase::GetCurrentPersistentId() {
|
||||
auto [_, result] = ExecuteSelect("SELECT last_object_id FROM object_id_tracker");
|
||||
if (result.eof()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return result.getIntField("last_object_id");
|
||||
}
|
||||
|
||||
void SQLiteDatabase::InsertDefaultPersistentId() {
|
||||
ExecuteInsert("INSERT INTO object_id_tracker VALUES (1);");
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdatePersistentId(const uint32_t newId) {
|
||||
ExecuteUpdate("UPDATE object_id_tracker SET last_object_id = ?;", newId);
|
||||
}
|
||||
26
dDatabase/GameDatabase/SQLite/Tables/PetNames.cpp
Normal file
26
dDatabase/GameDatabase/SQLite/Tables/PetNames.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
void SQLiteDatabase::SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) {
|
||||
ExecuteInsert(
|
||||
"INSERT INTO `pet_names` (`id`, `pet_name`, `approved`) VALUES (?, ?, ?) "
|
||||
"ON CONFLICT(id) DO UPDATE SET pet_name = ?, approved = ?;",
|
||||
petId,
|
||||
info.petName,
|
||||
info.approvalStatus,
|
||||
info.petName,
|
||||
info.approvalStatus);
|
||||
}
|
||||
|
||||
std::optional<IPetNames::Info> SQLiteDatabase::GetPetNameInfo(const LWOOBJID& petId) {
|
||||
auto [_, result] = ExecuteSelect("SELECT pet_name, approved FROM pet_names WHERE id = ? LIMIT 1;", petId);
|
||||
|
||||
if (result.eof()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
IPetNames::Info toReturn;
|
||||
toReturn.petName = result.getStringField("pet_name");
|
||||
toReturn.approvalStatus = result.getIntField("approved");
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
11
dDatabase/GameDatabase/SQLite/Tables/PlayKeys.cpp
Normal file
11
dDatabase/GameDatabase/SQLite/Tables/PlayKeys.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
std::optional<bool> SQLiteDatabase::IsPlaykeyActive(const int32_t playkeyId) {
|
||||
auto [_, keyCheckRes] = ExecuteSelect("SELECT active FROM `play_keys` WHERE id=?", playkeyId);
|
||||
|
||||
if (keyCheckRes.eof()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return keyCheckRes.getIntField("active");
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
void SQLiteDatabase::InsertCheatDetection(const IPlayerCheatDetections::Info& info) {
|
||||
ExecuteInsert(
|
||||
"INSERT INTO player_cheat_detections (account_id, name, violation_msg, violation_system_address) VALUES (?, ?, ?, ?)",
|
||||
info.userId, info.username, info.extraMessage, info.systemAddress);
|
||||
}
|
||||
195
dDatabase/GameDatabase/SQLite/Tables/Property.cpp
Normal file
195
dDatabase/GameDatabase/SQLite/Tables/Property.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
#include "ePropertySortType.h"
|
||||
|
||||
std::optional<IProperty::PropertyEntranceResult> SQLiteDatabase::GetProperties(const IProperty::PropertyLookup& params) {
|
||||
std::optional<IProperty::PropertyEntranceResult> result;
|
||||
std::string query;
|
||||
std::pair<CppSQLite3Statement, CppSQLite3Query> propertiesRes;
|
||||
|
||||
if (params.sortChoice == SORT_TYPE_FEATURED || params.sortChoice == SORT_TYPE_FRIENDS) {
|
||||
query = R"QUERY(
|
||||
FROM properties as p
|
||||
JOIN charinfo as ci
|
||||
ON ci.prop_clone_id = p.clone_id
|
||||
where p.zone_id = ?
|
||||
AND (
|
||||
p.description LIKE ?
|
||||
OR p.name LIKE ?
|
||||
OR ci.name LIKE ?
|
||||
)
|
||||
AND p.privacy_option >= ?
|
||||
AND p.owner_id IN (
|
||||
SELECT fr.requested_player AS player FROM (
|
||||
SELECT CASE
|
||||
WHEN player_id = ? THEN friend_id
|
||||
WHEN friend_id = ? THEN player_id
|
||||
END AS requested_player FROM friends
|
||||
) AS fr
|
||||
JOIN charinfo AS ci ON ci.id = fr.requested_player
|
||||
WHERE fr.requested_player IS NOT NULL AND fr.requested_player != ?
|
||||
) ORDER BY ci.name ASC
|
||||
)QUERY";
|
||||
const auto completeQuery = "SELECT p.* " + query + " LIMIT ? OFFSET ?;";
|
||||
propertiesRes = ExecuteSelect(
|
||||
completeQuery,
|
||||
params.mapId,
|
||||
"%" + params.searchString + "%",
|
||||
"%" + params.searchString + "%",
|
||||
"%" + params.searchString + "%",
|
||||
params.playerSort,
|
||||
params.playerId,
|
||||
params.playerId,
|
||||
params.playerId,
|
||||
params.numResults,
|
||||
params.startIndex
|
||||
);
|
||||
const auto countQuery = "SELECT COUNT(*) as count" + query + ";";
|
||||
auto [_, count] = ExecuteSelect(
|
||||
countQuery,
|
||||
params.mapId,
|
||||
"%" + params.searchString + "%",
|
||||
"%" + params.searchString + "%",
|
||||
"%" + params.searchString + "%",
|
||||
params.playerSort,
|
||||
params.playerId,
|
||||
params.playerId,
|
||||
params.playerId
|
||||
);
|
||||
if (!count.eof()) {
|
||||
result = IProperty::PropertyEntranceResult();
|
||||
result->totalEntriesMatchingQuery = count.getIntField("count");
|
||||
}
|
||||
} else {
|
||||
if (params.sortChoice == SORT_TYPE_REPUTATION) {
|
||||
query = R"QUERY(
|
||||
FROM properties as p
|
||||
JOIN charinfo as ci
|
||||
ON ci.prop_clone_id = p.clone_id
|
||||
where p.zone_id = ?
|
||||
AND (
|
||||
p.description LIKE ?
|
||||
OR p.name LIKE ?
|
||||
OR ci.name LIKE ?
|
||||
)
|
||||
AND p.privacy_option >= ?
|
||||
ORDER BY p.reputation DESC, p.last_updated DESC
|
||||
)QUERY";
|
||||
} else {
|
||||
query = R"QUERY(
|
||||
FROM properties as p
|
||||
JOIN charinfo as ci
|
||||
ON ci.prop_clone_id = p.clone_id
|
||||
where p.zone_id = ?
|
||||
AND (
|
||||
p.description LIKE ?
|
||||
OR p.name LIKE ?
|
||||
OR ci.name LIKE ?
|
||||
)
|
||||
AND p.privacy_option >= ?
|
||||
ORDER BY p.last_updated DESC
|
||||
)QUERY";
|
||||
}
|
||||
const auto completeQuery = "SELECT p.* " + query + " LIMIT ? OFFSET ?;";
|
||||
propertiesRes = ExecuteSelect(
|
||||
completeQuery,
|
||||
params.mapId,
|
||||
"%" + params.searchString + "%",
|
||||
"%" + params.searchString + "%",
|
||||
"%" + params.searchString + "%",
|
||||
params.playerSort,
|
||||
params.numResults,
|
||||
params.startIndex
|
||||
);
|
||||
const auto countQuery = "SELECT COUNT(*) as count" + query + ";";
|
||||
auto [_, count] = ExecuteSelect(
|
||||
countQuery,
|
||||
params.mapId,
|
||||
"%" + params.searchString + "%",
|
||||
"%" + params.searchString + "%",
|
||||
"%" + params.searchString + "%",
|
||||
params.playerSort
|
||||
);
|
||||
if (!count.eof()) {
|
||||
result = IProperty::PropertyEntranceResult();
|
||||
result->totalEntriesMatchingQuery = count.getIntField("count");
|
||||
}
|
||||
}
|
||||
|
||||
auto& [_, properties] = propertiesRes;
|
||||
if (!properties.eof() && !result.has_value()) result = IProperty::PropertyEntranceResult();
|
||||
while (!properties.eof()) {
|
||||
auto& entry = result->entries.emplace_back();
|
||||
entry.id = properties.getInt64Field("id");
|
||||
entry.ownerId = properties.getInt64Field("owner_id");
|
||||
entry.cloneId = properties.getInt64Field("clone_id");
|
||||
entry.name = properties.getStringField("name");
|
||||
entry.description = properties.getStringField("description");
|
||||
entry.privacyOption = properties.getIntField("privacy_option");
|
||||
entry.rejectionReason = properties.getStringField("rejection_reason");
|
||||
entry.lastUpdatedTime = properties.getIntField("last_updated");
|
||||
entry.claimedTime = properties.getIntField("time_claimed");
|
||||
entry.reputation = properties.getIntField("reputation");
|
||||
entry.modApproved = properties.getIntField("mod_approved");
|
||||
entry.performanceCost = properties.getFloatField("performance_cost");
|
||||
properties.nextRow();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<IProperty::Info> SQLiteDatabase::GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) {
|
||||
auto [_, propertyEntry] = ExecuteSelect(
|
||||
"SELECT id, owner_id, clone_id, name, description, privacy_option, rejection_reason, last_updated, time_claimed, reputation, mod_approved, performance_cost "
|
||||
"FROM properties WHERE zone_id = ? AND clone_id = ?;", mapId, cloneId);
|
||||
|
||||
if (propertyEntry.eof()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
IProperty::Info toReturn;
|
||||
toReturn.id = propertyEntry.getInt64Field("id");
|
||||
toReturn.ownerId = propertyEntry.getInt64Field("owner_id");
|
||||
toReturn.cloneId = propertyEntry.getInt64Field("clone_id");
|
||||
toReturn.name = propertyEntry.getStringField("name");
|
||||
toReturn.description = propertyEntry.getStringField("description");
|
||||
toReturn.privacyOption = propertyEntry.getIntField("privacy_option");
|
||||
toReturn.rejectionReason = propertyEntry.getStringField("rejection_reason");
|
||||
toReturn.lastUpdatedTime = propertyEntry.getIntField("last_updated");
|
||||
toReturn.claimedTime = propertyEntry.getIntField("time_claimed");
|
||||
toReturn.reputation = propertyEntry.getIntField("reputation");
|
||||
toReturn.modApproved = propertyEntry.getIntField("mod_approved");
|
||||
toReturn.performanceCost = propertyEntry.getFloatField("performance_cost");
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdatePropertyModerationInfo(const IProperty::Info& info) {
|
||||
ExecuteUpdate("UPDATE properties SET privacy_option = ?, rejection_reason = ?, mod_approved = ? WHERE id = ?;",
|
||||
info.privacyOption,
|
||||
info.rejectionReason,
|
||||
info.modApproved,
|
||||
info.id);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdatePropertyDetails(const IProperty::Info& info) {
|
||||
ExecuteUpdate("UPDATE properties SET name = ?, description = ? WHERE id = ?;", info.name, info.description, info.id);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) {
|
||||
ExecuteUpdate("UPDATE properties SET performance_cost = ? WHERE zone_id = ? AND clone_id = ?;", performanceCost, zoneId.GetMapID(), zoneId.GetCloneID());
|
||||
}
|
||||
|
||||
void SQLiteDatabase::InsertNewProperty(const IProperty::Info& info, const uint32_t templateId, const LWOZONEID& zoneId) {
|
||||
auto insertion = ExecuteInsert(
|
||||
"INSERT INTO properties"
|
||||
" (id, owner_id, template_id, clone_id, name, description, zone_id, rent_amount, rent_due, privacy_option, last_updated, time_claimed, rejection_reason, reputation, performance_cost)"
|
||||
" VALUES (?, ?, ?, ?, ?, ?, ?, 0, 0, 0, CAST(strftime('%s', 'now') as INT), CAST(strftime('%s', 'now') as INT), '', 0, 0.0)",
|
||||
info.id,
|
||||
info.ownerId,
|
||||
templateId,
|
||||
zoneId.GetCloneID(),
|
||||
info.name,
|
||||
info.description,
|
||||
zoneId.GetMapID()
|
||||
);
|
||||
}
|
||||
65
dDatabase/GameDatabase/SQLite/Tables/PropertyContents.cpp
Normal file
65
dDatabase/GameDatabase/SQLite/Tables/PropertyContents.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
std::vector<IPropertyContents::Model> SQLiteDatabase::GetPropertyModels(const LWOOBJID& propertyId) {
|
||||
auto [_, result] = ExecuteSelect(
|
||||
"SELECT id, lot, x, y, z, rx, ry, rz, rw, ugc_id, "
|
||||
"behavior_1, behavior_2, behavior_3, behavior_4, behavior_5 "
|
||||
"FROM properties_contents WHERE property_id = ?;", propertyId);
|
||||
|
||||
std::vector<IPropertyContents::Model> toReturn;
|
||||
while (!result.eof()) {
|
||||
IPropertyContents::Model model;
|
||||
model.id = result.getInt64Field("id");
|
||||
model.lot = static_cast<LOT>(result.getIntField("lot"));
|
||||
model.position.x = result.getFloatField("x");
|
||||
model.position.y = result.getFloatField("y");
|
||||
model.position.z = result.getFloatField("z");
|
||||
model.rotation.w = result.getFloatField("rw");
|
||||
model.rotation.x = result.getFloatField("rx");
|
||||
model.rotation.y = result.getFloatField("ry");
|
||||
model.rotation.z = result.getFloatField("rz");
|
||||
model.ugcId = result.getInt64Field("ugc_id");
|
||||
model.behaviors[0] = result.getIntField("behavior_1");
|
||||
model.behaviors[1] = result.getIntField("behavior_2");
|
||||
model.behaviors[2] = result.getIntField("behavior_3");
|
||||
model.behaviors[3] = result.getIntField("behavior_4");
|
||||
model.behaviors[4] = result.getIntField("behavior_5");
|
||||
|
||||
toReturn.push_back(std::move(model));
|
||||
result.nextRow();
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
void SQLiteDatabase::InsertNewPropertyModel(const LWOOBJID& propertyId, const IPropertyContents::Model& model, const std::string_view name) {
|
||||
try {
|
||||
ExecuteInsert(
|
||||
"INSERT INTO properties_contents"
|
||||
"(id, property_id, ugc_id, lot, x, y, z, rx, ry, rz, rw, model_name, model_description, behavior_1, behavior_2, behavior_3, behavior_4, behavior_5)"
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 18
|
||||
model.id, propertyId, model.ugcId == 0 ? std::nullopt : std::optional(model.ugcId), static_cast<uint32_t>(model.lot),
|
||||
model.position.x, model.position.y, model.position.z, model.rotation.x, model.rotation.y, model.rotation.z, model.rotation.w,
|
||||
name, "", // Model description. TODO implement this.
|
||||
model.behaviors[0], // behavior 1
|
||||
model.behaviors[1], // behavior 2
|
||||
model.behaviors[2], // behavior 3
|
||||
model.behaviors[3], // behavior 4
|
||||
model.behaviors[4] // behavior 5
|
||||
);
|
||||
} catch (std::exception& e) {
|
||||
LOG("Error inserting new property model: %s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array<std::pair<int32_t, std::string>, 5>& behaviors) {
|
||||
ExecuteUpdate(
|
||||
"UPDATE properties_contents SET x = ?, y = ?, z = ?, rx = ?, ry = ?, rz = ?, rw = ?, "
|
||||
"behavior_1 = ?, behavior_2 = ?, behavior_3 = ?, behavior_4 = ?, behavior_5 = ? WHERE id = ?;",
|
||||
position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, rotation.w,
|
||||
behaviors[0].first, behaviors[1].first, behaviors[2].first, behaviors[3].first, behaviors[4].first, propertyId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::RemoveModel(const LWOOBJID& modelId) {
|
||||
ExecuteDelete("DELETE FROM properties_contents WHERE id = ?;", modelId);
|
||||
}
|
||||
23
dDatabase/GameDatabase/SQLite/Tables/Servers.cpp
Normal file
23
dDatabase/GameDatabase/SQLite/Tables/Servers.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
void SQLiteDatabase::SetMasterIp(const std::string_view ip, const uint32_t port) {
|
||||
// We only want our 1 entry anyways, so we can just delete all and reinsert the one we want
|
||||
// since it would be two queries anyways.
|
||||
ExecuteDelete("DELETE FROM servers;");
|
||||
ExecuteInsert("INSERT INTO `servers` (`name`, `ip`, `port`, `state`, `version`) VALUES ('master', ?, ?, 0, 171022)", ip, port);
|
||||
}
|
||||
|
||||
std::optional<IServers::MasterInfo> SQLiteDatabase::GetMasterInfo() {
|
||||
auto [_, result] = ExecuteSelect("SELECT ip, port FROM servers WHERE name='master' LIMIT 1;");
|
||||
|
||||
if (result.eof()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
MasterInfo toReturn;
|
||||
|
||||
toReturn.ip = result.getStringField("ip");
|
||||
toReturn.port = result.getIntField("port");
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
72
dDatabase/GameDatabase/SQLite/Tables/Ugc.cpp
Normal file
72
dDatabase/GameDatabase/SQLite/Tables/Ugc.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
std::vector<IUgc::Model> SQLiteDatabase::GetUgcModels(const LWOOBJID& propertyId) {
|
||||
auto [_, result] = ExecuteSelect(
|
||||
"SELECT lxfml, u.id FROM ugc AS u JOIN properties_contents AS pc ON u.id = pc.ugc_id WHERE lot = 14 AND property_id = ? AND pc.ugc_id IS NOT NULL;",
|
||||
propertyId);
|
||||
|
||||
std::vector<IUgc::Model> toReturn;
|
||||
|
||||
while (!result.eof()) {
|
||||
IUgc::Model model;
|
||||
|
||||
int blobSize{};
|
||||
const auto* blob = result.getBlobField("lxfml", blobSize);
|
||||
model.lxfmlData << std::string(reinterpret_cast<const char*>(blob), blobSize);
|
||||
model.id = result.getInt64Field("id");
|
||||
toReturn.push_back(std::move(model));
|
||||
result.nextRow();
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
std::vector<IUgc::Model> SQLiteDatabase::GetAllUgcModels() {
|
||||
auto [_, result] = ExecuteSelect("SELECT id, lxfml FROM ugc;");
|
||||
|
||||
std::vector<IUgc::Model> models;
|
||||
while (!result.eof()) {
|
||||
IUgc::Model model;
|
||||
model.id = result.getInt64Field("id");
|
||||
|
||||
int blobSize{};
|
||||
const auto* blob = result.getBlobField("lxfml", blobSize);
|
||||
model.lxfmlData << std::string(reinterpret_cast<const char*>(blob), blobSize);
|
||||
models.push_back(std::move(model));
|
||||
result.nextRow();
|
||||
}
|
||||
|
||||
return models;
|
||||
}
|
||||
|
||||
void SQLiteDatabase::RemoveUnreferencedUgcModels() {
|
||||
ExecuteDelete("DELETE FROM ugc WHERE id NOT IN (SELECT ugc_id FROM properties_contents WHERE ugc_id IS NOT NULL);");
|
||||
}
|
||||
|
||||
void SQLiteDatabase::InsertNewUgcModel(
|
||||
std::istringstream& sd0Data, // cant be const sad
|
||||
const uint32_t blueprintId,
|
||||
const uint32_t accountId,
|
||||
const uint32_t characterId) {
|
||||
const std::istream stream(sd0Data.rdbuf());
|
||||
ExecuteInsert(
|
||||
"INSERT INTO `ugc`(`id`, `account_id`, `character_id`, `is_optimized`, `lxfml`, `bake_ao`, `filename`) VALUES (?,?,?,?,?,?,?)",
|
||||
blueprintId,
|
||||
accountId,
|
||||
characterId,
|
||||
0,
|
||||
&stream,
|
||||
false,
|
||||
"weedeater.lxfml"
|
||||
);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::DeleteUgcModelData(const LWOOBJID& modelId) {
|
||||
ExecuteDelete("DELETE FROM ugc WHERE id = ?;", modelId);
|
||||
ExecuteDelete("DELETE FROM properties_contents WHERE ugc_id = ?;", modelId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdateUgcModelData(const LWOOBJID& modelId, std::istringstream& lxfml) {
|
||||
const std::istream stream(lxfml.rdbuf());
|
||||
ExecuteUpdate("UPDATE ugc SET lxfml = ? WHERE id = ?;", &stream, modelId);
|
||||
}
|
||||
9
dDatabase/GameDatabase/SQLite/Tables/UgcModularBuild.cpp
Normal file
9
dDatabase/GameDatabase/SQLite/Tables/UgcModularBuild.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
void SQLiteDatabase::InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) {
|
||||
ExecuteInsert("INSERT INTO ugc_modular_build (ugc_id, ldf_config, character_id) VALUES (?,?,?)", bigId, modules, characterId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::DeleteUgcBuild(const LWOOBJID bigId) {
|
||||
ExecuteDelete("DELETE FROM ugc_modular_build WHERE ugc_id = ?;", bigId);
|
||||
}
|
||||
@@ -8,10 +8,6 @@ void TestSQLDatabase::Destroy(std::string source) {
|
||||
|
||||
}
|
||||
|
||||
sql::PreparedStatement* TestSQLDatabase::CreatePreppedStmt(const std::string& query) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TestSQLDatabase::Commit() {
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ class TestSQLDatabase : public GameDatabase {
|
||||
void Connect() override;
|
||||
void Destroy(std::string source = "") override;
|
||||
|
||||
sql::PreparedStatement* CreatePreppedStmt(const std::string& query) override;
|
||||
void Commit() override;
|
||||
bool GetAutoCommit() override;
|
||||
void SetAutoCommit(bool value) override;
|
||||
@@ -102,6 +101,7 @@ class TestSQLDatabase : public GameDatabase {
|
||||
void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) override {};
|
||||
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) override {};
|
||||
void DeleteUgcBuild(const LWOOBJID bigId) override {};
|
||||
uint32_t GetAccountCount() override { return 0; };
|
||||
};
|
||||
|
||||
#endif //!TESTSQLDATABASE_H
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
|
||||
#include <fstream>
|
||||
|
||||
Migration LoadMigration(std::string path) {
|
||||
Migration LoadMigration(std::string folder, std::string path) {
|
||||
Migration migration{};
|
||||
std::ifstream file(BinaryPathFinder::GetBinaryDir() / "migrations/" / path);
|
||||
std::ifstream file(BinaryPathFinder::GetBinaryDir() / "migrations/" / folder / path);
|
||||
|
||||
if (file.is_open()) {
|
||||
std::string line;
|
||||
@@ -34,10 +34,19 @@ Migration LoadMigration(std::string path) {
|
||||
void MigrationRunner::RunMigrations() {
|
||||
Database::Get()->CreateMigrationHistoryTable();
|
||||
|
||||
// has to be here because when moving the files to the new folder, the migration_history table is not updated so it will run them all again.
|
||||
|
||||
const auto migrationFolder = Database::GetMigrationFolder();
|
||||
if (!Database::Get()->IsMigrationRun("17_migration_for_migrations.sql") && migrationFolder == "mysql") {
|
||||
LOG("Running migration: 17_migration_for_migrations.sql");
|
||||
Database::Get()->ExecuteCustomQuery("UPDATE `migration_history` SET `name` = SUBSTR(`name`, 5) WHERE `name` LIKE \"dlu%\";");
|
||||
Database::Get()->InsertMigration("17_migration_for_migrations.sql");
|
||||
}
|
||||
|
||||
std::string finalSQL = "";
|
||||
bool runSd0Migrations = false;
|
||||
for (const auto& entry : GeneralUtils::GetSqlFileNamesFromFolder((BinaryPathFinder::GetBinaryDir() / "./migrations/dlu/").string())) {
|
||||
auto migration = LoadMigration("dlu/" + entry);
|
||||
for (const auto& entry : GeneralUtils::GetSqlFileNamesFromFolder((BinaryPathFinder::GetBinaryDir() / "./migrations/dlu/" / migrationFolder).string())) {
|
||||
auto migration = LoadMigration("dlu/" + migrationFolder + "/", entry);
|
||||
|
||||
if (migration.data.empty()) {
|
||||
continue;
|
||||
@@ -46,7 +55,7 @@ void MigrationRunner::RunMigrations() {
|
||||
if (Database::Get()->IsMigrationRun(migration.name)) continue;
|
||||
|
||||
LOG("Running migration: %s", migration.name.c_str());
|
||||
if (migration.name == "dlu/5_brick_model_sd0.sql") {
|
||||
if (migration.name == "5_brick_model_sd0.sql") {
|
||||
runSd0Migrations = true;
|
||||
} else {
|
||||
finalSQL.append(migration.data.c_str());
|
||||
@@ -86,10 +95,14 @@ void MigrationRunner::RunSQLiteMigrations() {
|
||||
cdstmt.execQuery().finalize();
|
||||
cdstmt.finalize();
|
||||
|
||||
Database::Get()->CreateMigrationHistoryTable();
|
||||
if (CDClientDatabase::ExecuteQuery("select * from migration_history where name = \"7_migration_for_migrations.sql\";").eof()) {
|
||||
LOG("Running migration: 7_migration_for_migrations.sql");
|
||||
CDClientDatabase::ExecuteQuery("UPDATE `migration_history` SET `name` = SUBSTR(`name`, 10) WHERE `name` LIKE \"cdserver%\";");
|
||||
CDClientDatabase::ExecuteQuery("INSERT INTO migration_history (name) VALUES (\"7_migration_for_migrations.sql\");");
|
||||
}
|
||||
|
||||
for (const auto& entry : GeneralUtils::GetSqlFileNamesFromFolder((BinaryPathFinder::GetBinaryDir() / "migrations/cdserver/").string())) {
|
||||
auto migration = LoadMigration("cdserver/" + entry);
|
||||
auto migration = LoadMigration("cdserver/", entry);
|
||||
|
||||
if (migration.data.empty()) continue;
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>")
|
||||
set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
|
||||
|
||||
add_library(dECS STATIC
|
||||
"Core.h"
|
||||
"Iter.h"
|
||||
"Core.cpp"
|
||||
"System.cpp"
|
||||
)
|
||||
target_include_directories(dECS PUBLIC .)
|
||||
target_link_libraries(dECS PRIVATE dCommon magic_enum::magic_enum)
|
||||
target_compile_options(dECS PRIVATE
|
||||
"$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra>>"
|
||||
"$<${msvc_cxx}:$<BUILD_INTERFACE:/W3>>"
|
||||
)
|
||||
@@ -1,70 +0,0 @@
|
||||
#include <atomic>
|
||||
#include <magic_enum/magic_enum_containers.hpp>
|
||||
#include <eReplicaComponentType.h>
|
||||
#include "Core.h"
|
||||
|
||||
namespace dECS {
|
||||
struct WorldData {
|
||||
using CompSignature = magic_enum::containers::bitset<eReplicaComponentType>;
|
||||
using CompMap = std::unordered_map<LWOOBJID, CompSignature>;
|
||||
using CompStorage = std::unordered_map<eReplicaComponentType, std::unique_ptr<IStorage>>;
|
||||
|
||||
std::atomic<LWOOBJID> nextId = 1;
|
||||
CompMap map;
|
||||
CompStorage data;
|
||||
};
|
||||
|
||||
World::World() : m_World{ std::make_shared<WorldData>() } {};
|
||||
|
||||
Entity World::MakeEntity() {
|
||||
return Entity{ m_World->nextId.fetch_add(1, std::memory_order::relaxed),
|
||||
m_World };
|
||||
}
|
||||
|
||||
void* Entity::AddComponent(const eReplicaComponentType kind, const StorageConstructor storageConstructor) {
|
||||
if (auto w = m_World.lock()) {
|
||||
// Add to kind signature
|
||||
w->map[m_Id].set(kind, true);
|
||||
|
||||
// Get or add storage
|
||||
auto storageIt = w->data.find(kind);
|
||||
if (storageIt == w->data.cend()) {
|
||||
bool inserted = false;
|
||||
std::tie(storageIt, inserted) = w->data.try_emplace(kind, storageConstructor());
|
||||
if (!inserted) throw "storage emplacement failure";
|
||||
}
|
||||
auto& storage = *storageIt->second;
|
||||
|
||||
// Return reference if already mapped, otherwise add component
|
||||
auto compIt = storage.rowMap.find(m_Id);
|
||||
if (compIt == storage.rowMap.cend()) {
|
||||
const auto curSize = storage.rowMap.size();
|
||||
storage.rowMap.emplace(m_Id, curSize);
|
||||
return storage.emplace_back();
|
||||
}
|
||||
const auto row = compIt->second;
|
||||
return storage.at(row);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const void* Entity::GetComponent(const eReplicaComponentType kind) const {
|
||||
if (auto const w = m_World.lock()) {
|
||||
// Check that the entity has this component
|
||||
if (!w->map[m_Id].test(kind)) return nullptr;
|
||||
|
||||
// Get the location where it's stored
|
||||
const auto& storage = *w->data.at(kind);
|
||||
const auto it = storage.rowMap.find(m_Id);
|
||||
if (it == storage.rowMap.cend()) return nullptr;
|
||||
const auto row = it->second;
|
||||
return storage.at(row);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* Entity::GetComponent(const eReplicaComponentType kind) {
|
||||
// Casting away const for this overload is safe, if not at all pretty
|
||||
return const_cast<void*>(std::as_const(*this).GetComponent(kind));
|
||||
}
|
||||
}
|
||||
180
dECS/Core.h
180
dECS/Core.h
@@ -1,180 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
class Component;
|
||||
enum class eReplicaComponentType : uint32_t;
|
||||
using LWOOBJID = int64_t;
|
||||
|
||||
namespace dECS {
|
||||
// template <typename C>
|
||||
// concept IsComponent = std::derived_from<C, Component>;
|
||||
|
||||
// Data structures
|
||||
struct WorldData;
|
||||
class World;
|
||||
|
||||
template <typename... Cs>
|
||||
class System;
|
||||
|
||||
class Entity;
|
||||
struct IStorage;
|
||||
|
||||
template <typename C>
|
||||
class Storage;
|
||||
|
||||
using WorldPtr = std::shared_ptr<WorldData>;
|
||||
using WeakWorldPtr = std::weak_ptr<WorldData>;
|
||||
|
||||
class World {
|
||||
public:
|
||||
World();
|
||||
|
||||
[[nodiscard]]
|
||||
Entity MakeEntity();
|
||||
|
||||
template <typename... Cs>
|
||||
[[nodiscard]]
|
||||
System<Cs...> MakeSystem() {
|
||||
return System<Cs...>{};
|
||||
}
|
||||
|
||||
template <typename... Cs, typename S>
|
||||
[[nodiscard]]
|
||||
System<Cs...> MakeSystem(S&& name) {
|
||||
return System<Cs...>{ std::forward<S>(name) };
|
||||
}
|
||||
|
||||
private:
|
||||
WorldPtr m_World;
|
||||
};
|
||||
|
||||
template <typename... Cs>
|
||||
class System {
|
||||
public:
|
||||
friend System World::MakeSystem<Cs...>();
|
||||
|
||||
template <typename... Ts, typename S>
|
||||
friend System<Ts...> World::MakeSystem(S&&);
|
||||
|
||||
/*template <typename Fn>
|
||||
requires std::is_invocable_r_v<void, Fn(Cs...), ObjId, Cs...>
|
||||
void ForEach(Fn&& f) {
|
||||
for (ObjId i = 0; i < mT.size(); ++i) {
|
||||
auto& c = mT[i];
|
||||
f(i, std::get<Cs>(c)...);
|
||||
}
|
||||
}*/
|
||||
|
||||
template <typename Fn>
|
||||
requires std::is_invocable_r_v<void, Fn(Cs...), Cs...>
|
||||
void ForEach(Fn&& fn) {
|
||||
std::tuple<Cs...> comps; // some sort of iterator that returns a tuple each 'step?'
|
||||
for (size_t i = 0; i < 5; ++i) {
|
||||
fn(std::get<Cs>(comps)...);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
System() = default;
|
||||
|
||||
template <typename S>
|
||||
explicit System(S&& name)
|
||||
: m_name{ std::forward<S>(name) }
|
||||
{}
|
||||
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
class Entity {
|
||||
public:
|
||||
friend Entity World::MakeEntity();
|
||||
|
||||
using StorageConstructor = std::function<std::unique_ptr<IStorage>()>;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr LWOOBJID GetObjectID() const noexcept {
|
||||
return m_Id;
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
void* AddComponent(eReplicaComponentType, StorageConstructor);
|
||||
|
||||
template <typename C>
|
||||
[[maybe_unused]]
|
||||
C* AddComponent() {
|
||||
return static_cast<C*>(AddComponent(C::ComponentType, std::make_unique<Storage<C>>));
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
const void* GetComponent(eReplicaComponentType) const;
|
||||
|
||||
[[nodiscard]]
|
||||
void* GetComponent(eReplicaComponentType);
|
||||
|
||||
template <typename C>
|
||||
[[nodiscard]]
|
||||
const C* GetComponent() const {
|
||||
return static_cast<const C*>(GetComponent(C::ComponentType));
|
||||
}
|
||||
|
||||
template <typename C>
|
||||
[[nodiscard]]
|
||||
C* GetComponent() {
|
||||
return static_cast<C*>(GetComponent(C::ComponentType));
|
||||
}
|
||||
|
||||
private:
|
||||
Entity(const LWOOBJID id, const WeakWorldPtr world)
|
||||
: m_Id{ id }
|
||||
, m_World { world }
|
||||
{}
|
||||
|
||||
LWOOBJID m_Id;
|
||||
|
||||
WeakWorldPtr m_World;
|
||||
};
|
||||
|
||||
struct IStorage {
|
||||
using RowMap = std::unordered_map<LWOOBJID, size_t>;
|
||||
|
||||
virtual ~IStorage() = default;
|
||||
|
||||
[[nodiscard]]
|
||||
virtual void* at(size_t) = 0;
|
||||
|
||||
[[nodiscard]]
|
||||
virtual const void* at(size_t) const = 0;
|
||||
|
||||
[[nodiscard]]
|
||||
virtual void* emplace_back() = 0;
|
||||
|
||||
RowMap rowMap;
|
||||
};
|
||||
|
||||
template <typename C>
|
||||
class Storage : public IStorage {
|
||||
public:
|
||||
[[nodiscard]]
|
||||
void* at(const size_t index) override {
|
||||
return static_cast<void*>(&m_Vec.at(index));
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
const void* at(const size_t index) const override {
|
||||
return static_cast<const void*>(&m_Vec.at(index));
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
void* emplace_back() override {
|
||||
return static_cast<void*>(&m_Vec.emplace_back());
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<C> m_Vec;
|
||||
};
|
||||
}
|
||||
12
dECS/Iter.h
12
dECS/Iter.h
@@ -1,12 +0,0 @@
|
||||
#include "Core.h"
|
||||
|
||||
namespace dECS {
|
||||
class Iter {
|
||||
public:
|
||||
[[nodiscard]]
|
||||
bool Next();
|
||||
|
||||
private:
|
||||
WeakWorldPtr m_World;
|
||||
};
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
#include "PetComponent.h"
|
||||
#include "MovementAIComponent.h"
|
||||
#include "MissionComponent.h"
|
||||
#include "eMissionState.h"
|
||||
|
||||
using Pet = PetComponent;
|
||||
using Mission = MissionComponent;
|
||||
using MovementAI = MovementAIComponent;
|
||||
|
||||
struct Position : NiPoint3 {};
|
||||
struct Treasure {};
|
||||
|
||||
namespace decs {
|
||||
template <typename... Cs>
|
||||
class System {
|
||||
public:
|
||||
template <typename Fn>
|
||||
void each(Fn&& fn) {
|
||||
fn();
|
||||
}
|
||||
};
|
||||
|
||||
class Scene {
|
||||
public:
|
||||
template <typename... Cs>
|
||||
System<Cs...> system() {
|
||||
return System<Cs...>{};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void run() {
|
||||
auto scene = decs::Scene{};
|
||||
|
||||
scene.system<Pet>()
|
||||
.each([](Pet& pet) {
|
||||
|
||||
});
|
||||
|
||||
scene.system<Pet, MovementAI>()
|
||||
.each([](Pet& pet, MovementAI& move) {
|
||||
|
||||
});
|
||||
|
||||
scene.system<Pet, const Mission, const Position>()
|
||||
.each([](Pet& pet, Mission const& mission, Position const& pos) {
|
||||
auto const digUnlocked = mission.GetMissionState(842) == eMissionState::COMPLETE;
|
||||
auto const treasurePos = PetDigServer::GetClosestTreasure(pos);
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
@@ -26,7 +26,6 @@ target_include_directories(dGameBase PUBLIC "." "dEntity"
|
||||
"${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase/CDClientTables"
|
||||
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase"
|
||||
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase/ITables"
|
||||
"${PROJECT_SOURCE_DIR}/thirdparty/mariadb-connector-cpp/include"
|
||||
# dPhysics
|
||||
"${PROJECT_SOURCE_DIR}/thirdparty/recastnavigation/Recast/Include"
|
||||
"${PROJECT_SOURCE_DIR}/thirdparty/recastnavigation/Detour/Include"
|
||||
|
||||
@@ -1499,7 +1499,7 @@ void Entity::RequestActivityExit(Entity* sender, LWOOBJID player, bool canceled)
|
||||
|
||||
CppScripts::Script* const Entity::GetScript() {
|
||||
auto* scriptComponent = GetComponent<ScriptComponent>();
|
||||
auto* script = scriptComponent ? scriptComponent->GetScript() : CppScripts::GetInvalidScript();
|
||||
auto* script = scriptComponent ? scriptComponent->GetScript() : &CppScripts::GetInvalidScript();
|
||||
DluAssert(script != nullptr);
|
||||
return script;
|
||||
}
|
||||
@@ -2175,7 +2175,7 @@ void Entity::SetRespawnRot(const NiQuaternion& rotation) {
|
||||
|
||||
int32_t Entity::GetCollisionGroup() const {
|
||||
for (const auto* component : m_Components | std::views::values) {
|
||||
auto* compToCheck = dynamic_cast<const PhysicsComponent*>(component);
|
||||
auto* compToCheck = dynamic_cast<const PhysicsComponent*>(component);
|
||||
if (compToCheck) {
|
||||
return compToCheck->GetCollisionGroup();
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ set(DGAME_DBEHAVIORS_SOURCES "AirMovementBehavior.cpp"
|
||||
"VerifyBehavior.cpp")
|
||||
|
||||
add_library(dBehaviors OBJECT ${DGAME_DBEHAVIORS_SOURCES})
|
||||
target_link_libraries(dBehaviors PUBLIC dDatabaseCDClient dPhysics magic_enum::magic_enum)
|
||||
target_link_libraries(dBehaviors PUBLIC dDatabaseCDClient dPhysics)
|
||||
target_include_directories(dBehaviors PUBLIC "."
|
||||
"${PROJECT_SOURCE_DIR}/dGame/dGameMessages" # via BehaviorContext.h
|
||||
PRIVATE
|
||||
|
||||
@@ -65,7 +65,6 @@ target_include_directories(dComponents PUBLIC "."
|
||||
"${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase/CDClientTables"
|
||||
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase"
|
||||
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase/ITables"
|
||||
"${PROJECT_SOURCE_DIR}/thirdparty/mariadb-connector-cpp/include"
|
||||
# dPhysics (via dpWorld.h)
|
||||
"${PROJECT_SOURCE_DIR}/thirdparty/recastnavigation/Recast/Include"
|
||||
"${PROJECT_SOURCE_DIR}/thirdparty/recastnavigation/Detour/Include"
|
||||
@@ -79,4 +78,4 @@ target_include_directories(dComponents PUBLIC "."
|
||||
)
|
||||
target_precompile_headers(dComponents REUSE_FROM dGameBase)
|
||||
|
||||
target_link_libraries(dComponents PUBLIC magic_enum::magic_enum INTERFACE dBehaviors)
|
||||
target_link_libraries(dComponents INTERFACE dBehaviors)
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
#include "Component.h"
|
||||
|
||||
|
||||
Component::Component(Entity* parent) {
|
||||
m_Parent = parent;
|
||||
}
|
||||
|
||||
Component::~Component() {
|
||||
|
||||
}
|
||||
|
||||
Entity* Component::GetParent() const {
|
||||
return m_Parent;
|
||||
}
|
||||
|
||||
void Component::Update(float deltaTime) {
|
||||
|
||||
}
|
||||
|
||||
@@ -2,10 +2,6 @@
|
||||
|
||||
#include "tinyxml2.h"
|
||||
|
||||
namespace RakNet {
|
||||
class BitStream;
|
||||
};
|
||||
|
||||
class Entity;
|
||||
|
||||
/**
|
||||
@@ -13,15 +9,14 @@ class Entity;
|
||||
*/
|
||||
class Component {
|
||||
public:
|
||||
Component() = default;
|
||||
Component(Entity* parent) : m_Parent{ parent } {}
|
||||
virtual ~Component() = default;
|
||||
Component(Entity* parent);
|
||||
virtual ~Component();
|
||||
|
||||
/**
|
||||
* Gets the owner of this component
|
||||
* @return the owner of this component
|
||||
*/
|
||||
Entity* GetParent() const { return m_Parent; }
|
||||
Entity* GetParent() const;
|
||||
|
||||
/**
|
||||
* Updates the component in the game loop
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "eStateChangeType.h"
|
||||
#include "eUseItemResponse.h"
|
||||
#include "Mail.h"
|
||||
#include "ProximityMonitorComponent.h"
|
||||
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
#include "CDInventoryComponentTable.h"
|
||||
@@ -829,6 +830,30 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) {
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (item->GetLot() == 8092) {
|
||||
// Trying to equip a car
|
||||
const auto proximityObjects = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::PROXIMITY_MONITOR);
|
||||
|
||||
// look for car instancers and check if we are in its setup range
|
||||
for (auto* const entity : proximityObjects) {
|
||||
if (!entity) continue;
|
||||
|
||||
auto* proximityMonitorComponent = entity->GetComponent<ProximityMonitorComponent>();
|
||||
if (!proximityMonitorComponent) continue;
|
||||
|
||||
if (proximityMonitorComponent->IsInProximity("Interaction_Distance", m_Parent->GetObjectID())) {
|
||||
// in the range of a car instancer
|
||||
entity->OnUse(m_Parent);
|
||||
GameMessages::UseItemOnClient itemMsg;
|
||||
itemMsg.target = entity->GetObjectID();
|
||||
itemMsg.itemLOT = item->GetLot();
|
||||
itemMsg.itemToUse = item->GetId();
|
||||
itemMsg.playerId = m_Parent->GetObjectID();
|
||||
itemMsg.Send(m_Parent->GetSystemAddress());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -913,11 +938,8 @@ void InventoryComponent::EquipScripts(Item* equippedItem) {
|
||||
if (scriptComponentID > -1) {
|
||||
CDScriptComponentTable* scriptCompTable = CDClientManager::GetTable<CDScriptComponentTable>();
|
||||
CDScriptComponent scriptCompData = scriptCompTable->GetByID(scriptComponentID);
|
||||
auto* itemScript = CppScripts::GetScript(m_Parent, scriptCompData.script_name);
|
||||
if (!itemScript) {
|
||||
LOG("null script?");
|
||||
}
|
||||
itemScript->OnFactionTriggerItemEquipped(m_Parent, equippedItem->GetId());
|
||||
auto& itemScript = CppScripts::GetScript(m_Parent, scriptCompData.script_name);
|
||||
itemScript.OnFactionTriggerItemEquipped(m_Parent, equippedItem->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -928,11 +950,8 @@ void InventoryComponent::UnequipScripts(Item* unequippedItem) {
|
||||
if (scriptComponentID > -1) {
|
||||
CDScriptComponentTable* scriptCompTable = CDClientManager::GetTable<CDScriptComponentTable>();
|
||||
CDScriptComponent scriptCompData = scriptCompTable->GetByID(scriptComponentID);
|
||||
auto* itemScript = CppScripts::GetScript(m_Parent, scriptCompData.script_name);
|
||||
if (!itemScript) {
|
||||
LOG("null script?");
|
||||
}
|
||||
itemScript->OnFactionTriggerItemUnequipped(m_Parent, unequippedItem->GetId());
|
||||
auto& itemScript = CppScripts::GetScript(m_Parent, scriptCompData.script_name);
|
||||
itemScript.OnFactionTriggerItemUnequipped(m_Parent, unequippedItem->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,5 +48,5 @@ CppScripts::Script* const ScriptComponent::GetScript() {
|
||||
void ScriptComponent::SetScript(const std::string& scriptName) {
|
||||
// Scripts are managed by the CppScripts class and are effecitvely singletons
|
||||
// and they may also be used by other script components so DON'T delete them.
|
||||
m_Script = CppScripts::GetScript(m_Parent, scriptName);
|
||||
m_Script = &CppScripts::GetScript(m_Parent, scriptName);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ set(DGAME_DGAMEMESSAGES_SOURCES
|
||||
|
||||
add_library(dGameMessages OBJECT ${DGAME_DGAMEMESSAGES_SOURCES})
|
||||
target_link_libraries(dGameMessages
|
||||
PUBLIC magic_enum::magic_enum dDatabase
|
||||
PUBLIC dDatabase
|
||||
INTERFACE dGameBase # TradingManager
|
||||
)
|
||||
target_include_directories(dGameMessages PUBLIC "."
|
||||
|
||||
@@ -6342,36 +6342,57 @@ void GameMessages::SendUpdateInventoryUi(LWOOBJID objectId, const SystemAddress&
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::DisplayTooltip::Send() const {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
namespace GameMessages {
|
||||
void GameMsg::Send(const SystemAddress& sysAddr) const {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(target);
|
||||
bitStream.Write(msgId);
|
||||
bitStream.Write(target); // Who this message will be sent to on the (a) client
|
||||
bitStream.Write(msgId); // the ID of this message
|
||||
|
||||
bitStream.Write(doOrDie);
|
||||
bitStream.Write(noRepeat);
|
||||
bitStream.Write(noRevive);
|
||||
bitStream.Write(isPropertyTooltip);
|
||||
bitStream.Write(show);
|
||||
bitStream.Write(translate);
|
||||
bitStream.Write(time);
|
||||
bitStream.Write<int32_t>(id.size());
|
||||
bitStream.Write(id);
|
||||
Serialize(bitStream); // write the message data
|
||||
|
||||
std::string toWrite;
|
||||
for (const auto* item : localizeParams) {
|
||||
toWrite += item->GetString() + "\n";
|
||||
// Send to everyone if someone sent unassigned system address, or to one specific client.
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) {
|
||||
SEND_PACKET_BROADCAST;
|
||||
} else {
|
||||
SEND_PACKET;
|
||||
}
|
||||
}
|
||||
if (!toWrite.empty()) toWrite.pop_back();
|
||||
bitStream.Write<int32_t>(toWrite.size());
|
||||
bitStream.Write(GeneralUtils::ASCIIToUTF16(toWrite));
|
||||
if (!toWrite.empty()) bitStream.Write<uint16_t>(0x00); // Null Terminator
|
||||
|
||||
bitStream.Write<int32_t>(imageName.size());
|
||||
bitStream.Write(imageName);
|
||||
bitStream.Write<int32_t>(text.size());
|
||||
bitStream.Write(text);
|
||||
void DisplayTooltip::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(doOrDie);
|
||||
bitStream.Write(noRepeat);
|
||||
bitStream.Write(noRevive);
|
||||
bitStream.Write(isPropertyTooltip);
|
||||
bitStream.Write(show);
|
||||
bitStream.Write(translate);
|
||||
bitStream.Write(time);
|
||||
bitStream.Write<int32_t>(id.size());
|
||||
bitStream.Write(id);
|
||||
|
||||
SEND_PACKET;
|
||||
std::string toWrite;
|
||||
for (const auto* item : localizeParams) {
|
||||
toWrite += item->GetString() + "\n";
|
||||
}
|
||||
if (!toWrite.empty()) toWrite.pop_back();
|
||||
bitStream.Write<int32_t>(toWrite.size());
|
||||
bitStream.Write(GeneralUtils::ASCIIToUTF16(toWrite));
|
||||
if (!toWrite.empty()) bitStream.Write<uint16_t>(0x00); // Null Terminator
|
||||
|
||||
bitStream.Write<int32_t>(imageName.size());
|
||||
bitStream.Write(imageName);
|
||||
bitStream.Write<int32_t>(text.size());
|
||||
bitStream.Write(text);
|
||||
}
|
||||
|
||||
void UseItemOnClient::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(itemLOT);
|
||||
bitStream.Write(itemToUse);
|
||||
bitStream.Write(itemType);
|
||||
bitStream.Write(playerId);
|
||||
bitStream.Write(targetPosition.x);
|
||||
bitStream.Write(targetPosition.y);
|
||||
bitStream.Write(targetPosition.z);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,10 +52,10 @@ namespace GameMessages {
|
||||
struct GameMsg {
|
||||
GameMsg(MessageType::Game gmId) : msgId{ gmId } {}
|
||||
virtual ~GameMsg() = default;
|
||||
virtual void Send() const {}
|
||||
void Send(const SystemAddress& sysAddr) const;
|
||||
virtual void Serialize(RakNet::BitStream& bitStream) const {}
|
||||
MessageType::Game msgId;
|
||||
LWOOBJID target{ LWOOBJID_EMPTY };
|
||||
SystemAddress sysAddr{ UNASSIGNED_SYSTEM_ADDRESS };
|
||||
};
|
||||
|
||||
class PropertyDataMessage;
|
||||
@@ -705,7 +705,17 @@ namespace GameMessages {
|
||||
std::vector<LDFBaseData*> localizeParams{};
|
||||
std::u16string imageName{};
|
||||
std::u16string text{};
|
||||
void Send() const override;
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
};
|
||||
|
||||
struct UseItemOnClient : public GameMsg {
|
||||
UseItemOnClient() : GameMsg(MessageType::Game::USE_ITEM_ON_CLIENT) {}
|
||||
LWOOBJID playerId{};
|
||||
LWOOBJID itemToUse{};
|
||||
uint32_t itemType{};
|
||||
LOT itemLOT{};
|
||||
NiPoint3 targetPosition{};
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ target_include_directories(dInventory PUBLIC "."
|
||||
"${PROJECT_SOURCE_DIR}/dGame/dMission" # via MissionComponent.h
|
||||
"${PROJECT_SOURCE_DIR}/dZoneManager" # via Item.cpp
|
||||
)
|
||||
target_link_libraries(dInventory PUBLIC magic_enum::magic_enum)
|
||||
target_precompile_headers(dInventory REUSE_FROM dGameBase)
|
||||
# Workaround for compiler bug where the optimized code could result in a memcpy of 0 bytes, even though that isnt possible.
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97185
|
||||
|
||||
@@ -287,8 +287,8 @@ void SlashCommandHandler::Startup() {
|
||||
RegisterCommand(SpawnPhysicsVertsCommand);
|
||||
|
||||
Command TeleportCommand{
|
||||
.help = "Teleports you",
|
||||
.info = "Teleports you. If no Y is given, you are teleported to the height of the terrain or physics object at (x, z)",
|
||||
.help = "Teleports you to a position or a player to another player.",
|
||||
.info = "Teleports you. If no Y is given, you are teleported to the height of the terrain or physics object at (x, z). Any of the coordinates can use the syntax of an exact position (10.0), or a relative position (~+10.0). A ~ means use the current value of that axis as the base value. Addition or subtraction is supported (~+10) (~-10). If source player and target player are players that exist in the world, then the source player will be teleported to target player.",
|
||||
.aliases = { "teleport", "tele", "tp" },
|
||||
.handle = DEVGMCommands::Teleport,
|
||||
.requiredLevel = eGameMasterLevel::JUNIOR_DEVELOPER
|
||||
@@ -1056,6 +1056,15 @@ void SlashCommandHandler::Startup() {
|
||||
};
|
||||
RegisterCommand(InstanceInfoCommand);
|
||||
|
||||
Command ServerUptimeCommand{
|
||||
.help = "Display the time the current world server has been active",
|
||||
.info = "Display the time the current world server has been active",
|
||||
.aliases = { "uptime" },
|
||||
.handle = GMZeroCommands::ServerUptime,
|
||||
.requiredLevel = eGameMasterLevel::DEVELOPER
|
||||
};
|
||||
RegisterCommand(ServerUptimeCommand);
|
||||
|
||||
//Commands that are handled by the client
|
||||
|
||||
Command faqCommand{
|
||||
|
||||
@@ -555,25 +555,45 @@ namespace DEVGMCommands {
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<float> ParseRelativeAxis(const float sourcePos, const std::string& toParse) {
|
||||
if (toParse.empty()) return std::nullopt;
|
||||
|
||||
// relative offset from current position
|
||||
if (toParse[0] == '~') {
|
||||
if (toParse.size() == 1) return sourcePos;
|
||||
|
||||
if (toParse.size() < 3 || !(toParse[1] != '+' || toParse[1] != '-')) return std::nullopt;
|
||||
|
||||
const auto offset = GeneralUtils::TryParse<float>(toParse.substr(2));
|
||||
if (!offset.has_value()) return std::nullopt;
|
||||
|
||||
bool isNegative = toParse[1] == '-';
|
||||
return isNegative ? sourcePos - offset.value() : sourcePos + offset.value();
|
||||
}
|
||||
|
||||
return GeneralUtils::TryParse<float>(toParse);
|
||||
}
|
||||
|
||||
void Teleport(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
||||
const auto splitArgs = GeneralUtils::SplitString(args, ' ');
|
||||
|
||||
const auto& sourcePos = entity->GetPosition();
|
||||
NiPoint3 pos{};
|
||||
auto* sourceEntity = entity;
|
||||
if (splitArgs.size() == 3) {
|
||||
|
||||
const auto x = GeneralUtils::TryParse<float>(splitArgs.at(0));
|
||||
const auto x = ParseRelativeAxis(sourcePos.x, splitArgs[0]);
|
||||
if (!x) {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Invalid x.");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto y = GeneralUtils::TryParse<float>(splitArgs.at(1));
|
||||
const auto y = ParseRelativeAxis(sourcePos.y, splitArgs[1]);
|
||||
if (!y) {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Invalid y.");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto z = GeneralUtils::TryParse<float>(splitArgs.at(2));
|
||||
const auto z = ParseRelativeAxis(sourcePos.z, splitArgs[2]);
|
||||
if (!z) {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Invalid z.");
|
||||
return;
|
||||
@@ -584,32 +604,39 @@ namespace DEVGMCommands {
|
||||
pos.SetZ(z.value());
|
||||
|
||||
LOG("Teleporting objectID: %llu to %f, %f, %f", entity->GetObjectID(), pos.x, pos.y, pos.z);
|
||||
GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr);
|
||||
} else if (splitArgs.size() == 2) {
|
||||
const auto x = ParseRelativeAxis(sourcePos.x, splitArgs[0]);
|
||||
auto* sourcePlayer = PlayerManager::GetPlayer(splitArgs[0]);
|
||||
if (!x && !sourcePlayer) {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Invalid x or source player not found.");
|
||||
return;
|
||||
}
|
||||
if (sourcePlayer) sourceEntity = sourcePlayer;
|
||||
|
||||
const auto x = GeneralUtils::TryParse<float>(splitArgs.at(0));
|
||||
if (!x) {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Invalid x.");
|
||||
const auto z = ParseRelativeAxis(sourcePos.z, splitArgs[1]);
|
||||
const auto* const targetPlayer = PlayerManager::GetPlayer(splitArgs[1]);
|
||||
if (!z && !targetPlayer) {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Invalid z or target player not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto z = GeneralUtils::TryParse<float>(splitArgs.at(1));
|
||||
if (!z) {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Invalid z.");
|
||||
if (x && z) {
|
||||
pos.SetX(x.value());
|
||||
pos.SetY(0.0f);
|
||||
pos.SetZ(z.value());
|
||||
} else if (sourcePlayer && targetPlayer) {
|
||||
pos = targetPlayer->GetPosition();
|
||||
} else {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Unable to teleport.");
|
||||
return;
|
||||
}
|
||||
|
||||
pos.SetX(x.value());
|
||||
pos.SetY(0.0f);
|
||||
pos.SetZ(z.value());
|
||||
|
||||
LOG("Teleporting objectID: %llu to X: %f, Z: %f", entity->GetObjectID(), pos.x, pos.z);
|
||||
GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr);
|
||||
} else {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Correct usage: /teleport <x> (<y>) <z> - if no Y given, will teleport to the height of the terrain (or any physics object).");
|
||||
}
|
||||
GameMessages::SendTeleport(sourceEntity->GetObjectID(), pos, sourceEntity->GetRotation(), sourceEntity->GetSystemAddress());
|
||||
|
||||
auto* possessorComponent = entity->GetComponent<PossessorComponent>();
|
||||
auto* possessorComponent = sourceEntity->GetComponent<PossessorComponent>();
|
||||
if (possessorComponent) {
|
||||
auto* possassableEntity = Game::entityManager->GetEntity(possessorComponent->GetPossessable());
|
||||
|
||||
|
||||
@@ -225,8 +225,13 @@ namespace GMZeroCommands {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Map: " + (GeneralUtils::to_u16string(zoneId.GetMapID())) + u"\nClone: " + (GeneralUtils::to_u16string(zoneId.GetCloneID())) + u"\nInstance: " + (GeneralUtils::to_u16string(zoneId.GetInstanceID())));
|
||||
}
|
||||
|
||||
// Display the server uptime
|
||||
void ServerUptime(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
||||
const auto time = Game::server->GetUptime();
|
||||
const auto seconds = std::chrono::duration_cast<std::chrono::seconds>(time).count();
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Server has been up for " + GeneralUtils::to_u16string(seconds) + u" s");
|
||||
}
|
||||
|
||||
//For client side commands
|
||||
void ClientHandled(Entity* entity, const SystemAddress& sysAddr, const std::string args) {}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace GMZeroCommands {
|
||||
void LeaveZone(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
||||
void Resurrect(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
||||
void InstanceInfo(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
||||
void ServerUptime(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
||||
void ClientHandled(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
||||
}
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
MigrationRunner::RunMigrations();
|
||||
const auto resServerPath = BinaryPathFinder::GetBinaryDir() / "resServer";
|
||||
std::filesystem::create_directories(resServerPath);
|
||||
const bool cdServerExists = std::filesystem::exists(resServerPath / "CDServer.sqlite");
|
||||
const bool oldCDServerExists = std::filesystem::exists(Game::assetManager->GetResPath() / "CDServer.sqlite");
|
||||
const bool fdbExists = std::filesystem::exists(Game::assetManager->GetResPath() / "cdclient.fdb");
|
||||
@@ -176,12 +177,16 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
// Run migrations should any need to be run.
|
||||
MigrationRunner::RunSQLiteMigrations();
|
||||
MigrationRunner::RunSQLiteMigrations();
|
||||
|
||||
//If the first command line argument is -a or --account then make the user
|
||||
//input a username and password, with the password being hidden.
|
||||
if (argc > 1 &&
|
||||
(strcmp(argv[1], "-a") == 0 || strcmp(argv[1], "--account") == 0)) {
|
||||
bool createAccount = Database::Get()->GetAccountCount() == 0 && Game::config->GetValue("skip_account_creation") != "1";
|
||||
if (createAccount) {
|
||||
LOG("No accounts exist in the database. Please create an account.");
|
||||
}
|
||||
if ((argc > 1 &&
|
||||
(strcmp(argv[1], "-a") == 0 || strcmp(argv[1], "--account") == 0)) || createAccount) {
|
||||
std::string username;
|
||||
std::string password;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ void StartChatServer() {
|
||||
//macOS doesn't need sudo to run on ports < 1024
|
||||
auto result = system(((BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str());
|
||||
#elif _WIN32
|
||||
auto result = system(("start " + (BinaryPathFinder::GetBinaryDir() / "ChatServer.exe").string()).c_str());
|
||||
auto result = system(("start /B " + (BinaryPathFinder::GetBinaryDir() / "ChatServer.exe").string()).c_str());
|
||||
#else
|
||||
if (std::atoi(Game::config->GetValue("use_sudo_chat").c_str())) {
|
||||
auto result = system(("sudo " + (BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str());
|
||||
@@ -31,7 +31,7 @@ void StartAuthServer() {
|
||||
#ifdef __APPLE__
|
||||
auto result = system(((BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str());
|
||||
#elif _WIN32
|
||||
auto result = system(("start " + (BinaryPathFinder::GetBinaryDir() / "AuthServer.exe").string()).c_str());
|
||||
auto result = system(("start /B " + (BinaryPathFinder::GetBinaryDir() / "AuthServer.exe").string()).c_str());
|
||||
#else
|
||||
if (std::atoi(Game::config->GetValue("use_sudo_auth").c_str())) {
|
||||
auto result = system(("sudo " + (BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str());
|
||||
@@ -43,7 +43,7 @@ void StartAuthServer() {
|
||||
|
||||
void StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID) {
|
||||
#ifdef _WIN32
|
||||
std::string cmd = "start " + (BinaryPathFinder::GetBinaryDir() / "WorldServer.exe").string() + " -zone ";
|
||||
std::string cmd = "start /B " + (BinaryPathFinder::GetBinaryDir() / "WorldServer.exe").string() + " -zone ";
|
||||
#else
|
||||
std::string cmd;
|
||||
if (std::atoi(Game::config->GetValue("use_sudo_world").c_str())) {
|
||||
|
||||
@@ -82,14 +82,14 @@ void AuthPackets::SendHandshake(dServer* server, const SystemAddress& sysAddr, c
|
||||
if (serverType == ServerType::Auth) bitStream.Write(ServiceId::Auth);
|
||||
else if (serverType == ServerType::World) bitStream.Write(ServiceId::World);
|
||||
else bitStream.Write(ServiceId::General);
|
||||
bitStream.Write<uint64_t>(215523470896);
|
||||
bitStream.Write<uint64_t>(219818241584);
|
||||
|
||||
server->Send(bitStream, sysAddr, false);
|
||||
}
|
||||
|
||||
std::string CleanReceivedString(const std::string& str) {
|
||||
std::string toReturn = str;
|
||||
const auto removed = std::ranges::find_if(toReturn, [](char c) { return isprint(c) == 0 && isblank(c) == 0; });
|
||||
const auto removed = std::ranges::find_if(toReturn, [](unsigned char c) { return isprint(c) == 0 && isblank(c) == 0; });
|
||||
toReturn.erase(removed, toReturn.end());
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#define _VARIADIC_MAX 10
|
||||
#include "dCommonVars.h"
|
||||
#include "dNetCommon.h"
|
||||
#include <magic_enum/magic_enum.hpp>
|
||||
#include "magic_enum.hpp"
|
||||
|
||||
enum class ServerType : uint32_t;
|
||||
enum class eLoginResponse : uint8_t;
|
||||
|
||||
@@ -8,7 +8,7 @@ set(DNET_SOURCES "AuthPackets.cpp"
|
||||
"ZoneInstanceManager.cpp")
|
||||
|
||||
add_library(dNet STATIC ${DNET_SOURCES})
|
||||
target_link_libraries(dNet PUBLIC magic_enum::magic_enum PRIVATE bcrypt MD5)
|
||||
target_link_libraries(dNet PRIVATE bcrypt MD5)
|
||||
target_include_directories(dNet PRIVATE
|
||||
"${PROJECT_SOURCE_DIR}/dCommon"
|
||||
"${PROJECT_SOURCE_DIR}/dCommon/dEnums"
|
||||
@@ -19,7 +19,6 @@ target_include_directories(dNet PRIVATE
|
||||
"${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase/CDClientTables"
|
||||
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase"
|
||||
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase/ITables"
|
||||
"${PROJECT_SOURCE_DIR}/thirdparty/mariadb-connector-cpp/include"
|
||||
|
||||
"${PROJECT_SOURCE_DIR}/dGame" # UserManager.h
|
||||
"${PROJECT_SOURCE_DIR}/dGame/dComponents"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <csignal>
|
||||
#include "RakPeerInterface.h"
|
||||
#include "ReplicaManager.h"
|
||||
@@ -80,6 +81,11 @@ public:
|
||||
|
||||
const ServerType GetServerType() const { return mServerType; }
|
||||
|
||||
[[nodiscard]]
|
||||
std::chrono::steady_clock::duration GetUptime() const {
|
||||
return std::chrono::steady_clock::now() - mStartTime;
|
||||
}
|
||||
|
||||
private:
|
||||
bool Startup();
|
||||
void Shutdown();
|
||||
@@ -114,4 +120,5 @@ protected:
|
||||
SystemAddress mMasterSystemAddress;
|
||||
std::string mMasterIP;
|
||||
int mMasterPort;
|
||||
std::chrono::steady_clock::time_point mStartTime = std::chrono::steady_clock::now();
|
||||
};
|
||||
|
||||
@@ -3,104 +3,106 @@
|
||||
#include "ScriptedActivityComponent.h"
|
||||
#include "GameMessages.h"
|
||||
#include "LeaderboardManager.h"
|
||||
#include "dServer.h"
|
||||
#include "eMissionTaskType.h"
|
||||
#include "eMissionState.h"
|
||||
#include "MissionComponent.h"
|
||||
#include <ctime>
|
||||
#include <chrono>
|
||||
|
||||
void NpcAgCourseStarter::OnStartup(Entity* self) {
|
||||
|
||||
}
|
||||
void NpcAgCourseStarter::OnStartup(Entity* self) {}
|
||||
|
||||
void NpcAgCourseStarter::OnUse(Entity* self, Entity* user) {
|
||||
auto* scriptedActivityComponent = self->GetComponent<ScriptedActivityComponent>();
|
||||
auto* const scriptedActivityComponent = self->GetComponent<ScriptedActivityComponent>();
|
||||
if (!scriptedActivityComponent) return;
|
||||
|
||||
if (scriptedActivityComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
const auto selfId = self->GetObjectID();
|
||||
const auto userId = user->GetObjectID();
|
||||
const auto& userSysAddr = user->GetSystemAddress();
|
||||
|
||||
if (scriptedActivityComponent->GetActivityPlayerData(user->GetObjectID()) != nullptr) {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"exit", 0, 0, LWOOBJID_EMPTY, "", user->GetSystemAddress());
|
||||
if (scriptedActivityComponent->GetActivityPlayerData(userId) != nullptr) {
|
||||
GameMessages::SendNotifyClientObject(selfId, u"exit", 0, 0, LWOOBJID_EMPTY, "", userSysAddr);
|
||||
} else {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"start", 0, 0, LWOOBJID_EMPTY, "", user->GetSystemAddress());
|
||||
GameMessages::SendNotifyClientObject(selfId, u"start", 0, 0, LWOOBJID_EMPTY, "", userSysAddr);
|
||||
}
|
||||
}
|
||||
|
||||
void NpcAgCourseStarter::OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) {
|
||||
auto* scriptedActivityComponent = self->GetComponent<ScriptedActivityComponent>();
|
||||
auto* const scriptedActivityComponent = self->GetComponent<ScriptedActivityComponent>();
|
||||
if (!scriptedActivityComponent) return;
|
||||
|
||||
if (scriptedActivityComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
const auto selfId = self->GetObjectID();
|
||||
const auto senderId = sender->GetObjectID();
|
||||
const auto& senderSysAddr = sender->GetSystemAddress();
|
||||
|
||||
if (identifier == u"player_dialog_cancel_course" && button == 1) {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"stop_timer", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress());
|
||||
GameMessages::SendNotifyClientObject(selfId, u"stop_timer", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr);
|
||||
GameMessages::SendNotifyClientObject(selfId, u"cancel_timer", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr);
|
||||
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"cancel_timer", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress());
|
||||
|
||||
scriptedActivityComponent->RemoveActivityPlayerData(sender->GetObjectID());
|
||||
scriptedActivityComponent->RemoveActivityPlayerData(senderId);
|
||||
|
||||
Game::entityManager->SerializeEntity(self);
|
||||
} else if (identifier == u"player_dialog_start_course" && button == 1) {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"start_timer", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress());
|
||||
|
||||
GameMessages::SendActivityStart(self->GetObjectID(), sender->GetSystemAddress());
|
||||
|
||||
auto* data = scriptedActivityComponent->AddActivityPlayerData(sender->GetObjectID());
|
||||
GameMessages::SendNotifyClientObject(selfId, u"start_timer", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr);
|
||||
GameMessages::SendActivityStart(selfId, senderSysAddr);
|
||||
|
||||
auto* const data = scriptedActivityComponent->AddActivityPlayerData(senderId);
|
||||
if (data->values[1] != 0) return;
|
||||
|
||||
time_t startTime = std::time(0) + 4; // Offset for starting timer
|
||||
|
||||
data->values[1] = *reinterpret_cast<float*>(&startTime);
|
||||
const auto raceStartTime = Game::server->GetUptime() + std::chrono::seconds(4); // Offset for starting timer
|
||||
const auto fRaceStartTime = std::chrono::duration<float, std::ratio<1>>(raceStartTime).count();
|
||||
data->values[1] = fRaceStartTime;
|
||||
|
||||
Game::entityManager->SerializeEntity(self);
|
||||
} else if (identifier == u"FootRaceCancel") {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"stop_timer", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress());
|
||||
GameMessages::SendNotifyClientObject(selfId, u"stop_timer", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr);
|
||||
|
||||
if (scriptedActivityComponent->GetActivityPlayerData(sender->GetObjectID()) != nullptr) {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"exit", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress());
|
||||
if (scriptedActivityComponent->GetActivityPlayerData(senderId) != nullptr) {
|
||||
GameMessages::SendNotifyClientObject(selfId, u"exit", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr);
|
||||
} else {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"start", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress());
|
||||
GameMessages::SendNotifyClientObject(selfId, u"start", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr);
|
||||
}
|
||||
|
||||
scriptedActivityComponent->RemoveActivityPlayerData(sender->GetObjectID());
|
||||
scriptedActivityComponent->RemoveActivityPlayerData(senderId);
|
||||
}
|
||||
}
|
||||
|
||||
void NpcAgCourseStarter::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) {
|
||||
auto* scriptedActivityComponent = self->GetComponent<ScriptedActivityComponent>();
|
||||
if (scriptedActivityComponent == nullptr) return;
|
||||
auto* const scriptedActivityComponent = self->GetComponent<ScriptedActivityComponent>();
|
||||
if (!scriptedActivityComponent) return;
|
||||
|
||||
auto* data = scriptedActivityComponent->GetActivityPlayerData(sender->GetObjectID());
|
||||
if (data == nullptr) return;
|
||||
const auto selfId = self->GetObjectID();
|
||||
const auto senderId = sender->GetObjectID();
|
||||
const auto& senderSysAddr = sender->GetSystemAddress();
|
||||
|
||||
auto* const data = scriptedActivityComponent->GetActivityPlayerData(senderId);
|
||||
if (!data) return;
|
||||
|
||||
if (args == "course_cancel") {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"cancel_timer", 0, 0,
|
||||
LWOOBJID_EMPTY, "", sender->GetSystemAddress());
|
||||
scriptedActivityComponent->RemoveActivityPlayerData(sender->GetObjectID());
|
||||
GameMessages::SendNotifyClientObject(selfId, u"cancel_timer", 0, 0,
|
||||
LWOOBJID_EMPTY, "", senderSysAddr);
|
||||
scriptedActivityComponent->RemoveActivityPlayerData(senderId);
|
||||
} else if (args == "course_finish") {
|
||||
time_t endTime = std::time(0);
|
||||
time_t finish = (endTime - *reinterpret_cast<time_t*>(&data->values[1]));
|
||||
const auto raceEndTime = Game::server->GetUptime();
|
||||
const auto fRaceEndTime = std::chrono::duration<float, std::ratio<1>>(raceEndTime).count();
|
||||
const auto raceTimeElapsed = fRaceEndTime - data->values[1];
|
||||
data->values[2] = raceTimeElapsed;
|
||||
|
||||
data->values[2] = *reinterpret_cast<float*>(&finish);
|
||||
|
||||
auto* missionComponent = sender->GetComponent<MissionComponent>();
|
||||
auto* const missionComponent = sender->GetComponent<MissionComponent>();
|
||||
if (missionComponent != nullptr) {
|
||||
missionComponent->ForceProgressTaskType(1884, 1, 1, false);
|
||||
missionComponent->Progress(eMissionTaskType::PERFORM_ACTIVITY, -finish, self->GetObjectID(),
|
||||
missionComponent->Progress(eMissionTaskType::PERFORM_ACTIVITY, -raceTimeElapsed, selfId,
|
||||
"performact_time");
|
||||
}
|
||||
|
||||
Game::entityManager->SerializeEntity(self);
|
||||
LeaderboardManager::SaveScore(sender->GetObjectID(), scriptedActivityComponent->GetActivityID(), static_cast<float>(finish));
|
||||
LeaderboardManager::SaveScore(senderId, scriptedActivityComponent->GetActivityID(), raceTimeElapsed);
|
||||
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"ToggleLeaderBoard",
|
||||
scriptedActivityComponent->GetActivityID(), 0, sender->GetObjectID(),
|
||||
"", sender->GetSystemAddress());
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"stop_timer", 1, finish, LWOOBJID_EMPTY, "",
|
||||
sender->GetSystemAddress());
|
||||
GameMessages::SendNotifyClientObject(selfId, u"ToggleLeaderBoard",
|
||||
scriptedActivityComponent->GetActivityID(), 0, senderId,
|
||||
"", senderSysAddr);
|
||||
GameMessages::SendNotifyClientObject(selfId, u"stop_timer", 1, raceTimeElapsed, LWOOBJID_EMPTY, "",
|
||||
senderSysAddr);
|
||||
|
||||
scriptedActivityComponent->RemoveActivityPlayerData(sender->GetObjectID());
|
||||
scriptedActivityComponent->RemoveActivityPlayerData(senderId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,6 +329,7 @@
|
||||
#include "WblRobotCitizen.h"
|
||||
#include "EnemyClearThreat.h"
|
||||
#include "AgSpiderBossMessage.h"
|
||||
#include "GfRaceInstancer.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
@@ -338,358 +339,359 @@ namespace {
|
||||
// This is in the translation unit instead of the header to prevent weird linker errors
|
||||
InvalidScript InvalidToReturn;
|
||||
std::map<std::string, CppScripts::Script*> g_Scripts;
|
||||
std::map<std::string, std::function<CppScripts::Script* ()>> scriptLoader = {
|
||||
std::map<std::string, std::function<std::unique_ptr<CppScripts::Script> ()>> scriptLoader = {
|
||||
|
||||
//VE / AG
|
||||
{ "scripts\\ai\\AG\\L_AG_SHIP_PLAYER_DEATH_TRIGGER.lua", []() { return new AgShipPlayerDeathTrigger(); } },
|
||||
{"scripts\\ai\\NP\\L_NPC_NP_SPACEMAN_BOB.lua", []() { return new NpcNpSpacemanBob(); } },
|
||||
{"scripts\\ai\\AG\\L_AG_SPACE_STUFF.lua", []() { return new AgSpaceStuff();} },
|
||||
{"scripts\\ai\\AG\\L_AG_SHIP_SHAKE.lua", []() { return new AgShipShake();}},
|
||||
{"scripts\\ai\\AG\\L_AG_SHIP_PLAYER_SHOCK_SERVER.lua", []() { return new AgShipPlayerShockServer();} },
|
||||
{"scripts\\ai\\AG\\L_AG_IMAG_SMASHABLE.lua", []() { return new AgImagSmashable();} },
|
||||
{"scripts\\02_server\\Map\\General\\L_STORY_BOX_INTERACT_SERVER.lua", []() { return new StoryBoxInteractServer();} },
|
||||
{"scripts\\02_server\\Map\\General\\L_BINOCULARS.lua", []() { return new Binoculars();} },
|
||||
{"scripts\\ai\\WILD\\L_ALL_CRATE_CHICKEN.lua", []() { return new AllCrateChicken();} },
|
||||
{ "scripts\\ai\\AG\\L_AG_SHIP_PLAYER_DEATH_TRIGGER.lua", []() { return std::make_unique<AgShipPlayerDeathTrigger>(); } },
|
||||
{"scripts\\ai\\NP\\L_NPC_NP_SPACEMAN_BOB.lua", []() { return std::make_unique<NpcNpSpacemanBob>(); } },
|
||||
{"scripts\\ai\\AG\\L_AG_SPACE_STUFF.lua", []() { return std::make_unique<AgSpaceStuff>();} },
|
||||
{"scripts\\ai\\AG\\L_AG_SHIP_SHAKE.lua", []() { return std::make_unique<AgShipShake>();}},
|
||||
{"scripts\\ai\\AG\\L_AG_SHIP_PLAYER_SHOCK_SERVER.lua", []() { return std::make_unique<AgShipPlayerShockServer>();} },
|
||||
{"scripts\\ai\\AG\\L_AG_IMAG_SMASHABLE.lua", []() { return std::make_unique<AgImagSmashable>();} },
|
||||
{"scripts\\02_server\\Map\\General\\L_STORY_BOX_INTERACT_SERVER.lua", []() { return std::make_unique<StoryBoxInteractServer>();} },
|
||||
{"scripts\\02_server\\Map\\General\\L_BINOCULARS.lua", []() { return std::make_unique<Binoculars>();} },
|
||||
{"scripts\\ai\\WILD\\L_ALL_CRATE_CHICKEN.lua", []() { return std::make_unique<AllCrateChicken>();} },
|
||||
// Broken? (below)
|
||||
{"scripts\\ai\\NS\\WH\\L_ROCKHYDRANT_SMASHABLE.lua", []() { return new RockHydrantSmashable();} },
|
||||
{"scripts\\02_server\\Map\\SS\\L_SS_MODULAR_BUILD_SERVER.lua", []() { return new SsModularBuildServer();} },
|
||||
{"scripts\\02_server\\Map\\Property\\AG_Small\\L_ZONE_AG_PROPERTY.lua", []() { return new ZoneAgProperty();} },
|
||||
{"scripts\\ai\\NS\\WH\\L_ROCKHYDRANT_SMASHABLE.lua", []() { return std::make_unique<RockHydrantSmashable>();} },
|
||||
{"scripts\\02_server\\Map\\SS\\L_SS_MODULAR_BUILD_SERVER.lua", []() { return std::make_unique<SsModularBuildServer>();} },
|
||||
{"scripts\\02_server\\Map\\Property\\AG_Small\\L_ZONE_AG_PROPERTY.lua", []() { return std::make_unique<ZoneAgProperty>();} },
|
||||
// this is done in Entity.cpp, not needed for our implementation (below)
|
||||
{"scripts\\02_server\\Map\\General\\L_POI_MISSION.lua", []() { return new InvalidScript();} },
|
||||
{"scripts\\02_server\\Map\\General\\L_TOUCH_MISSION_UPDATE_SERVER.lua", []() { return new TouchMissionUpdateServer();} },
|
||||
{"scripts\\ai\\AG\\L_ACT_SHARK_PLAYER_DEATH_TRIGGER.lua", []() { return new ActSharkPlayerDeathTrigger();} },
|
||||
{"scripts\\02_server\\Enemy\\General\\L_BASE_ENEMY_MECH.lua", []() { return new BaseEnemyMech();} },
|
||||
{"scripts\\zone\\AG\\L_ZONE_AG_SURVIVAL.lua", []() { return new ZoneAgSurvival();} },
|
||||
{"scripts\\02_server\\Objects\\L_BUFF_STATION_SERVER.lua", []() { return new AgSurvivalBuffStation();} },
|
||||
{"scripts\\ai\\AG\\L_AG_BUS_DOOR.lua", []() { return new AgBusDoor();} },
|
||||
{"scripts\\02_server\\Equipment\\L_MAESTROM_EXTRACTICATOR_SERVER.lua", []() { return new MaestromExtracticatorServer();} },
|
||||
{"scripts\\02_server\\Map\\AG\\L_AG_CAGED_BRICKS_SERVER.lua", []() { return new AgCagedBricksServer();} },
|
||||
{"scripts\\02_server\\Map\\AG\\L_NPC_WISP_SERVER.lua", []() { return new NpcWispServer();} },
|
||||
{"scripts\\02_server\\Map\\AG\\L_NPC_EPSILON_SERVER.lua", []() { return new NpcEpsilonServer();} },
|
||||
{"scripts\\ai\\AG\\L_AG_TURRET.lua", []() {return new AgTurret();}},
|
||||
{"scripts\\ai\\AG\\L_AG_TURRET_FOR_SHIP.lua", []() { return new AgTurret();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_AG_LASER_SENSOR_SERVER.lua", []() {return new AgLaserSensorServer();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_AG_MONUMENT_LASER_SERVER.lua", []() {return new AgMonumentLaserServer();}},
|
||||
{"scripts\\ai\\AG\\L_AG_FANS.lua", []() {return new AgFans();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_AG_MONUMENT_BIRDS.lua", []() {return new AgMonumentBirds();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_REMOVE_RENTAL_GEAR.lua", []() {return new RemoveRentalGear();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_NPC_NJ_ASSISTANT_SERVER.lua", []() {return new NpcNjAssistantServer();}},
|
||||
{"scripts\\ai\\AG\\L_AG_SALUTING_NPCS.lua", []() {return new AgSalutingNpcs();}},
|
||||
{"scripts\\ai\\AG\\L_AG_JET_EFFECT_SERVER.lua", []() {return new AgJetEffectServer();}},
|
||||
{"scripts\\02_server\\Enemy\\AG\\L_BOSS_SPIDER_QUEEN_ENEMY_SERVER.lua", []() {return new BossSpiderQueenEnemyServer();}},
|
||||
{"scripts\\02_server\\Map\\Property\\AG_Small\\L_ENEMY_SPIDER_SPAWNER.lua", []() {return new EnemySpiderSpawner();}},
|
||||
{"scripts/02_server/Map/Property/AG_Small/L_ENEMY_SPIDER_SPAWNER.lua", []() {return new EnemySpiderSpawner();}},
|
||||
{"scripts\\ai\\AG\\L_AG_QB_Elevator.lua", []() {return new AgQbElevator();}},
|
||||
{"scripts\\ai\\PROPERTY\\AG\\L_AG_PROP_GUARD.lua", []() {return new AgPropGuard();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_AG_BUGSPRAYER.lua", []() {return new AgBugsprayer();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_NPC_AG_COURSE_STARTER.lua", []() {return new NpcAgCourseStarter();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L__AG_MONUMENT_RACE_GOAL.lua", []() {return new AgMonumentRaceGoal();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L__AG_MONUMENT_RACE_CANCEL.lua", []() {return new AgMonumentRaceCancel();}},
|
||||
{"scripts\\02_server\\Map\\AG_Spider_Queen\\L_ZONE_AG_SPIDER_QUEEN.lua", []() {return new ZoneAgSpiderQueen();}},
|
||||
{"scripts\\02_server\\Map\\AG_Spider_Queen\\L_SPIDER_BOSS_TREASURE_CHEST_SERVER.lua", []() {return new SpiderBossTreasureChestServer();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_NPC_COWBOY_SERVER.lua", []() {return new NpcCowboyServer();}},
|
||||
{"scripts\\02_server\\Map\\Property\\AG_Med\\L_ZONE_AG_MED_PROPERTY.lua", []() {return new ZoneAgMedProperty();}},
|
||||
{"scripts\\ai\\AG\\L_AG_STROMBIE_PROPERTY.lua", []() {return new AgStromlingProperty();}},
|
||||
{"scripts\\ai\\AG\\L_AG_DARKLING_MECH.lua", []() {return new BaseEnemyMech();}},
|
||||
{"scripts\\ai\\AG\\L_AG_DARK_SPIDERLING.lua", []() {return new AgDarkSpiderling();}},
|
||||
{"scripts\\ai\\PROPERTY\\L_PROP_GUARDS.lua", []() {return new AgPropguards();}},
|
||||
{"scripts\\ai\\PROPERTY\\L_PROPERTY_FX_DAMAGE.lua", []() {return new PropertyFXDamage();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_NPC_PIRATE_SERVER.lua", []() {return new NpcPirateServer();}},
|
||||
{"scripts\\ai\\AG\\L_AG_PICNIC_BLANKET.lua", []() {return new AgPicnicBlanket();}},
|
||||
{"scripts\\02_server\\Map\\Property\\L_PROPERTY_BANK_INTERACT_SERVER.lua", []() {return new PropertyBankInteract();}},
|
||||
{"scripts\\02_server\\Enemy\\VE\\L_VE_MECH.lua", []() {return new VeMech();}},
|
||||
{"scripts\\02_server\\Map\\VE\\L_MISSION_CONSOLE_SERVER.lua", []() {return new VeMissionConsole();}},
|
||||
{"scripts\\02_server\\Map\\VE\\L_EPSILON_SERVER.lua", []() {return new VeEpsilonServer();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_POI_MISSION.lua", []() { return std::make_unique<InvalidScript>();} },
|
||||
{"scripts\\02_server\\Map\\General\\L_TOUCH_MISSION_UPDATE_SERVER.lua", []() { return std::make_unique<TouchMissionUpdateServer>();} },
|
||||
{"scripts\\ai\\AG\\L_ACT_SHARK_PLAYER_DEATH_TRIGGER.lua", []() { return std::make_unique<ActSharkPlayerDeathTrigger>();} },
|
||||
{"scripts\\02_server\\Enemy\\General\\L_BASE_ENEMY_MECH.lua", []() { return std::make_unique<BaseEnemyMech>();} },
|
||||
{"scripts\\zone\\AG\\L_ZONE_AG_SURVIVAL.lua", []() { return std::make_unique<ZoneAgSurvival>();} },
|
||||
{"scripts\\02_server\\Objects\\L_BUFF_STATION_SERVER.lua", []() { return std::make_unique<AgSurvivalBuffStation>();} },
|
||||
{"scripts\\ai\\AG\\L_AG_BUS_DOOR.lua", []() { return std::make_unique<AgBusDoor>();} },
|
||||
{"scripts\\02_server\\Equipment\\L_MAESTROM_EXTRACTICATOR_SERVER.lua", []() { return std::make_unique<MaestromExtracticatorServer>();} },
|
||||
{"scripts\\02_server\\Map\\AG\\L_AG_CAGED_BRICKS_SERVER.lua", []() { return std::make_unique<AgCagedBricksServer>();} },
|
||||
{"scripts\\02_server\\Map\\AG\\L_NPC_WISP_SERVER.lua", []() { return std::make_unique<NpcWispServer>();} },
|
||||
{"scripts\\02_server\\Map\\AG\\L_NPC_EPSILON_SERVER.lua", []() { return std::make_unique<NpcEpsilonServer>();} },
|
||||
{"scripts\\ai\\AG\\L_AG_TURRET.lua", []() {return std::make_unique<AgTurret>();}},
|
||||
{"scripts\\ai\\AG\\L_AG_TURRET_FOR_SHIP.lua", []() { return std::make_unique<AgTurret>();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_AG_LASER_SENSOR_SERVER.lua", []() {return std::make_unique<AgLaserSensorServer>();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_AG_MONUMENT_LASER_SERVER.lua", []() {return std::make_unique<AgMonumentLaserServer>();}},
|
||||
{"scripts\\ai\\AG\\L_AG_FANS.lua", []() {return std::make_unique<AgFans>();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_AG_MONUMENT_BIRDS.lua", []() {return std::make_unique<AgMonumentBirds>();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_REMOVE_RENTAL_GEAR.lua", []() {return std::make_unique<RemoveRentalGear>();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_NPC_NJ_ASSISTANT_SERVER.lua", []() {return std::make_unique<NpcNjAssistantServer>();}},
|
||||
{"scripts\\ai\\AG\\L_AG_SALUTING_NPCS.lua", []() {return std::make_unique<AgSalutingNpcs>();}},
|
||||
{"scripts\\ai\\AG\\L_AG_JET_EFFECT_SERVER.lua", []() {return std::make_unique<AgJetEffectServer>();}},
|
||||
{"scripts\\02_server\\Enemy\\AG\\L_BOSS_SPIDER_QUEEN_ENEMY_SERVER.lua", []() {return std::make_unique<BossSpiderQueenEnemyServer>();}},
|
||||
{"scripts\\02_server\\Map\\Property\\AG_Small\\L_ENEMY_SPIDER_SPAWNER.lua", []() {return std::make_unique<EnemySpiderSpawner>();}},
|
||||
{"scripts/02_server/Map/Property/AG_Small/L_ENEMY_SPIDER_SPAWNER.lua", []() {return std::make_unique<EnemySpiderSpawner>();}},
|
||||
{"scripts\\ai\\AG\\L_AG_QB_Elevator.lua", []() {return std::make_unique<AgQbElevator>();}},
|
||||
{"scripts\\ai\\PROPERTY\\AG\\L_AG_PROP_GUARD.lua", []() {return std::make_unique<AgPropGuard>();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_AG_BUGSPRAYER.lua", []() {return std::make_unique<AgBugsprayer>();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_NPC_AG_COURSE_STARTER.lua", []() {return std::make_unique<NpcAgCourseStarter>();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L__AG_MONUMENT_RACE_GOAL.lua", []() {return std::make_unique<AgMonumentRaceGoal>();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L__AG_MONUMENT_RACE_CANCEL.lua", []() {return std::make_unique<AgMonumentRaceCancel>();}},
|
||||
{"scripts\\02_server\\Map\\AG_Spider_Queen\\L_ZONE_AG_SPIDER_QUEEN.lua", []() {return std::make_unique<ZoneAgSpiderQueen>();}},
|
||||
{"scripts\\02_server\\Map\\AG_Spider_Queen\\L_SPIDER_BOSS_TREASURE_CHEST_SERVER.lua", []() {return std::make_unique<SpiderBossTreasureChestServer>();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_NPC_COWBOY_SERVER.lua", []() {return std::make_unique<NpcCowboyServer>();}},
|
||||
{"scripts\\02_server\\Map\\Property\\AG_Med\\L_ZONE_AG_MED_PROPERTY.lua", []() {return std::make_unique<ZoneAgMedProperty>();}},
|
||||
{"scripts\\ai\\AG\\L_AG_STROMBIE_PROPERTY.lua", []() {return std::make_unique<AgStromlingProperty>();}},
|
||||
{"scripts\\ai\\AG\\L_AG_DARKLING_MECH.lua", []() {return std::make_unique<BaseEnemyMech>();}},
|
||||
{"scripts\\ai\\AG\\L_AG_DARK_SPIDERLING.lua", []() {return std::make_unique<AgDarkSpiderling>();}},
|
||||
{"scripts\\ai\\PROPERTY\\L_PROP_GUARDS.lua", []() {return std::make_unique<AgPropguards>();}},
|
||||
{"scripts\\ai\\PROPERTY\\L_PROPERTY_FX_DAMAGE.lua", []() {return std::make_unique<PropertyFXDamage>();}},
|
||||
{"scripts\\02_server\\Map\\AG\\L_NPC_PIRATE_SERVER.lua", []() {return std::make_unique<NpcPirateServer>();}},
|
||||
{"scripts\\ai\\AG\\L_AG_PICNIC_BLANKET.lua", []() {return std::make_unique<AgPicnicBlanket>();}},
|
||||
{"scripts\\02_server\\Map\\Property\\L_PROPERTY_BANK_INTERACT_SERVER.lua", []() {return std::make_unique<PropertyBankInteract>();}},
|
||||
{"scripts\\02_server\\Enemy\\VE\\L_VE_MECH.lua", []() {return std::make_unique<VeMech>();}},
|
||||
{"scripts\\02_server\\Map\\VE\\L_MISSION_CONSOLE_SERVER.lua", []() {return std::make_unique<VeMissionConsole>();}},
|
||||
{"scripts\\02_server\\Map\\VE\\L_EPSILON_SERVER.lua", []() {return std::make_unique<VeEpsilonServer>();}},
|
||||
|
||||
//NS
|
||||
{"scripts\\ai\\NS\\L_NS_MODULAR_BUILD.lua", []() {return new NsModularBuild();}},
|
||||
{"scripts\\ai\\NS\\L_NS_GET_FACTION_MISSION_SERVER.lua", []() {return new NsGetFactionMissionServer();}},
|
||||
{"scripts\\ai\\NS\\L_NS_QB_IMAGINATION_STATUE.lua", []() {return new NsQbImaginationStatue();}},
|
||||
{"scripts\\02_server\\Map\\NS\\CONCERT_CHOICEBUILD_MANAGER_SERVER.lua", []() {return new NsConcertChoiceBuildManager();}},
|
||||
{"scripts\\ai\\NS\\L_NS_CONCERT_CHOICEBUILD.lua", []() {return new NsConcertChoiceBuild();}},
|
||||
{"scripts\\ai\\NS\\L_NS_CONCERT_QUICKBUILD.lua", []() {return new NsConcertQuickBuild();}},
|
||||
{"scripts\\ai\\AG\\L_AG_STAGE_PLATFORMS.lua", []() {return new AgStagePlatforms();}},
|
||||
{"scripts\\ai\\NS\\L_NS_CONCERT_INSTRUMENT_QB.lua", []() {return new NsConcertInstrument();}},
|
||||
{"scripts\\ai\\NS\\L_NS_JONNY_FLAG_MISSION_SERVER.lua", []() {return new NsJohnnyMissionServer();}},
|
||||
{"scripts\\02_server\\Objects\\L_STINKY_FISH_TARGET.lua", []() {return new StinkyFishTarget();}},
|
||||
{"scripts\\zone\\PROPERTY\\NS\\L_ZONE_NS_PROPERTY.lua", []() {return new ZoneNsProperty();}},
|
||||
{"scripts\\02_server\\Map\\Property\\NS_Med\\L_ZONE_NS_MED_PROPERTY.lua", []() {return new ZoneNsMedProperty();}},
|
||||
{"scripts\\02_server\\Map\\NS\\L_NS_TOKEN_CONSOLE_SERVER.lua", []() {return new NsTokenConsoleServer();}},
|
||||
{"scripts\\02_server\\Map\\NS\\L_NS_LUP_TELEPORT.lua", []() {return new NsLupTeleport();}},
|
||||
{"scripts\\02_server\\Map\\NS\\Waves\\L_ZONE_NS_WAVES.lua", []() {return new ZoneNsWaves();}},
|
||||
{"scripts\\02_server\\Enemy\\Waves\\L_WAVES_BOSS_HAMMERLING_ENEMY_SERVER.lua", []() {return new WaveBossHammerling();}},
|
||||
{"scripts\\02_server\\Enemy\\Waves\\L_WAVES_BOSS_APE_ENEMY_SERVER.lua", []() {return new WaveBossApe();}},
|
||||
{"scripts\\02_server\\Enemy\\Waves\\L_WAVES_BOSS_DARK_SPIDERLING_ENEMY_SERVER.lua", []() {return new WaveBossSpiderling();}},
|
||||
{"scripts\\02_server\\Enemy\\Waves\\L_WAVES_BOSS_HORESEMEN_ENEMY_SERVER.lua", []() {return new WaveBossHorsemen();}},
|
||||
{"scripts\\02_server\\Minigame\\General\\L_MINIGAME_TREASURE_CHEST_SERVER.lua", []() {return new MinigameTreasureChestServer();}},
|
||||
{"scripts\\02_server\\Map\\NS\\L_NS_LEGO_CLUB_DOOR.lua", []() {return new NsLegoClubDoor();}},
|
||||
{"scripts/ai/NS/L_CL_RING.lua", []() {return new ClRing();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_AMBIENTS.lua", []() {return new WildAmbients();}},
|
||||
{"scripts\\ai\\NS\\NS_PP_01\\L_NS_PP_01_TELEPORT.lua", []() {return new PropertyDeathPlane();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_QB_SPAWNER.lua", []() {return new QbSpawner();}},
|
||||
{"scripts\\ai\\AG\\L_AG_QB_Wall.lua", []() {return new AgQbWall();}},
|
||||
{"scripts\\ai\\NS\\L_NS_MODULAR_BUILD.lua", []() {return std::make_unique<NsModularBuild>();}},
|
||||
{"scripts\\ai\\NS\\L_NS_GET_FACTION_MISSION_SERVER.lua", []() {return std::make_unique<NsGetFactionMissionServer>();}},
|
||||
{"scripts\\ai\\NS\\L_NS_QB_IMAGINATION_STATUE.lua", []() {return std::make_unique<NsQbImaginationStatue>();}},
|
||||
{"scripts\\02_server\\Map\\NS\\CONCERT_CHOICEBUILD_MANAGER_SERVER.lua", []() {return std::make_unique<NsConcertChoiceBuildManager>();}},
|
||||
{"scripts\\ai\\NS\\L_NS_CONCERT_CHOICEBUILD.lua", []() {return std::make_unique<NsConcertChoiceBuild>();}},
|
||||
{"scripts\\ai\\NS\\L_NS_CONCERT_QUICKBUILD.lua", []() {return std::make_unique<NsConcertQuickBuild>();}},
|
||||
{"scripts\\ai\\AG\\L_AG_STAGE_PLATFORMS.lua", []() {return std::make_unique<AgStagePlatforms>();}},
|
||||
{"scripts\\ai\\NS\\L_NS_CONCERT_INSTRUMENT_QB.lua", []() {return std::make_unique<NsConcertInstrument>();}},
|
||||
{"scripts\\ai\\NS\\L_NS_JONNY_FLAG_MISSION_SERVER.lua", []() {return std::make_unique<NsJohnnyMissionServer>();}},
|
||||
{"scripts\\02_server\\Objects\\L_STINKY_FISH_TARGET.lua", []() {return std::make_unique<StinkyFishTarget>();}},
|
||||
{"scripts\\zone\\PROPERTY\\NS\\L_ZONE_NS_PROPERTY.lua", []() {return std::make_unique<ZoneNsProperty>();}},
|
||||
{"scripts\\02_server\\Map\\Property\\NS_Med\\L_ZONE_NS_MED_PROPERTY.lua", []() {return std::make_unique<ZoneNsMedProperty>();}},
|
||||
{"scripts\\02_server\\Map\\NS\\L_NS_TOKEN_CONSOLE_SERVER.lua", []() {return std::make_unique<NsTokenConsoleServer>();}},
|
||||
{"scripts\\02_server\\Map\\NS\\L_NS_LUP_TELEPORT.lua", []() {return std::make_unique<NsLupTeleport>();}},
|
||||
{"scripts\\02_server\\Map\\NS\\Waves\\L_ZONE_NS_WAVES.lua", []() {return std::make_unique<ZoneNsWaves>();}},
|
||||
{"scripts\\02_server\\Enemy\\Waves\\L_WAVES_BOSS_HAMMERLING_ENEMY_SERVER.lua", []() {return std::make_unique<WaveBossHammerling>();}},
|
||||
{"scripts\\02_server\\Enemy\\Waves\\L_WAVES_BOSS_APE_ENEMY_SERVER.lua", []() {return std::make_unique<WaveBossApe>();}},
|
||||
{"scripts\\02_server\\Enemy\\Waves\\L_WAVES_BOSS_DARK_SPIDERLING_ENEMY_SERVER.lua", []() {return std::make_unique<WaveBossSpiderling>();}},
|
||||
{"scripts\\02_server\\Enemy\\Waves\\L_WAVES_BOSS_HORESEMEN_ENEMY_SERVER.lua", []() {return std::make_unique<WaveBossHorsemen>();}},
|
||||
{"scripts\\02_server\\Minigame\\General\\L_MINIGAME_TREASURE_CHEST_SERVER.lua", []() {return std::make_unique<MinigameTreasureChestServer>();}},
|
||||
{"scripts\\02_server\\Map\\NS\\L_NS_LEGO_CLUB_DOOR.lua", []() {return std::make_unique<NsLegoClubDoor>();}},
|
||||
{"scripts/ai/NS/L_CL_RING.lua", []() {return std::make_unique<ClRing>();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_AMBIENTS.lua", []() {return std::make_unique<WildAmbients>();}},
|
||||
{"scripts\\ai\\NS\\NS_PP_01\\L_NS_PP_01_TELEPORT.lua", []() {return std::make_unique<PropertyDeathPlane>();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_QB_SPAWNER.lua", []() {return std::make_unique<QbSpawner>();}},
|
||||
{"scripts\\ai\\AG\\L_AG_QB_Wall.lua", []() {return std::make_unique<AgQbWall>();}},
|
||||
|
||||
//GF
|
||||
{"scripts\\02_server\\Map\\GF\\L_GF_TORCH.lua", []() {return new GfTikiTorch();}},
|
||||
{"scripts\\ai\\GF\\L_SPECIAL_FIREPIT.lua", []() {return new GfCampfire();}},
|
||||
{"scripts\\ai\\GF\\L_GF_ORGAN.lua", []() {return new GfOrgan();}},
|
||||
{"scripts\\ai\\GF\\L_GF_BANANA.lua", []() {return new GfBanana();}},
|
||||
{"scripts\\ai\\GF\\L_GF_BANANA_CLUSTER.lua", []() {return new GfBananaCluster();}},
|
||||
{"scripts/ai/GF/L_GF_JAILKEEP_MISSION.lua", []() {return new GfJailkeepMission();}},
|
||||
{"scripts\\ai\\GF\\L_TRIGGER_AMBUSH.lua", []() {return new TriggerAmbush();}},
|
||||
{"scripts\\02_server\\Map\\GF\\L_GF_CAPTAINS_CANNON.lua", []() {return new GfCaptainsCannon();}},
|
||||
{"scripts\\02_server\\Map\\GF\\L_MAST_TELEPORT.lua", []() {return new MastTeleport();}},
|
||||
{"scripts\\ai\\GF\\L_GF_JAIL_WALLS.lua", []() {return new GfJailWalls();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_QB_ENEMY_STUNNER.lua", []() {return new QbEnemyStunner();}},
|
||||
{"scripts\\02_server\\Map\\GF\\L_GF_TORCH.lua", []() {return std::make_unique<GfTikiTorch>();}},
|
||||
{"scripts\\ai\\GF\\L_SPECIAL_FIREPIT.lua", []() {return std::make_unique<GfCampfire>();}},
|
||||
{"scripts\\ai\\GF\\L_GF_ORGAN.lua", []() {return std::make_unique<GfOrgan>();}},
|
||||
{"scripts\\ai\\GF\\L_GF_BANANA.lua", []() {return std::make_unique<GfBanana>();}},
|
||||
{"scripts\\ai\\GF\\L_GF_BANANA_CLUSTER.lua", []() {return std::make_unique<GfBananaCluster>();}},
|
||||
{"scripts/ai/GF/L_GF_JAILKEEP_MISSION.lua", []() {return std::make_unique<GfJailkeepMission>();}},
|
||||
{"scripts\\ai\\GF\\L_TRIGGER_AMBUSH.lua", []() {return std::make_unique<TriggerAmbush>();}},
|
||||
{"scripts\\02_server\\Map\\GF\\L_GF_CAPTAINS_CANNON.lua", []() {return std::make_unique<GfCaptainsCannon>();}},
|
||||
{"scripts\\02_server\\Map\\GF\\L_MAST_TELEPORT.lua", []() {return std::make_unique<MastTeleport>();}},
|
||||
{"scripts\\ai\\GF\\L_GF_JAIL_WALLS.lua", []() {return std::make_unique<GfJailWalls>();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_QB_ENEMY_STUNNER.lua", []() {return std::make_unique<QbEnemyStunner>();}},
|
||||
//Technically also used once in AG (below)
|
||||
{"scripts\\ai\\GF\\L_GF_PET_DIG_BUILD.lua", []() {return new PetDigBuild();}},
|
||||
{"scripts\\02_server\\Map\\GF\\L_SPAWN_LION_SERVER.lua", []() {return new SpawnLionServer();}},
|
||||
{"scripts\\02_server\\Enemy\\General\\L_BASE_ENEMY_APE.lua", []() {return new BaseEnemyApe();}},
|
||||
{"scripts\\02_server\\Enemy\\General\\L_GF_APE_SMASHING_QB.lua", []() {return new GfApeSmashingQB();}},
|
||||
{"scripts\\zone\\PROPERTY\\GF\\L_ZONE_GF_PROPERTY.lua", []() {return new ZoneGfProperty();}},
|
||||
{"scripts\\ai\\GF\\L_GF_ARCHWAY.lua", []() {return new GfArchway();}},
|
||||
{"scripts\\ai\\GF\\L_GF_MAELSTROM_GEYSER.lua", []() {return new GfMaelstromGeyser();}},
|
||||
{"scripts\\ai\\GF\\L_PIRATE_REP.lua", []() {return new PirateRep();}},
|
||||
{"scripts\\ai\\GF\\L_GF_PARROT_CRASH.lua", []() {return new GfParrotCrash();}},
|
||||
{"scripts\\ai\\GF\\L_GF_PET_DIG_BUILD.lua", []() {return std::make_unique<PetDigBuild>();}},
|
||||
{"scripts\\02_server\\Map\\GF\\L_SPAWN_LION_SERVER.lua", []() {return std::make_unique<SpawnLionServer>();}},
|
||||
{"scripts\\02_server\\Enemy\\General\\L_BASE_ENEMY_APE.lua", []() {return std::make_unique<BaseEnemyApe>();}},
|
||||
{"scripts\\02_server\\Enemy\\General\\L_GF_APE_SMASHING_QB.lua", []() {return std::make_unique<GfApeSmashingQB>();}},
|
||||
{"scripts\\zone\\PROPERTY\\GF\\L_ZONE_GF_PROPERTY.lua", []() {return std::make_unique<ZoneGfProperty>();}},
|
||||
{"scripts\\ai\\GF\\L_GF_ARCHWAY.lua", []() {return std::make_unique<GfArchway>();}},
|
||||
{"scripts\\ai\\GF\\L_GF_MAELSTROM_GEYSER.lua", []() {return std::make_unique<GfMaelstromGeyser>();}},
|
||||
{"scripts\\ai\\GF\\L_PIRATE_REP.lua", []() {return std::make_unique<PirateRep>();}},
|
||||
{"scripts\\ai\\GF\\L_GF_PARROT_CRASH.lua", []() {return std::make_unique<GfParrotCrash>();}},
|
||||
|
||||
//SG
|
||||
{"scripts\\ai\\MINIGAME\\SG_GF\\SERVER\\SG_CANNON.lua", []() {return new SGCannon();}},
|
||||
{"scripts\\ai\\MINIGAME\\SG_GF\\L_ZONE_SG_SERVER.lua", []() {return new ZoneSGServer();}},
|
||||
{"scripts\\ai\\MINIGAME\\SG_GF\\SERVER\\SG_CANNON.lua", []() {return std::make_unique<SGCannon>();}},
|
||||
{"scripts\\ai\\MINIGAME\\SG_GF\\L_ZONE_SG_SERVER.lua", []() {return std::make_unique<ZoneSGServer>();}},
|
||||
|
||||
//PR
|
||||
{"scripts\\client\\ai\\PR\\L_PR_WHISTLE.lua", []() {return new PrWhistle();}},
|
||||
{"scripts\\02_server\\Map\\PR\\L_PR_SEAGULL_FLY.lua", []() {return new PrSeagullFly();}},
|
||||
{"scripts\\ai\\PETS\\L_HYDRANT_SMASHABLE.lua", []() {return new HydrantSmashable();}},
|
||||
{"scripts\\02_server\\map\\PR\\L_HYDRANT_BROKEN.lua", []() {return new HydrantBroken();}},
|
||||
{"scripts\\02_server\\Map\\General\\PET_DIG_SERVER.lua", []() {return new PetDigServer();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_SKELETON_DRAGON_PET_DIG_SERVER.lua", []() {return new PetDigServer();}},
|
||||
//{"scripts\\02_server\\Map\\AM\\L_SKELETON_DRAGON_PET_DIG_SERVER.lua", [](){return new PetDigServer();}},
|
||||
{"scripts\\client\\ai\\PR\\L_CRAB_SERVER.lua", []() {return new CrabServer();}},
|
||||
{"scripts\\02_server\\Pets\\L_PET_FROM_DIG_SERVER.lua", []() {return new PetFromDigServer();}},
|
||||
{"scripts\\02_server\\Pets\\L_PET_FROM_OBJECT_SERVER.lua", []() {return new PetFromObjectServer();}},
|
||||
{"scripts\\02_server\\Pets\\L_DAMAGING_PET.lua", []() {return new DamagingPets();}},
|
||||
{"scripts\\02_server\\Map\\PR\\L_SPAWN_GRYPHON_SERVER.lua", []() {return new SpawnGryphonServer();}},
|
||||
{"scripts\\client\\ai\\PR\\L_PR_WHISTLE.lua", []() {return std::make_unique<PrWhistle>();}},
|
||||
{"scripts\\02_server\\Map\\PR\\L_PR_SEAGULL_FLY.lua", []() {return std::make_unique<PrSeagullFly>();}},
|
||||
{"scripts\\ai\\PETS\\L_HYDRANT_SMASHABLE.lua", []() {return std::make_unique<HydrantSmashable>();}},
|
||||
{"scripts\\02_server\\map\\PR\\L_HYDRANT_BROKEN.lua", []() {return std::make_unique<HydrantBroken>();}},
|
||||
{"scripts\\02_server\\Map\\General\\PET_DIG_SERVER.lua", []() {return std::make_unique<PetDigServer>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_SKELETON_DRAGON_PET_DIG_SERVER.lua", []() {return std::make_unique<PetDigServer>();}},
|
||||
//{"scripts\\02_server\\Map\\AM\\L_SKELETON_DRAGON_PET_DIG_SERVER.lua", [](){return std::make_unique<PetDigServer>();}},
|
||||
{"scripts\\client\\ai\\PR\\L_CRAB_SERVER.lua", []() {return std::make_unique<CrabServer>();}},
|
||||
{"scripts\\02_server\\Pets\\L_PET_FROM_DIG_SERVER.lua", []() {return std::make_unique<PetFromDigServer>();}},
|
||||
{"scripts\\02_server\\Pets\\L_PET_FROM_OBJECT_SERVER.lua", []() {return std::make_unique<PetFromObjectServer>();}},
|
||||
{"scripts\\02_server\\Pets\\L_DAMAGING_PET.lua", []() {return std::make_unique<DamagingPets>();}},
|
||||
{"scripts\\02_server\\Map\\PR\\L_SPAWN_GRYPHON_SERVER.lua", []() {return std::make_unique<SpawnGryphonServer>();}},
|
||||
|
||||
//FV
|
||||
{"scripts\\02_server\\Map\\FV\\L_ACT_CANDLE.lua", []() {return new FvCandle();}},
|
||||
{"scripts\\02_server\\Map\\FV\\L_ENEMY_RONIN_SPAWNER.lua", []() {return new EnemyRoninSpawner();}},
|
||||
{"scripts\\02_server\\Enemy\\FV\\L_FV_MAELSTROM_CAVALRY.lua", []() {return new FvMaelstromCavalry();}},
|
||||
{"scripts\\ai\\FV\\L_ACT_NINJA_TURRET_1.lua", []() {return new ActNinjaTurret();}},
|
||||
{"scripts\\02_server\\Map\\FV\\L_FV_HORSEMEN_TRIGGER.lua", []() {return new FvHorsemenTrigger();}},
|
||||
{"scripts\\ai\\FV\\L_FV_FLYING_CREVICE_DRAGON.lua", []() {return new FvFlyingCreviceDragon();}},
|
||||
{"scripts\\02_server\\Enemy\\FV\\L_FV_MAELSTROM_DRAGON.lua", []() {return new FvMaelstromDragon();}},
|
||||
{"scripts\\ai\\FV\\L_FV_DRAGON_SMASHING_GOLEM_QB.lua", []() {return new FvDragonSmashingGolemQb();}},
|
||||
{"scripts\\02_server\\Enemy\\General\\L_TREASURE_CHEST_DRAGON_SERVER.lua", []() {return new TreasureChestDragonServer();}},
|
||||
{"scripts\\ai\\GENERAL\\L_INSTANCE_EXIT_TRANSFER_PLAYER_TO_LAST_NON_INSTANCE.lua", []() {return new InstanceExitTransferPlayerToLastNonInstance();}},
|
||||
{"scripts\\ai\\FV\\L_NPC_FREE_GF_NINJAS.lua", []() {return new FvFreeGfNinjas();}},
|
||||
{"scripts\\ai\\FV\\L_FV_PANDA_SPAWNER_SERVER.lua", []() {return new FvPandaSpawnerServer();}},
|
||||
{"scripts\\ai\\FV\\L_FV_PANDA_SERVER.lua", []() {return new FvPandaServer();}},
|
||||
{"scripts\\zone\\PROPERTY\\FV\\L_ZONE_FV_PROPERTY.lua", []() {return new ZoneFvProperty();}},
|
||||
{"scripts\\ai\\FV\\L_FV_BRICK_PUZZLE_SERVER.lua", []() {return new FvBrickPuzzleServer();}},
|
||||
{"scripts\\ai\\FV\\L_FV_CONSOLE_LEFT_QUICKBUILD.lua", []() {return new FvConsoleLeftQuickbuild();}},
|
||||
{"scripts\\ai\\FV\\L_FV_CONSOLE_RIGHT_QUICKBUILD.lua", []() {return new FvConsoleRightQuickbuild();}},
|
||||
{"scripts\\ai\\FV\\L_FV_FACILITY_BRICK.lua", []() {return new FvFacilityBrick();}},
|
||||
{"scripts\\ai\\FV\\L_FV_FACILITY_PIPES.lua", []() {return new FvFacilityPipes();}},
|
||||
{"scripts\\02_server\\Map\\FV\\L_IMG_BRICK_CONSOLE_QB.lua", []() {return new ImgBrickConsoleQB();}},
|
||||
{"scripts\\ai\\FV\\L_ACT_PARADOX_PIPE_FIX.lua", []() {return new ActParadoxPipeFix();}},
|
||||
{"scripts\\ai\\FV\\L_FV_NINJA_GUARDS.lua", []() {return new FvNinjaGuard();}},
|
||||
{"scripts\\ai\\FV\\L_ACT_PASS_THROUGH_WALL.lua", []() {return new FvPassThroughWall();}},
|
||||
{"scripts\\ai\\FV\\L_ACT_BOUNCE_OVER_WALL.lua", []() {return new FvBounceOverWall();}},
|
||||
{"scripts\\02_server\\Map\\FV\\L_NPC_FONG.lua", []() {return new FvFong();}},
|
||||
{"scripts\\ai\\FV\\L_FV_MAELSTROM_GEYSER.lua", []() {return new FvMaelstromGeyser();}},
|
||||
{"scripts\\02_server\\Map\\FV\\Racing\\RACE_SHIP_LAP_COLUMNS_SERVER.lua", []() {return new RaceShipLapColumnsServer();}},
|
||||
{"scripts\\02_server\\Map\\FV\\L_ACT_CANDLE.lua", []() {return std::make_unique<FvCandle>();}},
|
||||
{"scripts\\02_server\\Map\\FV\\L_ENEMY_RONIN_SPAWNER.lua", []() {return std::make_unique<EnemyRoninSpawner>();}},
|
||||
{"scripts\\02_server\\Enemy\\FV\\L_FV_MAELSTROM_CAVALRY.lua", []() {return std::make_unique<FvMaelstromCavalry>();}},
|
||||
{"scripts\\ai\\FV\\L_ACT_NINJA_TURRET_1.lua", []() {return std::make_unique<ActNinjaTurret>();}},
|
||||
{"scripts\\02_server\\Map\\FV\\L_FV_HORSEMEN_TRIGGER.lua", []() {return std::make_unique<FvHorsemenTrigger>();}},
|
||||
{"scripts\\ai\\FV\\L_FV_FLYING_CREVICE_DRAGON.lua", []() {return std::make_unique<FvFlyingCreviceDragon>();}},
|
||||
{"scripts\\02_server\\Enemy\\FV\\L_FV_MAELSTROM_DRAGON.lua", []() {return std::make_unique<FvMaelstromDragon>();}},
|
||||
{"scripts\\ai\\FV\\L_FV_DRAGON_SMASHING_GOLEM_QB.lua", []() {return std::make_unique<FvDragonSmashingGolemQb>();}},
|
||||
{"scripts\\02_server\\Enemy\\General\\L_TREASURE_CHEST_DRAGON_SERVER.lua", []() {return std::make_unique<TreasureChestDragonServer>();}},
|
||||
{"scripts\\ai\\GENERAL\\L_INSTANCE_EXIT_TRANSFER_PLAYER_TO_LAST_NON_INSTANCE.lua", []() {return std::make_unique<InstanceExitTransferPlayerToLastNonInstance>();}},
|
||||
{"scripts\\ai\\FV\\L_NPC_FREE_GF_NINJAS.lua", []() {return std::make_unique<FvFreeGfNinjas>();}},
|
||||
{"scripts\\ai\\FV\\L_FV_PANDA_SPAWNER_SERVER.lua", []() {return std::make_unique<FvPandaSpawnerServer>();}},
|
||||
{"scripts\\ai\\FV\\L_FV_PANDA_SERVER.lua", []() {return std::make_unique<FvPandaServer>();}},
|
||||
{"scripts\\zone\\PROPERTY\\FV\\L_ZONE_FV_PROPERTY.lua", []() {return std::make_unique<ZoneFvProperty>();}},
|
||||
{"scripts\\ai\\FV\\L_FV_BRICK_PUZZLE_SERVER.lua", []() {return std::make_unique<FvBrickPuzzleServer>();}},
|
||||
{"scripts\\ai\\FV\\L_FV_CONSOLE_LEFT_QUICKBUILD.lua", []() {return std::make_unique<FvConsoleLeftQuickbuild>();}},
|
||||
{"scripts\\ai\\FV\\L_FV_CONSOLE_RIGHT_QUICKBUILD.lua", []() {return std::make_unique<FvConsoleRightQuickbuild>();}},
|
||||
{"scripts\\ai\\FV\\L_FV_FACILITY_BRICK.lua", []() {return std::make_unique<FvFacilityBrick>();}},
|
||||
{"scripts\\ai\\FV\\L_FV_FACILITY_PIPES.lua", []() {return std::make_unique<FvFacilityPipes>();}},
|
||||
{"scripts\\02_server\\Map\\FV\\L_IMG_BRICK_CONSOLE_QB.lua", []() {return std::make_unique<ImgBrickConsoleQB>();}},
|
||||
{"scripts\\ai\\FV\\L_ACT_PARADOX_PIPE_FIX.lua", []() {return std::make_unique<ActParadoxPipeFix>();}},
|
||||
{"scripts\\ai\\FV\\L_FV_NINJA_GUARDS.lua", []() {return std::make_unique<FvNinjaGuard>();}},
|
||||
{"scripts\\ai\\FV\\L_ACT_PASS_THROUGH_WALL.lua", []() {return std::make_unique<FvPassThroughWall>();}},
|
||||
{"scripts\\ai\\FV\\L_ACT_BOUNCE_OVER_WALL.lua", []() {return std::make_unique<FvBounceOverWall>();}},
|
||||
{"scripts\\02_server\\Map\\FV\\L_NPC_FONG.lua", []() {return std::make_unique<FvFong>();}},
|
||||
{"scripts\\ai\\FV\\L_FV_MAELSTROM_GEYSER.lua", []() {return std::make_unique<FvMaelstromGeyser>();}},
|
||||
{"scripts\\02_server\\Map\\FV\\Racing\\RACE_SHIP_LAP_COLUMNS_SERVER.lua", []() {return std::make_unique<RaceShipLapColumnsServer>();}},
|
||||
|
||||
//yes we know the lap numbers dont match the file name or anim. Thats what they desgined it as.
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\FV_RACE_DRAGON_LAP1_SERVER.lua", []() {return new FvRaceDragon("lap_01", 2);}},
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\FV_RACE_DRAGON_LAP2_SERVER.lua", []() {return new FvRaceDragon("lap_02", 0);}},
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\FV_RACE_DRAGON_LAP3_SERVER.lua", []() {return new FvRaceDragon("lap_03", 1);}},
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\FV_RACE_PILLAR_ABC_SERVER.lua", []() {return new FvRacePillarABCServer();}},
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\FV_RACE_PILLAR_D_SERVER.lua", []() {return new FvRacePillarDServer();}},
|
||||
{"scripts\\02_server\\Map\\FV\\Racing\\RACE_FIREBALLS.lua", []() {return new RaceFireballs();}},
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\FV_RACE_DRAGON_LAP1_SERVER.lua", []() {return std::make_unique<FvRaceDragon>("lap_01", 2);}},
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\FV_RACE_DRAGON_LAP2_SERVER.lua", []() {return std::make_unique<FvRaceDragon>("lap_02", 0);}},
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\FV_RACE_DRAGON_LAP3_SERVER.lua", []() {return std::make_unique<FvRaceDragon>("lap_03", 1);}},
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\FV_RACE_PILLAR_ABC_SERVER.lua", []() {return std::make_unique<FvRacePillarABCServer>();}},
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\FV_RACE_PILLAR_D_SERVER.lua", []() {return std::make_unique<FvRacePillarDServer>();}},
|
||||
{"scripts\\02_server\\Map\\FV\\Racing\\RACE_FIREBALLS.lua", []() {return std::make_unique<RaceFireballs>();}},
|
||||
|
||||
//Misc.
|
||||
{"scripts\\02_server\\Map\\General\\L_EXPLODING_ASSET.lua", []() {return new ExplodingAsset();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_WISHING_WELL_SERVER.lua", []() {return new WishingWellServer();}},
|
||||
{"scripts\\ai\\ACT\\L_ACT_PLAYER_DEATH_TRIGGER.lua", []() {return new ActPlayerDeathTrigger();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_GROWING_FLOWER_SERVER.lua", []() {return new GrowingFlower();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_TOKEN_CONSOLE_SERVER.lua", []() {return new TokenConsoleServer();}},
|
||||
{"scripts\\ai\\ACT\\FootRace\\L_ACT_BASE_FOOT_RACE.lua", []() {return new BaseFootRaceManager();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_PROP_PLATFORM.lua", []() {return new PropertyPlatform();}},
|
||||
{"scripts\\02_server\\Map\\VE\\L_VE_BRICKSAMPLE_SERVER.lua", []() {return new VeBricksampleServer();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_MAIL_BOX_SERVER.lua", []() {return new MailBoxServer();}},
|
||||
{"scripts\\ai\\ACT\\L_ACT_MINE.lua", []() {return new ActMine();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_WANDERING_VENDOR.lua", []() {return new WanderingVendor();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_EXPLODING_ASSET.lua", []() {return std::make_unique<ExplodingAsset>();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_WISHING_WELL_SERVER.lua", []() {return std::make_unique<WishingWellServer>();}},
|
||||
{"scripts\\ai\\ACT\\L_ACT_PLAYER_DEATH_TRIGGER.lua", []() {return std::make_unique<ActPlayerDeathTrigger>();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_GROWING_FLOWER_SERVER.lua", []() {return std::make_unique<GrowingFlower>();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_TOKEN_CONSOLE_SERVER.lua", []() {return std::make_unique<TokenConsoleServer>();}},
|
||||
{"scripts\\ai\\ACT\\FootRace\\L_ACT_BASE_FOOT_RACE.lua", []() {return std::make_unique<BaseFootRaceManager>();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_PROP_PLATFORM.lua", []() {return std::make_unique<PropertyPlatform>();}},
|
||||
{"scripts\\02_server\\Map\\VE\\L_VE_BRICKSAMPLE_SERVER.lua", []() {return std::make_unique<VeBricksampleServer>();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_MAIL_BOX_SERVER.lua", []() {return std::make_unique<MailBoxServer>();}},
|
||||
{"scripts\\ai\\ACT\\L_ACT_MINE.lua", []() {return std::make_unique<ActMine>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_WANDERING_VENDOR.lua", []() {return std::make_unique<WanderingVendor>();}},
|
||||
|
||||
//Racing
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\RACE_IMAGINE_CRATE_SERVER.lua", []() {return new RaceImagineCrateServer();}},
|
||||
{"scripts\\ai\\ACT\\L_ACT_VEHICLE_DEATH_TRIGGER.lua", []() {return new ActVehicleDeathTrigger();}},
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\RACE_IMAGINE_POWERUP.lua", []() {return new RaceImaginePowerup();}},
|
||||
{"scripts\\02_server\\Map\\FV\\Racing\\RACE_MAELSTROM_GEISER.lua", []() {return new RaceMaelstromGeiser();}},
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\FV_RACE_SMASH_EGG_IMAGINE_SERVER.lua", []() {return new FvRaceSmashEggImagineServer();}},
|
||||
{"scripts\\02_server\\Map\\FV\\Racing\\FV_RACING_COLUMNS.lua", []() {return new FvRacingColumns();}},
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\RACE_SMASH_SERVER.lua", []() {return new RaceSmashServer();}},
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\RACE_IMAGINE_CRATE_SERVER.lua", []() {return std::make_unique<RaceImagineCrateServer>();}},
|
||||
{"scripts\\ai\\ACT\\L_ACT_VEHICLE_DEATH_TRIGGER.lua", []() {return std::make_unique<ActVehicleDeathTrigger>();}},
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\RACE_IMAGINE_POWERUP.lua", []() {return std::make_unique<RaceImaginePowerup>();}},
|
||||
{"scripts\\02_server\\Map\\FV\\Racing\\RACE_MAELSTROM_GEISER.lua", []() {return std::make_unique<RaceMaelstromGeiser>();}},
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\FV_RACE_SMASH_EGG_IMAGINE_SERVER.lua", []() {return std::make_unique<FvRaceSmashEggImagineServer>();}},
|
||||
{"scripts\\02_server\\Map\\FV\\Racing\\FV_RACING_COLUMNS.lua", []() {return std::make_unique<FvRacingColumns>();}},
|
||||
{"scripts\\ai\\RACING\\OBJECTS\\RACE_SMASH_SERVER.lua", []() {return std::make_unique<RaceSmashServer>();}},
|
||||
|
||||
//NT
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_SENTINELWALKWAY_SERVER.lua", []() {return new NtSentinelWalkwayServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_PARADOXTELE_SERVER.lua", []() {return new NtParadoxTeleServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_DARKITECT_REVEAL_SERVER.lua", []() {return new NtDarkitectRevealServer();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_BANK_INTERACT_SERVER.lua", []() {return new BankInteractServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_VENTURESPEEDPAD_SERVER.lua", []() {return new NtVentureSpeedPadServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_VENTURE_CANNON_SERVER.lua", []() {return new NtVentureCannonServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_COMBAT_CHALLENGE_SERVER.lua", []() {return new NtCombatChallengeServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_COMBAT_CHALLENGE_DUMMY.lua", []() {return new NtCombatChallengeDummy();}},
|
||||
{"scripts\\02_server\\Map\\NT\\\\L_NT_COMBAT_EXPLODING_TARGET.lua", []() {return new NtCombatChallengeExplodingDummy();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_BASE_INTERACT_DROP_LOOT_SERVER.lua", []() {return new BaseInteractDropLootServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_ASSEMBLYTUBE_SERVER.lua", []() {return new NtAssemblyTubeServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_PARADOX_PANEL_SERVER.lua", []() {return new NtParadoxPanelServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_IMAG_BEAM_BUFFER.lua", []() {return new NtImagBeamBuffer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_BEAM_IMAGINATION_COLLECTORS.lua", []() {return new NtBeamImaginationCollectors();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_DIRT_CLOUD_SERVER.lua", []() {return new NtDirtCloudServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_CONSOLE_TELEPORT_SERVER.lua", []() {return new NtConsoleTeleportServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_SPAWN_STEGO_SERVER.lua", []() {return new SpawnStegoServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_SPAWN_SABERCAT_SERVER.lua", []() {return new SpawnSaberCatServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_SPAWN_SHRAKE_SERVER.lua", []() {return new SpawnShrakeServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_DUKE_SERVER.lua", []() {return new NtDukeServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_HAEL_SERVER.lua", []() {return new NtHaelServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_FACTION_SPY_SERVER.lua", []() {return new NtFactionSpyServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_OVERBUILD_SERVER.lua", []() {return new NtOverbuildServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_VANDA_SERVER.lua", []() {return new NtVandaServer();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_FORCE_VOLUME_SERVER.lua", []() {return new ForceVolumeServer();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_FRICTION_VOLUME_SERVER.lua", []() {return new FrictionVolumeServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_XRAY_SERVER.lua", []() {return new NtXRayServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_SLEEPING_GUARD.lua", []() {return new NtSleepingGuard();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_IMAGIMETER_VISIBILITY_SERVER.lua", []() {return new NTImagimeterVisibility();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_PIPE_VISIBILITY_SERVER.lua", []() {return new NTPipeVisibilityServer();}},
|
||||
{"scripts\\ai\\MINIGAME\\Objects\\MINIGAME_BLUE_MARK.lua", []() {return new MinigameBlueMark();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_NAOMI_BREADCRUMB_SERVER.lua", []() {return new NtNaomiBreadcrumbServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_NAOMI_DIRT_SERVER.lua", []() {return new NTNaomiDirtServer();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_SENTINELWALKWAY_SERVER.lua", []() {return std::make_unique<NtSentinelWalkwayServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_PARADOXTELE_SERVER.lua", []() {return std::make_unique<NtParadoxTeleServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_DARKITECT_REVEAL_SERVER.lua", []() {return std::make_unique<NtDarkitectRevealServer>();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_BANK_INTERACT_SERVER.lua", []() {return std::make_unique<BankInteractServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_VENTURESPEEDPAD_SERVER.lua", []() {return std::make_unique<NtVentureSpeedPadServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_VENTURE_CANNON_SERVER.lua", []() {return std::make_unique<NtVentureCannonServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_COMBAT_CHALLENGE_SERVER.lua", []() {return std::make_unique<NtCombatChallengeServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_COMBAT_CHALLENGE_DUMMY.lua", []() {return std::make_unique<NtCombatChallengeDummy>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\\\L_NT_COMBAT_EXPLODING_TARGET.lua", []() {return std::make_unique<NtCombatChallengeExplodingDummy>();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_BASE_INTERACT_DROP_LOOT_SERVER.lua", []() {return std::make_unique<BaseInteractDropLootServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_ASSEMBLYTUBE_SERVER.lua", []() {return std::make_unique<NtAssemblyTubeServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_PARADOX_PANEL_SERVER.lua", []() {return std::make_unique<NtParadoxPanelServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_IMAG_BEAM_BUFFER.lua", []() {return std::make_unique<NtImagBeamBuffer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_BEAM_IMAGINATION_COLLECTORS.lua", []() {return std::make_unique<NtBeamImaginationCollectors>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_DIRT_CLOUD_SERVER.lua", []() {return std::make_unique<NtDirtCloudServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_CONSOLE_TELEPORT_SERVER.lua", []() {return std::make_unique<NtConsoleTeleportServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_SPAWN_STEGO_SERVER.lua", []() {return std::make_unique<SpawnStegoServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_SPAWN_SABERCAT_SERVER.lua", []() {return std::make_unique<SpawnSaberCatServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_SPAWN_SHRAKE_SERVER.lua", []() {return std::make_unique<SpawnShrakeServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_DUKE_SERVER.lua", []() {return std::make_unique<NtDukeServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_HAEL_SERVER.lua", []() {return std::make_unique<NtHaelServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_FACTION_SPY_SERVER.lua", []() {return std::make_unique<NtFactionSpyServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_OVERBUILD_SERVER.lua", []() {return std::make_unique<NtOverbuildServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_VANDA_SERVER.lua", []() {return std::make_unique<NtVandaServer>();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_FORCE_VOLUME_SERVER.lua", []() {return std::make_unique<ForceVolumeServer>();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_FRICTION_VOLUME_SERVER.lua", []() {return std::make_unique<FrictionVolumeServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_XRAY_SERVER.lua", []() {return std::make_unique<NtXRayServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_SLEEPING_GUARD.lua", []() {return std::make_unique<NtSleepingGuard>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_IMAGIMETER_VISIBILITY_SERVER.lua", []() {return std::make_unique<NTImagimeterVisibility>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_PIPE_VISIBILITY_SERVER.lua", []() {return std::make_unique<NTPipeVisibilityServer>();}},
|
||||
{"scripts\\ai\\MINIGAME\\Objects\\MINIGAME_BLUE_MARK.lua", []() {return std::make_unique<MinigameBlueMark>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_NAOMI_BREADCRUMB_SERVER.lua", []() {return std::make_unique<NtNaomiBreadcrumbServer>();}},
|
||||
{"scripts\\02_server\\Map\\NT\\L_NT_NAOMI_DIRT_SERVER.lua", []() {return std::make_unique<NTNaomiDirtServer>();}},
|
||||
|
||||
//AM Crux
|
||||
{"scripts\\02_server\\Map\\AM\\L_AM_CONSOLE_TELEPORT_SERVER.lua", []() {return new AmConsoleTeleportServer();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_RANDOM_SPAWNER_FIN.lua", []() {return new RandomSpawnerFin();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_RANDOM_SPAWNER_PIT.lua", []() {return new RandomSpawnerPit();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_RANDOM_SPAWNER_STR.lua", []() {return new RandomSpawnerStr();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_RANDOM_SPAWNER_ZIP.lua", []() {return new RandomSpawnerZip();}},
|
||||
{"scripts\\02_server\\Enemy\\AM\\L_AM_DARKLING_MECH.lua", []() {return new AmDarklingMech();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_BRIDGE.lua", []() {return new AmBridge();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_DRAW_BRIDGE.lua", []() {return new AmDrawBridge();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_SHIELD_GENERATOR.lua", []() {return new AmShieldGenerator();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_SHIELD_GENERATOR_QUICKBUILD.lua", []() {return new AmShieldGeneratorQuickbuild();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_DROPSHIP_COMPUTER.lua", []() {return new AmDropshipComputer();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_SCROLL_READER_SERVER.lua", []() {return new AmScrollReaderServer();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_TEMPLE_SKILL_VOLUME.lua", []() {return new AmTemplateSkillVolume();}},
|
||||
{"scripts\\02_server\\Enemy\\General\\L_ENEMY_NJ_BUFF.lua", []() {return new EnemyNjBuff();}},
|
||||
{"scripts\\02_server\\Enemy\\AM\\L_AM_SKELETON_ENGINEER.lua", []() {return new AmSkeletonEngineer();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_SKULLKIN_DRILL.lua", []() {return new AmSkullkinDrill();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_SKULLKIN_DRILL_STAND.lua", []() {return new AmSkullkinDrillStand();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_SKULLKIN_TOWER.lua", []() {return new AmSkullkinTower();}},
|
||||
{"scripts\\02_server\\Enemy\\AM\\L_AM_NAMED_DARKLING_DRAGON.lua", []() {return new AmDarklingDragon();}},
|
||||
{"scripts\\02_server\\Enemy\\AM\\L_AM_DARKLING_DRAGON.lua", []() {return new AmDarklingDragon();}},
|
||||
{"scripts\\02_server\\Enemy\\AM\\L_AM_DARKLING_APE.lua", []() {return new BaseEnemyApe();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_BLUE_X.lua", []() {return new AmBlueX();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_TEAPOT_SERVER.lua", []() {return new AmTeapotServer();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_AM_CONSOLE_TELEPORT_SERVER.lua", []() {return std::make_unique<AmConsoleTeleportServer>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_RANDOM_SPAWNER_FIN.lua", []() {return std::make_unique<RandomSpawnerFin>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_RANDOM_SPAWNER_PIT.lua", []() {return std::make_unique<RandomSpawnerPit>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_RANDOM_SPAWNER_STR.lua", []() {return std::make_unique<RandomSpawnerStr>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_RANDOM_SPAWNER_ZIP.lua", []() {return std::make_unique<RandomSpawnerZip>();}},
|
||||
{"scripts\\02_server\\Enemy\\AM\\L_AM_DARKLING_MECH.lua", []() {return std::make_unique<AmDarklingMech>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_BRIDGE.lua", []() {return std::make_unique<AmBridge>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_DRAW_BRIDGE.lua", []() {return std::make_unique<AmDrawBridge>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_SHIELD_GENERATOR.lua", []() {return std::make_unique<AmShieldGenerator>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_SHIELD_GENERATOR_QUICKBUILD.lua", []() {return std::make_unique<AmShieldGeneratorQuickbuild>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_DROPSHIP_COMPUTER.lua", []() {return std::make_unique<AmDropshipComputer>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_SCROLL_READER_SERVER.lua", []() {return std::make_unique<AmScrollReaderServer>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_TEMPLE_SKILL_VOLUME.lua", []() {return std::make_unique<AmTemplateSkillVolume>();}},
|
||||
{"scripts\\02_server\\Enemy\\General\\L_ENEMY_NJ_BUFF.lua", []() {return std::make_unique<EnemyNjBuff>();}},
|
||||
{"scripts\\02_server\\Enemy\\AM\\L_AM_SKELETON_ENGINEER.lua", []() {return std::make_unique<AmSkeletonEngineer>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_SKULLKIN_DRILL.lua", []() {return std::make_unique<AmSkullkinDrill>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_SKULLKIN_DRILL_STAND.lua", []() {return std::make_unique<AmSkullkinDrillStand>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_SKULLKIN_TOWER.lua", []() {return std::make_unique<AmSkullkinTower>();}},
|
||||
{"scripts\\02_server\\Enemy\\AM\\L_AM_NAMED_DARKLING_DRAGON.lua", []() {return std::make_unique<AmDarklingDragon>();}},
|
||||
{"scripts\\02_server\\Enemy\\AM\\L_AM_DARKLING_DRAGON.lua", []() {return std::make_unique<AmDarklingDragon>();}},
|
||||
{"scripts\\02_server\\Enemy\\AM\\L_AM_DARKLING_APE.lua", []() {return std::make_unique<BaseEnemyApe>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_BLUE_X.lua", []() {return std::make_unique<AmBlueX>();}},
|
||||
{"scripts\\02_server\\Map\\AM\\L_TEAPOT_SERVER.lua", []() {return std::make_unique<AmTeapotServer>();}},
|
||||
|
||||
//Ninjago
|
||||
{"scripts\\02_server\\Map\\njhub\\L_GARMADON_CELEBRATION_SERVER.lua", []() {return new NjGarmadonCelebration();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_WU_NPC.lua", []() {return new NjWuNPC();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_SCROLL_CHEST_SERVER.lua", []() {return new NjScrollChestServer();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_COLE_NPC.lua", []() {return new NjColeNPC();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_JAY_MISSION_ITEMS.lua", []() {return new NjJayMissionItems();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_NPC_MISSION_SPINJITZU_SERVER.lua", []() {return new NjNPCMissionSpinjitzuServer();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_ENEMY_SKELETON_SPAWNER.lua", []() {return new EnemySkeletonSpawner();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_NJ_RAIL_SWITCH.lua", []() {return new NjRailSwitch();}},
|
||||
{"scripts\\02_server\\Map\\General\\Ninjago\\L_RAIL_ACTIVATORS_SERVER.lua", []() {return new NjRailActivatorsServer();}},
|
||||
{"scripts\\02_server\\Map\\General\\Ninjago\\L_RAIL_POST_SERVER.lua", []() {return new NjRailPostServer();}},
|
||||
{"scripts\\02_server\\Map\\General\\Ninjago\\L_ICE_RAIL_ACTIVATOR_SERVER.lua", []() {return new NjIceRailActivator();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_FALLING_TILE.lua", []() {return new FallingTile();}},
|
||||
{"scripts\\02_server\\Enemy\\General\\L_ENEMY_NJ_BUFF_STUN_IMMUNITY.lua", []() {return new EnemyNjBuff();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_IMAGINATION_SHRINE_SERVER.lua", []() {return new ImaginationShrineServer();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_LIEUTENANT.lua", []() {return new Lieutenant();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_RAIN_OF_ARROWS.lua", []() {return new RainOfArrows();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_CAVE_PRISON_CAGE.lua", []() {return new CavePrisonCage();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\boss_instance\\L_MONASTERY_BOSS_INSTANCE_SERVER.lua", []() {return new NjMonastryBossInstance();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_CATAPULT_BOUNCER_SERVER.lua", []() {return new CatapultBouncerServer();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_CATAPULT_BASE_SERVER.lua", []() {return new CatapultBaseServer();}},
|
||||
{"scripts\\02_server\\Map\\General\\Ninjago\\L_NJHUB_LAVA_PLAYER_DEATH_TRIGGER.lua", []() {return new NjhubLavaPlayerDeathTrigger();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_MON_CORE_NOOK_DOORS.lua", []() {return new MonCoreNookDoors();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_MON_CORE_SMASHABLE_DOORS.lua", []() {return new MonCoreSmashableDoors();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_MON_CORE_SMASHABLE_DOORS.lua", []() {return new MonCoreSmashableDoors();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_FLAME_JET_SERVER.lua", []() {return new FlameJetServer();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_BURNING_TILE.lua", []() {return new BurningTile();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_SPAWN_EARTH_PET_SERVER.lua", []() {return new NjEarthDragonPetServer();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_EARTH_PET_SERVER.lua", []() {return new NjEarthPetServer();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_DRAGON_EMBLEM_CHEST_SERVER.lua", []() {return new NjDragonEmblemChestServer();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_NYA_MISSION_ITEMS.lua", []() {return new NjNyaMissionitems();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_GARMADON_CELEBRATION_SERVER.lua", []() {return std::make_unique<NjGarmadonCelebration>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_WU_NPC.lua", []() {return std::make_unique<NjWuNPC>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_SCROLL_CHEST_SERVER.lua", []() {return std::make_unique<NjScrollChestServer>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_COLE_NPC.lua", []() {return std::make_unique<NjColeNPC>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_JAY_MISSION_ITEMS.lua", []() {return std::make_unique<NjJayMissionItems>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_NPC_MISSION_SPINJITZU_SERVER.lua", []() {return std::make_unique<NjNPCMissionSpinjitzuServer>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_ENEMY_SKELETON_SPAWNER.lua", []() {return std::make_unique<EnemySkeletonSpawner>();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_NJ_RAIL_SWITCH.lua", []() {return std::make_unique<NjRailSwitch>();}},
|
||||
{"scripts\\02_server\\Map\\General\\Ninjago\\L_RAIL_ACTIVATORS_SERVER.lua", []() {return std::make_unique<NjRailActivatorsServer>();}},
|
||||
{"scripts\\02_server\\Map\\General\\Ninjago\\L_RAIL_POST_SERVER.lua", []() {return std::make_unique<NjRailPostServer>();}},
|
||||
{"scripts\\02_server\\Map\\General\\Ninjago\\L_ICE_RAIL_ACTIVATOR_SERVER.lua", []() {return std::make_unique<NjIceRailActivator>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_FALLING_TILE.lua", []() {return std::make_unique<FallingTile>();}},
|
||||
{"scripts\\02_server\\Enemy\\General\\L_ENEMY_NJ_BUFF_STUN_IMMUNITY.lua", []() {return std::make_unique<EnemyNjBuff>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_IMAGINATION_SHRINE_SERVER.lua", []() {return std::make_unique<ImaginationShrineServer>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_LIEUTENANT.lua", []() {return std::make_unique<Lieutenant>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_RAIN_OF_ARROWS.lua", []() {return std::make_unique<RainOfArrows>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_CAVE_PRISON_CAGE.lua", []() {return std::make_unique<CavePrisonCage>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\boss_instance\\L_MONASTERY_BOSS_INSTANCE_SERVER.lua", []() {return std::make_unique<NjMonastryBossInstance>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_CATAPULT_BOUNCER_SERVER.lua", []() {return std::make_unique<CatapultBouncerServer>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_CATAPULT_BASE_SERVER.lua", []() {return std::make_unique<CatapultBaseServer>();}},
|
||||
{"scripts\\02_server\\Map\\General\\Ninjago\\L_NJHUB_LAVA_PLAYER_DEATH_TRIGGER.lua", []() {return std::make_unique<NjhubLavaPlayerDeathTrigger>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_MON_CORE_NOOK_DOORS.lua", []() {return std::make_unique<MonCoreNookDoors>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_MON_CORE_SMASHABLE_DOORS.lua", []() {return std::make_unique<MonCoreSmashableDoors>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_MON_CORE_SMASHABLE_DOORS.lua", []() {return std::make_unique<MonCoreSmashableDoors>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_FLAME_JET_SERVER.lua", []() {return std::make_unique<FlameJetServer>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_BURNING_TILE.lua", []() {return std::make_unique<BurningTile>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_SPAWN_EARTH_PET_SERVER.lua", []() {return std::make_unique<NjEarthDragonPetServer>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_EARTH_PET_SERVER.lua", []() {return std::make_unique<NjEarthPetServer>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_DRAGON_EMBLEM_CHEST_SERVER.lua", []() {return std::make_unique<NjDragonEmblemChestServer>();}},
|
||||
{"scripts\\02_server\\Map\\njhub\\L_NYA_MISSION_ITEMS.lua", []() {return std::make_unique<NjNyaMissionitems>();}},
|
||||
|
||||
//DLU
|
||||
{"scripts\\02_server\\DLU\\DLUVanityTeleportingObject.lua", []() {return new DLUVanityTeleportingObject();}},
|
||||
{"scripts\\02_server\\DLU\\DLUVanityTeleportingObject.lua", []() {return std::make_unique<DLUVanityTeleportingObject>();}},
|
||||
|
||||
//Survival Minigame
|
||||
{"scripts\\02_server\\Enemy\\Survival\\L_AG_SURVIVAL_STROMBIE.lua", []() {return new AgSurvivalStromling();}},
|
||||
{"scripts\\02_server\\Enemy\\Survival\\L_AG_SURVIVAL_DARKLING_MECH.lua", []() {return new AgSurvivalMech();}},
|
||||
{"scripts\\02_server\\Enemy\\Survival\\L_AG_SURVIVAL_DARK_SPIDERLING.lua", []() {return new AgSurvivalSpiderling();}},
|
||||
{"scripts\\02_server\\Enemy\\Survival\\L_AG_SURVIVAL_STROMBIE.lua", []() {return std::make_unique<AgSurvivalStromling>();}},
|
||||
{"scripts\\02_server\\Enemy\\Survival\\L_AG_SURVIVAL_DARKLING_MECH.lua", []() {return std::make_unique<AgSurvivalMech>();}},
|
||||
{"scripts\\02_server\\Enemy\\Survival\\L_AG_SURVIVAL_DARK_SPIDERLING.lua", []() {return std::make_unique<AgSurvivalSpiderling>();}},
|
||||
|
||||
//Scripted Equipment
|
||||
{"scripts\\EquipmentScripts\\Sunflower.lua", []() {return new Sunflower();}},
|
||||
{"scripts/EquipmentScripts/AnvilOfArmor.lua", []() {return new AnvilOfArmor();}},
|
||||
{"scripts/EquipmentScripts/FountainOfImagination.lua", []() {return new FountainOfImagination();}},
|
||||
{"scripts/EquipmentScripts/CauldronOfLife.lua", []() {return new CauldronOfLife();}},
|
||||
{"scripts\\02_server\\Equipment\\L_BOOTYDIG_SERVER.lua", []() {return new BootyDigServer();}},
|
||||
{"scripts\\EquipmentScripts\\PersonalFortress.lua", []() {return new PersonalFortress();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_PROPERTY_DEVICE.lua", []() {return new PropertyDevice();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_IMAG_BACKPACK_HEALS_SERVER.lua", []() {return new ImaginationBackpackHealServer();}},
|
||||
{"scripts\\ai\\GENERAL\\L_LEGO_DIE_ROLL.lua", []() {return new LegoDieRoll();}},
|
||||
{"scripts\\EquipmentScripts\\BuccaneerValiantShip.lua", []() {return new BuccaneerValiantShip();}},
|
||||
{"scripts\\EquipmentScripts\\FireFirstSkillonStartup.lua", []() {return new FireFirstSkillonStartup();}},
|
||||
{"scripts\\equipmenttriggers\\gempack.lua", []() {return new GemPack();}},
|
||||
{"scripts\\equipmenttriggers\\shardarmor.lua", []() {return new ShardArmor();}},
|
||||
{"scripts\\equipmenttriggers\\coilbackpack.lua", []() {return new TeslaPack();}},
|
||||
{"scripts\\EquipmentScripts\\stunImmunity.lua", []() {return new StunImmunity();}},
|
||||
{"scripts\\EquipmentScripts\\Sunflower.lua", []() {return std::make_unique<Sunflower>();}},
|
||||
{"scripts/EquipmentScripts/AnvilOfArmor.lua", []() {return std::make_unique<AnvilOfArmor>();}},
|
||||
{"scripts/EquipmentScripts/FountainOfImagination.lua", []() {return std::make_unique<FountainOfImagination>();}},
|
||||
{"scripts/EquipmentScripts/CauldronOfLife.lua", []() {return std::make_unique<CauldronOfLife>();}},
|
||||
{"scripts\\02_server\\Equipment\\L_BOOTYDIG_SERVER.lua", []() {return std::make_unique<BootyDigServer>();}},
|
||||
{"scripts\\EquipmentScripts\\PersonalFortress.lua", []() {return std::make_unique<PersonalFortress>();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_PROPERTY_DEVICE.lua", []() {return std::make_unique<PropertyDevice>();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_IMAG_BACKPACK_HEALS_SERVER.lua", []() {return std::make_unique<ImaginationBackpackHealServer>();}},
|
||||
{"scripts\\ai\\GENERAL\\L_LEGO_DIE_ROLL.lua", []() {return std::make_unique<LegoDieRoll>();}},
|
||||
{"scripts\\EquipmentScripts\\BuccaneerValiantShip.lua", []() {return std::make_unique<BuccaneerValiantShip>();}},
|
||||
{"scripts\\EquipmentScripts\\FireFirstSkillonStartup.lua", []() {return std::make_unique<FireFirstSkillonStartup>();}},
|
||||
{"scripts\\equipmenttriggers\\gempack.lua", []() {return std::make_unique<GemPack>();}},
|
||||
{"scripts\\equipmenttriggers\\shardarmor.lua", []() {return std::make_unique<ShardArmor>();}},
|
||||
{"scripts\\equipmenttriggers\\coilbackpack.lua", []() {return std::make_unique<TeslaPack>();}},
|
||||
{"scripts\\EquipmentScripts\\stunImmunity.lua", []() {return std::make_unique<StunImmunity>();}},
|
||||
|
||||
//FB
|
||||
{"scripts\\ai\\NS\\WH\\L_ROCKHYDRANT_BROKEN.lua", []() {return new RockHydrantBroken();}},
|
||||
{"scripts\\ai\\NS\\L_NS_WH_FANS.lua", []() {return new WhFans();}},
|
||||
{"scripts\\ai\\NS\\WH\\L_ROCKHYDRANT_BROKEN.lua", []() {return std::make_unique<RockHydrantBroken>();}},
|
||||
{"scripts\\ai\\NS\\L_NS_WH_FANS.lua", []() {return std::make_unique<WhFans>();}},
|
||||
|
||||
//WBL
|
||||
{"scripts\\zone\\LUPs\\WBL_generic_zone.lua", []() {return new WblGenericZone();}},
|
||||
{"scripts\\zone\\LUPs\\WBL_generic_zone.lua", []() {return std::make_unique<WblGenericZone>();}},
|
||||
|
||||
//Alpha
|
||||
{"scripts\\ai\\FV\\L_TRIGGER_GAS.lua", []() {return new TriggerGas();}},
|
||||
{"scripts\\ai\\FV\\L_ACT_NINJA_SENSEI.lua", []() {return new ActNinjaSensei();}},
|
||||
{"scripts\\ai\\FV\\L_TRIGGER_GAS.lua", []() {return std::make_unique<TriggerGas>();}},
|
||||
{"scripts\\ai\\FV\\L_ACT_NINJA_SENSEI.lua", []() {return std::make_unique<ActNinjaSensei>();}},
|
||||
|
||||
//Pickups
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_1_BRONZE-COIN-SPAWNER.lua", []() {return new SpecialCoinSpawner(1);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_1_GOLD-COIN-SPAWNER.lua", []() {return new SpecialCoinSpawner(10000);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_1_SILVER-COIN-SPAWNER.lua", []() {return new SpecialCoinSpawner(100);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_10_BRONZE-COIN-SPAWNER.lua", []() {return new SpecialCoinSpawner(10);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_10_GOLD-COIN-SPAWNER.lua", []() {return new SpecialCoinSpawner(100000);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_10_SILVER-COIN-SPAWNER.lua", []() {return new SpecialCoinSpawner(1000);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_25_BRONZE-COIN-SPAWNER.lua", []() {return new SpecialCoinSpawner(25);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_25_GOLD-COIN-SPAWNER.lua", []() {return new SpecialCoinSpawner(250000);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_25_SILVER-COIN-SPAWNER.lua", []() {return new SpecialCoinSpawner(2500);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_IMAGINE-POWERUP-SPAWNER.lua", []() {return new SpecialPowerupSpawner(13);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_IMAGINE-POWERUP-SPAWNER-2PT.lua", []() {return new SpecialPowerupSpawner(129);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_LIFE-POWERUP-SPAWNER.lua", []() {return new SpecialPowerupSpawner(5);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_ARMOR-POWERUP-SPAWNER.lua", []() {return new SpecialPowerupSpawner(747);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_SPEED_BUFF_SPAWNER.lua", []() {return new SpecialSpeedBuffSpawner();}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_1_BRONZE-COIN-SPAWNER.lua", []() {return std::make_unique<SpecialCoinSpawner>(1);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_1_GOLD-COIN-SPAWNER.lua", []() {return std::make_unique<SpecialCoinSpawner>(10000);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_1_SILVER-COIN-SPAWNER.lua", []() {return std::make_unique<SpecialCoinSpawner>(100);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_10_BRONZE-COIN-SPAWNER.lua", []() {return std::make_unique<SpecialCoinSpawner>(10);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_10_GOLD-COIN-SPAWNER.lua", []() {return std::make_unique<SpecialCoinSpawner>(100000);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_10_SILVER-COIN-SPAWNER.lua", []() {return std::make_unique<SpecialCoinSpawner>(1000);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_25_BRONZE-COIN-SPAWNER.lua", []() {return std::make_unique<SpecialCoinSpawner>(25);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_25_GOLD-COIN-SPAWNER.lua", []() {return std::make_unique<SpecialCoinSpawner>(250000);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_25_SILVER-COIN-SPAWNER.lua", []() {return std::make_unique<SpecialCoinSpawner>(2500);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_IMAGINE-POWERUP-SPAWNER.lua", []() {return std::make_unique<SpecialPowerupSpawner>(13);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_IMAGINE-POWERUP-SPAWNER-2PT.lua", []() {return std::make_unique<SpecialPowerupSpawner>(129);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_LIFE-POWERUP-SPAWNER.lua", []() {return std::make_unique<SpecialPowerupSpawner>(5);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_ARMOR-POWERUP-SPAWNER.lua", []() {return std::make_unique<SpecialPowerupSpawner>(747);}},
|
||||
{"scripts\\ai\\SPEC\\L_SPECIAL_SPEED_BUFF_SPAWNER.lua", []() {return std::make_unique<SpecialSpeedBuffSpawner>();}},
|
||||
|
||||
//Wild
|
||||
{"scripts\\ai\\WILD\\L_WILD_GF_RAT.lua", []() {return new WildAndScared();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_GF_SNAIL.lua", []() {return new WildAndScared();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_GF_GLOWBUG.lua", []() {return new WildGfGlowbug();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_AMBIENT_CRAB.lua", []() {return new WildAmbientCrab();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_PANTS.lua", []() {return new WildPants();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_NINJA_BRICKS.lua", []() {return new WildNinjaBricks();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_NINJA_STUDENT.lua", []() {return new WildNinjaStudent();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_NINJA_SENSEI.lua", []() {return new WildNinjaSensei();}},
|
||||
{"scripts\\ai\\WILD\\L_LUP_generic_interact.lua", []() {return new LupGenericInteract();}},
|
||||
{"scripts\\zone\\LUPs\\RobotCity Intro\\WBL_RCIntro_RobotCitizenBlue.lua", []() {return new WblRobotCitizen();}},
|
||||
{"scripts\\zone\\LUPs\\RobotCity Intro\\WBL_RCIntro_RobotCitizenGreen.lua", []() {return new WblRobotCitizen();}},
|
||||
{"scripts\\zone\\LUPs\\RobotCity Intro\\WBL_RCIntro_RobotCitizenOrange.lua", []() {return new WblRobotCitizen();}},
|
||||
{"scripts\\zone\\LUPs\\RobotCity Intro\\WBL_RCIntro_RobotCitizenRed.lua", []() {return new WblRobotCitizen();}},
|
||||
{"scripts\\zone\\LUPs\\RobotCity Intro\\WBL_RCIntro_RobotCitizenYellow.lua", []() {return new WblRobotCitizen();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_ENEMY_CLEAR_THREAT.lua", []() {return new EnemyClearThreat();}},
|
||||
{"scripts\\ai\\AG\\L_AG_SPIDER_BOSS_MESSAGE.lua", []() {return new AgSpiderBossMessage();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_GF_RAT.lua", []() {return std::make_unique<WildAndScared>();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_GF_SNAIL.lua", []() {return std::make_unique<WildAndScared>();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_GF_GLOWBUG.lua", []() {return std::make_unique<WildGfGlowbug>();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_AMBIENT_CRAB.lua", []() {return std::make_unique<WildAmbientCrab>();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_PANTS.lua", []() {return std::make_unique<WildPants>();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_NINJA_BRICKS.lua", []() {return std::make_unique<WildNinjaBricks>();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_NINJA_STUDENT.lua", []() {return std::make_unique<WildNinjaStudent>();}},
|
||||
{"scripts\\ai\\WILD\\L_WILD_NINJA_SENSEI.lua", []() {return std::make_unique<WildNinjaSensei>();}},
|
||||
{"scripts\\ai\\WILD\\L_LUP_generic_interact.lua", []() {return std::make_unique<LupGenericInteract>();}},
|
||||
{"scripts\\zone\\LUPs\\RobotCity Intro\\WBL_RCIntro_RobotCitizenBlue.lua", []() {return std::make_unique<WblRobotCitizen>();}},
|
||||
{"scripts\\zone\\LUPs\\RobotCity Intro\\WBL_RCIntro_RobotCitizenGreen.lua", []() {return std::make_unique<WblRobotCitizen>();}},
|
||||
{"scripts\\zone\\LUPs\\RobotCity Intro\\WBL_RCIntro_RobotCitizenOrange.lua", []() {return std::make_unique<WblRobotCitizen>();}},
|
||||
{"scripts\\zone\\LUPs\\RobotCity Intro\\WBL_RCIntro_RobotCitizenRed.lua", []() {return std::make_unique<WblRobotCitizen>();}},
|
||||
{"scripts\\zone\\LUPs\\RobotCity Intro\\WBL_RCIntro_RobotCitizenYellow.lua", []() {return std::make_unique<WblRobotCitizen>();}},
|
||||
{"scripts\\02_server\\Map\\General\\L_ENEMY_CLEAR_THREAT.lua", []() {return std::make_unique<EnemyClearThreat>();}},
|
||||
{"scripts\\ai\\AG\\L_AG_SPIDER_BOSS_MESSAGE.lua", []() {return std::make_unique<AgSpiderBossMessage>();}},
|
||||
{"scripts\\ai\\GF\\L_GF_RACE_INSTANCER.lua", []() {return std::make_unique<GfRaceInstancer>();}},
|
||||
|
||||
};
|
||||
|
||||
@@ -703,26 +705,28 @@ namespace {
|
||||
"scripts\\zone\\AG\\L_ZONE_AG.lua",
|
||||
"scripts\\zone\\NS\\L_ZONE_NS.lua",
|
||||
"scripts\\zone\\GF\\L_ZONE_GF.lua",
|
||||
"scripts\\ai\\AG\\CONCERT_STAGE.lua",
|
||||
"scripts\\ai\\NS\\L_NS_CAR_MODULAR_BUILD.lua", // In our implementation, this is done in GameMessages.cpp
|
||||
};
|
||||
};
|
||||
|
||||
CppScripts::Script* const CppScripts::GetScript(Entity* parent, const std::string& scriptName) {
|
||||
CppScripts::Script& CppScripts::GetScript(Entity* parent, const std::string& scriptName) {
|
||||
auto itr = g_Scripts.find(scriptName);
|
||||
if (itr != g_Scripts.end()) {
|
||||
return itr->second;
|
||||
return *itr->second;
|
||||
}
|
||||
|
||||
const auto itrTernary = scriptLoader.find(scriptName);
|
||||
Script* script = itrTernary != scriptLoader.cend() ? itrTernary->second() : &InvalidToReturn;
|
||||
auto& script = itrTernary != scriptLoader.cend() ? *itrTernary->second() : InvalidToReturn;
|
||||
|
||||
if (script == &InvalidToReturn && !scriptName.empty() && !g_ExcludedScripts.contains(scriptName)) {
|
||||
if (&script == &InvalidToReturn && !scriptName.empty() && !g_ExcludedScripts.contains(scriptName)) {
|
||||
LOG_DEBUG("LOT %i attempted to load CppScript for '%s', but returned InvalidScript.", parent->GetLOT(), scriptName.c_str());
|
||||
}
|
||||
|
||||
g_Scripts[scriptName] = script;
|
||||
g_Scripts[scriptName] = &script;
|
||||
return script;
|
||||
}
|
||||
|
||||
CppScripts::Script* const CppScripts::GetInvalidScript() {
|
||||
return &InvalidToReturn;
|
||||
CppScripts::Script& CppScripts::GetInvalidScript() {
|
||||
return InvalidToReturn;
|
||||
}
|
||||
|
||||
@@ -354,13 +354,13 @@ namespace CppScripts {
|
||||
* @param player the player to remove
|
||||
* @param canceled if it was done via the cancel button
|
||||
*/
|
||||
virtual void OnRequestActivityExit(Entity* sender, LWOOBJID player, bool canceled){};
|
||||
virtual void OnRequestActivityExit(Entity* sender, LWOOBJID player, bool canceled) {};
|
||||
};
|
||||
|
||||
Script* const GetScript(Entity* parent, const std::string& scriptName);
|
||||
Script& GetScript(Entity* parent, const std::string& scriptName);
|
||||
|
||||
// Get the invalid script. Would be a static variable of the namespace, but that would be
|
||||
// more cluttery to use. Also this allows us to control where this invalid script is defined and initialized
|
||||
// since we dont want anyone externally modifying it.
|
||||
Script* const GetInvalidScript();
|
||||
Script& GetInvalidScript();
|
||||
};
|
||||
|
||||
@@ -25,11 +25,10 @@ void AgSpiderBossMessage::MakeBox(Entity* self) const {
|
||||
if (!tgt) return;
|
||||
GameMessages::DisplayTooltip tooltip;
|
||||
tooltip.target = tgt->GetObjectID();
|
||||
tooltip.sysAddr = tgt->GetSystemAddress();
|
||||
tooltip.show = true;
|
||||
tooltip.text = box.boxText;
|
||||
tooltip.time = box.boxTime * 1000; // to ms
|
||||
tooltip.Send();
|
||||
tooltip.Send(tgt->GetSystemAddress());
|
||||
}
|
||||
|
||||
void AgSpiderBossMessage::OnCollisionPhantom(Entity* self, Entity* target) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
set(DSCRIPTS_SOURCES_AI_GF
|
||||
"GfRaceInstancer.cpp"
|
||||
"GfCampfire.cpp"
|
||||
"GfOrgan.cpp"
|
||||
"GfBanana.cpp"
|
||||
|
||||
7
dScripts/ai/GF/GfRaceInstancer.cpp
Normal file
7
dScripts/ai/GF/GfRaceInstancer.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#include "GfRaceInstancer.h"
|
||||
|
||||
#include "Entity.h"
|
||||
|
||||
void GfRaceInstancer::OnStartup(Entity* self) {
|
||||
self->SetProximityRadius(self->HasVar(u"interaction_distance") ? self->GetVar<float>(u"interaction_distance") : 16.0f, "Interaction_Distance");
|
||||
}
|
||||
11
dScripts/ai/GF/GfRaceInstancer.h
Normal file
11
dScripts/ai/GF/GfRaceInstancer.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef GFRACEINSTANCER_H
|
||||
#define GFRACEINSTANCER_H
|
||||
|
||||
#include "CppScripts.h"
|
||||
|
||||
class GfRaceInstancer : public CppScripts::Script {
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
};
|
||||
|
||||
#endif //!GFRACEINSTANCER_H
|
||||
@@ -13,7 +13,7 @@ void Server::SetupLogger(const std::string_view serviceName) {
|
||||
|
||||
const auto logsDir = BinaryPathFinder::GetBinaryDir() / "logs";
|
||||
|
||||
if (!std::filesystem::exists(logsDir)) std::filesystem::create_directory(logsDir);
|
||||
if (!std::filesystem::exists(logsDir)) std::filesystem::create_directories(logsDir);
|
||||
|
||||
std::string logPath = (logsDir / serviceName).string() + "_" + std::to_string(time(nullptr)) + ".log";
|
||||
bool logToConsole = false;
|
||||
|
||||
@@ -13,7 +13,7 @@ target_include_directories(WorldServer PRIVATE
|
||||
"${PROJECT_SOURCE_DIR}/dServer" # BinaryPathFinder.h
|
||||
)
|
||||
|
||||
target_link_libraries(WorldServer PUBLIC ${COMMON_LIBRARIES}
|
||||
target_link_libraries(WorldServer ${COMMON_LIBRARIES}
|
||||
dScripts
|
||||
dGameBase
|
||||
dComponents
|
||||
|
||||
@@ -34,6 +34,9 @@ services:
|
||||
- CLIENT_LOCATION=/app/luclient
|
||||
- DLU_CONFIG_DIR=/app/configs
|
||||
- DUMP_FOLDER=/app/dump
|
||||
- DATABASE_TYPE=mariadb
|
||||
- SQLITE_DATABASE_PATH=${SQLITE_DATABASE_PATH:-resServer/dlu.sqlite}
|
||||
- SKIP_ACCOUNT_CREATION=${SKIP_ACCOUNT_CREATION:-1}
|
||||
- MYSQL_HOST=darkflamedb
|
||||
- MYSQL_DATABASE=${MARIADB_DATABASE:-darkflame}
|
||||
- MYSQL_USERNAME=${MARIADB_USER:-darkflame}
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
|setannmsg|`/setannmsg <title>`|Sets the message of an announcement.|8|
|
||||
|setanntitle|`/setanntitle <title>`|Sets the title of an announcement.|8|
|
||||
|shutdownuniverse|`/shutdownuniverse`|Sends a shutdown message to the master server. This will send an announcement to all players that the universe will shut down in 10 minutes.|9|
|
||||
|uptime|`/uptime`|Displays the time the current world server has been active.|8|
|
||||
|
||||
## Development Commands
|
||||
|
||||
@@ -59,7 +60,7 @@ These commands are primarily for development and testing. The usage of many of t
|
||||
|testmap|`/testmap <zone> (force) (clone-id)`|Transfers you to the given zone by id and clone id. Add "force" to skip checking if the zone is accessible (this can softlock your character, though, if you e.g. try to teleport to Frostburgh).|1|
|
||||
|reportproxphys|`/reportproxphys`|Prints to console the position and radius of proximity sensors.|6|
|
||||
|spawnphysicsverts|`/spawnphysicsverts`|Spawns a 1x1 brick at all vertices of phantom physics objects.|6|
|
||||
|teleport|`/teleport <x> (y) <z>` or <br> `/tele <x> (y) <z>`|Teleports you. If no Y is given, you are teleported to the height of the terrain or physics object at (x, z). Alias: `/tele`.|6|
|
||||
|teleport|`/teleport <x/source player> (y) <z/target player>` or <br> `/tele <x/source player> (y) <z/target player>`|Teleports you. If no Y is given, you are teleported to the height of the terrain or physics object at (x, z). Any of the coordinates can use the syntax of an exact position (10.0), or a relative position (~+10.0). A ~ means use the current value of that axis as the base value. Addition or subtraction is supported (~+10) (~-10). If source player and target player are players that exist in the world, then the source player will be teleported to target player. Alias: `/tele`.|6|
|
||||
|activatespawner|`/activatespawner <spawner name>`|Activates spawner by name.|8|
|
||||
|addmission|`/addmission <mission id>`|Accepts the mission, adding it to your journal.|8|
|
||||
|boost|`/boost (time)`|Adds a passive boost action if you are in a vehicle. If time is given it will end after that amount of time|8|
|
||||
|
||||
0
migrations/cdserver/7_migration_for_migrations.sql
Normal file
0
migrations/cdserver/7_migration_for_migrations.sql
Normal file
1
migrations/dlu/mysql/17_migration_for_migrations.sql
Normal file
1
migrations/dlu/mysql/17_migration_for_migrations.sql
Normal file
@@ -0,0 +1 @@
|
||||
-- see MigrationRunner.cpp for what this does
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user