2023-02-18 20:10:02 -03:00
|
|
|
// Copyright 2023 The Forgotten Server Authors. All rights reserved.
|
2022-02-22 15:41:21 -03:00
|
|
|
// Use of this source code is governed by the GPL-2.0 License that can be found in the LICENSE file.
|
2013-07-07 02:30:08 +02:00
|
|
|
|
|
|
|
|
#include "otpch.h"
|
|
|
|
|
|
2023-12-13 01:56:46 +01:00
|
|
|
#include "otserv.h"
|
|
|
|
|
|
2022-03-18 21:20:02 +01:00
|
|
|
#include "configmanager.h"
|
|
|
|
|
#include "databasemanager.h"
|
|
|
|
|
#include "databasetasks.h"
|
2013-07-07 02:30:08 +02:00
|
|
|
#include "game.h"
|
2024-06-01 01:05:43 +02:00
|
|
|
#include "http/http.h"
|
2013-07-07 02:30:08 +02:00
|
|
|
#include "iomarket.h"
|
2022-03-18 21:20:02 +01:00
|
|
|
#include "monsters.h"
|
|
|
|
|
#include "outfit.h"
|
2013-10-30 21:38:24 +01:00
|
|
|
#include "protocolstatus.h"
|
2022-03-18 21:20:02 +01:00
|
|
|
#include "rsa.h"
|
2013-11-10 05:02:15 +01:00
|
|
|
#include "scheduler.h"
|
revscriptsys (#2558)
* initial revscriptsys
creates a new folder called 'scripts' in the data folder.
lua files placed in the 'scripts' or sub folders will automaticly get registered on load with the right setup ofcourse.
Registering happens in the lua file itself, doesn't require xml settings.
lua files can be deactivated by placing a '#' infront of the filename ex: '#positions.lua' it wont get loaded then.
Currently it supports:
-Actions
-TalkActions
-CreatureEvents
-GlobalEvents
-MoveEvents
There is still stuff on the todo list but they'll get added sooner or later.
Co-Authored-By: Sam <thesumm@users.noreply.github.com>
* compiler fixes
added boost-filesystem to appveyor.yml
fixed a few more compiler errors.
* cleanup on script.cpp
removed using namespace for std / boost filesystem
* some fixes
had to make adjustment so lua callbacks and xml settings work alongside and don't crash the server
* small fixes on movements & function additions
Have to revert the function + callback for stepin/stepout & additem/removeitem as it doesn't make sense on the second look and might cause a stackoverflow
I've also reworked the equip/dequip so it doesn't get double calls.
It'll first check if functions return true if not it won't bother to read the callback
accidently used an old spellbook.lua
added :aid(ids) :uid(ids) functions for MoveEvents
* revert to 'using' functions and suggestion of Djarek
Could revert most of movements.h
made the declaration of the static functions more clear
Co-Authored-By: Damian Jarek <djarek@users.noreply.github.com>
* small fixes
removed commentary from movement.cpp
added newline for position.lua
reworked spellbook.lua with table.concat
* Monster handler & other stuff
- MonsterType's can now be created through lua functions.
- added an interface to create MonsterType's easily through lua files (register_monster_type.lua)
- added #example.lua in 'scripts\monsters\'
- renamed action vector functions for a better standard
- renamed _lib folder to lib, this folder gets now loaded when the other lib folder gets loaded aswell
- moved loading lua scripts out of the scriptfilemanager, we need to load everything after monsters etc. is loaded so MonsterType script manipulation does work
- added Loot() & MonsterSpell() metatables
* fix compiler error
* forgot to remove test code
removed test outfit from MonsterType
* small changes
- added createFunctions(class) it virtually creates the get/set functions for the class passed on
- 'events' folder in monsters is excluded from auto parsing files, as we load callbacks for specific monsters which have an eventFile set to 'true' or 'filename' in this folder.
* compiler error fix
* minor change on createFunctions
* stripping path string
* added Game.createMonsterType(name) and small fixes
- added Game.createMonsterType(name)
- reworked MonsterType(name) to return nil if the MonsterType does not exist, so we don't suddenly create a MonsterType if we do not even want to.
- changed reinterpret_cast to static_cast
* config.lua option for console
- added an option to disable scripts console logging, it can be disabled by placing 'showScriptsLogInConsole = false' into config.lua
* initial revscriptsys
creates a new folder called 'scripts' in the data folder.
lua files placed in the 'scripts' or sub folders will automaticly get registered on load with the right setup ofcourse.
Registering happens in the lua file itself, doesn't require xml settings.
lua files can be deactivated by placing a '#' infront of the filename ex: '#positions.lua' it wont get loaded then.
Currently it supports:
-Actions
-TalkActions
-CreatureEvents
-GlobalEvents
-MoveEvents
There is still stuff on the todo list but they'll get added sooner or later.
Co-Authored-By: Sam <thesumm@users.noreply.github.com>
cleanup on script.cpp
removed using namespace for std / boost filesystem
small fixes on movements & function additions
Have to revert the function + callback for stepin/stepout & additem/removeitem as it doesn't make sense on the second look and might cause a stackoverflow
I've also reworked the equip/dequip so it doesn't get double calls.
It'll first check if functions return true if not it won't bother to read the callback
accidently used an old spellbook.lua
added :aid(ids) :uid(ids) functions for MoveEvents
Monster handler & other stuff
- MonsterType's can now be created through lua functions.
- added an interface to create MonsterType's easily through lua files (register_monster_type.lua)
- added #example.lua in 'scripts\monsters\'
- renamed action vector functions for a better standard
- renamed _lib folder to lib, this folder gets now loaded when the other lib folder gets loaded aswell
- moved loading lua scripts out of the scriptfilemanager, we need to load everything after monsters etc. is loaded so MonsterType script manipulation does work
- added Loot() & MonsterSpell() metatables
small changes
- added createFunctions(class) it virtually creates the get/set functions for the class passed on
- 'events' folder in monsters is excluded from auto parsing files, as we load callbacks for specific monsters which have an eventFile set to 'true' or 'filename' in this folder.
stripping path string
added Game.createMonsterType(name) and small fixes
- added Game.createMonsterType(name)
- reworked MonsterType(name) to return nil if the MonsterType does not exist, so we don't suddenly create a MonsterType if we do not even want to.
- changed reinterpret_cast to static_cast
config.lua option for console
- added an option to disable scripts console logging, it can be disabled by placing 'showScriptsLogInConsole = false' into config.lua
2019-04-16 16:33:38 +02:00
|
|
|
#include "script.h"
|
2022-03-18 21:20:02 +01:00
|
|
|
#include "scriptmanager.h"
|
|
|
|
|
#include "server.h"
|
|
|
|
|
|
2018-01-06 06:51:27 -05:00
|
|
|
#include <fstream>
|
2022-03-18 21:20:02 +01:00
|
|
|
|
2020-05-03 16:52:32 -04:00
|
|
|
#if __has_include("gitmetadata.h")
|
2022-03-18 21:20:02 +01:00
|
|
|
#include "gitmetadata.h"
|
2020-05-03 16:52:32 -04:00
|
|
|
#endif
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2014-12-04 18:24:25 +01:00
|
|
|
DatabaseTasks g_databaseTasks;
|
2014-01-22 05:25:05 +01:00
|
|
|
Dispatcher g_dispatcher;
|
|
|
|
|
Scheduler g_scheduler;
|
2013-07-07 02:30:08 +02:00
|
|
|
|
|
|
|
|
Game g_game;
|
|
|
|
|
Monsters g_monsters;
|
|
|
|
|
Vocations g_vocations;
|
2019-04-26 14:22:33 +02:00
|
|
|
extern Scripts* g_scripts;
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2013-11-08 02:01:45 +01:00
|
|
|
std::mutex g_loaderLock;
|
|
|
|
|
std::condition_variable g_loaderSignal;
|
|
|
|
|
std::unique_lock<std::mutex> g_loaderUniqueLock(g_loaderLock);
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2023-12-13 01:56:46 +01:00
|
|
|
namespace {
|
|
|
|
|
|
2013-07-07 02:30:08 +02:00
|
|
|
void startupErrorMessage(const std::string& errorStr)
|
|
|
|
|
{
|
2022-02-16 21:11:15 -05:00
|
|
|
fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, "> ERROR: {:s}\n", errorStr);
|
2013-07-25 21:38:28 +02:00
|
|
|
g_loaderSignal.notify_all();
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2023-12-13 01:56:46 +01:00
|
|
|
void mainLoader(ServiceManager* services)
|
2020-11-28 05:43:10 +01:00
|
|
|
{
|
2022-04-13 14:06:08 +00:00
|
|
|
// dispatcher thread
|
2020-11-28 05:43:10 +01:00
|
|
|
g_game.setGameState(GAME_STATE_STARTUP);
|
|
|
|
|
|
|
|
|
|
srand(static_cast<unsigned int>(OTSYS_TIME()));
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
SetConsoleTitle(STATUS_SERVER_NAME);
|
2022-04-13 14:06:08 +00:00
|
|
|
|
2022-03-27 23:29:32 +02:00
|
|
|
// fixes a problem with escape characters not being processed in Windows consoles
|
|
|
|
|
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
|
DWORD dwMode = 0;
|
|
|
|
|
GetConsoleMode(hOut, &dwMode);
|
|
|
|
|
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
|
|
|
|
SetConsoleMode(hOut, dwMode);
|
2020-11-28 05:43:10 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
printServerVersion();
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2018-01-06 06:51:27 -05:00
|
|
|
// check if config.lua or config.lua.dist exist
|
2024-04-27 00:48:25 -03:00
|
|
|
const std::string& configFile = getString(ConfigManager::CONFIG_FILE);
|
2020-11-28 05:43:10 +01:00
|
|
|
std::ifstream c_test("./" + configFile);
|
2018-01-06 06:51:27 -05:00
|
|
|
if (!c_test.is_open()) {
|
|
|
|
|
std::ifstream config_lua_dist("./config.lua.dist");
|
|
|
|
|
if (config_lua_dist.is_open()) {
|
2020-11-28 05:43:10 +01:00
|
|
|
std::cout << ">> copying config.lua.dist to " << configFile << std::endl;
|
|
|
|
|
std::ofstream config_lua(configFile);
|
2018-01-06 06:51:27 -05:00
|
|
|
config_lua << config_lua_dist.rdbuf();
|
|
|
|
|
config_lua.close();
|
|
|
|
|
config_lua_dist.close();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
c_test.close();
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-07 02:30:08 +02:00
|
|
|
// read global config
|
|
|
|
|
std::cout << ">> Loading config" << std::endl;
|
2024-04-27 00:48:25 -03:00
|
|
|
if (!ConfigManager::load()) {
|
2020-11-28 05:43:10 +01:00
|
|
|
startupErrorMessage("Unable to load " + configFile + "!");
|
2013-07-07 02:30:08 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-19 23:21:54 +01:00
|
|
|
#ifdef _WIN32
|
2024-04-27 00:48:25 -03:00
|
|
|
const std::string& defaultPriority = getString(ConfigManager::DEFAULT_PRIORITY);
|
2022-03-17 20:15:08 +01:00
|
|
|
if (caseInsensitiveEqual(defaultPriority, "high")) {
|
2013-07-07 02:30:08 +02:00
|
|
|
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
|
2022-03-17 20:15:08 +01:00
|
|
|
} else if (caseInsensitiveEqual(defaultPriority, "above-normal")) {
|
2013-07-07 02:30:08 +02:00
|
|
|
SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);
|
2015-03-19 21:33:27 +01:00
|
|
|
}
|
2015-03-19 23:21:54 +01:00
|
|
|
#endif
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2022-04-13 14:06:08 +00:00
|
|
|
// set RSA key
|
2022-02-16 21:11:15 -05:00
|
|
|
std::cout << ">> Loading RSA key " << std::endl;
|
2018-10-09 20:02:28 -05:00
|
|
|
try {
|
2024-04-29 05:56:44 -03:00
|
|
|
std::ifstream key{"key.pem"};
|
|
|
|
|
std::string pem{std::istreambuf_iterator<char>{key}, std::istreambuf_iterator<char>{}};
|
|
|
|
|
tfs::rsa::loadPEM(pem);
|
2022-04-13 14:06:08 +00:00
|
|
|
} catch (const std::exception& e) {
|
2018-10-09 20:02:28 -05:00
|
|
|
startupErrorMessage(e.what());
|
|
|
|
|
return;
|
|
|
|
|
}
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2013-07-25 14:44:42 +02:00
|
|
|
std::cout << ">> Establishing database connection..." << std::flush;
|
2013-07-25 21:38:28 +02:00
|
|
|
|
2017-01-01 16:55:12 -02:00
|
|
|
if (!Database::getInstance().connect()) {
|
2013-07-17 02:06:56 +02:00
|
|
|
startupErrorMessage("Failed to connect to database.");
|
2013-07-07 02:30:08 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-03 03:47:47 +01:00
|
|
|
std::cout << " MySQL " << Database::getClientVersion() << std::endl;
|
2013-07-07 02:30:08 +02:00
|
|
|
|
|
|
|
|
// run database manager
|
|
|
|
|
std::cout << ">> Running database manager" << std::endl;
|
|
|
|
|
|
2013-11-03 03:47:47 +01:00
|
|
|
if (!DatabaseManager::isDatabaseSetup()) {
|
2022-04-13 14:06:08 +00:00
|
|
|
startupErrorMessage(
|
|
|
|
|
"The database you have specified in config.lua is empty, please import the schema.sql to your database.");
|
2013-07-07 02:30:08 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2014-12-04 19:59:49 +01:00
|
|
|
g_databaseTasks.start();
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2013-11-03 03:47:47 +01:00
|
|
|
DatabaseManager::updateDatabase();
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2024-04-27 00:48:25 -03:00
|
|
|
if (getBoolean(ConfigManager::OPTIMIZE_DATABASE) && !DatabaseManager::optimizeTables()) {
|
2013-07-07 02:30:08 +02:00
|
|
|
std::cout << "> No tables were optimized." << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-13 14:06:08 +00:00
|
|
|
// load vocations
|
2013-07-07 02:30:08 +02:00
|
|
|
std::cout << ">> Loading vocations" << std::endl;
|
2024-06-01 01:05:43 +02:00
|
|
|
if (std::ifstream is{"data/XML/vocations.xml"}; !g_vocations.loadFromXml(is, "data/XML/vocations.xml")) {
|
2013-07-07 02:30:08 +02:00
|
|
|
startupErrorMessage("Unable to load vocations!");
|
2013-07-25 21:38:28 +02:00
|
|
|
return;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// load item data
|
2021-11-28 15:11:30 -03:00
|
|
|
std::cout << ">> Loading items... ";
|
2017-12-30 01:33:42 +01:00
|
|
|
if (!Item::items.loadFromOtb("data/items/items.otb")) {
|
2013-07-07 02:30:08 +02:00
|
|
|
startupErrorMessage("Unable to load items (OTB)!");
|
2013-07-25 21:38:28 +02:00
|
|
|
return;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
2022-04-13 14:06:08 +00:00
|
|
|
std::cout << fmt::format("OTB v{:d}.{:d}.{:d}", Item::items.majorVersion, Item::items.minorVersion,
|
|
|
|
|
Item::items.buildNumber)
|
|
|
|
|
<< std::endl;
|
2013-07-07 02:30:08 +02:00
|
|
|
|
|
|
|
|
if (!Item::items.loadFromXml()) {
|
|
|
|
|
startupErrorMessage("Unable to load items (XML)!");
|
2013-07-25 21:38:28 +02:00
|
|
|
return;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::cout << ">> Loading script systems" << std::endl;
|
2017-01-01 16:26:09 -02:00
|
|
|
if (!ScriptingManager::getInstance().loadScriptSystems()) {
|
2013-07-07 02:30:08 +02:00
|
|
|
startupErrorMessage("Failed to load script systems");
|
2013-07-25 21:38:28 +02:00
|
|
|
return;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2019-08-07 17:37:29 +02:00
|
|
|
std::cout << ">> Loading lua scripts" << std::endl;
|
|
|
|
|
if (!g_scripts->loadScripts("scripts", false, false)) {
|
|
|
|
|
startupErrorMessage("Failed to load lua scripts");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-07 02:30:08 +02:00
|
|
|
std::cout << ">> Loading monsters" << std::endl;
|
|
|
|
|
if (!g_monsters.loadFromXml()) {
|
|
|
|
|
startupErrorMessage("Unable to load monsters!");
|
2013-07-25 21:38:28 +02:00
|
|
|
return;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2019-08-07 17:37:29 +02:00
|
|
|
std::cout << ">> Loading lua monsters" << std::endl;
|
2024-12-02 10:02:25 +01:00
|
|
|
if (!g_scripts->loadScripts("monster", false, false)) {
|
2019-08-07 17:37:29 +02:00
|
|
|
startupErrorMessage("Failed to load lua monsters");
|
2013-07-25 21:38:28 +02:00
|
|
|
return;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
2019-08-07 17:37:29 +02:00
|
|
|
std::cout << ">> Loading outfits" << std::endl;
|
|
|
|
|
if (!Outfits::getInstance().loadFromXml()) {
|
|
|
|
|
startupErrorMessage("Unable to load outfits!");
|
revscriptsys (#2558)
* initial revscriptsys
creates a new folder called 'scripts' in the data folder.
lua files placed in the 'scripts' or sub folders will automaticly get registered on load with the right setup ofcourse.
Registering happens in the lua file itself, doesn't require xml settings.
lua files can be deactivated by placing a '#' infront of the filename ex: '#positions.lua' it wont get loaded then.
Currently it supports:
-Actions
-TalkActions
-CreatureEvents
-GlobalEvents
-MoveEvents
There is still stuff on the todo list but they'll get added sooner or later.
Co-Authored-By: Sam <thesumm@users.noreply.github.com>
* compiler fixes
added boost-filesystem to appveyor.yml
fixed a few more compiler errors.
* cleanup on script.cpp
removed using namespace for std / boost filesystem
* some fixes
had to make adjustment so lua callbacks and xml settings work alongside and don't crash the server
* small fixes on movements & function additions
Have to revert the function + callback for stepin/stepout & additem/removeitem as it doesn't make sense on the second look and might cause a stackoverflow
I've also reworked the equip/dequip so it doesn't get double calls.
It'll first check if functions return true if not it won't bother to read the callback
accidently used an old spellbook.lua
added :aid(ids) :uid(ids) functions for MoveEvents
* revert to 'using' functions and suggestion of Djarek
Could revert most of movements.h
made the declaration of the static functions more clear
Co-Authored-By: Damian Jarek <djarek@users.noreply.github.com>
* small fixes
removed commentary from movement.cpp
added newline for position.lua
reworked spellbook.lua with table.concat
* Monster handler & other stuff
- MonsterType's can now be created through lua functions.
- added an interface to create MonsterType's easily through lua files (register_monster_type.lua)
- added #example.lua in 'scripts\monsters\'
- renamed action vector functions for a better standard
- renamed _lib folder to lib, this folder gets now loaded when the other lib folder gets loaded aswell
- moved loading lua scripts out of the scriptfilemanager, we need to load everything after monsters etc. is loaded so MonsterType script manipulation does work
- added Loot() & MonsterSpell() metatables
* fix compiler error
* forgot to remove test code
removed test outfit from MonsterType
* small changes
- added createFunctions(class) it virtually creates the get/set functions for the class passed on
- 'events' folder in monsters is excluded from auto parsing files, as we load callbacks for specific monsters which have an eventFile set to 'true' or 'filename' in this folder.
* compiler error fix
* minor change on createFunctions
* stripping path string
* added Game.createMonsterType(name) and small fixes
- added Game.createMonsterType(name)
- reworked MonsterType(name) to return nil if the MonsterType does not exist, so we don't suddenly create a MonsterType if we do not even want to.
- changed reinterpret_cast to static_cast
* config.lua option for console
- added an option to disable scripts console logging, it can be disabled by placing 'showScriptsLogInConsole = false' into config.lua
* initial revscriptsys
creates a new folder called 'scripts' in the data folder.
lua files placed in the 'scripts' or sub folders will automaticly get registered on load with the right setup ofcourse.
Registering happens in the lua file itself, doesn't require xml settings.
lua files can be deactivated by placing a '#' infront of the filename ex: '#positions.lua' it wont get loaded then.
Currently it supports:
-Actions
-TalkActions
-CreatureEvents
-GlobalEvents
-MoveEvents
There is still stuff on the todo list but they'll get added sooner or later.
Co-Authored-By: Sam <thesumm@users.noreply.github.com>
cleanup on script.cpp
removed using namespace for std / boost filesystem
small fixes on movements & function additions
Have to revert the function + callback for stepin/stepout & additem/removeitem as it doesn't make sense on the second look and might cause a stackoverflow
I've also reworked the equip/dequip so it doesn't get double calls.
It'll first check if functions return true if not it won't bother to read the callback
accidently used an old spellbook.lua
added :aid(ids) :uid(ids) functions for MoveEvents
Monster handler & other stuff
- MonsterType's can now be created through lua functions.
- added an interface to create MonsterType's easily through lua files (register_monster_type.lua)
- added #example.lua in 'scripts\monsters\'
- renamed action vector functions for a better standard
- renamed _lib folder to lib, this folder gets now loaded when the other lib folder gets loaded aswell
- moved loading lua scripts out of the scriptfilemanager, we need to load everything after monsters etc. is loaded so MonsterType script manipulation does work
- added Loot() & MonsterSpell() metatables
small changes
- added createFunctions(class) it virtually creates the get/set functions for the class passed on
- 'events' folder in monsters is excluded from auto parsing files, as we load callbacks for specific monsters which have an eventFile set to 'true' or 'filename' in this folder.
stripping path string
added Game.createMonsterType(name) and small fixes
- added Game.createMonsterType(name)
- reworked MonsterType(name) to return nil if the MonsterType does not exist, so we don't suddenly create a MonsterType if we do not even want to.
- changed reinterpret_cast to static_cast
config.lua option for console
- added an option to disable scripts console logging, it can be disabled by placing 'showScriptsLogInConsole = false' into config.lua
2019-04-16 16:33:38 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-25 21:38:28 +02:00
|
|
|
std::cout << ">> Checking world type... " << std::flush;
|
2024-04-27 00:48:25 -03:00
|
|
|
std::string worldType = boost::algorithm::to_lower_copy(getString(ConfigManager::WORLD_TYPE));
|
2013-07-07 02:30:08 +02:00
|
|
|
if (worldType == "pvp") {
|
|
|
|
|
g_game.setWorldType(WORLD_TYPE_PVP);
|
|
|
|
|
} else if (worldType == "no-pvp") {
|
|
|
|
|
g_game.setWorldType(WORLD_TYPE_NO_PVP);
|
|
|
|
|
} else if (worldType == "pvp-enforced") {
|
|
|
|
|
g_game.setWorldType(WORLD_TYPE_PVP_ENFORCED);
|
|
|
|
|
} else {
|
|
|
|
|
std::cout << std::endl;
|
2022-04-13 14:06:08 +00:00
|
|
|
startupErrorMessage(
|
|
|
|
|
fmt::format("Unknown world type: {:s}, valid world types are: pvp, no-pvp and pvp-enforced.",
|
2024-04-27 00:48:25 -03:00
|
|
|
getString(ConfigManager::WORLD_TYPE)));
|
2013-07-25 21:38:28 +02:00
|
|
|
return;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
2022-03-22 02:54:08 +01:00
|
|
|
std::cout << boost::algorithm::to_upper_copy(worldType) << std::endl;
|
2013-07-07 02:30:08 +02:00
|
|
|
|
|
|
|
|
std::cout << ">> Loading map" << std::endl;
|
2024-04-27 00:48:25 -03:00
|
|
|
if (!g_game.loadMainMap(getString(ConfigManager::MAP_NAME))) {
|
2013-07-07 02:30:08 +02:00
|
|
|
startupErrorMessage("Failed to load map");
|
2013-07-25 21:38:28 +02:00
|
|
|
return;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::cout << ">> Initializing gamestate" << std::endl;
|
|
|
|
|
g_game.setGameState(GAME_STATE_INIT);
|
|
|
|
|
|
2013-11-24 20:35:35 +01:00
|
|
|
// Game client protocols
|
2024-04-27 00:48:25 -03:00
|
|
|
services->add<ProtocolGame>(static_cast<uint16_t>(getNumber(ConfigManager::GAME_PORT)));
|
2013-07-07 02:30:08 +02:00
|
|
|
|
|
|
|
|
// OT protocols
|
2024-04-27 00:48:25 -03:00
|
|
|
services->add<ProtocolStatus>(static_cast<uint16_t>(getNumber(ConfigManager::STATUS_PORT)));
|
2013-07-07 02:30:08 +02:00
|
|
|
|
2025-06-28 18:47:00 +02:00
|
|
|
#ifdef HTTP
|
2024-06-01 01:05:43 +02:00
|
|
|
// HTTP server
|
2025-07-10 10:14:06 +02:00
|
|
|
tfs::http::start(getBoolean(ConfigManager::BIND_ONLY_GLOBAL_ADDRESS), getString(ConfigManager::IP),
|
|
|
|
|
getNumber(ConfigManager::HTTP_PORT), getNumber(ConfigManager::HTTP_WORKERS));
|
2025-06-28 18:47:00 +02:00
|
|
|
#endif
|
2024-06-01 01:05:43 +02:00
|
|
|
|
2015-01-19 06:06:14 -06:00
|
|
|
RentPeriod_t rentPeriod;
|
2024-04-27 00:48:25 -03:00
|
|
|
std::string strRentPeriod = boost::algorithm::to_lower_copy(getString(ConfigManager::HOUSE_RENT_PERIOD));
|
2015-01-19 06:06:14 -06:00
|
|
|
|
|
|
|
|
if (strRentPeriod == "yearly") {
|
|
|
|
|
rentPeriod = RENTPERIOD_YEARLY;
|
|
|
|
|
} else if (strRentPeriod == "weekly") {
|
|
|
|
|
rentPeriod = RENTPERIOD_WEEKLY;
|
|
|
|
|
} else if (strRentPeriod == "monthly") {
|
|
|
|
|
rentPeriod = RENTPERIOD_MONTHLY;
|
|
|
|
|
} else if (strRentPeriod == "daily") {
|
|
|
|
|
rentPeriod = RENTPERIOD_DAILY;
|
|
|
|
|
} else {
|
|
|
|
|
rentPeriod = RENTPERIOD_NEVER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_game.map.houses.payHouses(rentPeriod);
|
|
|
|
|
|
2025-10-05 14:16:32 -03:00
|
|
|
tfs::iomarket::checkExpiredOffers();
|
|
|
|
|
tfs::iomarket::updateStatistics();
|
2013-07-07 02:30:08 +02:00
|
|
|
|
|
|
|
|
std::cout << ">> Loaded all modules, server starting up..." << std::endl;
|
|
|
|
|
|
2015-03-19 21:33:27 +01:00
|
|
|
#ifndef _WIN32
|
2013-07-07 02:30:08 +02:00
|
|
|
if (getuid() == 0 || geteuid() == 0) {
|
2022-04-13 14:06:08 +00:00
|
|
|
std::cout << "> Warning: " << STATUS_SERVER_NAME
|
|
|
|
|
<< " has been executed as root user, please consider running it as a normal user." << std::endl;
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
g_game.start(services);
|
|
|
|
|
g_game.setGameState(GAME_STATE_NORMAL);
|
2013-07-10 07:42:05 +02:00
|
|
|
g_loaderSignal.notify_all();
|
2013-07-07 02:30:08 +02:00
|
|
|
}
|
2020-11-28 05:43:10 +01:00
|
|
|
|
2023-12-13 01:56:46 +01:00
|
|
|
[[noreturn]] void badAllocationHandler()
|
2020-11-28 05:43:10 +01:00
|
|
|
{
|
2023-12-13 01:56:46 +01:00
|
|
|
// Use functions that only use stack allocation
|
|
|
|
|
puts("Allocation failed, server out of memory.\nDecrease the size of your map or compile in 64 bits mode.\n");
|
|
|
|
|
getchar();
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
void startServer()
|
|
|
|
|
{
|
|
|
|
|
// Setup bad allocation handler
|
|
|
|
|
std::set_new_handler(badAllocationHandler);
|
|
|
|
|
|
|
|
|
|
ServiceManager serviceManager;
|
2020-11-28 05:43:10 +01:00
|
|
|
|
2023-12-13 01:56:46 +01:00
|
|
|
g_dispatcher.start();
|
|
|
|
|
g_scheduler.start();
|
2020-11-28 05:43:10 +01:00
|
|
|
|
2023-12-13 01:56:46 +01:00
|
|
|
g_dispatcher.addTask([services = &serviceManager]() { mainLoader(services); });
|
|
|
|
|
|
|
|
|
|
g_loaderSignal.wait(g_loaderUniqueLock);
|
|
|
|
|
|
|
|
|
|
if (serviceManager.is_running()) {
|
2024-04-27 00:48:25 -03:00
|
|
|
std::cout << ">> " << getString(ConfigManager::SERVER_NAME) << " Server Online!" << std::endl << std::endl;
|
2023-12-13 01:56:46 +01:00
|
|
|
serviceManager.run();
|
|
|
|
|
} else {
|
|
|
|
|
std::cout << ">> No services running. The server is NOT online." << std::endl;
|
|
|
|
|
g_scheduler.shutdown();
|
|
|
|
|
g_databaseTasks.shutdown();
|
|
|
|
|
g_dispatcher.shutdown();
|
2020-11-28 05:43:10 +01:00
|
|
|
}
|
|
|
|
|
|
2023-12-13 01:56:46 +01:00
|
|
|
g_scheduler.join();
|
|
|
|
|
g_databaseTasks.join();
|
|
|
|
|
g_dispatcher.join();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void printServerVersion()
|
|
|
|
|
{
|
|
|
|
|
#if defined(GIT_RETRIEVED_STATE) && GIT_RETRIEVED_STATE
|
|
|
|
|
std::cout << STATUS_SERVER_NAME << " - Version " << GIT_DESCRIBE << std::endl;
|
|
|
|
|
std::cout << "Git SHA1 " << GIT_SHORT_SHA1 << " dated " << GIT_COMMIT_DATE_ISO8601 << std::endl;
|
|
|
|
|
#if GIT_IS_DIRTY
|
|
|
|
|
std::cout << "*** DIRTY - NOT OFFICIAL RELEASE ***" << std::endl;
|
|
|
|
|
#endif
|
|
|
|
|
#else
|
|
|
|
|
std::cout << STATUS_SERVER_NAME << " - Version " << STATUS_SERVER_VERSION << std::endl;
|
|
|
|
|
#endif
|
|
|
|
|
std::cout << std::endl;
|
|
|
|
|
|
|
|
|
|
std::cout << "Compiled with " << BOOST_COMPILER << std::endl;
|
|
|
|
|
std::cout << "Compiled on " << __DATE__ << ' ' << __TIME__ << " for platform ";
|
|
|
|
|
#if defined(__amd64__) || defined(_M_X64)
|
|
|
|
|
std::cout << "x64" << std::endl;
|
|
|
|
|
#elif defined(__i386__) || defined(_M_IX86) || defined(_X86_)
|
|
|
|
|
std::cout << "x86" << std::endl;
|
|
|
|
|
#elif defined(__arm__)
|
|
|
|
|
std::cout << "ARM" << std::endl;
|
|
|
|
|
#else
|
|
|
|
|
std::cout << "unknown" << std::endl;
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(LUAJIT_VERSION)
|
|
|
|
|
std::cout << "Linked with " << LUAJIT_VERSION << " for Lua support" << std::endl;
|
|
|
|
|
#else
|
|
|
|
|
std::cout << "Linked with " << LUA_RELEASE << " for Lua support" << std::endl;
|
|
|
|
|
#endif
|
|
|
|
|
std::cout << std::endl;
|
|
|
|
|
|
|
|
|
|
std::cout << "A server developed by " << STATUS_SERVER_DEVELOPERS << std::endl;
|
|
|
|
|
std::cout << "Visit our forum for updates, support, and resources: https://otland.net/." << std::endl;
|
|
|
|
|
std::cout << std::endl;
|
2020-11-28 05:43:10 +01:00
|
|
|
}
|