Skip to content

Commit

Permalink
libEGM GMX Persistent Ids (#1989)
Browse files Browse the repository at this point in the history
* Use persistent ids across a GMX.
* First instance id in GM classic is actually 100001
* First tile id is 10000001 confirmed by Rusky
  • Loading branch information
RobertBColton committed Aug 6, 2020
1 parent cfabdf2 commit 2e697aa
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 31 deletions.
32 changes: 15 additions & 17 deletions CommandLine/libEGM/gmx.cpp
Expand Up @@ -37,8 +37,8 @@ namespace gmx {
std::ostream outputStream(nullptr);
std::ostream errorStream(nullptr);

void PackBuffer(const LookupMap& resMap, std::string type, std::string res, int &id, google::protobuf::Message *m, std::string gmxPath);
void PackRes(const LookupMap& resMap, std::string &dir, int id, pugi::xml_node &node, google::protobuf::Message *m, int depth);
void PackBuffer(const LookupMap& resMap, std::string type, std::string res, std::unordered_map<std::string, int>& ids, google::protobuf::Message *m, std::string gmxPath);
void PackRes(const LookupMap& resMap, std::string &dir, std::unordered_map<std::string, int>& ids, pugi::xml_node &node, google::protobuf::Message *m, int depth);

namespace {

Expand Down Expand Up @@ -120,9 +120,9 @@ class gmx_root_walker {
for (auto parent = std::next(nodes.begin()); parent != nodes.end(); ++parent) {
groupPath += (*parent)->name() + "/";
}
PackRes(idLookup, groupPath, idMap[resType], xmlNode, res, 0);
PackRes(idLookup, groupPath, idMap, xmlNode, res, 0);
} else {
PackBuffer(idLookup, resType, xmlNode.value(), idMap[resType], res, gmxPath);
PackBuffer(idLookup, resType, xmlNode.value(), idMap, res, gmxPath);
}
return;
}
Expand Down Expand Up @@ -262,7 +262,7 @@ void PackShader(std::string fName, int id, buffers::resources::Shader *shader) {
}
}

void PackRes(const LookupMap& resMap, std::string &dir, int id, pugi::xml_node &node, google::protobuf::Message *m, int depth) {
void PackRes(const LookupMap& resMap, std::string &dir, std::unordered_map<std::string, int>& ids, pugi::xml_node &node, google::protobuf::Message *m, int depth) {
const google::protobuf::Descriptor *desc = m->GetDescriptor();
const google::protobuf::Reflection *refl = m->GetReflection();
for (int i = 0; i < desc->field_count(); i++) {
Expand All @@ -272,7 +272,7 @@ void PackRes(const LookupMap& resMap, std::string &dir, int id, pugi::xml_node &
const google::protobuf::FieldOptions opts = field->options();

if (field->name() == "id") {
id += opts.GetExtension(buffers::id_start);
int id = opts.GetExtension(buffers::id_start) + ids[m->GetTypeName()]++;
outputStream << "Setting " << field->name() << " (" << field->type_name() << ") as " << id << std::endl;
refl->SetInt32(m, field, id);
} else {
Expand Down Expand Up @@ -306,12 +306,11 @@ void PackRes(const LookupMap& resMap, std::string &dir, int id, pugi::xml_node &

if (string_ends_with(gmxName, "action")) {
std::vector<Action> actions;
int cid = 0;
for (pugi::xml_node n = child.first_element_by_path(gmxName.c_str()); n != nullptr; n = n.next_sibling()) {
if (strcmp(n.name(), "action") == 0) { // skip over any siblings that aren't twins <foo/><bar/><foo/> <- bar would be skipped
n.append_attribute("visited") = "true";
Action action;
PackRes(resMap, dir, cid++, n, &action, depth + 1);
PackRes(resMap, dir, ids, n, &action, depth + 1);
actions.emplace_back(action);
}
}
Expand Down Expand Up @@ -353,13 +352,12 @@ void PackRes(const LookupMap& resMap, std::string &dir, int id, pugi::xml_node &

switch (field->cpp_type()) {
case CppType::CPPTYPE_MESSAGE: {
int cid = 0;
for (pugi::xml_node n = child; n != nullptr; n = n.next_sibling()) {
if (n.name() ==
alias) { // skip over any siblings that aren't twins <foo/><bar/><foo/> <- bar would be skipped
n.append_attribute("visited") = "true";
google::protobuf::Message *msg = refl->AddMessage(m, field);
PackRes(resMap, dir, cid++, n, msg, depth + 1);
PackRes(resMap, dir, ids, n, msg, depth + 1);
}
}
break;
Expand Down Expand Up @@ -410,7 +408,7 @@ void PackRes(const LookupMap& resMap, std::string &dir, int id, pugi::xml_node &
// If field is a singular message we need to recurse into this method again
case CppType::CPPTYPE_MESSAGE: {
google::protobuf::Message *msg = refl->MutableMessage(m, field);
PackRes(resMap, dir, 0, child, msg, depth + 1);
PackRes(resMap, dir, ids, child, msg, depth + 1);
break;
}
case CppType::CPPTYPE_INT32: {
Expand Down Expand Up @@ -474,19 +472,19 @@ void PackRes(const LookupMap& resMap, std::string &dir, int id, pugi::xml_node &
}
}

void PackBuffer(const LookupMap& resMap, std::string type, std::string res, int &id, google::protobuf::Message *m, std::string gmxPath) {
void PackBuffer(const LookupMap& resMap, std::string type, std::string res, std::unordered_map<std::string, int>& ids, google::protobuf::Message *m, std::string gmxPath) {
// Scripts and Shaders are plain text not xml
std::string fName = gmxPath + string_replace_all(res, "\\", "/");
std::string resName = fName.substr(fName.find_last_of('/') + 1, fName.length() - 1);
resName = resName.substr(0, resName.find_last_of('.'));

if (type == "script") {
buffers::resources::Script script;
PackScript(fName, id++, &script);
PackScript(fName, ids[script.GetTypeName()]++, &script);
m->CopyFrom(*static_cast<google::protobuf::Message *>(&script));
} else if (type == "shader") {
buffers::resources::Shader shader;
PackShader(fName, id++, &shader);
PackShader(fName, ids[shader.GetTypeName()]++, &shader);
m->CopyFrom(*static_cast<google::protobuf::Message *>(&shader));
} else {
std::string fileExt = type;
Expand All @@ -503,7 +501,7 @@ void PackBuffer(const LookupMap& resMap, std::string type, std::string res, int
outputStream << "Parsing " << fName << "..." << std::endl;
// Start a resource (sprite, object, room)
std::string dir = fName.substr(0, fName.find_last_of("/"));
PackRes(resMap, dir, id++, root, m, 0);
PackRes(resMap, dir, ids, root, m, 0);

visited_walker walker;
doc.traverse(walker);
Expand Down Expand Up @@ -558,9 +556,9 @@ T* LoadResource(std::string fName, std::string type) {
if (resType != type || resName.empty()) // trying to load wrong type (eg a.gmx has <b> instead of <a> as root xml)
return nullptr;

int id = 0;
std::unordered_map<std::string, int> ids;
T* res = new T();
PackBuffer(LookupMap(), resType, resName, id, res, dir);
PackBuffer(LookupMap(), resType, resName, ids, res, dir);
return res;
}

Expand Down
Expand Up @@ -53,12 +53,12 @@ gtest_expect_eq(position_free(x,y),0);&#13;
&#13;
gtest_expect_eq(position_empty(122,122),1);&#13;
gtest_expect_eq(position_meeting(48,48,obj_player),1);&#13;
gtest_expect_eq(collision_rectangle(16,16,80,80,obj_player,1,0),100000);&#13;
gtest_expect_eq(collision_line(16,10,80,80,obj_player,1,0),100000);&#13;
gtest_expect_eq(collision_point(40,56,obj_player,1,0),100000);&#13;
gtest_expect_eq(collision_circle(44,52,3,obj_player,1,0),100000);&#13;
gtest_expect_eq(collision_ellipse(40,40,54,54,obj_player,1,0),100000);&#13;
gtest_expect_eq(instance_position(48,48,obj_player),100000);&#13;
gtest_expect_eq(collision_rectangle(16,16,80,80,obj_player,1,0),100001);&#13;
gtest_expect_eq(collision_line(16,10,80,80,obj_player,1,0),100001);&#13;
gtest_expect_eq(collision_point(40,56,obj_player,1,0),100001);&#13;
gtest_expect_eq(collision_circle(44,52,3,obj_player,1,0),100001);&#13;
gtest_expect_eq(collision_ellipse(40,40,54,54,obj_player,1,0),100001);&#13;
gtest_expect_eq(instance_position(48,48,obj_player),100001);&#13;
&#13;
gtest_expect_eq(distance_to_point(33,32),1);&#13;
alarm[0] = 1;</string>
Expand All @@ -83,11 +83,11 @@ alarm[0] = 1;</string>
<arguments>
<argument>
<kind>1</kind>
<string>gtest_expect_eq(instance_position(128,48,obj_enemy),100002);&#13;
<string>gtest_expect_eq(instance_position(128,48,obj_enemy),100003);&#13;
position_destroy_solid(128,48);&#13;
gtest_expect_eq(instance_position(128,48,obj_enemy),noone);&#13;
instance_create(224,224,obj_enemy);&#13;
gtest_expect_eq(instance_position(224,224,obj_enemy),100003);&#13;
gtest_expect_eq(instance_position(224,224,obj_enemy),100004);&#13;
position_destroy(224,224);&#13;
gtest_expect_eq(instance_position(224,224,obj_enemy),noone);&#13;
&#13;
Expand All @@ -103,11 +103,11 @@ y = 212;&#13;
instance_deactivate_region(16,96,32,32,1,1);&#13;
gtest_expect_eq(instance_position(48,128,obj_enemy),noone);&#13;
instance_activate_region(16,96,32,32,1);&#13;
gtest_expect_eq(instance_position(48,128,obj_enemy),100004);&#13;
gtest_expect_eq(instance_position(48,128,obj_enemy),100005);&#13;
instance_deactivate_circle(48,96,6,1,1);&#13;
gtest_expect_eq(instance_position(48,96,obj_enemy),noone);&#13;
instance_activate_circle(48,96,6,1);&#13;
gtest_expect_eq(instance_position(48,128,obj_enemy),100004);&#13;
gtest_expect_eq(instance_position(48,128,obj_enemy),100005);&#13;
&#13;
game_end();</string>
</argument>
Expand All @@ -133,7 +133,7 @@ game_end();</string>
<kind>1</kind>
<string>position_change(128,128,obj_change,1);&#13;
gtest_expect_eq(instance_exists(obj_change),1);&#13;
gtest_expect_eq(instance_position(128,128,obj_change),100001);&#13;
gtest_expect_eq(instance_position(128,128,obj_change),100002);&#13;
gtest_expect_eq(instance_position(128,128,obj_enemy),noone);&#13;
&#13;
//Check destroying objects at position&#13;
Expand All @@ -142,7 +142,7 @@ gtest_expect_eq(instance_position(128,128,obj_change),noone);&#13;
object_set_solid(obj_enemy,1);&#13;
instance_create(128,48,obj_enemy);&#13;
gtest_expect_eq(distance_to_object(obj_enemy),48);
gtest_expect_eq(instance_position(128,48,obj_enemy),100002);&#13;
gtest_expect_eq(instance_position(128,48,obj_enemy),100003);&#13;
alarm[1] = 1;</string>
</argument>
</arguments>
Expand Down
4 changes: 2 additions & 2 deletions shared/protos/Room.proto
Expand Up @@ -59,7 +59,7 @@ message Room {

message Instance {
optional string name = 1;
optional int32 id = 2 [(id_start) = 100000];
optional int32 id = 2 [(id_start) = 100001];
optional string object_type = 3 [(resource_ref)="object", (gmx) = "objName"];
optional double x = 4;
optional double y = 5;
Expand All @@ -84,7 +84,7 @@ message Room {

message Tile {
optional string name = 1;
optional int32 id = 2 [(id_start) = 10000000];
optional int32 id = 2 [(id_start) = 10000001];
optional string background_name = 3 [(resource_ref)="background", (gmx) = "bgName"];
optional double x = 4;
optional double y = 5;
Expand Down

0 comments on commit 2e697aa

Please sign in to comment.