Skip to content

Commit

Permalink
Move account storage to Lua (#4590)
Browse files Browse the repository at this point in the history
  • Loading branch information
ramon-bernardo authored Dec 18, 2023
1 parent 36b3c89 commit caf195f
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 128 deletions.
72 changes: 64 additions & 8 deletions data/lib/core/game.lua
Original file line number Diff line number Diff line change
Expand Up @@ -231,18 +231,74 @@ do
end
end
end

function Game.getFormattedWorldTime()
local worldTime = Game.getWorldTime()
local hours = math.floor(worldTime / 60)

local minutes = worldTime % 60
if minutes < 10 then
minutes = '0' .. minutes
end

minutes = math.floor(minutes)

return hours .. ':' .. minutes
end
end

function Game.getFormattedWorldTime()
local worldTime = Game.getWorldTime()
local hours = math.floor(worldTime / 60)
do
local accountsStorage = {}

local minutes = worldTime % 60
if minutes < 10 then
minutes = '0' .. minutes
function Game.getAccountsStorage()
return accountsStorage
end

minutes = math.floor(minutes)
function Game.clearAccountStorageValue(accountId, key)
local accountStorage = accountsStorage[accountId]
if accountStorage then
accountStorage[key] = nil
end
end

function Game.getAccountStorageValue(accountId, key)
local accountStorage = accountsStorage[accountId]
return accountStorage and accountStorage[key] or nil
end

function Game.setAccountStorageValue(accountId, key, value)
if not accountsStorage[accountId] then
accountsStorage[accountId] = {}
end
accountsStorage[accountId][key] = value
end

return hours .. ':' .. minutes
function Game.saveAccountsStorage()
local transaction = DBTransaction()
if not transaction:begin() then
return false
end

local result = db.query("DELETE FROM `account_storage`")
if not result then
return false
end

local accountsStorage = Game.getAccountsStorage()
for accountId, accountStorage in pairs(accountsStorage) do
local query = DBInsert("INSERT INTO `account_storage` (`account_id`, `key`, `value`) VALUES")
for key, value in pairs(accountStorage) do
local success = query:addRow(accountId .. ", " .. key .. ", " .. value)
if not success then
return false
end
end

if not query:execute() then
return false
end
end

return transaction:commit()
end
end
34 changes: 34 additions & 0 deletions data/scripts/globalevents/account_storage.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
-- load accounts storages
local load = GlobalEvent("LoadAccountStorage")

function load.onStartup()
local resultId = db.storeQuery("SELECT `account_id`, `key`, `value` FROM `account_storage`")
if not resultId then
return true
end

repeat
local accountId = result.getNumber(resultId, "account_id")
local key = result.getNumber(resultId, "key")
local value = result.getNumber(resultId, "value")
Game.setAccountStorageValue(accountId, key, value)
until not result.next(resultId)
result.free(resultId)

return true
end

load:register()

-- save accounts storages
local save = GlobalEvent("SaveAccountStorage")

function save.onSave()
local success = Game.saveAccountsStorage()
if not success then
print("Failed to save account-level storage values.")
end
return true
end

save:register()
74 changes: 0 additions & 74 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ void Game::setGameState(GameState_t newState)
mounts.loadFromXml();

loadPlayersRecord();
loadAccountStorageValues();

g_globalEvents->startup();
break;
Expand Down Expand Up @@ -160,10 +159,6 @@ void Game::saveGameState()

std::cout << "Saving server..." << std::endl;

if (!saveAccountStorageValues()) {
std::cout << "[Error - Game::saveGameState] Failed to save account-level storage values." << std::endl;
}

for (const auto& it : players) {
it.second->loginPosition = it.second->getPosition();
IOLoginData::savePlayer(it.second);
Expand Down Expand Up @@ -4720,75 +4715,6 @@ void Game::addDistanceEffect(const SpectatorVec& spectators, const Position& fro
}
}

void Game::setAccountStorageValue(const uint32_t accountId, const uint32_t key, const int32_t value)
{
if (value == -1) {
accountStorageMap[accountId].erase(key);
return;
}

accountStorageMap[accountId][key] = value;
}

int32_t Game::getAccountStorageValue(const uint32_t accountId, const uint32_t key) const
{
const auto& accountMapIt = accountStorageMap.find(accountId);
if (accountMapIt != accountStorageMap.end()) {
const auto& storageMapIt = accountMapIt->second.find(key);
if (storageMapIt != accountMapIt->second.end()) {
return storageMapIt->second;
}
}
return -1;
}

void Game::loadAccountStorageValues()
{
Database& db = Database::getInstance();

DBResult_ptr result;
if ((result = db.storeQuery("SELECT `account_id`, `key`, `value` FROM `account_storage`"))) {
do {
g_game.setAccountStorageValue(result->getNumber<uint32_t>("account_id"), result->getNumber<uint32_t>("key"),
result->getNumber<int32_t>("value"));
} while (result->next());
}
}

bool Game::saveAccountStorageValues() const
{
DBTransaction transaction;
Database& db = Database::getInstance();

if (!transaction.begin()) {
return false;
}

if (!db.executeQuery("DELETE FROM `account_storage`")) {
return false;
}

for (const auto& accountIt : g_game.accountStorageMap) {
if (accountIt.second.empty()) {
continue;
}

DBInsert accountStorageQuery("INSERT INTO `account_storage` (`account_id`, `key`, `value`) VALUES");
for (const auto& storageIt : accountIt.second) {
if (!accountStorageQuery.addRow(
fmt::format("{:d}, {:d}, {:d}", accountIt.first, storageIt.first, storageIt.second))) {
return false;
}
}

if (!accountStorageQuery.execute()) {
return false;
}
}

return transaction.commit();
}

void Game::startDecay(Item* item)
{
if (!item || !item->canDecay()) {
Expand Down
6 changes: 0 additions & 6 deletions src/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,11 +447,6 @@ class Game
static void addDistanceEffect(const SpectatorVec& spectators, const Position& fromPos, const Position& toPos,
uint8_t effect);

void setAccountStorageValue(const uint32_t accountId, const uint32_t key, const int32_t value);
int32_t getAccountStorageValue(const uint32_t accountId, const uint32_t key) const;
void loadAccountStorageValues();
bool saveAccountStorageValues() const;

void startDecay(Item* item);

void sendOfflineTrainingDialog(Player* player);
Expand Down Expand Up @@ -518,7 +513,6 @@ class Game
std::unordered_map<uint32_t, Guild*> guilds;
std::unordered_map<uint16_t, Item*> uniqueItems;
std::map<uint32_t, uint32_t> stages;
std::unordered_map<uint32_t, std::unordered_map<uint32_t, int32_t>> accountStorageMap;

std::list<Item*> decayItems[EVENT_DECAY_BUCKETS];
std::list<Creature*> checkCreatureLists[EVENT_CREATURECOUNT];
Expand Down
44 changes: 8 additions & 36 deletions src/luascript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2268,10 +2268,6 @@ void LuaScriptInterface::registerFunctions()

registerMethod("Game", "reload", LuaScriptInterface::luaGameReload);

registerMethod("Game", "getAccountStorageValue", LuaScriptInterface::luaGameGetAccountStorageValue);
registerMethod("Game", "setAccountStorageValue", LuaScriptInterface::luaGameSetAccountStorageValue);
registerMethod("Game", "saveAccountStorageValues", LuaScriptInterface::luaGameSaveAccountStorageValues);

// Variant
registerClass("Variant", "", LuaScriptInterface::luaVariantCreate);

Expand Down Expand Up @@ -4167,12 +4163,14 @@ const luaL_Reg LuaScriptInterface::luaDatabaseTable[] = {

int LuaScriptInterface::luaDatabaseExecute(lua_State* L)
{
// db.query(query)
pushBoolean(L, Database::getInstance().executeQuery(getString(L, -1)));
return 1;
}

int LuaScriptInterface::luaDatabaseAsyncExecute(lua_State* L)
{
// db.asyncQuery(query, callback)
std::function<void(DBResult_ptr, bool)> callback;
if (lua_gettop(L) > 1) {
int32_t ref = luaL_ref(L, LUA_REGISTRYINDEX);
Expand Down Expand Up @@ -4203,6 +4201,7 @@ int LuaScriptInterface::luaDatabaseAsyncExecute(lua_State* L)

int LuaScriptInterface::luaDatabaseStoreQuery(lua_State* L)
{
// db.storeQuery(query)
if (DBResult_ptr res = Database::getInstance().storeQuery(getString(L, -1))) {
lua_pushnumber(L, ScriptEnvironment::addResult(res));
} else {
Expand All @@ -4213,6 +4212,7 @@ int LuaScriptInterface::luaDatabaseStoreQuery(lua_State* L)

int LuaScriptInterface::luaDatabaseAsyncStoreQuery(lua_State* L)
{
// db.asyncStoreQuery(query, callback)
std::function<void(DBResult_ptr, bool)> callback;
if (lua_gettop(L) > 1) {
int32_t ref = luaL_ref(L, LUA_REGISTRYINDEX);
Expand Down Expand Up @@ -4247,25 +4247,29 @@ int LuaScriptInterface::luaDatabaseAsyncStoreQuery(lua_State* L)

int LuaScriptInterface::luaDatabaseEscapeString(lua_State* L)
{
// db.escapeString(s)
pushString(L, Database::getInstance().escapeString(getString(L, -1)));
return 1;
}

int LuaScriptInterface::luaDatabaseEscapeBlob(lua_State* L)
{
// db.escapeBlob(s, length)
uint32_t length = getNumber<uint32_t>(L, 2);
pushString(L, Database::getInstance().escapeBlob(getString(L, 1).c_str(), length));
return 1;
}

int LuaScriptInterface::luaDatabaseLastInsertId(lua_State* L)
{
// db.lastInsertId()
lua_pushnumber(L, Database::getInstance().getLastInsertId());
return 1;
}

int LuaScriptInterface::luaDatabaseTableExists(lua_State* L)
{
// db.tableExists(tableName)
pushBoolean(L, DatabaseManager::tableExists(getString(L, -1)));
return 1;
}
Expand Down Expand Up @@ -5090,38 +5094,6 @@ int LuaScriptInterface::luaGameReload(lua_State* L)
return 1;
}

int LuaScriptInterface::luaGameGetAccountStorageValue(lua_State* L)
{
// Game.getAccountStorageValue(accountId, key)
uint32_t accountId = getNumber<uint32_t>(L, 1);
uint32_t key = getNumber<uint32_t>(L, 2);

lua_pushnumber(L, g_game.getAccountStorageValue(accountId, key));

return 1;
}

int LuaScriptInterface::luaGameSetAccountStorageValue(lua_State* L)
{
// Game.setAccountStorageValue(accountId, key, value)
uint32_t accountId = getNumber<uint32_t>(L, 1);
uint32_t key = getNumber<uint32_t>(L, 2);
int32_t value = getNumber<int32_t>(L, 3);

g_game.setAccountStorageValue(accountId, key, value);
lua_pushboolean(L, true);

return 1;
}

int LuaScriptInterface::luaGameSaveAccountStorageValues(lua_State* L)
{
// Game.saveAccountStorageValues()
lua_pushboolean(L, g_game.saveAccountStorageValues());

return 1;
}

// Variant
int LuaScriptInterface::luaVariantCreate(lua_State* L)
{
Expand Down
4 changes: 0 additions & 4 deletions src/luascript.h
Original file line number Diff line number Diff line change
Expand Up @@ -557,10 +557,6 @@ class LuaScriptInterface

static int luaGameReload(lua_State* L);

static int luaGameGetAccountStorageValue(lua_State* L);
static int luaGameSetAccountStorageValue(lua_State* L);
static int luaGameSaveAccountStorageValues(lua_State* L);

// Variant
static int luaVariantCreate(lua_State* L);

Expand Down

0 comments on commit caf195f

Please sign in to comment.