diff client/packhand.c client/packhand.c --- client/packhand.c Mon Jan 1 15:59:11 2001 +++ client/packhand.c Thu Jan 4 23:43:32 2001 @@ -243,15 +243,6 @@ pcity=find_city_by_id(packet->id); if (pcity && (pcity->owner != packet->owner)) { - /* With current server, this shouldn't happen: when city changes - * owner it is re-created with a new id. Unclear what to do here; - * try to cope... - */ - freelog(LOG_ERROR, - "Got existing city id (%d %s) with wrong owner (%d %s, old %d %s)", - packet->id, pcity->name, packet->owner, - get_player(packet->owner)->name, pcity->owner, - get_player(pcity->owner)->name); client_remove_city(pcity); pcity = 0; } @@ -456,15 +447,6 @@ pcity=find_city_by_id(packet->id); if (pcity && (pcity->owner != packet->owner)) { - /* With current server, this shouldn't happen: when city changes - * owner it is re-created with a new id. Unclear what to do here; - * try to cope... - */ - freelog(LOG_ERROR, - "Got existing city id (%d %s) with wrong owner (%d %s, old %d %s)", - packet->id, pcity->name, packet->owner, - get_player(packet->owner)->name, pcity->owner, - get_player(pcity->owner)->name); client_remove_city(pcity); pcity = 0; } diff common/city.h common/city.h --- common/city.h Mon Jan 1 15:59:11 2001 +++ common/city.h Thu Jan 4 23:43:32 2001 @@ -154,6 +154,7 @@ struct city { int id; + int orig_id; int owner; int x, y; char name[MAX_LEN_NAME]; diff server/cityhand.c server/cityhand.c --- server/cityhand.c Mon Jan 1 15:59:11 2001 +++ server/cityhand.c Thu Jan 4 23:43:32 2001 @@ -157,6 +157,7 @@ pcity=fc_malloc(sizeof(struct city)); pcity->id=get_next_id_number(); + pcity->orig_id = pcity->id; idex_register_city(pcity); pcity->owner=pplayer->player_no; pcity->x=x; @@ -284,7 +285,7 @@ struct packet_city_request *preq) { struct city *pcity; - pcity=find_city_by_id(preq->city_id); + pcity=find_city_by_orig_id(preq->city_id); if(!pcity) return; if(!player_owns_city(pplayer, pcity)) @@ -332,7 +333,7 @@ { struct city *pcity; - pcity=find_city_by_id(preq->city_id); + pcity=find_city_by_orig_id(preq->city_id); if(!pcity) return; if (!player_owns_city(pplayer, pcity)) return; @@ -360,7 +361,7 @@ struct packet_city_request *preq) { struct city *pcity; - pcity=find_city_by_id(preq->city_id); + pcity=find_city_by_orig_id(preq->city_id); if (preq->worker_x < 0 || preq->worker_x > 4) return; @@ -440,7 +441,7 @@ void handle_city_sell(struct player *pplayer, struct packet_city_request *preq) { struct city *pcity; - pcity=find_city_by_id(preq->city_id); + pcity=find_city_by_orig_id(preq->city_id); if (!pcity || !player_owns_city(pplayer, pcity) || preq->build_id>=game.num_impr_types) return; @@ -524,7 +525,7 @@ void handle_city_worklist(struct player *pplayer, struct packet_city_request *preq) { struct city *pcity; - pcity=find_city_by_id(preq->city_id); + pcity=find_city_by_orig_id(preq->city_id); copy_worklist(pcity->worklist, &preq->worklist); @@ -537,7 +538,7 @@ void handle_city_buy(struct player *pplayer, struct packet_city_request *preq) { struct city *pcity; - pcity=find_city_by_id(preq->city_id); + pcity=find_city_by_orig_id(preq->city_id); really_handle_city_buy(pplayer, pcity); } @@ -547,7 +548,7 @@ void handle_city_refresh(struct player *pplayer, struct packet_generic_integer *preq) { struct city *pcity; - pcity=find_city_by_id(preq->value); + pcity=find_city_by_orig_id(preq->value); if (pcity) { city_refresh(pcity); send_city_info(pplayer, pcity); @@ -631,7 +632,7 @@ struct packet_city_request *preq) { struct city *pcity; - pcity=find_city_by_id(preq->city_id); + pcity=find_city_by_orig_id(preq->city_id); if (!pcity) { freelog(LOG_ERROR, "Pcity null in handle_city_change" " (%s, id = %d)!", pplayer->name, preq->city_id); @@ -665,7 +666,7 @@ char *cp; struct city *pcity; - pcity=find_city_by_id(preq->city_id); + pcity=find_city_by_orig_id(preq->city_id); if(!player_owns_city(pplayer, pcity)) return; @@ -686,7 +687,7 @@ void handle_city_options(struct player *pplayer, struct packet_generic_values *preq) { - struct city *pcity = find_city_by_id(preq->value1); + struct city *pcity = find_city_by_orig_id(preq->value1); if (!pcity || pcity->owner != pplayer->player_no) return; pcity->city_options = preq->value2; /* We don't need to send the full city info, since no other properties @@ -897,7 +898,7 @@ /************************************************************************** FIXME: should be in the same file as transfer_city **************************************************************************/ -void remove_city(struct city *pcity) +void remove_city(struct city *pcity, int remove_from_clients) { int o, x, y; struct player *pplayer = city_owner(pcity); @@ -935,18 +936,21 @@ /* idex_unregister_city() is called in game_remove_city() below */ - /* dealloc_id(pcity->id); We do NOT dealloc cityID's as the cities may still be - alive in the client. As the number of romoved cities is small the leak is - acceptable. */ + /* We can never deallocate original id, as some clients may still + have old city with that id. --Caz */ + if (pcity->id != pcity->orig_id) + dealloc_id(pcity->id); /* DO NOT remove city from minimap here. -- Syela */ game_remove_city(pcity); - for(o=0; oid=pcity->id; + packet->id=pcity->orig_id; packet->owner=pcity->owner; packet->x=pcity->x; packet->y=pcity->y; @@ -1008,7 +1012,7 @@ packet->ppl_scientist=pcity->ppl_scientist; packet->ppl_taxman=pcity->ppl_taxman; for (i=0;i<4;i++) { - packet->trade[i]=pcity->trade[i]; + packet->trade[i]=orig_city_id(pcity->trade[i]); packet->trade_value[i]=pcity->trade_value[i]; } @@ -1085,7 +1089,7 @@ packet->happy=1; } - if ((pcity = map_get_city(x,y)) && pcity->id == pdcity->id && + if ((pcity = map_get_city(x,y)) && pcity->orig_id == pdcity->id && city_got_building(pcity, B_PALACE)) packet->capital=1; else @@ -1106,13 +1110,13 @@ struct dumb_city *pdcity; if (!plrtile->city) { plrtile->city = fc_malloc(sizeof(struct dumb_city)); - plrtile->city->id = pcity->id; + plrtile->city->id = pcity->orig_id; } pdcity = plrtile->city; - if (pdcity->id != pcity->id) { + if (pdcity->id != pcity->orig_id) { freelog(LOG_ERROR, "Trying to update old city (wrong ID)" " at %i,%i for player %s", pcity->x, pcity->y, pplayer->name); - pdcity->id = pcity->id; /* ?? */ + pdcity->id = pcity->orig_id; /* ?? */ } sz_strlcpy(pdcity->name, pcity->name); pdcity->size = pcity->size; @@ -1131,7 +1135,7 @@ if (pdcity) { pcity = map_get_tile(x,y)->city; - if (!pcity || (pcity && pcity->id != pdcity->id)) { + if (!pcity || (pcity && pcity->orig_id != pdcity->id)) { packet.value=pdcity->id; lsend_packet_generic_integer(&pplayer->connections, PACKET_REMOVE_CITY, &packet); diff server/cityhand.h server/cityhand.h --- server/cityhand.h Mon Jan 1 15:59:11 2001 +++ server/cityhand.h Thu Jan 4 23:43:32 2001 @@ -24,7 +24,7 @@ struct packet_generic_values; void create_city(struct player *pplayer, const int x, const int y, char *name); -void remove_city(struct city *pcity); +void remove_city(struct city *pcity, int remove_from_clients); void send_city_info(struct player *dest, struct city *pcity); void send_city_info_at_tile(struct player *pviewer, struct conn_list *dest, struct city *pcity, int x, int y); diff server/citytools.c server/citytools.c --- server/citytools.c Thu Jan 4 19:40:46 2001 +++ server/citytools.c Thu Jan 4 23:43:33 2001 @@ -1073,6 +1073,7 @@ *pnewcity->worklist = *pcity->worklist; pnewcity->id=get_next_id_number(); + pnewcity->orig_id = pcity->orig_id; idex_register_city(pnewcity); for (i = 0; i < game.num_impr_types; i++) { @@ -1104,7 +1105,7 @@ } transfer_city_units(pplayer, cplayer, pnewcity, pcity, kill_outside, transfer_unit_verbose); - remove_city(pcity); + remove_city(pcity, 0); map_set_city(pnewcity->x, pnewcity->y, pnewcity); reset_move_costs(pnewcity->x, pnewcity->y); @@ -1128,6 +1129,7 @@ /* advisor_choose_build(pcity); we add the civ bug here :) */ send_city_info(0, pnewcity); + map_fog_pseudo_city_area(cplayer, pnewcity->x, pnewcity->y); /* What wasn't obsolete for the old owner may be so now. */ remove_obsolete_buildings_city(pnewcity, 1); @@ -1146,11 +1148,6 @@ send_tile_info (0, pnewcity->x, pnewcity->y); } - /* We lose visibility as the old city is removed, and if the square isn't - shown here the old owner will never get told about the new city */ - update_dumb_city(cplayer, pnewcity); - send_city_info(cplayer, pnewcity); - maybe_make_first_contact(pnewcity->x, pnewcity->y, pplayer->player_no); return pnewcity; @@ -1179,3 +1176,50 @@ } } +/********************************************************************** + ... +***********************************************************************/ +int orig_city_id(int id) +{ + struct city *pcity; + + if ((pcity=find_city_by_id(id))) + return pcity->orig_id; + return 0; +} + +/********************************************************************** + ... +***********************************************************************/ +struct city *find_city_by_orig_id(int id) +{ + return player_find_city_by_orig_id(0, id); +} + +/********************************************************************** + ... +***********************************************************************/ +struct city *player_find_city_by_orig_id(struct player *owner, int id) +{ + struct city *pcity; + + /* Most of the time city id == orig_id. + This is fast way to check city id. */ + pcity = find_city_by_id(id); + if(pcity) { + if (owner && owner->player_no != pcity->owner) + return 0; + return pcity; + } + + /* Slower method to check actual orig_id. */ + players_iterate(pplayer) { + if (!owner || owner == pplayer) { + city_list_iterate(pplayer->cities, pcity) { + if (id == pcity->orig_id) + return pcity; + } city_list_iterate_end; + } + } players_iterate_end; + return 0; +} diff server/citytools.h server/citytools.h --- server/citytools.h Mon Jan 1 15:59:11 2001 +++ server/citytools.h Thu Jan 4 23:43:33 2001 @@ -69,4 +69,8 @@ void adjust_city_free_cost(int *num_free, int *this_cost); +int orig_city_id(int id); +struct city *find_city_by_orig_id(int id); +struct city *player_find_city_by_orig_id(struct player *owner, int id); + #endif /* FC__CITYTOOLS_H */ diff server/cityturn.c server/cityturn.c --- server/cityturn.c Mon Jan 1 15:59:12 2001 +++ server/cityturn.c Thu Jan 4 23:43:33 2001 @@ -832,7 +832,7 @@ { if(pcity->size<1) { remove_city_from_minimap(pcity->x, pcity->y); - remove_city(pcity); + remove_city(pcity, 1); return; } if(city_specialists(pcity)) { @@ -1819,5 +1819,5 @@ x,y, unit_types[pcity->currently_building].name, get_nation_name_plural(pplayer->nation)); - remove_city(pcity); + remove_city(pcity, 1); } diff server/diplhand.c server/diplhand.c --- server/diplhand.c Mon Jan 1 15:59:12 2001 +++ server/diplhand.c Thu Jan 4 23:43:33 2001 @@ -279,6 +279,7 @@ struct Treaty *ptreaty; struct player *plr0, *plr1, *pgiver; int capability; + int real_value; plr0=&game.players[packet->plrno0]; plr1=&game.players[packet->plrno1]; @@ -294,10 +295,13 @@ */ if(packet->clause_type == CLAUSE_CITY){ - struct city *pcity = find_city_by_id(packet->value); + struct city *pcity = find_city_by_orig_id(packet->value); if (pcity && !map_get_known_and_seen(pcity->x, pcity->y, plr1->player_no)) give_citymap_from_player_to_player(pcity, plr0, plr1); + real_value = pcity->id; } + else + real_value = packet->value; capability = 1; conn_list_iterate(plr0->connections, pconn) { @@ -318,7 +322,7 @@ } if((ptreaty=find_treaty(plr0, plr1))) { - if(add_clause(ptreaty, pgiver, packet->clause_type, packet->value)) { + if(add_clause(ptreaty, pgiver, packet->clause_type, real_value)) { lsend_packet_diplomacy_info(&plr0->connections, PACKET_DIPLOMACY_CREATE_CLAUSE, packet); @@ -432,7 +436,10 @@ packet.clause_type = pclause->type; packet.plrno_from = pclause->from->player_no; - packet.value = pclause->value; + if(pclause->type == CLAUSE_CITY) + packet.value = orig_city_id(pclause->value); + else + packet.value = pclause->value; send_packet_diplomacy_info(dest, PACKET_DIPLOMACY_CREATE_CLAUSE, &packet); diff server/savegame.c server/savegame.c --- server/savegame.c Thu Jan 4 19:40:46 2001 +++ server/savegame.c Thu Jan 4 23:43:41 2001 @@ -722,6 +722,7 @@ pcity->id=secfile_lookup_int(file, "player%d.c%d.id", plrno, i); alloc_id(pcity->id); idex_register_city(pcity); + pcity->orig_id=pcity->id; pcity->owner=plrno; pcity->x=secfile_lookup_int(file, "player%d.c%d.x", plrno, i); pcity->y=secfile_lookup_int(file, "player%d.c%d.y", plrno, i); @@ -1312,8 +1313,8 @@ secfile_insert_int(file, punit->foul, "player%d.u%d.foul", plrno, i); 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, orig_city_id(punit->homecity), + "player%d.u%d.homecity", plrno, i); secfile_insert_int(file, punit->type, "player%d.u%d.type", plrno, i); secfile_insert_int(file, punit->activity, "player%d.u%d.activity", @@ -1387,7 +1388,7 @@ char buf[512]; i++; - secfile_insert_int(file, pcity->id, "player%d.c%d.id", plrno, i); + secfile_insert_int(file, pcity->orig_id, "player%d.c%d.id", plrno, i); secfile_insert_int(file, pcity->x, "player%d.c%d.x", plrno, i); secfile_insert_int(file, pcity->y, "player%d.c%d.y", plrno, i); secfile_insert_str(file, pcity->name, "player%d.c%d.name", plrno, i); @@ -1401,8 +1402,8 @@ secfile_insert_int(file, pcity->ppl_taxman, "player%d.c%d.ntaxman", plrno, i); for(j=0; j<4; j++) - secfile_insert_int(file, pcity->trade[j], "player%d.c%d.traderoute%d", - plrno, i, j); + secfile_insert_int(file, orig_city_id(pcity->trade[j]), + "player%d.c%d.traderoute%d", plrno, i, j); secfile_insert_int(file, pcity->food_stock, "player%d.c%d.food_stock", plrno, i); diff server/unithand.c server/unithand.c --- server/unithand.c Mon Jan 1 15:59:12 2001 +++ server/unithand.c Thu Jan 4 23:43:33 2001 @@ -156,7 +156,7 @@ struct city *pcity; if(!(punit=player_find_unit_by_id(pplayer, packet->unit_id))) return; - if(!(pcity=find_city_by_id(packet->city_id))) return; + if(!(pcity=find_city_by_orig_id(packet->city_id))) return; if(punit->x!=pcity->x || punit->y!=pcity->y) { notify_player(pplayer, _("Game: Illegal move, unit not in city!")); @@ -191,7 +191,7 @@ struct packet_generic_integer *packet) { struct player *pplayer = pconn->player; - struct city *pcity=find_city_by_id(packet->value); + struct city *pcity=find_city_by_orig_id(packet->value); struct unit *punit=find_unit_by_id(packet->value); struct packet_generic_values req; @@ -224,7 +224,7 @@ { struct unit *pdiplomat=player_find_unit_by_id(pplayer, packet->diplomat_id); struct unit *pvictim=find_unit_by_id(packet->target_id); - struct city *pcity=find_city_by_id(packet->target_id); + struct city *pcity=find_city_by_orig_id(packet->target_id); if (!pdiplomat) return; if (!unit_flag(pdiplomat->type, F_DIPLOMAT)) @@ -307,20 +307,21 @@ struct unit *punit; if ((punit=player_find_unit_by_id(pplayer, req->unit_id))) { - struct city *pcity; - if ((pcity=player_find_city_by_id(pplayer, req->city_id)) - && pcity->owner == punit->owner) { - unit_list_insert(&pcity->units_supported, punit); - city_refresh(pcity); - send_city_info(pplayer, pcity); + struct city *new_homecity = 0; + struct city *old_homecity = 0; + if ((new_homecity=player_find_city_by_orig_id(pplayer, req->city_id)) + && new_homecity->owner == punit->owner) { + unit_list_insert(&new_homecity->units_supported, punit); + city_refresh(new_homecity); + send_city_info(pplayer, new_homecity); - if((pcity=player_find_city_by_id(pplayer, punit->homecity))) { - unit_list_unlink(&pcity->units_supported, punit); - city_refresh(pcity); - send_city_info(pplayer, pcity); + if((old_homecity=player_find_city_by_id(pplayer, punit->homecity))) { + unit_list_unlink(&old_homecity->units_supported, punit); + city_refresh(old_homecity); + send_city_info(pplayer, old_homecity); } - punit->homecity=req->city_id; + punit->homecity=new_homecity->id; send_unit_info(pplayer, punit); } } @@ -911,7 +912,7 @@ && punit->homecity) { struct packet_unit_request req; req.unit_id = punit->id; - req.city_id = pcity->id; + req.city_id = pcity->orig_id; req.name[0] = '\0'; return handle_unit_establish_trade(pplayer, &req); } @@ -941,7 +942,7 @@ /* if is_diplomat_action_available() then there must be a city or a unit */ if (pcity) { - packet.target_id = pcity->id; + packet.target_id = pcity->orig_id; } else if (pdefender) { packet.target_id = pdefender->id; } else { @@ -1130,7 +1131,7 @@ if (!punit || !unit_flag(punit->type, F_CARAVAN)) return; - pcity_dest = find_city_by_id(req->city_id); + pcity_dest = find_city_by_orig_id(req->city_id); if (!pcity_dest || !unit_can_help_build_wonder(punit, pcity_dest)) return; @@ -1177,7 +1178,7 @@ return 0; pcity_homecity=player_find_city_by_id(pplayer, punit->homecity); - pcity_dest=find_city_by_id(req->city_id); + pcity_dest=find_city_by_orig_id(req->city_id); if(!pcity_homecity || !pcity_dest) return 0; @@ -1289,7 +1290,7 @@ pcity->x,pcity->y, get_nation_name_plural(pplayer->nation)); remove_city_from_minimap(pcity->x, pcity->y); - remove_city(pcity); + remove_city(pcity, 1); if (do_civil_war) civil_war(cplayer); return; @@ -1495,7 +1496,7 @@ packet->owner = punit->owner; packet->x = punit->x; packet->y = punit->y; - packet->homecity = punit->homecity; + packet->homecity = orig_city_id(punit->homecity); packet->veteran = punit->veteran; packet->type = punit->type; packet->movesleft = punit->moves_left; @@ -1516,7 +1517,7 @@ packet->carried = carried; packet->select_it = select_it; packet->packet_use = packet_use; - packet->info_city_id = info_city_id; + packet->info_city_id = orig_city_id(info_city_id); packet->serial_num = serial_num; }