Autor: Karpio
Licencja: Róbta co chceta, tylko podajcie autora
Testowane na silniku The Forgotten Server 0.4_DEV.r4086

Wielu ma ten problem. Co zrobić, gdy jesteśmy z dala od kompa, a The Forgotten Server zerwie połączenie z bazą danych? Teraz jest na to rozwiązanie!

W tym celu musimy trochę zedytować silnik. Otwieramy plik globalevent.cpp i szukamy:

GlobalEventMap GlobalEvents::getEventMap(GlobalEvent_t type)

następnie w tej funkcji szukamy:

case GLOBALEVENT_GLOBALSAVE:

i pod tym doklejamy:

globalevent.cpp
case GLOBALEVENT_LOSTCONNECTION:

Następnie szukamy:

else if(tmpStrValue == "record" || tmpStrValue == "playersrecord")
			m_eventType = GLOBALEVENT_RECORD;

i pod tym dodajemy:

globalevent.cpp
else if(tmpStrValue == "lostconnection")
		     m_eventType = GLOBALEVENT_LOSTCONNECTION;

Potem szukamy:

case GLOBALEVENT_TIMER:
			return "onTime";

i pod tym dodajemy:

globalevent.cpp
case GLOBALEVENT_LOSTCONNECTION:
            return "onLostConnection";

Zapisujemy plik i otwieramy globalevent.h
Szukamy:

GLOBALEVENT_RECORD

i po tym dopisujemy przecinek oraz

globalevent.h
GLOBALEVENT_LOSTCONNECTION

Zapisujemy.

Udajemy się do databasemysql.cpp
Szukamy:

#include "configmanager.h"

i pod tym doklejamy:

databasemysql.cpp
#include "globalevent.h"
 
extern GlobalEvents* g_globalEvents;

Szukamy:

bool DatabaseMySQL::connect(bool _reconnect)
{
	if(_reconnect)
	{
		std::clog << "WARNING: MYSQL Lost connection, attempting to reconnect..." << std::endl;
		if(++m_attempts > MAX_RECONNECT_ATTEMPTS)
		{

i pod tym doklejamy:

databasemysql.cpp
GlobalEventMap recordEvents = g_globalEvents->getEventMap(GLOBALEVENT_LOSTCONNECTION);
	            for(GlobalEventMap::iterator it = recordEvents.begin(); it != recordEvents.end(); ++it)
	                it->second->executeEvent();

Tak aby cała ta funkcja wyglądała mniej więcej tak:

databasemysq.cpp
bool DatabaseMySQL::connect(bool _reconnect)
{
	if(_reconnect)
	{
		std::clog << "WARNING: MYSQL Lost connection, attempting to reconnect..." << std::endl;
		if(++m_attempts > MAX_RECONNECT_ATTEMPTS)
		{
            GlobalEventMap recordEvents = g_globalEvents->getEventMap(GLOBALEVENT_LOSTCONNECTION);
	            for(GlobalEventMap::iterator it = recordEvents.begin(); it != recordEvents.end(); ++it)
	                it->second->executeEvent();
			std::clog << "Failed connection to database - maximum reconnect attempts passed." << std::endl;
			return false;
		}
	}
 
	if(mysql_real_connect(&m_handle, g_config.getString(ConfigManager::SQL_HOST).c_str(), g_config.getString(
		ConfigManager::SQL_USER).c_str(), g_config.getString(ConfigManager::SQL_PASS).c_str(), g_config.getString(
		ConfigManager::SQL_DB).c_str(), g_config.getNumber(ConfigManager::SQL_PORT), NULL, 0))
	{
		m_attempts = 0;
		return true;
	}
 
	std::clog << "Failed connecting to database - MYSQL ERROR: " << mysql_error(&m_handle) << " (" << mysql_errno(&m_handle) << ")" << std::endl;
	return false;
}

Kompilujemy.

Silnik mamy gotowy.
Teraz czas na LUA.
Wchodzimy w data/globalevents/globalevents.xml i doklejamy:

globalevents.xml
<globalevent name="database" type="lostconnection" event="script" value="database.lua"/>

Następnie wchodzimy w data/globalevents/scripts i tworzymy plik database.lua i wklejamy do niego:

database.lua
-- System by Karpio
local log = true
 
function onLostConnection()
	if(log) then
		local file = io.open(getDataDir().."logs/server/connections.log", "a+")
		file:write("["..os.date("%c").."] Server (ID: "..getConfigValue("worldId")..") lost connection with database\n")
		file:close()
	end
	os.exit()
	return true
end

To wszystko. Od teraz Wasz OTS automatycznie się wyłączy przy zerwaniu połączenia z bazą (dopiero po wykorzystaniu limitu prób ponownego nawiązania połączenia).