1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00
This commit is contained in:
AlexVinS 2021-02-15 17:16:41 +03:00
parent a59e12ca5f
commit ec6f7b88fe
10 changed files with 147 additions and 19 deletions

View File

@ -182,6 +182,7 @@
<Unit filename="../scripts/lib/erm/MA.lua" /> <Unit filename="../scripts/lib/erm/MA.lua" />
<Unit filename="../scripts/lib/erm/MF.lua" /> <Unit filename="../scripts/lib/erm/MF.lua" />
<Unit filename="../scripts/lib/erm/MF_T.lua" /> <Unit filename="../scripts/lib/erm/MF_T.lua" />
<Unit filename="../scripts/lib/erm/OB_T.lua" />
<Unit filename="../scripts/lib/erm/OW.lua" /> <Unit filename="../scripts/lib/erm/OW.lua" />
<Unit filename="../scripts/lib/erm/PI_T.lua" /> <Unit filename="../scripts/lib/erm/PI_T.lua" />
<Unit filename="../scripts/lib/erm/ReceiverBase.lua" /> <Unit filename="../scripts/lib/erm/ReceiverBase.lua" />

View File

@ -211,16 +211,38 @@ public:
bool tryGet(int position, double & value); bool tryGet(int position, double & value);
bool tryGet(int position, std::string & value); bool tryGet(int position, std::string & value);
template<typename T, typename std::enable_if<detail::IsRegularClass<T>::value, int>::type = 0> template<typename T, typename std::enable_if<detail::IsRegularClass<T>::value && std::is_const<T>::value, int>::type = 0>
bool tryGet(int position, T * & value) STRONG_INLINE bool tryGet(int position, T * & value)
{ {
return tryGetUData(position, value); using NCValue = typename std::remove_const<T>::type;
using UData = NCValue *;
using CUData = T *;
return tryGetCUData<T *, UData, CUData>(position, value);
} }
template<typename T, typename std::enable_if<detail::IsRegularClass<T>::value, int>::type = 0> template<typename T, typename std::enable_if<detail::IsRegularClass<T>::value && !std::is_const<T>::value, int>::type = 0>
bool tryGet(int position, std::shared_ptr<T> & value) STRONG_INLINE bool tryGet(int position, T * & value)
{ {
return tryGetUData(position, value); return tryGetUData<T *>(position, value);
}
template<typename T, typename std::enable_if<detail::IsRegularClass<T>::value && std::is_const<T>::value, int>::type = 0>
STRONG_INLINE bool tryGet(int position, std::shared_ptr<T> & value)
{
using NCValue = typename std::remove_const<T>::type;
using UData = std::shared_ptr<NCValue>;
using CUData = std::shared_ptr<T>;
return tryGetCUData<std::shared_ptr<T>, UData, CUData>(position, value);
}
template<typename T, typename std::enable_if<detail::IsRegularClass<T>::value && !std::is_const<T>::value, int>::type = 0>
STRONG_INLINE bool tryGet(int position, std::shared_ptr<T> & value)
{
return tryGetUData<std::shared_ptr<T>>(position, value);
} }
template<typename U> template<typename U>
@ -228,13 +250,67 @@ public:
{ {
static auto KEY = api::TypeRegistry::get()->getKey<U>(); static auto KEY = api::TypeRegistry::get()->getKey<U>();
void * raw = luaL_checkudata(L, position, KEY); void * raw = lua_touserdata(L, position);
if(!raw) if(!raw)
return false; return false;
value = *(static_cast<U *>(raw)); if(lua_getmetatable(L, position) == 0)
return true; return false;
lua_getfield(L, LUA_REGISTRYINDEX, KEY);
if(lua_rawequal(L, -1, -2) == 1)
{
value = *(static_cast<U *>(raw));
lua_pop(L, 2);
return true;
}
lua_pop(L, 2);
return false;
}
template<typename T, typename U, typename CU>
bool tryGetCUData(int position, T & value)
{
static auto KEY = api::TypeRegistry::get()->getKey<U>();
static auto C_KEY = api::TypeRegistry::get()->getKey<CU>();
void * raw = lua_touserdata(L, position);
if(!raw)
return false;
if(lua_getmetatable(L, position) == 0)
return false;
//top is metatable
lua_getfield(L, LUA_REGISTRYINDEX, KEY);
if(lua_rawequal(L, -1, -2) == 1)
{
value = *(static_cast<U *>(raw));
lua_pop(L, 2);
return true;
}
lua_pop(L, 1);
//top is metatable
lua_getfield(L, LUA_REGISTRYINDEX, C_KEY);
if(lua_rawequal(L, -1, -2) == 1)
{
value = *(static_cast<CU *>(raw));
lua_pop(L, 2);
return true;
}
lua_pop(L, 2);
return false;
} }
bool tryGet(int position, JsonNode & value); bool tryGet(int position, JsonNode & value);

