(svn r3721) - [3/4] Present the game with a unified structure for the configuration-ini, saveload, console and gui representations of the settings. From part 3 on, OpenTTD is once again compilable.

- Code has been added to the saveload code to honour the SLF_SAVE_NO and SLF_NETWORK_NO flags. SLF_NETWORK_NO just reads in the the bytestream and then discards it because that setting is not synchronised. For this the function SlSkipBytes() has been reinstated
- SAVEGAME_VERSION has been changed from a constant ENUM to a constant integer. This was done for the configuration-code to be able to tell which version of a CONDVAR type to handle. As said before, because settings can be saved to the savegame, they will become conditional at some point. The configuration code always has to read the 'most recent' version.
- GameOptions are saved through the new structure. It is fully compatible with any old savegame...however it is better. Because of the move to this new format we can instruct the loader to skip certain variables. Autosave for example isn't synchronised anymore (in the network). The same goes for currency and kilometers :D. That is the only functionality change this patch is supposed to have if I have written it correctly.
- NOTE! Patches are still not saved so for Multiplayer to work network_client.c and network_server.c needed slight modifications.
pull/155/head
Darkvater 19 years ago
parent 85e0d9c967
commit a9d33943d7

@ -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++;
}
}

@ -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);

@ -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;

@ -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

@ -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}
};

Loading…
Cancel
Save