Layout work on an AngelScript implementation.
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
72
src/AngelScript/AngelScripResolver.cpp
Normal file
72
src/AngelScript/AngelScripResolver.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "AngelScripResolver.hpp"
|
||||
#include "TypeRegistry/RegisterPokemonTypes.hpp"
|
||||
#include "../../extern/angelscript_addons/scriptstdstring/scriptstdstring.h"
|
||||
#include "../../extern/angelscript_addons/scripthelper/scripthelper.h"
|
||||
|
||||
CreatureLib::Battling::ScriptResolver* PkmnLib::Battling::BattleLibrary::CreateScriptResolver(){
|
||||
return new AngelScripResolver();
|
||||
}
|
||||
void AngelScripResolver::Initialize(CreatureLib::Battling::BattleLibrary* library) {
|
||||
_engine = asCreateScriptEngine();
|
||||
|
||||
_engine->SetEngineProperty(asEP_DISALLOW_EMPTY_LIST_ELEMENTS, true);
|
||||
_engine->SetEngineProperty(asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE, true);
|
||||
_engine->SetEngineProperty(asEP_ALLOW_IMPLICIT_HANDLE_TYPES, true);
|
||||
_engine->SetEngineProperty(asEP_ALWAYS_IMPL_DEFAULT_CONSTRUCT, true);
|
||||
_engine->SetEngineProperty(asEP_AUTO_GARBAGE_COLLECT, false);
|
||||
|
||||
int32_t r = _engine->SetMessageCallback(asFUNCTION(MessageCallback), nullptr, asCALL_CDECL);
|
||||
if (r < 0)
|
||||
throw CreatureException("Registering message callback failed.");
|
||||
|
||||
RegisterStdString(_engine);
|
||||
r = _engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(Print), asCALL_CDECL);
|
||||
if (r < 0) throw CreatureException("Registering print function failed.");
|
||||
|
||||
RegisterExceptionRoutines(_engine);
|
||||
|
||||
RegisterPokemonTypes::Register(_engine);
|
||||
|
||||
_mainModule = _engine->GetModule("pkmn", asGM_ALWAYS_CREATE);
|
||||
|
||||
_contextPool = new ContextPool(_engine);
|
||||
}
|
||||
AngelScriptTypeInfo* AngelScripResolver::GetTypeInfo(const std::string& name) {
|
||||
auto find = _types.find(name);
|
||||
if (find != _types.end()){
|
||||
return find->second;
|
||||
}
|
||||
auto type = _mainModule->GetTypeInfoByDecl(name.c_str());
|
||||
if (type == nullptr){
|
||||
_types.insert({name, nullptr});
|
||||
return nullptr;
|
||||
}
|
||||
auto typeinfo = new AngelScriptTypeInfo(type);
|
||||
_types.insert({name, typeinfo});
|
||||
return typeinfo;
|
||||
}
|
||||
void AngelScripResolver::MessageCallback(const asSMessageInfo* msg, void* param) {
|
||||
const char* type = "ERR ";
|
||||
if (msg->type == asMSGTYPE_WARNING)
|
||||
type = "WARN";
|
||||
else if (msg->type == asMSGTYPE_INFORMATION)
|
||||
type = "INFO";
|
||||
printf("%s (%d, %d) : %s : %s\n", msg->section, msg->row, msg->col, type, msg->message);
|
||||
}
|
||||
CreatureLib::Battling::Script* AngelScripResolver::LoadScript(ScriptCategory category, const std::string& scriptName) {
|
||||
auto typeInfo = GetTypeInfo(scriptName);
|
||||
if (typeInfo == nullptr) return nullptr;
|
||||
auto ctx = _contextPool->RequestContext();
|
||||
auto obj = typeInfo->Instantiate(ctx);
|
||||
_contextPool->ReturnContextToPool(ctx);
|
||||
return new AngelScriptScript(scriptName, typeInfo, obj, _contextPool);
|
||||
}
|
||||
void AngelScripResolver::FinalizeModule() {
|
||||
int r = _mainModule->Build();
|
||||
if (r < 0)
|
||||
throw CreatureException("Building Script Module failed.");
|
||||
}
|
||||
void AngelScripResolver::CreateScript(const char* scriptName) {
|
||||
auto scriptString = _loadFunc(scriptName);
|
||||
_mainModule->AddScriptSection(scriptName, scriptString);
|
||||
}
|
||||
46
src/AngelScript/AngelScripResolver.hpp
Normal file
46
src/AngelScript/AngelScripResolver.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef PKMNLIB_ANGELSCRIPRESOLVER_HPP
|
||||
#define PKMNLIB_ANGELSCRIPRESOLVER_HPP
|
||||
|
||||
#include <Battling/ScriptHandling/ScriptResolver.hpp>
|
||||
#include "../Battling/Library/BattleLibrary.hpp"
|
||||
|
||||
#undef GetProperty
|
||||
#include <angelscript.h>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include "AngelScriptScript.hpp"
|
||||
#include "AngelScriptTypeInfo.hpp"
|
||||
|
||||
class AngelScripResolver : public CreatureLib::Battling::ScriptResolver {
|
||||
private:
|
||||
asIScriptEngine* _engine = nullptr;
|
||||
asIScriptModule* _mainModule = nullptr;
|
||||
ContextPool* _contextPool = nullptr;
|
||||
const char* (*_loadFunc)(const char*) = nullptr;
|
||||
std::unordered_map<std::string, AngelScriptTypeInfo*> _types;
|
||||
|
||||
static void MessageCallback(const asSMessageInfo* msg, void* param);
|
||||
static void Print(const std::string& str) { std::cout << str << std::endl; }
|
||||
AngelScriptTypeInfo* GetTypeInfo(const std::string& name);
|
||||
|
||||
public:
|
||||
~AngelScripResolver() override {
|
||||
delete _contextPool;
|
||||
for (const auto& type : _types) {
|
||||
delete type.second;
|
||||
}
|
||||
_types.clear();
|
||||
_engine->ShutDownAndRelease();
|
||||
}
|
||||
|
||||
void Initialize(CreatureLib::Battling::BattleLibrary* library) override;
|
||||
|
||||
void SetCreateFunction(const char* (*loadFunc)(const char* scriptName)) { _loadFunc = loadFunc; }
|
||||
|
||||
void CreateScript(const char* scriptName);
|
||||
|
||||
void FinalizeModule();
|
||||
|
||||
CreatureLib::Battling::Script* LoadScript(ScriptCategory category, const std::string& scriptName) override;
|
||||
};
|
||||
#endif // PKMNLIB_ANGELSCRIPRESOLVER_HPP
|
||||
@@ -1 +1,2 @@
|
||||
#undef GetProperty
|
||||
#include "AngelScriptScript.hpp"
|
||||
|
||||
@@ -1,6 +1,55 @@
|
||||
#ifndef PKMNLIB_ANGELSCRIPTSCRIPT_HPP
|
||||
#define PKMNLIB_ANGELSCRIPTSCRIPT_HPP
|
||||
#include <Battling/ScriptHandling/Script.hpp>
|
||||
#undef GetProperty
|
||||
#include <angelscript.h>
|
||||
#include "AngelScriptTypeInfo.hpp"
|
||||
#include "ContextPool.hpp"
|
||||
|
||||
class AngelScriptScript {};
|
||||
class AngelScriptScript : public CreatureLib::Battling::Script {
|
||||
private:
|
||||
AngelScriptTypeInfo* _type = nullptr;
|
||||
ContextPool* _ctxPool = nullptr;
|
||||
|
||||
asIScriptObject* _obj = nullptr;
|
||||
|
||||
public:
|
||||
AngelScriptScript(const std::string& name, AngelScriptTypeInfo* type, asIScriptObject* obj, ContextPool* ctxPool)
|
||||
: CreatureLib::Battling::Script(name), _type(type), _ctxPool(ctxPool), _obj(obj) {
|
||||
}
|
||||
|
||||
~AngelScriptScript() override { _obj->Release(); }
|
||||
|
||||
void InvokeMethod(const char* name) {
|
||||
auto func = _type->GetFunction(name);
|
||||
if (func == nullptr) return;
|
||||
auto ctx = _ctxPool->RequestContext();
|
||||
ctx->Prepare(func);
|
||||
ctx->SetObject(_obj);
|
||||
auto result = ctx->Execute();
|
||||
if (result != asEXECUTION_FINISHED){
|
||||
if (result == asEXECUTION_EXCEPTION){
|
||||
throw CreatureException(ctx->GetExceptionString());
|
||||
}
|
||||
throw CreatureException("Function failed.");
|
||||
}
|
||||
_ctxPool->ReturnContextToPool(ctx);
|
||||
}
|
||||
|
||||
asIScriptObject* GetScriptObject(){
|
||||
return _obj;
|
||||
}
|
||||
|
||||
asIScriptFunction* PrepareMethod(const char* name, asIScriptContext* ctx){
|
||||
auto func = _type->GetFunction(name);
|
||||
ctx->Prepare(func);
|
||||
ctx->SetObject(_obj);
|
||||
return func;
|
||||
}
|
||||
|
||||
ContextPool* GetContextPool(){
|
||||
return _ctxPool;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // PKMNLIB_ANGELSCRIPTSCRIPT_HPP
|
||||
|
||||
1
src/AngelScript/AngelScriptTypeInfo.cpp
Normal file
1
src/AngelScript/AngelScriptTypeInfo.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "AngelScriptTypeInfo.hpp"
|
||||
47
src/AngelScript/AngelScriptTypeInfo.hpp
Normal file
47
src/AngelScript/AngelScriptTypeInfo.hpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef PKMNLIB_ANGELSCRIPTTYPEINFO_HPP
|
||||
#define PKMNLIB_ANGELSCRIPTTYPEINFO_HPP
|
||||
|
||||
#include <angelscript.h>
|
||||
#include <unordered_map>
|
||||
#include <Core/Exceptions/CreatureException.hpp>
|
||||
|
||||
class AngelScriptTypeInfo {
|
||||
private:
|
||||
asITypeInfo* _type = nullptr;
|
||||
std::unordered_map<std::string, asIScriptFunction*> _functions;
|
||||
|
||||
public:
|
||||
explicit AngelScriptTypeInfo(asITypeInfo* type) : _type(type){}
|
||||
~AngelScriptTypeInfo(){
|
||||
for (const auto& f: _functions){
|
||||
f.second->Release();
|
||||
}
|
||||
_functions.clear();
|
||||
}
|
||||
|
||||
asIScriptFunction* GetFunction(const std::string& functionName){
|
||||
auto find = _functions.find(functionName);
|
||||
if (find != _functions.end()){
|
||||
return find->second;
|
||||
}
|
||||
auto func = _type->GetMethodByName(functionName.c_str());
|
||||
func->AddRef();
|
||||
_functions.insert({functionName, func});
|
||||
return func;
|
||||
}
|
||||
|
||||
asIScriptObject* Instantiate(asIScriptContext* ctx){
|
||||
auto factory = _type->GetFactoryByIndex(0);
|
||||
ctx->Prepare(factory);
|
||||
auto result = ctx->Execute();
|
||||
if (result != asEXECUTION_FINISHED){
|
||||
throw CreatureException("Instantiation failed.");
|
||||
}
|
||||
asIScriptObject* obj = *(asIScriptObject**)ctx->GetAddressOfReturnValue();
|
||||
obj->AddRef();
|
||||
return obj;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // PKMNLIB_ANGELSCRIPTTYPEINFO_HPP
|
||||
1
src/AngelScript/ContextPool.cpp
Normal file
1
src/AngelScript/ContextPool.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "ContextPool.hpp"
|
||||
37
src/AngelScript/ContextPool.hpp
Normal file
37
src/AngelScript/ContextPool.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef PKMNLIB_CONTEXTPOOL_HPP
|
||||
#define PKMNLIB_CONTEXTPOOL_HPP
|
||||
|
||||
#include <angelscript.h>
|
||||
#include <vector>
|
||||
|
||||
class ContextPool {
|
||||
std::vector<asIScriptContext*> _pool;
|
||||
asIScriptEngine* _engine;
|
||||
|
||||
public:
|
||||
ContextPool(asIScriptEngine* engine) : _engine(engine) {}
|
||||
|
||||
~ContextPool(){
|
||||
for (auto ctx: _pool){
|
||||
ctx->Release();
|
||||
}
|
||||
}
|
||||
|
||||
asIScriptContext* RequestContext() {
|
||||
// Get a context from the pool, or create a new
|
||||
asIScriptContext* ctx = nullptr;
|
||||
if (!_pool.empty()) {
|
||||
ctx = *_pool.rbegin();
|
||||
_pool.pop_back();
|
||||
} else
|
||||
ctx = _engine->CreateContext();
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void ReturnContextToPool(asIScriptContext* ctx) {
|
||||
_pool.push_back(ctx);
|
||||
ctx->Unprepare();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // PKMNLIB_CONTEXTPOOL_HPP
|
||||
@@ -1,16 +0,0 @@
|
||||
#include "../Battling/Library/PokemonScriptResolver.hpp"
|
||||
#define ANGELSCRIPT_DLL_LIBRARY_IMPORT
|
||||
#define GetPropertyCache
|
||||
#undef GetProperty
|
||||
#include <angelscript.h>
|
||||
#define GetProperty GetPropertyCache
|
||||
|
||||
using namespace PkmnLib::Battling;
|
||||
|
||||
void PokemonScriptResolver::Initialize(const PkmnLib::Battling::BattleLibrary* library){
|
||||
}
|
||||
|
||||
CreatureLib::Battling::Script* PokemonScriptResolver::LoadScript(ScriptCategory category, const std::string& scriptName){
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
36
src/AngelScript/TypeRegistry/RegisterPokemonTypes.cpp
Normal file
36
src/AngelScript/TypeRegistry/RegisterPokemonTypes.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "RegisterPokemonTypes.hpp"
|
||||
#include <cassert>
|
||||
#include "../../Library/Species/PokemonSpecies.hpp"
|
||||
|
||||
void RegisterPokemonTypes::Register(asIScriptEngine* engine) {
|
||||
RegisterGenderEnum(engine);
|
||||
RegisterSpeciesType(engine);
|
||||
}
|
||||
|
||||
void RegisterPokemonTypes::RegisterGenderEnum(asIScriptEngine* engine) {
|
||||
int r = engine->RegisterEnum("Gender"); assert(r >= 0);
|
||||
r = engine->RegisterEnumValue("Gender", "Male", 0); assert(r >= 0);
|
||||
r = engine->RegisterEnumValue("Gender", "Female", 1); assert(r >= 0);
|
||||
r = engine->RegisterEnumValue("Gender", "Genderless", 2); assert(r >= 0);
|
||||
}
|
||||
|
||||
void RegisterPokemonTypes::RegisterSpeciesType(asIScriptEngine* engine) {
|
||||
int r = engine->RegisterObjectType("Species", 0, asOBJ_REF | asOBJ_NOCOUNT);
|
||||
assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("Species", "const string& get_Name() const property",
|
||||
asMETHOD(PkmnLib::Library::PokemonSpecies, GetName), asCALL_THISCALL);
|
||||
assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("Species", "uint16 get_Id() const property",
|
||||
asMETHOD(PkmnLib::Library::PokemonSpecies, GetId), asCALL_THISCALL);
|
||||
assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("Species", "float get_GenderRate() const property",
|
||||
asMETHOD(PkmnLib::Library::PokemonSpecies, GetGenderRate), asCALL_THISCALL);
|
||||
assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("Species", "uint8 get_CaptureRate() const property",
|
||||
asMETHOD(PkmnLib::Library::PokemonSpecies, GetCaptureRate), asCALL_THISCALL);
|
||||
assert(r >= 0);
|
||||
r = engine->RegisterObjectMethod("Species", "Gender GetRandomGender() const",
|
||||
asMETHOD(PkmnLib::Library::PokemonSpecies, GetRandomGender), asCALL_THISCALL);
|
||||
assert(r >= 0);
|
||||
|
||||
}
|
||||
14
src/AngelScript/TypeRegistry/RegisterPokemonTypes.hpp
Normal file
14
src/AngelScript/TypeRegistry/RegisterPokemonTypes.hpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef PKMNLIB_REGISTERPOKEMONTYPES_HPP
|
||||
#define PKMNLIB_REGISTERPOKEMONTYPES_HPP
|
||||
#include <angelscript.h>
|
||||
|
||||
class RegisterPokemonTypes {
|
||||
public:
|
||||
static void Register(asIScriptEngine* engine);
|
||||
|
||||
private:
|
||||
static void RegisterGenderEnum(asIScriptEngine* engine);
|
||||
static void RegisterSpeciesType(asIScriptEngine* engine);
|
||||
};
|
||||
|
||||
#endif // PKMNLIB_REGISTERPOKEMONTYPES_HPP
|
||||
@@ -33,7 +33,8 @@ namespace PkmnLib::Battling {
|
||||
const Library::NatureLibrary* GetNatureLibrary() const {
|
||||
return GetStaticLib()->GetNatureLibrary();
|
||||
}
|
||||
|
||||
static CreatureLib::Battling::ScriptResolver* CreateScriptResolver();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // PKMNLIB_BATTLELIBRARY_HPP
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#ifndef PKMNLIB_POKEMONSCRIPTRESOLVER_HPP
|
||||
#define PKMNLIB_POKEMONSCRIPTRESOLVER_HPP
|
||||
|
||||
#include <Battling/ScriptHandling/ScriptResolver.hpp>
|
||||
#include "../../Battling/Library/BattleLibrary.hpp"
|
||||
namespace PkmnLib::Battling {
|
||||
class PokemonScriptResolver : public CreatureLib::Battling::ScriptResolver {
|
||||
public:
|
||||
~PokemonScriptResolver() override = default;
|
||||
void Initialize(const PkmnLib::Battling::BattleLibrary* library);
|
||||
CreatureLib::Battling::Script* LoadScript(ScriptCategory category, const std::string& scriptName) override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // PKMNLIB_POKEMONSCRIPTRESOLVER_HPP
|
||||
Reference in New Issue
Block a user