diff --git a/src/p_saveg.c b/src/p_saveg.c index 4fdc3d488..4a414e9e1 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1149,6 +1149,12 @@ static void P_NetUnArchiveWorld(void) if (diff2 & SD_TAG) { size_t ncount = READUINT32(get); + + // Remove entries from global lists. + for (j = 0; j < sectors[i].tags.count; j++) + Taggroup_Remove(tags_sectors, sectors[i].tags.tags[j], i); + + // Reallocate if size differs. if (ncount != sectors[i].tags.count) { sectors[i].tags.count = ncount; @@ -1157,6 +1163,10 @@ static void P_NetUnArchiveWorld(void) for (j = 0; j < ncount; j++) sectors[i].tags.tags[j] = READINT16(get); + + // Add new entries. + for (j = 0; j < sectors[i].tags.count; j++) + Taggroup_Remove(tags_sectors, sectors[i].tags.tags[j], i); } if (diff3 & SD_COLORMAP) diff --git a/src/taglist.c b/src/taglist.c index 1849c314c..3b0135abd 100644 --- a/src/taglist.c +++ b/src/taglist.c @@ -63,58 +63,97 @@ boolean Tag_Compare (const taglist_t* list1, const taglist_t* list2) return true; } -static void Taglist_AddToSectors (const mtag_t tag, const size_t itemid) + +size_t Taggroup_Find (const taggroup_t *group, const size_t id) { - taggroup_t* tagelems; + size_t i; + + if (!group) + return -1; + + for (i = 0; i < group->count; i++) + if (group->elements[i] == id) + return i; + + return -1; +} + +void Taggroup_Add (taggroup_t *garray[], const mtag_t tag, size_t id) +{ + taggroup_t *group; if (tag == MTAG_GLOBAL) return; - if (!tags_sectors[(UINT16)tag]) - tags_sectors[(UINT16)tag] = Z_Calloc(sizeof(taggroup_t), PU_LEVEL, NULL); + group = garray[(UINT16)tag]; - tagelems = tags_sectors[(UINT16)tag]; - tagelems->count++; - tagelems->elements = Z_Realloc(tagelems->elements, tagelems->count * sizeof(size_t), PU_LEVEL, NULL); - tagelems->elements[tagelems->count - 1] = itemid; + // Don't add duplicate entries. + if (Taggroup_Find(group, id) != (size_t)-1) + return; + + // Create group if empty. + if (!group) + group = garray[(UINT16)tag] = Z_Calloc(sizeof(taggroup_t), PU_LEVEL, NULL); + + group->count++; + group->elements = Z_Realloc(group->elements, group->count * sizeof(size_t), PU_LEVEL, NULL); + group->elements[group->count - 1] = id; +} + +void Taggroup_Remove (taggroup_t *garray[], const mtag_t tag, size_t id) +{ + taggroup_t *group; + size_t rempos; + size_t newcount; + + if (tag == MTAG_GLOBAL) + return; + + group = garray[(UINT16)tag]; + + if ((rempos = Taggroup_Find(group, id)) == (size_t)-1) + return; + + // Strip away taggroup if no elements left. + if (!(newcount = --group->count)) + { + Z_Free(group->elements); + Z_Free(group); + garray[(UINT16)tag] = NULL; + } + else + { + size_t *newelements = Z_Malloc(newcount * sizeof(size_t), PU_LEVEL, NULL); + size_t i; + + // Copy the previous entries save for the one to remove. + for (i = 0; i < rempos; i++) + newelements[i] = group->elements[i]; + + for (i = rempos + 1; i < group->count; i++) + newelements[i - 1] = group->elements[i]; + + Z_Free(group->elements); + group->elements = newelements; + group->count = newcount; + } +} + +// Initialization. + +static void Taglist_AddToSectors (const mtag_t tag, const size_t itemid) +{ + Taggroup_Add(tags_sectors, tag, itemid); } static void Taglist_AddToLines (const mtag_t tag, const size_t itemid) { - taggroup_t* tagelems; - - if (tag == MTAG_GLOBAL) - return; - - if (!tags_lines[(UINT16)tag]) - tags_lines[(UINT16)tag] = Z_Calloc(sizeof(taggroup_t), PU_LEVEL, NULL); - - tagelems = tags_lines[(UINT16)tag]; - tagelems->count++; - tagelems->elements = Z_Realloc(tagelems->elements, tagelems->count * sizeof(size_t), PU_LEVEL, NULL); - tagelems->elements[tagelems->count - 1] = itemid; + Taggroup_Add(tags_lines, tag, itemid); } static void Taglist_AddToMapthings (const mtag_t tag, const size_t itemid) { - taggroup_t* tagelems; - - if (tag == MTAG_GLOBAL) - return; - - if (!tags_mapthings[(UINT16)tag]) - tags_mapthings[(UINT16)tag] = Z_Calloc(sizeof(taggroup_t), PU_LEVEL, NULL); - - tagelems = tags_mapthings[(UINT16)tag]; - tagelems->count++; - tagelems->elements = Z_Realloc(tagelems->elements, tagelems->count * sizeof(size_t), PU_LEVEL, NULL); - tagelems->elements[tagelems->count - 1] = itemid; -} - -void Tag_SectorFSet (const size_t id, const mtag_t tag) -{ - sector_t* sec = §ors[id]; - Tag_FSet(&sec->tags, tag); + Taggroup_Add(tags_mapthings, tag, itemid); } void Taglist_InitGlobalTables(void) @@ -144,6 +183,8 @@ void Taglist_InitGlobalTables(void) } } +// Iteration, inagme search. + INT32 Tag_Iterate_Sectors (const mtag_t tag, const size_t p) { if (tag == MTAG_GLOBAL) @@ -217,3 +258,17 @@ INT32 Tag_FindLineSpecial(const INT16 special, const mtag_t tag) } return -1; } + +// Ingame list manipulation. + +void Tag_SectorFSet (const size_t id, const mtag_t tag) +{ + sector_t* sec = §ors[id]; + mtag_t curtag = Tag_FGet(&sec->tags); + if (curtag == tag) + return; + + Taggroup_Remove(tags_sectors, curtag, id); + Taggroup_Add(tags_sectors, tag, id); + Tag_FSet(&sec->tags, tag); +} diff --git a/src/taglist.h b/src/taglist.h index 050bebed7..d1acff6cb 100644 --- a/src/taglist.h +++ b/src/taglist.h @@ -35,6 +35,9 @@ taggroup_t* tags_sectors[MAXTAGS + 1]; taggroup_t* tags_lines[MAXTAGS + 1]; taggroup_t* tags_mapthings[MAXTAGS + 1]; +void Taggroup_Add (taggroup_t *garray[], const mtag_t tag, size_t id); +void Taggroup_Remove (taggroup_t *garray[], const mtag_t tag, size_t id); + void Taglist_InitGlobalTables(void); INT32 Tag_Iterate_Sectors (const mtag_t tag, const size_t p);