1 #include <algorithm>
2 #include <cstring>
3 #include <cctype>
4 #include "xr_entity.h"
5 #include "xr_ini_file.h"
6 #include "xr_level_spawn.h"
7 #include "xr_entity_factory.h"
8 #include "xr_file_system.h"
9 #include "syncer.h"
10
11 using namespace xray_re;
12
to_xrai_compat(xr_level_spawn & spawn,const xr_ini_file & ini,const char * section)13 void syncer::to_xrai_compat(xr_level_spawn& spawn, const xr_ini_file& ini, const char* section)
14 {
15 for (xr_entity_vec_it it = spawn.spawns().begin(), end = spawn.spawns().end(); it != end; ++it) {
16 cse_abstract* entity = *it;
17 char clsid[9];
18 entity->clsid().get(clsid);
19 if (ini.line_exist(section, clsid))
20 entity->name() = ini.r_string(section, clsid);
21 entity->version() = CSE_VERSION_2215;
22 entity->script_version() = 2;
23 }
24 }
25
skip_ws(const char * p)26 static inline const char* skip_ws(const char* p)
27 {
28 for (int c; (c = *p) && (c == ' ' || c == '\t'); ++p) {}
29 return p;
30 }
31
skip_name(const char * p)32 static inline const char* skip_name(const char* p)
33 {
34 for (int c; (c = *p); ++p) {
35 if (!std::isalnum(c) && c != '_')
36 break;
37 }
38 return p;
39 }
40
split_link(const char * link_spec,std::string & level_name,std::string & point_name)41 static inline bool split_link(const char* link_spec, std::string& level_name, std::string& point_name)
42 {
43 const char* p = skip_name(link_spec);
44 if (p == link_spec) {
45 // to delete links
46 level_name.clear();
47 point_name.clear();
48 return true;
49 }
50 level_name.assign(link_spec, p);
51 p = skip_ws(p);
52 if (*p++ != ',')
53 return false;
54 p = skip_name(link_spec = skip_ws(p));
55 if (p == link_spec)
56 return false;
57 point_name.assign(link_spec, p);
58 return true;
59 }
60
edit_links(xr_level_spawn & spawn,const xr_ini_file & ini,const char * section)61 void syncer::edit_links(xr_level_spawn& spawn, const xr_ini_file& ini, const char* section)
62 {
63 if (!ini.section_exist(section))
64 return;
65
66 std::string level_name, point_name;
67 for (xr_entity_vec_it it = spawn.spawns().begin(), end = spawn.spawns().end();
68 it != end; ++it) {
69 cse_alife_graph_point* gp = dynamic_cast<cse_alife_graph_point*>(*it);
70 if (gp == 0)
71 continue;
72 const char* name = gp->name_replace().c_str();
73 if (!ini.line_exist(section, name))
74 continue;
75 const char* link_spec = ini.r_string(section, name);
76 if (split_link(link_spec, level_name, point_name)) {
77 gp->connection_level() = level_name;
78 gp->connection_point() = point_name;
79 } else {
80 msg("can't parse link fixup for %s:%s", section, name);
81 }
82 }
83 }
84
operator ()graph_point_pred85 struct graph_point_pred { bool operator()(const cse_abstract* l, const cse_abstract* r) const {
86 const cse_alife_graph_point* gp1 = dynamic_cast<const cse_alife_graph_point*>(l);
87 const cse_alife_graph_point* gp2 = dynamic_cast<const cse_alife_graph_point*>(r);
88 if (gp1 == 0)
89 return gp2 == 0 ? false : true;
90 else if (gp2 == 0)
91 return false;
92 int cmp = gp2->connection_level().compare(gp1->connection_level());
93 if (cmp)
94 return cmp < 0;
95 const fvector3& p1 = l->position();
96 const fvector3& p2 = r->position();
97 return p1.x < p2.x || (p1.x == p2.x && (p1.z < p2.z || (p1.z == p2.z && p1.y < p2.y)));
98 }};
99
dump_links(xr_level_spawn & spawn,xr_writer & w,const char * section)100 void syncer::dump_links(xr_level_spawn& spawn, xr_writer& w, const char* section)
101 {
102 std::sort(spawn.spawns().begin(), spawn.spawns().end(), graph_point_pred());
103 w.w_sf("[%s]\n", section);
104 for (xr_entity_vec_it it = spawn.spawns().begin(), end = spawn.spawns().end(); it != end; ++it) {
105 cse_alife_graph_point* gp = dynamic_cast<cse_alife_graph_point*>(*it);
106 if (gp == 0)
107 continue;
108 w.w_sf("%-32s= ", gp->name_replace().c_str());
109 if (!gp->connection_level().empty()) {
110 w.w_sf("%s", gp->connection_level().c_str());
111 if (!gp->connection_point().empty())
112 w.w_sf(", %s", gp->connection_point().c_str());
113 w.w_sf("\t");
114 }
115 const fvector3& p = gp->position();
116 w.w_sf("; %7.2f %7.2f %7.2f\n", p.x, p.y, p.z);
117 }
118 w.w_sf("\n");
119 }
120
load_graph_points(xr_level_spawn & spawn,const char * path,const char * name) const121 bool syncer::load_graph_points(xr_level_spawn& spawn, const char* path, const char* name) const
122 {
123 xr_file_system& fs = xr_file_system::instance();
124 xr_reader* r = fs.r_open(path, name);
125 if (r == 0)
126 return false;
127 xr_reader* s;
128 for (uint32_t id = 0; (s = r->open_chunk(id)); ++id) {
129 xr_packet packet;
130 s->r_packet(packet, s->size());
131 uint16_t pkt_id;
132 packet.r_begin(pkt_id);
133 xr_assert(pkt_id == M_SPAWN);
134 const char* name = packet.skip_sz();
135 #if 1
136 packet.r_seek(0);
137 cse_abstract* entity = create_entity(name);
138 if (entity && entity->clsid() == "AI_GRAPH") {
139 entity->spawn_read(packet);
140 entity->version() = CSE_VERSION_SOC;
141 entity->script_version() = 6;
142 spawn.spawns().push_back(entity);
143 } else {
144 delete entity;
145 }
146 #else
147 if (std::strcmp(name, "graph_point") == 0) {
148 packet.r_seek(0);
149 cse_abstract* entity = create_entity(name);
150 xr_assert(entity);
151 entity->spawn_read(packet);
152 entity->version() = CSE_VERSION_SOC;
153 entity->script_version() = 6;
154 spawn.spawns().push_back(entity);
155 }
156 #endif
157 r->close_chunk(s);
158 }
159 fs.r_close(r);
160 return true;
161 }
162