summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--network_client.c30
-rw-r--r--network_server.c30
-rw-r--r--saveload.c33
-rw-r--r--saveload.h10
-rw-r--r--settings.c70
5 files changed, 129 insertions, 44 deletions
diff --git a/network_client.c b/network_client.c
index f8d88e8fc..83a20de5b 100644
--- a/network_client.c
+++ b/network_client.c
@@ -826,7 +826,7 @@ static NetworkClientPacket* const _network_client_packet[] = {
// If this fails, check the array above with network_data.h
assert_compile(lengthof(_network_client_packet) == PACKET_END);
-extern const SettingDesc patch_settings[];
+extern const SettingDesc _patch_settings[];
// This is a TEMPORARY solution to get the patch-settings
// to the client. When the patch-settings are saved in the savegame
@@ -835,25 +835,25 @@ static void NetworkRecvPatchSettings(NetworkClientState* cs, Packet* p)
{
const SettingDesc *item;
- item = patch_settings;
+ item = _patch_settings;
- while (item->name != NULL) {
- switch (item->flags) {
- case SDT_BOOL:
- case SDT_INT8:
- case SDT_UINT8:
- *(uint8 *)(item->ptr) = NetworkRecv_uint8(cs, p);
+ for (; item->save.cmd != SL_END; item++) {
+ void *var = ini_get_variable(&item->save, &_patches);
+ switch (GetVarMemType(item->save.conv)) {
+ case SLE_VAR_BL:
+ case SLE_VAR_I8:
+ case SLE_VAR_U8:
+ *(uint8 *)(var) = NetworkRecv_uint8(cs, p);
break;
- case SDT_INT16:
- case SDT_UINT16:
- *(uint16 *)(item->ptr) = NetworkRecv_uint16(cs, p);
+ case SLE_VAR_I16:
+ case SLE_VAR_U16:
+ *(uint16 *)(var) = NetworkRecv_uint16(cs, p);
break;
- case SDT_INT32:
- case SDT_UINT32:
- *(uint32 *)(item->ptr) = NetworkRecv_uint32(cs, p);
+ case SLE_VAR_I32:
+ case SLE_VAR_U32:
+ *(uint32 *)(var) = NetworkRecv_uint32(cs, p);
break;
}
- item++;
}
}
diff --git a/network_server.c b/network_server.c
index 095922c10..2c863587d 100644
--- a/network_server.c
+++ b/network_server.c
@@ -1188,7 +1188,7 @@ static NetworkServerPacket* const _network_server_packet[] = {
assert_compile(lengthof(_network_server_packet) == PACKET_END);
-extern const SettingDesc patch_settings[];
+extern const SettingDesc _patch_settings[];
// This is a TEMPORARY solution to get the patch-settings
// to the client. When the patch-settings are saved in the savegame
@@ -1200,25 +1200,25 @@ static void NetworkSendPatchSettings(NetworkClientState* cs)
NetworkSend_uint8(p, MAP_PACKET_PATCH);
// Now send all the patch-settings in a pretty order..
- item = patch_settings;
+ item = _patch_settings;
- while (item->name != NULL) {
- switch (item->flags) {
- case SDT_BOOL:
- case SDT_INT8:
- case SDT_UINT8:
- NetworkSend_uint8(p, *(uint8 *)item->ptr);
+ for (; item->save.cmd != SL_END; item++) {
+ const void *var = ini_get_variable(&item->save, &_patches);
+ switch (GetVarMemType(item->save.conv)) {
+ case SLE_VAR_BL:
+ case SLE_VAR_I8:
+ case SLE_VAR_U8:
+ NetworkSend_uint8(p, *(uint8 *)var);
break;
- case SDT_INT16:
- case SDT_UINT16:
- NetworkSend_uint16(p, *(uint16 *)item->ptr);
+ case SLE_VAR_I16:
+ case SLE_VAR_U16:
+ NetworkSend_uint16(p, *(uint16 *)var);
break;
- case SDT_INT32:
- case SDT_UINT32:
- NetworkSend_uint32(p, *(uint32 *)item->ptr);
+ case SLE_VAR_I32:
+ case SLE_VAR_U32:
+ NetworkSend_uint32(p, *(uint32 *)var);
break;
}
- item++;
}
NetworkSend_Packet(p, cs);
diff --git a/saveload.c b/saveload.c
index 20c27b6c5..206b6f9c1 100644
--- a/saveload.c
+++ b/saveload.c
@@ -25,14 +25,11 @@
#include "town.h"
#include "player.h"
#include "saveload.h"
+#include "network.h"
#include "variables.h"
#include <setjmp.h>
-enum {
- SAVEGAME_VERSION = 21,
-
-};
-
+const uint16 SAVEGAME_VERSION = 21;
uint16 _sl_version; /// the major savegame version identifier
byte _sl_minor_version; /// the minor savegame version, DO NOT USE!
@@ -381,19 +378,14 @@ static void SlCopyBytes(void *ptr, size_t length)
}
}
-#if 0
-/**
- * Read in bytes from the file/data structure but don't do
- * anything with them
- * NOTICE: currently unused
+/** Read in bytes from the file/data structure but don't do
+ * anything with them, discarding them in effect
* @param length The amount of bytes that is being treated this way
*/
static inline void SlSkipBytes(size_t length)
{
- for (; length != 0; length--)
- SlReadByte();
+ for (; length != 0; length--) SlReadByte();
}
-#endif
/* Get the length of the current object */
uint SlGetFieldLength(void) {return _sl.obj_len;}
@@ -570,10 +562,24 @@ void SlArray(void *array, uint length, VarType conv)
static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld)
{
if (_sl_version < sld->version_from || _sl_version > sld->version_to) return false;
+ if (sld->conv & SLF_SAVE_NO) return false;
return true;
}
+/** Are we going to load this variable when loading a savegame or not?
+ * @note If the variable is skipped it is skipped in the savegame
+ * bytestream itself as well, so there is no need to skip it somewhere else */
+static inline bool SlSkipVariableOnLoad(const SaveLoad *sld)
+{
+ if ((sld->conv & SLF_NETWORK_NO) && !_sl.save && _networking && !_network_server) {
+ SlSkipBytes(SlCalcConvMemLen(sld->conv) * sld->length);
+ return true;
+ }
+
+ return false;
+}
+
/**
* Calculate the size of an object.
* @param sld The @SaveLoad description of the object so we know how to manipulate it
@@ -626,6 +632,7 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld)
case SL_STR:
/* CONDITIONAL saveload types depend on the savegame version */
if (!SlIsObjectValidInSavegame(sld)) return false;
+ if (SlSkipVariableOnLoad(sld)) return false;
switch (sld->cmd) {
case SL_VAR: SlSaveLoadConv(ptr, conv); break;
diff --git a/saveload.h b/saveload.h
index e56d25876..077f3c84c 100644
--- a/saveload.h
+++ b/saveload.h
@@ -230,6 +230,16 @@ static inline bool CheckSavegameVersion(uint16 version)
return _sl_version < version;
}
+/** Checks if some version from/to combination falls within the range of the
+ * active savegame version */
+static inline bool SlIsObjectCurrentlyValid(uint16 version_from, uint16 version_to)
+{
+ extern const uint16 SAVEGAME_VERSION;
+ if (SAVEGAME_VERSION < version_from || SAVEGAME_VERSION > version_to) return false;
+
+ return true;
+}
+
/* Get the NumberType of a setting. This describes the integer type
* as it is represented in memory
* @param type VarType holding information about the variable-type
diff --git a/settings.c b/settings.c
index 351d50e7b..862155dc6 100644
--- a/settings.c
+++ b/settings.c
@@ -609,6 +609,8 @@ static void ini_load_settings(IniFile *ini, const SettingDesc *sd, const char *g
const SettingDescBase *sdb = &sd->desc;
const SaveLoad *sld = &sd->save;
+ if (!SlIsObjectCurrentlyValid(sld->version_from, sld->version_to)) continue;
+
// XXX - wtf is this?? (group override?)
s = strchr(sdb->name, '.');
if (s != NULL) {
@@ -673,6 +675,7 @@ static void ini_save_settings(IniFile *ini, const SettingDesc *sd, const char *g
/* If the setting is not saved to the configuration
* file, just continue with the next setting */
+ if (!SlIsObjectCurrentlyValid(sld->version_from, sld->version_to)) continue;
if (sld->conv & SLF_CONFIG_NO) continue;
// XXX - wtf is this?? (group override?)
@@ -1252,6 +1255,71 @@ void SaveToConfig(void)
ini_free(ini);
}
+/** Save and load handler for patches/settings
+ * @param osd SettingDesc struct containing all information
+ * @param object can be either NULL in which case we load global variables or
+ * a pointer to a struct which is getting saved */
+static void LoadSettings(const SettingDesc *osd, void *object)
+{
+ for (; osd->save.cmd != SL_END; osd++) {
+ const SaveLoad *sld = &osd->save;
+ void *ptr = ini_get_variable(sld, object);
+
+ if (!SlObjectMember(ptr, sld)) continue;
+ }
+}
+
+/** Loadhandler for a list of global variables
+ * @note this is actually a stub for LoadSettings with the
+ * object pointer set to NULL */
+static inline void LoadSettingsGlobList(const SettingDescGlobVarList *sdg)
+{
+ LoadSettings((const SettingDesc*)sdg, NULL);
+}
+
+/** Save and load handler for patches/settings
+ * @param osd SettingDesc struct containing all information
+ * @param object can be either NULL in which case we load global variables or
+ * a pointer to a struct which is getting saved */
+static void SaveSettings(const SettingDesc *sd, void *object)
+{
+ /* We need to write the CH_RIFF header, but unfortunately can't call
+ * SlCalcLength() because we have a different format. So do this manually */
+ const SettingDesc *i;
+ size_t length = 0;
+ for (i = sd; i->save.cmd != SL_END; i++) {
+ length += SlCalcObjMemberLength(&i->save);
+ }
+ SlSetLength(length);
+
+ for (i = sd; i->save.cmd != SL_END; i++) {
+ void *ptr = ini_get_variable(&i->save, object);
+ SlObjectMember(ptr, &i->save);
+ }
+}
+
+/** Savehandler for a list of global variables
+ * @note this is actually a stub for SaveSettings with the
+ * object pointer set to NULL */
+static inline void SaveSettingsGlobList(const SettingDescGlobVarList *sdg)
+{
+ SaveSettings((const SettingDesc*)sdg, NULL);
+}
+
+static void Load_OPTS(void)
+{
+ /* Copy over default setting since some might not get loaded in
+ * a networking environment. This ensures for example that the local
+ * autosave-frequency stays when joining a network-server */
+ _opt = _opt_newgame;
+ LoadSettings(_gameopt_settings, &_opt);
+}
+
+static void Save_OPTS(void)
+{
+ SaveSettings(_gameopt_settings, &_opt);
+}
+
void CheckConfig(void)
{
// fix up news_display_opt from old to new
@@ -1273,5 +1341,5 @@ void CheckConfig(void)
}
const ChunkHandler _setting_chunk_handlers[] = {
- { 'OPTS', SaveLoad_OPTS, SaveLoad_OPTS, CH_RIFF | CH_LAST}
+ { 'OPTS', Save_OPTS, Load_OPTS, CH_RIFF | CH_LAST}
};