diff --git bauer/tree_builder.cc bauer/tree_builder.cc index 71adc8b4b..6ad6262e2 100644 --- bauer/tree_builder.cc +++ bauer/tree_builder.cc @@ -26,6 +26,7 @@ static const uint8 tree_age_index[(baum_t::AGE_LIMIT >> 6) + 1] = vector_tpl tree_builder_t::tree_list(0); weighted_vector_tpl tree_builder_t::tree_list_per_climate[MAX_CLIMATES]; stringhashtable_tpl tree_builder_t::desc_table; +vector_tpl tree_builder_t::loaded_tree_names; /// Quick lookup of an image, assuring always five seasons and five ages. @@ -343,3 +344,33 @@ bool tree_builder_t::spawn_tree_near(const baum_t *tree, int radius) return plant_tree_on_coordinate(k, tree->get_desc(), true, false); } + +void tree_builder_t::rdwr_tree_ids(loadsave_t *file) +{ + xml_tag_t tag(file, "tree_ids"); + + uint8 num_trees = tree_list.get_count()-1; + file->rdwr_byte(num_trees); + + if (file->is_loading()) { + loaded_tree_names.clear(); + plainstring str; + + for (uint8 i = 0; i < num_trees; ++i) { + file->rdwr_str(str); + loaded_tree_names.append(str); + } + } + else { + for (uint8 i = 0; i < num_trees; ++i) { + plainstring str = tree_list[i]->get_name(); + file->rdwr_str(str); + } + } +} + + +const char *tree_builder_t::get_loaded_desc_name(uint8 loaded_id) +{ + return (loaded_id < loaded_tree_names.get_count()) ? loaded_tree_names[loaded_id].c_str() : NULL; +} diff --git bauer/tree_builder.h bauer/tree_builder.h index 2ef39943f..f69e65d47 100644 --- bauer/tree_builder.h +++ bauer/tree_builder.h @@ -11,6 +11,8 @@ #include "../tpl/weighted_vector_tpl.h" #include "../tpl/vector_tpl.h" +#include "../utils/plainstring.h" + #include "../dataobj/koord.h" #include "../display/simimg.h" @@ -27,7 +29,15 @@ private: static vector_tpl tree_list; ///< Mapping tree_id -> desc static weighted_vector_tpl tree_list_per_climate[MAX_CLIMATES]; ///< index vector into tree_list, accessible per climate + static vector_tpl loaded_tree_names; + public: + static void rdwr_tree_ids(loadsave_t *file); + + /// When loading a save which was saved with a different set of tree paks + /// the loaded ID is different from the real tree ID. + static const char *get_loaded_desc_name(uint8 loaded_id); + static const tree_desc_t *get_desc_by_name(const char * tree_name) { return desc_table.get(tree_name); } static const tree_desc_t *get_desc_by_id(uint8 tree_id) { return tree_id < get_num_trees() ? tree_list[tree_id] : NULL; } static uint8 get_id_by_desc(const tree_desc_t *desc) { return tree_list.index_of(desc); } diff --git boden/boden.cc boden/boden.cc index 265aafbb1..e8f2e8c21 100644 --- boden/boden.cc +++ boden/boden.cc @@ -22,8 +22,8 @@ boden_t::boden_t(loadsave_t *file, koord pos ) : grund_t( koord3d(pos,0) ) { grund_t::rdwr( file ); - // restoring trees (disadvantage: loosing offsets but much smaller savegame footprint) - if( file->is_version_atleast(110, 1) ) { + if( file->is_version_atleast(110, 1) && file->is_version_less(122, 2) ) { + // restoring trees (disadvantage: losing offsets but much smaller savegame footprint) sint16 id = file->rd_obj_id(); while( id!=-1 ) { sint32 age; @@ -54,8 +54,8 @@ void boden_t::rdwr(loadsave_t *file) { grund_t::rdwr(file); - if( file->is_version_atleast(110, 1) ) { - // a server send the smallest possible savegames to clients, i.e. saves only types and age of trees + if( file->is_version_atleast(110, 1) && file->is_version_less(122, 2) ) { + // a server sends the smallest possible savegames to clients, i.e. saves only types and age of trees if( env_t::server && !hat_wege() ) { for( uint8 i=0; iget_typ()==obj_t::gebaeude && ((gebaeude_t *)new_obj)->get_fabrik()) // things with convoi will not be saved || (new_obj->get_typ()>=66 && new_obj->get_typ()<82) - || (env_t::server && new_obj->get_typ()==obj_t::baum && file->is_version_atleast(110, 1)) + || (env_t::server && new_obj->get_typ()==obj_t::baum && (file->is_version_atleast(110, 1) && file->is_version_less(122, 2))) ) { // these objects are simply not saved } diff --git obj/baum.cc obj/baum.cc index 5033b888c..bbbbf6511 100644 --- obj/baum.cc +++ obj/baum.cc @@ -78,49 +78,88 @@ void baum_t::rdwr(loadsave_t *file) { xml_tag_t d( file, "baum_t" ); - obj_t::rdwr(file); + if (file->is_version_atleast(122, 2)) { + // don't use obj_t::rdwr here, we don't want to rdwr the owner (trees are always unowned) + sint8 byte = (sint8)(((sint16)16*(sint16)get_xoff())/OBJECT_OFFSET_STEPS); + file->rdwr_byte(byte); + set_xoff((sint8)(((sint16)byte*OBJECT_OFFSET_STEPS)/16)); + byte = (sint8)(((sint16)16*(sint16)get_yoff())/OBJECT_OFFSET_STEPS); + file->rdwr_byte(byte); + set_yoff((sint8)(((sint16)byte*OBJECT_OFFSET_STEPS)/16)); + + uint16 data = zoff << 12 | get_age(); + file->rdwr_short(data); + zoff = data >> 12; + geburt = welt->get_current_month() - (data & 0xFFF); + + file->rdwr_byte(tree_id); + + if (file->is_loading()) { + // paks might have changed, make sure we still have this tree + const char *old_name = tree_builder_t::get_loaded_desc_name(tree_id); + const tree_desc_t *desc = NULL; + + if (old_name) { + desc = tree_builder_t::get_desc_by_name( old_name ); + if( !desc ) { + desc = tree_builder_t::get_desc_by_name( translator::compatibility_name(old_name) ); + } + } - uint32 age = get_age() << 18; - file->rdwr_long(age); + if( desc ) { + tree_id = tree_builder_t::get_id_by_desc( desc ); + } + else { + // not a tree / pak missing + tree_id = tree_builder_t::get_num_trees(); + } + } + } + else { + obj_t::rdwr(file); - // after loading, calculate anew - age &= 0xFFF << 18; - geburt = welt->get_current_month() - (age>>18); + uint32 age = get_age() << 18; + file->rdwr_long(age); - if(file->is_loading()) { - char buf[128]; - file->rdwr_str(buf, lengthof(buf)); + // after loading, calculate anew + age &= 0xFFF << 18; + geburt = welt->get_current_month() - (age>>18); - const tree_desc_t *desc = tree_builder_t::get_desc_by_name( buf ); - if( !desc ) { - desc = tree_builder_t::get_desc_by_name( translator::compatibility_name(buf) ); - } + if(file->is_loading()) { + char buf[128]; + file->rdwr_str(buf, lengthof(buf)); - if( desc ) { - tree_id = tree_builder_t::get_id_by_desc( desc ); + const tree_desc_t *desc = tree_builder_t::get_desc_by_name( buf ); + if( !desc ) { + desc = tree_builder_t::get_desc_by_name( translator::compatibility_name(buf) ); + } + + if( desc ) { + tree_id = tree_builder_t::get_id_by_desc( desc ); + } + else { + // not a tree + tree_id = tree_builder_t::get_num_trees(); + } } else { - // not a tree - tree_id = tree_builder_t::get_num_trees(); + const char *c = get_desc()->get_name(); + file->rdwr_str(c); } - } - else { - const char *c = get_desc()->get_name(); - file->rdwr_str(c); - } - // z-offset - if(file->is_version_atleast(111, 1)) { - uint8 zoff_ = zoff; - file->rdwr_byte(zoff_); - zoff = zoff_; - } - else { - // correct z-offset - if(file->is_loading()) { - // this will trigger recalculation of offset in finish_rd() - // we cant call calc_off() since this->pos is still invalid - set_xoff(-128); + // z-offset + if(file->is_version_atleast(111, 1)) { + uint8 zoff_ = zoff; + file->rdwr_byte(zoff_); + zoff = zoff_; + } + else { + // correct z-offset + if(file->is_loading()) { + // this will trigger recalculation of offset in finish_rd() + // we cant call calc_off() since this->pos is still invalid + set_xoff(-128); + } } } } diff --git simversion.h simversion.h index 668652939..b432cc9ed 100644 --- simversion.h +++ simversion.h @@ -23,8 +23,8 @@ // Beware: SAVEGAME minor is often ahead of version minor when there were patches. // ==> These have no direct connection at all! -#define SIM_SAVE_MINOR 1 -#define SIM_SERVER_MINOR 1 +#define SIM_SAVE_MINOR 2 +#define SIM_SERVER_MINOR 2 // NOTE: increment before next release to enable save/load of new features #define MAKEOBJ_VERSION "60.5" diff --git simworld.cc simworld.cc index 048678e17..22ce58d9c 100644 --- simworld.cc +++ simworld.cc @@ -5609,6 +5609,12 @@ void karte_t::rdwr_gamestate(loadsave_t *file, loadingscreen_t *ls) active_player_nr = 0; } + // rdwr tree ID mapping to restore tree IDs + if (file->is_version_atleast(122, 2)) { + DBG_MESSAGE("karte_t::rdwr_gamestate()", "rdwr tree IDs"); + tree_builder_t::rdwr_tree_ids(file); + } + // rdwr static states senke_t::static_rdwr(file);