#include "godot_scene.h" #include #include #include #include namespace com::fourisland::lingo2_archipelago { namespace { struct Heading { std::string type; std::string id; std::string path; std::string resource_type; std::string name; std::string parent; GodotInstanceType instance_type; }; Heading ParseTscnHeading(std::string_view line) { std::string original_line(line); Heading heading; if (line[0] != '[') { std::ostringstream errormsg; errormsg << "Heading must start with [." << std::endl << "Bad heading: " << original_line; throw std::invalid_argument(errormsg.str()); } line.remove_prefix(1); int divider = line.find_first_of(" ]"); if (divider == std::string_view::npos) { std::ostringstream errormsg; errormsg << "Malformatted heading: " << line << std::endl << "Original line: " << original_line; throw std::invalid_argument(errormsg.str()); } heading.type = std::string(line.substr(0, divider)); line.remove_prefix(divider + 1); while (!line.empty()) { divider = line.find_first_of("="); if (divider == std::string_view::npos) { std::ostringstream errormsg; errormsg << "Malformatted heading: " << line << std::endl << "Original line: " << original_line; throw std::invalid_argument(errormsg.str()); } std::string key(line.substr(0, divider)); line.remove_prefix(divider + 1); if (line[0] == '"') { line.remove_prefix(1); divider = line.find_first_of("\""); if (divider == std::string_view::npos) { std::ostringstream errormsg; errormsg << "Malformatted heading: " << line << std::endl << "Original line: " << original_line; throw std::invalid_argument(errormsg.str()); } std::string strval(line.substr(0, divider)); line.remove_prefix(divider + 2); if (key == "name") { heading.name = strval; } else if (key == "parent") { heading.parent = strval; } else if (key == "path") { heading.path = strval; } else if (key == "type") { heading.resource_type = strval; } else if (key == "id") { heading.id = strval; } } else if (line[0] == 'S' || line[0] == 'E') { GodotInstanceType rrval; char internal = line[0]; line.remove_prefix(13); // SubResource(" divider = line.find_first_of("\""); if (divider == std::string_view::npos) { std::ostringstream errormsg; errormsg << "Malformatted heading: " << line << std::endl << "Original line: " << original_line; throw std::invalid_argument(errormsg.str()); } std::string refid = std::string(line.substr(0, divider)); line.remove_prefix(divider + 3); GodotInstanceType instance_type; if (internal == 'E') { instance_type = GodotExtResourceRef{.id = refid}; } else { // SubResource is not supported right now. } if (key == "instance") { heading.instance_type = instance_type; } else { // Other keys aren't supported right now. } } else { divider = line.find_first_of(" ]"); if (divider == std::string_view::npos) { std::ostringstream errormsg; errormsg << "Malformatted heading: " << line << std::endl << "Original line: " << original_line; throw std::invalid_argument(errormsg.str()); } int numval = std::atoi(line.substr(0, divider).data()); line.remove_prefix(divider + 1); // keyvals_[key] = numval; } } return heading; } } // namespace std::string GodotNode::GetPath() const { if (parent.empty() || parent == ".") { return name; } else { return parent + "/" + name; } } GodotScene ReadGodotSceneFromFile(const std::string& path) { std::map ext_resources; std::vector nodes; std::ifstream input(path); std::string line; bool section_started = false; Heading cur_heading; std::ostringstream cur_value; bool value_started = false; auto handle_end_of_section = [&]() { section_started = false; value_started = false; if (cur_heading.type == "sub_resource") { // sub_resources_[std::get(cur_heading.GetKeyval("id"))] = // {cur_heading, cur_value.str(), ""}; } else { // other_.emplace_back(cur_heading, cur_value.str()); } cur_value = {}; }; while (std::getline(input, line)) { if (section_started && (line.empty() || line[0] == '[')) { handle_end_of_section(); } if (!line.empty() && line[0] == '[') { Heading heading = ParseTscnHeading(line); if (heading.type == "gd_scene") { // file_descriptor_ = heading; } else if (heading.type == "ext_resource") { GodotExtResource ext_resource; ext_resource.path = heading.path; ext_resource.type = heading.resource_type; ext_resources[heading.id] = ext_resource; } else if (heading.type == "node") { if (heading.parent != "") { nodes.push_back(GodotNode{.name = heading.name, .parent = heading.parent, .instance_type = heading.instance_type}); } } else { cur_heading = heading; section_started = true; } } else if (!line.empty()) { if (value_started) { cur_value << std::endl; } else { value_started = true; } cur_value << line; } } if (section_started) { handle_end_of_section(); } return GodotScene(std::move(ext_resources), std::move(nodes)); } } // namespace com::fourisland::lingo2_archipelago '#n62'>62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
doors {
  name: "Obverse White/Orange Door"
  type: EVENT
  panels { room: "Flipped Orange Area" name: "HEAVEN" }
}
doors {
  name: "Obverse White/Blue Door"
  type: EVENT
  panels { room: "Flipped Blue Area" name: "HEAD" }
}
doors {
  name: "Obverse White/Black Door"
  type: EVENT
  panels { room: "Start" name: "FULL" }
}
doors {
  name: "Obverse White/Green Door"
  type: EVENT
  panels { room: "Flipped Green Area" name: "HIGH" }
}
doors {
  name: "Obverse White/Purple Door"
  type: EVENT
  panels { room: "Flipped Purple Area" name: "CEILING" }
}
doors {
  name: "Flipped White/Orange Door"
  type: EVENT
  panels { room: "Obverse Orange Isolated Section" name: "TOP" }
}
doors {
  name: "Flipped White/Purple Door"
  type: EVENT
  panels { room: "Obverse Orange Isolated Section" name: "TOP" }
  # Is this a mistake? It seems like it should be Obverse Purple Area / ABOVE.
}
doors {
  name: "Flipped White/Yellow Door"
  type: EVENT
  panels { room: "Start" name: "ATTIC" }
}
doors {
  name: "Obverse Black/Green Panel"
  type: EVENT
  # The panel blocks your way; there's no door.
  panels { room: "Obverse Black Area" name: "TRAIN" }
}
doors {
  name: "Obverse Black/Yellow Panel"
  type: EVENT
  # The panel blocks your way; there's no door.
  panels { room: "Obverse Black Area" name: "MOUNTAIN" }
}
doors {
  name: "Obverse Black/Pink Door"
  type: EVENT
  panels { room: "Flipped Black Area" name: "SEAPLANE" }
}
doors {
  name: "Flipped Green/Black Door"
  type: EVENT
  panels { room: "Obverse Black Area" name: "TRAIN" }
}
doors {
  name: "Flipped Green/Purple Door"
  type: EVENT
  panels { room: "Obverse Green Area" name: "UPSIDE" }
}
doors {
  name: "Flipped Orange/Brown Door"
  type: EVENT
  panels { room: "Obverse Orange Front Area" name: "UP" }
  panels { room: "Obverse Orange Back Area" name: "OVER" }
}
doors {
  name: "Obverse Blue/Orange Door"
  type: EVENT
  panels { room: "Flipped Blue Area" name: "SKY" }
}
doors {
  name: "Obverse Red/Orange Door"
  type: EVENT
  panels { room: "Flipped Red Area" name: "RAISED" }
}
doors {
  name: "Obverse Purple/Red Door"
  type: EVENT
  panels { room: "Flipped Purple Area" name: "LEAVES" }
}
doors {
  name: "Obverse Yellow/Blue Door"
  type: EVENT
  panels { room: "Flipped Yellow Back Area" name: "ANGELS" }
}
doors {
  name: "Flipped Pink/Yellow Door"
  type: EVENT
  panels { room: "Obverse Pink Area" name: "CLOUD" }
}
doors {
  name: "Flipped Yellow/Black Door"
  type: EVENT
  panels { room: "Obverse Black Area" name: "MOUNTAIN" }
}
doors {
  name: "Flipped Purple/Red Door"
  type: EVENT
  panels { room: "Obverse Purple Area" name: "DRAGON" }
}
doors {
  name: "Flipped Black/Pink Panel"
  type: EVENT
  # The panel blocks your way; there's no door.
  panels { room: "Flipped Black Area" name: "SEAPLANE" }
}