summaryrefslogtreecommitdiff
path: root/newgrf_config.c
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2006-12-27 18:25:17 +0000
committerrubidium <rubidium@openttd.org>2006-12-27 18:25:17 +0000
commit17e8ce42020a9354a1eb61f7488b4e0ac22772dc (patch)
tree17849fbdb250fb405aa70ef3b19b245d9e512ad9 /newgrf_config.c
parentd2ad96dd161157cf977f325fac809c9191188899 (diff)
downloadopenttd-17e8ce42020a9354a1eb61f7488b4e0ac22772dc.tar.xz
(svn r7582) -Fix (r7490): appending static GRFs to the list of to-be loaded GRF for a game could result in duplicate GRFs in that list, which can cause a segmentation fault while loading the GRFs.
Diffstat (limited to 'newgrf_config.c')
-rw-r--r--newgrf_config.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/newgrf_config.c b/newgrf_config.c
index f07e869e9..421333ba8 100644
--- a/newgrf_config.c
+++ b/newgrf_config.c
@@ -131,6 +131,50 @@ GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src)
return dst;
}
+/**
+ * Removes duplicates from lists of GRFConfigs. These duplicates
+ * are introduced when the _grfconfig_static GRFs are appended
+ * to the _grfconfig on a newgame or savegame. As the parameters
+ * of the static GRFs could be different that the parameters of
+ * the ones used non-statically. This can result in desyncs in
+ * multiplayers, so the duplicate static GRFs have to be removed.
+ *
+ * This function _assumes_ that all static GRFs are placed after
+ * the non-static GRFs.
+ *
+ * @param list the list to remove the duplicates from
+ */
+static void RemoveDuplicatesFromGRFConfigList(GRFConfig *list)
+{
+ GRFConfig *prev;
+ GRFConfig *cur;
+
+ if (list == NULL) return;
+
+ for (prev = list, cur = list->next; cur != NULL; prev = cur, cur = cur->next) {
+ if (cur->grfid != list->grfid) continue;
+ assert(HASBIT(cur->flags, GCF_STATIC));
+ prev->next = cur->next;
+ ClearGRFConfig(&cur);
+ cur = prev; // Just go back one so it continues as normal later on
+ }
+
+ RemoveDuplicatesFromGRFConfigList(list->next);
+}
+
+/**
+ * Appends the static GRFs to a list of GRFs
+ * @param dst the head of the list to add to
+ */
+void AppendStaticGRFConfigs(GRFConfig **dst)
+{
+ GRFConfig **tail = dst;
+ while (*tail != NULL) tail = &(*tail)->next;
+
+ CopyGRFConfigList(tail, _grfconfig_static);
+ RemoveDuplicatesFromGRFConfigList(*dst);
+}
+
/* Reset the current GRF Config to either blank or newgame settings */
void ResetGRFConfig(bool defaults)
@@ -138,7 +182,7 @@ void ResetGRFConfig(bool defaults)
GRFConfig **c = &_grfconfig;
if (defaults) c = CopyGRFConfigList(c, _grfconfig_newgame);
- CopyGRFConfigList(c, _grfconfig_static);
+ AppendStaticGRFConfigs(&_grfconfig);
}
@@ -400,6 +444,7 @@ static void Load_NGRF(void)
ClearGRFConfigList(&_grfconfig);
_grfconfig = first;
+ AppendStaticGRFConfigs(&_grfconfig);
}
const ChunkHandler _newgrf_chunk_handlers[] = {