A bunch of work on the concept of script owners.
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Deukhoofd 2021-10-29 23:54:44 +02:00
parent 0623bdff06
commit ede314ef39
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
19 changed files with 110 additions and 32 deletions

View File

@ -14,8 +14,8 @@ export uint8_t PkmnLib_AngelScriptResolver_CreateScript(AngelScriptResolver* p,
}
export uint8_t PkmnLib_AngelScriptResolver_FinalizeModule(AngelScriptResolver* p) { Try(p->FinalizeModule();) }
export uint8_t PkmnLib_AngelScriptResolver_LoadScript(CreatureLib::Battling::BattleScript*& out, AngelScriptResolver* p,
ScriptCategory category, const char* scriptName) {
Try(out = p->LoadScript(category, ArbUt::StringView(scriptName));)
void* owner, ScriptCategory category, const char* scriptName) {
Try(out = p->LoadScript(owner, category, ArbUt::StringView(scriptName));)
}
export uint8_t PkmnLib_AngelScriptResolver_LoadEvolutionScript(PkmnLib::Battling::EvolutionScript const*& out,
AngelScriptResolver* p, const char* scriptName) {

View File

@ -4,7 +4,7 @@ void PkmnLib::Battling::Battle::SetWeather(const ArbUt::StringView& name) {
_weatherScript->OnRemove();
}
_weatherScript = std::unique_ptr<CreatureLib::Battling::BattleScript>(
_library->LoadScript(static_cast<ScriptCategory>(PkmnScriptCategory::Weather), name));
_library->LoadScript(this, static_cast<ScriptCategory>(PkmnScriptCategory::Weather), name));
_eventHook.Trigger<WeatherChangeEvent>(name);
}
void PkmnLib::Battling::Battle::ClearWeather() {
@ -57,9 +57,9 @@ PkmnLib::Battling::Battle* PkmnLib::Battling::Battle::Clone() const {
battle->_hasEnded = _hasEnded;
battle->_battleResult = _battleResult;
battle->_currentTurn = _currentTurn;
_volatile.Clone(battle->_volatile);
_volatile.Clone(battle, battle->_volatile);
if (_weatherScript != nullptr) {
battle->_weatherScript = std::unique_ptr<CreatureLib::Battling::BattleScript>(_weatherScript->Clone());
battle->_weatherScript = std::unique_ptr<CreatureLib::Battling::BattleScript>(_weatherScript->Clone(battle));
}
return battle;

View File

@ -13,6 +13,8 @@
namespace PkmnLib::Battling {
class PkmnScript : public CreatureLib::Battling::BattleScript {
public:
PkmnScript(const ArbUt::OptionalBorrowedPtr<void>& owner) : CreatureLib::Battling::BattleScript(owner) {}
virtual void ModifyCriticalStage(CreatureLib::Battling::ExecutingAttack* attack,
CreatureLib::Battling::Creature* target, uint8_t hit, uint8_t* critStage){};
virtual void OverrideCriticalModifier(CreatureLib::Battling::ExecutingAttack* attack,

View File

@ -53,14 +53,14 @@ CreatureLib::Battling::Creature* PkmnLib::Battling::Pokemon::Clone() const {
c->_battleData.OnBattleField = _battleData.OnBattleField;
c->_battleData.Index = _battleData.Index;
if (_activeTalent != nullptr) {
c->_activeTalent = std::unique_ptr<PkmnScript::BattleScript>(_activeTalent->Clone());
c->_activeTalent = std::unique_ptr<PkmnScript::BattleScript>(_activeTalent->Clone(c));
}
c->_hasOverridenTalent = _hasOverridenTalent;
c->_overridenTalentName = _overridenTalentName;
if (_status != nullptr) {
c->_status = std::unique_ptr<PkmnScript::BattleScript>(_status->Clone());
c->_status = std::unique_ptr<PkmnScript::BattleScript>(_status->Clone(c));
}
_volatile.Clone(c->_volatile);
_volatile.Clone(c, c->_volatile);
c->_types = std::vector<u8>(_types);
c->_friendship = _friendship;
c->RecalculateFlatStats();

View File

@ -165,7 +165,8 @@ void AngelScriptResolver::MessageCallback(const asSMessageInfo* msg, void*) {
printf("%s (%d, %d) : %s : %s\n", msg->section, msg->row, msg->col, type, msg->message);
}
CreatureLib::Battling::BattleScript* AngelScriptResolver::LoadScript(ScriptCategory category,
CreatureLib::Battling::BattleScript* AngelScriptResolver::LoadScript(const ArbUt::OptionalBorrowedPtr<void>& owner,
ScriptCategory category,
const ArbUt::StringView& scriptName) {
ArbUt::Dictionary<ArbUt::StringView, AngelScriptTypeInfo*> innerDb;
auto v = _typeDatabase.TryGet(category);
@ -187,7 +188,8 @@ CreatureLib::Battling::BattleScript* AngelScriptResolver::LoadScript(ScriptCateg
auto ctx = _contextPool->RequestContext();
auto obj = const_cast<AngelScriptTypeInfo*>(t.value().get())->Instantiate(ctx);
_contextPool->ReturnContextToPool(ctx);
return new AngelScriptScript(this, t.value(), obj, _contextPool);
auto ownerType = GetScriptOwnerType(category);
return new AngelScriptScript(owner, ownerType, this, t.value(), obj, _contextPool);
}
CreatureLib::Battling::ItemUseScript* AngelScriptResolver::LoadItemScript(const CreatureLib::Library::Item* item) {

View File

@ -11,6 +11,7 @@
#define ANGELSCRIPT_DLL_LIBRARY_IMPORT
#include <Arbutils/StringView.hpp>
#include <angelscript.h>
#include "../../Battling/PkmnScriptCategory.hpp"
#include "AngelScriptItemUseScript.hpp"
#include "AngelScriptScript.hpp"
#include "AngelScriptTypeInfo.hpp"
@ -35,6 +36,7 @@ private:
ArbUt::Dictionary<ArbUt::StringView, asITypeInfo*> _evolutionTypes;
ArbUt::Dictionary<const CreatureLib::Library::Item*, AngelScriptItemUseScript*> _itemUseScripts;
ArbUt::Dictionary<ArbUt::StringView, AngelScriptEvolutionScript*> _evolutionScripts;
ArbUt::Dictionary<ScriptCategory, asITypeInfo*> _scriptOwnerTypes;
static void MessageCallback(const asSMessageInfo* msg, void* param);
static void Print(const std::string& str) { std::cout << str << std::endl; }
@ -60,7 +62,8 @@ public:
void DefineWord(const std::string& word) { _builder.DefineWord(word.c_str()); }
CreatureLib::Battling::BattleScript* LoadScript(ScriptCategory category,
CreatureLib::Battling::BattleScript* LoadScript(const ArbUt::OptionalBorrowedPtr<void>& owner,
ScriptCategory category,
const ArbUt::StringView& scriptName) override;
CreatureLib::Battling::ItemUseScript* LoadItemScript(const CreatureLib::Library::Item* item) override;
@ -112,5 +115,27 @@ public:
inline AngelscriptUserdata* GetUserdata() const noexcept { return _userData; }
inline ArbUt::OptionalBorrowedPtr<AngelscriptDebugger> GetDebugger() const noexcept { return _debugger.GetValue(); }
inline void SetDebugger(AngelscriptDebugger* debugger) noexcept { _debugger = debugger; }
inline asITypeInfo* GetScriptOwnerType(ScriptCategory category) {
auto tryget = _scriptOwnerTypes.TryGet(category);
if (tryget.has_value()) {
return tryget.value();
}
asITypeInfo* t = nullptr;
switch (category) {
case ScriptCategory::Attack: t = _engine->GetTypeInfoByName("ExecutingMove"); break;
case ScriptCategory::Talent: t = _engine->GetTypeInfoByName("Pokemon"); break;
case ScriptCategory::Status: t = _engine->GetTypeInfoByName("Pokemon"); break;
case ScriptCategory::Creature: t = _engine->GetTypeInfoByName("Pokemon"); break;
case ScriptCategory::Battle: t = _engine->GetTypeInfoByName("Battle"); break;
case ScriptCategory::Side: t = _engine->GetTypeInfoByName("BattleSide"); break;
}
switch (static_cast<PkmnScriptCategory>(category)) {
case PkmnScriptCategory::Weather: t = _engine->GetTypeInfoByName("Battle"); break;
}
_scriptOwnerTypes.Set(category, t);
return t;
}
};
#endif // PKMNLIB_ANGELSCRIPRESOLVER_HPP

View File

@ -15,6 +15,27 @@ AngelScriptScript::GetEffectParameters(const ArbUt::List<CreatureLib::Library::E
return new NativeArray<ArbUt::List<CreatureLib::Library::EffectParameter*>>(&ls);
}
AngelScriptScript::AngelScriptScript(const ArbUt::OptionalBorrowedPtr<void>& owner, asITypeInfo* ownerType,
AngelScriptResolver* resolver, AngelScriptTypeInfo* type, asIScriptObject* obj,
ContextPool* ctxPool)
: PkmnLib::Battling::PkmnScript(owner), _resolver(resolver), _type(type), _ctxPool(ctxPool), _obj(obj) {
if (_type->GetGetOwner().Exists) {
CScriptHandle* handle = nullptr;
AngelScriptUtils::AngelscriptFunctionCall(
_type->GetGetOwner().Function, _ctxPool, _obj, _resolver, GetName(), [&](asIScriptContext*) {},
[&](asIScriptContext* ctx) { handle = (CScriptHandle*)ctx->GetReturnObject(); });
handle->Set(owner.GetValue(), ownerType);
}
}
CScriptHandle* AngelScriptScript::GetAngelscriptOwner() {
CScriptHandle* handle = nullptr;
AngelScriptUtils::AngelscriptFunctionCall(
_type->GetGetOwner().Function, _ctxPool, _obj, _resolver, GetName(), [&](asIScriptContext*) {},
[&](asIScriptContext* ctx) { handle = (CScriptHandle*)ctx->GetReturnObject(); });
return handle;
}
void AngelScriptScript::OnInitialize(const ArbUt::List<CreatureLib::Library::EffectParameter*>& parameters) {
CALL_HOOK(OnInitialize, {
auto arr = GetEffectParameters(parameters);
@ -301,12 +322,13 @@ void AngelScriptScript::ModifyNumberOfHits(CreatureLib::Battling::AttackTurnChoi
ctx->SetArgAddress(1, numberOfHits);
})}
CreatureLib::Battling::BattleScript* AngelScriptScript::Clone() {
CreatureLib::Battling::BattleScript* AngelScriptScript::Clone(const ArbUt::OptionalBorrowedPtr<void>& owner) {
auto* ctx = _ctxPool->RequestContext();
auto* obj = _type->Instantiate(ctx);
if (_obj != nullptr) {
obj->CopyFrom(_obj);
}
_ctxPool->ReturnContextToPool(ctx);
return new AngelScriptScript(_resolver, _type, obj, _ctxPool);
return new AngelScriptScript(owner, GetAngelscriptOwner()->GetType(), _resolver, _type, obj, _ctxPool);
}

View File

@ -1,9 +1,11 @@
#ifndef PKMNLIB_ANGELSCRIPTSCRIPT_HPP
#define PKMNLIB_ANGELSCRIPTSCRIPT_HPP
#include <CreatureLib/Battling/ScriptHandling/BattleScript.hpp>
#include <CreatureLib/Battling/ScriptHandling/ScriptCategory.hpp>
#define ANGELSCRIPT_DLL_LIBRARY_IMPORT
#include <angelscript.h>
#include "../../../extern/angelscript_addons/scriptarray/scriptarray.h"
#include "../../../extern/angelscript_addons/scripthandle/scripthandle.h"
#include "../../Battling/PkmnScript.hpp"
#include "AngelScriptTypeInfo.hpp"
#include "TypeRegistry/NativeArray.hpp"
@ -22,13 +24,13 @@ private:
GetEffectParameters(const ArbUt::List<CreatureLib::Library::EffectParameter*>& ls);
public:
AngelScriptScript(AngelScriptResolver* resolver, AngelScriptTypeInfo* type, asIScriptObject* obj,
ContextPool* ctxPool)
: _resolver(resolver), _type(type), _ctxPool(ctxPool), _obj(obj) {}
AngelScriptScript(const ArbUt::OptionalBorrowedPtr<void>& owner, asITypeInfo* ownerType,
AngelScriptResolver* resolver, AngelScriptTypeInfo* type, asIScriptObject* obj,
ContextPool* ctxPool);
~AngelScriptScript() override { _obj->Release(); }
BattleScript* Clone() override;
BattleScript* Clone(const ArbUt::OptionalBorrowedPtr<void>& owner) override;
inline asIScriptObject* GetRawAngelscriptObject() const noexcept { return _obj; }
@ -44,6 +46,7 @@ public:
ContextPool* GetContextPool() { return _ctxPool; }
CScriptHandle* GetAngelscriptOwner();
void OnInitialize(const ArbUt::List<CreatureLib::Library::EffectParameter*>& parameters) override;
void Stack() override;

View File

@ -36,7 +36,8 @@ public:
const ArbUt::StringView& GetName() const noexcept { return _name; }
const char* GetDecl() { return _type->GetName(); }
inline asITypeInfo* GetType() const { return _type; }
inline const char* GetDecl() { return _type->GetName(); }
asIScriptFunction* GetFunction(const ArbUt::BasicStringView& functionName) {
auto v = _functions.TryGet(functionName);
@ -70,6 +71,23 @@ private:
public: \
const FunctionInfo& Get##name() const { return __##name; }
private:
FunctionInfo InitializeGetOwner(){
auto t = _type;
while (t != nullptr){
auto val = t->GetMethodByDecl("protected ref@ GetOwner()", false);
if (val != nullptr){
return FunctionInfo{.Exists = true, .Function = val};
}
t = t->GetBaseType();
}
return FunctionInfo{.Exists = false, .Function = nullptr};
}
FunctionInfo __GetOwner = InitializeGetOwner();
public:
const FunctionInfo& GetGetOwner() const { return __GetOwner; }
SCRIPT_HOOK_FUNCTION(OnInitialize, "void OnInitialize(const narray<EffectParameter@>@ parameters)");
SCRIPT_HOOK_FUNCTION(Stack, "void Stack()");
SCRIPT_HOOK_FUNCTION(OnRemove, "void OnRemove()");

View File

@ -5,7 +5,11 @@ void BasicScriptClass::Register(asIScriptEngine* engine) {
// application registry interface. As such, we just create it from string.
int r = engine->GetModuleByIndex(0)->AddScriptSection("PkmnScript", R"(
shared abstract class PkmnScript {
// CreatureLib methods
private ref@ __owner;
protected ref@ GetOwner() { return __owner; };
// CreatureLib methods
void OnInitialize(const narray<EffectParameter@>@ parameters){};
void Stack(){};
void OnRemove(){};

View File

@ -113,7 +113,7 @@ static AngelScriptResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary*
static AngelScriptScript* GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const ArbUt::StringView& scriptName) {
auto lib = GetScriptResolver(mainLib);
auto s = lib->LoadScript(ScriptCategory::Creature, scriptName);
auto s = lib->LoadScript(nullptr, ScriptCategory::Creature, scriptName);
auto script = dynamic_cast<AngelScriptScript*>(s);
REQUIRE(script != nullptr);

View File

@ -44,7 +44,7 @@ TEST_CASE("Build script resolver, then create object") {
lib->CreateScript("testScript1", _scripts["testScript1"]);
lib->FinalizeModule();
auto obj = lib->LoadScript(ScriptCategory::Creature, "testScript1"_cnc);
auto obj = lib->LoadScript(nullptr, ScriptCategory::Creature, "testScript1"_cnc);
delete obj;
delete lib;
@ -56,7 +56,7 @@ TEST_CASE("Build script resolver, create object, invoke addition method") {
lib->CreateScript("testScript1", _scripts["testScript1"]);
lib->FinalizeModule();
auto obj = dynamic_cast<AngelScriptScript*>(lib->LoadScript(ScriptCategory::Creature, "testScript1"_cnc));
auto obj = dynamic_cast<AngelScriptScript*>(lib->LoadScript(nullptr, ScriptCategory::Creature, "testScript1"_cnc));
REQUIRE(obj != nullptr);
auto ctxPool = obj->GetContextPool();
auto ctx = ctxPool->RequestContext();
@ -86,7 +86,8 @@ TEST_CASE("Get a script resolver, save the byte code to memory, create new scrip
originLib->Initialize(TestLibrary::GetLibrary());
originLib->CreateScript("testScript1", _scripts["testScript1"]);
originLib->FinalizeModule();
auto obj = dynamic_cast<AngelScriptScript*>(originLib->LoadScript(ScriptCategory::Creature, "testScript1"_cnc));
auto obj =
dynamic_cast<AngelScriptScript*>(originLib->LoadScript(nullptr, ScriptCategory::Creature, "testScript1"_cnc));
REQUIRE(obj != nullptr);
REQUIRE(obj->GetType()->GetOnInitialize().Exists);
delete obj;
@ -96,7 +97,7 @@ TEST_CASE("Get a script resolver, save the byte code to memory, create new scrip
auto newLib = dynamic_cast<AngelScriptResolver*>(PkmnLib::Battling::BattleLibrary::CreateScriptResolver());
newLib->Initialize(TestLibrary::GetLibrary());
newLib->LoadByteCodeFromMemory(byteCode, size);
obj = dynamic_cast<AngelScriptScript*>(newLib->LoadScript(ScriptCategory::Creature, "testScript1"_cnc));
obj = dynamic_cast<AngelScriptScript*>(newLib->LoadScript(nullptr, ScriptCategory::Creature, "testScript1"_cnc));
REQUIRE(obj != nullptr);
REQUIRE(obj->GetType()->GetOnInitialize().Exists);
delete obj;
@ -114,7 +115,8 @@ TEST_CASE("Get a script resolver, save the byte code to file, create new script
auto newLib = dynamic_cast<AngelScriptResolver*>(PkmnLib::Battling::BattleLibrary::CreateScriptResolver());
newLib->Initialize(TestLibrary::GetLibrary());
newLib->LoadByteCodeFromFile("foo.bin");
auto obj = dynamic_cast<AngelScriptScript*>(newLib->LoadScript(ScriptCategory::Creature, "testScript1"_cnc));
auto obj =
dynamic_cast<AngelScriptScript*>(newLib->LoadScript(nullptr, ScriptCategory::Creature, "testScript1"_cnc));
REQUIRE(obj != nullptr);
delete obj;
delete originLib;

View File

@ -44,7 +44,7 @@ static AngelScriptResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary*
static ScriptData GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const ArbUt::StringView& funcName) {
auto lib = GetScriptResolver(mainLib);
auto s = lib->LoadScript(ScriptCategory::Creature, "testScript1"_cnc);
auto s = lib->LoadScript(nullptr, ScriptCategory::Creature, "testScript1"_cnc);
auto script = dynamic_cast<AngelScriptScript*>(s);
REQUIRE(script != nullptr);

View File

@ -57,7 +57,7 @@ static AngelScriptResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary*
static ScriptData GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const ArbUt::StringView& funcName) {
auto lib = GetScriptResolver(mainLib);
auto s = lib->LoadScript(ScriptCategory::Creature, "testScript1"_cnc);
auto s = lib->LoadScript(nullptr, ScriptCategory::Creature, "testScript1"_cnc);
auto script = dynamic_cast<AngelScriptScript*>(s);
REQUIRE(script != nullptr);

View File

@ -45,7 +45,7 @@ static AngelScriptResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary*
static ScriptData GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const ArbUt::StringView& funcName) {
auto lib = GetScriptResolver(mainLib);
auto s = lib->LoadScript(ScriptCategory::Creature, "testScript1"_cnc);
auto s = lib->LoadScript(nullptr, ScriptCategory::Creature, "testScript1"_cnc);
auto script = dynamic_cast<AngelScriptScript*>(s);
REQUIRE(script != nullptr);

View File

@ -41,7 +41,7 @@ static AngelScriptResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary*
static ScriptData GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const ArbUt::StringView& funcName) {
auto lib = GetScriptResolver(mainLib);
auto s = lib->LoadScript(ScriptCategory::Creature, "testScript1"_cnc);
auto s = lib->LoadScript(nullptr, ScriptCategory::Creature, "testScript1"_cnc);
auto script = dynamic_cast<AngelScriptScript*>(s);
REQUIRE(script != nullptr);

View File

@ -45,7 +45,7 @@ static AngelScriptResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary*
static ScriptData GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const ArbUt::StringView& funcName) {
auto lib = GetScriptResolver(mainLib);
auto s = lib->LoadScript(ScriptCategory::Creature, "testScript1"_cnc);
auto s = lib->LoadScript(nullptr, ScriptCategory::Creature, "testScript1"_cnc);
auto script = dynamic_cast<AngelScriptScript*>(s);
REQUIRE(script != nullptr);

View File

@ -43,7 +43,7 @@ static AngelScriptResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary*
static ScriptData GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const ArbUt::StringView& funcName) {
auto lib = GetScriptResolver(mainLib);
auto s = lib->LoadScript(ScriptCategory::Creature, "testScript1"_cnc);
auto s = lib->LoadScript(nullptr, ScriptCategory::Creature, "testScript1"_cnc);
auto script = dynamic_cast<AngelScriptScript*>(s);
REQUIRE(script != nullptr);

View File

@ -44,7 +44,7 @@ static AngelScriptResolver* GetScriptResolver(PkmnLib::Battling::BattleLibrary*
static ScriptData GetScript(PkmnLib::Battling::BattleLibrary* mainLib, const ArbUt::StringView& funcName) {
auto lib = GetScriptResolver(mainLib);
auto s = lib->LoadScript(ScriptCategory::Creature, "testScript1"_cnc);
auto s = lib->LoadScript(nullptr, ScriptCategory::Creature, "testScript1"_cnc);
auto script = dynamic_cast<AngelScriptScript*>(s);
REQUIRE(script != nullptr);