mod-eluna icon indicating copy to clipboard operation
mod-eluna copied to clipboard

BREAKING CHANGE: Feat(Multistate): Add MultiState

Open iThorgrim opened this issue 11 months ago • 6 comments

✨ MultiState Support for mod-eluna

📝 Description

This pull request introduces MultiState support in mod-eluna, allowing each map in AzerothCore to have its own independent Lua state.

[!NOTE] Implementation based on this PR.

[!WARNING] Require this PR.

⚡ Features

  • Each map now has its own Lua state, created automatically.
  • Scripts can behave differently per map without requiring additional logic.
  • New API methods to retrieve and manage state information.
  • Ensures compatibility with the existing Eluna ecosystem.

📊 New API Methods

1. GetStateMapId()

Retrieves the map ID associated with the current Lua state.

Example:

if (GetStateMapId() == 530) then
    local function OnPlayerLogin(event, player)
        player:SendNotification("Hello AzerothCore !")
    end
    RegisterPlayerEvent(3, OnPlayerLogin)
else
    local function OnPlayerLogin(event, player)
        player:SendNotification("It's MultiState !")
    end
    RegisterPlayerEvent(3, OnPlayerLogin)
end

In this example, players logging into map 530 will receive a different notification than players on other maps.

2. GetStateByMap(mapId)

Fetches the Lua state for a given map.

Example:

local state = GetStateByMap(530)
if state then
    print("Lua state exists for map 530!")
end

🔧 Implementation Details

  • A new state is created automatically for each map when it loads.
  • Scripts are executed within their respective map's state.
  • Keeps global Eluna compatibility, ensuring existing scripts function as expected.

💡 Why MultiState?

  • Better script isolation: Different maps can have unique logic without conflicts.
  • Performance improvements: Reduces unnecessary execution of scripts across all maps.
  • Modular scripting: Developers can design scripts per zone rather than globally.

🎨 Testing

if (GetStateMapId() == 530) then
    local function OnPlayerLogin(event, player)
        player:SendNotification("Hello AzerothCore !")
    end
    RegisterPlayerEvent(3, OnPlayerLogin)
else
    local function OnPlayerLogin(event, player)
        player:SendNotification("It's MultiState !")
    end
    RegisterPlayerEvent(3, OnPlayerLogin)
end

Results:

https://github.com/user-attachments/assets/828f1313-718a-4018-9117-70a97701b418

iThorgrim avatar Jan 29 '25 23:01 iThorgrim

This PR is going to require intensive testing. Thanks for the effort, I'm looking forward to some testers.

55Honey avatar Feb 01 '25 11:02 55Honey

Compilation failed. The log is:错误 MSB3073 命令“setlocal "C:\Program Files\CMake\bin\cmake.exe" -E make_directory D:/az0202/build/bin/RelWithDebInfo/configs/modules if %errorlevel% neq 0 goto :cmEnd :cmEnd endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone :cmErrorLevel exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd setlocal "C:\Program Files\CMake\bin\cmake.exe" -E copy D:/az0202/modules/mod-1v1-arena/conf/1v1arena.conf.dist D:/az0202/build/bin/RelWithDebInfo/configs/modules if %errorlevel% neq 0 goto :cmEnd :cmEnd endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone :cmErrorLevel exit /b %1 :cmDone

zbhcn avatar Feb 02 '25 07:02 zbhcn

Compilation failed. The log is:错误 MSB3073 命令“setlocal "C:\Program Files\CMake\bin\cmake.exe" -E make_directory D:/az0202/build/bin/RelWithDebInfo/configs/modules if %errorlevel% neq 0 goto :cmEnd :cmEnd endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone :cmErrorLevel exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd setlocal "C:\Program Files\CMake\bin\cmake.exe" -E copy D:/az0202/modules/mod-1v1-arena/conf/1v1arena.conf.dist D:/az0202/build/bin/RelWithDebInfo/configs/modules if %errorlevel% neq 0 goto :cmEnd :cmEnd endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone :cmErrorLevel exit /b %1 :cmDone

Your screen gives no indication of a possible error, there's nothing to help you understand the error or to help you, there's no usable information.

iThorgrim avatar Feb 02 '25 12:02 iThorgrim

