diff -X freeciv/diff_ignore -Nurd attr-2/client/civclient.c attr-2_note-8/client/civclient.c --- attr-2/client/civclient.c Fri Feb 16 21:11:38 2001 +++ attr-2_note-8/client/civclient.c Fri Feb 16 21:25:35 2001 @@ -18,6 +18,7 @@ #include #include #include +#include #ifdef HAVE_UNISTD_H #include @@ -80,9 +81,34 @@ int turn_gold_difference; int did_advance_tech_this_turn; +int request_sno_of_currently_handled_packet; static void client_remove_all_cli_conn(void); +static void handle_callbacks(int response_to_sno, + enum callback_time callback_time, + int packet_type); +struct callback { + int request_sno; + enum callback_time call_back_time; + callback_function_t callback_function; + int user_data; +}; + +#define SPECLIST_TAG callback +#define SPECLIST_TYPE struct callback +#include "speclist.h" + +#define SPECLIST_TAG callback +#define SPECLIST_TYPE struct callback +#include "speclist_c.h" + +#define callback_list_iterate(callbacklist, pcallback) \ + TYPED_LIST_ITERATE(struct callback, callbacklist, pcallback) +#define callback_list_iterate_end LIST_ITERATE_END + +static struct callback_list callbacks; + /************************************************************************** ... **************************************************************************/ @@ -164,6 +190,7 @@ init_our_capability(); game_init(); attribute_init(); + callback_list_init(&callbacks); /* This seed is not saved anywhere; randoms in the client should have cosmetic effects only (eg city name suggestions). --dwp */ @@ -180,8 +207,11 @@ /************************************************************************** ... **************************************************************************/ -void handle_packet_input(char *packet, int type) +void handle_packet_input(char *packet, int type, int request_sno) { + request_sno_of_currently_handled_packet = request_sno; + handle_callbacks(request_sno, call_back_before, type); + switch(type) { case PACKET_JOIN_GAME_REPLY: handle_join_game_reply((struct packet_join_game_reply *)packet); @@ -358,6 +388,10 @@ case PACKET_ADVANCE_FOCUS: handle_advance_focus((struct packet_generic_integer *)packet); break; + + case PACKET_NOTE: + handle_note((struct packet_note *)packet); + break; case PACKET_CONN_INFO: handle_conn_info((struct packet_conn_info *)packet); @@ -376,6 +410,15 @@ break; } + handle_callbacks(request_sno, call_back_after, type); + + if (type == PACKET_NOTE + && is_final_category(((struct packet_note *) packet)->category)) { + handle_callbacks(request_sno, call_back_after_final, type); + } + + request_sno_of_currently_handled_packet = 0; + free(packet); } @@ -429,12 +472,13 @@ void send_move_unit(struct unit *punit) { struct packet_move_unit move; + int sno; move.unid=punit->id; move.x=punit->x; move.y=punit->y; - send_packet_move_unit(&aconnection, &move); + sno=send_packet_move_unit(&aconnection, &move); } /************************************************************************** @@ -537,6 +581,82 @@ struct connection *pconn = conn_list_get(&game.all_connections, 0); client_remove_cli_conn(pconn); } +} + +/************************************************************************** + Goes through all callbacks and call all matching ones. Remove old + callbacks. +**************************************************************************/ +static void handle_callbacks(int response_to_sno, + enum callback_time callback_time, + int packet_type) +{ + callback_list_iterate(callbacks, pcallback); + { + if (pcallback->request_sno == response_to_sno && + pcallback->call_back_time == callback_time) { + pcallback->callback_function(packet_type, pcallback->user_data); + } + + /* old -> remove it */ + if (pcallback->request_sno < response_to_sno) { + callback_list_unlink(&callbacks, pcallback); + free(pcallback); + } + } + callback_list_iterate_end; +} + +/************************************************************************** + Adds a callout for the given request. +**************************************************************************/ +void install_response_callback(int request_sno, + enum callback_time when, + callback_function_t callback, int user_data) +{ + struct callback *pcb = fc_malloc(sizeof(struct callback)); + + /* serial number of 0 is invalid */ + assert(request_sno != 0); + assert(when == call_back_before || when == call_back_after + || when == call_back_after_final); + assert(callback != NULL); + + pcb->request_sno = request_sno; + pcb->call_back_time = when; + pcb->callback_function = callback; + pcb->user_data = user_data; + + callback_list_insert(&callbacks, pcb); +} + +/************************************************************************** + Send to given note to itself. +**************************************************************************/ +void send_note_xy_self(int x, int y, int category, const char *format, ...) +{ + struct packet_note packet; + + va_list args; + va_start(args, format); + build_note_packet(&packet, x, y, category, format, args); + va_end(args); + + handle_note(&packet); +} +/************************************************************************** + Send to given note to itself. +**************************************************************************/ +void send_note_self(int category, const char *format, ...) +{ + struct packet_note packet; + + va_list args; + va_start(args, format); + build_note_packet(&packet, -1, -1, category, format, args); + va_end(args); + + handle_note(&packet); } void dealloc_id(int id); /* double kludge (suppress a possible warning) */ diff -X freeciv/diff_ignore -Nurd attr-2/client/civclient.h attr-2_note-8/client/civclient.h --- attr-2/client/civclient.h Fri Feb 16 21:11:38 2001 +++ attr-2_note-8/client/civclient.h Fri Feb 16 21:23:39 2001 @@ -16,7 +16,7 @@ #include "packets.h" /* enum report_type */ #include "game.h" /* enum client_states */ -void handle_packet_input(char *packet, int type); +void handle_packet_input(char *packet, int type, int request_sno); void send_unit_info(struct unit *punit); void send_move_unit(struct unit *punit); @@ -32,6 +32,10 @@ void client_remove_cli_conn(struct connection *pconn); +void send_note_xy_self(int x, int y, int category, + const char *format, ...); +void send_note_self(int category, const char *format, ...); + extern int turn_gold_difference; extern int seconds_to_turndone; extern int last_turn_gold_amount; @@ -41,5 +45,28 @@ extern char server_host[512]; extern char name[512]; extern int server_port; + +extern int request_sno_of_currently_handled_packet; + +typedef void (*callback_function_t)(int packet_type, int user_data); + +enum callback_time { + /* the callback will be called before the generic packet handling + method */ + call_back_before, + + /* the callback will be called after the generic packet handling + method */ + call_back_after, + + /* the callback will be called after the generic packet handling + method of the final note */ + call_back_after_final +}; + +void install_response_callback(int request_sno, + enum callback_time when, + callback_function_t callback, + int user_data); #endif /* FC__CIVCLIENT_H */ diff -X freeciv/diff_ignore -Nurd attr-2/client/clinet.c attr-2_note-8/client/clinet.c --- attr-2/client/clinet.c Mon Jan 15 01:30:18 2001 +++ attr-2_note-8/client/clinet.c Fri Feb 16 21:23:39 2001 @@ -148,6 +148,8 @@ aconnection.buffer = new_socket_packet_buffer(); aconnection.send_buffer = new_socket_packet_buffer(); aconnection.last_write = 0; + aconnection.next_sno = 1; + aconnection.current_initiator_sno = 0; aconnection.used = 1; @@ -187,13 +189,19 @@ void input_from_server(int fid) { if(read_socket_data(fid, aconnection.buffer)>=0) { - int type, result; + int type, result, request_sno; char *packet; while (1) { - packet = get_packet_from_connection(&aconnection, &type, &result); + packet = + get_packet_from_connection(&aconnection, &type, &result, + &request_sno); if (result) { - handle_packet_input(packet, type); + /* We don't use this field on the client, but it will be set + * by get_packet_from_connection(). + */ + aconnection.current_initiator_sno = 0; + handle_packet_input(packet, type, request_sno); } else { break; } diff -X freeciv/diff_ignore -Nurd attr-2/client/packhand.c attr-2_note-8/client/packhand.c --- attr-2/client/packhand.c Fri Feb 16 21:11:38 2001 +++ attr-2_note-8/client/packhand.c Fri Feb 16 21:26:18 2001 @@ -60,6 +60,7 @@ #include "tilespec.h" #include "wldlg_g.h" #include "attribute.h" +#include "dynamicvarargs.h" #include "packhand.h" @@ -269,7 +270,7 @@ **************************************************************************/ void handle_city_info(struct packet_city_info *packet) { - int i, x, y, city_is_new; + int i, x, y, city_is_new, old_size; struct city *pcity; int popup; int update_descriptions = 0; @@ -308,6 +309,7 @@ pcity->y=packet->y; sz_strlcpy(pcity->name, packet->name); + old_size = pcity->size; pcity->size=packet->size; pcity->ppl_happy[4]=packet->ppl_happy; pcity->ppl_content[4]=packet->ppl_content; @@ -397,6 +399,23 @@ timer_initialized = 1; } } + + if (pcity->size > old_size && !city_is_new) { + send_note_xy_self(make_category(CBT_INFO, CAO_OWN_CITY, + CDI_SIZE, CSDI_NONE), + pcity->x, pcity->y, + N_("Client: %s grows from size %d to size %d"), + AT_CITY(pcity->id), AT_INT(old_size), + AT_INT(pcity->size)); + } + + if (pcity->size < old_size && !city_is_new) { + send_note_xy_self(make_category(CBT_INFO, CAO_OWN_CITY, + CDI_SIZE, CSDI_NONE), + pcity->x, pcity->y, + N_("Client: Population loss of %d in %s"), + AT_INT(old_size - pcity->size), AT_CITY(pcity->id)); + } } /************************************************************************** @@ -616,6 +635,9 @@ if(sound_bell_at_new_turn && (!game.player_ptr->ai.control || ai_manual_turn_done)) sound_bell(); + + send_note_self(make_category(CBT_INFO, CAO_GAME, CDI_NONE, CSDI_NONE), + _("Year: %s"), AT_USTRING(textyear(ppacket->year))); } /************************************************************************** @@ -2164,6 +2186,59 @@ popup_sabotage_dialog(pcity); } +} + +/************************************************************************** +... +**************************************************************************/ +static void format_note(struct packet_note *packet, char *mystring, + int navail) +{ + va_dyn a; + int i; + + a = dva_init(); + + for (i = 0; i < packet->arguments_used; i++) { + if (packet->arguments[i].type == at_int) { + dva_int(a, packet->arguments[i].integer); + } else if (packet->arguments[i].type == at_ustring || + packet->arguments[i].type == at_int_ustring) { + dva_string(a, packet->arguments[i].string); + } else if (packet->arguments[i].type == at_int_tstring) { + dva_string(a, _(packet->arguments[i].string)); + } else { + assert(0); + } + } + + vsnprintf(mystring, navail, _(packet->format_string), dva_get(a)); + dva_end(a); +} + +/************************************************************************** +... +**************************************************************************/ +void handle_note(struct packet_note *packet) +{ + char buffer[MAX_LEN_MSG]; + struct packet_generic_message packet2; + + /* final note which is automatically created by the server */ + if (packet->category == + make_category(CBT_FINAL, CAO_GAME, CDI_NONE, CSDI_NONE)) { + return; + } + + format_note(packet, buffer, sizeof(buffer)); + + /* FIXME handle this in a proper way */ + packet2.x = packet->x; + packet2.y = packet->y; + packet2.event = E_NOEVENT; + strncpy(packet2.message, buffer, MAX_LEN_MSG); + + handle_chat_msg(&packet2); } /************************************************************************** diff -X freeciv/diff_ignore -Nurd attr-2/client/packhand.h attr-2_note-8/client/packhand.h --- attr-2/client/packhand.h Fri Feb 16 21:11:38 2001 +++ attr-2_note-8/client/packhand.h Fri Feb 16 21:25:59 2001 @@ -59,5 +59,6 @@ void handle_diplomat_action(struct packet_diplomat_action *packet); void handle_sabotage_list(struct packet_sabotage_list *packet); void handle_player_attribute_chunk(struct packet_attribute_chunk *packet); +void handle_note(struct packet_note *packet); #endif /* FC__PACKHAND_H */ diff -X freeciv/diff_ignore -Nurd attr-2/common/Makefile.am attr-2_note-8/common/Makefile.am --- attr-2/common/Makefile.am Mon Aug 14 14:48:27 2000 +++ attr-2_note-8/common/Makefile.am Fri Feb 16 21:23:39 2001 @@ -21,6 +21,8 @@ create_lsend.pl \ diptreaty.c \ diptreaty.h \ + dynamicvarargs.c \ + dynamicvarargs.h \ events.h \ fcintl.c \ fcintl.h \ @@ -44,6 +46,8 @@ log.h \ map.c \ map.h \ + note.c \ + note.h \ nation.c \ nation.h \ netintf.c \ diff -X freeciv/diff_ignore -Nurd attr-2/common/capstr.c attr-2_note-8/common/capstr.c --- attr-2/common/capstr.c Fri Feb 16 21:11:38 2001 +++ attr-2_note-8/common/capstr.c Fri Feb 16 21:26:58 2001 @@ -74,7 +74,7 @@ " game_ruleset nuclear_fallout land_channel_requirement event_wonder_obsolete" \ " event00_fix conn_info gen_impr_oversights diplo_move_city packet_short_city" \ " indef_impr_types worklist_true_ids shared_vision activity_patrol" \ -" gen_granary_size attributes" +" gen_granary_size attributes sno" /* "+1.11" is protocol for 1.11.0 stable release. @@ -135,6 +135,8 @@ food storage box is calculated. "attributes" is the ability to request and transfer attribute blocks. + + "sno" adds two serial numbers to each packet. */ void init_our_capability(void) diff -X freeciv/diff_ignore -Nurd attr-2/common/connection.c attr-2_note-8/common/connection.c --- attr-2/common/connection.c Mon Sep 18 22:36:14 2000 +++ attr-2_note-8/common/connection.c Fri Feb 16 21:23:39 2001 @@ -251,7 +251,7 @@ /************************************************************************** write data to socket **************************************************************************/ -int send_connection_data(struct connection *pc, unsigned char *data, int len) +void send_connection_data(struct connection *pc, unsigned char *data, int len) { if (pc && pc->used) { if(pc->send_buffer->do_buffer_sends) { @@ -272,7 +272,6 @@ flush_connection_send_buffer_all(pc); } } - return 0; } /************************************************************************** diff -X freeciv/diff_ignore -Nurd attr-2/common/connection.h attr-2_note-8/common/connection.h --- attr-2/common/connection.h Sat Oct 28 00:20:08 2000 +++ attr-2_note-8/common/connection.h Fri Feb 16 21:23:39 2001 @@ -108,9 +108,23 @@ int route_length; /* These are used when recieving goto routes; they are send split, and in the time where the route is partially recieved it is stored here. */ + + /* will increase for every packet send by this connection */ + int next_sno; + /* + * Server: holds the sno of the request which is processed now. Can be zero. + * Client: will always be zero + */ + int current_initiator_sno; + /* + * boolean; only for server; if set the packet which is currently + * processed is a command and needs a final note + */ + int needs_final_note; + /* boolean; only for server; if set the final note was sent */ + int final_note_sent; }; - const char *cmdlevel_name(enum cmdlevel_id lvl); enum cmdlevel_id cmdlevel_named(const char *token); @@ -121,7 +135,7 @@ int read_socket_data(int sock, struct socket_packet_buffer *buffer); void flush_connection_send_buffer_all(struct connection *pc); void flush_connection_send_buffer_packets(struct connection *pc); -int send_connection_data(struct connection *pc, unsigned char *data, int len); +void send_connection_data(struct connection *pc, unsigned char *data, int len); void connection_do_buffer(struct connection *pc); void connection_do_unbuffer(struct connection *pc); diff -X freeciv/diff_ignore -Nurd attr-2/common/dynamicvarargs.c attr-2_note-8/common/dynamicvarargs.c --- attr-2/common/dynamicvarargs.c Thu Jan 1 01:00:00 1970 +++ attr-2_note-8/common/dynamicvarargs.c Fri Feb 16 21:23:39 2001 @@ -0,0 +1,59 @@ +/********************************************************************** + Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "dynamicvarargs.h" + +/* The real type of va_dyn is hidden! Looks a bit strange, but is + lots easier to handle. */ + +struct dynamicvarargs { + unsigned char buf[50]; + unsigned int curpos; +}; + +/* use it static, as it is not yet used in multitasking */ +static struct dynamicvarargs dva; + +va_dyn dva_init(void) +{ + /* maybe malloc() dva */ + dva.curpos = 0; + return (va_dyn) (&dva); +} + +void dva_end(va_dyn pvarargs) +{ + /* maybe free() va_dyn */ +} + +void dva_string(va_dyn pvarargs, char *a) +{ + struct dynamicvarargs *pdva = (struct dynamicvarargs *) pvarargs; + + *((char **)(pdva->buf+pdva->curpos)) = a; + pdva->curpos += sizeof(char *); +} + +void dva_int(va_dyn pvarargs, int i) +{ + struct dynamicvarargs *pdva = (struct dynamicvarargs *) pvarargs; + + *((int *)(pdva->buf+pdva->curpos)) = i; + pdva->curpos += sizeof(int); +} diff -X freeciv/diff_ignore -Nurd attr-2/common/dynamicvarargs.h attr-2_note-8/common/dynamicvarargs.h --- attr-2/common/dynamicvarargs.h Thu Jan 1 01:00:00 1970 +++ attr-2_note-8/common/dynamicvarargs.h Fri Feb 16 21:23:39 2001 @@ -0,0 +1,32 @@ +/********************************************************************** + Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +***********************************************************************/ + +#ifndef FC__DYNAMICVARARGS_H +#define FC__DYNAMICVARARGS_H + +typedef void * va_dyn; + +va_dyn dva_init(void); +#define dva_get(a) ((va_list) a) +void dva_end(va_dyn pvarargs); + +void dva_string(va_dyn pvarargs, char *a); +void dva_int(va_dyn pvarargs, int i); + +/* The methods used to build the varargs file maybe a possible poartability + problem. That's why the are sperated in a special file. + But the current supported systems should not have problems with it as long + as only int and char * are used! +*/ + +#endif /* FC__DYNAMICVARARGS_H */ diff -X freeciv/diff_ignore -Nurd attr-2/common/note.c attr-2_note-8/common/note.c --- attr-2/common/note.c Thu Jan 1 01:00:00 1970 +++ attr-2_note-8/common/note.c Fri Feb 16 21:23:39 2001 @@ -0,0 +1,51 @@ +/********************************************************************** + Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +***********************************************************************/ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "note.h" + +int make_category(enum category_basic_type basic_type, + enum category_affected_object affected_object, + enum category_detail_information detail_information, + enum category_subdetail_information subdetail_information) +{ + int result; + +#define C(x) assert(x >= 0 && x < 256) + + C(basic_type); + C(affected_object); + C(detail_information); + C(subdetail_information); + +#undef C + + assert(sizeof(int) >= 4); + + result = basic_type | (affected_object << 8) | + (detail_information << 16) | (subdetail_information << 24); + return result; +} + +int is_final_category(int category) +{ + enum category_basic_type basic_type = category & 0xff; + + return (basic_type == CBT_FAILURE || + basic_type == CBT_SUCCESS || basic_type == CBT_FINAL); +} diff -X freeciv/diff_ignore -Nurd attr-2/common/note.h attr-2_note-8/common/note.h --- attr-2/common/note.h Thu Jan 1 01:00:00 1970 +++ attr-2_note-8/common/note.h Fri Feb 16 21:23:39 2001 @@ -0,0 +1,182 @@ +/********************************************************************** + Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +***********************************************************************/ +#ifndef FC__NOTE_H +#define FC__NOTE_H + +#include + +/* + * There will be exactly one final note per command packet (see + * is_command_packet()). This final note can be CBT_FAILURE, + * CBT_SUCCESS or CBT_FINAL. After a final note will no other packet + * be transmitted. CBT_FINAL will be used if none of CBT_FAILURE or + * CBT_SUCCESS was send but the current packet is a command and so + * requires a final note. + */ +enum category_basic_type { + /* a command failed */ + CBT_FAILURE=1, + /* a command succeeded */ + CBT_SUCCESS, + /* a command ends with unknown status */ + CBT_FINAL, + /* an information */ + CBT_INFO +}; + +/* + * Describes the affected object. + */ +enum category_affected_object { + /* server messages */ + CAO_GAME=1, + /* global warming, nuclear winter */ + CAO_ENVIRONMENT, + /* start, stop, finish, great library */ + CAO_WONDER, + CAO_SPACESHIP, + + CAO_OWN_UNIT, + CAO_OWN_CITY, + CAO_OWN_PLAYER, + CAO_OWN_NATION, + + CAO_OTHER_UNIT, + CAO_OTHER_CITY, + CAO_OTHER_PLAYER, + /* including barbarians, contact, destroyed */ + CAO_OTHER_NATION +}; + +/* + * Depending on the affected object + */ +enum category_detail_information { + CDI_NONE=1, + /* + * CAO_*_CITY + */ + /* increase, descrease, aqueduct */ + CDI_SIZE, + /* buying, selling, changing, finishing */ + CDI_PRODUCTION, + CDI_WORKLIST, + /* normal, disorder, love */ + CDI_HAPPINESS, + + /* + * CAO_*_NATION + */ + /* low on founds, gold found in hut, looted city */ + CDI_GOLD, + CDI_GOVERMENT, + /* huts, research */ + CDI_TECH, + + /* + * CAO_OTHER_NATION + */ + /* pact, state */ + CDI_DIPLOMACY, + + /* + * CAO_*_UNIT + */ + /* stealing, poision, bribe, incite, ... */ + CDI_DIPLOMAT, + /* can't attack, win, lose */ + CDI_BATTLE, + CDI_MOVE, + + /* + * CAO_OWN_UNIT + */ + /* (as in F_SETTLERS) everything about terrain mods */ + CDI_SETTLERS, + /* (as in F_CITIES) everything about city founding and adding */ + CDI_CITIES, + /* trying to establish a traderoute */ + CDI_TRADEROUTE, + + /* + * CAO_GAME + */ + CDI_OBSOLETE +}; + +/* + * Depending on the affected object and the detailed information + */ +enum category_subdetail_information { + CSDI_NONE=1 +}; + +enum argument_types { + /* transfer an int */ + at_int, + /* transfer an untranslated string */ + at_ustring, + /* transfer an int and a string which would get translated */ + at_int_tstring, + /* transfer an int and a string which would _NOT_ get translated */ + at_int_ustring +}; + +#define MAX_ARGUMENTS 10 +#define MAX_LEN_FORMAT_STRING 1024 +#define MAX_LEN_ARGUMENT_STRING 1024 + +#include "packets.h" + +#define AT_MAGIC_NUMBER (0xdeadbabe) + +#define AT_INT(x) (int)AT_MAGIC_NUMBER,(int)at_int,(int)x +#define AT_USTRING(x) (int)AT_MAGIC_NUMBER,(int)at_ustring,(char *)x +#define AT_CITY(x) (int)AT_MAGIC_NUMBER,(int)at_int_ustring,\ + (int)x,(char *)(find_city_by_id(x)->name) +#define AT_PLAYER(x) (int)AT_MAGIC_NUMBER,(int)at_int_ustring,\ + (int)x,(char *)(game.players[x].name) +#define AT_UNIT_TYPE(x) (int)AT_MAGIC_NUMBER,(int)at_int_tstring,\ + (int)x,(char *)(get_unit_type(x)->name) +#define AT_TECH(x) (int)AT_MAGIC_NUMBER,(int)at_int_tstring,\ + (int)x,(char *)(advances[x].name_orig) +/* to be continued */ + +/* + * Constructs a new category based on the given sub + * categories. detail_information can be + * CDI_NONE. subdetail_information can be CSDI_NONE. + */ +int make_category(enum category_basic_type basic_type, + enum category_affected_object affected_object, + enum category_detail_information detail_information, + enum category_subdetail_information subdetail_information); + +/* + * Tests the given category for the given sub categories. A value of + * zero will always match. + * + * Examples: + * + * is_category(category, 0, CAO_CITY, CDI_SIZE, 0) will test if the + * category has anything to do with a city and its size. + */ +int is_category(int category, + enum category_basic_type basic_type, + enum category_affected_object affected_object, + enum category_detail_information detail_information, + enum category_subdetail_information subdetail_information); + +int is_final_category(int category); + +#endif /* FC__NOTE_H */ diff -X freeciv/diff_ignore -Nurd attr-2/common/packets.c attr-2_note-8/common/packets.c --- attr-2/common/packets.c Fri Feb 16 21:11:38 2001 +++ attr-2_note-8/common/packets.c Fri Feb 16 21:23:39 2001 @@ -115,7 +115,8 @@ static unsigned int swab_uint32(unsigned int val); static void swab_puint16(int *ptr); static void swab_puint32(int *ptr); - +static int send_packet_data(struct connection *pc, unsigned char *data, + int len); /************************************************************************** Swap bytes on an integer considered as 16 bits @@ -155,15 +156,16 @@ instead of just testing if the returning package is NULL as we sometimes return a NULL packet even if everything is OK (receive_packet_goto_route). **************************************************************************/ -void *get_packet_from_connection(struct connection *pc, int *ptype, int *presult) +void *get_packet_from_connection(struct connection *pc, int *ptype, + int *presult, int *pinitiator_sno) { - int len, type; - *presult = 0; + int len, type, sno, initiator_sno; + *presult = 0; if (pc->used==0) return NULL; /* connection was closed, stop reading */ - if(pc->buffer->ndata<3) + if(pc->buffer->ndata<5) return NULL; /* length and type not read */ get_uint16(pc->buffer->data, &len); @@ -194,10 +196,27 @@ put_uint16(pc->buffer->data, len); } + if (pc && has_capability("sno", pc->capability)) { + get_uint16(pc->buffer->data + len - 4, &sno); + get_uint16(pc->buffer->data + len - 2, &initiator_sno); + freelog(LOG_DEBUG, "received a packet with sno=%d, " + "initiator_sno=%d from connection %d", sno, initiator_sno, + pc->id); + } else { + sno = 1; + initiator_sno = 0; + } + + pc->current_initiator_sno = sno; + pc->needs_final_note = is_command_packet(type); + pc->final_note_sent = 0; + freelog(LOG_DEBUG, "packet type %d len %d", type, len); *ptype=type; *presult = 1; + if (pinitiator_sno) + *pinitiator_sno = initiator_sno; switch(type) { @@ -367,6 +386,9 @@ case PACKET_ATTRIBUTE_CHUNK: return receive_packet_attribute_chunk(pc); + case PACKET_NOTE: + return receive_packet_note(pc); + default: freelog(LOG_ERROR, "unknown packet type %d received from %s", type, conn_description(pc)); @@ -391,19 +413,23 @@ Initialize pack_iter at the start of receiving a packet. Sets all entries in piter. There should already be a packet, and it should have at least - 3 bytes, as checked in get_packet_from_connection(). + 5 bytes, as checked in get_packet_from_connection(). The length data will already be byte swapped if necessary. **************************************************************************/ static void pack_iter_init(struct pack_iter *piter, struct connection *pc) { assert(piter!=NULL && pc!=NULL); - assert(pc->buffer->ndata >= 3); + assert(pc->buffer->ndata >= 5); piter->swap_bytes = pc->byte_swap; piter->ptr = piter->base = pc->buffer->data; piter->ptr = get_uint16(piter->ptr, &piter->len); piter->ptr = get_uint8(piter->ptr, &piter->type); - piter->short_packet = (piter->len < 3); + if (pc && has_capability("sno", pc->capability)) { + piter->short_packet = (piter->len < 5); + } else { + piter->short_packet = (piter->len < 3); + } piter->bad_string = 0; piter->bad_bit_string = 0; } @@ -1270,7 +1296,7 @@ cptr=put_uint32(cptr, packet->value); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************* @@ -1312,7 +1338,7 @@ cptr=put_uint16(cptr, packet->value); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************* @@ -1350,7 +1376,7 @@ cptr=put_uint8(cptr, packet->y); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } @@ -1391,7 +1417,7 @@ cptr=put_uint8(cptr, packet->make_winner_veteran); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } @@ -1435,7 +1461,7 @@ cptr=put_string(cptr, packet->name); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } @@ -1477,7 +1503,7 @@ cptr=put_uint16(cptr, packet->dest_y); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************* @@ -1529,7 +1555,7 @@ put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************* @@ -1586,7 +1612,7 @@ cptr=put_string(cptr, packet->name); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } @@ -1692,7 +1718,7 @@ put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } @@ -1812,7 +1838,7 @@ put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************* @@ -1911,7 +1937,7 @@ put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************* @@ -1992,7 +2018,7 @@ cptr=put_uint8(cptr, pinfo->is_earth?1:0); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************* @@ -2081,7 +2107,7 @@ cptr=put_uint8(cptr, pinfo->known); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -2094,7 +2120,7 @@ cptr=put_uint8(buffer+2, PACKET_NEW_YEAR); cptr=put_uint32(cptr, request->year); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -2107,7 +2133,7 @@ cptr=put_uint8(cptr, type); cptr=put_uint8(cptr, action); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -2136,7 +2162,7 @@ unsigned char buffer[MAX_LEN_PACKET], *cptr; cptr=put_uint8(buffer+2, PACKET_BEFORE_NEW_YEAR); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************* @@ -2200,7 +2226,7 @@ if(req->fuel) cptr=put_uint8(cptr, req->fuel); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************* @@ -2279,7 +2305,7 @@ put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************* @@ -2467,7 +2493,7 @@ put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } @@ -2602,7 +2628,7 @@ cptr=put_uint16(cptr, request->unid); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } @@ -2644,7 +2670,7 @@ cptr=put_string(cptr, request->version_label); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -2673,7 +2699,7 @@ put_uint16(buffer, cptr-buffer); } - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -2713,7 +2739,7 @@ cptr=put_string(cptr, packet->message); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -2726,7 +2752,7 @@ cptr=put_uint8(buffer+2, type); cptr=put_uint32(cptr, packet->value); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -2858,7 +2884,7 @@ cptr=put_uint8(cptr,packet->city_style); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -2898,7 +2924,7 @@ put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -2968,7 +2994,7 @@ put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************* @@ -3059,7 +3085,7 @@ } put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -3143,7 +3169,7 @@ } put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -3229,7 +3255,7 @@ } put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -3345,7 +3371,7 @@ put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -3448,7 +3474,7 @@ put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -3575,7 +3601,7 @@ freelog(LOG_DEBUG, "send gov %s", packet->name); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } int send_packet_ruleset_government_ruler_title(struct connection *pc, @@ -3592,7 +3618,7 @@ cptr=put_string(cptr, packet->female_title); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -3721,7 +3747,7 @@ put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } @@ -3774,7 +3800,7 @@ put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -3833,7 +3859,7 @@ } put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -3902,7 +3928,7 @@ cptr=put_bit_string(cptr, (char*)packet->structure); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -3965,7 +3991,7 @@ cptr=put_uint8(cptr, packet->num); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -4001,7 +4027,7 @@ cptr=put_string(cptr, packet->name); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -4038,7 +4064,7 @@ cptr = put_bit_string(cptr, (char *)packet->improvements); put_uint16(buffer, cptr-buffer); - return send_connection_data(pc, buffer, cptr-buffer); + return send_packet_data(pc, buffer, cptr-buffer); } /************************************************************************** @@ -4125,7 +4151,7 @@ cptr = put_uint16(cptr, packet->unit_id); put_uint16(buffer, cptr-buffer); - send_connection_data(pc, buffer, cptr-buffer); + send_packet_data(pc, buffer, cptr-buffer); this_chunk++; } @@ -4214,6 +4240,189 @@ default: freelog(LOG_ERROR, "invalid type in receive_packet_goto_route()"); return NULL; + } +} + +/************************************************************************** +... +**************************************************************************/ +int send_packet_note(struct connection *pc, + const struct packet_note *packet) +{ + unsigned char buffer[MAX_LEN_PACKET], *cptr; + int i, sno; + + cptr = put_uint8(buffer+2, PACKET_NOTE); + cptr = put_uint8(cptr, packet->x); + cptr = put_uint8(cptr, packet->y); + cptr = put_uint32(cptr, packet->category); + cptr = put_uint8(cptr, packet->arguments_used); + cptr = put_string(cptr, packet->format_string); + + for (i = 0; i < packet->arguments_used; i++) { + cptr = put_uint32(cptr, (unsigned int) (packet->arguments[i].type)); + cptr = put_uint32(cptr, packet->arguments[i].integer); + cptr = put_string(cptr, packet->arguments[i].string); + } + + put_uint16(buffer, cptr - buffer); + + sno = send_packet_data(pc, buffer, cptr - buffer); + + if (is_final_category(packet->category)) { + assert(!pc->final_note_sent); + pc->final_note_sent = 1; + } + + return sno; +} + +/************************************************************************** +... +**************************************************************************/ +struct packet_note *receive_packet_note(struct connection *pc) +{ + struct pack_iter iter; + struct packet_note *packet = fc_malloc(sizeof(struct packet_note)); + int i; + + pack_iter_init(&iter, pc); + + iget_uint8(&iter, &packet->x); + iget_uint8(&iter, &packet->y); + iget_uint32(&iter, &packet->category); + iget_uint8(&iter, &packet->arguments_used); + iget_string(&iter, packet->format_string, + sizeof(packet->format_string)); + + for (i = 0; i < packet->arguments_used; i++) { + int type; + + iget_uint32(&iter, &type); + packet->arguments[i].type = (enum argument_types) type; + iget_uint32(&iter, &packet->arguments[i].integer); + iget_string(&iter, packet->arguments[i].string, + sizeof(packet->arguments[i].string)); + } + + pack_iter_end(&iter, pc); + remove_packet_from_buffer(pc->buffer); + + if (packet->x == 255) + packet->x = -1; + + if (packet->y == 255) + packet->y = -1; + + return packet; +} + +/************************************************************************** +Changes the data from: + u16 size + u8 type + u8 real_data[] +to + u16 size+4 + u8 type + u8 real_data[] + u16 sno + u16 initiator_sno +It returns the serial number of the outgoing packet. +**************************************************************************/ +static int send_packet_data(struct connection *pc, unsigned char *data, + int orig_len) +{ + int sno_to_use = 1, new_len = orig_len; + + if (pc && has_capability("sno", pc->capability)) { + sno_to_use = pc->next_sno++; + new_len += 4; + + assert(new_len < MAX_LEN_PACKET); + /* after the final note no other packet is allowed */ + assert(!pc->final_note_sent); + + freelog(LOG_DEBUG, "send packet with sno=%d and initiator_sno=%d", + sno_to_use, pc->current_initiator_sno); + + put_uint16(data, new_len); + + put_uint16(data + orig_len, sno_to_use); + put_uint16(data + orig_len + 2, pc->current_initiator_sno); + } + + send_connection_data(pc, data, new_len); + + return sno_to_use; +} +/************************************************************************** + If it is a command packet there will be a final note send. +**************************************************************************/ +int is_command_packet(int packet_type) +{ + return 1; +} + +/************************************************************************** +... +**************************************************************************/ +static int count_args_in_format_string(const char *format_string) +{ + int result = 0, i, len = strlen(format_string); + + for (i = 0; i < len; i++) { + if (format_string[i] == '%' && format_string[i + 1] != '%') { + result++; + i++; + } + } + return result; +} + +/************************************************************************** + Fills the given packet with the supplied arguments. +**************************************************************************/ +void build_note_packet(struct packet_note *packet, + int x, int y, int category, + const char *format, va_list vargs) +{ + int args_used = count_args_in_format_string(format), i; + + assert(args_used < MAX_ARGUMENTS); + assert(strlen(format) < MAX_LEN_FORMAT_STRING - 1); + + packet->arguments_used = args_used; + packet->x = x; + packet->y = y; + packet->category = category; + strcpy(packet->format_string, format); + + for (i = 0; i < args_used; i++) { + int magic = va_arg(vargs, int); + enum argument_types type = (enum argument_types) va_arg(vargs, int); + int integer=-1; + char *string=NULL; + + assert(magic == AT_MAGIC_NUMBER); + + if (type == at_int || type == at_int_tstring || type == at_int_ustring) { + integer = va_arg(vargs, int); + } + + if (type == at_ustring || type == at_int_tstring + || type == at_int_ustring) { + string = va_arg(vargs, char *); + assert(string); + assert(strlen(string) < MAX_LEN_ARGUMENT_STRING - 1); + } + + packet->arguments[i].type = type; + packet->arguments[i].integer = integer; + if(string!=NULL) + strcpy(packet->arguments[i].string, string); + else + packet->arguments[i].string[0]=0; } } diff -X freeciv/diff_ignore -Nurd attr-2/common/packets.h attr-2_note-8/common/packets.h --- attr-2/common/packets.h Fri Feb 16 21:11:39 2001 +++ attr-2_note-8/common/packets.h Fri Feb 16 21:27:33 2001 @@ -19,6 +19,7 @@ #include "shared.h" /* MAX_LEN_NAME, MAX_LEN_ADDR */ #include "spaceship.h" #include "worklist.h" +#include "note.h" #define MAX_LEN_USERNAME 10 /* see below */ #define MAX_LEN_MSG 1536 @@ -119,6 +120,7 @@ PACKET_PATROL_ROUTE, PACKET_ATTRIBUTE_CHUNK, PACKET_PLAYER_ATTRIBUTE_BLOCK, + PACKET_NOTE, PACKET_LAST /* leave this last */ }; @@ -428,6 +430,15 @@ int x,y,event; }; +struct packet_note { + int x, y, category, arguments_used; + char format_string[MAX_LEN_FORMAT_STRING]; + struct { + enum argument_types type; + int integer; + char string[MAX_LEN_ARGUMENT_STRING]; + } arguments[MAX_ARGUMENTS]; +}; /********************************************************* like the packet above. @@ -866,6 +877,10 @@ unsigned char *put_uint16(unsigned char *buffer, int val); unsigned char *put_string(unsigned char *buffer, const char *mystring); +int is_command_packet(int packet_type); +void build_note_packet(struct packet_note *packet, int x, int y, + int category, const char *format, va_list vargs); + int send_packet_diplomacy_info(struct connection *pc, enum packet_type pt, const struct packet_diplomacy_info *packet); struct packet_diplomacy_info * @@ -1066,13 +1081,17 @@ struct packet_sabotage_list * receive_packet_sabotage_list(struct connection *pc); -void *get_packet_from_connection(struct connection *pc, int *ptype, int *presult); +void *get_packet_from_connection(struct connection *pc, int *ptype, + int *presult, int *pinitiator_sno); void remove_packet_from_buffer(struct socket_packet_buffer *buffer); int send_packet_goto_route(struct connection *pc, const struct packet_goto_route *packet, enum goto_route_type type); struct packet_goto_route *receive_packet_goto_route(struct connection *pc); + +int send_packet_note(struct connection *pc, const struct packet_note *packet); +struct packet_note *receive_packet_note(struct connection *pc); int send_packet_attribute_chunk(struct connection *pc, struct packet_attribute_chunk *packet); diff -X freeciv/diff_ignore -Nurd attr-2/common/packets_lsend.c attr-2_note-8/common/packets_lsend.c --- attr-2/common/packets_lsend.c Wed Jan 24 20:40:02 2001 +++ attr-2_note-8/common/packets_lsend.c Fri Feb 16 21:23:39 2001 @@ -355,3 +355,10 @@ conn_list_iterate_end; } +void lsend_packet_note(struct conn_list *dest, const struct packet_note *packet) +{ + conn_list_iterate(*dest, pconn) + send_packet_note(pconn, packet); + conn_list_iterate_end; +} + diff -X freeciv/diff_ignore -Nurd attr-2/common/packets_lsend.h attr-2_note-8/common/packets_lsend.h --- attr-2/common/packets_lsend.h Wed Jan 24 20:40:02 2001 +++ attr-2_note-8/common/packets_lsend.h Fri Feb 16 21:23:39 2001 @@ -102,3 +102,4 @@ void lsend_packet_goto_route(struct conn_list *dest, const struct packet_goto_route *packet, enum goto_route_type type); +void lsend_packet_note(struct conn_list *dest, const struct packet_note *packet); diff -X freeciv/diff_ignore -Nurd attr-2/server/citytools.c attr-2_note-8/server/citytools.c --- attr-2/server/citytools.c Thu Feb 15 22:27:10 2001 +++ attr-2_note-8/server/citytools.c Fri Feb 16 21:23:39 2001 @@ -966,7 +966,8 @@ /************************************************************************** ... **************************************************************************/ -void create_city(struct player *pplayer, const int x, const int y, char *name) +struct city *create_city(struct player *pplayer, const int x, const int y, + char *name) { struct city *pcity, *othercity; int i, x_itr, y_itr; @@ -1083,6 +1084,8 @@ && !can_unit_do_activity(punit, punit->activity)) handle_unit_activity_request(punit, ACTIVITY_IDLE); } unit_list_iterate_end; + + return pcity; } /************************************************************************** diff -X freeciv/diff_ignore -Nurd attr-2/server/citytools.h attr-2_note-8/server/citytools.h --- attr-2/server/citytools.h Tue Feb 13 18:53:20 2001 +++ attr-2_note-8/server/citytools.h Fri Feb 16 21:23:39 2001 @@ -80,7 +80,8 @@ void reality_check_city(struct player *pplayer,int x, int y); void update_dumb_city(struct player *pplayer, struct city *pcity); -void create_city(struct player *pplayer, const int x, const int y, char *name); +struct city *create_city(struct player *pplayer, const int x, const int y, + char *name); void remove_city(struct city *pcity); int establish_trade_route(struct city *pc1, struct city *pc2); diff -X freeciv/diff_ignore -Nurd attr-2/server/gamehand.c attr-2_note-8/server/gamehand.c --- attr-2/server/gamehand.c Thu Feb 15 19:40:38 2001 +++ attr-2_note-8/server/gamehand.c Fri Feb 16 21:23:39 2001 @@ -165,9 +165,6 @@ apacket.year = year; lsend_packet_new_year(&game.est_connections, &apacket); - - /* Hmm, clients could add this themselves based on above packet? */ - notify_conn(&game.est_connections, _("Year: %s"), textyear(year)); } diff -X freeciv/diff_ignore -Nurd attr-2/server/plrhand.c attr-2_note-8/server/plrhand.c --- attr-2/server/plrhand.c Fri Feb 16 21:11:39 2001 +++ attr-2_note-8/server/plrhand.c Fri Feb 16 21:23:40 2001 @@ -15,6 +15,7 @@ #endif #include +#include #include "capability.h" #include "events.h" @@ -884,6 +885,30 @@ } /************************************************************************** + New version of vnotify_conn_ex. +**************************************************************************/ +static void vsend_note_xy_conn_list(struct conn_list *dest, int x, int y, + int category, const char *format, + va_list vargs) +{ + struct packet_note packet; + + build_note_packet(&packet, x, y, category, format, vargs); + + conn_list_iterate(*dest, pconn) { + if (!(y >= 0 && y < map.ysize && server_state >= RUN_GAME_STATE + && ((pconn->player == NULL && pconn->observer) + || (pconn->player != NULL + && map_get_known(x, y, pconn->player))))) { + packet.x = -1; + packet.y = -1; + } + send_packet_note(pconn, &packet); + } + conn_list_iterate_end; +} + +/************************************************************************** See vnotify_conn_ex - this is just the "non-v" version, with varargs. **************************************************************************/ void notify_conn_ex(struct conn_list *dest, int x, int y, int event, @@ -896,6 +921,18 @@ } /************************************************************************** + See vsend_note_xy_conn_list - this is just the "non-v" version, with varargs. +**************************************************************************/ +void send_note_xy_conn_list(struct conn_list *dest, int x, int y, + int category, const char *format, ...) +{ + va_list args; + va_start(args, format); + vsend_note_xy_conn_list(dest, x, y, category, format, args); + va_end(args); +} + +/************************************************************************** See vnotify_conn_ex - this is varargs, and cannot specify (x,y), event. **************************************************************************/ void notify_conn(struct conn_list *dest, const char *format, ...) @@ -907,6 +944,18 @@ } /************************************************************************** + See vsend_note_xy_conn_list - this is with varargs and without (x,y). +**************************************************************************/ +void send_note_conn_list(struct conn_list *dest, int category, + const char *format, ...) +{ + va_list args; + va_start(args, format); + vsend_note_xy_conn_list(dest, -1, -1, category, format, args); + va_end(args); +} + +/************************************************************************** Similar to vnotify_conn_ex (see also), but takes player as "destination". If player != NULL, sends to all connections for that player. If player == NULL, sends to all established connections, to support @@ -931,6 +980,26 @@ } /************************************************************************** + Similar to send_note_xy_conn_list (see also), but takes player as + "destination". If player != NULL, sends to all connections for that + player. +**************************************************************************/ +void send_note_xy_player(const struct player *pplayer, int x, int y, + int category, const char *format, ...) +{ + struct conn_list *dest; + va_list args; + + assert(pplayer); + + dest = (struct conn_list*)&pplayer->connections; + + va_start(args, format); + vsend_note_xy_conn_list(dest, x, y, category, format, args); + va_end(args); +} + +/************************************************************************** Just like notify_player_ex, but no (x,y) nor event type. **************************************************************************/ void notify_player(const struct player *pplayer, const char *format, ...) @@ -950,6 +1019,48 @@ } /************************************************************************** + Just like send_note_xy_player, but no (x,y). +**************************************************************************/ +void send_note_player(const struct player *pplayer, int category, + const char *format, ...) +{ + struct conn_list *dest; + va_list args; + + assert(pplayer); + + dest = (struct conn_list*)&pplayer->connections; + + va_start(args, format); + vsend_note_xy_conn_list(dest, -1, -1, category, format, args); + va_end(args); +} + +/************************************************************************** + Just like send_note_xy_player, but no (x,y) and for all players. +**************************************************************************/ +void send_note_all(int category, const char *format, ...) +{ + va_list args; + + va_start(args, format); + vsend_note_xy_conn_list(&game.est_connections, -1, -1, category, format, args); + va_end(args); +} + +/************************************************************************** + Just like send_note_xy_player but for all players. +**************************************************************************/ +void send_note_xy_all(int x, int y, int category, const char *format, ...) +{ + va_list args; + + va_start(args, format); + vsend_note_xy_conn_list(&game.est_connections, x, y, category, format, args); + va_end(args); +} + +/************************************************************************** Send message to all players who have an embassy with pplayer, but excluding specified player. **************************************************************************/ @@ -970,6 +1081,29 @@ && exclude != &game.players[i]) { lsend_packet_generic_message(&game.players[i].connections, PACKET_CHAT_MSG, &genmsg); + } + } +} + +/************************************************************************** + Send message to all players who have an embassy with pplayer, + but excluding specified player. +**************************************************************************/ +void send_note_embassies(struct player *pplayer, struct player *exclude, + int category, const char *format, ...) +{ + int i; + struct packet_note packet; + va_list args; + + va_start(args, format); + build_note_packet(&packet, -1, -1, category, format, args); + va_end(args); + + for(i=0; ibyte_swap = 0; pconn->capability[0] = '\0'; pconn->access_level = access_level_for_next_connection(); + pconn->next_sno = 1; + pconn->current_initiator_sno = 0; sz_strlcpy(pconn->name, makeup_connection_name(&pconn->id)); sz_strlcpy(pconn->addr, diff -X freeciv/diff_ignore -Nurd attr-2/server/srv_main.c attr-2_note-8/server/srv_main.c --- attr-2/server/srv_main.c Fri Feb 16 21:11:39 2001 +++ attr-2_note-8/server/srv_main.c Fri Feb 16 21:23:40 2001 @@ -894,6 +894,25 @@ } /************************************************************************** + Undoes effects from common/packets.c:get_packet_from_connection() +**************************************************************************/ +static void finish_handling_packet(struct connection *pconn, char *packet, + int type) +{ + freelog(LOG_DEBUG, "finish processing packet from connection %d", + pconn->id); + if(pconn->needs_final_note && !pconn->final_note_sent) + { + send_note_player(pconn->player, + make_category(CBT_FINAL, CAO_GAME, CDI_NONE, + CSDI_NONE), "dummy message"); + } + pconn->current_initiator_sno = 0; + pconn->needs_final_note = 0; + pconn->final_note_sent = 0; +} + +/************************************************************************** ... **************************************************************************/ void handle_packet_input(struct connection *pconn, char *packet, int type) @@ -901,18 +920,24 @@ struct player *pplayer; /* a NULL packet can be returned from receive_packet_goto_route() */ - if (packet == NULL) + if (packet == NULL) { + finish_handling_packet(pconn, packet, type); return; + } - switch(type) { + switch (type) { case PACKET_REQUEST_JOIN_GAME: - handle_request_join_game(pconn, (struct packet_req_join_game *)packet); + handle_request_join_game(pconn, + (struct packet_req_join_game *) packet); + finish_handling_packet(pconn, packet, type); free(packet); return; break; } if (!pconn->established) { + finish_handling_packet(pconn, packet, type); + freelog(LOG_ERROR, "Received game packet from unaccepted connection %s", conn_description(pconn)); free(packet); @@ -922,6 +947,8 @@ pplayer = pconn->player; if(pplayer == NULL) { + finish_handling_packet(pconn, packet, type); + /* don't support these yet */ freelog(LOG_ERROR, "Received packet from non-player connection %s", conn_description(pconn)); @@ -933,6 +960,8 @@ if((!pplayer->is_alive || pconn->observer) && !(type == PACKET_CHAT_MSG || type == PACKET_REPORT_REQUEST)) { + finish_handling_packet(pconn, packet, type); + free(packet); return; } @@ -1132,6 +1161,8 @@ freelog(LOG_ERROR, "Received unknown packet %d from %s", type, conn_description(pconn)); } + + finish_handling_packet(pconn, packet, type); free(packet); pplayer->current_conn = NULL; diff -X freeciv/diff_ignore -Nurd attr-2/server/stdinhand.c attr-2_note-8/server/stdinhand.c --- attr-2/server/stdinhand.c Sat Jan 20 03:07:52 2001 +++ attr-2_note-8/server/stdinhand.c Fri Feb 16 21:23:40 2001 @@ -2518,6 +2518,10 @@ if (sset_is_to_client(cmd)) { notify_player(0, _("Option: %s has been set to %d."), settings[cmd].name, val); + send_note_all(make_category(CBT_INFO, CAO_GAME, CDI_NONE, + CSDI_NONE), + N_("Option: %s has been set to %d."), + AT_USTRING(settings[cmd].name), AT_INT(val)); /* canonify map generator settings( all of which are int ) */ adjust_terrain_param(); /* send any modified game parameters to the clients -- diff -X freeciv/diff_ignore -Nurd attr-2/server/unithand.c attr-2_note-8/server/unithand.c --- attr-2/server/unithand.c Tue Feb 13 18:53:23 2001 +++ attr-2_note-8/server/unithand.c Fri Feb 16 21:23:40 2001 @@ -459,8 +459,15 @@ } send_tile_info(0, punit->x, punit->y); - create_city(pplayer, punit->x, punit->y, name); + pcity=create_city(pplayer, punit->x, punit->y, name); wipe_unit(punit); + + send_note_xy_player(pplayer, pcity->x, pcity->y, + make_category(CBT_SUCCESS, CAO_OWN_CITY, CDI_NONE, + CSDI_NONE), + N_("Game: New city with name %s founded at (%d,%d)"), + AT_CITY(pcity->id), AT_INT(pcity->x), + AT_INT(pcity->y)); } /************************************************************************** @@ -703,6 +710,11 @@ struct player *pplayer = unit_owner(punit); notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, _("Game: You found %d gold."), cred); + send_note_xy_player(pplayer, punit->x, punit->y, + make_category(CBT_INFO, CAO_OWN_NATION, CDI_GOLD, + CSDI_NONE), + N_("Game: You found %d gold."), AT_INT(cred)); + pplayer->economic.gold += cred; } @@ -731,6 +743,11 @@ const char *tech_name = advances[new_tech].name; notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, _("Game: You gain knowledge about %s."), tech_name); + send_note_xy_player(pplayer, punit->x, punit->y, + make_category(CBT_INFO, CAO_OWN_NATION, CDI_TECH, + CSDI_NONE), + N_("Game: You gain knowledge about %s."), + AT_TECH(new_tech)); gamelog(GAMELOG_TECH,"%s discover %s (Hut)", get_nation_name_plural(pplayer->nation), tech_name);