? civscore.log ? change_field1.diff ? diff ? data/misc/chiefs_front.spec ? data/misc/shields_front.spec Index: common/map.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/map.c,v retrieving revision 1.97 diff -u -r1.97 map.c --- common/map.c 2001/10/15 13:42:50 1.97 +++ common/map.c 2001/10/25 09:27:48 @@ -1144,11 +1144,12 @@ ptile->terrain = T_UNKNOWN; ptile->special = S_NO_SPECIAL; ptile->known = 0; - ptile->sent = 0; ptile->city = NULL; unit_list_init(&ptile->units); ptile->worked = NULL; /* pointer to city working tile */ ptile->assigned = 0; /* bitvector */ + /* bit vector, this new tile has been changed for all players */ + ptile->server.changed = 0xffffffff; } /*************************************************************** @@ -1181,7 +1182,10 @@ { assert(is_real_tile(x, y)); normalize_map_pos(&x, &y); - MAP_TILE(x, y)->continent = val; + if (MAP_TILE(x, y)->continent != val) { + MAP_TILE(x, y)->continent = val; + map_tile_set_changed(x, y, NULL); + } } @@ -1214,32 +1218,65 @@ { assert(is_real_tile(x, y)); normalize_map_pos(&x, &y); - MAP_TILE(x, y)->terrain = ter; + if (MAP_TILE(x, y)->terrain != ter) { + MAP_TILE(x, y)->terrain = ter; + map_tile_set_changed(x, y, NULL); + } } /*************************************************************** -... + Use this method for changes of the special which aren't visible to + the clients. The supplied position has to be normal. +***************************************************************/ +void base_map_set_special(int x, int y, enum tile_special_type spe) +{ + assert(is_normal_map_pos(x, y)); + MAP_TILE(x, y)->special |= spe; +} + +/*************************************************************** + Use this method for changes of the special which are visible to the + clients. ***************************************************************/ void map_set_special(int x, int y, enum tile_special_type spe) { assert(is_real_tile(x, y)); normalize_map_pos(&x, &y); - MAP_TILE(x, y)->special |= spe; + if (!(MAP_TILE(x, y)->special & spe)) { + map_tile_set_changed(x, y, NULL); + base_map_set_special(x, y, spe); + } if (spe & (S_ROAD | S_RAILROAD)) reset_move_costs(x, y); } /*************************************************************** -... + Use this method for changes of the special which aren't visible to + the clients. The supplied position has to be normal. +***************************************************************/ +void base_map_clear_special(int x, int y, enum tile_special_type spe) +{ + assert(is_normal_map_pos(x, y)); + + MAP_TILE(x, y)->special &= ~spe; +} + +/*************************************************************** + Use this method for changes of the special which are visible to the + clients. ***************************************************************/ void map_clear_special(int x, int y, enum tile_special_type spe) { assert(is_real_tile(x, y)); normalize_map_pos(&x, &y); - MAP_TILE(x, y)->special &= ~spe; + if (MAP_TILE(x, y)->special & spe) { + map_tile_set_changed(x, y, NULL); + base_map_clear_special(x, y, spe); + } + if (spe & (S_ROAD | S_RAILROAD)) reset_move_costs(x, y); } @@ -1431,4 +1468,34 @@ /* FIXME: this check will not work with an orthogonal map */ return (start_x == end_x) || (start_y == end_y); +} + +/*************************************************************** + If a player pointer is given this method will mark this tile changed + for this player. If the player argument is NULL this tile has been + changed for all players. +***************************************************************/ +void map_tile_set_changed(int x, int y, struct player *pplayer) +{ + if (pplayer) { + MAP_TILE(x, y)->server.changed |= (1u << pplayer->player_no); + } else { + MAP_TILE(x, y)->server.changed = 0xffffffff; + } +} + +/*************************************************************** + Clears the changed flag for this player for this tile. +***************************************************************/ +void map_tile_clear_changed(int x, int y, struct player *pplayer) +{ + MAP_TILE(x, y)->server.changed &= ~(1u << pplayer->player_no); +} + +/*************************************************************** + Tests if this tile has changed for the given player. +***************************************************************/ +int map_tile_get_changed(int x, int y, struct player *pplayer) +{ + return (MAP_TILE(x, y)->server.changed & (1u << pplayer->player_no)); } Index: common/map.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/map.h,v retrieving revision 1.100 diff -u -r1.100 map.h --- common/map.h 2001/10/19 08:12:52 1.100 +++ common/map.h 2001/10/25 09:27:49 @@ -52,13 +52,19 @@ unsigned int known; /* A bitvector on the server side, an enum known_type on the client side. Player_no is index */ - unsigned int sent; /* Indicates if the client know the tile - as TILE_KNOWN_NODRAW. A bitvector like known. - Not used on the client side. */ int assigned; /* these can save a lot of CPU usage -- Syela */ struct city *worked; /* city working tile, or NULL if none */ signed short continent; signed char move_cost[8]; /* don't know if this helps! */ + struct { + /* + * A bit vector. Only used at the server side. If the bit is set + * this tile has changed for this player and needs to be sent. If + * unset any attempt to send this tile to this player will do + * nothing. + */ + unsigned int changed; + } server; }; @@ -269,7 +275,9 @@ enum tile_special_type map_get_special(int x, int y); void map_set_terrain(int x, int y, enum tile_terrain_type ter); void map_set_special(int x, int y, enum tile_special_type spe); +void base_map_set_special(int x, int y, enum tile_special_type spe); void map_clear_special(int x, int y, enum tile_special_type spe); +void base_map_clear_special(int x, int y, enum tile_special_type spe); void tile_init(struct tile *ptile); enum known_type tile_is_known(int x, int y); int is_real_tile(int x, int y); @@ -334,6 +342,10 @@ int can_channel_land(int x, int y); int can_reclaim_ocean(int x, int y); + +void map_tile_set_changed(int x, int y, struct player *pplayer); +int map_tile_get_changed(int x, int y, struct player *pplayer); +void map_tile_clear_changed(int x, int y, struct player *pplayer); extern struct civ_map map; Index: server/maphand.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/maphand.c,v retrieving revision 1.87 diff -u -r1.87 maphand.c --- server/maphand.c 2001/10/11 12:37:06 1.87 +++ server/maphand.c 2001/10/25 09:27:52 @@ -45,10 +45,6 @@ struct conn_list *dest, int x, int y); static void send_NODRAW_tiles(struct player *pplayer, struct conn_list *dest, int x, int y, int len); -static int map_get_sent(int x, int y, struct player *pplayer); -static void map_set_sent(int x, int y, struct player *pplayer); -static void map_clear_sent(int x, int y, struct player *pplayer); -static void set_unknown_tiles_to_unsent(struct player *pplayer); static void shared_vision_change_seen(int x, int y, struct player *pplayer, int change); static int map_get_seen(int x, int y, struct player *pplayer); @@ -281,12 +277,6 @@ if (dest==NULL) dest = &game.game_connections; - conn_list_iterate(*dest, pconn) { - if (pconn->player) { - set_unknown_tiles_to_unsent(pconn->player); - } - } conn_list_iterate_end; - /* send whole map row by row to each player to balance the load of the send buffers better */ for (y=0; yplayer; - if (pplayer==NULL && !pconn->observer) { + + if ((pplayer == NULL && !pconn->observer) || !pconn->used) { continue; } + + /* + * Don't sent it, if there was no change. + */ + if (pplayer && !map_tile_get_changed(x, y, pplayer)) { + continue; + } + if (pplayer == NULL || map_get_known_and_seen(x, y, pplayer)) { info.known = TILE_KNOWN; info.type = ptile->terrain; info.special = ptile->special; if (pplayer) { update_tile_knowledge(pplayer,x,y); + map_tile_clear_changed(x, y, pplayer); } send_packet_tile_info(pconn, &info); } @@ -371,7 +371,7 @@ info.x = x; info.y = y; - if (pplayer==NULL) { /* observer sees all */ + if (pplayer==NULL) { /* observer sees all */ info.known=TILE_KNOWN; info.type = ptile->terrain; info.special = ptile->special; @@ -390,8 +390,28 @@ info.known = TILE_UNKNOWN; info.type = ptile->terrain; info.special = ptile->special; + } + + /* + * Don't sent it, if there was no change. + */ + if (pplayer && !map_tile_get_changed(x, y, pplayer)) { + return; } - lsend_packet_tile_info(dest, &info); + + conn_list_iterate(*dest, pconn) { + struct player *pplayer2 = pconn->player; + + if (!pconn->used) { + continue; + } + + send_packet_tile_info(pconn, &info); + + if (pplayer2) { + map_tile_clear_changed(x, y, pplayer2); + } + } conn_list_iterate_end; } /************************************************************************** @@ -527,10 +547,7 @@ { conn_list_do_buffer(dest); square_iterate(x, y, len+1, abs_x, abs_y) { - if (!map_get_sent(abs_x, abs_y, pplayer)) { - send_tile_info_always(pplayer, dest, abs_x, abs_y); - map_set_sent(abs_x, abs_y, pplayer); - } + send_tile_info_always(pplayer, dest, abs_x, abs_y); } square_iterate_end; conn_list_do_unbuffer(dest); } @@ -796,8 +813,9 @@ { map_get_player_tile(x, y, pplayer)->seen += change; freelog(LOG_DEBUG, "%d,%d, p: %d, change %d, result %d\n", x, y, - pplayer->player_no, change, map_get_player_tile(x, y, - pplayer)->seen); + pplayer->player_no, change, map_get_player_tile(x, y, + pplayer)->seen); + map_tile_set_changed(x, y, pplayer); } /*************************************************************** @@ -824,7 +842,10 @@ ***************************************************************/ void map_set_known(int x, int y, struct player *pplayer) { - map_get_tile(x, y)->known |= (1u<player_no); + if (!(map_get_tile(x, y)->known & (1u << pplayer->player_no))) { + map_get_tile(x, y)->known |= (1u << pplayer->player_no); + map_tile_set_changed(x, y, pplayer); + } } /*************************************************************** @@ -832,7 +853,10 @@ ***************************************************************/ void map_clear_known(int x, int y, struct player *pplayer) { - map_get_tile(x, y)->known &= ~(1u<player_no); + if (map_get_tile(x, y)->known & (1u << pplayer->player_no)) { + map_get_tile(x, y)->known &= ~(1u << pplayer->player_no); + map_tile_set_changed(x, y, pplayer); + } } /*************************************************************** @@ -863,40 +887,6 @@ players_iterate(pplayer) { map_know_and_see_all(pplayer); } players_iterate_end; -} - -/*************************************************************** -... -***************************************************************/ -static void map_set_sent(int x, int y, struct player *pplayer) -{ - map_get_tile(x, y)->sent |= (1u<player_no); -} - -/*************************************************************** -... -***************************************************************/ -static void map_clear_sent(int x, int y, struct player *pplayer) -{ - map_get_tile(x, y)->sent &= ~(1u<player_no); -} - -/*************************************************************** -... -***************************************************************/ -static int map_get_sent(int x, int y, struct player *pplayer) -{ - return map_get_tile(x, y)->sent & (1u<player_no); -} - -/*************************************************************** -... -***************************************************************/ -static void set_unknown_tiles_to_unsent(struct player *pplayer) -{ - whole_map_iterate(x, y) { - map_clear_sent(x, y, pplayer); - } whole_map_iterate_end; } /*************************************************************** Index: server/savegame.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v retrieving revision 1.36 diff -u -r1.36 savegame.c --- server/savegame.c 2001/10/17 13:16:45 1.36 +++ server/savegame.c 2001/10/25 09:27:54 @@ -313,7 +313,8 @@ /* get the terrain type */ LOAD_MAP_DATA(secfile_lookup_str(file, "map.t%03d", y), - map_get_tile(x, y)->terrain = char2terrain(ch)); + (map_get_tile(x, y)->terrain = + char2terrain(ch), map_tile_set_changed(x, y, NULL))); assign_continent_numbers(); } @@ -396,12 +397,6 @@ map.have_specials = 1; - - /* Should be handled as part of send_all_know_tiles, - but do it here too for safety */ - whole_map_iterate(x, y) { - map_get_tile(x, y)->sent = 0; - } whole_map_iterate_end; } /*************************************************************** Index: server/settlers.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/settlers.c,v retrieving revision 1.112 diff -u -r1.112 settlers.c --- server/settlers.c 2001/10/14 21:02:17 1.112 +++ server/settlers.c 2001/10/25 09:27:55 @@ -440,9 +440,9 @@ if (!city_map_to_map(&x, &y, pcity, i, j)) return -1; if (!(map_get_special(x, y) & S_POLLUTION)) return(-1); - map_clear_special(x, y, S_POLLUTION); + base_map_clear_special(x, y, S_POLLUTION); m = city_tile_value(pcity, i, j, 0, 0); - map_set_special(x, y, S_POLLUTION); + base_map_set_special(x, y, S_POLLUTION); m = (m + best + 50) * 2; return(m); } @@ -458,9 +458,9 @@ if (!city_map_to_map(&x, &y, pcity, i, j)) return -1; if (!(map_get_special(x, y) & S_FALLOUT)) return(-1); - map_clear_special(x, y, S_FALLOUT); + base_map_clear_special(x, y, S_FALLOUT); m = city_tile_value(pcity, i, j, 0, 0); - map_set_special(x, y, S_FALLOUT); + base_map_set_special(x, y, S_FALLOUT); if (!pplayer->ai.control) m = (m + best + 50) * 2; return(m); @@ -524,7 +524,7 @@ if (ptile->city && type->irrigation_result == T_OCEAN) return -1; ptile->terrain = type->irrigation_result; - map_clear_special(x, y, S_MINE); + base_map_clear_special(x, y, S_MINE); m = city_tile_value(pcity, i, j, 0, 0); ptile->terrain = t; ptile->special = s; @@ -533,18 +533,18 @@ !(ptile->special&S_IRRIGATION) && !(ptile->special&S_MINE) && !(ptile->city) && (is_wet_or_is_wet_cardinal_around(pplayer, x, y)))) { - map_set_special(x, y, S_IRRIGATION); + base_map_set_special(x, y, S_IRRIGATION); m = city_tile_value(pcity, i, j, 0, 0); - map_clear_special(x, y, S_IRRIGATION); + base_map_clear_special(x, y, S_IRRIGATION); return(m); } else if((ptile->terrain==type->irrigation_result && (ptile->special&S_IRRIGATION) && !(ptile->special&S_FARMLAND) && player_knows_techs_with_flag(pplayer, TF_FARMLAND) && !(ptile->special&S_MINE) && !(ptile->city) && (is_wet_or_is_wet_cardinal_around(pplayer, x, y)))) { - map_set_special(x, y, S_FARMLAND); + base_map_set_special(x, y, S_FARMLAND); m = city_tile_value(pcity, i, j, 0, 0); - map_clear_special(x, y, S_FARMLAND); + base_map_clear_special(x, y, S_FARMLAND); return(m); } else return(-1); } @@ -581,9 +581,9 @@ /* Note that this code means we will never try to mine a city into the ocean */ if ((ptile->terrain == T_HILLS || ptile->terrain == T_MOUNTAINS) && !(ptile->special&S_IRRIGATION) && !(ptile->special&S_MINE)) { - map_set_special(x, y, S_MINE); + base_map_set_special(x, y, S_MINE); m = city_tile_value(pcity, i, j, 0, 0); - map_clear_special(x, y, S_MINE); + base_map_clear_special(x, y, S_MINE); return(m); } else return(-1); } @@ -622,11 +622,11 @@ ptile->terrain = r; if (get_tile_type(r)->mining_result != r) - map_clear_special(x, y, S_MINE); + base_map_clear_special(x, y, S_MINE); if (get_tile_type(r)->irrigation_result != r) { - map_clear_special(x, y, S_FARMLAND); - map_clear_special(x, y, S_IRRIGATION); + base_map_clear_special(x, y, S_FARMLAND); + base_map_clear_special(x, y, S_IRRIGATION); } m = city_tile_value(pcity, i, j, 0, 0);