View File

@ -161,13 +161,16 @@ class OpaqueWrapper : public RegistarBase
{ {
public: public:
using ObjectType = typename std::remove_cv<T>::type; using ObjectType = typename std::remove_cv<T>::type;
using UDataType = T *; using UDataType = ObjectType *;
using CUDataType = const ObjectType *;
using RegType = detail::RegType<UDataType>; using RegType = detail::RegType<UDataType>;
using CustomRegType = detail::CustomRegType; using CustomRegType = detail::CustomRegType;
void pushMetatable(lua_State * L) const override final void pushMetatable(lua_State * L) const override final
{ {
static auto KEY = api::TypeRegistry::get()->getKey<UDataType>(); static auto KEY = api::TypeRegistry::get()->getKey<UDataType>();
static auto S_KEY = api::TypeRegistry::get()->getKey<CUDataType>();
LuaStack S(L); LuaStack S(L);
@ -176,6 +179,11 @@ public:
S.balance(); S.balance();
if(luaL_newmetatable(L, S_KEY) != 0)
adjustMetatable(L);
S.balance();
detail::Dispatcher<Proxy, UDataType>::pushStaticTable(L); detail::Dispatcher<Proxy, UDataType>::pushStaticTable(L);
adjustStaticTable(L); adjustStaticTable(L);

View File

@ -26,8 +26,6 @@ VCMI_REGISTER_CORE_SCRIPT_API(CreatureProxy, "Creature");
const std::vector<CreatureProxy::RegType> CreatureProxy::REGISTER = const std::vector<CreatureProxy::RegType> CreatureProxy::REGISTER =
{ {
{"accessBonuses", LuaCallWrapper<const EntityWithBonuses<CreatureID>>::createFunctor(&EntityWithBonuses<CreatureID>::accessBonuses)},
{"getCost", LuaCallWrapper<const Creature>::createFunctor(&Creature::getCost)}, {"getCost", LuaCallWrapper<const Creature>::createFunctor(&Creature::getCost)},
{"isDoubleWide", LuaCallWrapper<const Creature>::createFunctor(&Creature::isDoubleWide)}, {"isDoubleWide", LuaCallWrapper<const Creature>::createFunctor(&Creature::isDoubleWide)},
}; };

View File

@ -21,10 +21,10 @@ namespace scripting
namespace api namespace api
{ {
class ObjectInstanceProxy : public OpaqueWrapper<const IObjectInterface, ObjectInstanceProxy> class ObjectInstanceProxy : public OpaqueWrapper<const CGObjectInstance, ObjectInstanceProxy>
{ {
public: public:
using Wrapper = OpaqueWrapper<const IObjectInterface, ObjectInstanceProxy>; using Wrapper = OpaqueWrapper<const CGObjectInstance, ObjectInstanceProxy>;
static const std::vector<typename Wrapper::RegType> REGISTER; static const std::vector<typename Wrapper::RegType> REGISTER;
static const std::vector<typename Wrapper::CustomRegType> REGISTER_CUSTOM; static const std::vector<typename Wrapper::CustomRegType> REGISTER_CUSTOM;
}; };

View File

@ -39,6 +39,21 @@ const std::vector<ObjectVisitStartedProxy::CustomRegType> ObjectVisitStartedProx
&SubscriptionRegistryProxy<ObjectVisitStartedProxy>::subscribeAfter, &SubscriptionRegistryProxy<ObjectVisitStartedProxy>::subscribeAfter,
true true
}, },
{
"getPlayer",
LuaMethodWrapper<ObjectVisitStarted, PlayerColor(ObjectVisitStarted:: *)()const, &ObjectVisitStarted::getPlayer>::invoke,
false
},
{
"getHero",
LuaMethodWrapper<ObjectVisitStarted, ObjectInstanceID(ObjectVisitStarted:: *)()const, &ObjectVisitStarted::getHero>::invoke,
false
},
{
"getObject",
LuaMethodWrapper<ObjectVisitStarted, ObjectInstanceID(ObjectVisitStarted:: *)()const, &ObjectVisitStarted::getObject>::invoke,
false
},
}; };
} }

