Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
luanluciano93 committed Jan 4, 2025
2 parents 006f854 + e5fb63c commit bfd6e57
Show file tree
Hide file tree
Showing 15 changed files with 214 additions and 96 deletions.
10 changes: 6 additions & 4 deletions .github/workflows/build-ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,14 @@ jobs:
run: >
sudo apt-get update && sudo apt-get install ccache linux-headers-"$(uname -r)"
- name: Switch to gcc-12 on Ubuntu 22.04
- name: Switch to gcc-13 on Ubuntu 22.04
if: matrix.os == 'ubuntu-22.04'
run: |
sudo apt install gcc-12 g++-12
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100 --slave /usr/bin/g++ g++ /usr/bin/g++-12 --slave /usr/bin/gcov gcov /usr/bin/gcov-12
sudo update-alternatives --set gcc /usr/bin/gcc-12
sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
sudo apt-get update
sudo apt install gcc-13 g++-13 -y
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 100 --slave /usr/bin/g++ g++ /usr/bin/g++-13 --slave /usr/bin/gcov gcov /usr/bin/gcov-12
sudo update-alternatives --set gcc /usr/bin/gcc-13
- name: Switch to gcc-14 on Ubuntu 24.04
if: matrix.os == 'ubuntu-24.04'
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -395,5 +395,8 @@ canary.old
# VCPKG
vcpkg_installed

# DB Backups
database_backup

# CLION
cmake-build-*
1 change: 1 addition & 0 deletions config.lua.dist
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ mysqlHost = "127.0.0.1"
mysqlUser = "root"
mysqlPass = "root"
mysqlDatabase = "otservbr-global"
mysqlDatabaseBackup = false
mysqlPort = 3306
mysqlSock = ""
passwordType = "sha1"
Expand Down
1 change: 1 addition & 0 deletions data-otservbr-global/lib/functions/load.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dofile(DATA_DIRECTORY .. "/lib/functions/players.lua")
76 changes: 76 additions & 0 deletions data-otservbr-global/lib/functions/players.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
function Player.getCookiesDelivered(self)
local storage, amount =
{
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.SimonTheBeggar,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.Markwin,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.Ariella,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.Hairycles,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.Djinn,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.AvarTar,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.OrcKing,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.Lorbas,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.Wyda,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.Hjaern,
}, 0
for i = 1, #storage do
if self:getStorageValue(storage[i]) == 1 then
amount = amount + 1
end
end
return amount
end

function Player.checkGnomeRank(self)
local points = self:getStorageValue(Storage.Quest.U9_60.BigfootsBurden.Rank)
local questProgress = self:getStorageValue(Storage.Quest.U9_60.BigfootsBurden.QuestLine)
if points >= 30 and points < 120 then
if questProgress <= 25 then
self:setStorageValue(Storage.Quest.U9_60.BigfootsBurden.QuestLine, 26)
self:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)
self:addAchievement("Gnome Little Helper")
end
elseif points >= 120 and points < 480 then
if questProgress <= 26 then
self:setStorageValue(Storage.Quest.U9_60.BigfootsBurden.QuestLine, 27)
self:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)
self:addAchievement("Gnome Little Helper")
self:addAchievement("Gnome Friend")
end
elseif points >= 480 and points < 1440 then
if questProgress <= 27 then
self:setStorageValue(Storage.Quest.U9_60.BigfootsBurden.QuestLine, 28)
self:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)
self:addAchievement("Gnome Little Helper")
self:addAchievement("Gnome Friend")
self:addAchievement("Gnomelike")
end
elseif points >= 1440 then
if questProgress <= 29 then
self:setStorageValue(Storage.Quest.U9_60.BigfootsBurden.QuestLine, 30)
self:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)
self:addAchievement("Gnome Little Helper")
self:addAchievement("Gnome Friend")
self:addAchievement("Gnomelike")
self:addAchievement("Honorary Gnome")
end
end
return true
end

function Player.addFamePoint(self)
local points = self:getStorageValue(Storage.Quest.U10_20.SpikeTaskQuest.Constants.Spike_Fame_Points)
local current = math.max(0, points)
self:setStorageValue(Storage.Quest.U10_20.SpikeTaskQuest.Constants.Spike_Fame_Points, current + 1)
self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have received a fame point.")
end

