diff --git a/.github/workflows/build-windows-solution.yml b/.github/workflows/build-windows-solution.yml index 58dcf97f159..4b2f5fb306c 100644 --- a/.github/workflows/build-windows-solution.yml +++ b/.github/workflows/build-windows-solution.yml @@ -17,6 +17,9 @@ on: env: CMAKE_BUILD_PARALLEL_LEVEL: 2 MAKEFLAGS: "-j 2" + GITHUB_WORKSPACE: ${{ github.workspace }} + VCPKG_ROOT: ${{ github.workspace }}/vcpkg + VCPKG_TRIPLET: x64-windows jobs: cancel-runs: @@ -55,8 +58,16 @@ jobs: ./bootstrap-vcpkg.bat ./vcpkg integrate install + - name: Print useful paths + run: | + Write-Host "Workspace: $env:GITHUB_WORKSPACE" + Write-Host "Vcpkg Path: $env:GITHUB_WORKSPACE\vcpkg" + Write-Host "Triplet: ${{ matrix.triplet }}" + - name: Build project - run: msbuild.exe /p:VcpkgEnableManifest=true /p:Configuration=Debug /p:Platform=x64 /p:VcpkgRoot=$env:GITHUB_WORKSPACE/vcpkg vcproj/canary.sln + env: + GITHUB_WORKSPACE: ${{ github.workspace }} + run: msbuild.exe /p:VcpkgEnableManifest=true /p:Configuration=Debug /p:Platform=x64 /p:GITHUB_WORKSPACE="$env:GITHUB_WORKSPACE" vcproj/canary.sln - name: Upload artifacts uses: actions/upload-artifact@main diff --git a/CMakeLists.txt b/CMakeLists.txt index 8730b5057fb..9c8ffef6c0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,7 +113,6 @@ option(RUN_TESTS_AFTER_BUILD "Run tests when building" OFF) # By default, tests # ***************************************************************************** # Add project # ***************************************************************************** -add_subdirectory(src/protobuf) add_subdirectory(src) if(BUILD_TESTS) diff --git a/cmake/modules/BaseConfig.cmake b/cmake/modules/BaseConfig.cmake index b79167ed6a2..6f58a2eebdb 100644 --- a/cmake/modules/BaseConfig.cmake +++ b/cmake/modules/BaseConfig.cmake @@ -1,3 +1,5 @@ +cmake_minimum_required(VERSION 3.22 FATAL_ERROR) + # ***************************************************************************** # CMake Features # ***************************************************************************** @@ -69,6 +71,7 @@ option(DEBUG_LOG "Enable Debug Log" OFF) option(ASAN_ENABLED "Build this target with AddressSanitizer" OFF) option(BUILD_STATIC_LIBRARY "Build using static libraries" OFF) option(SPEED_UP_BUILD_UNITY "Compile using build unity for speed up build" ON) +option(USE_PRECOMPILED_HEADER "Compile using precompiled header" ON) # === ASAN === if(ASAN_ENABLED) diff --git a/cmake/modules/CanaryLib.cmake b/cmake/modules/CanaryLib.cmake index 957a83c7a3e..202d25efa33 100644 --- a/cmake/modules/CanaryLib.cmake +++ b/cmake/modules/CanaryLib.cmake @@ -14,27 +14,22 @@ add_subdirectory(lib) add_subdirectory(kv) add_subdirectory(lua) add_subdirectory(map) +add_subdirectory(protobuf) add_subdirectory(security) add_subdirectory(server) add_subdirectory(utils) # Add more global sources - please add preferably in the sub_directory CMakeLists. -set(ProtobufFiles - protobuf/appearances.pb.cc - protobuf/kv.pb.cc -) - -# Add more global sources - please add preferably in the sub_directory CMakeLists. -target_sources(${PROJECT_NAME}_lib PRIVATE canary_server.cpp ${ProtobufFiles}) - -# Skip unity build inclusion for protobuf files -set_source_files_properties( - ${ProtobufFiles} PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON -) - +target_sources(${PROJECT_NAME}_lib PRIVATE canary_server.cpp) # Add public pre compiler header to lib, to pass down to related targets -target_precompile_headers(${PROJECT_NAME}_lib PUBLIC pch.hpp) +if (NOT SPEED_UP_BUILD_UNITY) + target_precompile_headers(${PROJECT_NAME}_lib PUBLIC pch.hpp) +endif() + +if(NOT SPEED_UP_BUILD_UNITY AND USE_PRECOMPILED_HEADERS) + target_compile_definitions(${PROJECT_NAME}_lib PUBLIC -DUSE_PRECOMPILED_HEADER) +endif() # ***************************************************************************** # Build flags - need to be set before the links and sources @@ -52,8 +47,8 @@ if(MSVC) MODULE_LINKER_FLAGS "/LTCG" EXE_LINKER_FLAGS "/LTCG") else() - include(CheckIPOSupported) - check_ipo_supported(RESULT result) + include(CheckIPOSupported) + check_ipo_supported(RESULT result) if(result) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto=auto") message(STATUS "IPO/LTO enabled with -flto=auto for non-MSVC compiler.") @@ -102,14 +97,15 @@ target_link_libraries(${PROJECT_NAME}_lib unofficial::argon2::libargon2 unofficial::libmariadb unofficial::mariadbclient - opentelemetry-cpp::common - opentelemetry-cpp::metrics - opentelemetry-cpp::api - opentelemetry-cpp::ext - opentelemetry-cpp::sdk - opentelemetry-cpp::logs - opentelemetry-cpp::ostream_metrics_exporter - opentelemetry-cpp::prometheus_exporter + opentelemetry-cpp::common + opentelemetry-cpp::metrics + opentelemetry-cpp::api + opentelemetry-cpp::ext + opentelemetry-cpp::sdk + opentelemetry-cpp::logs + opentelemetry-cpp::ostream_metrics_exporter + opentelemetry-cpp::prometheus_exporter + protobuf ) if(CMAKE_BUILD_TYPE MATCHES Debug) @@ -121,8 +117,10 @@ endif() if (MSVC) if(BUILD_STATIC_LIBRARY) target_link_libraries(${PROJECT_NAME}_lib PUBLIC jsoncpp_static) + set(VCPKG_TARGET_TRIPLET "x64-windows-static" CACHE STRING "") else() target_link_libraries(${PROJECT_NAME}_lib PUBLIC jsoncpp_lib) + set(VCPKG_TARGET_TRIPLET "x64-windows" CACHE STRING "") endif() target_link_libraries(${PROJECT_NAME}_lib PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${MYSQL_CLIENT_LIBS}) diff --git a/data-otservbr-global/lib/core/storages.lua b/data-otservbr-global/lib/core/storages.lua index 116a87fec56..11cd653f0ae 100644 --- a/data-otservbr-global/lib/core/storages.lua +++ b/data-otservbr-global/lib/core/storages.lua @@ -3071,6 +3071,10 @@ GlobalStorage = { AftershockHealth = 60174, ForeshockStage = 60175, AftershockStage = 60176, + RuptureResonanceStage = 60177, + RuptureResonanceActive = 60178, + EradicatorWeak = 60178, + EradicatorReleaseT = 60179, OutburstStage = 60180, OutburstHealth = 60181, OutburstChargingKilled = 60182, diff --git a/data-otservbr-global/scripts/actions/other/potions.lua b/data-otservbr-global/scripts/actions/other/potions.lua index febc3ed9d3e..921eb551aeb 100644 --- a/data-otservbr-global/scripts/actions/other/potions.lua +++ b/data-otservbr-global/scripts/actions/other/potions.lua @@ -268,13 +268,12 @@ function flaskPotion.onUse(player, item, fromPosition, target, toPosition, isHot player:addAchievementProgress("Potion Addict", 100000) target:say("Aaaah...", MESSAGE_POTION) - if fromPosition.x == CONTAINER_POSITION and not container == store_inbox then - local container = Container(item:getParent().uid) - if player:getStorageValueByName("talkaction.potions.flask") ~= 1 then + local deactivatedFlasks = player:kv():get("talkaction.potions.flask") or false + if not deactivatedFlasks then + if fromPosition.x == CONTAINER_POSITION then + local container = Container(item:getParent().uid) container:addItem(potion.flask, 1) - end - else - if player:getStorageValueByName("talkaction.potions.flask") ~= 1 then + else player:addItem(potion.flask, 1) end end diff --git a/data-otservbr-global/scripts/actions/quests/heart_of_destruction/rupture_lever.lua b/data-otservbr-global/scripts/actions/quests/heart_of_destruction/rupture_lever.lua index 3c335c70716..ecb892cef8e 100644 --- a/data-otservbr-global/scripts/actions/quests/heart_of_destruction/rupture_lever.lua +++ b/data-otservbr-global/scripts/actions/quests/heart_of_destruction/rupture_lever.lua @@ -1,130 +1,41 @@ --- FUNCTIONS -local function doCheckArea() - local upConer = { x = 32324, y = 31239, z = 14 } -- upLeftCorner - local downConer = { x = 32347, y = 31263, z = 14 } -- downRightCorner - - for i = upConer.x, downConer.x do - for j = upConer.y, downConer.y do - for k = upConer.z, downConer.z do - local room = { x = i, y = j, z = k } - local tile = Tile(room) - if tile then - local creatures = tile:getCreatures() - if creatures and #creatures > 0 then - for _, creature in pairs(creatures) do - local player = Player(creature) - if player then - return true - end - end - end - end - end - end - end - return false -end - -local function clearArea() - local upConer = { x = 32324, y = 31239, z = 14 } -- upLeftCorner - local downConer = { x = 32347, y = 31263, z = 14 } -- downRightCorner - - for i = upConer.x, downConer.x do - for j = upConer.y, downConer.y do - for k = upConer.z, downConer.z do - local room = { x = i, y = j, z = k } - local tile = Tile(room) - if tile then - local creatures = tile:getCreatures() - if creatures and #creatures > 0 then - for _, creatureUid in pairs(creatures) do - local creature = Creature(creatureUid) - if creature then - if creature:isPlayer() then - creature:teleportTo({ x = 32088, y = 31321, z = 13 }) - elseif creature:isMonster() then - creature:remove() - end - end - end - end - end - end - end - end -end --- FUNCTIONS END - -local heartDestructionRupture = Action() -function heartDestructionRupture.onUse(player, item, fromPosition, itemEx, toPosition) - local config = { - playerPositions = { - Position(32309, 31248, 14), - Position(32309, 31249, 14), - Position(32309, 31250, 14), - Position(32309, 31251, 14), - Position(32309, 31252, 14), - }, - - newPos = { x = 32335, y = 31257, z = 14 }, - } - - local pushPos = { x = 32309, y = 31248, z = 14 } - - if item.actionid == 14327 then - if item.itemid == 8911 then - if player:getPosition().x == pushPos.x and player:getPosition().y == pushPos.y and player:getPosition().z == pushPos.z then - local storePlayers = {} - for i = 1, #config.playerPositions do - local tile = Tile(Position(config.playerPositions[i])) - if tile then - local playerTile = tile:getTopCreature() - if playerTile and playerTile:isPlayer() then - storePlayers[#storePlayers + 1] = playerTile - end - end - end - - if doCheckArea() == false then - clearArea() - - local players - - for i = 1, #storePlayers do - players = storePlayers[i] - config.playerPositions[i]:sendMagicEffect(CONST_ME_POFF) - players:teleportTo(config.newPos) - players:setBossCooldown("Rupture", os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN)) - end - Position(config.newPos):sendMagicEffect(11) - - areaRupture1 = addEvent(clearArea, 15 * 60000) - - ruptureResonanceStage = 0 - resonanceActive = false - - Game.createMonster("Spark of Destruction", { x = 32331, y = 31254, z = 14 }, false, true) - Game.createMonster("Spark of Destruction", { x = 32338, y = 31254, z = 14 }, false, true) - Game.createMonster("Spark of Destruction", { x = 32330, y = 31250, z = 14 }, false, true) - Game.createMonster("Spark of Destruction", { x = 32338, y = 31250, z = 14 }, false, true) - Game.createMonster("Rupture", { x = 32332, y = 31250, z = 14 }, false, true) - - local vortex = Tile({ x = 32326, y = 31250, z = 14 }):getItemById(23482) - if vortex then - vortex:transform(23483) - vortex:setActionId(14343) - end - else - player:sendTextMessage(19, "Someone is in the area.") - end - else - return true +local config = { + boss = { + name = "Rupture", + position = Position(32332, 31250, 14), + }, + playerPositions = { + { pos = Position(32309, 31248, 14), teleport = Position(32335, 31257, 14), effect = CONST_ME_TELEPORT }, + { pos = Position(32309, 31249, 14), teleport = Position(32335, 31257, 14), effect = CONST_ME_TELEPORT }, + { pos = Position(32309, 31250, 14), teleport = Position(32335, 31257, 14), effect = CONST_ME_TELEPORT }, + { pos = Position(32309, 31251, 14), teleport = Position(32335, 31257, 14), effect = CONST_ME_TELEPORT }, + { pos = Position(32309, 31252, 14), teleport = Position(32335, 31257, 14), effect = CONST_ME_TELEPORT }, + }, + specPos = { + from = Position(32324, 31239, 14), + to = Position(32347, 31263, 14), + }, + monsters = { + { name = "Spark of Destruction", pos = Position(32331, 31254, 14) }, + { name = "Spark of Destruction", pos = Position(32338, 31254, 14) }, + { name = "Spark of Destruction", pos = Position(32330, 31250, 14) }, + { name = "Spark of Destruction", pos = Position(32338, 31250, 14) }, + }, + onUseExtra = function() + Game.setStorageValue(GlobalStorage.HeartOfDestruction.RuptureResonanceStage, -1) + Game.setStorageValue(GlobalStorage.HeartOfDestruction.RuptureResonanceActive, -1) + + local tile = Tile(Position(32326, 31250, 14)) + if tile then + local vortex = tile:getItemById(23482) + if vortex then + vortex:transform(23483) + vortex:setActionId(14343) end end - item:transform(item.itemid == 8911 and 8912 or 8911) - end - return true -end + end, + exit = Position(32088, 31321, 13), +} -heartDestructionRupture:aid(14327) -heartDestructionRupture:register() +local lever = BossLever(config) +lever:aid(14327) +lever:register() diff --git a/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/rupture_heal.lua b/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/rupture_heal.lua index 9951dcd71e7..00915af16a8 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/rupture_heal.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/rupture_heal.lua @@ -1,7 +1,9 @@ local ruptureHeal = CreatureEvent("RuptureHeal") + function ruptureHeal.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin) - local healthGain = math.random(5000, 10000) - if attacker and attacker:isPlayer() and resonanceActive == true then + local resonanceActive = Game.getStorageValue(GlobalStorage.HeartOfDestruction.RuptureResonanceActive) + if attacker and attacker:isPlayer() and resonanceActive == 1 then + local healthGain = math.random(5000, 10000) creature:addHealth(healthGain) creature:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN) end diff --git a/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/rupture_resonance.lua b/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/rupture_resonance.lua index 3736d47d7c0..fbbbfefbf12 100644 --- a/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/rupture_resonance.lua +++ b/data-otservbr-global/scripts/creaturescripts/quests/heart_of_destruction/rupture_resonance.lua @@ -1,50 +1,37 @@ +local function createSpawnWave(stage) + Game.createMonster("Spark of Destruction", Position(32331, 31254, 14), false, true) + Game.createMonster("Spark of Destruction", Position(32338, 31254, 14), false, true) + Game.createMonster("Spark of Destruction", Position(32330, 31250, 14), false, true) + Game.createMonster("Spark of Destruction", Position(32338, 31250, 14), false, true) + Game.createMonster("Damage Resonance", Position(32332, 31250, 14), false, true) + Game.setStorageValue(GlobalStorage.HeartOfDestruction.RuptureResonanceStage, stage) + Game.setStorageValue(GlobalStorage.HeartOfDestruction.RuptureResonanceActive, 1) +end + local ruptureResonance = CreatureEvent("RuptureResonance") + function ruptureResonance.onThink(creature) if not creature or not creature:isMonster() then return false end - local hp = (creature:getHealth() / creature:getMaxHealth()) * 100 - if hp <= 80 and ruptureResonanceStage == 0 and resonanceActive == false then - Game.createMonster("spark of destruction", { x = 32331, y = 31254, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32338, y = 31254, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32330, y = 31250, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32338, y = 31250, z = 14 }, false, true) - Game.createMonster("damage resonance", { x = 32332, y = 31250, z = 14 }, false, true) - ruptureResonanceStage = 1 - resonanceActive = true - elseif hp <= 60 and ruptureResonanceStage == 1 and resonanceActive == false then - Game.createMonster("spark of destruction", { x = 32331, y = 31254, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32338, y = 31254, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32330, y = 31250, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32338, y = 31250, z = 14 }, false, true) - Game.createMonster("damage resonance", { x = 32332, y = 31250, z = 14 }, false, true) - ruptureResonanceStage = 2 - resonanceActive = true - elseif hp <= 40 and ruptureResonanceStage == 2 and resonanceActive == false then - Game.createMonster("spark of destruction", { x = 32331, y = 31254, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32338, y = 31254, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32330, y = 31250, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32338, y = 31250, z = 14 }, false, true) - Game.createMonster("damage resonance", { x = 32332, y = 31250, z = 14 }, false, true) - ruptureResonanceStage = 3 - resonanceActive = true - elseif hp <= 25 and ruptureResonanceStage == 3 and resonanceActive == false then - Game.createMonster("spark of destruction", { x = 32331, y = 31254, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32338, y = 31254, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32330, y = 31250, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32338, y = 31250, z = 14 }, false, true) - Game.createMonster("damage resonance", { x = 32332, y = 31250, z = 14 }, false, true) - ruptureResonanceStage = 4 - resonanceActive = true - elseif hp <= 10 and ruptureResonanceStage == 4 and resonanceActive == false then - Game.createMonster("spark of destruction", { x = 32331, y = 31254, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32338, y = 31254, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32330, y = 31250, z = 14 }, false, true) - Game.createMonster("spark of destruction", { x = 32338, y = 31250, z = 14 }, false, true) - Game.createMonster("damage resonance", { x = 32332, y = 31250, z = 14 }, false, true) - ruptureResonanceStage = -1 - resonanceActive = true + local ruptureResonanceStage = Game.getStorageValue(GlobalStorage.HeartOfDestruction.RuptureResonanceStage) > 0 and Game.getStorageValue(GlobalStorage.HeartOfDestruction.RuptureResonanceStage) or 0 + local resonanceActive = Game.setStorageValue(GlobalStorage.HeartOfDestruction.RuptureResonanceActive) + + local thresholds = { + { limit = 80, stage = 0, wave = 1 }, + { limit = 60, stage = 1, wave = 2 }, + { limit = 40, stage = 2, wave = 3 }, + { limit = 25, stage = 3, wave = 4 }, + { limit = 10, stage = 4, wave = -1 }, + } + + local hpPercent = (creature:getHealth() / creature:getMaxHealth()) * 100 + for _, threshold in ipairs(thresholds) do + if hpPercent <= threshold.limit and ruptureResonanceStage == threshold.stage and resonanceActive ~= 1 then + createSpawnWave(threshold.wave) + break + end end return true diff --git a/data/XML/storages.xml b/data/XML/storages.xml index 171eec35a7a..735b4c62ed8 100644 --- a/data/XML/storages.xml +++ b/data/XML/storages.xml @@ -29,6 +29,5 @@ When adding a new range or storage, make sure that the ranges do not overlap, an - diff --git a/data/libs/achievements_lib.lua b/data/libs/achievements_lib.lua index 2b0f441ad29..d95fed99b69 100644 --- a/data/libs/achievements_lib.lua +++ b/data/libs/achievements_lib.lua @@ -570,10 +570,6 @@ achievements = { [475] = { name = "Taskmaster", grade = 1, points = 2, description = "Having hunted and bested them all, you live for the thrill of the hunt!" }, [476] = { name = "Verminbane", grade = 1, points = 2, description = "And so it begins!" }, - --12.60 - [480] = { name = "Honorary Rascoohan", grade = 1, points = 2, description = "When in Rascacoon, do as the Rascoohans do!" }, - [481] = { name = "Release the Kraken", grade = 1, points = 3, description = "Riding around on this squishy companion gives you the feeling of flying through the air... uhm... swimming through the seven seas!" }, - --Custom [477] = { name = "Waypoint Explorer", grade = 1, points = 1, description = "You've explored all the towns of Tibia and discovered each town's waypoint." }, [478] = { name = "Up the Molehill", grade = 1, points = 3, description = "Putting this candle stump on your new mount was kind of a waiting game. You're even tempted to call it whack-a-mole. But in the end you found a loyal companion for your journeys into the depths." }, diff --git a/data/scripts/talkactions/player/flask.lua b/data/scripts/talkactions/player/flask.lua index f3ccdb0bb7a..232b9485602 100644 --- a/data/scripts/talkactions/player/flask.lua +++ b/data/scripts/talkactions/player/flask.lua @@ -5,12 +5,12 @@ function flask.onSay(player, words, param) player:sendCancelMessage("You need to specify on/off param.") return true end - if param == "on" and player:getStorageValueByName("talkaction.potions.flask") ~= 1 then - player:setStorageValueByName("talkaction.potions.flask", 1) + if param == "on" then + player:kv():set("talkaction.potions.flask", true) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You will not receive flasks!") player:getPosition():sendMagicEffect(CONST_ME_REDSMOKE) elseif param == "off" then - player:setStorageValueByName("talkaction.potions.flask", 0) + player:kv():remove("talkaction.potions.flask") player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You will receive flasks.") player:getPosition():sendMagicEffect(CONST_ME_REDSMOKE) end diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index abd35c09c36..2abd46f06c2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,3 +1,5 @@ +cmake_minimum_required(VERSION 3.22 FATAL_ERROR) + # Base configurations and settings for the project include(BaseConfig) include(GNUInstallDirs) diff --git a/src/account/account_definitions.hpp b/src/account/account_definitions.hpp index 0948055f2b5..b6867e47b13 100644 --- a/src/account/account_definitions.hpp +++ b/src/account/account_definitions.hpp @@ -9,7 +9,10 @@ #pragma once -#include +#ifndef USE_PRECOMPILED_HEADERS + #include + #include +#endif namespace account { enum Errors : uint8_t { diff --git a/src/creatures/combat/spells.cpp b/src/creatures/combat/spells.cpp index 013d1b4a1ff..a0554fdcbbe 100644 --- a/src/creatures/combat/spells.cpp +++ b/src/creatures/combat/spells.cpp @@ -16,6 +16,8 @@ #include "lua/scripts/lua_environment.hpp" #include "creatures/players/wheel/player_wheel.hpp" +#include "lua/global/lua_variant.hpp" + Spells::Spells() = default; Spells::~Spells() = default; diff --git a/src/creatures/combat/spells.hpp b/src/creatures/combat/spells.hpp index 4a237ff391d..804ec62f930 100644 --- a/src/creatures/combat/spells.hpp +++ b/src/creatures/combat/spells.hpp @@ -20,6 +20,8 @@ class InstantSpell; class RuneSpell; class Spell; +struct LuaVariant; + using VocSpellMap = std::map; class Spells final : public Scripts { diff --git a/src/creatures/creatures_definitions.hpp b/src/creatures/creatures_definitions.hpp index 71c607b64c3..674f0b6775c 100644 --- a/src/creatures/creatures_definitions.hpp +++ b/src/creatures/creatures_definitions.hpp @@ -9,8 +9,18 @@ #pragma once -// Enum +#ifndef USE_PRECOMPILED_HEADERS + #include + #include + #include + #include + #include + #include + #include + #include +#endif +// Enum enum SkillsId_t { SKILLVALUE_LEVEL = 0, SKILLVALUE_TRIES = 1, @@ -317,72 +327,6 @@ enum MarketOfferState_t { OFFERSTATE_ACCEPTEDEX = 255, }; -enum ObjectCategory_t { - OBJECTCATEGORY_NONE = 0, - OBJECTCATEGORY_ARMORS = 1, - OBJECTCATEGORY_NECKLACES = 2, - OBJECTCATEGORY_BOOTS = 3, - OBJECTCATEGORY_CONTAINERS = 4, - OBJECTCATEGORY_DECORATION = 5, - OBJECTCATEGORY_FOOD = 6, - OBJECTCATEGORY_HELMETS = 7, - OBJECTCATEGORY_LEGS = 8, - OBJECTCATEGORY_OTHERS = 9, - OBJECTCATEGORY_POTIONS = 10, - OBJECTCATEGORY_RINGS = 11, - OBJECTCATEGORY_RUNES = 12, - OBJECTCATEGORY_SHIELDS = 13, - OBJECTCATEGORY_TOOLS = 14, - OBJECTCATEGORY_VALUABLES = 15, - OBJECTCATEGORY_AMMO = 16, - OBJECTCATEGORY_AXES = 17, - OBJECTCATEGORY_CLUBS = 18, - OBJECTCATEGORY_DISTANCEWEAPONS = 19, - OBJECTCATEGORY_SWORDS = 20, - OBJECTCATEGORY_WANDS = 21, - OBJECTCATEGORY_PREMIUMSCROLLS = 22, // not used in quickloot - OBJECTCATEGORY_TIBIACOINS = 23, // not used in quickloot - OBJECTCATEGORY_CREATUREPRODUCTS = 24, - OBJECTCATEGORY_GOLD = 30, - OBJECTCATEGORY_DEFAULT = 31, // unassigned loot - - OBJECTCATEGORY_FIRST = OBJECTCATEGORY_ARMORS, - OBJECTCATEGORY_LAST = OBJECTCATEGORY_DEFAULT, -}; - -static bool isValidObjectCategory(uint8_t category) { - static std::unordered_set valid = { - OBJECTCATEGORY_NONE, - OBJECTCATEGORY_ARMORS, - OBJECTCATEGORY_NECKLACES, - OBJECTCATEGORY_BOOTS, - OBJECTCATEGORY_CONTAINERS, - OBJECTCATEGORY_DECORATION, - OBJECTCATEGORY_FOOD, - OBJECTCATEGORY_HELMETS, - OBJECTCATEGORY_LEGS, - OBJECTCATEGORY_OTHERS, - OBJECTCATEGORY_POTIONS, - OBJECTCATEGORY_RINGS, - OBJECTCATEGORY_RUNES, - OBJECTCATEGORY_SHIELDS, - OBJECTCATEGORY_TOOLS, - OBJECTCATEGORY_VALUABLES, - OBJECTCATEGORY_AMMO, - OBJECTCATEGORY_AXES, - OBJECTCATEGORY_CLUBS, - OBJECTCATEGORY_DISTANCEWEAPONS, - OBJECTCATEGORY_SWORDS, - OBJECTCATEGORY_WANDS, - OBJECTCATEGORY_PREMIUMSCROLLS, - OBJECTCATEGORY_TIBIACOINS, - OBJECTCATEGORY_CREATUREPRODUCTS, - OBJECTCATEGORY_GOLD, - OBJECTCATEGORY_DEFAULT, - }; - return valid.contains(category); -} - enum RespawnPeriod_t { RESPAWNPERIOD_ALL, RESPAWNPERIOD_DAY, @@ -1488,7 +1432,7 @@ struct FamiliarEntry { struct Skill { uint64_t tries = 0; uint16_t level = 10; - double_t percent = 0; + double percent = 0; }; struct Kill { diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index 576957ec553..9a2e04af8b4 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -17,6 +17,7 @@ #include "creatures/players/wheel/player_wheel.hpp" #include "creatures/players/storages/storages.hpp" #include "game/game.hpp" +#include "game/modal_window/modal_window.hpp" #include "game/scheduling/dispatcher.hpp" #include "game/scheduling/task.hpp" #include "game/scheduling/save_manager.hpp" @@ -32,6 +33,7 @@ #include "core.hpp" #include "map/spectators.hpp" #include "lib/metrics/metrics.hpp" +#include "enums/object_category.hpp" MuteCountMap Player::muteCountMap; @@ -6539,6 +6541,17 @@ void Player::initializeTaskHunting() { } std::string Player::getBlessingsName() const { + static const phmap::flat_hash_map BlessingNames = { + { TWIST_OF_FATE, "Twist of Fate" }, + { WISDOM_OF_SOLITUDE, "The Wisdom of Solitude" }, + { SPARK_OF_THE_PHOENIX, "The Spark of the Phoenix" }, + { FIRE_OF_THE_SUNS, "The Fire of the Suns" }, + { SPIRITUAL_SHIELDING, "The Spiritual Shielding" }, + { EMBRACE_OF_TIBIA, "The Embrace of Tibia" }, + { BLOOD_OF_THE_MOUNTAIN, "Blood of the Mountain" }, + { HEARTH_OF_THE_MOUNTAIN, "Heart of the Mountain" }, + }; + uint8_t count = 0; std::for_each(blessings.begin(), blessings.end(), [&count](uint8_t amount) { if (amount != 0) { diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index 192eb53ff6e..048ea3a9285 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -34,6 +34,7 @@ #include "vocations/vocation.hpp" #include "creatures/npcs/npc.hpp" #include "game/bank/bank.hpp" +#include "enums/object_category.hpp" class House; class NetworkMessage; @@ -50,6 +51,8 @@ class Spell; class PlayerWheel; class Spectators; +struct ModalWindow; + struct ForgeHistory { ForgeAction_t actionType = ForgeAction_t::FUSION; uint8_t tier = 0; diff --git a/src/database/database.cpp b/src/database/database.cpp index 916ffd1ee44..c548b13614a 100644 --- a/src/database/database.cpp +++ b/src/database/database.cpp @@ -99,6 +99,10 @@ bool Database::commit() { return true; } +bool Database::isRecoverableError(unsigned int error) const { + return error == CR_SERVER_LOST || error == CR_SERVER_GONE_ERROR || error == CR_CONN_HOST_ERROR || error == 1053 /*ER_SERVER_SHUTDOWN*/ || error == CR_CONNECTION_ERROR; +} + bool Database::retryQuery(const std::string_view &query, int retries) { while (retries > 0 && mysql_query(handle, query.data()) != 0) { g_logger().error("Query: {}", query.substr(0, 256)); diff --git a/src/database/database.hpp b/src/database/database.hpp index 9158ae7080d..e6c0b46182a 100644 --- a/src/database/database.hpp +++ b/src/database/database.hpp @@ -12,6 +12,11 @@ #include "declarations.hpp" #include "lib/logging/log_with_spd_log.hpp" +#ifndef USE_PRECOMPILED_HEADERS + #include + #include +#endif + class DBResult; using DBResult_ptr = std::shared_ptr; @@ -58,9 +63,7 @@ class Database { bool rollback(); bool commit(); - bool isRecoverableError(unsigned int error) const { - return error == CR_SERVER_LOST || error == CR_SERVER_GONE_ERROR || error == CR_CONN_HOST_ERROR || error == 1053 /*ER_SERVER_SHUTDOWN*/ || error == CR_CONNECTION_ERROR; - } + bool isRecoverableError(unsigned int error) const; MYSQL* handle = nullptr; std::recursive_mutex databaseLock; diff --git a/src/enums/lua_variant_type.hpp b/src/enums/lua_variant_type.hpp new file mode 100644 index 00000000000..7f7ac216dd5 --- /dev/null +++ b/src/enums/lua_variant_type.hpp @@ -0,0 +1,19 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019-2022 OpenTibiaBR + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ + +#pragma once + +enum LuaVariantType_t { + VARIANT_NONE, + + VARIANT_NUMBER, + VARIANT_POSITION, + VARIANT_TARGETPOSITION, + VARIANT_STRING, +}; diff --git a/src/enums/object_category.hpp b/src/enums/object_category.hpp new file mode 100644 index 00000000000..fe3e4422a34 --- /dev/null +++ b/src/enums/object_category.hpp @@ -0,0 +1,43 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019-2022 OpenTibiaBR + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ + +#pragma once + +enum ObjectCategory_t { + OBJECTCATEGORY_NONE = 0, + OBJECTCATEGORY_ARMORS = 1, + OBJECTCATEGORY_NECKLACES = 2, + OBJECTCATEGORY_BOOTS = 3, + OBJECTCATEGORY_CONTAINERS = 4, + OBJECTCATEGORY_DECORATION = 5, + OBJECTCATEGORY_FOOD = 6, + OBJECTCATEGORY_HELMETS = 7, + OBJECTCATEGORY_LEGS = 8, + OBJECTCATEGORY_OTHERS = 9, + OBJECTCATEGORY_POTIONS = 10, + OBJECTCATEGORY_RINGS = 11, + OBJECTCATEGORY_RUNES = 12, + OBJECTCATEGORY_SHIELDS = 13, + OBJECTCATEGORY_TOOLS = 14, + OBJECTCATEGORY_VALUABLES = 15, + OBJECTCATEGORY_AMMO = 16, + OBJECTCATEGORY_AXES = 17, + OBJECTCATEGORY_CLUBS = 18, + OBJECTCATEGORY_DISTANCEWEAPONS = 19, + OBJECTCATEGORY_SWORDS = 20, + OBJECTCATEGORY_WANDS = 21, + OBJECTCATEGORY_PREMIUMSCROLLS = 22, // not used in quickloot + OBJECTCATEGORY_TIBIACOINS = 23, // not used in quickloot + OBJECTCATEGORY_CREATUREPRODUCTS = 24, + OBJECTCATEGORY_GOLD = 30, + OBJECTCATEGORY_DEFAULT = 31, // unassigned loot + + OBJECTCATEGORY_FIRST = OBJECTCATEGORY_ARMORS, + OBJECTCATEGORY_LAST = OBJECTCATEGORY_DEFAULT, +}; diff --git a/src/game/game.cpp b/src/game/game.cpp index 732b589e488..397695f822f 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -36,12 +36,13 @@ #include "creatures/players/wheel/player_wheel.hpp" #include "creatures/npcs/npc.hpp" #include "server/network/webhook/webhook.hpp" -#include "protobuf/appearances.pb.h" #include "server/network/protocol/protocollogin.hpp" #include "server/network/protocol/protocolstatus.hpp" #include "map/spectators.hpp" - #include "kv/kv.hpp" +#include "enums/object_category.hpp" + +#include namespace InternalGame { void sendBlockEffect(BlockType_t blockType, CombatType_t combatType, const Position &targetPos, std::shared_ptr source) { @@ -247,8 +248,8 @@ void Game::loadBoostedCreature() { const auto monsterType = g_monsters().getMonsterType(selectedMonster.name); if (!monsterType) { g_logger().warn("[Game::loadBoostedCreature] - " - "It was not possible to generate a new boosted creature-> Monster '" - + selectedMonster.name + "' not found."); + "It was not possible to generate a new boosted creature-> Monster '{}' not found.", + selectedMonster.name); return; } @@ -1030,8 +1031,8 @@ FILELOADER_ERRORS Game::loadAppearanceProtobuf(const std::string &file) { // Verify that the version of the library that we linked against is // compatible with the version of the headers we compiled against. GOOGLE_PROTOBUF_VERIFY_VERSION; - appearances = Appearances(); - if (!appearances.ParseFromIstream(&fileStream)) { + m_appearancesPtr = std::make_unique(); + if (!m_appearancesPtr->ParseFromIstream(&fileStream)) { g_logger().error("[Game::loadAppearanceProtobuf] - Failed to parse binary file {}, file is invalid", file); fileStream.close(); return ERROR_NOT_OPEN; @@ -1043,18 +1044,18 @@ FILELOADER_ERRORS Game::loadAppearanceProtobuf(const std::string &file) { // Only iterate other objects if necessary if (g_configManager().getBoolean(WARN_UNSAFE_SCRIPTS, __FUNCTION__)) { // Registering distance effects - for (uint32_t it = 0; it < appearances.effect_size(); it++) { - registeredMagicEffects.push_back(static_cast(appearances.effect(it).id())); + for (uint32_t it = 0; it < m_appearancesPtr->effect_size(); it++) { + registeredMagicEffects.push_back(static_cast(m_appearancesPtr->effect(it).id())); } // Registering missile effects - for (uint32_t it = 0; it < appearances.missile_size(); it++) { - registeredDistanceEffects.push_back(static_cast(appearances.missile(it).id())); + for (uint32_t it = 0; it < m_appearancesPtr->missile_size(); it++) { + registeredDistanceEffects.push_back(static_cast(m_appearancesPtr->missile(it).id())); } // Registering outfits - for (uint32_t it = 0; it < appearances.outfit_size(); it++) { - registeredLookTypes.push_back(static_cast(appearances.outfit(it).id())); + for (uint32_t it = 0; it < m_appearancesPtr->outfit_size(); it++) { + registeredLookTypes.push_back(static_cast(m_appearancesPtr->outfit(it).id())); } } @@ -2165,7 +2166,7 @@ std::tuple Game::addItemBatch(const std::shared } } - if (dropping || ret != RETURNVALUE_NOERROR && dropOnMap) { + if (dropping || (ret != RETURNVALUE_NOERROR && dropOnMap)) { dropping = true; ret = internalAddItem(destination->getTile(), item, INDEX_WHEREEVER, FLAG_NOLIMIT); } @@ -7611,7 +7612,7 @@ bool Game::gameIsDay() { return isDay; } -void Game::dieSafely(std::string errorMsg /* = "" */) { +void Game::dieSafely(const std::string &errorMsg /* = "" */) { g_logger().error(errorMsg); shutdown(); } diff --git a/src/game/game.hpp b/src/game/game.hpp index 6db878c7ce2..1ff697989d8 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -23,7 +23,17 @@ #include "creatures/players/grouping/team_finder.hpp" #include "utils/wildcardtree.hpp" #include "items/items_classification.hpp" -#include "protobuf/appearances.pb.h" +#include "modal_window/modal_window.hpp" +#include "enums/object_category.hpp" + +// Forward declaration for protobuf class +namespace Canary { + namespace protobuf { + namespace appearances { + class Appearances; + } // namespace appearances + } // namespace protobuf +} // namespace Canary class ServiceManager; class Creature; @@ -361,7 +371,6 @@ class Game { void playerLootAllCorpses(std::shared_ptr player, const Position &pos, bool lootAllCorpses); void playerSetManagedContainer(uint32_t playerId, ObjectCategory_t category, const Position &pos, uint16_t itemId, uint8_t stackPos, bool isLootContainer); void playerClearManagedContainer(uint32_t playerId, ObjectCategory_t category, bool isLootContainer); - ; void playerOpenManagedContainer(uint32_t playerId, ObjectCategory_t category, bool isLootContainer); void playerSetQuickLootFallback(uint32_t playerId, bool fallback); void playerQuickLootBlackWhitelist(uint32_t playerId, QuickLootFilter_t filter, const std::vector itemIds); @@ -410,7 +419,7 @@ class Game { void cleanup(); void shutdown(); - void dieSafely(std::string errorMsg); + void dieSafely(const std::string &errorMsg); void addBestiaryList(uint16_t raceid, std::string name); const std::map &getBestiaryList() const { return BestiaryList; @@ -567,7 +576,7 @@ class Game { Map map; Mounts mounts; Raids raids; - Canary::protobuf::appearances::Appearances appearances; + std::unique_ptr m_appearancesPtr; auto getTilesToClean() const { return tilesToClean; diff --git a/src/game/game_definitions.hpp b/src/game/game_definitions.hpp index 17bc69dd514..f529f93d169 100644 --- a/src/game/game_definitions.hpp +++ b/src/game/game_definitions.hpp @@ -9,8 +9,6 @@ #pragma once -#include "movement/position.hpp" - // Enums enum StackPosType_t { STACKPOS_MOVE, @@ -109,20 +107,3 @@ enum Webhook_Colors_t : uint32_t { WEBHOOK_COLOR_YELLOW = 0xFFFF00, WEBHOOK_COLOR_BLUE = 0x0000FF }; - -// Structs -struct ModalWindow { - std::list> buttons, choices; - std::string title, message; - uint32_t id; - uint8_t defaultEnterButton, defaultEscapeButton; - bool priority; - - ModalWindow(uint32_t newId, std::string newTitle, std::string newMessage) : - title(std::move(newTitle)), - message(std::move(newMessage)), - id(newId), - defaultEnterButton(0xFF), - defaultEscapeButton(0xFF), - priority(false) { } -}; diff --git a/src/game/modal_window/modal_window.hpp b/src/game/modal_window/modal_window.hpp new file mode 100644 index 00000000000..f79ab41cfea --- /dev/null +++ b/src/game/modal_window/modal_window.hpp @@ -0,0 +1,33 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019-2022 OpenTibiaBR + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ + +#pragma once + +#ifndef USE_PRECOMPILED_HEADERS + #include + #include + #include + #include +#endif + +struct ModalWindow { + std::list> buttons, choices; + std::string title, message; + uint32_t id; + uint8_t defaultEnterButton, defaultEscapeButton; + bool priority; + + ModalWindow(uint32_t newId, std::string newTitle, std::string newMessage) : + title(std::move(newTitle)), + message(std::move(newMessage)), + id(newId), + defaultEnterButton(0xFF), + defaultEscapeButton(0xFF), + priority(false) { } +}; diff --git a/src/game/movement/position.cpp b/src/game/movement/position.cpp index cdf78d5e307..0dccd9c9beb 100644 --- a/src/game/movement/position.cpp +++ b/src/game/movement/position.cpp @@ -12,6 +12,12 @@ #include "game/movement/position.hpp" #include "utils/tools.hpp" +double Position::getEuclideanDistance(const Position &p1, const Position &p2) { + int32_t dx = Position::getDistanceX(p1, p2); + int32_t dy = Position::getDistanceY(p1, p2); + return std::sqrt(dx * dx + dy * dy); +} + Direction Position::getRandomDirection() { static std::vector dirList { DIRECTION_NORTH, diff --git a/src/game/movement/position.hpp b/src/game/movement/position.hpp index 2f79453eb39..7ec62154785 100644 --- a/src/game/movement/position.hpp +++ b/src/game/movement/position.hpp @@ -62,11 +62,7 @@ struct Position { static int32_t getDiagonalDistance(const Position &p1, const Position &p2) { return std::max(Position::getDistanceX(p1, p2), Position::getDistanceY(p1, p2)); } - static double getEuclideanDistance(const Position &p1, const Position &p2) { - int32_t dx = Position::getDistanceX(p1, p2); - int32_t dy = Position::getDistanceY(p1, p2); - return std::sqrt(dx * dx + dy * dy); - } + static double getEuclideanDistance(const Position &p1, const Position &p2); static Direction getRandomDirection(); diff --git a/src/io/functions/iologindata_load_player.cpp b/src/io/functions/iologindata_load_player.cpp index 2c50938a37f..f4adff4b124 100644 --- a/src/io/functions/iologindata_load_player.cpp +++ b/src/io/functions/iologindata_load_player.cpp @@ -12,6 +12,7 @@ #include "creatures/players/wheel/player_wheel.hpp" #include "io/functions/iologindata_load_player.hpp" #include "game/game.hpp" +#include "enums/object_category.hpp" void IOLoginDataLoad::loadItems(ItemsMap &itemsMap, DBResult_ptr result, const std::shared_ptr &player) { try { diff --git a/src/items/item.cpp b/src/items/item.cpp index a3d8fc76046..2c0569711c7 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -28,6 +28,20 @@ Items Item::items; std::shared_ptr Item::CreateItem(const uint16_t type, uint16_t count /*= 0*/, Position* itemPosition /*= nullptr*/) { + // A map which contains items that, when on creating, should be transformed to the default type. + static const phmap::flat_hash_map ItemTransformationMap = { + { ITEM_SWORD_RING_ACTIVATED, ITEM_SWORD_RING }, + { ITEM_CLUB_RING_ACTIVATED, ITEM_CLUB_RING }, + { ITEM_DWARVEN_RING_ACTIVATED, ITEM_DWARVEN_RING }, + { ITEM_RING_HEALING_ACTIVATED, ITEM_RING_HEALING }, + { ITEM_STEALTH_RING_ACTIVATED, ITEM_STEALTH_RING }, + { ITEM_TIME_RING_ACTIVATED, ITEM_TIME_RING }, + { ITEM_PAIR_SOFT_BOOTS_ACTIVATED, ITEM_PAIR_SOFT_BOOTS }, + { ITEM_DEATH_RING_ACTIVATED, ITEM_DEATH_RING }, + { ITEM_PRISMATIC_RING_ACTIVATED, ITEM_PRISMATIC_RING }, + { ITEM_OLD_DIAMOND_ARROW, ITEM_DIAMOND_ARROW }, + }; + std::shared_ptr newItem = nullptr; const ItemType &it = Item::items[type]; diff --git a/src/items/items.cpp b/src/items/items.cpp index 6c517c8a1ed..b26c980cc45 100644 --- a/src/items/items.cpp +++ b/src/items/items.cpp @@ -14,6 +14,8 @@ #include "game/game.hpp" #include "utils/pugicast.hpp" +#include + Items::Items() = default; void Items::clear() { @@ -76,8 +78,8 @@ void Items::loadFromProtobuf() { using namespace Canary::protobuf::appearances; bool supportAnimation = g_configManager().getBoolean(OLD_PROTOCOL, __FUNCTION__); - for (uint32_t it = 0; it < g_game().appearances.object_size(); ++it) { - Appearance object = g_game().appearances.object(it); + for (uint32_t it = 0; it < g_game().m_appearancesPtr->object_size(); ++it) { + Appearance object = g_game().m_appearancesPtr->object(it); // This scenario should never happen but on custom assets this can break the loader. if (!object.has_flags()) { diff --git a/src/items/weapons/weapons.cpp b/src/items/weapons/weapons.cpp index 05bec0b0a6f..0c6853ec807 100644 --- a/src/items/weapons/weapons.cpp +++ b/src/items/weapons/weapons.cpp @@ -14,6 +14,8 @@ #include "lua/creature/events.hpp" #include "items/weapons/weapons.hpp" +#include "lua/global/lua_variant.hpp" + Weapons::Weapons() = default; Weapons::~Weapons() = default; diff --git a/src/items/weapons/weapons.hpp b/src/items/weapons/weapons.hpp index 78a7195fb3c..b6ab050d8ea 100644 --- a/src/items/weapons/weapons.hpp +++ b/src/items/weapons/weapons.hpp @@ -21,6 +21,8 @@ class WeaponMelee; class WeaponDistance; class WeaponWand; +struct LuaVariant; + using WeaponUnique_ptr = std::unique_ptr; using WeaponShared_ptr = std::shared_ptr; diff --git a/src/kv/CMakeLists.txt b/src/kv/CMakeLists.txt index 71f8a18b6a9..4ca100e96d2 100644 --- a/src/kv/CMakeLists.txt +++ b/src/kv/CMakeLists.txt @@ -1,5 +1,6 @@ target_sources(${PROJECT_NAME}_lib PRIVATE value_wrapper.cpp + value_wrapper_proto.cpp kv.cpp kv_sql.cpp ) diff --git a/src/kv/kv.hpp b/src/kv/kv.hpp index d30e46f2a0d..8f0b0ef40f7 100644 --- a/src/kv/kv.hpp +++ b/src/kv/kv.hpp @@ -9,11 +9,15 @@ #pragma once -#include -#include -#include -#include -#include +#ifndef USE_PRECOMPILED_HEADERS + #include + #include + #include + #include + #include + #include + #include +#endif #include "lib/logging/logger.hpp" #include "kv/value_wrapper.hpp" diff --git a/src/kv/kv_sql.cpp b/src/kv/kv_sql.cpp index 4784efa5c9e..e5a3fc2ba3a 100644 --- a/src/kv/kv_sql.cpp +++ b/src/kv/kv_sql.cpp @@ -9,14 +9,12 @@ #include "pch.hpp" -#include -#include - #include "kv/kv_sql.hpp" #include "kv/value_wrapper_proto.hpp" -#include "protobuf/kv.pb.h" #include "utils/tools.hpp" +#include + std::optional KVSQL::load(const std::string &key) { auto query = fmt::format("SELECT `key_name`, `timestamp`, `value` FROM `kv_store` WHERE `key_name` = {}", db.escapeString(key)); auto result = db.storeQuery(query); @@ -34,7 +32,7 @@ std::optional KVSQL::load(const std::string &key) { auto timestamp = result->getNumber("timestamp"); Canary::protobuf::kv::ValueWrapper protoValue; if (protoValue.ParseFromArray(data, static_cast(size))) { - valueWrapper = ProtoSerializable::fromProto(protoValue, timestamp); + valueWrapper = ProtoSerializable::fromProto(protoValue, timestamp); return valueWrapper; } logger.error("Failed to deserialize value for key {}", key); @@ -66,7 +64,7 @@ bool KVSQL::save(const std::string &key, const ValueWrapper &value) { } bool KVSQL::prepareSave(const std::string &key, const ValueWrapper &value, DBInsert &update) { - auto protoValue = ProtoSerializable::toProto(value); + auto protoValue = ProtoSerializable::toProto(value); std::string data; if (!protoValue.SerializeToString(&data)) { return false; diff --git a/src/kv/value_wrapper.cpp b/src/kv/value_wrapper.cpp index af304eeacad..c8ee3be5038 100644 --- a/src/kv/value_wrapper.cpp +++ b/src/kv/value_wrapper.cpp @@ -1,3 +1,14 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019-2022 OpenTibiaBR + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ + +#include "pch.hpp" + #include "kv/value_wrapper.hpp" #include "utils/tools.hpp" diff --git a/src/kv/value_wrapper_proto.cpp b/src/kv/value_wrapper_proto.cpp new file mode 100644 index 00000000000..9e60296c6e6 --- /dev/null +++ b/src/kv/value_wrapper_proto.cpp @@ -0,0 +1,111 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019-2022 OpenTibiaBR + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ + +#include "pch.hpp" + +#include "kv/value_wrapper_proto.hpp" + +#include "kv/value_wrapper.hpp" + +#include + +namespace ProtoHelpers { + void setProtoStringValue(Canary::protobuf::kv::ValueWrapper &protoValue, const StringType &arg) { + protoValue.set_str_value(arg); + } + + void setProtoBooleanValue(Canary::protobuf::kv::ValueWrapper &protoValue, const BooleanType &arg) { + protoValue.set_bool_value(arg); + } + + void setProtoIntValue(Canary::protobuf::kv::ValueWrapper &protoValue, const IntType &arg) { + protoValue.set_int_value(arg); + } + + void setProtoDoubleValue(Canary::protobuf::kv::ValueWrapper &protoValue, const DoubleType &arg) { + protoValue.set_double_value(arg); + } + + void setProtoArrayValue(Canary::protobuf::kv::ValueWrapper &protoValue, const ArrayType &arg) { + auto arrayValue = protoValue.mutable_array_value(); + for (const auto &elem : arg) { + *arrayValue->add_values() = ProtoSerializable::toProto(elem); + } + } + + void setProtoMapValue(Canary::protobuf::kv::ValueWrapper &protoValue, const MapType &arg) { + auto mapValue = protoValue.mutable_map_value(); + for (const auto &[key, value] : arg) { + auto* elem = mapValue->add_items(); + elem->set_key(key); + *elem->mutable_value() = ProtoSerializable::toProto(*value); + } + } +} + +Canary::protobuf::kv::ValueWrapper ProtoSerializable::toProto(const ValueWrapper &obj) { + Canary::protobuf::kv::ValueWrapper protoValue; + + std::visit( + [&protoValue](const auto &arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + ProtoHelpers::setProtoStringValue(protoValue, arg); + } else if constexpr (std::is_same_v) { + ProtoHelpers::setProtoBooleanValue(protoValue, arg); + } else if constexpr (std::is_same_v) { + ProtoHelpers::setProtoIntValue(protoValue, arg); + } else if constexpr (std::is_same_v) { + ProtoHelpers::setProtoDoubleValue(protoValue, arg); + } else if constexpr (std::is_same_v) { + ProtoHelpers::setProtoArrayValue(protoValue, arg); + } else if constexpr (std::is_same_v) { + ProtoHelpers::setProtoMapValue(protoValue, arg); + } + }, + obj.getVariant() + ); + + return protoValue; +} + +ValueWrapper ProtoSerializable::fromProto(const Canary::protobuf::kv::ValueWrapper &protoValue, uint64_t timestamp) { + ValueVariant data; + switch (protoValue.value_case()) { + case Canary::protobuf::kv::ValueWrapper::kStrValue: + data = protoValue.str_value(); + break; + case Canary::protobuf::kv::ValueWrapper::kBoolValue: + data = protoValue.bool_value(); + break; + case Canary::protobuf::kv::ValueWrapper::kIntValue: + data = protoValue.int_value(); + break; + case Canary::protobuf::kv::ValueWrapper::kDoubleValue: + data = protoValue.double_value(); + break; + case Canary::protobuf::kv::ValueWrapper::kArrayValue: { + ArrayType array; + for (const auto &protoElem : protoValue.array_value().values()) { + array.emplace_back(fromProto(protoElem, timestamp)); + } + data = array; + } break; + case Canary::protobuf::kv::ValueWrapper::kMapValue: { + MapType map; + for (const auto &protoElem : protoValue.map_value().items()) { + map[protoElem.key()] = std::make_shared(fromProto(protoElem.value(), timestamp)); + } + data = map; + } break; + default: + break; + } + return ValueWrapper(data, timestamp); +} diff --git a/src/kv/value_wrapper_proto.hpp b/src/kv/value_wrapper_proto.hpp index 15802c543fa..5c347880468 100644 --- a/src/kv/value_wrapper_proto.hpp +++ b/src/kv/value_wrapper_proto.hpp @@ -9,114 +9,36 @@ #pragma once -#include +class ValueWrapper; + +using StringType = std::string; +using BooleanType = bool; +using IntType = int; +using DoubleType = double; +using ArrayType = std::vector; +using MapType = phmap::flat_hash_map>; + +using ValueVariant = std::variant; + +// Forward declaration for protobuf class +namespace Canary { + namespace protobuf { + namespace kv { + class ValueWrapper; + } // namespace kv + } // namespace protobuf +} // namespace Canary -#include "kv/value_wrapper.hpp" -#include "protobuf/kv.pb.h" - -template struct ProtoSerializable { - static Canary::protobuf::kv::ValueWrapper toProto(const T &obj); - static T fromProto(const Canary::protobuf::kv::ValueWrapper &protoValue, uint64_t timestamp); -}; - -template <> -struct ProtoSerializable { static Canary::protobuf::kv::ValueWrapper toProto(const ValueWrapper &obj); static ValueWrapper fromProto(const Canary::protobuf::kv::ValueWrapper &protoValue, uint64_t timestamp); }; namespace ProtoHelpers { - void setProtoStringValue(Canary::protobuf::kv::ValueWrapper &protoValue, const StringType &arg) { - protoValue.set_str_value(arg); - } - - void setProtoBooleanValue(Canary::protobuf::kv::ValueWrapper &protoValue, const BooleanType &arg) { - protoValue.set_bool_value(arg); - } - - void setProtoIntValue(Canary::protobuf::kv::ValueWrapper &protoValue, const IntType &arg) { - protoValue.set_int_value(arg); - } - - void setProtoDoubleValue(Canary::protobuf::kv::ValueWrapper &protoValue, const DoubleType &arg) { - protoValue.set_double_value(arg); - } - - void setProtoArrayValue(Canary::protobuf::kv::ValueWrapper &protoValue, const ArrayType &arg) { - auto arrayValue = protoValue.mutable_array_value(); - for (const auto &elem : arg) { - *arrayValue->add_values() = ProtoSerializable::toProto(elem); - } - } - - void setProtoMapValue(Canary::protobuf::kv::ValueWrapper &protoValue, const MapType &arg) { - auto mapValue = protoValue.mutable_map_value(); - for (const auto &[key, value] : arg) { - auto* elem = mapValue->add_items(); - elem->set_key(key); - *elem->mutable_value() = ProtoSerializable::toProto(*value); - } - } -} - -inline Canary::protobuf::kv::ValueWrapper ProtoSerializable::toProto(const ValueWrapper &obj) { - Canary::protobuf::kv::ValueWrapper protoValue; - - std::visit( - [&protoValue](const auto &arg) { - using T = std::decay_t; - if constexpr (std::is_same_v) { - ProtoHelpers::setProtoStringValue(protoValue, arg); - } else if constexpr (std::is_same_v) { - ProtoHelpers::setProtoBooleanValue(protoValue, arg); - } else if constexpr (std::is_same_v) { - ProtoHelpers::setProtoIntValue(protoValue, arg); - } else if constexpr (std::is_same_v) { - ProtoHelpers::setProtoDoubleValue(protoValue, arg); - } else if constexpr (std::is_same_v) { - ProtoHelpers::setProtoArrayValue(protoValue, arg); - } else if constexpr (std::is_same_v) { - ProtoHelpers::setProtoMapValue(protoValue, arg); - } - }, - obj.getVariant() - ); - - return protoValue; -} - -inline ValueWrapper ProtoSerializable::fromProto(const Canary::protobuf::kv::ValueWrapper &protoValue, uint64_t timestamp) { - ValueVariant data; - switch (protoValue.value_case()) { - case Canary::protobuf::kv::ValueWrapper::kStrValue: - data = protoValue.str_value(); - break; - case Canary::protobuf::kv::ValueWrapper::kBoolValue: - data = protoValue.bool_value(); - break; - case Canary::protobuf::kv::ValueWrapper::kIntValue: - data = protoValue.int_value(); - break; - case Canary::protobuf::kv::ValueWrapper::kDoubleValue: - data = protoValue.double_value(); - break; - case Canary::protobuf::kv::ValueWrapper::kArrayValue: { - ArrayType array; - for (const auto &protoElem : protoValue.array_value().values()) { - array.emplace_back(fromProto(protoElem, timestamp)); - } - data = array; - } break; - case Canary::protobuf::kv::ValueWrapper::kMapValue: { - MapType map; - for (const auto &protoElem : protoValue.map_value().items()) { - map[protoElem.key()] = std::make_shared(fromProto(protoElem.value(), timestamp)); - } - data = map; - } break; - default: - break; - } - return ValueWrapper(data, timestamp); + void setProtoStringValue(Canary::protobuf::kv::ValueWrapper &protoValue, const StringType &arg); + void setProtoBooleanValue(Canary::protobuf::kv::ValueWrapper &protoValue, const BooleanType &arg); + void setProtoIntValue(Canary::protobuf::kv::ValueWrapper &protoValue, const IntType &arg); + void setProtoDoubleValue(Canary::protobuf::kv::ValueWrapper &protoValue, const DoubleType &arg); + void setProtoArrayValue(Canary::protobuf::kv::ValueWrapper &protoValue, const ArrayType &arg); + void setProtoMapValue(Canary::protobuf::kv::ValueWrapper &protoValue, const MapType &arg); } diff --git a/src/lib/di/container.hpp b/src/lib/di/container.hpp index c7d7a2655d6..b0c65b049ef 100644 --- a/src/lib/di/container.hpp +++ b/src/lib/di/container.hpp @@ -10,7 +10,6 @@ #include "account/account_repository_db.hpp" #include "lib/di/injector.hpp" -#include "lib/logging/logger.hpp" #include "lib/logging/log_with_spd_log.hpp" #include "kv/kv_sql.hpp" diff --git a/src/lib/logging/log_with_spd_log.cpp b/src/lib/logging/log_with_spd_log.cpp index 9b58317b819..ca56f146915 100644 --- a/src/lib/logging/log_with_spd_log.cpp +++ b/src/lib/logging/log_with_spd_log.cpp @@ -35,6 +35,6 @@ std::string LogWithSpdLog::getLevel() const { return std::string { level.begin(), level.end() }; } -void LogWithSpdLog::log(const std::string lvl, const fmt::basic_string_view msg) const { +void LogWithSpdLog::log(const std::string &lvl, const fmt::basic_string_view msg) const { spdlog::log(spdlog::level::from_str(lvl), msg); } diff --git a/src/lib/logging/log_with_spd_log.hpp b/src/lib/logging/log_with_spd_log.hpp index e69e2c81859..6e2fd075e9d 100644 --- a/src/lib/logging/log_with_spd_log.hpp +++ b/src/lib/logging/log_with_spd_log.hpp @@ -18,9 +18,9 @@ class LogWithSpdLog final : public Logger { static Logger &getInstance(); void setLevel(const std::string &name) override; - [[nodiscard]] std::string getLevel() const override; + std::string getLevel() const override; - void log(std::string lvl, fmt::basic_string_view msg) const override; + void log(const std::string &lvl, fmt::basic_string_view msg) const override; }; constexpr auto g_logger = LogWithSpdLog::getInstance; diff --git a/src/lib/logging/logger.hpp b/src/lib/logging/logger.hpp index 45c99bcf06f..e8474b74858 100644 --- a/src/lib/logging/logger.hpp +++ b/src/lib/logging/logger.hpp @@ -8,6 +8,10 @@ */ #pragma once +#ifndef USE_PRECOMPILED_HEADERS + #include +#endif + #define LOG_LEVEL_TRACE \ std::string { \ "trace" \ @@ -44,7 +48,7 @@ class Logger { virtual void setLevel(const std::string &name) = 0; [[nodiscard]] virtual std::string getLevel() const = 0; - virtual void log(std::string lvl, fmt::basic_string_view msg) const = 0; + virtual void log(const std::string &lvl, fmt::basic_string_view msg) const = 0; template void trace(const fmt::format_string &fmt, Args &&... args) { diff --git a/src/lua/callbacks/creaturecallback.hpp b/src/lua/callbacks/creaturecallback.hpp index 4b017e773d5..f59cef0248e 100644 --- a/src/lua/callbacks/creaturecallback.hpp +++ b/src/lua/callbacks/creaturecallback.hpp @@ -9,7 +9,6 @@ #pragma once -#include "pch.hpp" #include "creatures/creature.hpp" class Creature; diff --git a/src/lua/functions/core/game/global_functions.cpp b/src/lua/functions/core/game/global_functions.cpp index 2bf9549ff97..bd40793f32f 100644 --- a/src/lua/functions/core/game/global_functions.cpp +++ b/src/lua/functions/core/game/global_functions.cpp @@ -18,6 +18,7 @@ #include "lua/scripts/script_environment.hpp" #include "server/network/protocol/protocolstatus.hpp" #include "creatures/players/wheel/player_wheel.hpp" +#include "lua/global/lua_timer_event_descr.hpp" class Creature; int GlobalFunctions::luaDoPlayerAddItem(lua_State* L) { diff --git a/src/lua/functions/core/game/lua_enums.hpp b/src/lua/functions/core/game/lua_enums.hpp index 448e09fb647..654b46059d0 100644 --- a/src/lua/functions/core/game/lua_enums.hpp +++ b/src/lua/functions/core/game/lua_enums.hpp @@ -9,8 +9,6 @@ #pragma once -#include "pch.hpp" - #include "account/account.hpp" #include "declarations.hpp" #include "lua/scripts/luascript.hpp" diff --git a/src/lua/functions/core/game/modal_window_functions.cpp b/src/lua/functions/core/game/modal_window_functions.cpp index ee2cb7bd89f..754d36d43ea 100644 --- a/src/lua/functions/core/game/modal_window_functions.cpp +++ b/src/lua/functions/core/game/modal_window_functions.cpp @@ -11,6 +11,7 @@ #include "creatures/players/player.hpp" #include "lua/functions/core/game/modal_window_functions.hpp" +#include "game/modal_window/modal_window.hpp" // ModalWindow int ModalWindowFunctions::luaModalWindowCreate(lua_State* L) { diff --git a/src/lua/functions/creatures/combat/combat_functions.cpp b/src/lua/functions/creatures/combat/combat_functions.cpp index 3661536aea6..0d55cae9060 100644 --- a/src/lua/functions/creatures/combat/combat_functions.cpp +++ b/src/lua/functions/creatures/combat/combat_functions.cpp @@ -13,6 +13,7 @@ #include "game/game.hpp" #include "lua/functions/creatures/combat/combat_functions.hpp" #include "lua/scripts/lua_environment.hpp" +#include "lua/global/lua_variant.hpp" int CombatFunctions::luaCombatCreate(lua_State* L) { // Combat() diff --git a/src/lua/functions/creatures/combat/variant_functions.cpp b/src/lua/functions/creatures/combat/variant_functions.cpp index 4741e69ed0f..602dbfa1820 100644 --- a/src/lua/functions/creatures/combat/variant_functions.cpp +++ b/src/lua/functions/creatures/combat/variant_functions.cpp @@ -11,6 +11,7 @@ #include "items/cylinder.hpp" #include "lua/functions/creatures/combat/variant_functions.hpp" +#include "lua/global/lua_variant.hpp" int VariantFunctions::luaVariantCreate(lua_State* L) { // Variant(number or string or position or thing) diff --git a/src/lua/functions/lua_functions_loader.cpp b/src/lua/functions/lua_functions_loader.cpp index ae812e2cc88..330ad92b3ee 100644 --- a/src/lua/functions/lua_functions_loader.cpp +++ b/src/lua/functions/lua_functions_loader.cpp @@ -25,6 +25,9 @@ #include "lua/functions/lua_functions_loader.hpp" #include "lua/functions/map/map_functions.hpp" #include "lua/functions/core/game/zone_functions.hpp" +#include "lua/global/lua_variant.hpp" + +#include "enums/lua_variant_type.hpp" class LuaScriptInterface; diff --git a/src/lua/functions/lua_functions_loader.hpp b/src/lua/functions/lua_functions_loader.hpp index 17495cd2e63..0fa201bba50 100644 --- a/src/lua/functions/lua_functions_loader.hpp +++ b/src/lua/functions/lua_functions_loader.hpp @@ -26,6 +26,8 @@ class Guild; class Zone; class KV; +struct LuaVariant; + #define reportErrorFunc(a) reportError(__FUNCTION__, a, true) class LuaFunctionsLoader { diff --git a/src/lua/global/lua_timer_event_descr.hpp b/src/lua/global/lua_timer_event_descr.hpp new file mode 100644 index 00000000000..da9bdc9b402 --- /dev/null +++ b/src/lua/global/lua_timer_event_descr.hpp @@ -0,0 +1,27 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019-2022 OpenTibiaBR + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ + +#pragma once + +#ifndef USE_PRECOMPILED_HEADERS + #include + #include + #include +#endif + +struct LuaTimerEventDesc { + int32_t scriptId = -1; + std::string scriptName; + int32_t function = -1; + std::list parameters; + uint32_t eventId = 0; + + LuaTimerEventDesc() = default; + LuaTimerEventDesc(LuaTimerEventDesc &&other) = default; +}; diff --git a/src/lua/global/lua_variant.hpp b/src/lua/global/lua_variant.hpp new file mode 100644 index 00000000000..13250cc6288 --- /dev/null +++ b/src/lua/global/lua_variant.hpp @@ -0,0 +1,27 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019-2022 OpenTibiaBR + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ + +#pragma once + +#include "enums/lua_variant_type.hpp" +#include "game/movement/position.hpp" + +#ifndef USE_PRECOMPILED_HEADERS + #include + #include +#endif + +struct LuaVariant { + LuaVariantType_t type = VARIANT_NONE; + std::string text; + std::string instantName; + std::string runeName; + Position pos; + uint32_t number = 0; +}; diff --git a/src/lua/lua_definitions.hpp b/src/lua/lua_definitions.hpp index 028c0c32b62..e0ff4028c0b 100644 --- a/src/lua/lua_definitions.hpp +++ b/src/lua/lua_definitions.hpp @@ -115,15 +115,6 @@ enum ModuleType_t { MODULE_TYPE_NONE, }; -enum LuaVariantType_t { - VARIANT_NONE, - - VARIANT_NUMBER, - VARIANT_POSITION, - VARIANT_TARGETPOSITION, - VARIANT_STRING, -}; - enum ErrorCode_t { LUA_ERROR_PLAYER_NOT_FOUND, LUA_ERROR_CREATURE_NOT_FOUND, @@ -214,24 +205,3 @@ enum BugReportType_t : uint8_t { BUG_CATEGORY_TECHNICAL = 2, BUG_CATEGORY_OTHER = 3 }; - -// Struct -struct LuaVariant { - LuaVariantType_t type = VARIANT_NONE; - std::string text; - std::string instantName; - std::string runeName; - Position pos; - uint32_t number = 0; -}; - -struct LuaTimerEventDesc { - int32_t scriptId = -1; - std::string scriptName; - int32_t function = -1; - std::list parameters; - uint32_t eventId = 0; - - LuaTimerEventDesc() = default; - LuaTimerEventDesc(LuaTimerEventDesc &&other) = default; -}; diff --git a/src/lua/scripts/lua_environment.cpp b/src/lua/scripts/lua_environment.cpp index 717ce36ae48..f5552d108a4 100644 --- a/src/lua/scripts/lua_environment.cpp +++ b/src/lua/scripts/lua_environment.cpp @@ -13,6 +13,7 @@ #include "lua/scripts/lua_environment.hpp" #include "lua/functions/lua_functions_loader.hpp" #include "lua/scripts/script_environment.hpp" +#include "lua/global/lua_timer_event_descr.hpp" bool LuaEnvironment::shuttingDown = false; diff --git a/src/lua/scripts/lua_environment.hpp b/src/lua/scripts/lua_environment.hpp index 042a21fe1d8..8a7e7db66af 100644 --- a/src/lua/scripts/lua_environment.hpp +++ b/src/lua/scripts/lua_environment.hpp @@ -14,6 +14,8 @@ #include "lua/scripts/luascript.hpp" #include "items/weapons/weapons.hpp" +#include "lua/global/lua_timer_event_descr.hpp" + class AreaCombat; class Combat; class Cylinder; diff --git a/src/lua/scripts/script_environment.hpp b/src/lua/scripts/script_environment.hpp index 4c219b0a0ef..285e5d77131 100644 --- a/src/lua/scripts/script_environment.hpp +++ b/src/lua/scripts/script_environment.hpp @@ -74,7 +74,6 @@ class ScriptEnvironment { void removeItemByUID(uint32_t uid); private: - using VariantVector = std::vector; using StorageMap = std::map; using DBResultMap = std::map; diff --git a/src/map/mapcache.hpp b/src/map/mapcache.hpp index 6265e979fa4..bc3e59a700a 100644 --- a/src/map/mapcache.hpp +++ b/src/map/mapcache.hpp @@ -14,8 +14,6 @@ class Map; class Tile; -class BasicItem; -class BasicTile; class Item; class Position; class FileStream; @@ -83,7 +81,7 @@ struct BasicTile { struct Floor { explicit Floor(uint8_t z) : - z(z) {}; + z(z) { } std::shared_ptr getTile(uint16_t x, uint16_t y) const { std::shared_lock sl(mutex); diff --git a/src/map/spectators.cpp b/src/map/spectators.cpp index 7eabde6850c..8ae8514bb97 100644 --- a/src/map/spectators.cpp +++ b/src/map/spectators.cpp @@ -7,6 +7,8 @@ * Website: https://docs.opentibiabr.com/ */ +#include "pch.hpp" + #include "spectators.hpp" #include "game/game.hpp" @@ -16,6 +18,52 @@ void Spectators::clearCache() { spectatorsCache.clear(); } +bool Spectators::contains(const std::shared_ptr &creature) { + return creatures.contains(creature); +} + +bool Spectators::erase(const std::shared_ptr &creature) { + return creatures.erase(creature); +} + +Spectators Spectators::insert(const std::shared_ptr &creature) { + if (creature) { + creatures.emplace(creature); + } + return *this; +} + +Spectators Spectators::insertAll(const SpectatorList &list) { + if (!list.empty()) { + creatures.insertAll(list); + } + return *this; +} + +Spectators Spectators::join(Spectators &anotherSpectators) { + return insertAll(anotherSpectators.creatures.data()); +} + +bool Spectators::empty() const noexcept { + return creatures.empty(); +} + +size_t Spectators::size() noexcept { + return creatures.size(); +} + +CreatureVector::iterator Spectators::begin() noexcept { + return creatures.begin(); +} + +CreatureVector::iterator Spectators::end() noexcept { + return creatures.end(); +} + +const CreatureVector &Spectators::data() noexcept { + return creatures.data(); +} + bool Spectators::checkCache(const SpectatorsCache::FloorData &specData, bool onlyPlayers, const Position ¢erPos, bool checkDistance, bool multifloor, int32_t minRangeX, int32_t maxRangeX, int32_t minRangeY, int32_t maxRangeY) { const auto &list = multifloor || !specData.floor ? specData.multiFloor : specData.floor; diff --git a/src/map/spectators.hpp b/src/map/spectators.hpp index 8e73df9ad6f..6b9a0445510 100644 --- a/src/map/spectators.hpp +++ b/src/map/spectators.hpp @@ -9,7 +9,6 @@ #pragma once -#include "pch.hpp" #include "creatures/creature.hpp" class Player; @@ -49,56 +48,16 @@ class Spectators { requires std::is_base_of_v Spectators filter(); - bool contains(const std::shared_ptr &creature) { - return creatures.contains(creature); - } - - bool erase(const std::shared_ptr &creature) { - return creatures.erase(creature); - } - - template - bool erase_if(F fnc) { - return std::erase_if(creatures, std::move(fnc)) > 0; - } - - Spectators insert(const std::shared_ptr &creature) { - if (creature) { - creatures.emplace(creature); - } - return *this; - } - - Spectators insertAll(const SpectatorList &list) { - if (!list.empty()) { - creatures.insertAll(list); - } - return *this; - } - - Spectators join(Spectators &anotherSpectators) { - return insertAll(anotherSpectators.creatures.data()); - } - - bool empty() const noexcept { - return creatures.empty(); - } - - size_t size() noexcept { - return creatures.size(); - } - - auto begin() noexcept { - return creatures.begin(); - } - - auto end() noexcept { - return creatures.end(); - } - - const auto &data() noexcept { - return creatures.data(); - } + bool contains(const std::shared_ptr &creature); + bool erase(const std::shared_ptr &creature); + Spectators insert(const std::shared_ptr &creature); + Spectators insertAll(const SpectatorList &list); + Spectators join(Spectators &anotherSpectators); + bool empty() const noexcept; + size_t size() noexcept; + CreatureVector::iterator begin() noexcept; + CreatureVector::iterator end() noexcept; + const CreatureVector &data() noexcept; private: static phmap::flat_hash_map spectatorsCache; diff --git a/src/map/utils/astarnodes.hpp b/src/map/utils/astarnodes.hpp index 26f33cdfcc4..546d490d858 100644 --- a/src/map/utils/astarnodes.hpp +++ b/src/map/utils/astarnodes.hpp @@ -9,7 +9,7 @@ #pragma once -class Position; +struct Position; class Creature; class Tile; diff --git a/src/map/utils/qtreenode.hpp b/src/map/utils/qtreenode.hpp index d4131ccfe49..83f052a6abf 100644 --- a/src/map/utils/qtreenode.hpp +++ b/src/map/utils/qtreenode.hpp @@ -19,7 +19,7 @@ class QTreeNode { public: constexpr QTreeNode() = default; - virtual ~QTreeNode() {}; + virtual ~QTreeNode() { } // non-copyable QTreeNode(const QTreeNode &) = delete; diff --git a/src/pch.hpp b/src/pch.hpp index ea0233ee1a8..5f15a62613b 100644 --- a/src/pch.hpp +++ b/src/pch.hpp @@ -36,12 +36,15 @@ #include #include #include +#include #include #include #include #include #include #include +#include +#include // -------------------- // System Includes diff --git a/src/protobuf/CMakeLists.txt b/src/protobuf/CMakeLists.txt index 4ca2bac2ce2..ec6bda53de7 100644 --- a/src/protobuf/CMakeLists.txt +++ b/src/protobuf/CMakeLists.txt @@ -4,36 +4,31 @@ project(protobuf) find_package(Protobuf REQUIRED) +find_package(Threads) include_directories(${PROTOBUF_INCLUDE_DIRS}) file(GLOB ProtoFiles - "${CMAKE_CURRENT_SOURCE_DIR}/appearances.proto" - "${CMAKE_CURRENT_SOURCE_DIR}/kv.proto" + "${CMAKE_CURRENT_SOURCE_DIR}/**/*.proto" + "${CMAKE_CURRENT_SOURCE_DIR}/*.proto" ) -PROTOBUF_GENERATE_CPP(ProtoSources ProtoHeaders ${ProtoFiles}) -add_library(${PROJECT_NAME} ${ProtoSources} ${ProtoHeaders}) -target_link_libraries(${PROJECT_NAME} ${PROTOBUF_LIBRARY}) - -add_custom_command( - TARGET ${PROJECT_NAME} POST_BUILD - # Copy files "appearances.pb.cc" to the "src/protobuf" folder - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_BINARY_DIR}/appearances.pb.cc - ${CMAKE_CURRENT_SOURCE_DIR}/appearances.pb.cc - - # Copy files "appearances.pb.h" to the "src/protobuf" folder - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_BINARY_DIR}/appearances.pb.h - ${CMAKE_CURRENT_SOURCE_DIR}/appearances.pb.h - - # Copy files "kv.pb.cc" to the "src/protobuf" folder - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_BINARY_DIR}/kv.pb.cc - ${CMAKE_CURRENT_SOURCE_DIR}/kv.pb.cc - - # Copy files "kv.pb.hpp" to the "src/protobuf" folder - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_BINARY_DIR}/kv.pb.h - ${CMAKE_CURRENT_SOURCE_DIR}/kv.pb.h - ) + +if (MSVC AND BUILD_STATIC_LIBRARY) + add_library(${PROJECT_NAME} STATIC ${ProtoFiles}) +else() + add_library(${PROJECT_NAME} ${ProtoFiles}) +endif() + +target_link_libraries(${PROJECT_NAME} + PUBLIC + protobuf::libprotobuf +) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) + +message("Diretório de construção atual: ${CMAKE_CURRENT_BINARY_DIR}") + +if (MSVC AND BUILD_STATIC_LIBRARY) + set_property(TARGET ${PROJECT_NAME} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") +endif() + +protobuf_generate(TARGET ${PROJECT_NAME} LANGUAGE cpp) diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 9fe6b75b827..daffdcb52d1 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -22,6 +22,7 @@ #include "lua/modules/modules.hpp" #include "creatures/monsters/monster.hpp" #include "creatures/monsters/monsters.hpp" +#include "game/modal_window/modal_window.hpp" #include "server/network/message/outputmessage.hpp" #include "creatures/players/player.hpp" #include "creatures/players/wheel/player_wheel.hpp" @@ -31,6 +32,7 @@ #include "creatures/combat/spells.hpp" #include "creatures/players/management/waitlist.hpp" #include "items/weapons/weapons.hpp" +#include "enums/object_category.hpp" /* * NOTE: This namespace is used so that we can add functions without having to declare them in the ".hpp/.hpp" file @@ -2782,7 +2784,7 @@ void ProtocolGame::refreshCyclopediaMonsterTracker(const std::unordered_setinfo.raceid; const auto stages = g_ioBosstiary().getBossRaceKillStages(mtype->info.bosstiaryRace); if (isBoss && (stages.empty() || stages.size() != 3)) { @@ -3727,7 +3729,7 @@ void ProtocolGame::sendCyclopediaCharacterOutfitsMounts() { uint16_t mountSize = 0; auto startMounts = msg.getBufferPosition(); msg.skipBytes(2); - for (const auto mount : g_game().mounts.getMounts()) { + for (const auto &mount : g_game().mounts.getMounts()) { const std::string type = mount->type; if (player->hasMount(mount)) { ++mountSize; diff --git a/src/server/network/protocol/protocolgame.hpp b/src/server/network/protocol/protocolgame.hpp index d8445a5868a..0906f75e6f4 100644 --- a/src/server/network/protocol/protocolgame.hpp +++ b/src/server/network/protocol/protocolgame.hpp @@ -26,6 +26,9 @@ class ProtocolGame; class PreySlot; class TaskHuntingSlot; class TaskHuntingOption; + +struct ModalWindow; + using ProtocolGame_ptr = std::shared_ptr; struct TextMessage { diff --git a/src/utils/definitions.hpp b/src/utils/definitions.hpp index 71566fe0ee3..a40792d6d85 100644 --- a/src/utils/definitions.hpp +++ b/src/utils/definitions.hpp @@ -30,8 +30,6 @@ #define OS_WINDOWS #endif - #define WIN32_LEAN_AND_MEAN - #ifdef _MSC_VER #ifdef NDEBUG #define _SECURE_SCL 0 diff --git a/src/utils/tools.cpp b/src/utils/tools.cpp index 25d2e8bc478..c7bccf2afae 100644 --- a/src/utils/tools.cpp +++ b/src/utils/tools.cpp @@ -1613,6 +1613,39 @@ std::string getObjectCategoryName(ObjectCategory_t category) { } } +bool isValidObjectCategory(ObjectCategory_t category) { + static std::unordered_set valid = { + OBJECTCATEGORY_NONE, + OBJECTCATEGORY_ARMORS, + OBJECTCATEGORY_NECKLACES, + OBJECTCATEGORY_BOOTS, + OBJECTCATEGORY_CONTAINERS, + OBJECTCATEGORY_DECORATION, + OBJECTCATEGORY_FOOD, + OBJECTCATEGORY_HELMETS, + OBJECTCATEGORY_LEGS, + OBJECTCATEGORY_OTHERS, + OBJECTCATEGORY_POTIONS, + OBJECTCATEGORY_RINGS, + OBJECTCATEGORY_RUNES, + OBJECTCATEGORY_SHIELDS, + OBJECTCATEGORY_TOOLS, + OBJECTCATEGORY_VALUABLES, + OBJECTCATEGORY_AMMO, + OBJECTCATEGORY_AXES, + OBJECTCATEGORY_CLUBS, + OBJECTCATEGORY_DISTANCEWEAPONS, + OBJECTCATEGORY_SWORDS, + OBJECTCATEGORY_WANDS, + OBJECTCATEGORY_PREMIUMSCROLLS, + OBJECTCATEGORY_TIBIACOINS, + OBJECTCATEGORY_CREATUREPRODUCTS, + OBJECTCATEGORY_GOLD, + OBJECTCATEGORY_DEFAULT, + }; + return valid.contains(category); +} + uint8_t forgeBonus(int32_t number) { // None if (number < 7400) { @@ -1777,6 +1810,11 @@ std::string getFormattedTimeRemaining(uint32_t time) { return output.str(); } +unsigned int getNumberOfCores() { + static auto cores = std::thread::hardware_concurrency(); + return cores; +} + /** * @brief Formats a number to a string with commas * @param number The number to format diff --git a/src/utils/tools.hpp b/src/utils/tools.hpp index add8fe59117..86bf7a942e0 100644 --- a/src/utils/tools.hpp +++ b/src/utils/tools.hpp @@ -13,6 +13,15 @@ #include "declarations.hpp" #include "enums/item_attribute.hpp" #include "game/movement/position.hpp" +#include "enums/object_category.hpp" + +namespace pugi { + class xml_parse_result; +} + +#ifndef USE_PRECOMPILED_HEADERS + #include +#endif void printXMLError(const std::string &where, const std::string &fileName, const pugi::xml_parse_result &result); @@ -133,6 +142,7 @@ NameEval_t validateName(const std::string &name); bool isCaskItem(uint16_t itemId); std::string getObjectCategoryName(ObjectCategory_t category); +bool isValidObjectCategory(ObjectCategory_t category); int64_t OTSYS_TIME(); void UPDATE_OTSYS_TIME(); @@ -145,9 +155,7 @@ std::string formatPrice(std::string price, bool space /* = false*/); std::vector split(const std::string &str); std::string getFormattedTimeRemaining(uint32_t time); -static inline unsigned int getNumberOfCores() { - return std::thread::hardware_concurrency(); -} +unsigned int getNumberOfCores(); static inline Cipbia_Elementals_t getCipbiaElement(CombatType_t combatType) { switch (combatType) { diff --git a/src/utils/utils_definitions.hpp b/src/utils/utils_definitions.hpp index 712f3f5f587..2d18849b399 100644 --- a/src/utils/utils_definitions.hpp +++ b/src/utils/utils_definitions.hpp @@ -663,20 +663,6 @@ enum ItemID_t : uint16_t { ITEM_NONE = 0 }; -// A map which contains items that, when on creating, should be transformed to the default type. -const phmap::flat_hash_map ItemTransformationMap = { - { ITEM_SWORD_RING_ACTIVATED, ITEM_SWORD_RING }, - { ITEM_CLUB_RING_ACTIVATED, ITEM_CLUB_RING }, - { ITEM_DWARVEN_RING_ACTIVATED, ITEM_DWARVEN_RING }, - { ITEM_RING_HEALING_ACTIVATED, ITEM_RING_HEALING }, - { ITEM_STEALTH_RING_ACTIVATED, ITEM_STEALTH_RING }, - { ITEM_TIME_RING_ACTIVATED, ITEM_TIME_RING }, - { ITEM_PAIR_SOFT_BOOTS_ACTIVATED, ITEM_PAIR_SOFT_BOOTS }, - { ITEM_DEATH_RING_ACTIVATED, ITEM_DEATH_RING }, - { ITEM_PRISMATIC_RING_ACTIVATED, ITEM_PRISMATIC_RING }, - { ITEM_OLD_DIAMOND_ARROW, ITEM_DIAMOND_ARROW }, -}; - enum class PlayerFlags_t : uint8_t { CannotUseCombat, CannotAttackPlayer, @@ -734,17 +720,6 @@ enum Blessings_t : uint8_t { HEARTH_OF_THE_MOUNTAIN = 8, }; -const phmap::flat_hash_map BlessingNames = { - { TWIST_OF_FATE, "Twist of Fate" }, - { WISDOM_OF_SOLITUDE, "The Wisdom of Solitude" }, - { SPARK_OF_THE_PHOENIX, "The Spark of the Phoenix" }, - { FIRE_OF_THE_SUNS, "The Fire of the Suns" }, - { SPIRITUAL_SHIELDING, "The Spiritual Shielding" }, - { EMBRACE_OF_TIBIA, "The Embrace of Tibia" }, - { BLOOD_OF_THE_MOUNTAIN, "Blood of the Mountain" }, - { HEARTH_OF_THE_MOUNTAIN, "Heart of the Mountain" }, -}; - enum BedItemPart_t : uint8_t { BED_NONE_PART, BED_PILLOW_PART, diff --git a/tests/fixture/lib/logging/in_memory_logger.hpp b/tests/fixture/lib/logging/in_memory_logger.hpp index 0b1f9972888..a6767a446a7 100644 --- a/tests/fixture/lib/logging/in_memory_logger.hpp +++ b/tests/fixture/lib/logging/in_memory_logger.hpp @@ -56,12 +56,12 @@ class InMemoryLogger : public Logger { // But you can implement level filtering if you like. } - [[nodiscard]] std::string getLevel() const override { + std::string getLevel() const override { // For simplicity, let's just return a default level. You can adjust as needed. return "DEBUG"; } - virtual void log(std::string lvl, fmt::basic_string_view msg) const override { + virtual void log(const std::string &lvl, const fmt::basic_string_view msg) const override { logs.push_back({ lvl, { msg.data(), msg.size() } }); } diff --git a/tests/unit/lib/logging/in_memory_logger.hpp b/tests/unit/lib/logging/in_memory_logger.hpp index 0b1f9972888..f97f2ad402b 100644 --- a/tests/unit/lib/logging/in_memory_logger.hpp +++ b/tests/unit/lib/logging/in_memory_logger.hpp @@ -56,12 +56,12 @@ class InMemoryLogger : public Logger { // But you can implement level filtering if you like. } - [[nodiscard]] std::string getLevel() const override { + std::string getLevel() const override { // For simplicity, let's just return a default level. You can adjust as needed. return "DEBUG"; } - virtual void log(std::string lvl, fmt::basic_string_view msg) const override { + virtual void log(const std::string &lvl, fmt::basic_string_view msg) const override { logs.push_back({ lvl, { msg.data(), msg.size() } }); } diff --git a/vcproj/canary.vcxproj b/vcproj/canary.vcxproj index 52ffdb55022..a3f005d3d53 100644 --- a/vcproj/canary.vcxproj +++ b/vcproj/canary.vcxproj @@ -201,8 +201,6 @@ - - @@ -303,6 +301,7 @@ + @@ -387,14 +386,6 @@ - - false - false - - - false - false - @@ -426,6 +417,7 @@ Win32Proj 10.0 $(ProjectDir)../ + $(OutDirFullPath)src @@ -496,8 +488,9 @@ Disabled Speed - $(VcpkgRoot)\installed\$(VcpkgTriplet)\include\; - vcpkg_installed\$(VcpkgTriplet)\include\ + $(GITHUB_WORKSPACE)\vcpkg\installed\$(VcpkgTriplet)\include\; + vcpkg_installed\$(VcpkgTriplet)\include\; + generated Level1 true @@ -514,7 +507,7 @@ Console - $(VcpkgRoot)\installed\$(VcpkgTriplet)\lib\; + $(GITHUB_WORKSPACE)\vcpkg\installed\$(VcpkgTriplet)\lib\; vcpkg_installed\$(VcpkgTriplet)\lib\ UseLinkTimeCodeGeneration @@ -530,8 +523,9 @@ MaxSpeed Speed - $(VcpkgRoot)\installed\$(VcpkgTriplet)\include\; - vcpkg_installed\$(VcpkgTriplet)\include\ + $(GITHUB_WORKSPACE)\vcpkg\installed\$(VcpkgTriplet)\include\; + vcpkg_installed\$(VcpkgTriplet)\include\; + generated Level1 true @@ -547,7 +541,7 @@ Console - $(VcpkgRoot)\installed\$(VcpkgTriplet)\lib\; + $(GITHUB_WORKSPACE)\vcpkg\installed\$(VcpkgTriplet)\lib\; vcpkg_installed\$(VcpkgTriplet)\lib\ UseLinkTimeCodeGeneration @@ -557,7 +551,41 @@ true + + + + + true + + + false + + + + + + $(ProjectDir)vcpkg_installed\$(VcpkgTriplet)\tools\protobuf\protoc + ..\$(SourcePath)\protobuf + + + $(ProjectDir)vcpkg_installed\$(VcpkgTriplet)\tools\protobuf\protoc + $(GITHUB_WORKSPACE)\src\protobuf + + + + + + + + + false + + + false + + + - + \ No newline at end of file