View File

@ -200,7 +200,7 @@ end
!?TL client only? depends on time limit feature !?TL client only? depends on time limit feature
]] ]]
local supportedTriggers = {"PI", "FU", "GM", "MF", "TM"} local supportedTriggers = {"PI", "FU", "GM", "MF", "OB", "TM"}
local TriggerLoaders = {} local TriggerLoaders = {}

View File

@ -6,7 +6,7 @@ local trigger = TriggerBase:new()
function trigger:new(o) function trigger:new(o)
o = TriggerBase.new(self, o) o = TriggerBase.new(self, o)
o.sub = ApplyDamage.subscribeBefore(EVENT_BUS, function(event) o.sub = ApplyDamage.subscribeBefore(eventBus, function(event)
o:call(event) o:call(event)
end) end)
return o return o

27
scripts/lib/erm/OB_T.lua Normal file
View File

@ -0,0 +1,27 @@
local TriggerBase = require("core:erm.TriggerBase")
local ObjectVisitStarted = require("events.ObjectVisitStarted")
local eventBus = EVENT_BUS
local game = GAME
local trigger = TriggerBase:new()
function trigger:new(o)
o = TriggerBase.new(self, o)
local id1 = tonumber(o.id[1])
o.sub = ObjectVisitStarted.subscribeBefore(eventBus,
function(event)
local objIndex = event:getObject()
local obj = game:getObj(objIndex, false)
if obj:getObjGroupIndex() == id1 then
o:call(event)
end
end)
return o
end
return trigger

View File

@ -42,23 +42,26 @@ protected:
TEST_F(ERM_OB_T, ByTypeIndex) TEST_F(ERM_OB_T, ByTypeIndex)
{ {
EXPECT_CALL(infoMock, getObj(Eq(ObjectInstanceID(234)), _)).WillRepeatedly(Return(&objectMock)); EXPECT_CALL(infoMock, getObj(Eq(ObjectInstanceID(234)), _)).Times(AtLeast(1)).WillRepeatedly(Return(&objectMock));
EXPECT_CALL(objectMock, getObjGroupIndex()).WillRepeatedly(Return(420)); EXPECT_CALL(objectMock, getObjGroupIndex()).Times(AtLeast(1)).WillRepeatedly(Return(420));
loadScript(VLC->scriptHandler->erm, loadScript(VLC->scriptHandler->erm,
"VERM\n" "VERM\n"
"!?OB420;\n" "!?OB420;\n"
"!!VRv42:S4;\n" "!!VRv42:S4;\n"
"!?OB421;\n"
"!!VRv43:S5;\n"
); );
SCOPED_TRACE("\n" + subject->code); SCOPED_TRACE("\n" + subject->code);
runClientServer(); runClientServer();
events::ObjectVisitStarted::defaultExecute(&eventBus, nullptr, PlayerColor(2), ObjectInstanceID(234), ObjectInstanceID(235)); events::ObjectVisitStarted::defaultExecute(&eventBus, nullptr, PlayerColor(2), ObjectInstanceID(235), ObjectInstanceID(234));
const JsonNode actualState = context->saveState(); const JsonNode actualState = context->saveState();
EXPECT_EQ(actualState["ERM"]["v"]["42"], JsonUtils::floatNode(4)) << actualState.toJson(); EXPECT_EQ(actualState["ERM"]["v"]["42"], JsonUtils::floatNode(4)) << actualState.toJson();
EXPECT_TRUE(actualState["ERM"]["v"]["43"].isNull()) << actualState.toJson();
} }
} }