Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BREAKING CHANGE: Feat(Multistate): Add MultiState #249

Open
wants to merge 24 commits into
base: master
Choose a base branch
from

Conversation

iThorgrim
Copy link

@iThorgrim iThorgrim commented Jan 29, 2025

✨ 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:

Desktop.2025-01-30.18-55-01.mp4

@TheSCREWEDSoftware TheSCREWEDSoftware added the BREAKING CHANGE Changes that require intervention after updating. label Jan 31, 2025
@TheSCREWEDSoftware TheSCREWEDSoftware changed the title Feat(Multistate): Add MultiState BREAKING CHANGE: Feat(Multistate): Add MultiState Feb 1, 2025
@55Honey
Copy link
Member

55Honey commented Feb 1, 2025

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

@zbhcn
Copy link

zbhcn commented Feb 2, 2025

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

@iThorgrim
Copy link
Author

iThorgrim commented Feb 2, 2025

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.

@YggdrasilWotLK
Copy link

YggdrasilWotLK commented Feb 3, 2025

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
Copy link

YggdrasilWotLK commented Feb 3, 2025

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)

@iThorgrim
Copy link
Author

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 :-/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
BREAKING CHANGE Changes that require intervention after updating.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants