BREAKING CHANGE: Feat(Multistate): Add MultiState
✨ 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
This PR is going to require intensive testing. Thanks for the effort, I'm looking forward to some testers.
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
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.
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:
-
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.
-
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());
}
}
}
-
I had to replace all instances of ReputationGain with ReputationReward in /mod-eluna/src/LuaEngine/methods/CreatureMethods.h
-
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
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)
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 :-/