mirror of
https://github.com/vcmi/vcmi.git
synced 2025-06-21 00:19:29 +02:00
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there. * Declared existing Entity APIs. * Added basic script context caching * Started Lua script module * Started Lua spell effect API * Started script state persistence * Started battle info callback binding * CommitPackage removed * Extracted spells::Caster to own header; Expanded Spell API. * implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C * !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented * Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key) * Re-enabled VERM macros. * !?GM0 added * !?TM implemented * Added !!MF:N * Started !?OB, !!BM, !!HE, !!OW, !!UN * Added basic support of w-variables * Added support for ERM indirect variables * Made !?FU regular trigger * !!re (ERA loop receiver) implemented * Fixed ERM receivers with zero args.
This commit is contained in:
.travis.ymlCCallback.cppCCallback.h
AI
BattleAI
EmptyAI
StupidAI
VCAI
CI
CMakeLists.txtGlobal.hMods/vcmi/Data/s
client
CGameInfo.cppCGameInfo.hCMT.cppCMusicHandler.cppCMusicHandler.hCPlayerInterface.cppCPlayerInterface.hCServerHandler.cppClient.cppClient.hGraphics.cppGraphics.hNetPacksClient.cppVCMI_client.cbp
battle
gui
lobby
widgets
windows
cmake_modules
config
include
vcmi
Artifact.hArtifactService.hCreature.hCreatureService.hEntity.hEntityService.hEnvironment.hFaction.hFactionService.hHeroClass.hHeroClassService.hHeroType.hHeroTypeService.hMetatype.hPlayer.hServerCallback.hServices.hSkill.hSkillService.hTeam.h
events
AdventureEvents.hApplyDamage.hBattleEvents.hEvent.hEventBus.hGameResumed.hGenericEvents.hObjectVisitEnded.hObjectVisitStarted.hPlayerGotTurn.hSubscriptionRegistry.hTurnStarted.h
scripting
spells
vstd
lib
CArtHandler.cppCArtHandler.hCCreatureHandler.cppCCreatureHandler.hCCreatureSet.cppCCreatureSet.hCGameInfoCallback.cppCGameInfoCallback.hCGameInterface.cppCGameInterface.hCGameState.cppCGameState.hCGameStateFwd.hCHeroHandler.cppCHeroHandler.hCMakeLists.txtCModHandler.cppCPathfinder.cppCPlayerState.cppCPlayerState.hCScriptingModule.cppCScriptingModule.hCSkillHandler.cppCSkillHandler.hCStack.cppCStack.hCThreadHelper.hCTownHandler.cppCTownHandler.hGameConstants.cppGameConstants.hHeroBonus.cppHeroBonus.hIGameCallback.cppIGameCallback.hIGameEventsReceiver.hIHandlerBase.hJsonNode.cppNetPacks.hNetPacksBase.hNetPacksLib.cppScriptHandler.cppScriptHandler.hVCMI_Lib.cppVCMI_Lib.hVCMI_lib.cbp
abilities
battle
BattleInfo.cppBattleInfo.hCBattleInfoCallback.cppCBattleInfoCallback.hCBattleInfoEssentials.hCCallbackBase.hCObstacleInstance.cppCPlayerBattleCallback.hCUnitState.cppCUnitState.hIBattleInfoCallback.hIBattleState.hSideInBattle.hUnit.h
events
ApplyDamage.cppApplyDamage.hGameResumed.cppGameResumed.hObjectVisitEnded.cppObjectVisitEnded.hObjectVisitStarted.cppObjectVisitStarted.hPlayerGotTurn.cppPlayerGotTurn.hTurnStarted.cppTurnStarted.h
filesystem
mapObjects
CArmedInstance.cppCBank.cppCGHeroInstance.cppCGHeroInstance.hCGMarket.cppCGPandoraBox.cppCGTownInstance.cppCGTownInstance.hCObjectClassesHandler.cppCObjectClassesHandler.hCObjectHandler.cppCObjectHandler.hCQuest.cppCRewardableObject.cppCommonConstructors.cppJsonRandom.cppMiscObjects.cpp
mapping
registerTypes
rmg
serializer
CSerializer.cppCSerializer.hJsonDeserializer.cppJsonSerializeFormat.cppJsonSerializeFormat.hJsonSerializer.cppJsonTreeSerializer.hJsonUpdater.cppJsonUpdater.h
spells
AbilityCaster.cppAbilityCaster.hAdventureSpellMechanics.cppAdventureSpellMechanics.hBattleSpellMechanics.cppBattleSpellMechanics.hBonusCaster.cppBonusCaster.hCSpellHandler.cppCSpellHandler.hISpellMechanics.cppISpellMechanics.hMagic.hProblem.hProxyCaster.cppProxyCaster.h
effects
vstd
osx
scripting
erm
CMakeLists.txtERM.cbpERMInterpreter.cppERMInterpreter.hERMParser.cppERMParser.hERMScriptModule.cppERMScriptModule.h
lua
CMakeLists.txtLua.cbpLuaCallWrapper.hLuaFunctor.hLuaReference.cppLuaReference.hLuaScriptModule.cppLuaScriptModule.hLuaScriptingContext.cppLuaScriptingContext.hLuaSpellEffect.cppLuaSpellEffect.hLuaStack.cppLuaStack.hLuaWrapper.hStdInc.cppStdInc.h
api
Artifact.cppArtifact.hBattleCb.cppBattleCb.hBonusSystem.cppBonusSystem.hCreature.cppCreature.hFaction.cppFaction.hGameCb.cppGameCb.hHeroClass.cppHeroClass.hHeroInstance.cppHeroInstance.hHeroType.cppHeroType.hObjectInstance.cppObjectInstance.hPlayer.cppPlayer.hRegistry.cppRegistry.hServerCb.cppServerCb.hServices.cppServices.hSkill.cppSkill.hSpell.cppSpell.hStackInstance.cppStackInstance.h
battle
events
AdventureEvents.cppAdventureEvents.hBattleEvents.cppBattleEvents.hEventBusProxy.cppEventBusProxy.hGenericEvents.cppGenericEvents.hSubscriptionRegistryProxy.cppSubscriptionRegistryProxy.h
netpacks
scripts/lib
Metatype.luaerm.lua
erm
BM.luaBU.luaDO.luaFU.luaFU_T.luaGM_T.luaHE.luaIF.luaMA.luaMF.luaMF_T.luaOW.luaPI_T.luaReceiverBase.luaTM.luaTM_T.luaTriggerBase.luaUN.luaVR.lua
verm.luaserver
test
CMakeLists.txtCVcmiTestConfig.cppJsonComparer.cppTest.cbp
vcmi.workspacebattle
entity
erm
ERMPersistenceTest.cppERM_BM.cppERM_BU.cppERM_FU.cppERM_GM_T.cppERM_MA.cppERM_MC.cppERM_MF.cppERM_OB_T.cppERM_TM_T.cppERM_UN.cppERM_VR.cppExamplesTest.cpp
events
game
mock
BattleFake.cppBattleFake.hmock_Creature.hmock_CreatureService.hmock_Environment.hmock_IBattleInfoCallback.hmock_IGameCallback.cppmock_IGameCallback.hmock_IGameEventCallback.hmock_IGameInfoCallback.hmock_ServerCallback.hmock_Services.hmock_battle_IBattleState.hmock_battle_Unit.hmock_events_ApplyDamage.hmock_scripting_Context.hmock_scripting_Pool.hmock_scripting_Script.hmock_scripting_Service.hmock_spells_Mechanics.hmock_spells_Problem.hmock_spells_Spell.hmock_spells_SpellService.hmock_spells_effects_Registry.hmock_vstd_CLoggerBase.h
netpacks
scripting
LuaSandboxTest.cppLuaSpellEffectAPITest.cppLuaSpellEffectTest.cppPoolTest.cppScriptFixture.cppScriptFixture.h
serializer
spells
CSpellTest.cpp
effects
testdata
erm
DO1.jsonDO1.vermDO2.jsonDO2.vermheroVar.jsonheroVar.vermindirectVar.jsonindirectVar.vermlist-manipulation.jsonlist-manipulation.vermre1.jsonre1.vermstd.jsonstd.vermtesty.jsontesty.verm
lua
vcai
607
scripting/lua/LuaScriptingContext.cpp
Normal file
607
scripting/lua/LuaScriptingContext.cpp
Normal file
@ -0,0 +1,607 @@
|
||||
/*
|
||||
* LuaScriptingContext.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
|
||||
#include "LuaScriptingContext.h"
|
||||
|
||||
#include <vstd/StringUtils.h>
|
||||
#include <vcmi/events/EventBus.h>
|
||||
#include <vcmi/ServerCallback.h>
|
||||
|
||||
#include "LuaStack.h"
|
||||
|
||||
#include "api/Registry.h"
|
||||
|
||||
#include "../../lib/JsonNode.h"
|
||||
#include "../../lib/NetPacks.h"
|
||||
#include "../../lib/filesystem/Filesystem.h"
|
||||
#include "../../lib/battle/IBattleInfoCallback.h"
|
||||
#include "../../lib/CGameInfoCallback.h"
|
||||
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
|
||||
const std::string LuaContext::STATE_FIELD = "DATA";
|
||||
|
||||
LuaContext::LuaContext(const Script * source, const Environment * env_)
|
||||
: ContextBase(env_->logger()),
|
||||
script(source),
|
||||
env(env_)
|
||||
{
|
||||
L = luaL_newstate();
|
||||
|
||||
static const std::vector<luaL_Reg> STD_LIBS =
|
||||
{
|
||||
{"", luaopen_base},
|
||||
{LUA_TABLIBNAME, luaopen_table},
|
||||
{LUA_STRLIBNAME, luaopen_string},
|
||||
{LUA_MATHLIBNAME, luaopen_math},
|
||||
{LUA_BITLIBNAME, luaopen_bit}
|
||||
};
|
||||
|
||||
for(const luaL_Reg & lib : STD_LIBS)
|
||||
{
|
||||
lua_pushcfunction(L, lib.func);
|
||||
lua_pushstring(L, lib.name);
|
||||
lua_call(L, 1, 0);
|
||||
}
|
||||
|
||||
popAll();
|
||||
|
||||
cleanupGlobals();
|
||||
|
||||
popAll();
|
||||
|
||||
lua_newtable(L);
|
||||
modules = std::make_shared<LuaReference>(L);
|
||||
popAll();
|
||||
|
||||
registerCore();
|
||||
|
||||
popAll();
|
||||
|
||||
LuaStack S(L);
|
||||
|
||||
S.push(env->game());
|
||||
lua_setglobal(L, "GAME");
|
||||
|
||||
S.push(env->battle());
|
||||
lua_setglobal(L, "BATTLE");
|
||||
|
||||
S.push(env->eventBus());
|
||||
lua_setglobal(L, "EVENT_BUS");
|
||||
|
||||
S.push(env->services());
|
||||
lua_setglobal(L, "SERVICES");
|
||||
|
||||
popAll();
|
||||
}
|
||||
|
||||
LuaContext::~LuaContext()
|
||||
{
|
||||
modules.reset();
|
||||
scriptClosure.reset();
|
||||
lua_close(L);
|
||||
}
|
||||
|
||||
void LuaContext::cleanupGlobals()
|
||||
{
|
||||
LuaStack S(L);
|
||||
S.clear();
|
||||
S.pushNil();
|
||||
lua_setglobal(L, "collectgarbage");
|
||||
|
||||
S.pushNil();
|
||||
lua_setglobal(L, "dofile");
|
||||
|
||||
S.pushNil();
|
||||
lua_setglobal(L, "load");
|
||||
|
||||
S.pushNil();
|
||||
lua_setglobal(L, "loadfile");
|
||||
|
||||
S.pushNil();
|
||||
lua_setglobal(L, "loadstring");
|
||||
|
||||
S.pushNil();
|
||||
lua_setglobal(L, "print");
|
||||
|
||||
S.clear();
|
||||
|
||||
lua_getglobal(L, LUA_STRLIBNAME);
|
||||
|
||||
S.push("dump");
|
||||
S.pushNil();
|
||||
lua_rawset(L, -3);
|
||||
S.clear();
|
||||
|
||||
lua_getglobal(L, LUA_MATHLIBNAME);
|
||||
|
||||
S.push("random");
|
||||
S.pushNil();
|
||||
lua_rawset(L, -3);
|
||||
|
||||
|
||||
S.push("randomseed");
|
||||
S.pushNil();
|
||||
lua_rawset(L, -3);
|
||||
S.clear();
|
||||
}
|
||||
|
||||
void LuaContext::run(ServerCallback * server, const JsonNode & initialState)
|
||||
{
|
||||
{
|
||||
LuaStack S(L);
|
||||
S.push(server);
|
||||
lua_setglobal(L, "SERVER");
|
||||
S.clear();
|
||||
}
|
||||
|
||||
run(initialState);
|
||||
|
||||
// {
|
||||
// LuaStack S(L);
|
||||
// S.pushNil();
|
||||
// lua_setglobal(L, "SERVER");
|
||||
// S.clear();
|
||||
// }
|
||||
}
|
||||
|
||||
void LuaContext::run(const JsonNode & initialState)
|
||||
{
|
||||
setGlobal(STATE_FIELD, initialState);
|
||||
|
||||
int ret = luaL_loadbuffer(L, script->getSource().c_str(), script->getSource().size(), script->getName().c_str());
|
||||
|
||||
if(ret)
|
||||
{
|
||||
logger->error("Script '%s' failed to load, error: %s", script->getName(), toStringRaw(-1));
|
||||
popAll();
|
||||
return;
|
||||
}
|
||||
|
||||
scriptClosure = std::make_shared<LuaReference>(L);
|
||||
popAll();
|
||||
scriptClosure->push();
|
||||
|
||||
ret = lua_pcall(L, 0, 0, 0);
|
||||
|
||||
if(ret)
|
||||
{
|
||||
logger->error("Script '%s' failed to run, error: '%s'", script->getName(), toStringRaw(-1));
|
||||
popAll();
|
||||
}
|
||||
}
|
||||
|
||||
int LuaContext::errorRetVoid(const std::string & message)
|
||||
{
|
||||
logger->error(message);
|
||||
popAll();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JsonNode LuaContext::callGlobal(const std::string & name, const JsonNode & parameters)
|
||||
{
|
||||
LuaStack S(L);
|
||||
|
||||
lua_getglobal(L, name.c_str());
|
||||
|
||||
if(!S.isFunction(-1))
|
||||
{
|
||||
boost::format fmt("%s is not a function");
|
||||
fmt % name;
|
||||
|
||||
logger->error(fmt.str());
|
||||
|
||||
S.clear();
|
||||
|
||||
return JsonNode();
|
||||
}
|
||||
|
||||
int argc = parameters.Vector().size();
|
||||
|
||||
for(int idx = 0; idx < argc; idx++)
|
||||
S.push(parameters.Vector()[idx]);
|
||||
|
||||
if(lua_pcall(L, argc, 1, 0))
|
||||
{
|
||||
std::string error = lua_tostring(L, -1);
|
||||
|
||||
boost::format fmt("Lua function %s failed with message: %s");
|
||||
fmt % name % error;
|
||||
|
||||
logger->error(fmt.str());
|
||||
|
||||
S.clear();
|
||||
|
||||
return JsonNode();
|
||||
}
|
||||
|
||||
JsonNode ret;
|
||||
|
||||
pop(ret);
|
||||
S.balance();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
JsonNode LuaContext::callGlobal(ServerCallback * cb, const std::string & name, const JsonNode & parameters)
|
||||
{
|
||||
LuaStack S(L);
|
||||
S.push(cb);
|
||||
lua_setglobal(L, "SERVER");
|
||||
|
||||
auto ret = callGlobal(name, parameters);
|
||||
|
||||
S.pushNil();
|
||||
lua_setglobal(L, "SERVER");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LuaContext::getGlobal(const std::string & name, int & value)
|
||||
{
|
||||
LuaStack S(L);
|
||||
|
||||
lua_getglobal(L, name.c_str());
|
||||
|
||||
lua_Integer temp;
|
||||
if(S.tryGetInteger(-1, temp))
|
||||
value = static_cast<int>(temp);
|
||||
else
|
||||
value = 0;
|
||||
S.balance();
|
||||
}
|
||||
|
||||
void LuaContext::getGlobal(const std::string & name, std::string & value)
|
||||
{
|
||||
LuaStack S(L);
|
||||
|
||||
lua_getglobal(L, name.c_str());
|
||||
|
||||
if(!S.tryGet(-1, value))
|
||||
value.clear();
|
||||
|
||||
S.balance();
|
||||
}
|
||||
|
||||
void LuaContext::getGlobal(const std::string & name, double & value)
|
||||
{
|
||||
LuaStack S(L);
|
||||
|
||||
lua_getglobal(L, name.c_str());
|
||||
|
||||
if(!S.tryGet(-1, value))
|
||||
value = 0.0;
|
||||
|
||||
S.balance();
|
||||
}
|
||||
|
||||
void LuaContext::getGlobal(const std::string & name, JsonNode & value)
|
||||
{
|
||||
LuaStack S(L);
|
||||
|
||||
lua_getglobal(L, name.c_str());
|
||||
|
||||
pop(value);
|
||||
|
||||
S.balance();
|
||||
}
|
||||
|
||||
void LuaContext::setGlobal(const std::string & name, int value)
|
||||
{
|
||||
lua_pushinteger(L, static_cast<lua_Integer>(value));
|
||||
lua_setglobal(L, name.c_str());
|
||||
}
|
||||
|
||||
void LuaContext::setGlobal(const std::string & name, const std::string & value)
|
||||
{
|
||||
lua_pushlstring(L, value.c_str(), value.size());
|
||||
lua_setglobal(L, name.c_str());
|
||||
}
|
||||
|
||||
void LuaContext::setGlobal(const std::string & name, double value)
|
||||
{
|
||||
lua_pushnumber(L, value);
|
||||
lua_setglobal(L, name.c_str());
|
||||
}
|
||||
|
||||
void LuaContext::setGlobal(const std::string & name, const JsonNode & value)
|
||||
{
|
||||
LuaStack S(L);
|
||||
S.push(value);
|
||||
lua_setglobal(L, name.c_str());
|
||||
S.balance();
|
||||
}
|
||||
|
||||
JsonNode LuaContext::saveState()
|
||||
{
|
||||
JsonNode data;
|
||||
getGlobal(STATE_FIELD, data);
|
||||
return std::move(data);
|
||||
}
|
||||
|
||||
void LuaContext::pop(JsonNode & value)
|
||||
{
|
||||
auto type = lua_type(L, -1);
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case LUA_TNUMBER:
|
||||
value.Float() = lua_tonumber(L, -1);
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
value.Bool() = (lua_toboolean(L, -1) != 0);
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
value.String() = toStringRaw(-1);
|
||||
break;
|
||||
case LUA_TTABLE:
|
||||
{
|
||||
JsonNode asVector(JsonNode::JsonType::DATA_VECTOR);
|
||||
JsonNode asStruct(JsonNode::JsonType::DATA_STRUCT);
|
||||
|
||||
lua_pushnil(L); /* first key */
|
||||
|
||||
while(lua_next(L, -2) != 0)
|
||||
{
|
||||
/* 'key' (at index -2) and 'value' (at index -1) */
|
||||
|
||||
JsonNode fieldValue;
|
||||
pop(fieldValue);
|
||||
|
||||
if(lua_type(L, -1) == LUA_TNUMBER)
|
||||
{
|
||||
auto key = lua_tointeger(L, -1);
|
||||
|
||||
if(key > 0)
|
||||
{
|
||||
if(asVector.Vector().size() < key)
|
||||
asVector.Vector().resize(key);
|
||||
--key;
|
||||
asVector.Vector().at(key) = fieldValue;
|
||||
}
|
||||
}
|
||||
else if(lua_isstring(L, -1))
|
||||
{
|
||||
auto key = toStringRaw(-1);
|
||||
asStruct[key] = fieldValue;
|
||||
}
|
||||
}
|
||||
|
||||
if(!asVector.Vector().empty())
|
||||
{
|
||||
std::swap(value, asVector);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::swap(value, asStruct);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
value.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
void LuaContext::push(const std::string & value)
|
||||
{
|
||||
lua_pushlstring(L, value.c_str(), value.size());
|
||||
}
|
||||
|
||||
void LuaContext::push(lua_CFunction f, void * opaque)
|
||||
{
|
||||
lua_pushlightuserdata(L, opaque);
|
||||
lua_pushcclosure(L, f, 1);
|
||||
}
|
||||
|
||||
void LuaContext::popAll()
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
}
|
||||
|
||||
std::string LuaContext::toStringRaw(int index)
|
||||
{
|
||||
size_t len = 0;
|
||||
auto raw = lua_tolstring(L, index, &len);
|
||||
return std::string(raw, len);
|
||||
}
|
||||
|
||||
void LuaContext::registerCore()
|
||||
{
|
||||
push(&LuaContext::require, this);
|
||||
lua_setglobal(L, "require");
|
||||
|
||||
push(&LuaContext::logError, this);
|
||||
lua_setglobal(L, "logError");
|
||||
|
||||
popAll();//just in case
|
||||
|
||||
for(auto & registar : api::Registry::get()->getCoreData())
|
||||
{
|
||||
registar.second->pushMetatable(L); //table
|
||||
|
||||
modules->push(); //table modules
|
||||
push(registar.first); //table modules name
|
||||
lua_pushvalue(L, -3); //table modules name table
|
||||
lua_rawset(L, -3);
|
||||
|
||||
popAll();
|
||||
}
|
||||
}
|
||||
|
||||
int LuaContext::require(lua_State * L)
|
||||
{
|
||||
LuaContext * self = static_cast<LuaContext *>(lua_touserdata(L, lua_upvalueindex(1)));
|
||||
|
||||
if(!self)
|
||||
{
|
||||
lua_pushstring(L, "internal error");
|
||||
lua_error(L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return self->loadModule();
|
||||
}
|
||||
|
||||
int LuaContext::loadModule()
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if(argc < 1)
|
||||
return errorRetVoid("Module name required");
|
||||
|
||||
//if module is loaded already, assume that module name is valid
|
||||
modules->push();
|
||||
lua_pushvalue(L, -2);
|
||||
lua_rawget(L, -2);
|
||||
|
||||
if(lua_istable(L, -1))
|
||||
{
|
||||
lua_replace(L, 1);
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//continue with more checks
|
||||
if(!lua_isstring(L, 1))
|
||||
return errorRetVoid("Module name must be string");
|
||||
|
||||
std::string resourceName = toStringRaw(1);
|
||||
|
||||
if(resourceName.empty())
|
||||
return errorRetVoid("Module name is empty");
|
||||
|
||||
auto temp = vstd::split(resourceName, ":");
|
||||
|
||||
std::string scope;
|
||||
std::string modulePath;
|
||||
|
||||
if(temp.size() <= 1)
|
||||
{
|
||||
modulePath = temp.at(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
scope = temp.at(0);
|
||||
modulePath = temp.at(1);
|
||||
}
|
||||
|
||||
if(scope.empty())
|
||||
{
|
||||
auto registar = api::Registry::get()->find(modulePath);
|
||||
|
||||
if(!registar)
|
||||
{
|
||||
return errorRetVoid("Module not found: "+modulePath);
|
||||
}
|
||||
|
||||
registar->pushMetatable(L);
|
||||
}
|
||||
else if(scope == "core")
|
||||
{
|
||||
|
||||
// boost::algorithm::replace_all(modulePath, boost::is_any_of("\\/ "), "");
|
||||
|
||||
boost::algorithm::replace_all(modulePath, ".", "/");
|
||||
|
||||
auto loader = CResourceHandler::get("core");
|
||||
|
||||
modulePath = "scripts/lib/" + modulePath;
|
||||
|
||||
ResourceID id(modulePath, EResType::LUA);
|
||||
|
||||
if(!loader->existsResource(id))
|
||||
return errorRetVoid("Module not found: "+modulePath);
|
||||
|
||||
auto rawData = loader->load(id)->readAll();
|
||||
|
||||
auto sourceText = std::string((char *)rawData.first.get(), rawData.second);
|
||||
|
||||
int ret = luaL_loadbuffer(L, sourceText.c_str(), sourceText.size(), modulePath.c_str());
|
||||
|
||||
if(ret)
|
||||
return errorRetVoid(toStringRaw(-1));
|
||||
|
||||
ret = lua_pcall(L, 0, 1, 0);
|
||||
|
||||
if(ret)
|
||||
{
|
||||
logger->error("Module '%s' failed to run, error: %s", modulePath, toStringRaw(-1));
|
||||
popAll();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//todo: also allow loading scripts from same scope
|
||||
return errorRetVoid("No access to scope "+scope);
|
||||
}
|
||||
|
||||
modules->push(); //name table modules
|
||||
lua_pushvalue(L, 1);//name table modules name
|
||||
|
||||
if(!lua_isstring(L, -1))
|
||||
return errorRetVoid("Module name corrupted");
|
||||
|
||||
lua_pushvalue(L, -3);//name table modules name table
|
||||
lua_rawset(L, -3);//name table modules
|
||||
lua_pop(L, 1);//name table
|
||||
|
||||
lua_replace(L, 1);//table table
|
||||
lua_settop(L, 1);//table
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaContext::print(lua_State * L)
|
||||
{
|
||||
//TODO:
|
||||
lua_settop(L, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaContext::printImpl()
|
||||
{
|
||||
//TODO:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaContext::logError(lua_State * L)
|
||||
{
|
||||
LuaContext * self = static_cast<LuaContext *>(lua_touserdata(L, lua_upvalueindex(1)));
|
||||
|
||||
if(!self)
|
||||
{
|
||||
lua_pushstring(L, "internal error");
|
||||
lua_error(L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return self->logErrorImpl();
|
||||
}
|
||||
|
||||
int LuaContext::logErrorImpl()
|
||||
{
|
||||
LuaStack S(L);
|
||||
|
||||
std::string message;
|
||||
|
||||
if(S.tryGet(1, message))
|
||||
logger->error(message);
|
||||
|
||||
return S.retVoid();
|
||||
}
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user