function Player.getFamePoints(self)
local points = self:getStorageValue(Storage.Quest.U10_20.SpikeTaskQuest.Constants.Spike_Fame_Points)
return math.max(0, points)
end

function Player.removeFamePoints(self, amount)
local points = self:getStorageValue(Storage.Quest.U10_20.SpikeTaskQuest.Constants.Spike_Fame_Points)
local current = math.max(0, points)
self:setStorageValue(Storage.Quest.U10_20.SpikeTaskQuest.Constants.Spike_Fame_Points, current - amount)
end
3 changes: 3 additions & 0 deletions data-otservbr-global/lib/lib.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ dofile(DATA_DIRECTORY .. "/lib/quests/quest.lua")

-- Tables library
dofile(DATA_DIRECTORY .. "/lib/tables/load.lua")

-- Functions library
dofile(DATA_DIRECTORY .. "/lib/functions/load.lua")
10 changes: 5 additions & 5 deletions data-otservbr-global/npc/thorgrin.lua
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ npcType.onCloseChannel = function(npc, creature)
end

-- Travel
local function addTravelKeyword(keyword, cost, destination)
local travelKeyword = keywordHandler:addKeyword({ keyword }, StdModule.say, { npcHandler = npcHandler, text = "Do you seek a ride to " .. keyword:titleCase() .. " for |TRAVELCOST|?", cost = cost, discount = "postman" })
travelKeyword:addChildKeyword({ "yes" }, StdModule.travel, { npcHandler = npcHandler, premium = false, cost = cost, discount = "postman", destination = destination })
travelKeyword:addChildKeyword({ "no" }, StdModule.say, { npcHandler = npcHandler, text = "Then not.", reset = true })
local function addTravelKeyword(keyword, cost, destination, text, action, discount)
local travelKeyword = keywordHandler:addKeyword({ keyword }, StdModule.say, { npcHandler = npcHandler, text = text or "Do you seek a ride to " .. keyword:titleCase() .. " for |TRAVELCOST|?", cost = cost, discount = discount or "postman" })
travelKeyword:addChildKeyword({ "yes" }, StdModule.travel, { npcHandler = npcHandler, premium = false, cost = cost, discount = discount or "postman", destination = destination, text = "Full steam ahead!" }, nil, action)
travelKeyword:addChildKeyword({ "no" }, StdModule.say, { npcHandler = npcHandler, text = "Then not", reset = true })
end

addTravelKeyword("kazordoon", 210, Position(32659, 31957, 15))
addTravelKeyword("cormaya", 110, Position(33310, 31988, 15))
addTravelKeyword("gnomprona", { "Would you like to travel to Gnomprona for |TRAVELCOST|?", "Full steam ahead!", "Then not." }, 200, "postman", Position(33516, 32856, 14))
addTravelKeyword("gnomprona", 200, Position(33516, 32856, 14), "Would you like to travel to Gnomprona for |TRAVELCOST|?", nil, "postman")

keywordHandler:addKeyword({ "passage" }, StdModule.say, { npcHandler = npcHandler, text = "Do you want me take you to {Cormaya}, {Kazordoon} or {Gnomprona}?" })

Expand Down
85 changes: 0 additions & 85 deletions data/libs/functions/player.lua
Original file line number Diff line number Diff line change
Expand Up @@ -90,91 +90,6 @@ function Player.addManaSpent(...)
end

-- Functions From OTServBR-Global
function Player.getCookiesDelivered(self)
if not IsRunningGlobalDatapack() then
return true
end

local storage, amount =
{
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.SimonTheBeggar,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.Markwin,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.Ariella,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.Hairycles,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.Djinn,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.AvarTar,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.OrcKing,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.Lorbas,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.Wyda,
Storage.Quest.U8_1.WhatAFoolishQuest.CookieDelivery.Hjaern,
}, 0
for i = 1, #storage do
if self:getStorageValue(storage[i]) == 1 then
amount = amount + 1
end
end
return amount
end

function Player.checkGnomeRank(self)
if not IsRunningGlobalDatapack() then
return true
end

