mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-24 14:37:25 +00:00
Merge remote-tracking branch 'upstream/main'
This commit is contained in:
commit
41b8762c8f
26
README.md
26
README.md
@ -422,11 +422,6 @@ Here is a summary of the commands available in-game. All commands are prefixed b
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
# Credits
|
# Credits
|
||||||
## Active Contributors
|
|
||||||
* [EmosewaMC](https://github.com/EmosewaMC)
|
|
||||||
* [Jettford](https://github.com/Jettford)
|
|
||||||
* [Aaron K.](https://github.com/aronwk-aaron)
|
|
||||||
|
|
||||||
## DLU Team
|
## DLU Team
|
||||||
* [DarwinAnim8or](https://github.com/DarwinAnim8or)
|
* [DarwinAnim8or](https://github.com/DarwinAnim8or)
|
||||||
* [Wincent01](https://github.com/Wincent01)
|
* [Wincent01](https://github.com/Wincent01)
|
||||||
@ -434,25 +429,30 @@ Here is a summary of the commands available in-game. All commands are prefixed b
|
|||||||
* [averysumner](https://github.com/codeshaunted)
|
* [averysumner](https://github.com/codeshaunted)
|
||||||
* [Jon002](https://github.com/jaller200)
|
* [Jon002](https://github.com/jaller200)
|
||||||
* [Jonny](https://github.com/cuzitsjonny)
|
* [Jonny](https://github.com/cuzitsjonny)
|
||||||
|
* [Aaron K.](https://github.com/aronwk-aaron)
|
||||||
|
|
||||||
### Research and tools
|
### Research and Tools
|
||||||
* [lcdr](https://github.com/lcdr)
|
* [lcdr](https://github.com/lcdr)
|
||||||
* [Xiphoseer](https://github.com/Xiphoseer)
|
* [Xiphoseer](https://github.com/Xiphoseer)
|
||||||
|
|
||||||
### Community management
|
### Community Management
|
||||||
* [Neal](https://github.com/NealSpellman)
|
* [Neal](https://github.com/NealSpellman)
|
||||||
|
|
||||||
### Former contributors
|
### Logo
|
||||||
|
* Cole Peterson (BlasterBuilder)
|
||||||
|
|
||||||
|
## Active Contributors
|
||||||
|
* [EmosewaMC](https://github.com/EmosewaMC)
|
||||||
|
* [Jettford](https://github.com/Jettford)
|
||||||
|
|
||||||
|
## Former Contributors
|
||||||
* TheMachine
|
* TheMachine
|
||||||
* Matthew
|
* Matthew
|
||||||
* [Raine](https://github.com/Rainebannister)
|
* [Raine](https://github.com/Rainebannister)
|
||||||
* Bricknave
|
* Bricknave
|
||||||
|
|
||||||
### Logo
|
## Special Thanks
|
||||||
* Cole Peterson (BlasterBuilder)
|
|
||||||
|
|
||||||
## Special thanks
|
|
||||||
* humanoid24
|
* humanoid24
|
||||||
* pwjones1969
|
* pwjones1969
|
||||||
* [Simon](https://github.com/SimonNitzsche)
|
* [Simon](https://github.com/SimonNitzsche)
|
||||||
* ALL OF THE NETDEVIL AND LEGO TEAMS!
|
* [ALL OF THE NETDEVIL AND LEGO TEAMS!](https://www.mobygames.com/game/macintosh/lego-universe/credits)
|
||||||
|
@ -32,6 +32,8 @@ dLogger* SetupLogger();
|
|||||||
void HandlePacket(Packet* packet);
|
void HandlePacket(Packet* packet);
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
constexpr uint32_t authFramerate = mediumFramerate;
|
||||||
|
constexpr uint32_t authFrameDelta = mediumFrameDelta;
|
||||||
Diagnostics::SetProcessName("Auth");
|
Diagnostics::SetProcessName("Auth");
|
||||||
Diagnostics::SetProcessFileName(argv[0]);
|
Diagnostics::SetProcessFileName(argv[0]);
|
||||||
Diagnostics::Initialize();
|
Diagnostics::Initialize();
|
||||||
@ -67,7 +69,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
//Find out the master's IP:
|
//Find out the master's IP:
|
||||||
std::string masterIP;
|
std::string masterIP;
|
||||||
int masterPort = 1500;
|
uint32_t masterPort = 1500;
|
||||||
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
||||||
auto res = stmt->executeQuery();
|
auto res = stmt->executeQuery();
|
||||||
while (res->next()) {
|
while (res->next()) {
|
||||||
@ -79,8 +81,8 @@ int main(int argc, char** argv) {
|
|||||||
delete stmt;
|
delete stmt;
|
||||||
|
|
||||||
//It's safe to pass 'localhost' here, as the IP is only used as the external IP.
|
//It's safe to pass 'localhost' here, as the IP is only used as the external IP.
|
||||||
int maxClients = 50;
|
uint32_t maxClients = 50;
|
||||||
int ourPort = 1001; //LU client is hardcoded to use this for auth port, so I'm making it the default.
|
uint32_t ourPort = 1001; //LU client is hardcoded to use this for auth port, so I'm making it the default.
|
||||||
if (Game::config->GetValue("max_clients") != "") maxClients = std::stoi(Game::config->GetValue("max_clients"));
|
if (Game::config->GetValue("max_clients") != "") maxClients = std::stoi(Game::config->GetValue("max_clients"));
|
||||||
if (Game::config->GetValue("port") != "") ourPort = std::atoi(Game::config->GetValue("port").c_str());
|
if (Game::config->GetValue("port") != "") ourPort = std::atoi(Game::config->GetValue("port").c_str());
|
||||||
|
|
||||||
@ -89,16 +91,18 @@ int main(int argc, char** argv) {
|
|||||||
//Run it until server gets a kill message from Master:
|
//Run it until server gets a kill message from Master:
|
||||||
auto t = std::chrono::high_resolution_clock::now();
|
auto t = std::chrono::high_resolution_clock::now();
|
||||||
Packet* packet = nullptr;
|
Packet* packet = nullptr;
|
||||||
int framesSinceLastFlush = 0;
|
constexpr uint32_t logFlushTime = 30 * authFramerate; // 30 seconds in frames
|
||||||
int framesSinceMasterDisconnect = 0;
|
constexpr uint32_t sqlPingTime = 10 * 60 * authFramerate; // 10 minutes in frames
|
||||||
int framesSinceLastSQLPing = 0;
|
uint32_t framesSinceLastFlush = 0;
|
||||||
|
uint32_t framesSinceMasterDisconnect = 0;
|
||||||
|
uint32_t framesSinceLastSQLPing = 0;
|
||||||
|
|
||||||
while (!Game::shouldShutdown) {
|
while (!Game::shouldShutdown) {
|
||||||
//Check if we're still connected to master:
|
//Check if we're still connected to master:
|
||||||
if (!Game::server->GetIsConnectedToMaster()) {
|
if (!Game::server->GetIsConnectedToMaster()) {
|
||||||
framesSinceMasterDisconnect++;
|
framesSinceMasterDisconnect++;
|
||||||
|
|
||||||
if (framesSinceMasterDisconnect >= 30)
|
if (framesSinceMasterDisconnect >= authFramerate)
|
||||||
break; //Exit our loop, shut down.
|
break; //Exit our loop, shut down.
|
||||||
} else framesSinceMasterDisconnect = 0;
|
} else framesSinceMasterDisconnect = 0;
|
||||||
|
|
||||||
@ -114,16 +118,16 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Push our log every 30s:
|
//Push our log every 30s:
|
||||||
if (framesSinceLastFlush >= 900) {
|
if (framesSinceLastFlush >= logFlushTime) {
|
||||||
Game::logger->Flush();
|
Game::logger->Flush();
|
||||||
framesSinceLastFlush = 0;
|
framesSinceLastFlush = 0;
|
||||||
} else framesSinceLastFlush++;
|
} else framesSinceLastFlush++;
|
||||||
|
|
||||||
//Every 10 min we ping our sql server to keep it alive hopefully:
|
//Every 10 min we ping our sql server to keep it alive hopefully:
|
||||||
if (framesSinceLastSQLPing >= 40000) {
|
if (framesSinceLastSQLPing >= sqlPingTime) {
|
||||||
//Find out the master's IP for absolutely no reason:
|
//Find out the master's IP for absolutely no reason:
|
||||||
std::string masterIP;
|
std::string masterIP;
|
||||||
int masterPort;
|
uint32_t masterPort;
|
||||||
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
||||||
auto res = stmt->executeQuery();
|
auto res = stmt->executeQuery();
|
||||||
while (res->next()) {
|
while (res->next()) {
|
||||||
@ -138,7 +142,7 @@ int main(int argc, char** argv) {
|
|||||||
} else framesSinceLastSQLPing++;
|
} else framesSinceLastSQLPing++;
|
||||||
|
|
||||||
//Sleep our thread since auth can afford to.
|
//Sleep our thread since auth can afford to.
|
||||||
t += std::chrono::milliseconds(mediumFramerate); //Auth can run at a lower "fps"
|
t += std::chrono::milliseconds(authFrameDelta); //Auth can run at a lower "fps"
|
||||||
std::this_thread::sleep_until(t);
|
std::this_thread::sleep_until(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
#include "ChatPacketHandler.h"
|
#include "ChatPacketHandler.h"
|
||||||
|
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
|
|
||||||
|
//RakNet includes:
|
||||||
|
#include "RakNetDefines.h"
|
||||||
namespace Game {
|
namespace Game {
|
||||||
dLogger* logger = nullptr;
|
dLogger* logger = nullptr;
|
||||||
dServer* server = nullptr;
|
dServer* server = nullptr;
|
||||||
@ -28,8 +31,6 @@ namespace Game {
|
|||||||
bool shouldShutdown = false;
|
bool shouldShutdown = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//RakNet includes:
|
|
||||||
#include "RakNetDefines.h"
|
|
||||||
|
|
||||||
dLogger* SetupLogger();
|
dLogger* SetupLogger();
|
||||||
void HandlePacket(Packet* packet);
|
void HandlePacket(Packet* packet);
|
||||||
@ -37,6 +38,8 @@ void HandlePacket(Packet* packet);
|
|||||||
PlayerContainer playerContainer;
|
PlayerContainer playerContainer;
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
constexpr uint32_t chatFramerate = mediumFramerate;
|
||||||
|
constexpr uint32_t chatFrameDelta = mediumFrameDelta;
|
||||||
Diagnostics::SetProcessName("Chat");
|
Diagnostics::SetProcessName("Chat");
|
||||||
Diagnostics::SetProcessFileName(argv[0]);
|
Diagnostics::SetProcessFileName(argv[0]);
|
||||||
Diagnostics::Initialize();
|
Diagnostics::Initialize();
|
||||||
@ -87,7 +90,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
//Find out the master's IP:
|
//Find out the master's IP:
|
||||||
std::string masterIP;
|
std::string masterIP;
|
||||||
int masterPort = 1000;
|
uint32_t masterPort = 1000;
|
||||||
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
||||||
auto res = stmt->executeQuery();
|
auto res = stmt->executeQuery();
|
||||||
while (res->next()) {
|
while (res->next()) {
|
||||||
@ -99,8 +102,8 @@ int main(int argc, char** argv) {
|
|||||||
delete stmt;
|
delete stmt;
|
||||||
|
|
||||||
//It's safe to pass 'localhost' here, as the IP is only used as the external IP.
|
//It's safe to pass 'localhost' here, as the IP is only used as the external IP.
|
||||||
int maxClients = 50;
|
uint32_t maxClients = 50;
|
||||||
int ourPort = 1501;
|
uint32_t ourPort = 1501;
|
||||||
if (Game::config->GetValue("max_clients") != "") maxClients = std::stoi(Game::config->GetValue("max_clients"));
|
if (Game::config->GetValue("max_clients") != "") maxClients = std::stoi(Game::config->GetValue("max_clients"));
|
||||||
if (Game::config->GetValue("port") != "") ourPort = std::atoi(Game::config->GetValue("port").c_str());
|
if (Game::config->GetValue("port") != "") ourPort = std::atoi(Game::config->GetValue("port").c_str());
|
||||||
|
|
||||||
@ -111,16 +114,18 @@ int main(int argc, char** argv) {
|
|||||||
//Run it until server gets a kill message from Master:
|
//Run it until server gets a kill message from Master:
|
||||||
auto t = std::chrono::high_resolution_clock::now();
|
auto t = std::chrono::high_resolution_clock::now();
|
||||||
Packet* packet = nullptr;
|
Packet* packet = nullptr;
|
||||||
int framesSinceLastFlush = 0;
|
constexpr uint32_t logFlushTime = 30 * chatFramerate; // 30 seconds in frames
|
||||||
int framesSinceMasterDisconnect = 0;
|
constexpr uint32_t sqlPingTime = 10 * 60 * chatFramerate; // 10 minutes in frames
|
||||||
int framesSinceLastSQLPing = 0;
|
uint32_t framesSinceLastFlush = 0;
|
||||||
|
uint32_t framesSinceMasterDisconnect = 0;
|
||||||
|
uint32_t framesSinceLastSQLPing = 0;
|
||||||
|
|
||||||
while (!Game::shouldShutdown) {
|
while (!Game::shouldShutdown) {
|
||||||
//Check if we're still connected to master:
|
//Check if we're still connected to master:
|
||||||
if (!Game::server->GetIsConnectedToMaster()) {
|
if (!Game::server->GetIsConnectedToMaster()) {
|
||||||
framesSinceMasterDisconnect++;
|
framesSinceMasterDisconnect++;
|
||||||
|
|
||||||
if (framesSinceMasterDisconnect >= 30)
|
if (framesSinceMasterDisconnect >= chatFramerate)
|
||||||
break; //Exit our loop, shut down.
|
break; //Exit our loop, shut down.
|
||||||
} else framesSinceMasterDisconnect = 0;
|
} else framesSinceMasterDisconnect = 0;
|
||||||
|
|
||||||
@ -136,16 +141,16 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Push our log every 30s:
|
//Push our log every 30s:
|
||||||
if (framesSinceLastFlush >= 900) {
|
if (framesSinceLastFlush >= logFlushTime) {
|
||||||
Game::logger->Flush();
|
Game::logger->Flush();
|
||||||
framesSinceLastFlush = 0;
|
framesSinceLastFlush = 0;
|
||||||
} else framesSinceLastFlush++;
|
} else framesSinceLastFlush++;
|
||||||
|
|
||||||
//Every 10 min we ping our sql server to keep it alive hopefully:
|
//Every 10 min we ping our sql server to keep it alive hopefully:
|
||||||
if (framesSinceLastSQLPing >= 40000) {
|
if (framesSinceLastSQLPing >= sqlPingTime) {
|
||||||
//Find out the master's IP for absolutely no reason:
|
//Find out the master's IP for absolutely no reason:
|
||||||
std::string masterIP;
|
std::string masterIP;
|
||||||
int masterPort;
|
uint32_t masterPort;
|
||||||
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
||||||
auto res = stmt->executeQuery();
|
auto res = stmt->executeQuery();
|
||||||
while (res->next()) {
|
while (res->next()) {
|
||||||
@ -160,7 +165,7 @@ int main(int argc, char** argv) {
|
|||||||
} else framesSinceLastSQLPing++;
|
} else framesSinceLastSQLPing++;
|
||||||
|
|
||||||
//Sleep our thread since auth can afford to.
|
//Sleep our thread since auth can afford to.
|
||||||
t += std::chrono::milliseconds(mediumFramerate); //Chat can run at a lower "fps"
|
t += std::chrono::milliseconds(chatFrameDelta); //Chat can run at a lower "fps"
|
||||||
std::this_thread::sleep_until(t);
|
std::this_thread::sleep_until(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,15 +6,25 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include "../thirdparty/raknet/Source/BitStream.h"
|
#include "BitStream.h"
|
||||||
|
|
||||||
#pragma warning (disable:4251) //Disables SQL warnings
|
#pragma warning (disable:4251) //Disables SQL warnings
|
||||||
|
|
||||||
typedef int RESTICKET;
|
typedef int RESTICKET;
|
||||||
|
|
||||||
const int highFrameRate = 16; //60fps
|
// These are the same define, but they mean two different things in different contexts
|
||||||
const int mediumFramerate = 33; //30fps
|
// so a different define to distinguish what calculation is happening will help clarity.
|
||||||
const int lowFramerate = 66; //15fps
|
#define FRAMES_TO_MS(x) 1000 / x
|
||||||
|
#define MS_TO_FRAMES(x) 1000 / x
|
||||||
|
|
||||||
|
//=========== FRAME TIMINGS ===========
|
||||||
|
constexpr uint32_t highFramerate = 60;
|
||||||
|
constexpr uint32_t mediumFramerate = 30;
|
||||||
|
constexpr uint32_t lowFramerate = 15;
|
||||||
|
|
||||||
|
constexpr uint32_t highFrameDelta = FRAMES_TO_MS(highFramerate);
|
||||||
|
constexpr uint32_t mediumFrameDelta = FRAMES_TO_MS(mediumFramerate);
|
||||||
|
constexpr uint32_t lowFrameDelta = FRAMES_TO_MS(lowFramerate);
|
||||||
|
|
||||||
//========== MACROS ===========
|
//========== MACROS ===========
|
||||||
|
|
||||||
|
@ -208,7 +208,7 @@ void ScriptedActivityComponent::PlayerLeave(LWOOBJID playerID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ScriptedActivityComponent::Update(float deltaTime) {
|
void ScriptedActivityComponent::Update(float deltaTime) {
|
||||||
|
std::vector<Lobby*> lobbiesToRemove{};
|
||||||
// Ticks all the lobbies, not applicable for non-instance activities
|
// Ticks all the lobbies, not applicable for non-instance activities
|
||||||
for (Lobby* lobby : m_Queue) {
|
for (Lobby* lobby : m_Queue) {
|
||||||
for (LobbyPlayer* player : lobby->players) {
|
for (LobbyPlayer* player : lobby->players) {
|
||||||
@ -219,6 +219,11 @@ void ScriptedActivityComponent::Update(float deltaTime) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lobby->players.empty()) {
|
||||||
|
lobbiesToRemove.push_back(lobby);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Update the match time for all players
|
// Update the match time for all players
|
||||||
if (m_ActivityInfo.maxTeamSize != 1 && lobby->players.size() >= m_ActivityInfo.minTeamSize
|
if (m_ActivityInfo.maxTeamSize != 1 && lobby->players.size() >= m_ActivityInfo.minTeamSize
|
||||||
|| m_ActivityInfo.maxTeamSize == 1 && lobby->players.size() >= m_ActivityInfo.minTeams) {
|
|| m_ActivityInfo.maxTeamSize == 1 && lobby->players.size() >= m_ActivityInfo.minTeams) {
|
||||||
@ -262,13 +267,17 @@ void ScriptedActivityComponent::Update(float deltaTime) {
|
|||||||
// The timer has elapsed, start the instance
|
// The timer has elapsed, start the instance
|
||||||
if (lobby->timer <= 0.0f) {
|
if (lobby->timer <= 0.0f) {
|
||||||
Game::logger->Log("ScriptedActivityComponent", "Setting up instance.");
|
Game::logger->Log("ScriptedActivityComponent", "Setting up instance.");
|
||||||
|
|
||||||
ActivityInstance* instance = NewInstance();
|
ActivityInstance* instance = NewInstance();
|
||||||
LoadPlayersIntoInstance(instance, lobby->players);
|
LoadPlayersIntoInstance(instance, lobby->players);
|
||||||
RemoveLobby(lobby);
|
|
||||||
instance->StartZone();
|
instance->StartZone();
|
||||||
|
lobbiesToRemove.push_back(lobby);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (!lobbiesToRemove.empty()) {
|
||||||
|
RemoveLobby(lobbiesToRemove.front());
|
||||||
|
lobbiesToRemove.erase(lobbiesToRemove.begin());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptedActivityComponent::RemoveLobby(Lobby* lobby) {
|
void ScriptedActivityComponent::RemoveLobby(Lobby* lobby) {
|
||||||
|
@ -31,6 +31,15 @@ Instance* InstanceManager::GetInstance(LWOMAPID mapID, bool isFriendTransfer, LW
|
|||||||
Instance* instance = FindInstance(mapID, isFriendTransfer, cloneID);
|
Instance* instance = FindInstance(mapID, isFriendTransfer, cloneID);
|
||||||
if (instance) return instance;
|
if (instance) return instance;
|
||||||
|
|
||||||
|
// If we are shutting down, return a nullptr so a new instance is not created.
|
||||||
|
if (m_IsShuttingDown) {
|
||||||
|
Game::logger->Log("InstanceManager",
|
||||||
|
"Tried to create a new instance map/instance/clone %i/%i/%i, but Master is shutting down.",
|
||||||
|
mapID,
|
||||||
|
m_LastInstanceID + 1,
|
||||||
|
cloneID);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
//TODO: Update this so that the IP is read from a configuration file instead
|
//TODO: Update this so that the IP is read from a configuration file instead
|
||||||
|
|
||||||
int softCap = 8;
|
int softCap = 8;
|
||||||
@ -238,7 +247,7 @@ void InstanceManager::RedirectPendingRequests(Instance* instance) {
|
|||||||
for (const auto& request : instance->GetPendingAffirmations()) {
|
for (const auto& request : instance->GetPendingAffirmations()) {
|
||||||
auto* in = Game::im->GetInstance(zoneId.GetMapID(), false, zoneId.GetCloneID());
|
auto* in = Game::im->GetInstance(zoneId.GetMapID(), false, zoneId.GetCloneID());
|
||||||
|
|
||||||
if (!in->GetIsReady()) // Instance not ready, make a pending request
|
if (in && !in->GetIsReady()) // Instance not ready, make a pending request
|
||||||
{
|
{
|
||||||
in->GetPendingRequests().push_back(request);
|
in->GetPendingRequests().push_back(request);
|
||||||
|
|
||||||
@ -295,6 +304,15 @@ Instance* InstanceManager::CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID clon
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_IsShuttingDown) {
|
||||||
|
Game::logger->Log("InstanceManager",
|
||||||
|
"Tried to create a new private instance map/instance/clone %i/%i/%i, but Master is shutting down.",
|
||||||
|
mapID,
|
||||||
|
m_LastInstanceID + 1,
|
||||||
|
cloneID);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
int maxPlayers = 999;
|
int maxPlayers = 999;
|
||||||
|
|
||||||
uint32_t port = GetFreePort();
|
uint32_t port = GetFreePort();
|
||||||
|
@ -128,6 +128,7 @@ public:
|
|||||||
|
|
||||||
Instance* CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID cloneID, const std::string& password);
|
Instance* CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID cloneID, const std::string& password);
|
||||||
Instance* FindPrivateInstance(const std::string& password);
|
Instance* FindPrivateInstance(const std::string& password);
|
||||||
|
void SetIsShuttingDown(bool value) { this->m_IsShuttingDown = value; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
dLogger* mLogger;
|
dLogger* mLogger;
|
||||||
@ -136,6 +137,11 @@ private:
|
|||||||
unsigned short m_LastPort;
|
unsigned short m_LastPort;
|
||||||
LWOINSTANCEID m_LastInstanceID;
|
LWOINSTANCEID m_LastInstanceID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the master server is currently shutting down.
|
||||||
|
*/
|
||||||
|
bool m_IsShuttingDown = false;
|
||||||
|
|
||||||
//Private functions:
|
//Private functions:
|
||||||
bool IsInstanceFull(Instance* instance, bool isFriendTransfer);
|
bool IsInstanceFull(Instance* instance, bool isFriendTransfer);
|
||||||
int GetSoftCap(LWOMAPID mapID);
|
int GetSoftCap(LWOMAPID mapID);
|
||||||
|
@ -52,8 +52,8 @@ namespace Game {
|
|||||||
} //namespace Game
|
} //namespace Game
|
||||||
|
|
||||||
bool shutdownSequenceStarted = false;
|
bool shutdownSequenceStarted = false;
|
||||||
void ShutdownSequence(int signal = -1);
|
void ShutdownSequence(int32_t signal = -1);
|
||||||
int FinalizeShutdown(int signal = -1);
|
int32_t FinalizeShutdown(int32_t signal = -1);
|
||||||
dLogger* SetupLogger();
|
dLogger* SetupLogger();
|
||||||
void StartAuthServer();
|
void StartAuthServer();
|
||||||
void StartChatServer();
|
void StartChatServer();
|
||||||
@ -63,6 +63,8 @@ SystemAddress authServerMasterPeerSysAddr;
|
|||||||
SystemAddress chatServerMasterPeerSysAddr;
|
SystemAddress chatServerMasterPeerSysAddr;
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
constexpr uint32_t masterFramerate = mediumFramerate;
|
||||||
|
constexpr uint32_t masterFrameDelta = mediumFrameDelta;
|
||||||
Diagnostics::SetProcessName("Master");
|
Diagnostics::SetProcessName("Master");
|
||||||
Diagnostics::SetProcessFileName(argv[0]);
|
Diagnostics::SetProcessFileName(argv[0]);
|
||||||
Diagnostics::Initialize();
|
Diagnostics::Initialize();
|
||||||
@ -73,8 +75,8 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
//Triggers the shutdown sequence at application exit
|
//Triggers the shutdown sequence at application exit
|
||||||
std::atexit([]() { ShutdownSequence(); });
|
std::atexit([]() { ShutdownSequence(); });
|
||||||
signal(SIGINT, [](int signal) { ShutdownSequence(EXIT_FAILURE); });
|
signal(SIGINT, [](int32_t signal) { ShutdownSequence(EXIT_FAILURE); });
|
||||||
signal(SIGTERM, [](int signal) { ShutdownSequence(EXIT_FAILURE); });
|
signal(SIGTERM, [](int32_t signal) { ShutdownSequence(EXIT_FAILURE); });
|
||||||
|
|
||||||
//Create all the objects we need to run our service:
|
//Create all the objects we need to run our service:
|
||||||
Game::logger = SetupLogger();
|
Game::logger = SetupLogger();
|
||||||
@ -237,8 +239,8 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxClients = 999;
|
uint32_t maxClients = 999;
|
||||||
int ourPort = 1000;
|
uint32_t ourPort = 1000;
|
||||||
if (Game::config->GetValue("max_clients") != "") maxClients = std::stoi(Game::config->GetValue("max_clients"));
|
if (Game::config->GetValue("max_clients") != "") maxClients = std::stoi(Game::config->GetValue("max_clients"));
|
||||||
if (Game::config->GetValue("port") != "") ourPort = std::stoi(Game::config->GetValue("port"));
|
if (Game::config->GetValue("port") != "") ourPort = std::stoi(Game::config->GetValue("port"));
|
||||||
|
|
||||||
@ -287,9 +289,13 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
auto t = std::chrono::high_resolution_clock::now();
|
auto t = std::chrono::high_resolution_clock::now();
|
||||||
Packet* packet = nullptr;
|
Packet* packet = nullptr;
|
||||||
int framesSinceLastFlush = 0;
|
constexpr uint32_t logFlushTime = 15 * masterFramerate;
|
||||||
int framesSinceLastSQLPing = 0;
|
constexpr uint32_t sqlPingTime = 10 * 60 * masterFramerate;
|
||||||
int framesSinceKillUniverseCommand = 0;
|
constexpr uint32_t shutdownUniverseTime = 10 * 60 * masterFramerate;
|
||||||
|
constexpr uint32_t instanceReadyTimeout = 30 * masterFramerate;
|
||||||
|
uint32_t framesSinceLastFlush = 0;
|
||||||
|
uint32_t framesSinceLastSQLPing = 0;
|
||||||
|
uint32_t framesSinceKillUniverseCommand = 0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
//In world we'd update our other systems here.
|
//In world we'd update our other systems here.
|
||||||
@ -303,17 +309,17 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Push our log every 15s:
|
//Push our log every 15s:
|
||||||
if (framesSinceLastFlush >= 900) {
|
if (framesSinceLastFlush >= logFlushTime) {
|
||||||
Game::logger->Flush();
|
Game::logger->Flush();
|
||||||
framesSinceLastFlush = 0;
|
framesSinceLastFlush = 0;
|
||||||
} else
|
} else
|
||||||
framesSinceLastFlush++;
|
framesSinceLastFlush++;
|
||||||
|
|
||||||
//Every 10 min we ping our sql server to keep it alive hopefully:
|
//Every 10 min we ping our sql server to keep it alive hopefully:
|
||||||
if (framesSinceLastSQLPing >= 40000) {
|
if (framesSinceLastSQLPing >= sqlPingTime) {
|
||||||
//Find out the master's IP for absolutely no reason:
|
//Find out the master's IP for absolutely no reason:
|
||||||
std::string masterIP;
|
std::string masterIP;
|
||||||
int masterPort;
|
uint32_t masterPort;
|
||||||
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
||||||
auto res = stmt->executeQuery();
|
auto res = stmt->executeQuery();
|
||||||
while (res->next()) {
|
while (res->next()) {
|
||||||
@ -330,7 +336,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
//10m shutdown for universe kill command
|
//10m shutdown for universe kill command
|
||||||
if (Game::shouldShutdown) {
|
if (Game::shouldShutdown) {
|
||||||
if (framesSinceKillUniverseCommand >= 40000) {
|
if (framesSinceKillUniverseCommand >= shutdownUniverseTime) {
|
||||||
//Break main loop and exit
|
//Break main loop and exit
|
||||||
break;
|
break;
|
||||||
} else
|
} else
|
||||||
@ -354,7 +360,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
instance->SetAffirmationTimeout(affirmTimeout);
|
instance->SetAffirmationTimeout(affirmTimeout);
|
||||||
|
|
||||||
if (affirmTimeout == 1000) {
|
if (affirmTimeout == instanceReadyTimeout) {
|
||||||
instance->Shutdown();
|
instance->Shutdown();
|
||||||
instance->SetIsShuttingDown(true);
|
instance->SetIsShuttingDown(true);
|
||||||
|
|
||||||
@ -373,7 +379,7 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t += std::chrono::milliseconds(highFrameRate);
|
t += std::chrono::milliseconds(masterFrameDelta);
|
||||||
std::this_thread::sleep_until(t);
|
std::this_thread::sleep_until(t);
|
||||||
}
|
}
|
||||||
return FinalizeShutdown(EXIT_SUCCESS);
|
return FinalizeShutdown(EXIT_SUCCESS);
|
||||||
@ -424,7 +430,6 @@ void HandlePacket(Packet* packet) {
|
|||||||
if (instance) {
|
if (instance) {
|
||||||
LWOZONEID zoneID = instance->GetZoneID(); //Get the zoneID so we can recreate a server
|
LWOZONEID zoneID = instance->GetZoneID(); //Get the zoneID so we can recreate a server
|
||||||
Game::im->RemoveInstance(instance); //Delete the old
|
Game::im->RemoveInstance(instance); //Delete the old
|
||||||
//Game::im->GetInstance(zoneID.GetMapID(), false, 0); //Create the new
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet->systemAddress == chatServerMasterPeerSysAddr) {
|
if (packet->systemAddress == chatServerMasterPeerSysAddr) {
|
||||||
@ -465,14 +470,17 @@ void HandlePacket(Packet* packet) {
|
|||||||
inStream.Read(mythranShift);
|
inStream.Read(mythranShift);
|
||||||
inStream.Read(zoneID);
|
inStream.Read(zoneID);
|
||||||
inStream.Read(zoneClone);
|
inStream.Read(zoneClone);
|
||||||
|
if (shutdownSequenceStarted) {
|
||||||
|
Game::logger->Log("MasterServer", "Shutdown sequence has been started. Not creating a new zone.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
Instance* in = Game::im->GetInstance(zoneID, false, zoneClone);
|
Instance* in = Game::im->GetInstance(zoneID, false, zoneClone);
|
||||||
|
|
||||||
for (auto* instance : Game::im->GetInstances()) {
|
for (auto* instance : Game::im->GetInstances()) {
|
||||||
Game::logger->Log("MasterServer", "Instance: %i/%i/%i -> %i", instance->GetMapID(), instance->GetCloneID(), instance->GetInstanceID(), instance == in);
|
Game::logger->Log("MasterServer", "Instance: %i/%i/%i -> %i", instance->GetMapID(), instance->GetCloneID(), instance->GetInstanceID(), instance == in);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!in->GetIsReady()) //Instance not ready, make a pending request
|
if (in && !in->GetIsReady()) //Instance not ready, make a pending request
|
||||||
{
|
{
|
||||||
in->GetPendingRequests().push_back({ requestID, static_cast<bool>(mythranShift), packet->systemAddress });
|
in->GetPendingRequests().push_back({ requestID, static_cast<bool>(mythranShift), packet->systemAddress });
|
||||||
Game::logger->Log("MasterServer", "Server not ready, adding pending request %llu %i %i", requestID, zoneID, zoneClone);
|
Game::logger->Log("MasterServer", "Server not ready, adding pending request %llu %i %i", requestID, zoneID, zoneClone);
|
||||||
@ -644,7 +652,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
|
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
inStream.Read<uint32_t>(len);
|
inStream.Read<uint32_t>(len);
|
||||||
for (int i = 0; len > i; i++) {
|
for (uint32_t i = 0; len > i; i++) {
|
||||||
char character;
|
char character;
|
||||||
inStream.Read<char>(character);
|
inStream.Read<char>(character);
|
||||||
password += character;
|
password += character;
|
||||||
@ -670,7 +678,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
uint32_t len;
|
uint32_t len;
|
||||||
inStream.Read<uint32_t>(len);
|
inStream.Read<uint32_t>(len);
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (uint32_t i = 0; i < len; i++) {
|
||||||
char character; inStream.Read<char>(character);
|
char character; inStream.Read<char>(character);
|
||||||
password += character;
|
password += character;
|
||||||
}
|
}
|
||||||
@ -718,11 +726,15 @@ void HandlePacket(Packet* packet) {
|
|||||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
uint64_t header = inStream.Read(header);
|
uint64_t header = inStream.Read(header);
|
||||||
|
|
||||||
int zoneID;
|
int32_t zoneID;
|
||||||
inStream.Read(zoneID);
|
inStream.Read(zoneID);
|
||||||
|
if (shutdownSequenceStarted) {
|
||||||
|
Game::logger->Log("MasterServer", "Shutdown sequence has been started. Not prepping a new zone.");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
Game::logger->Log("MasterServer", "Prepping zone %i", zoneID);
|
Game::logger->Log("MasterServer", "Prepping zone %i", zoneID);
|
||||||
Game::im->GetInstance(zoneID, false, 0);
|
Game::im->GetInstance(zoneID, false, 0);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,7 +783,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
Game::logger->Log("MasterServer", "Unknown master packet ID from server: %i", packet->data[3]);
|
Game::logger->Log("MasterServer", "Unknown master packet ID from server: %i", packet->data[3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartChatServer() {
|
void StartChatServer() {
|
||||||
if (Game::shouldShutdown) {
|
if (Game::shouldShutdown) {
|
||||||
@ -788,9 +800,9 @@ void StartChatServer() {
|
|||||||
auto result = system(("sudo " + (BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str());
|
auto result = system(("sudo " + (BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str());
|
||||||
} else {
|
} else {
|
||||||
auto result = system(((BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str());
|
auto result = system(((BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartAuthServer() {
|
void StartAuthServer() {
|
||||||
if (Game::shouldShutdown) {
|
if (Game::shouldShutdown) {
|
||||||
@ -806,15 +818,20 @@ void StartAuthServer() {
|
|||||||
auto result = system(("sudo " + (BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str());
|
auto result = system(("sudo " + (BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str());
|
||||||
} else {
|
} else {
|
||||||
auto result = system(((BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str());
|
auto result = system(((BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShutdownSequence(int signal) {
|
void ShutdownSequence(int32_t signal) {
|
||||||
if (shutdownSequenceStarted) {
|
if (shutdownSequenceStarted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Game::im) {
|
||||||
|
FinalizeShutdown(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::im->SetIsShuttingDown(true);
|
||||||
shutdownSequenceStarted = true;
|
shutdownSequenceStarted = true;
|
||||||
Game::shouldShutdown = true;
|
Game::shouldShutdown = true;
|
||||||
|
|
||||||
@ -826,40 +843,38 @@ void ShutdownSequence(int signal) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto* objIdManager = ObjectIDManager::TryInstance();
|
auto* objIdManager = ObjectIDManager::TryInstance();
|
||||||
if (objIdManager != nullptr) {
|
if (objIdManager) {
|
||||||
objIdManager->SaveToDatabase();
|
objIdManager->SaveToDatabase();
|
||||||
Game::logger->Log("MasterServer", "Saved ObjectIDTracker to DB");
|
Game::logger->Log("MasterServer", "Saved ObjectIDTracker to DB");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto t = std::chrono::high_resolution_clock::now();
|
|
||||||
auto ticks = 0;
|
|
||||||
|
|
||||||
if (!Game::im) {
|
|
||||||
FinalizeShutdown(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// A server might not be finished spinning up yet, remove all of those here.
|
// A server might not be finished spinning up yet, remove all of those here.
|
||||||
for (auto instance : Game::im->GetInstances()) {
|
for (auto* instance : Game::im->GetInstances()) {
|
||||||
if (!instance->GetIsReady()) {
|
if (!instance->GetIsReady()) {
|
||||||
Game::im->RemoveInstance(instance);
|
Game::im->RemoveInstance(instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto instance : Game::im->GetInstances()) {
|
for (auto* instance : Game::im->GetInstances()) {
|
||||||
instance->SetIsShuttingDown(true);
|
instance->SetIsShuttingDown(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::logger->Log("MasterServer", "Attempting to shutdown instances, max 60 seconds...");
|
Game::logger->Log("MasterServer", "Attempting to shutdown instances, max 60 seconds...");
|
||||||
|
|
||||||
|
auto t = std::chrono::high_resolution_clock::now();
|
||||||
|
uint32_t framesSinceShutdownStart = 0;
|
||||||
|
constexpr uint32_t maxShutdownTime = 60 * mediumFramerate;
|
||||||
|
bool allInstancesShutdown = false;
|
||||||
|
Packet* packet = nullptr;
|
||||||
while (true) {
|
while (true) {
|
||||||
auto packet = Game::server->Receive();
|
packet = Game::server->Receive();
|
||||||
if (packet) {
|
if (packet) {
|
||||||
HandlePacket(packet);
|
HandlePacket(packet);
|
||||||
Game::server->DeallocatePacket(packet);
|
Game::server->DeallocatePacket(packet);
|
||||||
packet = nullptr;
|
packet = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto done = true;
|
allInstancesShutdown = true;
|
||||||
|
|
||||||
for (auto* instance : Game::im->GetInstances()) {
|
for (auto* instance : Game::im->GetInstances()) {
|
||||||
if (instance == nullptr) {
|
if (instance == nullptr) {
|
||||||
@ -867,21 +882,21 @@ void ShutdownSequence(int signal) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!instance->GetShutdownComplete()) {
|
if (!instance->GetShutdownComplete()) {
|
||||||
done = false;
|
allInstancesShutdown = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (done && authServerMasterPeerSysAddr == UNASSIGNED_SYSTEM_ADDRESS && chatServerMasterPeerSysAddr == UNASSIGNED_SYSTEM_ADDRESS) {
|
if (allInstancesShutdown && authServerMasterPeerSysAddr == UNASSIGNED_SYSTEM_ADDRESS && chatServerMasterPeerSysAddr == UNASSIGNED_SYSTEM_ADDRESS) {
|
||||||
Game::logger->Log("MasterServer", "Finished shutting down MasterServer!");
|
Game::logger->Log("MasterServer", "Finished shutting down MasterServer!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
t += std::chrono::milliseconds(highFrameRate);
|
t += std::chrono::milliseconds(mediumFrameDelta);
|
||||||
std::this_thread::sleep_until(t);
|
std::this_thread::sleep_until(t);
|
||||||
|
|
||||||
ticks++;
|
framesSinceShutdownStart++;
|
||||||
|
|
||||||
if (ticks == 600 * 6) {
|
if (framesSinceShutdownStart == maxShutdownTime) {
|
||||||
Game::logger->Log("MasterServer", "Finished shutting down by timeout!");
|
Game::logger->Log("MasterServer", "Finished shutting down by timeout!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -890,7 +905,7 @@ void ShutdownSequence(int signal) {
|
|||||||
FinalizeShutdown(signal);
|
FinalizeShutdown(signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
int FinalizeShutdown(int signal) {
|
int32_t FinalizeShutdown(int32_t signal) {
|
||||||
//Delete our objects here:
|
//Delete our objects here:
|
||||||
Database::Destroy("MasterServer");
|
Database::Destroy("MasterServer");
|
||||||
if (Game::config) delete Game::config;
|
if (Game::config) delete Game::config;
|
||||||
|
@ -2,23 +2,18 @@
|
|||||||
|
|
||||||
#include "UserManager.h"
|
#include "UserManager.h"
|
||||||
|
|
||||||
//Times are 1 / fps, in ms
|
#define SOCIAL { lowFrameDelta }
|
||||||
#define HIGH 16 //60 fps
|
#define SOCIAL_HUB { mediumFrameDelta } //Added to compensate for the large playercounts in NS and NT
|
||||||
#define MEDIUM 33 //30 fps
|
#define BATTLE { highFrameDelta }
|
||||||
#define LOW 66 //15 fps
|
#define BATTLE_INSTANCE { mediumFrameDelta }
|
||||||
|
#define RACE { highFrameDelta }
|
||||||
#define SOCIAL { LOW }
|
#define PROPERTY { lowFrameDelta }
|
||||||
#define SOCIAL_HUB { MEDIUM } //Added to compensate for the large playercounts in NS and NT
|
|
||||||
#define BATTLE { HIGH }
|
|
||||||
#define BATTLE_INSTANCE { MEDIUM }
|
|
||||||
#define RACE { HIGH }
|
|
||||||
#define PROPERTY { LOW }
|
|
||||||
|
|
||||||
PerformanceProfile PerformanceManager::m_CurrentProfile = SOCIAL;
|
PerformanceProfile PerformanceManager::m_CurrentProfile = SOCIAL;
|
||||||
|
|
||||||
PerformanceProfile PerformanceManager::m_DefaultProfile = SOCIAL;
|
PerformanceProfile PerformanceManager::m_DefaultProfile = SOCIAL;
|
||||||
|
|
||||||
PerformanceProfile PerformanceManager::m_InactiveProfile = { LOW };
|
PerformanceProfile PerformanceManager::m_InactiveProfile = { lowFrameDelta };
|
||||||
|
|
||||||
std::map<LWOMAPID, PerformanceProfile> PerformanceManager::m_Profiles = {
|
std::map<LWOMAPID, PerformanceProfile> PerformanceManager::m_Profiles = {
|
||||||
// VE
|
// VE
|
||||||
@ -72,13 +67,6 @@ std::map<LWOMAPID, PerformanceProfile> PerformanceManager::m_Profiles = {
|
|||||||
{ 2001, BATTLE_INSTANCE },
|
{ 2001, BATTLE_INSTANCE },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
PerformanceManager::PerformanceManager() {
|
|
||||||
}
|
|
||||||
|
|
||||||
PerformanceManager::~PerformanceManager() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void PerformanceManager::SelectProfile(LWOMAPID mapID) {
|
void PerformanceManager::SelectProfile(LWOMAPID mapID) {
|
||||||
const auto pair = m_Profiles.find(mapID);
|
const auto pair = m_Profiles.find(mapID);
|
||||||
|
|
||||||
@ -91,10 +79,10 @@ void PerformanceManager::SelectProfile(LWOMAPID mapID) {
|
|||||||
m_CurrentProfile = pair->second;
|
m_CurrentProfile = pair->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t PerformanceManager::GetServerFramerate() {
|
uint32_t PerformanceManager::GetServerFrameDelta() {
|
||||||
if (UserManager::Instance()->GetUserCount() == 0) {
|
if (UserManager::Instance()->GetUserCount() == 0) {
|
||||||
return m_InactiveProfile.serverFramerate;
|
return m_InactiveProfile.serverFrameDelta;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_CurrentProfile.serverFramerate;
|
return m_CurrentProfile.serverFrameDelta;
|
||||||
}
|
}
|
||||||
|
@ -5,21 +5,16 @@
|
|||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
|
|
||||||
struct PerformanceProfile {
|
struct PerformanceProfile {
|
||||||
uint32_t serverFramerate;
|
uint32_t serverFrameDelta;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class PerformanceManager {
|
class PerformanceManager {
|
||||||
public:
|
public:
|
||||||
~PerformanceManager();
|
|
||||||
|
|
||||||
static void SelectProfile(LWOMAPID mapID);
|
static void SelectProfile(LWOMAPID mapID);
|
||||||
|
|
||||||
static uint32_t GetServerFramerate();
|
static uint32_t GetServerFrameDelta();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PerformanceManager();
|
|
||||||
|
|
||||||
static PerformanceProfile m_CurrentProfile;
|
static PerformanceProfile m_CurrentProfile;
|
||||||
static PerformanceProfile m_DefaultProfile;
|
static PerformanceProfile m_DefaultProfile;
|
||||||
static PerformanceProfile m_InactiveProfile;
|
static PerformanceProfile m_InactiveProfile;
|
||||||
|
@ -82,7 +82,7 @@ void WorldShutdownProcess(uint32_t zoneId);
|
|||||||
void FinalizeShutdown();
|
void FinalizeShutdown();
|
||||||
void SendShutdownMessageToMaster();
|
void SendShutdownMessageToMaster();
|
||||||
|
|
||||||
dLogger* SetupLogger(int zoneID, int instanceID);
|
dLogger* SetupLogger(uint32_t zoneID, uint32_t instanceID);
|
||||||
void HandlePacketChat(Packet* packet);
|
void HandlePacketChat(Packet* packet);
|
||||||
void HandlePacket(Packet* packet);
|
void HandlePacket(Packet* packet);
|
||||||
|
|
||||||
@ -92,8 +92,8 @@ struct tempSessionInfo {
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::map<std::string, tempSessionInfo> m_PendingUsers;
|
std::map<std::string, tempSessionInfo> m_PendingUsers;
|
||||||
int instanceID = 0;
|
uint32_t instanceID = 0;
|
||||||
int g_CloneID = 0;
|
uint32_t g_CloneID = 0;
|
||||||
std::string databaseChecksum = "";
|
std::string databaseChecksum = "";
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
@ -107,13 +107,13 @@ int main(int argc, char** argv) {
|
|||||||
signal(SIGINT, [](int) { WorldShutdownSequence(); });
|
signal(SIGINT, [](int) { WorldShutdownSequence(); });
|
||||||
signal(SIGTERM, [](int) { WorldShutdownSequence(); });
|
signal(SIGTERM, [](int) { WorldShutdownSequence(); });
|
||||||
|
|
||||||
int zoneID = 1000;
|
uint32_t zoneID = 1000;
|
||||||
int cloneID = 0;
|
uint32_t cloneID = 0;
|
||||||
int maxClients = 8;
|
uint32_t maxClients = 8;
|
||||||
int ourPort = 2007;
|
uint32_t ourPort = 2007;
|
||||||
|
|
||||||
//Check our arguments:
|
//Check our arguments:
|
||||||
for (int i = 0; i < argc; ++i) {
|
for (int32_t i = 0; i < argc; ++i) {
|
||||||
std::string argument(argv[i]);
|
std::string argument(argv[i]);
|
||||||
|
|
||||||
if (argument == "-zone") zoneID = atoi(argv[i + 1]);
|
if (argument == "-zone") zoneID = atoi(argv[i + 1]);
|
||||||
@ -185,7 +185,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
//Find out the master's IP:
|
//Find out the master's IP:
|
||||||
std::string masterIP = "localhost";
|
std::string masterIP = "localhost";
|
||||||
int masterPort = 1000;
|
uint32_t masterPort = 1000;
|
||||||
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
||||||
auto res = stmt->executeQuery();
|
auto res = stmt->executeQuery();
|
||||||
while (res->next()) {
|
while (res->next()) {
|
||||||
@ -204,7 +204,7 @@ int main(int argc, char** argv) {
|
|||||||
Game::server = new dServer(masterIP, ourPort, instanceID, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::World, Game::config, &Game::shouldShutdown, zoneID);
|
Game::server = new dServer(masterIP, ourPort, instanceID, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::World, Game::config, &Game::shouldShutdown, zoneID);
|
||||||
|
|
||||||
//Connect to the chat server:
|
//Connect to the chat server:
|
||||||
int chatPort = 1501;
|
uint32_t chatPort = 1501;
|
||||||
if (Game::config->GetValue("chat_server_port") != "") chatPort = std::atoi(Game::config->GetValue("chat_server_port").c_str());
|
if (Game::config->GetValue("chat_server_port") != "") chatPort = std::atoi(Game::config->GetValue("chat_server_port").c_str());
|
||||||
|
|
||||||
auto chatSock = SocketDescriptor(uint16_t(ourPort + 2), 0);
|
auto chatSock = SocketDescriptor(uint16_t(ourPort + 2), 0);
|
||||||
@ -220,22 +220,22 @@ int main(int argc, char** argv) {
|
|||||||
auto t = std::chrono::high_resolution_clock::now();
|
auto t = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
Packet* packet = nullptr;
|
Packet* packet = nullptr;
|
||||||
int framesSinceLastFlush = 0;
|
uint32_t framesSinceLastFlush = 0;
|
||||||
int framesSinceMasterDisconnect = 0;
|
uint32_t framesSinceMasterDisconnect = 0;
|
||||||
int framesSinceChatDisconnect = 0;
|
uint32_t framesSinceChatDisconnect = 0;
|
||||||
int framesSinceLastUsersSave = 0;
|
uint32_t framesSinceLastUsersSave = 0;
|
||||||
int framesSinceLastSQLPing = 0;
|
uint32_t framesSinceLastSQLPing = 0;
|
||||||
int framesSinceLastUser = 0;
|
uint32_t framesSinceLastUser = 0;
|
||||||
|
|
||||||
const float maxPacketProcessingTime = 1.5f; //0.015f;
|
const float maxPacketProcessingTime = 1.5f; //0.015f;
|
||||||
const int maxPacketsToProcess = 1024;
|
const uint32_t maxPacketsToProcess = 1024;
|
||||||
|
|
||||||
bool ready = false;
|
bool ready = false;
|
||||||
int framesSinceMasterStatus = 0;
|
uint32_t framesSinceMasterStatus = 0;
|
||||||
int framesSinceShutdownSequence = 0;
|
uint32_t framesSinceShutdownSequence = 0;
|
||||||
int currentFramerate = highFrameRate;
|
uint32_t currentFramerate = highFramerate;
|
||||||
|
|
||||||
int ghostingStepCount = 0;
|
uint32_t ghostingStepCount = 0;
|
||||||
auto ghostingLastTime = std::chrono::high_resolution_clock::now();
|
auto ghostingLastTime = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
PerformanceManager::SelectProfile(zoneID);
|
PerformanceManager::SelectProfile(zoneID);
|
||||||
@ -264,7 +264,7 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int bufferSize = 1024;
|
const int32_t bufferSize = 1024;
|
||||||
MD5* md5 = new MD5();
|
MD5* md5 = new MD5();
|
||||||
|
|
||||||
char fileStreamBuffer[1024] = {};
|
char fileStreamBuffer[1024] = {};
|
||||||
@ -288,6 +288,14 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t currentFrameDelta = highFrameDelta;
|
||||||
|
// These values are adjust them selves to the current framerate should it update.
|
||||||
|
uint32_t logFlushTime = 15 * currentFramerate; // 15 seconds in frames
|
||||||
|
uint32_t shutdownTimeout = 10 * 60 * currentFramerate; // 10 minutes in frames
|
||||||
|
uint32_t noMasterConnectionTimeout = 5 * currentFramerate; // 5 seconds in frames
|
||||||
|
uint32_t chatReconnectionTime = 30 * currentFramerate; // 30 seconds in frames
|
||||||
|
uint32_t saveTime = 10 * 60 * currentFramerate; // 10 minutes in frames
|
||||||
|
uint32_t sqlPingTime = 10 * 60 * currentFramerate; // 10 minutes in frames
|
||||||
while (true) {
|
while (true) {
|
||||||
Metrics::StartMeasurement(MetricVariable::Frame);
|
Metrics::StartMeasurement(MetricVariable::Frame);
|
||||||
Metrics::StartMeasurement(MetricVariable::GameLoop);
|
Metrics::StartMeasurement(MetricVariable::GameLoop);
|
||||||
@ -300,24 +308,44 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
const auto occupied = UserManager::Instance()->GetUserCount() != 0;
|
const auto occupied = UserManager::Instance()->GetUserCount() != 0;
|
||||||
|
|
||||||
|
uint32_t newFrameDelta = currentFrameDelta;
|
||||||
if (!ready) {
|
if (!ready) {
|
||||||
currentFramerate = highFrameRate;
|
newFrameDelta = highFrameDelta;
|
||||||
} else {
|
} else {
|
||||||
currentFramerate = PerformanceManager::GetServerFramerate();
|
newFrameDelta = PerformanceManager::GetServerFrameDelta();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update to the new framerate and scale all timings to said new framerate
|
||||||
|
if (newFrameDelta != currentFrameDelta) {
|
||||||
|
float_t ratioBeforeToAfter = (float)currentFrameDelta / (float)newFrameDelta;
|
||||||
|
currentFrameDelta = newFrameDelta;
|
||||||
|
currentFramerate = MS_TO_FRAMES(newFrameDelta);
|
||||||
|
Game::logger->LogDebug("WorldServer", "Framerate for zone/instance/clone %i/%i/%i is now %i", zoneID, instanceID, cloneID, currentFramerate);
|
||||||
|
logFlushTime = 15 * currentFramerate; // 15 seconds in frames
|
||||||
|
framesSinceLastFlush *= ratioBeforeToAfter;
|
||||||
|
shutdownTimeout = 10 * 60 * currentFramerate; // 10 minutes in frames
|
||||||
|
framesSinceLastUser *= ratioBeforeToAfter;
|
||||||
|
noMasterConnectionTimeout = 5 * currentFramerate; // 5 seconds in frames
|
||||||
|
framesSinceMasterDisconnect *= ratioBeforeToAfter;
|
||||||
|
chatReconnectionTime = 30 * currentFramerate; // 30 seconds in frames
|
||||||
|
framesSinceChatDisconnect *= ratioBeforeToAfter;
|
||||||
|
saveTime = 10 * 60 * currentFramerate; // 10 minutes in frames
|
||||||
|
framesSinceLastUsersSave *= ratioBeforeToAfter;
|
||||||
|
sqlPingTime = 10 * 60 * currentFramerate; // 10 minutes in frames
|
||||||
|
framesSinceLastSQLPing *= ratioBeforeToAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Warning if we ran slow
|
//Warning if we ran slow
|
||||||
if (deltaTime > currentFramerate) {
|
if (deltaTime > currentFrameDelta) {
|
||||||
Game::logger->Log("WorldServer", "We're running behind, dT: %f > %f (framerate)", deltaTime, currentFramerate);
|
Game::logger->Log("WorldServer", "We're running behind, dT: %f > %f (framerate %i)", deltaTime, currentFrameDelta, currentFramerate);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check if we're still connected to master:
|
//Check if we're still connected to master:
|
||||||
if (!Game::server->GetIsConnectedToMaster()) {
|
if (!Game::server->GetIsConnectedToMaster()) {
|
||||||
framesSinceMasterDisconnect++;
|
framesSinceMasterDisconnect++;
|
||||||
|
|
||||||
int framesToWaitForMaster = ready ? 10 : 200;
|
if (framesSinceMasterDisconnect >= noMasterConnectionTimeout && !Game::shouldShutdown) {
|
||||||
if (framesSinceMasterDisconnect >= framesToWaitForMaster && !Game::shouldShutdown) {
|
Game::logger->Log("WorldServer", "Game loop running but no connection to master for %d frames, shutting down", noMasterConnectionTimeout);
|
||||||
Game::logger->Log("WorldServer", "Game loop running but no connection to master for %d frames, shutting down", framesToWaitForMaster);
|
|
||||||
Game::shouldShutdown = true;
|
Game::shouldShutdown = true;
|
||||||
}
|
}
|
||||||
} else framesSinceMasterDisconnect = 0;
|
} else framesSinceMasterDisconnect = 0;
|
||||||
@ -326,8 +354,7 @@ int main(int argc, char** argv) {
|
|||||||
if (!chatConnected) {
|
if (!chatConnected) {
|
||||||
framesSinceChatDisconnect++;
|
framesSinceChatDisconnect++;
|
||||||
|
|
||||||
// Attempt to reconnect every 30 seconds.
|
if (framesSinceChatDisconnect >= chatReconnectionTime) {
|
||||||
if (framesSinceChatDisconnect >= 2000) {
|
|
||||||
framesSinceChatDisconnect = 0;
|
framesSinceChatDisconnect = 0;
|
||||||
|
|
||||||
Game::chatServer->Connect(masterIP.c_str(), chatPort, "3.25 ND1", 8);
|
Game::chatServer->Connect(masterIP.c_str(), chatPort, "3.25 ND1", 8);
|
||||||
@ -379,7 +406,7 @@ int main(int argc, char** argv) {
|
|||||||
UserManager::Instance()->DeletePendingRemovals();
|
UserManager::Instance()->DeletePendingRemovals();
|
||||||
|
|
||||||
auto t1 = std::chrono::high_resolution_clock::now();
|
auto t1 = std::chrono::high_resolution_clock::now();
|
||||||
for (int curPacket = 0; curPacket < maxPacketsToProcess && timeSpent < maxPacketProcessingTime; curPacket++) {
|
for (uint32_t curPacket = 0; curPacket < maxPacketsToProcess && timeSpent < maxPacketProcessingTime; curPacket++) {
|
||||||
packet = Game::server->Receive();
|
packet = Game::server->Receive();
|
||||||
if (packet) {
|
if (packet) {
|
||||||
auto t1 = std::chrono::high_resolution_clock::now();
|
auto t1 = std::chrono::high_resolution_clock::now();
|
||||||
@ -404,7 +431,7 @@ int main(int argc, char** argv) {
|
|||||||
Metrics::EndMeasurement(MetricVariable::UpdateReplica);
|
Metrics::EndMeasurement(MetricVariable::UpdateReplica);
|
||||||
|
|
||||||
//Push our log every 15s:
|
//Push our log every 15s:
|
||||||
if (framesSinceLastFlush >= 1000) {
|
if (framesSinceLastFlush >= logFlushTime) {
|
||||||
Game::logger->Flush();
|
Game::logger->Flush();
|
||||||
framesSinceLastFlush = 0;
|
framesSinceLastFlush = 0;
|
||||||
} else framesSinceLastFlush++;
|
} else framesSinceLastFlush++;
|
||||||
@ -421,7 +448,7 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Save all connected users every 10 minutes:
|
//Save all connected users every 10 minutes:
|
||||||
if (framesSinceLastUsersSave >= 40000 && zoneID != 0) {
|
if (framesSinceLastUsersSave >= saveTime && zoneID != 0) {
|
||||||
UserManager::Instance()->SaveAllActiveCharacters();
|
UserManager::Instance()->SaveAllActiveCharacters();
|
||||||
framesSinceLastUsersSave = 0;
|
framesSinceLastUsersSave = 0;
|
||||||
|
|
||||||
@ -431,10 +458,10 @@ int main(int argc, char** argv) {
|
|||||||
} else framesSinceLastUsersSave++;
|
} else framesSinceLastUsersSave++;
|
||||||
|
|
||||||
//Every 10 min we ping our sql server to keep it alive hopefully:
|
//Every 10 min we ping our sql server to keep it alive hopefully:
|
||||||
if (framesSinceLastSQLPing >= 40000) {
|
if (framesSinceLastSQLPing >= sqlPingTime) {
|
||||||
//Find out the master's IP for absolutely no reason:
|
//Find out the master's IP for absolutely no reason:
|
||||||
std::string masterIP;
|
std::string masterIP;
|
||||||
int masterPort;
|
uint32_t masterPort;
|
||||||
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
||||||
auto res = stmt->executeQuery();
|
auto res = stmt->executeQuery();
|
||||||
while (res->next()) {
|
while (res->next()) {
|
||||||
@ -452,7 +479,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
Metrics::StartMeasurement(MetricVariable::Sleep);
|
Metrics::StartMeasurement(MetricVariable::Sleep);
|
||||||
|
|
||||||
t += std::chrono::milliseconds(currentFramerate);
|
t += std::chrono::milliseconds(currentFrameDelta);
|
||||||
std::this_thread::sleep_until(t);
|
std::this_thread::sleep_until(t);
|
||||||
|
|
||||||
Metrics::EndMeasurement(MetricVariable::Sleep);
|
Metrics::EndMeasurement(MetricVariable::Sleep);
|
||||||
@ -483,7 +510,7 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
dLogger* SetupLogger(int zoneID, int instanceID) {
|
dLogger* SetupLogger(uint32_t zoneID, uint32_t instanceID) {
|
||||||
std::string logPath = (BinaryPathFinder::GetBinaryDir() / ("logs/WorldServer_" + std::to_string(zoneID) + "_" + std::to_string(instanceID) + "_" + std::to_string(time(nullptr)) + ".log")).string();
|
std::string logPath = (BinaryPathFinder::GetBinaryDir() / ("logs/WorldServer_" + std::to_string(zoneID) + "_" + std::to_string(instanceID) + "_" + std::to_string(time(nullptr)) + ".log")).string();
|
||||||
bool logToConsole = false;
|
bool logToConsole = false;
|
||||||
bool logDebugStatements = false;
|
bool logDebugStatements = false;
|
||||||
@ -525,7 +552,7 @@ void HandlePacketChat(Packet* packet) {
|
|||||||
|
|
||||||
//Write our stream outwards:
|
//Write our stream outwards:
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
for (int i = 0; i < inStream.GetNumberOfBytesUsed(); i++) {
|
for (BitSize_t i = 0; i < inStream.GetNumberOfBytesUsed(); i++) {
|
||||||
bitStream.Write(packet->data[i + 16]); //16 bytes == header + playerID to skip
|
bitStream.Write(packet->data[i + 16]); //16 bytes == header + playerID to skip
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,7 +571,7 @@ void HandlePacketChat(Packet* packet) {
|
|||||||
|
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
inStream.Read<uint32_t>(len);
|
inStream.Read<uint32_t>(len);
|
||||||
for (int i = 0; len > i; i++) {
|
for (uint32_t i = 0; len > i; i++) {
|
||||||
char character;
|
char character;
|
||||||
inStream.Read<char>(character);
|
inStream.Read<char>(character);
|
||||||
title += character;
|
title += character;
|
||||||
@ -552,7 +579,7 @@ void HandlePacketChat(Packet* packet) {
|
|||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
inStream.Read<uint32_t>(len);
|
inStream.Read<uint32_t>(len);
|
||||||
for (int i = 0; len > i; i++) {
|
for (uint32_t i = 0; len > i; i++) {
|
||||||
char character;
|
char character;
|
||||||
inStream.Read<char>(character);
|
inStream.Read<char>(character);
|
||||||
msg += character;
|
msg += character;
|
||||||
@ -805,7 +832,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
uint32_t len;
|
uint32_t len;
|
||||||
inStream.Read(len);
|
inStream.Read(len);
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (uint32_t i = 0; i < len; i++) {
|
||||||
char character; inStream.Read<char>(character);
|
char character; inStream.Read<char>(character);
|
||||||
username += character;
|
username += character;
|
||||||
}
|
}
|
||||||
@ -1048,7 +1075,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
//Check for BBB models:
|
//Check for BBB models:
|
||||||
auto stmt = Database::CreatePreppedStmt("SELECT ugc_id FROM properties_contents WHERE lot=14 AND property_id=?");
|
auto stmt = Database::CreatePreppedStmt("SELECT ugc_id FROM properties_contents WHERE lot=14 AND property_id=?");
|
||||||
|
|
||||||
int templateId = result.getIntField(0);
|
int32_t templateId = result.getIntField(0);
|
||||||
|
|
||||||
result.finalize();
|
result.finalize();
|
||||||
|
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
# CREDITS
|
# CREDITS
|
||||||
|
|
||||||
## Developers
|
## DLU Team
|
||||||
DarwinAnim8or (Max)
|
DarwinAnim8or (Max)
|
||||||
Wincent01
|
Wincent01
|
||||||
Mick
|
Mick
|
||||||
averysumner (codeshaunted)
|
averysumner (codeshaunted)
|
||||||
Jon002
|
Jon002
|
||||||
Jonny
|
Jonny
|
||||||
EmosewaMC
|
|
||||||
Jettford
|
|
||||||
|
|
||||||
## Research & Tooling
|
|
||||||
Xiphoseer
|
Xiphoseer
|
||||||
lcdr
|
lcdr
|
||||||
|
Aaron K.
|
||||||
## Community Management
|
|
||||||
Neal
|
Neal
|
||||||
|
|
||||||
|
## Active Contributors
|
||||||
|
EmosewaMC
|
||||||
|
Jettford
|
Loading…
Reference in New Issue
Block a user