summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2016-12-20 12:41:28 +0100
committerPaweł Redman <pawel.redman@gmail.com>2016-12-20 12:41:28 +0100
commite36571c70ca3abb639ef64bf6f5c924ca19e4ffa (patch)
tree3d28e63c8710477c3314f2bb9ba44bf3942b463a
parent30330c305545e1b93acd2ec7b72df7673bde9181 (diff)
Implement map postprocessing fully.
Postprocessing removes info_* and team_* entities from all maps but the master (the first one in the command line) and (optionally) prefixes all targets and targetnames with a prefix (set by mapcat_prefix in the master worldspawn).
-rw-r--r--src/common.h1
-rw-r--r--src/main.c9
-rw-r--r--src/mapcat.c79
3 files changed, 88 insertions, 1 deletions
diff --git a/src/common.h b/src/common.h
index b005e2b..8acf3ba 100644
--- a/src/common.h
+++ b/src/common.h
@@ -132,5 +132,6 @@ void map_init(map_t *map);
void map_free(map_t *map);
int map_read(map_t *map, const char *path);
int map_write(const map_t *map, const char *path);
+int map_postprocess(map_t *map, bool filter_team_ents);
int map_merge(map_t *master, map_t *slave);
void map_print_stats(const char *path, const map_t *map);
diff --git a/src/main.c b/src/main.c
index 1b903d6..838afb5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -108,7 +108,7 @@ int main(int argc, char **argv)
map_init(&map);
- elist_for (input, inputs, list) {
+ elist_for(input, inputs, list) {
map_t part;
map_init(&part);
@@ -121,6 +121,13 @@ int main(int argc, char **argv)
if (!quiet)
map_print_stats(input->path, &part);
+ // team_* and info_* ents are kept only in the first part
+ if (map_postprocess(&part, (input != inputs))) {
+ map_free(&map);
+ map_free(&part);
+ goto out;
+ }
+
if (map_merge(&map, &part)) {
error("error: couldn't merge %s into %s\n",
input->path, output);
diff --git a/src/mapcat.c b/src/mapcat.c
index b33a694..7968586 100644
--- a/src/mapcat.c
+++ b/src/mapcat.c
@@ -617,6 +617,83 @@ out:
return rv;
}
+int map_postprocess(map_t *map, bool filter_team_ents)
+{
+ entity_t *entity;
+ entity_key_t *key;
+ char *prefix = NULL;
+
+ if (filter_team_ents) {
+ entity_t *next;
+
+ for (entity = map->entities; entity; entity = next) {
+ next = elist_next(entity, list);
+
+ if (strncmp(entity->classname, "team_", 5) &&
+ strncmp(entity->classname, "info_", 5))
+ continue;
+
+ map->num_discarded_entities++;
+ elist_unlink(&map->entities, entity, list);
+ free_entity(entity);
+ }
+ }
+
+ if (map->worldspawn) {
+ entity_key_t *next;
+
+ for (key = map->worldspawn->keys; key; key = next) {
+ next = elist_next(key, list);
+
+ if (!strcmp(key->key, "mapcat_prefix")) {
+ // shouldn't happen, but just in case
+ // (to prevent memory leaks)
+ if (prefix)
+ free(prefix);
+
+ prefix = key->value;
+ elist_unlink(&map->worldspawn->keys, key, list);
+ free(key->key);
+ // key->value is freed later (as prefix)
+ free(key);
+ }
+ }
+ }
+
+ if (prefix) {
+ size_t prefix_len = strlen(prefix);
+
+ elist_for(entity, map->entities, list)
+ elist_for(key, entity->keys, list) {
+ char *new;
+ size_t value_len;
+
+ if (strcmp(key->key, "target") &&
+ strcmp(key->key, "targetname"))
+ continue;
+
+ value_len = strlen(key->value);
+
+ new = malloc(value_len + prefix_len + 1);
+ if (!new) {
+ fprintf(stderr, "error: out of memory\n");
+ return 1;
+ }
+
+ memcpy(new, prefix, prefix_len);
+ memcpy(new + prefix_len, key->value, value_len);
+ new[prefix_len + value_len] = 0;
+
+ free(key->value);
+ key->value = new;
+ }
+
+ free(prefix);
+ }
+
+ return 0;
+}
+
//RETURN VALUE
// always 0 (this function cannot fail (yet))
// slave is left in invalid state after this function returns, do not use it
@@ -643,6 +720,8 @@ int map_merge(map_t *master, map_t *slave)
master->num_discarded_entities += slave->num_discarded_entities;
master->num_brushes += slave->num_brushes;
master->num_discarded_brushes += slave->num_discarded_brushes;
+ master->num_patches += slave->num_patches;
+ master->num_discarded_patches += slave->num_discarded_patches;
return 0;
}