local points = self:getStorageValue(Storage.Quest.U9_60.BigfootsBurden.Rank)
local questProgress = self:getStorageValue(Storage.Quest.U9_60.BigfootsBurden.QuestLine)
if points >= 30 and points < 120 then
if questProgress <= 25 then
self:setStorageValue(Storage.Quest.U9_60.BigfootsBurden.QuestLine, 26)
self:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)
self:addAchievement("Gnome Little Helper")
end
elseif points >= 120 and points < 480 then
if questProgress <= 26 then
self:setStorageValue(Storage.Quest.U9_60.BigfootsBurden.QuestLine, 27)
self:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)
self:addAchievement("Gnome Little Helper")
self:addAchievement("Gnome Friend")
end
elseif points >= 480 and points < 1440 then
if questProgress <= 27 then
self:setStorageValue(Storage.Quest.U9_60.BigfootsBurden.QuestLine, 28)
self:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)
self:addAchievement("Gnome Little Helper")
self:addAchievement("Gnome Friend")
self:addAchievement("Gnomelike")
end
elseif points >= 1440 then
if questProgress <= 29 then
self:setStorageValue(Storage.Quest.U9_60.BigfootsBurden.QuestLine, 30)
self:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)
self:addAchievement("Gnome Little Helper")
self:addAchievement("Gnome Friend")
self:addAchievement("Gnomelike")
self:addAchievement("Honorary Gnome")
end
end
return true
end

function Player.addFamePoint(self)
local points = self:getStorageValue(Storage.Quest.U10_20.SpikeTaskQuest.Constants.Spike_Fame_Points)
local current = math.max(0, points)
self:setStorageValue(Storage.Quest.U10_20.SpikeTaskQuest.Constants.Spike_Fame_Points, current + 1)
self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have received a fame point.")
end

function Player.getFamePoints(self)
local points = self:getStorageValue(Storage.Quest.U10_20.SpikeTaskQuest.Constants.Spike_Fame_Points)
return math.max(0, points)
end

function Player.removeFamePoints(self, amount)
local points = self:getStorageValue(Storage.Quest.U10_20.SpikeTaskQuest.Constants.Spike_Fame_Points)
local current = math.max(0, points)
self:setStorageValue(Storage.Quest.U10_20.SpikeTaskQuest.Constants.Spike_Fame_Points, current - amount)
end

function Player.depositMoney(self, amount)
return Bank.deposit(self, amount)
end
Expand Down
2 changes: 1 addition & 1 deletion data/scripts/movements/closing_door.lua
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ function closingDoor.onStepOut(creature, item, position, fromPosition)

while tileItem and i < tileCount do
tileItem = tile:getThing(i)
if tileItem and tileItem:getUniqueId() ~= item.uid and tileItem:getType():isMovable() then
if tileItem and tileItem:getUniqueId() ~= item.uid and tileItem:getType():isMovable() and not isCorpse(tileItem:getUniqueId()) then
tileItem:remove()
else
i = i + 1
Expand Down
1 change: 1 addition & 0 deletions src/canary_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ void CanaryServer::modulesLoadHelper(bool loaded, std::string moduleName) {
}

