mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 10:31:29 +00:00
[World] World Bootup Consolidation (#2294)
This commit is contained in:
parent
fb2df0e570
commit
c8b3ca53fe
@ -1,5 +1,5 @@
|
|||||||
/* EQEMu: Everquest Server Emulator
|
/* EQEMu: Everquest Server Emulator
|
||||||
|
|
||||||
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
|
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
@ -11,7 +11,7 @@
|
|||||||
are required to give you total support for your newly bought product;
|
are required to give you total support for your newly bought product;
|
||||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
static bool global_dictionary_init = false;
|
static bool global_dictionary_init = false;
|
||||||
void EQ::InitializeDynamicLookups() {
|
void EQ::InitializeDynamicLookups() {
|
||||||
if (global_dictionary_init == true)
|
if (global_dictionary_init)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
constants::InitializeDynamicLookups();
|
constants::InitializeDynamicLookups();
|
||||||
@ -167,7 +167,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
|||||||
ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL,
|
ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL,
|
||||||
ClientUnknown::INULL
|
ClientUnknown::INULL
|
||||||
),
|
),
|
||||||
|
|
||||||
ClientUnknown::INULL,
|
ClientUnknown::INULL,
|
||||||
ClientUnknown::INULL,
|
ClientUnknown::INULL,
|
||||||
ClientUnknown::INULL,
|
ClientUnknown::INULL,
|
||||||
@ -175,7 +175,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
|||||||
ClientUnknown::INULL,
|
ClientUnknown::INULL,
|
||||||
ClientUnknown::INULL,
|
ClientUnknown::INULL,
|
||||||
ClientUnknown::INULL,
|
ClientUnknown::INULL,
|
||||||
|
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
@ -194,7 +194,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
|||||||
Client62::INULL, Client62::INULL, Client62::INULL,
|
Client62::INULL, Client62::INULL, Client62::INULL,
|
||||||
Client62::INULL
|
Client62::INULL
|
||||||
),
|
),
|
||||||
|
|
||||||
Client62::INULL,
|
Client62::INULL,
|
||||||
Client62::INULL,
|
Client62::INULL,
|
||||||
Client62::INULL,
|
Client62::INULL,
|
||||||
@ -202,7 +202,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
|||||||
Client62::INULL,
|
Client62::INULL,
|
||||||
Client62::INULL,
|
Client62::INULL,
|
||||||
Client62::INULL,
|
Client62::INULL,
|
||||||
|
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
@ -221,7 +221,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
|||||||
Titanium::INULL, Titanium::INULL, Titanium::INULL,
|
Titanium::INULL, Titanium::INULL, Titanium::INULL,
|
||||||
Titanium::invtype::OTHER_SIZE
|
Titanium::invtype::OTHER_SIZE
|
||||||
),
|
),
|
||||||
|
|
||||||
Titanium::invslot::EQUIPMENT_BITMASK,
|
Titanium::invslot::EQUIPMENT_BITMASK,
|
||||||
Titanium::invslot::GENERAL_BITMASK,
|
Titanium::invslot::GENERAL_BITMASK,
|
||||||
Titanium::invslot::CURSOR_BITMASK,
|
Titanium::invslot::CURSOR_BITMASK,
|
||||||
@ -229,7 +229,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
|||||||
Titanium::invslot::CORPSE_BITMASK,
|
Titanium::invslot::CORPSE_BITMASK,
|
||||||
Titanium::invbag::SLOT_COUNT,
|
Titanium::invbag::SLOT_COUNT,
|
||||||
Titanium::invaug::SOCKET_COUNT,
|
Titanium::invaug::SOCKET_COUNT,
|
||||||
|
|
||||||
Titanium::inventory::AllowEmptyBagInBag,
|
Titanium::inventory::AllowEmptyBagInBag,
|
||||||
Titanium::inventory::AllowClickCastFromBag,
|
Titanium::inventory::AllowClickCastFromBag,
|
||||||
Titanium::inventory::ConcatenateInvTypeLimbo,
|
Titanium::inventory::ConcatenateInvTypeLimbo,
|
||||||
@ -248,7 +248,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
|||||||
SoF::INULL, SoF::INULL, SoF::INULL,
|
SoF::INULL, SoF::INULL, SoF::INULL,
|
||||||
SoF::invtype::OTHER_SIZE
|
SoF::invtype::OTHER_SIZE
|
||||||
),
|
),
|
||||||
|
|
||||||
SoF::invslot::EQUIPMENT_BITMASK,
|
SoF::invslot::EQUIPMENT_BITMASK,
|
||||||
SoF::invslot::GENERAL_BITMASK,
|
SoF::invslot::GENERAL_BITMASK,
|
||||||
SoF::invslot::CURSOR_BITMASK,
|
SoF::invslot::CURSOR_BITMASK,
|
||||||
@ -256,7 +256,7 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
|
|||||||
SoF::invslot::CORPSE_BITMASK,
|
SoF::invslot::CORPSE_BITMASK,
|
||||||
SoF::invbag::SLOT_COUNT,
|
SoF::invbag::SLOT_COUNT,
|
||||||
SoF::invaug::SOCKET_COUNT,
|
SoF::invaug::SOCKET_COUNT,
|
||||||
|
|
||||||
SoF::inventory::AllowEmptyBagInBag,
|
SoF::inventory::AllowEmptyBagInBag,
|
||||||
SoF::inventory::AllowClickCastFromBag,
|
SoF::inventory::AllowClickCastFromBag,
|
||||||
SoF::inventory::ConcatenateInvTypeLimbo,
|
SoF::inventory::ConcatenateInvTypeLimbo,
|
||||||
@ -763,7 +763,7 @@ void EQ::inventory::InitializeDynamicLookups() {
|
|||||||
// Notes:
|
// Notes:
|
||||||
// - Currently, there are only 3 known expansions that affect inventory-related settings in the clients..
|
// - Currently, there are only 3 known expansions that affect inventory-related settings in the clients..
|
||||||
// -- Expansion::PoR "Prophecy of Ro" - toggles between 24 (set) and 16 (clear) bank slots
|
// -- Expansion::PoR "Prophecy of Ro" - toggles between 24 (set) and 16 (clear) bank slots
|
||||||
// -- Expansion::TBS "The Buried Sea" - toggles slotPowerSource activated (set) and deactivated (clear)
|
// -- Expansion::TBS "The Buried Sea" - toggles slotPowerSource activated (set) and deactivated (clear)
|
||||||
// -- Expansion::HoT "House of Thule" - toggles slotGeneral9/slotGeneral10 activated (set) and deactivated (clear)
|
// -- Expansion::HoT "House of Thule" - toggles slotGeneral9/slotGeneral10 activated (set) and deactivated (clear)
|
||||||
// - Corspe size does not appear to reflect loss of active possessions slots
|
// - Corspe size does not appear to reflect loss of active possessions slots
|
||||||
// - Inspect size does not appear to reflect loss of active equipment slots
|
// - Inspect size does not appear to reflect loss of active equipment slots
|
||||||
@ -772,7 +772,7 @@ void EQ::inventory::InitializeDynamicLookups() {
|
|||||||
// - General9 and General10 slots are activated by GM flag when expansion bit is (clear)
|
// - General9 and General10 slots are activated by GM flag when expansion bit is (clear)
|
||||||
// - Obviously, the client must support the expansion to allow any (set) or override condition
|
// - Obviously, the client must support the expansion to allow any (set) or override condition
|
||||||
|
|
||||||
const uint32 dynamic_check_mask =
|
const uint32 dynamic_check_mask =
|
||||||
(
|
(
|
||||||
EQ::expansions::bitPoR |
|
EQ::expansions::bitPoR |
|
||||||
EQ::expansions::bitTBS |
|
EQ::expansions::bitTBS |
|
||||||
@ -1210,10 +1210,10 @@ void EQ::spells::InitializeDynamicLookups() {
|
|||||||
if (spells_dictionary_init == true)
|
if (spells_dictionary_init == true)
|
||||||
return;
|
return;
|
||||||
spells_dictionary_init = true;
|
spells_dictionary_init = true;
|
||||||
|
|
||||||
if (RuleB(World, UseClientBasedExpansionSettings))
|
if (RuleB(World, UseClientBasedExpansionSettings))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// use static references for now
|
// use static references for now
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1239,7 +1239,7 @@ const EQ::spells::LookupEntry* EQ::spells::DynamicGMLookup(versions::ClientVersi
|
|||||||
client_version = versions::ValidateClientVersion(client_version);
|
client_version = versions::ValidateClientVersion(client_version);
|
||||||
if (spells_dynamic_gm_lookup_entries[static_cast<int>(client_version)])
|
if (spells_dynamic_gm_lookup_entries[static_cast<int>(client_version)])
|
||||||
return spells_dynamic_gm_lookup_entries[static_cast<int>(client_version)].get();
|
return spells_dynamic_gm_lookup_entries[static_cast<int>(client_version)].get();
|
||||||
|
|
||||||
return &spells_static_lookup_entries[static_cast<int>(client_version)];
|
return &spells_static_lookup_entries[static_cast<int>(client_version)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,7 @@ SET(world_sources
|
|||||||
world_console_connection.cpp
|
world_console_connection.cpp
|
||||||
world_server_command_handler.cpp
|
world_server_command_handler.cpp
|
||||||
worlddb.cpp
|
worlddb.cpp
|
||||||
|
world_boot.cpp
|
||||||
world_store.cpp
|
world_store.cpp
|
||||||
zonelist.cpp
|
zonelist.cpp
|
||||||
zoneserver.cpp
|
zoneserver.cpp
|
||||||
@ -68,6 +69,7 @@ SET(world_headers
|
|||||||
world_tcp_connection.h
|
world_tcp_connection.h
|
||||||
world_server_command_handler.h
|
world_server_command_handler.h
|
||||||
worlddb.h
|
worlddb.h
|
||||||
|
world_boot.h
|
||||||
world_event_scheduler.h
|
world_event_scheduler.h
|
||||||
world_store.h
|
world_store.h
|
||||||
zonelist.h
|
zonelist.h
|
||||||
|
|||||||
524
world/main.cpp
524
world/main.cpp
@ -56,12 +56,8 @@
|
|||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
#include "../common/unix.h"
|
#include "../common/unix.h"
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/ipc.h>
|
|
||||||
#include <sys/sem.h>
|
#include <sys/sem.h>
|
||||||
#include <sys/shm.h>
|
|
||||||
|
|
||||||
#if not defined (FREEBSD) && not defined (DARWIN)
|
#if not defined (FREEBSD) && not defined (DARWIN)
|
||||||
union semun {
|
union semun {
|
||||||
@ -76,16 +72,13 @@ union semun {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../common/patches/patches.h"
|
#include "../common/patches/patches.h"
|
||||||
#include "../common/random.h"
|
|
||||||
#include "zoneserver.h"
|
#include "zoneserver.h"
|
||||||
#include "login_server.h"
|
#include "login_server.h"
|
||||||
#include "login_server_list.h"
|
#include "login_server_list.h"
|
||||||
#include "world_config.h"
|
#include "world_config.h"
|
||||||
#include "zoneserver.h"
|
|
||||||
#include "zonelist.h"
|
#include "zonelist.h"
|
||||||
#include "clientlist.h"
|
#include "clientlist.h"
|
||||||
#include "launcher_list.h"
|
#include "launcher_list.h"
|
||||||
#include "wguild_mgr.h"
|
|
||||||
#include "lfplist.h"
|
#include "lfplist.h"
|
||||||
#include "adventure_manager.h"
|
#include "adventure_manager.h"
|
||||||
#include "ucs.h"
|
#include "ucs.h"
|
||||||
@ -95,18 +88,13 @@ union semun {
|
|||||||
#include "dynamic_zone_manager.h"
|
#include "dynamic_zone_manager.h"
|
||||||
#include "expedition_database.h"
|
#include "expedition_database.h"
|
||||||
|
|
||||||
#include "../common/net/servertalk_server.h"
|
|
||||||
#include "../zone/data_bucket.h"
|
|
||||||
#include "world_server_command_handler.h"
|
#include "world_server_command_handler.h"
|
||||||
#include "../common/content/world_content_service.h"
|
#include "../common/content/world_content_service.h"
|
||||||
#include "../common/repositories/character_task_timers_repository.h"
|
#include "../common/repositories/character_task_timers_repository.h"
|
||||||
#include "../common/repositories/merchantlist_temp_repository.h"
|
|
||||||
#include "world_store.h"
|
#include "world_store.h"
|
||||||
#include "world_event_scheduler.h"
|
#include "world_event_scheduler.h"
|
||||||
#include "shared_task_manager.h"
|
#include "shared_task_manager.h"
|
||||||
#include "../common/ip_util.h"
|
#include "world_boot.h"
|
||||||
#include "../common/http/httplib.h"
|
|
||||||
#include "../common/http/uri.h"
|
|
||||||
|
|
||||||
WorldStore world_store;
|
WorldStore world_store;
|
||||||
ClientList client_list;
|
ClientList client_list;
|
||||||
@ -129,7 +117,6 @@ WorldContentService content_service;
|
|||||||
WebInterfaceList web_interface;
|
WebInterfaceList web_interface;
|
||||||
|
|
||||||
void CatchSignal(int sig_num);
|
void CatchSignal(int sig_num);
|
||||||
void CheckForServerScript(bool force_download = false);
|
|
||||||
|
|
||||||
inline void UpdateWindowTitle(std::string new_title)
|
inline void UpdateWindowTitle(std::string new_title)
|
||||||
{
|
{
|
||||||
@ -138,148 +125,6 @@ inline void UpdateWindowTitle(std::string new_title)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadDatabaseConnections()
|
|
||||||
{
|
|
||||||
LogInfo(
|
|
||||||
"Connecting to MySQL [{}]@[{}]:[{}]",
|
|
||||||
Config->DatabaseUsername.c_str(),
|
|
||||||
Config->DatabaseHost.c_str(),
|
|
||||||
Config->DatabasePort
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!database.Connect(
|
|
||||||
Config->DatabaseHost.c_str(),
|
|
||||||
Config->DatabaseUsername.c_str(),
|
|
||||||
Config->DatabasePassword.c_str(),
|
|
||||||
Config->DatabaseDB.c_str(),
|
|
||||||
Config->DatabasePort
|
|
||||||
)) {
|
|
||||||
LogError("Cannot continue without a database connection");
|
|
||||||
|
|
||||||
std::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Multi-tenancy: Content database
|
|
||||||
*/
|
|
||||||
if (!Config->ContentDbHost.empty()) {
|
|
||||||
if (!content_db.Connect(
|
|
||||||
Config->ContentDbHost.c_str(),
|
|
||||||
Config->ContentDbUsername.c_str(),
|
|
||||||
Config->ContentDbPassword.c_str(),
|
|
||||||
Config->ContentDbName.c_str(),
|
|
||||||
Config->ContentDbPort,
|
|
||||||
"content"
|
|
||||||
)) {
|
|
||||||
LogError("Cannot continue without a content database connection");
|
|
||||||
std::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
content_db.SetMysql(database.getMySQL());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckForXMLConfigUpgrade()
|
|
||||||
{
|
|
||||||
if (!std::ifstream("eqemu_config.json") && std::ifstream("eqemu_config.xml")) {
|
|
||||||
CheckForServerScript(true);
|
|
||||||
if (system("perl eqemu_server.pl convert_xml")) {}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
CheckForServerScript();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadServerConfig()
|
|
||||||
{
|
|
||||||
LogInfo("Loading server configuration");
|
|
||||||
if (!WorldConfig::LoadConfig()) {
|
|
||||||
LogError("Loading server configuration failed");
|
|
||||||
std::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterLoginservers()
|
|
||||||
{
|
|
||||||
if (Config->LoginCount == 0) {
|
|
||||||
if (Config->LoginHost.length()) {
|
|
||||||
loginserverlist.Add(
|
|
||||||
Config->LoginHost.c_str(),
|
|
||||||
Config->LoginPort,
|
|
||||||
Config->LoginAccount.c_str(),
|
|
||||||
Config->LoginPassword.c_str(),
|
|
||||||
Config->LoginLegacy
|
|
||||||
);
|
|
||||||
LogInfo("Added loginserver [{}]:[{}]", Config->LoginHost.c_str(), Config->LoginPort);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LinkedList<LoginConfig *> loginlist = Config->loginlist;
|
|
||||||
LinkedListIterator<LoginConfig *> iterator(loginlist);
|
|
||||||
iterator.Reset();
|
|
||||||
while (iterator.MoreElements()) {
|
|
||||||
if (iterator.GetData()->LoginHost.length()) {
|
|
||||||
loginserverlist.Add(
|
|
||||||
iterator.GetData()->LoginHost.c_str(),
|
|
||||||
iterator.GetData()->LoginPort,
|
|
||||||
iterator.GetData()->LoginAccount.c_str(),
|
|
||||||
iterator.GetData()->LoginPassword.c_str(),
|
|
||||||
iterator.GetData()->LoginLegacy
|
|
||||||
);
|
|
||||||
|
|
||||||
LogInfo(
|
|
||||||
"Added loginserver [{}]:[{}]",
|
|
||||||
iterator.GetData()->LoginHost.c_str(),
|
|
||||||
iterator.GetData()->LoginPort
|
|
||||||
);
|
|
||||||
}
|
|
||||||
iterator.Advance();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GMSayHookCallBackProcessWorld(uint16 log_category, std::string message)
|
|
||||||
{
|
|
||||||
// Cut messages down to 4000 max to prevent client crash
|
|
||||||
if (!message.empty()) {
|
|
||||||
message = message.substr(0, 4000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace Occurrences of % or MessageStatus will crash
|
|
||||||
Strings::FindReplace(message, std::string("%"), std::string("."));
|
|
||||||
|
|
||||||
if (message.find('\n') != std::string::npos) {
|
|
||||||
auto message_split = Strings::Split(message, '\n');
|
|
||||||
|
|
||||||
for (size_t iter = 0; iter < message_split.size(); ++iter) {
|
|
||||||
zoneserver_list.SendEmoteMessage(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
AccountStatus::QuestTroupe,
|
|
||||||
LogSys.GetGMSayColorFromCategory(log_category),
|
|
||||||
fmt::format(
|
|
||||||
" {}{}",
|
|
||||||
(iter == 0 ? " ---" : ""),
|
|
||||||
message_split[iter]
|
|
||||||
).c_str()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
zoneserver_list.SendEmoteMessage(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
AccountStatus::QuestTroupe,
|
|
||||||
LogSys.GetGMSayColorFromCategory(log_category),
|
|
||||||
"%s",
|
|
||||||
message.c_str()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* World process entrypoint
|
* World process entrypoint
|
||||||
*
|
*
|
||||||
@ -293,35 +138,15 @@ int main(int argc, char **argv)
|
|||||||
LogSys.LoadLogSettingsDefaults();
|
LogSys.LoadLogSettingsDefaults();
|
||||||
set_exception_handler();
|
set_exception_handler();
|
||||||
|
|
||||||
/**
|
if (!WorldBoot::LoadServerConfig()) {
|
||||||
* Database version
|
return 0;
|
||||||
*/
|
|
||||||
uint32 database_version = CURRENT_BINARY_DATABASE_VERSION;
|
|
||||||
uint32 bots_database_version = CURRENT_BINARY_BOTS_DATABASE_VERSION;
|
|
||||||
if (argc >= 2) {
|
|
||||||
if (strcasecmp(argv[1], "db_version") == 0) {
|
|
||||||
std::cout << "Binary Database Version: " << database_version << " : " << bots_database_version << std::endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
if (WorldBoot::HandleCommandInput(argc, argv)) {
|
||||||
* Command handler
|
return 0;
|
||||||
*/
|
|
||||||
if (argc > 1) {
|
|
||||||
LogSys.SilenceConsoleLogging();
|
|
||||||
|
|
||||||
WorldConfig::LoadConfig();
|
|
||||||
Config = WorldConfig::get();
|
|
||||||
|
|
||||||
LoadDatabaseConnections();
|
|
||||||
LogSys.EnableConsoleLogging();
|
|
||||||
|
|
||||||
WorldserverCommandHandler::CommandHandler(argc, argv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckForXMLConfigUpgrade();
|
WorldBoot::CheckForXMLConfigUpgrade();
|
||||||
LoadServerConfig();
|
|
||||||
|
|
||||||
Config = WorldConfig::get();
|
Config = WorldConfig::get();
|
||||||
|
|
||||||
@ -344,190 +169,30 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RegisterLoginservers();
|
WorldBoot::RegisterLoginservers();
|
||||||
LoadDatabaseConnections();
|
WorldBoot::LoadDatabaseConnections();
|
||||||
|
if (!WorldBoot::DatabaseLoadRoutines(argc, argv)) {
|
||||||
guild_mgr.SetDatabase(&database);
|
return 1;
|
||||||
|
|
||||||
// logging system init
|
|
||||||
auto logging = LogSys.SetDatabase(&database)
|
|
||||||
->LoadLogDatabaseSettings();
|
|
||||||
|
|
||||||
if (RuleB(Logging, WorldGMSayLogging)) {
|
|
||||||
logging->SetGMSayHandler(&GMSayHookCallBackProcessWorld);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logging->StartFileLogs();
|
// timers
|
||||||
|
Timer PurgeInstanceTimer(450000);
|
||||||
/**
|
PurgeInstanceTimer.Start(450000);
|
||||||
* Parse simple CLI passes
|
|
||||||
*/
|
|
||||||
bool ignore_db = false;
|
|
||||||
if (argc >= 2) {
|
|
||||||
if (strcasecmp(argv[1], "ignore_db") == 0) {
|
|
||||||
ignore_db = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cerr << "Error, unknown command line option" << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ignore_db) {
|
|
||||||
LogInfo("Checking Database Conversions");
|
|
||||||
database.CheckDatabaseConversions();
|
|
||||||
}
|
|
||||||
LogInfo("Loading variables");
|
|
||||||
database.LoadVariables();
|
|
||||||
|
|
||||||
std::string hotfix_name;
|
|
||||||
if (database.GetVariable("hotfix_name", hotfix_name)) {
|
|
||||||
if (!hotfix_name.empty()) {
|
|
||||||
LogInfo("Current hotfix in use: [{}]", hotfix_name.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LogInfo("Purging expired data buckets");
|
|
||||||
database.PurgeAllDeletedDataBuckets();
|
|
||||||
|
|
||||||
LogInfo("Loading zones");
|
|
||||||
|
|
||||||
world_store.LoadZones();
|
|
||||||
|
|
||||||
LogInfo("Clearing groups");
|
|
||||||
database.ClearGroup();
|
|
||||||
LogInfo("Clearing raids");
|
|
||||||
database.ClearRaid();
|
|
||||||
database.ClearRaidDetails();
|
|
||||||
database.ClearRaidLeader();
|
|
||||||
LogInfo("Clearing inventory snapshots");
|
|
||||||
database.ClearInvSnapshots();
|
|
||||||
LogInfo("Loading items");
|
|
||||||
|
|
||||||
if (!content_db.LoadItems(hotfix_name)) {
|
|
||||||
LogError("Error: Could not load item data. But ignoring");
|
|
||||||
}
|
|
||||||
|
|
||||||
LogInfo("Loading skill caps");
|
|
||||||
if (!content_db.LoadSkillCaps(std::string(hotfix_name))) {
|
|
||||||
LogError("Error: Could not load skill cap data. But ignoring");
|
|
||||||
}
|
|
||||||
|
|
||||||
LogInfo("Loading guilds");
|
|
||||||
guild_mgr.LoadGuilds();
|
|
||||||
|
|
||||||
//rules:
|
|
||||||
{
|
|
||||||
if (!RuleManager::Instance()->UpdateOrphanedRules(&database)) {
|
|
||||||
LogInfo("Failed to process 'Orphaned Rules' update operation.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!RuleManager::Instance()->UpdateInjectedRules(&database, "default")) {
|
|
||||||
LogInfo("Failed to process 'Injected Rules' for ruleset 'default' update operation.");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string tmp;
|
|
||||||
if (database.GetVariable("RuleSet", tmp)) {
|
|
||||||
LogInfo("Loading rule set [{}]", tmp.c_str());
|
|
||||||
|
|
||||||
if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str(), false)) {
|
|
||||||
LogInfo("Failed to load ruleset [{}], falling back to defaults", tmp.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
if (!RuleManager::Instance()->LoadRules(&database, "default", false)) {
|
|
||||||
LogInfo("No rule set configured, using default rules");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LogInfo("Loaded default rule set [default]", tmp.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!RuleManager::Instance()->RestoreRuleNotes(&database)) {
|
|
||||||
LogInfo("Failed to process 'Restore Rule Notes' update operation.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EQ::InitializeDynamicLookups();
|
|
||||||
LogInfo("Initialized dynamic dictionary entries");
|
|
||||||
|
|
||||||
if (RuleB(World, ClearTempMerchantlist)) {
|
|
||||||
LogInfo("Clearing temporary merchant lists");
|
|
||||||
database.ClearMerchantTemp();
|
|
||||||
}
|
|
||||||
|
|
||||||
LogInfo("Loading EQ time of day");
|
|
||||||
TimeOfDay_Struct eqTime;
|
|
||||||
time_t realtime;
|
|
||||||
eqTime = database.LoadTime(realtime);
|
|
||||||
zoneserver_list.worldclock.SetCurrentEQTimeOfDay(eqTime, realtime);
|
|
||||||
Timer EQTimeTimer(600000);
|
Timer EQTimeTimer(600000);
|
||||||
EQTimeTimer.Start(600000);
|
EQTimeTimer.Start(600000);
|
||||||
|
|
||||||
|
// global loads
|
||||||
LogInfo("Loading launcher list");
|
LogInfo("Loading launcher list");
|
||||||
launcher_list.LoadList();
|
launcher_list.LoadList();
|
||||||
|
zoneserver_list.Init();
|
||||||
LogInfo("Deleted [{}] stale player corpses from database", database.DeleteStalePlayerCorpses());
|
|
||||||
|
|
||||||
LogInfo("Loading adventures");
|
|
||||||
if (!adventure_manager.LoadAdventureTemplates()) {
|
|
||||||
LogInfo("Unable to load adventure templates");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!adventure_manager.LoadAdventureEntries()) {
|
|
||||||
LogInfo("Unable to load adventure templates");
|
|
||||||
}
|
|
||||||
|
|
||||||
adventure_manager.LoadLeaderboardInfo();
|
|
||||||
|
|
||||||
LogInfo("Purging expired dynamic zones and members");
|
|
||||||
dynamic_zone_manager.PurgeExpiredDynamicZones();
|
|
||||||
|
|
||||||
LogInfo("Purging expired expeditions");
|
|
||||||
ExpeditionDatabase::PurgeExpiredExpeditions();
|
|
||||||
ExpeditionDatabase::PurgeExpiredCharacterLockouts();
|
|
||||||
|
|
||||||
LogInfo("Purging expired character task timers");
|
|
||||||
CharacterTaskTimersRepository::DeleteWhere(database, "expire_time <= NOW()");
|
|
||||||
|
|
||||||
LogInfo("Purging expired instances");
|
|
||||||
database.PurgeExpiredInstances();
|
|
||||||
|
|
||||||
Timer PurgeInstanceTimer(450000);
|
|
||||||
PurgeInstanceTimer.Start(450000);
|
|
||||||
|
|
||||||
LogInfo("Loading dynamic zones");
|
|
||||||
dynamic_zone_manager.CacheAllFromDatabase();
|
|
||||||
|
|
||||||
LogInfo("Loading char create info");
|
|
||||||
content_db.LoadCharacterCreateAllocations();
|
|
||||||
content_db.LoadCharacterCreateCombos();
|
|
||||||
|
|
||||||
LogInfo("Initializing [EventScheduler]");
|
|
||||||
event_scheduler.SetDatabase(&database)->LoadScheduledEvents();
|
|
||||||
|
|
||||||
LogInfo("Initializing [WorldContentService]");
|
|
||||||
content_service.SetDatabase(&database)
|
|
||||||
->SetExpansionContext()
|
|
||||||
->ReloadContentFlags();
|
|
||||||
|
|
||||||
LogInfo("Initializing [SharedTaskManager]");
|
|
||||||
shared_task_manager.SetDatabase(&database)
|
|
||||||
->SetContentDatabase(&content_db)
|
|
||||||
->LoadTaskData()
|
|
||||||
->LoadSharedTaskState();
|
|
||||||
|
|
||||||
shared_task_manager.PurgeExpiredSharedTasks();
|
|
||||||
|
|
||||||
std::unique_ptr<EQ::Net::ConsoleServer> console;
|
std::unique_ptr<EQ::Net::ConsoleServer> console;
|
||||||
if (Config->TelnetEnabled) {
|
if (Config->TelnetEnabled) {
|
||||||
LogInfo("Console (TCP) listener started");
|
LogInfo("Console (TCP) listener started on [{}:{}]", Config->TelnetIP, Config->TelnetTCPPort);
|
||||||
console = std::make_unique<EQ::Net::ConsoleServer>(Config->TelnetIP, Config->TelnetTCPPort);
|
console = std::make_unique<EQ::Net::ConsoleServer>(Config->TelnetIP, Config->TelnetTCPPort);
|
||||||
RegisterConsoleFunctions(console);
|
RegisterConsoleFunctions(console);
|
||||||
}
|
}
|
||||||
|
|
||||||
zoneserver_list.Init();
|
|
||||||
std::unique_ptr<EQ::Net::ServertalkServer> server_connection;
|
std::unique_ptr<EQ::Net::ServertalkServer> server_connection;
|
||||||
server_connection = std::make_unique<EQ::Net::ServertalkServer>();
|
server_connection = std::make_unique<EQ::Net::ServertalkServer>();
|
||||||
|
|
||||||
@ -536,32 +201,44 @@ int main(int argc, char **argv)
|
|||||||
server_opts.ipv6 = false;
|
server_opts.ipv6 = false;
|
||||||
server_opts.credentials = Config->SharedKey;
|
server_opts.credentials = Config->SharedKey;
|
||||||
server_connection->Listen(server_opts);
|
server_connection->Listen(server_opts);
|
||||||
LogInfo("Server (TCP) listener started");
|
LogInfo("Server (TCP) listener started on port [{}]", Config->WorldTCPPort);
|
||||||
|
|
||||||
server_connection->OnConnectionIdentified(
|
server_connection->OnConnectionIdentified(
|
||||||
"Zone", [&console](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
"Zone", [&console](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
||||||
LogInfo("New Zone Server connection from [{2}] at [{0}:{1}]",
|
|
||||||
connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID());
|
|
||||||
|
|
||||||
numzones++;
|
numzones++;
|
||||||
zoneserver_list.Add(new ZoneServer(connection, console.get()));
|
zoneserver_list.Add(new ZoneServer(connection, console.get()));
|
||||||
|
|
||||||
|
LogInfo(
|
||||||
|
"New Zone Server connection from [{}] at [{}:{}] zone_count ({})",
|
||||||
|
connection->Handle()->RemoteIP(),
|
||||||
|
connection->Handle()->RemotePort(),
|
||||||
|
connection->GetUUID(),
|
||||||
|
numzones
|
||||||
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
server_connection->OnConnectionRemoved(
|
server_connection->OnConnectionRemoved(
|
||||||
"Zone", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
"Zone", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
||||||
LogInfo("Removed Zone Server connection from [{0}]",
|
|
||||||
connection->GetUUID());
|
|
||||||
|
|
||||||
numzones--;
|
numzones--;
|
||||||
zoneserver_list.Remove(connection->GetUUID());
|
zoneserver_list.Remove(connection->GetUUID());
|
||||||
|
|
||||||
|
LogInfo(
|
||||||
|
"Removed Zone Server connection from [{}] total zone_count [{}]",
|
||||||
|
connection->GetUUID(),
|
||||||
|
numzones
|
||||||
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
server_connection->OnConnectionIdentified(
|
server_connection->OnConnectionIdentified(
|
||||||
"Launcher", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
"Launcher", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
||||||
LogInfo("New Launcher connection from [{2}] at [{0}:{1}]",
|
LogInfo(
|
||||||
connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID());
|
"New Launcher connection from [{}] at [{}:{}]",
|
||||||
|
connection->Handle()->RemoteIP(),
|
||||||
|
connection->Handle()->RemotePort(),
|
||||||
|
connection->GetUUID()
|
||||||
|
);
|
||||||
|
|
||||||
launcher_list.Add(connection);
|
launcher_list.Add(connection);
|
||||||
}
|
}
|
||||||
@ -569,8 +246,10 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
server_connection->OnConnectionRemoved(
|
server_connection->OnConnectionRemoved(
|
||||||
"Launcher", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
"Launcher", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
||||||
LogInfo("Removed Launcher connection from [{0}]",
|
LogInfo(
|
||||||
connection->GetUUID());
|
"Removed Launcher connection from [{0}]",
|
||||||
|
connection->GetUUID()
|
||||||
|
);
|
||||||
|
|
||||||
launcher_list.Remove(connection);
|
launcher_list.Remove(connection);
|
||||||
}
|
}
|
||||||
@ -578,8 +257,11 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
server_connection->OnConnectionIdentified(
|
server_connection->OnConnectionIdentified(
|
||||||
"QueryServ", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
"QueryServ", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
||||||
LogInfo("New Query Server connection from [{2}] at [{0}:{1}]",
|
LogInfo(
|
||||||
connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID());
|
"New Query Server connection from [{}] at [{}:{}]",
|
||||||
|
connection->Handle()->RemoteIP(),
|
||||||
|
connection->Handle()->RemotePort(),
|
||||||
|
connection->GetUUID());
|
||||||
|
|
||||||
QSLink.AddConnection(connection);
|
QSLink.AddConnection(connection);
|
||||||
}
|
}
|
||||||
@ -587,8 +269,10 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
server_connection->OnConnectionRemoved(
|
server_connection->OnConnectionRemoved(
|
||||||
"QueryServ", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
"QueryServ", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
||||||
LogInfo("Removed Query Server connection from [{0}]",
|
LogInfo(
|
||||||
connection->GetUUID());
|
"Removed Query Server connection from [{}]",
|
||||||
|
connection->GetUUID()
|
||||||
|
);
|
||||||
|
|
||||||
QSLink.RemoveConnection(connection);
|
QSLink.RemoveConnection(connection);
|
||||||
}
|
}
|
||||||
@ -596,8 +280,12 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
server_connection->OnConnectionIdentified(
|
server_connection->OnConnectionIdentified(
|
||||||
"UCS", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
"UCS", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
||||||
LogInfo("New UCS Server connection from [{2}] at [{0}:{1}]",
|
LogInfo(
|
||||||
connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID());
|
"New UCS Server connection from [{}] at [{}:{}]",
|
||||||
|
connection->Handle()->RemoteIP(),
|
||||||
|
connection->Handle()->RemotePort(),
|
||||||
|
connection->GetUUID()
|
||||||
|
);
|
||||||
|
|
||||||
UCSLink.SetConnection(connection);
|
UCSLink.SetConnection(connection);
|
||||||
|
|
||||||
@ -607,7 +295,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
server_connection->OnConnectionRemoved(
|
server_connection->OnConnectionRemoved(
|
||||||
"UCS", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
"UCS", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
||||||
LogInfo("Connection lost from UCS Server [{0}]", connection->GetUUID());
|
LogInfo("Connection lost from UCS Server [{}]", connection->GetUUID());
|
||||||
|
|
||||||
auto ucs_connection = UCSLink.GetConnection();
|
auto ucs_connection = UCSLink.GetConnection();
|
||||||
|
|
||||||
@ -621,8 +309,12 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
server_connection->OnConnectionIdentified(
|
server_connection->OnConnectionIdentified(
|
||||||
"WebInterface", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
"WebInterface", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
||||||
LogInfo("New WebInterface Server connection from [{2}] at [{0}:{1}]",
|
LogInfo(
|
||||||
connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID());
|
"New WebInterface Server connection from [{}] at [{}:{}]",
|
||||||
|
connection->Handle()->RemoteIP(),
|
||||||
|
connection->Handle()->RemotePort(),
|
||||||
|
connection->GetUUID()
|
||||||
|
);
|
||||||
|
|
||||||
web_interface.AddConnection(connection);
|
web_interface.AddConnection(connection);
|
||||||
}
|
}
|
||||||
@ -630,14 +322,16 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
server_connection->OnConnectionRemoved(
|
server_connection->OnConnectionRemoved(
|
||||||
"WebInterface", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
"WebInterface", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> connection) {
|
||||||
LogInfo("Removed WebInterface Server connection from [{0}]",
|
LogInfo(
|
||||||
connection->GetUUID());
|
"Removed WebInterface Server connection from [{}]",
|
||||||
|
connection->GetUUID()
|
||||||
|
);
|
||||||
|
|
||||||
web_interface.RemoveConnection(connection);
|
web_interface.RemoveConnection(connection);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
WorldConfig::CheckForPossibleConfigurationIssues();
|
WorldBoot::CheckForPossibleConfigurationIssues();
|
||||||
|
|
||||||
EQStreamManagerInterfaceOptions opts(9000, false, false);
|
EQStreamManagerInterfaceOptions opts(9000, false, false);
|
||||||
opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS);
|
opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS);
|
||||||
@ -664,7 +358,11 @@ int main(int argc, char **argv)
|
|||||||
eqsm.OnNewConnection(
|
eqsm.OnNewConnection(
|
||||||
[&stream_identifier](std::shared_ptr<EQ::Net::EQStream> stream) {
|
[&stream_identifier](std::shared_ptr<EQ::Net::EQStream> stream) {
|
||||||
stream_identifier.AddStream(stream);
|
stream_identifier.AddStream(stream);
|
||||||
LogInfo("New connection from IP {}:{}", long2ip(stream->GetRemoteIP()), ntohs(stream->GetRemotePort()));
|
LogInfo(
|
||||||
|
"New [EverQuest Client] connection from IP [{}:{}]",
|
||||||
|
long2ip(stream->GetRemoteIP()),
|
||||||
|
ntohs(stream->GetRemotePort())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -736,9 +434,9 @@ int main(int argc, char **argv)
|
|||||||
database.ping();
|
database.ping();
|
||||||
content_db.ping();
|
content_db.ping();
|
||||||
|
|
||||||
std::string window_title = StringFormat(
|
std::string window_title = fmt::format(
|
||||||
"World: %s Clients: %i",
|
"World [{}] Clients [{}]",
|
||||||
Config->LongName.c_str(),
|
Config->LongName,
|
||||||
client_list.GetClientCount()
|
client_list.GetClientCount()
|
||||||
);
|
);
|
||||||
UpdateWindowTitle(window_title);
|
UpdateWindowTitle(window_title);
|
||||||
@ -762,73 +460,3 @@ void CatchSignal(int sig_num)
|
|||||||
LogInfo("Caught signal [{}]", sig_num);
|
LogInfo("Caught signal [{}]", sig_num);
|
||||||
RunLoops = false;
|
RunLoops = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateWindowTitle(char *iNewTitle)
|
|
||||||
{
|
|
||||||
#ifdef _WINDOWS
|
|
||||||
char tmp[500];
|
|
||||||
if (iNewTitle) {
|
|
||||||
snprintf(tmp, sizeof(tmp), "World: %s", iNewTitle);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
snprintf(tmp, sizeof(tmp), "World");
|
|
||||||
}
|
|
||||||
SetConsoleTitle(tmp);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_file_size(const std::string& filename) // path to file
|
|
||||||
{
|
|
||||||
FILE *p_file = NULL;
|
|
||||||
p_file = fopen(filename.c_str(),"rb");
|
|
||||||
fseek(p_file,0,SEEK_END);
|
|
||||||
int size = ftell(p_file);
|
|
||||||
fclose(p_file);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckForServerScript(bool force_download)
|
|
||||||
{
|
|
||||||
const std::string file = "eqemu_server.pl";
|
|
||||||
std::ifstream f(file);
|
|
||||||
|
|
||||||
/* Fetch EQEmu Server script */
|
|
||||||
if (!f || get_file_size(file) < 100 || force_download) {
|
|
||||||
|
|
||||||
if (force_download) {
|
|
||||||
std::remove("eqemu_server.pl");
|
|
||||||
} /* Delete local before fetch */
|
|
||||||
|
|
||||||
std::cout << "Pulling down EQEmu Server Maintenance Script (eqemu_server.pl)..." << std::endl;
|
|
||||||
|
|
||||||
// http get request
|
|
||||||
uri u("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl");
|
|
||||||
|
|
||||||
httplib::Client r(
|
|
||||||
fmt::format(
|
|
||||||
"{}://{}",
|
|
||||||
u.get_scheme(),
|
|
||||||
u.get_host()
|
|
||||||
).c_str()
|
|
||||||
);
|
|
||||||
|
|
||||||
r.set_connection_timeout(1, 0);
|
|
||||||
r.set_read_timeout(1, 0);
|
|
||||||
r.set_write_timeout(1, 0);
|
|
||||||
|
|
||||||
if (auto res = r.Get(u.get_path().c_str())) {
|
|
||||||
if (res->status == 200) {
|
|
||||||
// write file
|
|
||||||
std::ofstream out("eqemu_server.pl");
|
|
||||||
out << res->body;
|
|
||||||
out.close();
|
|
||||||
#ifdef _WIN32
|
|
||||||
#else
|
|
||||||
system("chmod 755 eqemu_server.pl");
|
|
||||||
system("chmod +x eqemu_server.pl");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
641
world/world_boot.cpp
Normal file
641
world/world_boot.cpp
Normal file
@ -0,0 +1,641 @@
|
|||||||
|
#include "../common/content/world_content_service.h"
|
||||||
|
#include "../common/emu_constants.h"
|
||||||
|
#include "../common/eqemu_logsys.h"
|
||||||
|
#include "../common/http/httplib.h"
|
||||||
|
#include "../common/http/uri.h"
|
||||||
|
#include "../common/net/console_server.h"
|
||||||
|
#include "../common/net/servertalk_server.h"
|
||||||
|
#include "../common/repositories/character_task_timers_repository.h"
|
||||||
|
#include "../common/rulesys.h"
|
||||||
|
#include "../common/strings.h"
|
||||||
|
#include "adventure_manager.h"
|
||||||
|
#include "dynamic_zone_manager.h"
|
||||||
|
#include "expedition_database.h"
|
||||||
|
#include "login_server_list.h"
|
||||||
|
#include "shared_task_manager.h"
|
||||||
|
#include "ucs.h"
|
||||||
|
#include "wguild_mgr.h"
|
||||||
|
#include "world_boot.h"
|
||||||
|
#include "world_config.h"
|
||||||
|
#include "world_event_scheduler.h"
|
||||||
|
#include "world_server_command_handler.h"
|
||||||
|
#include "world_store.h"
|
||||||
|
#include "worlddb.h"
|
||||||
|
#include "zonelist.h"
|
||||||
|
#include "zoneserver.h"
|
||||||
|
#include "../common/ip_util.h"
|
||||||
|
|
||||||
|
extern ZSList zoneserver_list;
|
||||||
|
extern WorldConfig Config;
|
||||||
|
|
||||||
|
void WorldBoot::GMSayHookCallBackProcessWorld(uint16 log_category, std::string message)
|
||||||
|
{
|
||||||
|
// Cut messages down to 4000 max to prevent client crash
|
||||||
|
if (!message.empty()) {
|
||||||
|
message = message.substr(0, 4000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace Occurrences of % or MessageStatus will crash
|
||||||
|
Strings::FindReplace(message, std::string("%"), std::string("."));
|
||||||
|
|
||||||
|
if (message.find('\n') != std::string::npos) {
|
||||||
|
auto message_split = Strings::Split(message, '\n');
|
||||||
|
|
||||||
|
for (size_t iter = 0; iter < message_split.size(); ++iter) {
|
||||||
|
zoneserver_list.SendEmoteMessage(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
AccountStatus::QuestTroupe,
|
||||||
|
LogSys.GetGMSayColorFromCategory(log_category),
|
||||||
|
fmt::format(
|
||||||
|
" {}{}",
|
||||||
|
(iter == 0 ? " ---" : ""),
|
||||||
|
message_split[iter]
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
zoneserver_list.SendEmoteMessage(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
AccountStatus::QuestTroupe,
|
||||||
|
LogSys.GetGMSayColorFromCategory(log_category),
|
||||||
|
"%s",
|
||||||
|
message.c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WorldBoot::HandleCommandInput(int argc, char **argv)
|
||||||
|
{
|
||||||
|
// database version
|
||||||
|
uint32 database_version = CURRENT_BINARY_DATABASE_VERSION;
|
||||||
|
uint32 bots_database_version = CURRENT_BINARY_BOTS_DATABASE_VERSION;
|
||||||
|
if (argc >= 2) {
|
||||||
|
if (strcasecmp(argv[1], "db_version") == 0) {
|
||||||
|
std::cout << "Binary Database Version: " << database_version << " : " << bots_database_version << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// command handler
|
||||||
|
if (argc > 1) {
|
||||||
|
LogSys.SilenceConsoleLogging();
|
||||||
|
WorldConfig::LoadConfig();
|
||||||
|
LoadDatabaseConnections();
|
||||||
|
LogSys.EnableConsoleLogging();
|
||||||
|
WorldserverCommandHandler::CommandHandler(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WorldBoot::LoadServerConfig()
|
||||||
|
{
|
||||||
|
LogInfo("[WorldBoot::LoadServerConfig] Loading server configuration");
|
||||||
|
if (!WorldConfig::LoadConfig()) {
|
||||||
|
LogError("[WorldBoot::LoadServerConfig] Loading server configuration failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WorldBoot::LoadDatabaseConnections()
|
||||||
|
{
|
||||||
|
const auto c = EQEmuConfig::get();
|
||||||
|
|
||||||
|
LogInfo(
|
||||||
|
"Connecting to MySQL [{}]@[{}]:[{}]",
|
||||||
|
c->DatabaseUsername.c_str(),
|
||||||
|
c->DatabaseHost.c_str(),
|
||||||
|
c->DatabasePort
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!database.Connect(
|
||||||
|
c->DatabaseHost.c_str(),
|
||||||
|
c->DatabaseUsername.c_str(),
|
||||||
|
c->DatabasePassword.c_str(),
|
||||||
|
c->DatabaseDB.c_str(),
|
||||||
|
c->DatabasePort
|
||||||
|
)) {
|
||||||
|
LogError("Cannot continue without a database connection");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multi-tenancy: Content database
|
||||||
|
*/
|
||||||
|
if (!c->ContentDbHost.empty()) {
|
||||||
|
if (!content_db.Connect(
|
||||||
|
c->ContentDbHost.c_str(),
|
||||||
|
c->ContentDbUsername.c_str(),
|
||||||
|
c->ContentDbPassword.c_str(),
|
||||||
|
c->ContentDbName.c_str(),
|
||||||
|
c->ContentDbPort,
|
||||||
|
"content"
|
||||||
|
)) {
|
||||||
|
LogError("Cannot continue without a content database connection");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
content_db.SetMysql(database.getMySQL());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_file_size(const std::string &filename) // path to file
|
||||||
|
{
|
||||||
|
FILE *p_file = NULL;
|
||||||
|
p_file = fopen(filename.c_str(), "rb");
|
||||||
|
fseek(p_file, 0, SEEK_END);
|
||||||
|
int size = ftell(p_file);
|
||||||
|
fclose(p_file);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WorldBoot::CheckForServerScript(bool force_download)
|
||||||
|
{
|
||||||
|
const std::string file = "eqemu_server.pl";
|
||||||
|
std::ifstream f(file);
|
||||||
|
|
||||||
|
/* Fetch EQEmu Server script */
|
||||||
|
if (!f || get_file_size(file) < 100 || force_download) {
|
||||||
|
|
||||||
|
if (force_download) {
|
||||||
|
std::remove("eqemu_server.pl");
|
||||||
|
} /* Delete local before fetch */
|
||||||
|
|
||||||
|
std::cout << "Pulling down EQEmu Server Maintenance Script (eqemu_server.pl)..." << std::endl;
|
||||||
|
|
||||||
|
// http get request
|
||||||
|
uri u("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl");
|
||||||
|
|
||||||
|
httplib::Client r(
|
||||||
|
fmt::format(
|
||||||
|
"{}://{}",
|
||||||
|
u.get_scheme(),
|
||||||
|
u.get_host()
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
r.set_connection_timeout(1, 0);
|
||||||
|
r.set_read_timeout(1, 0);
|
||||||
|
r.set_write_timeout(1, 0);
|
||||||
|
|
||||||
|
if (auto res = r.Get(u.get_path().c_str())) {
|
||||||
|
if (res->status == 200) {
|
||||||
|
// write file
|
||||||
|
std::ofstream out("eqemu_server.pl");
|
||||||
|
out << res->body;
|
||||||
|
out.close();
|
||||||
|
#ifdef _WIN32
|
||||||
|
#else
|
||||||
|
system("chmod 755 eqemu_server.pl");
|
||||||
|
system("chmod +x eqemu_server.pl");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldBoot::CheckForXMLConfigUpgrade()
|
||||||
|
{
|
||||||
|
if (!std::ifstream("eqemu_config.json") && std::ifstream("eqemu_config.xml")) {
|
||||||
|
CheckForServerScript(true);
|
||||||
|
if (system("perl eqemu_server.pl convert_xml")) {}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CheckForServerScript();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern LoginServerList loginserverlist;
|
||||||
|
|
||||||
|
void WorldBoot::RegisterLoginservers()
|
||||||
|
{
|
||||||
|
const auto c = EQEmuConfig::get();
|
||||||
|
|
||||||
|
if (c->LoginCount == 0) {
|
||||||
|
if (c->LoginHost.length()) {
|
||||||
|
loginserverlist.Add(
|
||||||
|
c->LoginHost.c_str(),
|
||||||
|
c->LoginPort,
|
||||||
|
c->LoginAccount.c_str(),
|
||||||
|
c->LoginPassword.c_str(),
|
||||||
|
c->LoginLegacy
|
||||||
|
);
|
||||||
|
LogInfo("Added loginserver [{}]:[{}]", c->LoginHost.c_str(), c->LoginPort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LinkedList<LoginConfig *> loginlist = c->loginlist;
|
||||||
|
LinkedListIterator<LoginConfig *> iterator(loginlist);
|
||||||
|
iterator.Reset();
|
||||||
|
while (iterator.MoreElements()) {
|
||||||
|
if (iterator.GetData()->LoginHost.length()) {
|
||||||
|
loginserverlist.Add(
|
||||||
|
iterator.GetData()->LoginHost.c_str(),
|
||||||
|
iterator.GetData()->LoginPort,
|
||||||
|
iterator.GetData()->LoginAccount.c_str(),
|
||||||
|
iterator.GetData()->LoginPassword.c_str(),
|
||||||
|
iterator.GetData()->LoginLegacy
|
||||||
|
);
|
||||||
|
|
||||||
|
LogInfo(
|
||||||
|
"Added loginserver [{}]:[{}]",
|
||||||
|
iterator.GetData()->LoginHost.c_str(),
|
||||||
|
iterator.GetData()->LoginPort
|
||||||
|
);
|
||||||
|
}
|
||||||
|
iterator.Advance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern SharedTaskManager shared_task_manager;
|
||||||
|
extern AdventureManager adventure_manager;
|
||||||
|
extern WorldEventScheduler event_scheduler;
|
||||||
|
|
||||||
|
bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv)
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
bool ignore_db = false;
|
||||||
|
if (argc >= 2) {
|
||||||
|
if (strcasecmp(argv[1], "ignore_db") == 0) {
|
||||||
|
ignore_db = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cerr << "Error, unknown command line option" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ignore_db) {
|
||||||
|
LogInfo("Checking Database Conversions");
|
||||||
|
database.CheckDatabaseConversions();
|
||||||
|
}
|
||||||
|
|
||||||
|
// logging system init
|
||||||
|
auto logging = LogSys.SetDatabase(&database)
|
||||||
|
->LoadLogDatabaseSettings();
|
||||||
|
|
||||||
|
if (RuleB(Logging, WorldGMSayLogging)) {
|
||||||
|
logging->SetGMSayHandler(&WorldBoot::GMSayHookCallBackProcessWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
logging->StartFileLogs();
|
||||||
|
|
||||||
|
LogInfo("Loading variables");
|
||||||
|
database.LoadVariables();
|
||||||
|
|
||||||
|
std::string hotfix_name;
|
||||||
|
if (database.GetVariable("hotfix_name", hotfix_name)) {
|
||||||
|
if (!hotfix_name.empty()) {
|
||||||
|
LogInfo("Current hotfix in use: [{}]", hotfix_name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
guild_mgr.SetDatabase(&database);
|
||||||
|
|
||||||
|
LogInfo("Purging expired data buckets");
|
||||||
|
database.PurgeAllDeletedDataBuckets();
|
||||||
|
|
||||||
|
LogInfo("Loading zones");
|
||||||
|
|
||||||
|
world_store.LoadZones();
|
||||||
|
|
||||||
|
LogInfo("Clearing groups");
|
||||||
|
database.ClearGroup();
|
||||||
|
LogInfo("Clearing raids");
|
||||||
|
database.ClearRaid();
|
||||||
|
database.ClearRaidDetails();
|
||||||
|
database.ClearRaidLeader();
|
||||||
|
LogInfo("Clearing inventory snapshots");
|
||||||
|
database.ClearInvSnapshots();
|
||||||
|
LogInfo("Loading items");
|
||||||
|
|
||||||
|
if (!content_db.LoadItems(hotfix_name)) {
|
||||||
|
LogError("Error: Could not load item data. But ignoring");
|
||||||
|
}
|
||||||
|
|
||||||
|
LogInfo("Loading skill caps");
|
||||||
|
if (!content_db.LoadSkillCaps(std::string(hotfix_name))) {
|
||||||
|
LogError("Error: Could not load skill cap data. But ignoring");
|
||||||
|
}
|
||||||
|
|
||||||
|
LogInfo("Loading guilds");
|
||||||
|
guild_mgr.LoadGuilds();
|
||||||
|
|
||||||
|
//rules:
|
||||||
|
{
|
||||||
|
if (!RuleManager::Instance()->UpdateOrphanedRules(&database)) {
|
||||||
|
LogInfo("Failed to process 'Orphaned Rules' update operation.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RuleManager::Instance()->UpdateInjectedRules(&database, "default")) {
|
||||||
|
LogInfo("Failed to process 'Injected Rules' for ruleset 'default' update operation.");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string tmp;
|
||||||
|
if (database.GetVariable("RuleSet", tmp)) {
|
||||||
|
LogInfo("Loading rule set [{}]", tmp.c_str());
|
||||||
|
|
||||||
|
if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str(), false)) {
|
||||||
|
LogInfo("Failed to load ruleset [{}], falling back to defaults", tmp.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
if (!RuleManager::Instance()->LoadRules(&database, "default", false)) {
|
||||||
|
LogInfo("No rule set configured, using default rules");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LogInfo("Loaded default rule set [default]", tmp.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RuleManager::Instance()->RestoreRuleNotes(&database)) {
|
||||||
|
LogInfo("Failed to process 'Restore Rule Notes' update operation.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EQ::InitializeDynamicLookups();
|
||||||
|
LogInfo("Initialized dynamic dictionary entries");
|
||||||
|
|
||||||
|
if (RuleB(World, ClearTempMerchantlist)) {
|
||||||
|
LogInfo("Clearing temporary merchant lists");
|
||||||
|
database.ClearMerchantTemp();
|
||||||
|
}
|
||||||
|
|
||||||
|
LogInfo("Loading EQ time of day");
|
||||||
|
TimeOfDay_Struct eqTime{};
|
||||||
|
time_t realtime;
|
||||||
|
eqTime = database.LoadTime(realtime);
|
||||||
|
zoneserver_list.worldclock.SetCurrentEQTimeOfDay(eqTime, realtime);
|
||||||
|
|
||||||
|
LogInfo("Deleted [{}] stale player corpses from database", database.DeleteStalePlayerCorpses());
|
||||||
|
|
||||||
|
LogInfo("Loading adventures");
|
||||||
|
if (!adventure_manager.LoadAdventureTemplates()) {
|
||||||
|
LogInfo("Unable to load adventure templates");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!adventure_manager.LoadAdventureEntries()) {
|
||||||
|
LogInfo("Unable to load adventure templates");
|
||||||
|
}
|
||||||
|
|
||||||
|
adventure_manager.LoadLeaderboardInfo();
|
||||||
|
|
||||||
|
LogInfo("Purging expired dynamic zones and members");
|
||||||
|
dynamic_zone_manager.PurgeExpiredDynamicZones();
|
||||||
|
|
||||||
|
LogInfo("Purging expired expeditions");
|
||||||
|
ExpeditionDatabase::PurgeExpiredExpeditions();
|
||||||
|
ExpeditionDatabase::PurgeExpiredCharacterLockouts();
|
||||||
|
|
||||||
|
LogInfo("Purging expired character task timers");
|
||||||
|
CharacterTaskTimersRepository::DeleteWhere(database, "expire_time <= NOW()");
|
||||||
|
|
||||||
|
LogInfo("Purging expired instances");
|
||||||
|
database.PurgeExpiredInstances();
|
||||||
|
|
||||||
|
LogInfo("Loading dynamic zones");
|
||||||
|
dynamic_zone_manager.CacheAllFromDatabase();
|
||||||
|
|
||||||
|
LogInfo("Loading char create info");
|
||||||
|
content_db.LoadCharacterCreateAllocations();
|
||||||
|
content_db.LoadCharacterCreateCombos();
|
||||||
|
|
||||||
|
LogInfo("Initializing [EventScheduler]");
|
||||||
|
event_scheduler.SetDatabase(&database)->LoadScheduledEvents();
|
||||||
|
|
||||||
|
LogInfo("Initializing [WorldContentService]");
|
||||||
|
content_service.SetDatabase(&database)
|
||||||
|
->SetExpansionContext()
|
||||||
|
->ReloadContentFlags();
|
||||||
|
|
||||||
|
LogInfo("Initializing [SharedTaskManager]");
|
||||||
|
shared_task_manager.SetDatabase(&database)
|
||||||
|
->SetContentDatabase(&content_db)
|
||||||
|
->LoadTaskData()
|
||||||
|
->LoadSharedTaskState();
|
||||||
|
|
||||||
|
shared_task_manager.PurgeExpiredSharedTasks();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldBoot::CheckForPossibleConfigurationIssues()
|
||||||
|
{
|
||||||
|
const auto c = EQEmuConfig::get();
|
||||||
|
|
||||||
|
if (c->DisableConfigChecks) {
|
||||||
|
LogInfo("Configuration checking [disabled]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string local_address = IpUtil::GetLocalIPAddress();
|
||||||
|
const std::string public_address = IpUtil::GetPublicIPAddress();
|
||||||
|
const std::string config_file = "eqemu_config.json";
|
||||||
|
const std::ifstream is_in_docker("/.dockerenv");
|
||||||
|
|
||||||
|
if (local_address.empty() && public_address.empty()) {
|
||||||
|
LogInfo("Configuration check, probes failed for local and public address, returning");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogInfo("Checking for possible configuration issues");
|
||||||
|
LogInfo("To disable configuration checks, set [server.disable_config_checks] to [true] in [{}]", config_file);
|
||||||
|
|
||||||
|
std::string config_address = c->WorldAddress;
|
||||||
|
if (!IpUtil::IsIPAddress(config_address)) {
|
||||||
|
config_address = IpUtil::DNSLookupSync(c->WorldAddress, 9000);
|
||||||
|
LogInfo(
|
||||||
|
"World config address using DNS [{}] resolves to [{}]",
|
||||||
|
c->WorldAddress,
|
||||||
|
config_address
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
// lan detection
|
||||||
|
if (local_address != public_address
|
||||||
|
&& IpUtil::IsIpInPrivateRfc1918(local_address)
|
||||||
|
&& local_address != c->LocalAddress
|
||||||
|
&& !is_in_docker
|
||||||
|
) {
|
||||||
|
LogWarning("# LAN detection (Configuration)");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("You appear to be on a LAN and your localaddress may not be properly set!");
|
||||||
|
LogWarning("This can prevent local clients from properly connecting to your server");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Config file [{}] path [server.world] variable [localaddress]", config_file);
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Local address (eqemu_config) value [{}] detected value [{}]", c->LocalAddress, local_address);
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// docker configuration
|
||||||
|
if (
|
||||||
|
(
|
||||||
|
(c->LocalAddress.empty() && config_address.empty()) ||
|
||||||
|
(config_address != public_address)
|
||||||
|
)
|
||||||
|
&& is_in_docker
|
||||||
|
) {
|
||||||
|
LogWarning("# Docker Configuration (Configuration)");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("You appear to running EQEmu in a docker container");
|
||||||
|
LogWarning("In order for networking to work properly you will need to properly configure your server");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning(
|
||||||
|
"If your Docker host is on a [LAN] or behind a NAT / Firewall, your [localaddress] variable under [server.world] will need to");
|
||||||
|
LogWarning(
|
||||||
|
"be set to your LAN address on the host, not the container address. [address] will need to be your public address");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning(
|
||||||
|
"If your Docker host is directly on the [public internet], your [localaddress] variable under [server.world] can be set to [127.0.0.1]."
|
||||||
|
);
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("[address] will need to be your public address");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Config file [{}] path [server.world] variable(s) [localaddress] [address]", config_file);
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Local address (eqemu_config) value [{}] detected value [{}]", c->LocalAddress, local_address);
|
||||||
|
LogWarning(
|
||||||
|
"Public address (eqemu_config) value [{}] detected value [{}]",
|
||||||
|
config_address,
|
||||||
|
public_address
|
||||||
|
);
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// docker LAN not set
|
||||||
|
if (c->LocalAddress.empty() && is_in_docker) {
|
||||||
|
LogWarning("# Docker LAN (Configuration)");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("You appear to running EQEmu in a docker container");
|
||||||
|
LogWarning(
|
||||||
|
"Your local address does not appear to be set, this may not be an issue if your deployment is not on a LAN"
|
||||||
|
);
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning(
|
||||||
|
"If your Docker host is on a [LAN] or behind a NAT / Firewall, your [localaddress] variable under [server.world] will need to");
|
||||||
|
LogWarning(
|
||||||
|
"be set to your LAN address on the host, not the container address. [address] will need to be your public address");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning(
|
||||||
|
"If your Docker host is directly on the [public internet], your [localaddress] variable under [server.world] can be set to [127.0.0.1]."
|
||||||
|
);
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("[address] will need to be your public address");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Config file [{}] path [server.world] variable(s) [localaddress] [address]", config_file);
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Local address (eqemu_config) value [{}] detected value [{}]", c->LocalAddress, local_address);
|
||||||
|
LogWarning(
|
||||||
|
"Public address (eqemu_config) value [{}] detected value [{}]",
|
||||||
|
config_address,
|
||||||
|
public_address
|
||||||
|
);
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public address different from configuration
|
||||||
|
if (!config_address.empty() && public_address != config_address) {
|
||||||
|
LogWarning("# Public address (Configuration)");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Your configured public address appears to be different from what's detected!");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Config file [{}] path [server.world] variable [address]", config_file);
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning(
|
||||||
|
"Public address (eqemu_config) value [{}] detected value [{}]",
|
||||||
|
config_address,
|
||||||
|
public_address
|
||||||
|
);
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public address set to meta-address
|
||||||
|
if (config_address == "0.0.0.0") {
|
||||||
|
LogWarning("# Public meta-address (Configuration)");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Your configured public address is set to a meta-address (0.0.0.0) (all-interfaces)");
|
||||||
|
LogWarning(
|
||||||
|
"The meta-address may not work properly and it is recommended you configure your public address explicitly");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Config file [{}] path [server.world] variable [address]", config_file);
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning(
|
||||||
|
"Public address (eqemu_config) value [{}] detected value [{}]",
|
||||||
|
config_address,
|
||||||
|
public_address
|
||||||
|
);
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// local address set to meta-address
|
||||||
|
if (c->LocalAddress == "0.0.0.0") {
|
||||||
|
LogWarning("# Local meta-address (Configuration)");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Your configured local address is set to a meta-address (0.0.0.0) (all-interfaces)");
|
||||||
|
LogWarning(
|
||||||
|
"The meta-address may not work properly and it is recommended you configure your local address explicitly"
|
||||||
|
);
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Config file [{}] path [server.world] variable [localaddress]", config_file);
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Local address (eqemu_config) value [{}] detected value [{}]", c->LocalAddress, local_address);
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ucs (public)
|
||||||
|
if (
|
||||||
|
(!config_address.empty() && c->MailHost != config_address) ||
|
||||||
|
(!config_address.empty() && c->ChatHost != config_address)
|
||||||
|
) {
|
||||||
|
LogWarning("# UCS Address Mailhost (Configuration)");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning(
|
||||||
|
"UCS (Universal Chat Service) mail or chat appears to use a different address from your main world address"
|
||||||
|
);
|
||||||
|
LogWarning("This can result in a chat service that doesn't network properly");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#mailserver]");
|
||||||
|
LogWarning("");
|
||||||
|
LogWarning(
|
||||||
|
"[server.world.address] value [{}] [server.chatserver.host] [{}]",
|
||||||
|
config_address,
|
||||||
|
c->ChatHost
|
||||||
|
);
|
||||||
|
LogWarning(
|
||||||
|
"[server.world.address] value [{}] [server.mailserver.host] [{}]",
|
||||||
|
config_address,
|
||||||
|
c->MailHost
|
||||||
|
);
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
21
world/world_boot.h
Normal file
21
world/world_boot.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef EQEMU_WORLD_BOOT_H
|
||||||
|
#define EQEMU_WORLD_BOOT_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "../common/types.h"
|
||||||
|
|
||||||
|
class WorldBoot {
|
||||||
|
public:
|
||||||
|
static void GMSayHookCallBackProcessWorld(uint16 log_category, std::string message);
|
||||||
|
static bool HandleCommandInput(int argc, char **argv);
|
||||||
|
static bool LoadServerConfig();
|
||||||
|
static bool LoadDatabaseConnections();
|
||||||
|
static void CheckForServerScript(bool force_download = false);
|
||||||
|
static void CheckForXMLConfigUpgrade();
|
||||||
|
static void RegisterLoginservers();
|
||||||
|
static bool DatabaseLoadRoutines(int argc, char **argv);
|
||||||
|
static void CheckForPossibleConfigurationIssues();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //EQEMU_WORLD_BOOT_H
|
||||||
@ -18,7 +18,6 @@
|
|||||||
#include "../common/global_define.h"
|
#include "../common/global_define.h"
|
||||||
#include "../common/eqemu_logsys.h"
|
#include "../common/eqemu_logsys.h"
|
||||||
#include "world_config.h"
|
#include "world_config.h"
|
||||||
#include "../common/ip_util.h"
|
|
||||||
|
|
||||||
WorldConfig *WorldConfig::_world_config = nullptr;
|
WorldConfig *WorldConfig::_world_config = nullptr;
|
||||||
|
|
||||||
@ -32,231 +31,4 @@ std::string WorldConfig::GetByName(const std::string &var_name) const
|
|||||||
}
|
}
|
||||||
return (EQEmuConfig::GetByName(var_name));
|
return (EQEmuConfig::GetByName(var_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldConfig::CheckForPossibleConfigurationIssues()
|
|
||||||
{
|
|
||||||
if (_config->DisableConfigChecks) {
|
|
||||||
LogInfo("Configuration checking [disabled]");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string local_address = IpUtil::GetLocalIPAddress();
|
|
||||||
const std::string public_address = IpUtil::GetPublicIPAddress();
|
|
||||||
const std::string config_file = "eqemu_config.json";
|
|
||||||
const std::ifstream is_in_docker("/.dockerenv");
|
|
||||||
|
|
||||||
if (local_address.empty() && public_address.empty()) {
|
|
||||||
LogInfo("Configuration check, probes failed for local and public address, returning");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LogInfo("Checking for possible configuration issues");
|
|
||||||
LogInfo("To disable configuration checks, set [server.disable_config_checks] to [true] in [{}]", config_file);
|
|
||||||
|
|
||||||
std::string config_address = _config->WorldAddress;
|
|
||||||
if (!IpUtil::IsIPAddress(config_address)) {
|
|
||||||
config_address = IpUtil::DNSLookupSync(_config->WorldAddress, 9000);
|
|
||||||
LogInfo(
|
|
||||||
"World config address using DNS [{}] resolves to [{}]",
|
|
||||||
_config->WorldAddress,
|
|
||||||
config_address
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << std::endl;
|
|
||||||
|
|
||||||
// lan detection
|
|
||||||
if (local_address != public_address
|
|
||||||
&& IpUtil::IsIpInPrivateRfc1918(local_address)
|
|
||||||
&& local_address != _config->LocalAddress
|
|
||||||
&& !is_in_docker
|
|
||||||
) {
|
|
||||||
LogWarning("# LAN detection (Configuration)");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("You appear to be on a LAN and your localaddress may not be properly set!");
|
|
||||||
LogWarning("This can prevent local clients from properly connecting to your server");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Config file [{}] path [server.world] variable [localaddress]", config_file);
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Local address (eqemu_config) value [{}] detected value [{}]", _config->LocalAddress, local_address);
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// docker configuration
|
|
||||||
if (
|
|
||||||
(
|
|
||||||
(_config->LocalAddress.empty() && config_address.empty()) ||
|
|
||||||
(config_address != public_address)
|
|
||||||
)
|
|
||||||
&& is_in_docker
|
|
||||||
) {
|
|
||||||
LogWarning("# Docker Configuration (Configuration)");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("You appear to running EQEmu in a docker container");
|
|
||||||
LogWarning("In order for networking to work properly you will need to properly configure your server");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning(
|
|
||||||
"If your Docker host is on a [LAN] or behind a NAT / Firewall, your [localaddress] variable under [server.world] will need to");
|
|
||||||
LogWarning(
|
|
||||||
"be set to your LAN address on the host, not the container address. [address] will need to be your public address");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning(
|
|
||||||
"If your Docker host is directly on the [public internet], your [localaddress] variable under [server.world] can be set to [127.0.0.1]."
|
|
||||||
);
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("[address] will need to be your public address");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Config file [{}] path [server.world] variable(s) [localaddress] [address]", config_file);
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Local address (eqemu_config) value [{}] detected value [{}]", _config->LocalAddress, local_address);
|
|
||||||
LogWarning(
|
|
||||||
"Public address (eqemu_config) value [{}] detected value [{}]",
|
|
||||||
config_address,
|
|
||||||
public_address
|
|
||||||
);
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// docker LAN not set
|
|
||||||
if (_config->LocalAddress.empty() && is_in_docker) {
|
|
||||||
LogWarning("# Docker LAN (Configuration)");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("You appear to running EQEmu in a docker container");
|
|
||||||
LogWarning(
|
|
||||||
"Your local address does not appear to be set, this may not be an issue if your deployment is not on a LAN"
|
|
||||||
);
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning(
|
|
||||||
"If your Docker host is on a [LAN] or behind a NAT / Firewall, your [localaddress] variable under [server.world] will need to");
|
|
||||||
LogWarning(
|
|
||||||
"be set to your LAN address on the host, not the container address. [address] will need to be your public address");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning(
|
|
||||||
"If your Docker host is directly on the [public internet], your [localaddress] variable under [server.world] can be set to [127.0.0.1]."
|
|
||||||
);
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("[address] will need to be your public address");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Config file [{}] path [server.world] variable(s) [localaddress] [address]", config_file);
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Local address (eqemu_config) value [{}] detected value [{}]", _config->LocalAddress, local_address);
|
|
||||||
LogWarning(
|
|
||||||
"Public address (eqemu_config) value [{}] detected value [{}]",
|
|
||||||
config_address,
|
|
||||||
public_address
|
|
||||||
);
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// public address different from configuration
|
|
||||||
if (!config_address.empty() && public_address != config_address) {
|
|
||||||
LogWarning("# Public address (Configuration)");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Your configured public address appears to be different from what's detected!");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Config file [{}] path [server.world] variable [address]", config_file);
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning(
|
|
||||||
"Public address (eqemu_config) value [{}] detected value [{}]",
|
|
||||||
config_address,
|
|
||||||
public_address
|
|
||||||
);
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// public address set to meta-address
|
|
||||||
if (config_address == "0.0.0.0") {
|
|
||||||
LogWarning("# Public meta-address (Configuration)");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Your configured public address is set to a meta-address (0.0.0.0) (all-interfaces)");
|
|
||||||
LogWarning(
|
|
||||||
"The meta-address may not work properly and it is recommended you configure your public address explicitly");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Config file [{}] path [server.world] variable [address]", config_file);
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning(
|
|
||||||
"Public address (eqemu_config) value [{}] detected value [{}]",
|
|
||||||
config_address,
|
|
||||||
public_address
|
|
||||||
);
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// local address set to meta-address
|
|
||||||
if (_config->LocalAddress == "0.0.0.0") {
|
|
||||||
LogWarning("# Local meta-address (Configuration)");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Your configured local address is set to a meta-address (0.0.0.0) (all-interfaces)");
|
|
||||||
LogWarning(
|
|
||||||
"The meta-address may not work properly and it is recommended you configure your local address explicitly"
|
|
||||||
);
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#world]");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Config file [{}] path [server.world] variable [localaddress]", config_file);
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Local address (eqemu_config) value [{}] detected value [{}]", _config->LocalAddress, local_address);
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ucs (public)
|
|
||||||
if (
|
|
||||||
(!config_address.empty() && _config->MailHost != config_address) ||
|
|
||||||
(!config_address.empty() && _config->ChatHost != config_address)
|
|
||||||
) {
|
|
||||||
LogWarning("# UCS Address Mailhost (Configuration)");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning(
|
|
||||||
"UCS (Universal Chat Service) mail or chat appears to use a different address from your main world address"
|
|
||||||
);
|
|
||||||
LogWarning("This can result in a chat service that doesn't network properly");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#mailserver]");
|
|
||||||
LogWarning("");
|
|
||||||
LogWarning(
|
|
||||||
"[server.world.address] value [{}] [server.chatserver.host] [{}]",
|
|
||||||
config_address,
|
|
||||||
_config->ChatHost
|
|
||||||
);
|
|
||||||
LogWarning(
|
|
||||||
"[server.world.address] value [{}] [server.mailserver.host] [{}]",
|
|
||||||
config_address,
|
|
||||||
_config->MailHost
|
|
||||||
);
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -68,8 +68,6 @@ public:
|
|||||||
static void SetWorldAddress(std::string addr) { if (_world_config) _world_config->WorldAddress=addr; }
|
static void SetWorldAddress(std::string addr) { if (_world_config) _world_config->WorldAddress=addr; }
|
||||||
static void SetLocalAddress(std::string addr) { if (_world_config) _world_config->LocalAddress=addr; }
|
static void SetLocalAddress(std::string addr) { if (_world_config) _world_config->LocalAddress=addr; }
|
||||||
|
|
||||||
static void CheckForPossibleConfigurationIssues();
|
|
||||||
|
|
||||||
void Dump() const;
|
void Dump() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user