[Freeciv-Dev] (PR#9123) Save unit types by names
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: |
undisclosed-recipients: ; |
Subject: |
[Freeciv-Dev] (PR#9123) Save unit types by names |
From: |
"Mateusz Stefek" <mstefek@xxxxxxxxx> |
Date: |
Sun, 27 Jun 2004 01:05:12 -0700 |
Reply-to: |
rt@xxxxxxxxxxx |
<URL: http://rt.freeciv.org/Ticket/Display.html?id=9123 >
After adding worker unit Diplomats from old savegames became nukes!!
And generally all units are read wrong.
To avoid such problems in the future I wrote a patch which saves unit
types by name. Old field "type" is still supported for backward
compatibility.
Same thing is needed for the following:
-City improvements
-Worklists
-research & techs
I'll try to implement this
--
mateusz
diff -ur -Xdiff_ignore freeorig/common/unittype.c freeciv/common/unittype.c
--- freeorig/common/unittype.c 2004-05-11 08:26:52.000000000 +0200
+++ freeciv/common/unittype.c 2004-06-26 16:55:16.000000000 +0200
@@ -239,6 +239,13 @@
/**************************************************************************
...
**************************************************************************/
+const char *unit_name_orig(Unit_Type_id id)
+{
+ return (unit_types[id].name_orig);
+}
+/**************************************************************************
+...
+**************************************************************************/
const char *get_unit_name(Unit_Type_id id)
{
struct unit_type *ptype;
@@ -363,6 +370,20 @@
}
/**************************************************************************
+Does a linear search of unit_types[].name_orig
+Returns U_LAST if none match.
+**************************************************************************/
+Unit_Type_id find_unit_type_by_name_orig(const char *s)
+{
+ unit_type_iterate(i) {
+ if (strcmp(unit_types[i].name_orig, s)==0)
+ return i;
+ } unit_type_iterate_end;
+
+ return U_LAST;
+}
+
+/**************************************************************************
Convert unit_move_type names to enum; case insensitive;
returns 0 if can't match.
**************************************************************************/
diff -ur -Xdiff_ignore freeorig/common/unittype.h freeciv/common/unittype.h
--- freeorig/common/unittype.h 2004-04-15 17:14:06.000000000 +0200
+++ freeciv/common/unittype.h 2004-06-26 16:55:53.000000000 +0200
@@ -238,6 +238,7 @@
int unit_pop_value(Unit_Type_id id);
const char *unit_name(Unit_Type_id id);
+const char *unit_name_orig(Unit_Type_id id);
const char *unit_class_name(Unit_Class_id id);
const char *get_unit_name(Unit_Type_id id);
@@ -253,6 +254,7 @@
const Unit_Type_id from, const Unit_Type_id to);
Unit_Type_id find_unit_type_by_name(const char *s);
+Unit_Type_id find_unit_type_by_name_orig(const char *s);
enum unit_move_type unit_move_type_from_str(const char *s);
Unit_Class_id unit_class_from_str(const char *s);
diff -ur -Xdiff_ignore freeorig/server/savegame.c freeciv/server/savegame.c
--- freeorig/server/savegame.c 2004-06-26 15:08:32.000000000 +0200
+++ freeciv/server/savegame.c 2004-06-26 17:38:52.000000000 +0200
@@ -181,6 +181,8 @@
static const char hex_chars[] = "0123456789abcdef";
static const char terrain_chars[] = "adfghjm prstu";
+static void load_player_units(struct player *plr, int plrno,
+ struct section_file *file);
/***************************************************************
This returns an ascii hex value of the given half-byte of the binary
integer. See ascii_hex2bin().
@@ -676,10 +678,9 @@
static void player_load(struct player *plr, int plrno,
struct section_file *file)
{
- int i, j, x, y, nunits, ncities, c_s;
+ int i, j, x, y, ncities, c_s;
const char *p;
char *savefile_options = secfile_lookup_str(file, "savefile.options");
- enum unit_activity activity;
struct ai_data *ai;
server_player_init(plr, TRUE);
@@ -1130,19 +1131,183 @@
city_list_insert_back(&plr->cities, pcity);
}
+ load_player_units(plr, plrno, file);
+
+ if (section_file_lookup(file, "player%d.attribute_v2_block_length", plrno)) {
+ int raw_length1, raw_length2, part_nr, parts;
+ size_t quoted_length;
+ char *quoted;
+
+ raw_length1 =
+ secfile_lookup_int(file, "player%d.attribute_v2_block_length", plrno);
+ if (plr->attribute_block.data) {
+ free(plr->attribute_block.data);
+ plr->attribute_block.data = NULL;
+ }
+ plr->attribute_block.data = fc_malloc(raw_length1);
+ plr->attribute_block.length = raw_length1;
+
+ quoted_length = secfile_lookup_int
+ (file, "player%d.attribute_v2_block_length_quoted", plrno);
+ quoted = fc_malloc(quoted_length + 1);
+ quoted[0] = 0;
+
+ parts =
+ secfile_lookup_int(file, "player%d.attribute_v2_block_parts", plrno);
+
+ for (part_nr = 0; part_nr < parts; part_nr++) {
+ char *current = secfile_lookup_str(file,
+
"player%d.attribute_v2_block_data.part%d",
+ plrno, part_nr);
+ if (!current)
+ break;
+ freelog(LOG_DEBUG, "quoted_length=%lu quoted=%lu current=%lu",
+ (unsigned long) quoted_length,
+ (unsigned long) strlen(quoted),
+ (unsigned long) strlen(current));
+ assert(strlen(quoted) + strlen(current) <= quoted_length);
+ strcat(quoted, current);
+ }
+ if (quoted_length != strlen(quoted)) {
+ freelog(LOG_NORMAL, "quoted_length=%lu quoted=%lu",
+ (unsigned long) quoted_length,
+ (unsigned long) strlen(quoted));
+ assert(0);
+ }
+
+ raw_length2 =
+ unquote_block(quoted,
+ plr->attribute_block.data,
+ plr->attribute_block.length);
+ assert(raw_length1 == raw_length2);
+ free(quoted);
+ }
+}
+
+/* old (1.14.1) unit order in default/civ2/history ruleset */
+const char* old_default_unit_types[] = {
+ "Settlers", "Engineers", "Warriors", "Phalanx",
+ "Archers", "Legion", "Pikeman", "Musketeers",
+ "Fanatics", "Partisan", "Alpine Troops","Riflemen",
+ "Marines", "Paratroopers", "Mech. Inf.", "Horsemen",
+ "Chariot", "Elephants", "Crusaders", "Knights",
+ "Dragoons", "Cavalary", "Armor", "Catapult",
+ "Cannon", "Artillery", "Howitzer", "Fighter",
+ "Bomber", "Helicopter", "Stealth Fighter", "Stealth Bomber",
+ "Trireme", "Caravel", "Galleon", "Frigate",
+ "Ironclad", "Destroyer", "Cruiser", "AEGIS Cruiser",
+ "Battleship", "Submarine", "Carrier", "Transport",
+ "Cruise Missile", "Nuclear", "Diplomat", "Spy",
+ "Caravan", "Freight", "Explorer", "Barbarian Leader",
+ "AWACS"
+};
+
+/* old (1.14.1) unit order in civ1 ruleset */
+const char* old_civ1_unit_types[] = {
+ "Settlers", "Engineers", "Militia", "Phalanx",
+ "Archers", "Legion", "Pikeman", "Musketeers",
+ "Fanatics", "Partisan", "Alpine Troops","Riflemen",
+ "Marines", "Paratroopers", "Mech. Inf.", "Cavalary",
+ "Chariot", "Elephants", "Crusaders", "Knights",
+ "Dragoons", "Civ2-Cavalary","Armor", "Catapult",
+ "Cannon", "Civ2-Artillery","Artillery", "Fighter",
+ "Bomber", "Helicopter", "Stealth Fighter", "Stealth Bomber",
+ "Trireme", "Sail", "Galleon", "Frigate",
+ "Ironclad", "Destroyer", "Cruiser", "AEGIS Cruiser",
+ "Battleship", "Submarine", "Carrier", "Transport",
+ "Cruise Missile", "Nuclear", "Diplomat", "Spy",
+ "Caravan", "Freight", "Explorer", "Barbarian Leader",
+};
+
+/***************************************************************
+ Nowadays unit types are saved by name, but old servers
+ need unit_type id. This function tries to find correct id
+ for unit type. It is used when unit is saved.
+***************************************************************/
+static int old_type_id(struct unit* punit)
+{
+ const char** T;
+ int k, i;
+ if (strcmp(game.rulesetdir, "civ1") == 0) {
+ T = old_civ1_unit_types;
+ k = ARRAY_SIZE(old_civ1_unit_types);
+ } else {
+ T = old_default_unit_types;
+ k = ARRAY_SIZE(old_default_unit_types);
+ }
+ for (i = 0; i < k; i++) {
+ if (strcmp(unit_name_orig(punit->type), T[i]) == 0) {
+ return i;
+ }
+ }
+ /* It's a new unit. Savegame cannot be backward compatible so we can
+ * return anything */
+ return punit->type;
+}
+
+/***************************************************************
+ ...
+***************************************************************/
+static void load_player_units(struct player *plr, int plrno,
+ struct section_file *file)
+{
+ int nunits, i, j;
+ enum unit_activity activity;
+ char *savefile_options = secfile_lookup_str(file, "savefile.options");
+
unit_list_init(&plr->units);
nunits=secfile_lookup_int(file, "player%d.nunits", plrno);
if (!plr->is_alive && nunits > 0) {
nunits = 0; /* Some old savegames may be buggy. */
}
-
- for(i=0; i<nunits; i++) { /* read the units */
+
+ for(i = 0; i < nunits; i++) {
struct unit *punit;
struct city *pcity;
int nat_x, nat_y;
-
+ const char* type_name;
+ Unit_Type_id type;
+
+ type_name = secfile_lookup_str_default(file, NULL,
+ "player%d.u%d.type_by_name",
+ plrno, i);
+ if (!type_name) {
+ /* before 1.15.0 unit types used to be saved by id */
+ int t = secfile_lookup_int(file, "player%d.u%d.type",
+ plrno, i);
+ if (t < 0) {
+ freelog(LOG_ERROR, _("Wrong player%d.u%d.type value (%d)"),
+ plrno, i, t);
+ exit(EXIT_FAILURE);
+ }
+ /* There was the same order in rulesets but different names.
+ * Warriors in civ1 are called Milita */
+ if (strcmp(game.rulesetdir, "civ1") == 0) {
+ if (t >= ARRAY_SIZE(old_civ1_unit_types)) {
+ freelog(LOG_ERROR, _("Wrong player%d.u%d.type value (%d)"),
+ plrno, i, t);
+ exit(EXIT_FAILURE);
+ }
+ type_name = old_civ1_unit_types[t];
+ } else {
+ if (t >= ARRAY_SIZE(old_default_unit_types)) {
+ freelog(LOG_ERROR, _("Wrong player%d.u%d.type value (%d)"),
+ plrno, i, t);
+ exit(EXIT_FAILURE);
+ }
+ type_name = old_default_unit_types[t];
+ }
+ }
+
+ type = find_unit_type_by_name_orig(type_name);
+ if (type == U_LAST) {
+ freelog(LOG_ERROR, _("Unknown unit type '%s' in player%d section"),
+ type_name, plrno);
+ exit(EXIT_FAILURE);
+ }
+
punit = create_unit_virtual(plr, NULL,
- secfile_lookup_int(file, "player%d.u%d.type", plrno, i),
+ type,
secfile_lookup_int(file, "player%d.u%d.veteran", plrno, i));
punit->id=secfile_lookup_int(file, "player%d.u%d.id", plrno, i);
alloc_id(punit->id);
@@ -1282,56 +1447,6 @@
unit_list_insert(&map_get_tile(punit->x, punit->y)->units, punit);
}
-
- if (section_file_lookup(file, "player%d.attribute_v2_block_length", plrno)) {
- int raw_length1, raw_length2, part_nr, parts;
- size_t quoted_length;
- char *quoted;
-
- raw_length1 =
- secfile_lookup_int(file, "player%d.attribute_v2_block_length", plrno);
- if (plr->attribute_block.data) {
- free(plr->attribute_block.data);
- plr->attribute_block.data = NULL;
- }
- plr->attribute_block.data = fc_malloc(raw_length1);
- plr->attribute_block.length = raw_length1;
-
- quoted_length = secfile_lookup_int
- (file, "player%d.attribute_v2_block_length_quoted", plrno);
- quoted = fc_malloc(quoted_length + 1);
- quoted[0] = 0;
-
- parts =
- secfile_lookup_int(file, "player%d.attribute_v2_block_parts", plrno);
-
- for (part_nr = 0; part_nr < parts; part_nr++) {
- char *current = secfile_lookup_str(file,
-
"player%d.attribute_v2_block_data.part%d",
- plrno, part_nr);
- if (!current)
- break;
- freelog(LOG_DEBUG, "quoted_length=%lu quoted=%lu current=%lu",
- (unsigned long) quoted_length,
- (unsigned long) strlen(quoted),
- (unsigned long) strlen(current));
- assert(strlen(quoted) + strlen(current) <= quoted_length);
- strcat(quoted, current);
- }
- if (quoted_length != strlen(quoted)) {
- freelog(LOG_NORMAL, "quoted_length=%lu quoted=%lu",
- (unsigned long) quoted_length,
- (unsigned long) strlen(quoted));
- assert(0);
- }
-
- raw_length2 =
- unquote_block(quoted,
- plr->attribute_block.data,
- plr->attribute_block.length);
- assert(raw_length1 == raw_length2);
- free(quoted);
- }
}
/**********************************************************************
@@ -1680,8 +1795,12 @@
secfile_insert_int(file, punit->hp, "player%d.u%d.hp", plrno, i);
secfile_insert_int(file, punit->homecity, "player%d.u%d.homecity",
plrno, i);
- secfile_insert_int(file, punit->type, "player%d.u%d.type",
+ /* .type is actually kept only for backward compatibility */
+ secfile_insert_int(file, old_type_id(punit), "player%d.u%d.type",
plrno, i);
+ secfile_insert_str(file, unit_name_orig(punit->type),
+ "player%d.u%d.type_by_name",
+ plrno, i);
secfile_insert_int(file, punit->activity, "player%d.u%d.activity",
plrno, i);
secfile_insert_int(file, punit->activity_count,
@@ -1978,7 +2097,6 @@
}
}
-
/***************************************************************
Assign values to ord_city and ord_map for each unit, so the
values can be saved.
Tylko w freeciv/server: testtest
Tylko w freeciv/server: testtest.gz
Tylko w freeciv/server: testtesttest
- [Freeciv-Dev] (PR#9123) Save unit types by names,
Mateusz Stefek <=
|
|