I just tried giving this a compile by pulling https://github.com/iThorgrim/azerothcore-wotlk/tree/ElunaMultiState and https://github.com/iThorgrim/mod-eluna/tree/MultiStates but had to iron out a few kinks to get it functional:

  1. Initially, it threw errors on missing liblua52.a in dir /mod-eluna/src/lualib/lua/. I snagged up a copy of this file from another project (https://github.com/AltimorTASDK/csgo_weapon_overhaul/blob/master/lua/liblua52.a) after which the compile proceeded.

  2. std::istringstream in /mod-eluna/src/LuaEngine/ElunaConfig.cpp's void ElunaConfig::TokenizeAllowedMaps() threw errors from not being defined, so I replaced with std::string handling. My adjusted void is

void ElunaConfig::TokenizeAllowedMaps()
{
   m_allowedMaps.clear();
   std::string mapString = GetConfig(CONFIG_ELUNA_ONLY_ON_MAPS);
   size_t pos = 0;
   std::string token;

   while ((pos = mapString.find(',')) != std::string::npos) {
       token = mapString.substr(0, pos);
       token.erase(std::remove_if(token.begin(), token.end(), [](char c) {
           return std::isspace(static_cast<unsigned char>(c));
       }), token.end());
       
       if (!token.empty()) {
           try {
               m_allowedMaps.emplace(std::stoul(token));
           }
           catch (std::exception&) {
               ELUNA_LOG_ERROR("[Eluna]: Error tokenizing Eluna.OnlyOnMaps, invalid config value '{}'", token.c_str());
           }
       }
       mapString.erase(0, pos + 1);
   }

   if (!mapString.empty()) {
       mapString.erase(std::remove_if(mapString.begin(), mapString.end(), [](char c) {
           return std::isspace(static_cast<unsigned char>(c));
       }), mapString.end());
       
       try {
           m_allowedMaps.emplace(std::stoul(mapString));
       }
       catch (std::exception&) {
           ELUNA_LOG_ERROR("[Eluna]: Error tokenizing Eluna.OnlyOnMaps, invalid config value '{}'", mapString.c_str());
       }
   }
}
  1. I had to replace all instances of ReputationGain with ReputationReward in /mod-eluna/src/LuaEngine/methods/CreatureMethods.h

  2. I had to replace line 989 of CreatureMethods.h (https://github.com/iThorgrim/mod-eluna/blob/cb9ad5fcb557aacd10d582388409aca2f9ac1f04/src/LuaEngine/methods/CreatureMethods.h#L989) " creature->SetDisableReputationReward(disable); " with " creature->SetReputationRewardDisabled(disable); " cf https://github.com/iThorgrim/azerothcore-wotlk/blob/713bab16ba0a02845bdaef6f008948480ec990aa/src/server/game/Entities/Creature/Creature.h#L362

YggdrasilWotLK avatar Feb 03 '25 01:02 YggdrasilWotLK

Update: I'm stuck on booting with the following issue now, any clue what might cause this? Wiping the game event tables and starting afresh doesn't seem to resolve it. Will take me some time to get to look into it and onto testing multithreaded mod-eluna, so if you guys have any pointers or clues, they're much appreciated!


2025-02-03T05:27:56.388590202Z
2025-02-03T05:27:56.388592642Z Loading WorldState...
2025-02-03T05:27:56.389355600Z GameEventMgr::GameEventSpawn attempt access to out of range mGameEventCreatureGuids element 191 (size: 181)
2025-02-03T05:27:56.389400479Z GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventCreatureGuids element -11 (size: 181)

YggdrasilWotLK avatar Feb 03 '25 05:02 YggdrasilWotLK

Update: I'm stuck on booting with the following issue now, any clue what might cause this? Wiping the game event tables and starting afresh doesn't seem to resolve it. Will take me some time to get to look into it and onto testing multithreaded mod-eluna, so if you guys have any pointers or clues, they're much appreciated!


2025-02-03T05:27:56.388590202Z
2025-02-03T05:27:56.388592642Z Loading WorldState...
2025-02-03T05:27:56.389355600Z GameEventMgr::GameEventSpawn attempt access to out of range mGameEventCreatureGuids element 191 (size: 181)
2025-02-03T05:27:56.389400479Z GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventCreatureGuids element -11 (size: 181)

I see you have this error's:

2025-02-03T05:27:56.389355600Z GameEventMgr::GameEventSpawn attempt access to out of range mGameEventCreatureGuids element 191 (size: 181) 2025-02-03T05:27:56.389400479Z GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventCreatureGuids element -11 (size: 181)

Except that I haven't made any changes that involve GameEvent in any way :-/

iThorgrim avatar Feb 03 '25 20:02 iThorgrim