void CanaryServer::shutdown() {
g_database().createDatabaseBackup(true);
g_dispatcher().shutdown();
g_metrics().shutdown();
inject<ThreadPool>().shutdown();
Expand Down
1 change: 1 addition & 0 deletions src/config/config_enums.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ enum ConfigKey_t : uint16_t {
MONTH_KILLS_TO_RED,
MULTIPLIER_ATTACKONFIST,
MYSQL_DB,
MYSQL_DB_BACKUP,
MYSQL_HOST,
MYSQL_PASS,
MYSQL_SOCK,
Expand Down
1 change: 1 addition & 0 deletions src/config/configmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ bool ConfigManager::load() {
loadStringConfig(L, MAP_DOWNLOAD_URL, "mapDownloadUrl", "");
loadStringConfig(L, MAP_NAME, "mapName", "canary");
loadStringConfig(L, MYSQL_DB, "mysqlDatabase", "canary");
loadBoolConfig(L, MYSQL_DB_BACKUP, "mysqlDatabaseBackup", false);
loadStringConfig(L, MYSQL_HOST, "mysqlHost", "127.0.0.1");
loadStringConfig(L, MYSQL_PASS, "mysqlPass", "");
loadStringConfig(L, MYSQL_SOCK, "mysqlSock", "");
Expand Down
2 changes: 1 addition & 1 deletion src/creatures/players/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,7 @@ void Player::addSkillAdvance(skills_t skill, uint64_t count) {

skills[skill].tries += count;

uint32_t newPercent;
double_t newPercent;
if (nextReqTries > currReqTries) {
newPercent = Player::getPercentLevel(skills[skill].tries, nextReqTries);
} else {
Expand Down
97 changes: 97 additions & 0 deletions src/database/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "config/configmanager.hpp"
#include "lib/di/container.hpp"
#include "lib/metrics/metrics.hpp"
#include "utils/tools.hpp"

Database::~Database() {
if (handle != nullptr) {
Expand Down Expand Up @@ -60,6 +61,102 @@ bool Database::connect(const std::string* host, const std::string* user, const s
return true;
}

void Database::createDatabaseBackup(bool compress) const {
if (!g_configManager().getBoolean(MYSQL_DB_BACKUP)) {
return;
}

// Get current time for formatting
auto now = std::chrono::system_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(now);
std::string formattedDate = fmt::format("{:%Y-%m-%d}", fmt::localtime(now_c));
std::string formattedTime = fmt::format("{:%H-%M-%S}", fmt::localtime(now_c));

// Create a backup directory based on the current date
std::string backupDir = fmt::format("database_backup/{}/", formattedDate);
std::filesystem::create_directories(backupDir);
std::string backupFileName = fmt::format("{}backup_{}.sql", backupDir, formattedTime);

// Create a temporary configuration file for MySQL credentials
std::string tempConfigFile = "database_backup.cnf";
std::ofstream configFile(tempConfigFile);
if (configFile.is_open()) {
configFile << "[client]\n";
configFile << "user=" << g_configManager().getString(MYSQL_USER) << "\n";
configFile << "password=" << g_configManager().getString(MYSQL_PASS) << "\n";
configFile << "host=" << g_configManager().getString(MYSQL_HOST) << "\n";
configFile << "port=" << g_configManager().getNumber(SQL_PORT) << "\n";
configFile.close();
} else {
g_logger().error("Failed to create temporary MySQL configuration file.");
return;
}

// Execute mysqldump command to create backup file
std::string command = fmt::format(
"mysqldump --defaults-extra-file={} {} > {}",
tempConfigFile, g_configManager().getString(MYSQL_DB), backupFileName
);

int result = std::system(command.c_str());
std::filesystem::remove(tempConfigFile);

if (result != 0) {
g_logger().error("Failed to create database backup using mysqldump.");
return;
}

// Compress the backup file if requested
std::string compressedFileName;
compressedFileName = backupFileName + ".gz";
gzFile gzFile = gzopen(compressedFileName.c_str(), "wb9");
if (!gzFile) {
g_logger().error("Failed to open gzip file for compression.");
return;
}

std::ifstream backupFile(backupFileName, std::ios::binary);
if (!backupFile.is_open()) {
g_logger().error("Failed to open backup file for compression: {}", backupFileName);
gzclose(gzFile);
return;
}

std::string buffer(8192, '\0');
while (backupFile.read(&buffer[0], buffer.size()) || backupFile.gcount() > 0) {
gzwrite(gzFile, buffer.data(), backupFile.gcount());
}

backupFile.close();
gzclose(gzFile);
std::filesystem::remove(backupFileName);

g_logger().info("Database backup successfully compressed to: {}", compressedFileName);

// Delete backups older than 7 days
auto nowTime = std::chrono::system_clock::now();
auto sevenDaysAgo = nowTime - std::chrono::hours(7 * 24); // 7 days in hours
for (const auto &entry : std::filesystem::directory_iterator("database_backup")) {
if (entry.is_directory()) {
try {
for (const auto &file : std::filesystem::directory_iterator(entry)) {
if (file.path().extension() == ".gz") {
auto fileTime = std::filesystem::last_write_time(file);
auto fileTimeSystemClock = std::chrono::clock_cast<std::chrono::system_clock>(fileTime);

if (fileTimeSystemClock < sevenDaysAgo) {
std::filesystem::remove(file);
g_logger().info("Deleted old backup file: {}", file.path().string());
}
}
}
} catch (const std::filesystem::filesystem_error &e) {
g_logger().error("Failed to check or delete files in backup directory: {}. Error: {}", entry.path().string(), e.what());
}
}
}
}

bool Database::beginTransaction() {
if (!executeQuery("BEGIN")) {
return false;
Expand Down
Loading

0 comments on commit bfd6e57

Please sign in to comment.