Open source Star Ruler 2 source code!

This commit is contained in:
Lucas de Vries
2018-07-17 14:15:37 +02:00
commit cc307720ff
4342 changed files with 2365070 additions and 0 deletions
+450
View File
@@ -0,0 +1,450 @@
#include "binds.h"
#include "obj/object.h"
#include "empire.h"
#include "util/format.h"
#include "main/logging.h"
#include "main/initialization.h"
#include "main/references.h"
#include "processing.h"
#include "scripts/script_components.h"
#include "scene/scripted_node.h"
extern std::vector<ScriptObjectType*> objTypeList;
extern const StateDefinition* empStates;
extern std::unordered_map<std::string, scene::scriptNodeType*> nodeTypes;
namespace scripts {
extern Object* objTarget(Object* obj, unsigned num);
extern void bindObject(ClassBind& object, ScriptObjectType* type, bool server);
extern void bindScriptNode(ClassBind& bind);
static Object* baseCast(Object* obj) {
if(obj)
obj->grab();
return obj;
}
static void castObj(asIScriptGeneric* f) {
Object* obj = (Object*)f->GetObject();
if(!obj || obj->type != f->GetFunction()->GetUserData()) {
f->SetReturnAddress(0);
}
else {
obj->grab();
f->SetReturnAddress(obj);
}
}
static void isObjectType(asIScriptGeneric* f) {
Object* obj = (Object*)f->GetObject();
if(!obj || obj->type != f->GetFunction()->GetUserData())
f->SetReturnByte(false);
else
f->SetReturnByte(true);
}
static scene::Node* nodeBaseCast(scene::ScriptedNode* node) {
if(node)
node->grab();
return node;
}
static void nodeCast(asIScriptGeneric* f) {
scene::ScriptedNode* node = dynamic_cast<scene::ScriptedNode*>((scene::Node*)f->GetObject());
if(!node || &node->type != f->GetFunction()->GetUserData()) {
f->SetReturnAddress(0);
}
else {
node->grab();
f->SetReturnAddress(node);
}
}
//Stored component offsets for each object type
void SetObjectTypeOffsets() {
auto* bpState = getStateValueType("Blueprint");
for(auto i = objTypeList.begin(), end = objTypeList.end(); i != end; ++i) {
ScriptObjectType* type = *i;
const StateDefinition& def = *type->states;
unsigned compCnt = getComponentCount();
type->componentOffsets.resize(compCnt, 0);
type->optionalComponents.resize(compCnt, false);
unsigned base = sizeof(Object);
StateDefinition::align(base);
for(auto var = def.types.begin(), endvar = def.types.end(); var != endvar; ++var) {
auto& mtype = *var->def;
if(&mtype == bpState)
type->blueprintOffset = base + var->offset;
bool optional = false;
Component* comp = getComponent(&mtype, &optional);
if(comp) {
if(type->componentOffsets[comp->id] != 0) {
error("ERROR: Object type '%s' has two components of type '%s'.",
type->name.c_str(), comp->name.c_str());
}
else {
type->componentOffsets[comp->id] = base + var->offset;
type->optionalComponents[comp->id] = optional;
}
}
}
}
}
static void writeEmpStates(Empire* emp, net::Message& msg) {
auto* def = Empire::getEmpireStates();
if(!def)
return;
def->syncWrite(msg, emp + 1);
}
static void readEmpStates(Empire* emp, net::Message& msg) {
auto* def = Empire::getEmpireStates();
if(!def)
return;
def->syncRead(msg, emp + 1);
}
static void restrictedState(asIScriptGeneric* f) {
Object* obj = (Object*)f->GetObject();
auto* member = (StateDefinition::stateDefMember*)f->GetFunction()->GetUserData();
if(obj->owner != Empire::getPlayerEmpire()) {
info("Cannot access state on unowned objects.");
member->def->setReturn(f, nullptr);
}
else {
void* memory = (void*)(obj + 1);
StateDefinition::align(memory);
member->def->setReturn(f, ((char*)memory) + member->offset);
}
}
static void paramStateGet(asIScriptGeneric* f) {
Object* obj = (Object*)f->GetObject();
auto* member = (StateDefinition::stateDefMember*)f->GetFunction()->GetUserData();
void* memory = (void*)(obj + 1);
StateDefinition::align(memory);
member->def->setReturn(f, ((char*)memory) + member->offset);
}
static void paramStateSet(asIScriptGeneric* f) {
Object* obj = (Object*)f->GetObject();
auto* member = (StateDefinition::stateDefMember*)f->GetFunction()->GetUserData();
void* memory = (void*)(obj + 1);
StateDefinition::align(memory);
member->def->setFromParam(f, ((char*)memory) + member->offset);
}
static void nodeFactory(asIScriptGeneric* f) {
auto* type = (scene::scriptNodeType*)f->GetFunction()->GetUserData();
scene::Node* node = new scene::ScriptedNode(type);
if(processing::isRunning())
node->queueReparent(devices.scene);
else
devices.scene->addChild(node);
*(scene::Node**)f->GetAddressOfReturnLocation() = node;
}
static double configGet(const std::string& name) {
auto it = gameConfig.indices.find(name);
if(it == gameConfig.indices.end())
return 0;
return gameConfig.values[it->second];
}
static void configSet(const std::string& name, double value) {
auto it = gameConfig.indices.find(name);
if(it != gameConfig.indices.end())
gameConfig.values[it->second] = value;
}
static double configGet_id(unsigned id) {
if(id >= gameConfig.count)
return 0;
return gameConfig.values[id];
}
static void configSet_id(unsigned id, double value) {
if(id >= gameConfig.count)
return;
gameConfig.values[id] = value;
}
static std::string configGetName(unsigned id) {
if(id >= gameConfig.count)
return "";
return gameConfig.names[id];
}
static unsigned configGetIndex(const std::string& name) {
auto it = gameConfig.indices.find(name);
if(it != gameConfig.indices.end())
return it->second;
return (unsigned)-1;
}
void RegisterObjectDefinitions() {
//Create the object types (states may refer to them)
for(auto i = objTypeList.begin(), end = objTypeList.end(); i != end; ++i) {
ScriptObjectType* type = *i;
ClassBind object(type->name.c_str(), asOBJ_REF);
}
}
static std::unordered_map<std::string,unsigned> empAttribNames;
static std::vector<std::string> empAttribIdents;
static std::vector<size_t> empAttribOffsets;
double getEmpAttrib(Empire* emp, unsigned index) {
if(index >= empAttribOffsets.size())
return 0.0;
return *(double*)(((char*)emp) + empAttribOffsets[index]);
}
void setEmpAttrib(Empire* emp, unsigned index, double value) {
if(index >= empAttribOffsets.size())
return;
*(double*)(((char*)emp) + empAttribOffsets[index]) = value;
}
unsigned getEmpAttribIndex(const std::string& str) {
auto it = empAttribNames.find(str);
if(it == empAttribNames.end())
return (unsigned)-1;
return it->second;
}
std::string getEmpAttribName(unsigned id) {
if(id >= empAttribIdents.size())
return "";
return empAttribIdents[id];
}
void buildEmpAttribIndices() {
empAttribNames.clear();
empAttribIdents.clear();
empAttribOffsets.clear();
auto* doubleType = getStateValueType("double");
if(!empStates)
return;
unsigned base = sizeof(Empire);
StateDefinition::align(base);
const StateDefinition& def = *empStates;
for(auto var = def.types.begin(), endvar = def.types.end(); var != endvar; ++var) {
//Bind member
auto& mtype = *var->def;
//Doubles are accessible generically in order to facilitate empire attributes
if(&mtype == doubleType && var->attribute) {
empAttribNames[var->name] = empAttribOffsets.size();
empAttribOffsets.push_back(base + var->offset);
empAttribIdents.push_back(var->name);
}
}
}
void RegisterDynamicTypes(bool server) {
//Bind global object states
{
ClassBind object("Object");
const StateDefinition& def = getStateDefinition("Object");
if(&def != &errorStateDefinition) {
//Add state list vars
unsigned base = sizeof(Object);
StateDefinition::align(base);
for(auto var = def.types.begin(), endvar = def.types.end(); var != endvar; ++var) {
//Bind member
auto& mtype = *var->def;
if(mtype.isParam()) {
if(var->def->returnable()) {
if(var->access != SR_Visible) {
object.addGenericMethod(format("$1 get_$2() const",
mtype.returnType.empty() ? mtype.type : mtype.returnType,
var->name).c_str(),
asFUNCTION(restrictedState), (void*)&*var)
doc("Member created from datafiles.", "");
}
else {
object.addGenericMethod(format("$1 get_$2() const",
mtype.returnType.empty() ? mtype.type : mtype.returnType,
var->name).c_str(),
asFUNCTION(paramStateGet), (void*)&*var)
doc("Member created from datafiles.", "");
}
}
if(server) {
object.addGenericMethod(format("void set_$2($1 value)",
mtype.type, var->name).c_str(),
asFUNCTION(paramStateSet), (void*)&*var)
doc("Member created from datafiles.", "");
}
}
else if(server || var->access == SR_Visible) {
object.addMember(format("$1 $2", mtype.type, var->name).c_str(), base + var->offset)
doc("Member created from datafiles.");
}
else if(var->access == SR_Restricted) {
if(var->def->returnable()) {
object.addGenericMethod(format("$1 get_$2() const",
mtype.returnType.empty() ? mtype.type : mtype.returnType,
var->name).c_str(),
asFUNCTION(restrictedState), (void*)&*var)
doc("Member created from datafiles.", "");
}
}
}
}
}
//Bind each custom object type, adding its state list variables in
EnumBind objType("ObjectType", false);
objType["OT_COUNT"] = objTypeList.size();
for(auto i = objTypeList.begin(), end = objTypeList.end(); i != end; ++i) {
ScriptObjectType* type = *i;
const StateDefinition& def = *type->states;
EnumBind objType("ObjectType", false);
objType[std::string("OT_")+type->name] = type->id;
ClassBind genObj("Object");
ClassBind object(type->name.c_str());
classdoc(object,"Derived Object created based on datafiles. Can be cast to and from an Object@.");
bindObject(object, type, server);
RegisterObjectComponentWrappers(object, server, type);
object.addExternMethod("Object@ opImplCast() const",
asFUNCTION(baseCast));
genObj.addGenericMethod(format("$1@ opCast() const", object.name).c_str(),
asFUNCTION(castObj), type);
genObj.addGenericMethod(format("bool get_is$1() const", object.name).c_str(),
asFUNCTION(isObjectType), type);
//Add state list vars
unsigned base = sizeof(Object);
StateDefinition::align(base);
for(auto var = def.types.begin(), endvar = def.types.end(); var != endvar; ++var) {
//Bind member
auto& mtype = *var->def;
if(mtype.isParam()) {
if(var->def->returnable()) {
if(var->access != SR_Visible) {
object.addGenericMethod(format("$1 get_$2() const",
mtype.returnType.empty() ? mtype.type : mtype.returnType,
var->name).c_str(),
asFUNCTION(restrictedState), (void*)&*var)
doc("Member created from datafiles.", "");
}
else {
object.addGenericMethod(format("$1 get_$2() const",
mtype.returnType.empty() ? mtype.type : mtype.returnType,
var->name).c_str(),
asFUNCTION(paramStateGet), (void*)&*var)
doc("Member created from datafiles.", "");
}
}
if(server) {
object.addGenericMethod(format("void set_$2($1 value)",
mtype.type, var->name).c_str(),
asFUNCTION(paramStateSet), (void*)&*var)
doc("Member created from datafiles.", "");
}
}
else if(server || var->access == SR_Visible) {
object.addMember(format("$1 $2", mtype.type, var->name).c_str(), base + var->offset)
doc("Member created from datafiles.");
}
else if(var->access == SR_Restricted) {
if(var->def->returnable()) {
object.addGenericMethod(format("$1 get_$2() const",
mtype.returnType.empty() ? mtype.type : mtype.returnType,
var->name).c_str(),
asFUNCTION(restrictedState), (void*)&*var)
doc("Member created from datafiles.", "");
}
}
}
}
//Bind game config
{
Namespace ns("config");
for(size_t i = 0; i < gameConfig.count; ++i)
bindGlobal(format("double $1", gameConfig.names[i]).c_str(), (void*)&gameConfig.values[i]);
bind("double get(const string& name)", asFUNCTION(configGet));
bind("void set(const string& name, double value)", asFUNCTION(configSet));
bind("double get(uint index)", asFUNCTION(configGet_id));
bind("void set(uint index, double value)", asFUNCTION(configSet_id));
bind("string getName(uint index)", asFUNCTION(configGetName));
bind("uint getIndex(const string& name)", asFUNCTION(configGetIndex));
}
//Bind empire states
if(empStates) {
const StateDefinition& def = *empStates;
auto* doubleType = getStateValueType("double");
EnumBind attr("EmpireAttribute");
ClassBind emp("Empire");
unsigned base = sizeof(Empire);
StateDefinition::align(base);
bind("uint getEmpireAttribute(const string& name)", asFUNCTION(getEmpAttribIndex));
bind("string getEmpireAttributeName(uint id)", asFUNCTION(getEmpAttribName));
emp.addExternMethod("double get_attributes(uint index) const", asFUNCTION(getEmpAttrib));
if(server)
emp.addExternMethod("void set_attributes(uint index, double value)", asFUNCTION(setEmpAttrib));
emp.addExternMethod("void writeSyncedStates(Message& msg)", asFUNCTION(writeEmpStates));
emp.addExternMethod("void readSyncedStates(Message& msg)", asFUNCTION(readEmpStates));
for(auto var = def.types.begin(), endvar = def.types.end(); var != endvar; ++var) {
//Bind member
auto& mtype = *var->def;
emp.addMember(format("$1 $2", mtype.type, var->name).c_str(), base + var->offset)
doc("Member created from datafiles.");
//Doubles are accessible generically in order to facilitate empire attributes
if(&mtype == doubleType && var->attribute)
attr[std::string("EA_")+var->name] = empAttribNames[var->name];
}
attr["EA_COUNT"] = empAttribNames.size();
}
//Node methods
for(auto i = nodeTypes.begin(), end = nodeTypes.end(); i != end; ++i) {
auto* type = i->second;
ClassBind baseNode("Node");
ClassBind node(type->name.c_str(), asOBJ_REF);
classdoc(node,"Derived Node created based on datafiles. Can be cast to and from a Node@.");
node.addGenericFactory(format("$1@ f()", type->name).c_str(), asFUNCTION(nodeFactory), type);
node.addExternMethod("Node@ opImplCast() const",
asFUNCTION(nodeBaseCast));
baseNode.addGenericMethod(format("$1@ opCast() const", type->name).c_str(),
asFUNCTION(nodeCast), type);
RegisterNodeMethodWrappers(node, server, type);
bindScriptNode(node);
}
}
};