Files
starruler-linux/source/game/scripts/generic_call.h
T
2018-07-17 14:15:37 +02:00

285 lines
7.3 KiB
C++

#pragma once
#include "scripts/manager.h"
#include "script_bind.h"
#include "vec3.h"
#include "vec2.h"
#include "quaternion.h"
#include <string>
#include <stdint.h>
#include <vector>
#include <functional>
#ifndef MAX_GENERIC_ARGUMENTS
#define MAX_GENERIC_ARGUMENTS 16
#endif
class Object;
class Empire;
class Design;
struct Player;
struct ScriptObjectType;
namespace net {
struct Message;
};
namespace scene {
class Node;
};
namespace scripts {
struct ArgumentDesc;
struct GenericValue;
typedef std::function<void(net::Message&,ArgumentDesc&,GenericValue&)> customRW;
typedef std::function<asIScriptObject*(ArgumentDesc&,asIScriptObject*)> customHandle;
struct GenericValue {
union {
int integer;
unsigned uint;
float sfloat;
double dfloat;
bool boolean;
int64_t longint;
std::string* str;
Object* obj;
Empire* emp;
scene::Node* node;
Design* design;
Player* player;
asIScriptObject* script;
net::Message* msg;
vec3d* v3;
vec2i* v2;
quaterniond* quat;
void* ptr;
};
bool managed;
volatile bool asyncReturned;
template<class T>
T& get() {
return *(T*)this;
}
GenericValue() :
ptr(nullptr), managed(false), asyncReturned(false) {}
};
void trivialCopy(GenericValue& to, GenericValue& from);
struct GenericType {
std::string name;
bool wouldConst;
std::function<void(GenericValue&,unsigned,asIScriptGeneric*)> get;
std::function<void(GenericValue&,GenericValue&)> copy;
std::function<void(GenericValue&,asIScriptGeneric*)> ret;
std::function<void(Call&,GenericValue&)> call;
std::function<void(Call&,ArgumentDesc&,GenericValue&,customHandle custom)> push;
std::function<void(net::Message&,ArgumentDesc&,GenericValue&,customRW custom)> write;
std::function<bool(net::Message&,ArgumentDesc&,GenericValue&,customRW custom)> read;
std::function<void(GenericValue&)> destruct;
GenericType() : wouldConst(false) {}
template<class T>
GenericType* setup(std::string Name, decltype(get) Get, decltype(ret) Ret, decltype(copy) Copy = trivialCopy,
decltype(call) Cl = nullptr, decltype(push) Push = nullptr,
decltype(write) Write = nullptr, decltype(read) Read = nullptr,
decltype(destruct) Destruct = nullptr, bool WouldConst = false) {
name = Name;
get = Get;
ret = Ret;
copy = Copy;
if(Cl == nullptr) {
call = [](Call& cl, GenericValue& val) {
cl.call(val.get<T>());
};
}
else {
call = Cl;
}
if(Push == nullptr) {
push = [](Call& cl, ArgumentDesc& desc, GenericValue& val, customHandle custom) {
cl.push(val.get<T>());
};
}
else {
push = Push;
}
if(Write == nullptr) {
write = [](net::Message& msg, ArgumentDesc& desc, GenericValue& val, customRW custom) {
msg << val.get<T>();
};
}
else {
write = Write;
}
if(Read == nullptr) {
read = [](net::Message& msg, ArgumentDesc& desc, GenericValue& val, customRW custom) -> bool {
msg >> val.get<T>();
return true;
};
}
else {
read = Read;
}
destruct = Destruct;
wouldConst = WouldConst;
return this;
}
};
extern GenericType* GT_uint;
extern GenericType* GT_Custom_Handle;
extern GenericType* GT_Player_Ref;
extern GenericType* GT_Object_Ref;
extern GenericType* GT_Empire_Ref;
extern GenericType* GT_Node_Ref;
const std::string& getTypeString(GenericType* type);
GenericType* getStringType(const std::string& type);
struct ArgumentDesc {
GenericType* type;
std::string argName;
std::string defaultValue;
std::string customName;
void* customType;
void* customRead;
void* customWrite;
bool isConst;
ArgumentDesc()
: type(nullptr), customType(nullptr), customRead(nullptr), customWrite(nullptr), isConst(false) {
}
ArgumentDesc(GenericType* Type)
: type(Type), customType(nullptr), customRead(nullptr), customWrite(nullptr), isConst(false) {
}
ArgumentDesc(GenericType* Type, bool IsConst)
: type(Type), customType(nullptr), customRead(nullptr), customWrite(nullptr), isConst(IsConst) {
}
ArgumentDesc(std::string CustomName, bool IsConst)
: type(GT_Custom_Handle), customName(CustomName), customType(nullptr), customRead(nullptr),
customWrite(nullptr), isConst(IsConst) {
}
void operator=(const ArgumentDesc& other) {
type = other.type;
defaultValue = other.defaultValue;
argName = other.argName;
customName = other.customName;
customType = other.customType;
customRead = other.customRead;
customWrite = other.customWrite;
isConst = other.isConst;
}
void operator=(GenericType* Type) {
type = Type;
}
operator GenericType*() {
return type;
}
std::string toString() {
if(!type)
return "void";
std::string out;
if(isConst)
out += "const ";
if(type == GT_Custom_Handle)
out += customName+"@";
else
out += getTypeString(type);
return out;
}
};
//Generic calls follow descriptors that state
//which arguments they have and what their return value is
class GenericCallDesc {
public:
std::string name;
ArgumentDesc returnType;
ArgumentDesc arguments[MAX_GENERIC_ARGUMENTS];
bool returnsArray;
bool constFunction;
unsigned argCount;
GenericCallDesc();
GenericCallDesc(std::string declaration, bool hasReturnType = true, bool customRefs = false);
void parse(std::string declaration, bool hasReturnType = true, bool customRefs = false);
void append(GenericType* argument);
void append(GenericCallDesc& desc);
void append(std::vector<std::string>& arguments, bool customRefs = false);
void prepend(ArgumentDesc argument);
GenericValue call(Call& cl);
std::string declaration(bool addReturnType = true, bool forceConst = false, unsigned start = 0);
};
//Call data holds the values of all the arguments for easy passing around
class GenericCallData {
public:
GenericCallDesc& desc;
GenericValue values[MAX_GENERIC_ARGUMENTS];
void* object;
GenericCallData(GenericCallDesc& desc);
GenericCallData(GenericCallData& data);
~GenericCallData();
//Generic call data can be sent over the network,
//the function descriptor should be sent manually though,
//depending on what system is sending it.
void write(net::Message& msg, unsigned startAt = 0, customRW custom = nullptr);
bool read(net::Message& msg, unsigned startAt = 0, customRW custom = nullptr);
//Read all the arguments from an angelscript generic
//call, and stash them here
GenericCallData(GenericCallDesc& desc, asIScriptGeneric* gen);
//Push all the arguments onto a script call to angelscript
void pushTo(Call& call, int startAt = 0, customHandle custom = nullptr);
GenericValue call(Call& cl);
};
//Retrieve the function matching the call desc from this manager
asIScriptFunction* getFunction(Manager* manager, const char* module, GenericCallDesc& desc, bool forceConst = false);
//Bind a generically specified function to a callback,
//the callback receives the argument data and the bind id
//returned by the call to bindGeneric so it can identify which
//generic call was received
typedef GenericValue (*GenericHandler)(void* arg, GenericCallData& data);
int bindGeneric(GenericCallDesc& desc, GenericHandler handler, void* arg = nullptr, bool acceptConst = false);
int bindGeneric(ClassBind& cls, GenericCallDesc& desc, GenericHandler handler, void* arg = nullptr, bool forceConst = false);
int bindGeneric(ClassBind& cls, const std::string& decl, GenericCallDesc& desc, GenericHandler handler, void* arg = 0);
void clearGenericBinds();
void initGenericTypes();
void bindGenericObjectType(ScriptObjectType* type, std::string name);
};