Complete.Org: Mailing Lists: Archives: freeciv-dev: August 2005:
[Freeciv-Dev] Re: (PR#13605) editing the terrain
Home

[Freeciv-Dev] Re: (PR#13605) editing the terrain

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] Re: (PR#13605) editing the terrain
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 4 Aug 2005 13:52:26 -0700
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=13605 >

Mike Kaufman wrote:
> <URL: http://bugs.freeciv.org/Ticket/Display.html?id=13605 >
> 
> here's a patch I started on, but got bogged down on the interface for
> editing player attributes. There's no way in hell it will compile on CVS,
> but you can try it out on a 26 April snapshot. It was working ok for me.

Not bad.  Here's an updated version of the patch.

Aside from local ugliness, this needs a major overhaul however.

- Almost all function and file names are bad.  tools.c and do_unit() are 
meaningless names.

- Sanity checks must be done.  You've written these into the client but 
they have to be done in the server (or better yet in the common code). 
It is easy to create a server crash with the current patch.

- The interface needs more work, naturally.  Probably Vasco should look 
at this.

-jason

Index: client/Makefile.am
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/Makefile.am,v
retrieving revision 1.66
diff -p -u -r1.66 Makefile.am
--- client/Makefile.am  9 May 2005 18:42:18 -0000       1.66
+++ client/Makefile.am  4 Aug 2005 20:48:22 -0000
@@ -171,6 +171,8 @@ civclient_SOURCES = $(ESD_FILES) $(SDL_F
        reqtree.h \
        text.c  \
        text.h  \
+       tools.c \
+       tools.h \
        tilespec.c      \
        tilespec.h      \
        audio.c         \
Index: client/civclient.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/civclient.c,v
retrieving revision 1.229
diff -p -u -r1.229 civclient.c
--- client/civclient.c  1 Aug 2005 06:48:28 -0000       1.229
+++ client/civclient.c  4 Aug 2005 20:48:22 -0000
@@ -98,6 +98,9 @@ bool waiting_for_end_turn = FALSE;
  */
 bool turn_done_sent = FALSE;
 
+/* allow the client to make global edits, but only if has_hack */
+bool edit_mode = FALSE;
+
 /**************************************************************************
   Convert a text string from the internal to the data encoding, when it
   is written to the network.
Index: client/civclient.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/civclient.h,v
retrieving revision 1.40
diff -p -u -r1.40 civclient.h
--- client/civclient.h  1 Jun 2005 00:47:15 -0000       1.40
+++ client/civclient.h  4 Aug 2005 20:48:22 -0000
@@ -50,6 +50,7 @@ extern int  server_port;
 extern bool auto_connect;
 extern bool waiting_for_end_turn;
 extern bool turn_done_sent;
+extern bool edit_mode; /* whether the client is allowed to make global edits */
 
 void wait_till_request_got_processed(int request_id);
 bool client_is_observer(void);
Index: client/control.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.c,v
retrieving revision 1.183
diff -p -u -r1.183 control.c
--- client/control.c    21 Jul 2005 08:07:18 -0000      1.183
+++ client/control.c    4 Aug 2005 20:48:22 -0000
@@ -2298,3 +2298,11 @@ void key_quickselect(enum quickselect_ty
     set_unit_focus_and_select(punit);
   }
 }
+
+/**************************************************************************
+...
+**************************************************************************/
+void key_editor_toggle(void)
+{
+  edit_mode ^= 1; 
+}
Index: client/control.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.h,v
retrieving revision 1.52
diff -p -u -r1.52 control.h
--- client/control.h    21 Jul 2005 08:07:18 -0000      1.52
+++ client/control.h    4 Aug 2005 20:48:22 -0000
@@ -171,6 +171,8 @@ void key_unit_unload_all(void);
 void key_unit_wait(void);
 void key_unit_wakeup_others(void);
 
+void key_editor_toggle(void);
+
 /* don't change this unless you also put more entries in data/Freeciv */
 #define MAX_NUM_UNITS_BELOW 4
 
Index: client/mapctrl_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapctrl_common.c,v
retrieving revision 1.61
diff -p -u -r1.61 mapctrl_common.c
--- client/mapctrl_common.c     3 Aug 2005 16:19:07 -0000       1.61
+++ client/mapctrl_common.c     4 Aug 2005 20:48:23 -0000
@@ -33,13 +33,13 @@
 #include "control.h"
 #include "fcintl.h"
 #include "goto.h"
+#include "mapctrl_common.h"
 #include "mapctrl_g.h"
 #include "mapview_g.h"
 #include "options.h"
 #include "overview_common.h"
 #include "tilespec.h"
-
-#include "mapctrl_common.h"
+#include "tools.h"
 
 /* Selection Rectangle */
 static int rec_anchor_x, rec_anchor_y;  /* canvas coordinates for anchor */
@@ -491,7 +491,9 @@ void action_button_pressed(int canvas_x,
 {
   struct tile *ptile = canvas_pos_to_tile(canvas_x, canvas_y);
 
-  if (can_client_change_view() && ptile) {
+  if (edit_mode) {
+    do_edit_click(ptile);
+  } else if (can_client_change_view() && ptile) {
     /* FIXME: Some actions here will need to check can_client_issue_orders.
      * But all we can check is the lowest common requirement. */
     do_map_click(ptile, qtype);
Index: client/tools.c
===================================================================
RCS file: client/tools.c
diff -N client/tools.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ client/tools.c      4 Aug 2005 20:48:23 -0000
@@ -0,0 +1,377 @@
+/********************************************************************** 
+ Freeciv - Copyright (C) 2005 - The Freeciv Poject
+   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 <config.h>
+#endif
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h> /* DEBUGGING */ 
+#include <string.h>
+
+#include "support.h"
+
+#include "game.h"
+#include "map.h"
+#include "packets.h"
+
+#include "clinet.h"
+#include "control.h"
+#include "tools.h"
+
+/* where the selected terrain and specials for editing are stored */
+static enum tool_type selected_tool = TOOL_PAINT;
+static enum tile_special_type selected_special = S_LAST;
+static struct terrain *selected_terrain = NULL;
+static enum paint_type selected_paint_type = PAINT_TERRAIN;
+static struct unit *selected_unit;
+static struct city *selected_city;
+
+static void do_paint(struct tile *ptile);
+static void do_unit(struct tile *ptile);
+static void do_city(struct tile *ptile);
+
+/******************************************************************
+ ...
+*******************************************************************/
+void tools_init(void)
+{ 
+  if (!selected_unit) {
+    selected_unit = create_unit_virtual(game.player_ptr, 0,
+                                       get_unit_type(0),
+                                       0);
+  }
+  if (!selected_city) {
+    selected_city = create_city_virtual(game.player_ptr, NULL, "");
+  }
+}
+
+/**************************************************************************
+ we have to do this or risk all sorts of fireworks in the server and 
+ here in the client. it's adding policy, but then what can we do?
+**************************************************************************/
+static void sanity_check_specials(struct tile *ptile, 
+                                  enum tile_special_type new_special)
+{
+  struct terrain *pterrain = ptile->terrain;
+  
+  if (terrain_has_flag(pterrain, TER_OCEANIC)) {
+    //    tile_clear_special(ptile, S_INFRASTRUCTURE_MASK);
+    tile_clear_special(ptile, S_POLLUTION);
+    tile_clear_special(ptile, S_FALLOUT);
+    tile_clear_special(ptile, S_RIVER);
+    tile_clear_special(ptile, S_HUT);
+  } 
+  
+  if (tile_has_special(ptile, S_RAILROAD)) {
+    tile_set_special(ptile, S_ROAD);
+  }
+
+  if (pterrain != pterrain->mining_result) {
+    tile_clear_special(ptile, S_MINE);
+  } 
+  
+  if (tile_has_special(ptile, S_FARMLAND)) {
+    tile_set_special(ptile, S_IRRIGATION);
+  } 
+  
+  if (pterrain != pterrain->irrigation_result) {
+    tile_clear_special(ptile, S_IRRIGATION);
+    tile_clear_special(ptile, S_FARMLAND);
+  } 
+  
+  if (tile_has_special(ptile, S_MINE)
+      && tile_has_special(ptile, S_IRRIGATION)) {
+    if (new_special == S_MINE) { 
+      tile_clear_special(ptile, S_IRRIGATION);
+      tile_clear_special(ptile, S_FARMLAND);
+    } else {
+      tile_clear_special(ptile, S_MINE);
+    }
+  }
+
+  if (tile_has_special(ptile, S_SPECIAL_1)
+      && tile_has_special(ptile, S_SPECIAL_2)) {
+    if (new_special == S_SPECIAL_1) {
+      tile_clear_special(ptile, S_SPECIAL_2);
+    } else {
+      tile_clear_special(ptile, S_SPECIAL_1);
+    }
+  }
+}
+
+/****************************************************************************
+ accessor function
+****************************************************************************/
+void set_selected_tool_type(enum tool_type type)
+{
+  selected_tool = type;
+}
+
+/****************************************************************************
+ accessor function
+****************************************************************************/
+void set_selected_paint_type(enum paint_type type)
+{
+  selected_paint_type = type;
+}
+
+/****************************************************************************
+ accessor function
+****************************************************************************/
+void set_selected_terrain(struct terrain *pterrain)
+{
+  selected_terrain = pterrain;
+}
+
+/****************************************************************************
+ accessor function
+****************************************************************************/
+void set_selected_special(enum tile_special_type special)
+{
+  selected_special = special;
+}
+
+/****************************************************************************
+ accessor function
+****************************************************************************/
+struct unit *get_selected_unit(void)
+{
+  return selected_unit;
+}
+
+/****************************************************************************
+ accessor function
+****************************************************************************/
+struct city *get_selected_city(void)
+{
+  return selected_city;
+}
+
+/****************************************************************************
+ if the client is in edit_mode, then this function captures clicks on the
+ map canvas.
+****************************************************************************/
+void do_edit_click(struct tile *ptile)
+{
+  switch(selected_tool) {
+  case TOOL_PAINT:
+    do_paint(ptile);
+    break;
+  case TOOL_UNIT:
+    do_unit(ptile);
+    break;
+  case TOOL_CITY:
+    do_city(ptile);
+    break;
+  default:
+    break;
+  }
+}
+
+/****************************************************************************
+ 
+****************************************************************************/
+static void do_paint(struct tile *ptile)
+{
+  struct tile tile = *ptile;
+
+  switch (selected_paint_type) {
+  case PAINT_TERRAIN:
+    dsend_packet_edit_tile(&aconnection, ptile->x, ptile->y,
+                          selected_terrain->index, ptile->special);
+    break;
+  case PAINT_SPECIAL:
+    /* add new special to existing specials on the tile */
+    if (selected_special == S_LAST) {
+      tile_clear_all_specials(&tile);
+    } else {
+      tile_set_special(&tile, selected_special);
+    }
+
+    /* see if new special if allowed. If not, then clear it */
+    sanity_check_specials(&tile, selected_special);
+
+    /* send the result to the server for changing */
+    dsend_packet_edit_tile(&aconnection, ptile->x, ptile->y,
+                           tile.terrain->index, tile.special);
+    break;
+  default:
+    break;
+  } 
+}
+
+/****************************************************************************
+ problem: could be multiple units on a particular tile
+ TODO: edit existing units
+****************************************************************************/
+static void do_unit(struct tile *ptile)
+{
+  struct packet_edit_unit packet;
+
+  packet.create_new = TRUE;
+  packet.id = selected_unit->id;
+  packet.owner = selected_unit->owner->player_no;
+
+  packet.x = ptile->x;
+  packet.y = ptile->y;
+
+  packet.homecity = selected_unit->homecity;
+
+  packet.veteran = selected_unit->veteran;
+  packet.ai = selected_unit->ai.control;
+  packet.paradropped = selected_unit->paradropped;
+  packet.done_moving = selected_unit->done_moving;
+
+  packet.type = selected_unit->type->index;
+
+  if (selected_unit->transported_by == -1) {
+    packet.transported = FALSE;
+    packet.transported_by = 0;
+  } else {
+    packet.transported = TRUE;
+    packet.transported_by = selected_unit->transported_by;
+  }
+
+  packet.unhappiness = selected_unit->unhappiness;
+  output_type_iterate(o) {
+    packet.upkeep[o] = selected_unit->upkeep[o];
+  } output_type_iterate_end;
+
+  packet.movesleft = selected_unit->moves_left;
+  packet.hp = selected_unit->hp;
+  packet.fuel = selected_unit->fuel;
+
+  if (selected_unit->goto_tile) {
+    packet.goto_dest_x = selected_unit->goto_tile->x;
+    packet.goto_dest_y = selected_unit->goto_tile->y;
+  } else {
+    packet.goto_dest_x = 255;
+    packet.goto_dest_y = 255;
+  }
+
+  packet.activity_count = selected_unit->activity_count;
+  packet.activity = selected_unit->activity;
+  packet.activity_target = selected_unit->activity_target;
+  packet.has_orders = FALSE; //selected_unit->has_orders;
+  
+  packet.orders_length = packet.orders_index = 0;
+  packet.orders_repeat = packet.orders_vigilant = FALSE;
+
+  /* TODO: There is more stuff here:
+   *  UINT16 orders_length, orders_index;
+   *  BOOL orders_repeat, orders_vigilant;
+   *  ORDERS orders[MAX_LEN_ROUTE:orders_length];
+   *  DIRECTION orders_dirs[MAX_LEN_ROUTE:orders_length];
+   *  ACTIVITY orders_activities[MAX_LEN_ROUTE:orders_length];
+   */
+
+  send_packet_edit_unit(&aconnection, &packet);
+}
+
+/****************************************************************************
+ basically package_city in citytools.c
+****************************************************************************/
+static void do_city(struct tile *ptile)
+{
+  struct packet_edit_city packet;
+  struct city *pcity = selected_city;
+  char *p;
+  int x, y, i;
+
+  packet.id=pcity->id;
+  packet.owner=pcity->owner->player_no;
+  packet.x = ptile->x;
+  packet.y = ptile->y;
+  sz_strlcpy(packet.name, pcity->name);
+
+  packet.size=pcity->size;
+  for (i=0;i<5;i++) {
+    packet.ppl_happy[i]=pcity->ppl_happy[i];
+    packet.ppl_content[i]=pcity->ppl_content[i];
+    packet.ppl_unhappy[i]=pcity->ppl_unhappy[i];
+    packet.ppl_angry[i]=pcity->ppl_angry[i];
+  }
+  /* The number of data in specilists[] array */
+  packet.specialists_size = SP_COUNT;
+  specialist_type_iterate(sp) {
+    packet.specialists[sp] = pcity->specialists[sp];
+  } specialist_type_iterate_end;
+  for (i = 0; i < NUM_TRADEROUTES; i++) {
+    packet.trade[i]=pcity->trade[i];
+    packet.trade_value[i]=pcity->trade_value[i];
+  }
+
+  output_type_iterate(o) {
+    packet.surplus[o] = pcity->surplus[o];
+    packet.waste[o] = pcity->waste[o];
+    packet.unhappy_penalty[o] = pcity->unhappy_penalty[o];
+    packet.prod[o] = pcity->prod[o];
+    packet.citizen_base[o] = pcity->citizen_base[o];
+    packet.usage[o] = pcity->usage[o];
+  } output_type_iterate_end;
+
+  packet.food_stock=pcity->food_stock;
+  packet.shield_stock=pcity->shield_stock;
+  packet.pollution=pcity->pollution;
+
+  packet.city_options=pcity->city_options;
+
+  packet.is_building_unit = pcity->production.is_unit;
+  packet.currently_building = pcity->production.value;
+
+  packet.turn_last_built=pcity->turn_last_built;
+  packet.turn_founded = pcity->turn_founded;
+  packet.changed_from_is_unit=pcity->changed_from.is_unit;
+  packet.changed_from_id = pcity->changed_from.value;
+  packet.before_change_shields=pcity->before_change_shields;
+  packet.disbanded_shields=pcity->disbanded_shields;
+  packet.caravan_shields=pcity->caravan_shields;
+  packet.last_turns_shield_surplus = pcity->last_turns_shield_surplus;
+
+  copy_worklist(&packet.worklist, &pcity->worklist);
+  packet.diplomat_investigate=FALSE;
+
+  packet.airlift = pcity->airlift;
+  packet.did_buy = pcity->did_buy;
+  packet.did_sell = pcity->did_sell;
+  packet.was_happy = pcity->was_happy;
+  for (y = 0; y < CITY_MAP_SIZE; y++) {
+    for (x = 0; x < CITY_MAP_SIZE; x++) {
+      packet.city_map[x + y * CITY_MAP_SIZE] = get_worker_city(pcity, x, y);
+    }
+  }
+
+  p = packet.improvements;
+
+  impr_type_iterate(i) {
+    *p++ = (city_got_building(pcity, i)) ? '1' : '0';
+  } impr_type_iterate_end;
+
+  *p = '\0';
+
+  send_packet_edit_city(&aconnection, &packet);
+}
+
+#if 0
+/****************************************************************************
+ basically package_city in citytools.c
+****************************************************************************/
+void do_edit_player(void)
+{
+  struct packet_edit_player packet;
+
+  send_packet_edit_city(&aconnection, &packet);
+}
+#endif
Index: client/tools.h
===================================================================
RCS file: client/tools.h
diff -N client/tools.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ client/tools.h      4 Aug 2005 20:48:23 -0000
@@ -0,0 +1,49 @@
+/**********************************************************************
+ Freeciv - Copyright (C) 2005 - The Freeciv Poject
+   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__TOOLS_H
+#define FC__TOOLS_H
+
+#include "fc_types.h"
+
+enum tool_type {
+  TOOL_PAINT,
+  TOOL_UNIT,
+  TOOL_CITY,
+  TOOL_PLAYER,
+  TOOL_DELETE,
+  TOOL_NUM
+};
+
+enum paint_type {
+  PAINT_TERRAIN,
+  PAINT_SPECIAL,
+  PAINT_NUM
+};
+
+typedef void (* ToolFunction) (struct tile *ptile);
+
+void tools_init(void);
+void show_tools(void);
+
+void set_selected_tool_type(enum tool_type type);
+void set_selected_paint_type(enum paint_type type);
+void set_selected_terrain(struct terrain *pterrain);
+void set_selected_special(enum tile_special_type special);
+struct unit *get_selected_unit(void);
+struct city *get_selected_city(void);
+
+
+void do_edit_click(struct tile *ptile);
+
+#endif /* FC__TOOLS_H */
Index: client/gui-gtk-2.0/Makefile.am
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/Makefile.am,v
retrieving revision 1.8
diff -p -u -r1.8 Makefile.am
--- client/gui-gtk-2.0/Makefile.am      23 Mar 2005 18:13:21 -0000      1.8
+++ client/gui-gtk-2.0/Makefile.am      4 Aug 2005 20:48:23 -0000
@@ -85,6 +85,8 @@ libguiclient_a_SOURCES = \
        spaceshipdlg.h  \
        sprite.c        \
        sprite.h        \
+       toolsdlg.c      \
+       toolsdlg.h      \
        wldlg.c         \
        wldlg.h 
 
Index: client/gui-gtk-2.0/menu.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/menu.c,v
retrieving revision 1.82
diff -p -u -r1.82 menu.c
--- client/gui-gtk-2.0/menu.c   21 Jul 2005 08:07:19 -0000      1.82
+++ client/gui-gtk-2.0/menu.c   4 Aug 2005 20:48:23 -0000
@@ -56,6 +56,7 @@
 #include "ratesdlg.h"
 #include "repodlgs.h"
 #include "spaceshipdlg.h"
+#include "toolsdlg.h"
 #include "wldlg.h"
 
 #include "menu.h"
@@ -157,6 +158,9 @@ enum MenuID {
   MENU_REPORT_MESSAGES,
   MENU_REPORT_DEMOGRAPHIC,
   MENU_REPORT_SPACESHIP,
+ 
+  MENU_EDITOR_TOGGLE,
+  MENU_EDITOR_TOOLS,
 
   MENU_HELP_LANGUAGES,
   MENU_HELP_CONNECTING,
@@ -563,6 +567,21 @@ static void reports_menu_callback(gpoint
   }
 }
 
+/****************************************************************** 
+ ... 
+******************************************************************/
+static void editor_menu_callback(gpointer callback_data,
+                                 guint callback_action, GtkWidget *widget)
+{   
+  switch(callback_action) {
+   case MENU_EDITOR_TOGGLE:
+    key_editor_toggle();
+    break;
+   case MENU_EDITOR_TOOLS:
+    show_tools();
+    break;
+  }
+}
 
 /****************************************************************
 ...
@@ -888,6 +907,15 @@ static GtkItemFactoryEntry menu_items[]    
        reports_menu_callback,  MENU_REPORT_DEMOGRAPHIC                         
        },
   { "/" N_("Reports") "/" N_("S_paceship"),            "F12",
        reports_menu_callback,  MENU_REPORT_SPACESHIP                           
        },
+  /* Editor menu ... */
+  { "/" N_("_Editor"),                                 NULL,
+        NULL,                   0,                                      
"<Branch>"      },
+  { "/" N_("_Editor") "/tearoff1",                      NULL,
+        NULL,                   0,                                      
"<Tearoff>"     },
+  { "/" N_("_Editor") "/" N_("Editing Mode"),          NULL,
+       editor_menu_callback,   MENU_EDITOR_TOGGLE,     "<CheckItem>"           
      },
+  { "/" N_("_Editor") "/" N_("_Tools"),                NULL,
+        editor_menu_callback,  MENU_EDITOR_TOOLS                               
       },
   /* Help menu ... */
   { "/" N_("_Help"),                                   NULL,
        NULL,                   0,                                      
"<Branch>"      },
@@ -1279,6 +1307,8 @@ void update_menus(void)
 
     menus_set_active("<main>/_View/_Full Screen", fullscreen_mode);
 
+    menus_set_active("<main>/_Editor/Editing Mode", edit_mode);
+
     /* Remaining part of this function: Update Orders menu */
 
     if (!can_client_issue_orders()) {
Index: client/gui-gtk-2.0/toolsdlg.c
===================================================================
RCS file: client/gui-gtk-2.0/toolsdlg.c
diff -N client/gui-gtk-2.0/toolsdlg.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ client/gui-gtk-2.0/toolsdlg.c       4 Aug 2005 20:48:23 -0000
@@ -0,0 +1,480 @@
+/********************************************************************** 
+ Freeciv - Copyright (C) 2005 - The Freeciv Project
+   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 <config.h>
+#endif
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "fcintl.h"
+#include "game.h"
+#include "government.h"
+#include "packets.h"
+#include "shared.h"
+#include "support.h"
+
+#include "toolsdlg.h"
+#include "tools.h"
+
+#define TABLE_WIDTH 3
+#define TOOL_WIDTH 5
+
+typedef struct {
+  const char *name;
+  int paint;
+} paint_item;
+
+static paint_item *terrains;
+
+static paint_item specials[] = {
+  { "clear", S_LAST },
+  { NULL, S_SPECIAL_1 },
+  { NULL, S_SPECIAL_2 },
+  { NULL, S_ROAD },
+  { NULL, S_IRRIGATION },
+  { NULL, S_RAILROAD },
+  { NULL, S_MINE },
+  { NULL, S_POLLUTION },
+  { NULL, S_HUT },
+  { NULL, S_FORTRESS },
+  { NULL, S_RIVER },
+  { NULL, S_FARMLAND },
+  { NULL, S_AIRBASE },
+  { NULL, S_FALLOUT }
+};
+
+static char *tool_names[TOOL_NUM] = {
+  N_("Paint"), N_("Unit"), N_("City"), N_("Player"), N_("Delete")
+};
+
+#define SPECIALS_NUM ARRAY_SIZE(specials)
+
+static GtkWidget *toolwin;
+static GtkWidget *notebook;
+
+static GList *tool_group;
+static GList *map_group;
+
+static void hide_tools(void);
+static void create_toolsdlg(void);
+static GtkWidget *create_map_palette(void);
+static void toggle_group_callback(GtkWidget *w, gpointer data);
+static void set_selected_paint(GtkWidget *w, gpointer data);
+static void tool_toggled(GtkWidget *widget, int tool);
+
+/****************************************************************************
+ show the toolbox window
+*****************************************************************************/
+void show_tools(void)
+{
+  if (toolwin) {
+    gtk_widget_show(toolwin);
+  } else {
+    create_toolsdlg();
+  }
+}
+
+/******************************************************************
+...
+*******************************************************************/
+static void hide_tools(void)
+{
+  gtk_widget_hide(toolwin);
+}
+
+/******************************************************************
+...
+*******************************************************************/
+static GtkWidget *create_map_palette(void)
+{
+  GtkWidget *button, *vbox;
+  GtkWidget *table = gtk_table_new(12, TABLE_WIDTH, TRUE);
+  int i, j, sig; 
+  int magic[3] = { 0, 5, 11 }; /* magic numbers to make the table look good */
+  int types_num[] = { game.control.terrain_count, SPECIALS_NUM };
+  paint_item *ptype[PAINT_NUM] = { NULL, specials };
+  
+  terrains = fc_realloc(terrains,
+                       game.control.terrain_count * sizeof(*terrains));
+  ptype[0] = terrains;
+  
+  vbox = gtk_vbox_new(TRUE, 5);
+  
+  for(i = 0; i < PAINT_NUM; i++) {
+    for(j = 0; j < types_num[i]; j++) {
+      paint_item *item = &ptype[i][j];
+
+      switch(i) {
+      case PAINT_TERRAIN:
+        item->paint = j;
+        item->name = get_terrain(item->paint)->name;
+        break;
+      case PAINT_SPECIAL:
+        if (!item->name) {
+         item->name = get_special_name(item->paint);
+       }
+        break;
+      }
+
+      button = gtk_toggle_button_new_with_label(item->name);
+
+      gtk_table_attach(GTK_TABLE(table), button,
+                       j % TABLE_WIDTH, j % TABLE_WIDTH + 1,
+                       j / TABLE_WIDTH + magic[i],  
+                       j / TABLE_WIDTH + magic[i] + 1, 
+                       GTK_FILL|GTK_EXPAND, GTK_FILL, 0, 0);
+
+      gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button),
+                                  (i == 0 && j == 0) ? TRUE : FALSE);
+      sig = g_signal_connect(button, "toggled",
+                           G_CALLBACK(set_selected_paint), GINT_TO_POINTER(j));
+      gtk_object_set_data(GTK_OBJECT(button), "paint", GINT_TO_POINTER(i));
+
+      /* add this button to a group */
+      map_group = g_list_append(map_group, button);
+
+      /* add this group and the signal id to widget internal data */
+      g_signal_connect(button, "toggled", G_CALLBACK(toggle_group_callback),
+                       (gpointer)map_group);
+      g_object_set_data(G_OBJECT(button), "sigid", GINT_TO_POINTER(sig));
+    }
+  }
+  
+  set_selected_terrain(get_terrain(terrains[0].paint));
+  gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 5);
+  gtk_widget_show_all(vbox);
+  
+  return vbox;
+}
+
+
+/******************************************************************
+ KILLOFF: this is for demonstration purposes only (and not demonstration of
+          coding goodness to be sure!)
+*******************************************************************/
+static void unit_callback(GtkSpinButton *spinbutton, gpointer data)
+{
+  struct unit *punit = get_selected_unit();
+  int param = GPOINTER_TO_INT(data);
+
+  switch (param) {
+  case 0:
+    punit->owner = get_player(gtk_spin_button_get_value_as_int(spinbutton));
+    break;
+  case 1:
+    punit->type = get_unit_type(gtk_spin_button_get_value_as_int(spinbutton));
+    break;
+  case 2:
+    punit->moves_left = gtk_spin_button_get_value_as_int(spinbutton);
+    break;
+  case 3:
+    punit->activity = gtk_spin_button_get_value_as_int(spinbutton);
+    break;
+  case 4:
+    punit->activity_target = gtk_spin_button_get_value_as_int(spinbutton);
+    break;
+  case 5:
+    punit->activity_count = gtk_spin_button_get_value_as_int(spinbutton);
+    break;
+  default:
+    break;
+  }
+}
+
+/******************************************************************
+ ...
+*******************************************************************/
+static GtkWidget *create_units_palette(void)
+{
+#define NUM_PARAMS 6
+
+  GtkWidget *hbox, *vbox, *label, *sb;
+  GtkAdjustment *adj;
+  int i;
+  struct unit *punit = get_selected_unit();
+
+  const char *names[NUM_PARAMS] = { _("Owner"), _("Type"),
+                                    _("Moves Left"), _("Activity"),
+                                    _("Activity Target"), _("Activity Count") 
};
+  int inits[NUM_PARAMS][3] = {
+    {punit->owner->player_no, 0, game.info.nplayers - 1},
+    {punit->type->index, 0, game.control.num_unit_types - 1},
+    {punit->moves_left, 0, 200},
+    {punit->activity, 0, ACTIVITY_LAST},
+    {punit->activity_target, 0, S_LAST},
+    {punit->activity_count, 0, 200}
+  };
+
+  vbox = gtk_vbox_new(FALSE, 5);
+
+  for (i = 0; i < NUM_PARAMS; i++) {
+    adj = (GtkAdjustment *)gtk_adjustment_new(inits[i][0], inits[i][1], 
+                                              inits[i][2], 1.0, 5.0, 5.0);
+    hbox = gtk_hbox_new(FALSE, 5);
+    sb = gtk_spin_button_new(adj, 1, 0);
+    label = gtk_label_new(names[i]);
+    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox), sb, TRUE, TRUE, 0);
+
+    g_signal_connect(sb, "value-changed", G_CALLBACK(unit_callback),
+                     GINT_TO_POINTER(i));
+  }
+
+  return vbox;
+#undef NUM_PARAMS
+}
+
+/******************************************************************
+ KILLOFF: this is for demonstration purposes only (and not demonstration of
+          coding goodness to be sure!)
+*******************************************************************/
+static void city_callback(GtkSpinButton *spinbutton, gpointer data)
+{
+  struct city *pcity = get_selected_city();
+  int param = GPOINTER_TO_INT(data);
+
+  switch (param) {
+  case 0:
+    pcity->owner = get_player(gtk_spin_button_get_value_as_int(spinbutton));
+    break;
+  case 1:
+    pcity->size = gtk_spin_button_get_value_as_int(spinbutton);
+    break;
+  case 2:
+    pcity->food_stock = gtk_spin_button_get_value_as_int(spinbutton);
+    break;
+  case 3:
+    pcity->shield_stock = gtk_spin_button_get_value_as_int(spinbutton);
+    break;
+  case 4:
+    pcity->pollution = gtk_spin_button_get_value_as_int(spinbutton);
+    break;
+  default:
+    break;
+  }
+}
+
+/******************************************************************
+ ...
+*******************************************************************/
+static GtkWidget *create_city_palette(void)
+{
+#define NUM_PARAMS 5
+
+  GtkWidget *hbox, *vbox, *label, *sb;
+  GtkAdjustment *adj;
+  int i;
+  struct city *pcity = get_selected_city();
+
+  const char *names[NUM_PARAMS] = { _("Owner"), _("Size"),
+                                    _("Food"), _("Shields"),
+                                    _("Pollution") };
+  int inits[NUM_PARAMS][3] = {
+    {pcity->owner->player_no, 0, game.info.nplayers - 1},
+    {pcity->size, 1, 63},
+    {pcity->food_stock, 0, 10000},
+    {pcity->shield_stock, 0, 10000},
+    {pcity->pollution, 0, 2000}
+  };
+
+  vbox = gtk_vbox_new(FALSE, 5);
+
+  for (i = 0; i < NUM_PARAMS; i++) {
+    adj = (GtkAdjustment *)gtk_adjustment_new(inits[i][0], inits[i][1], 
+                                              inits[i][2], 1.0, 5.0, 5.0);
+    hbox = gtk_hbox_new(FALSE, 5);
+    sb = gtk_spin_button_new(adj, 1, 0);
+    label = gtk_label_new(names[i]);
+    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox), sb, TRUE, TRUE, 0);
+
+    g_signal_connect(sb, "value-changed", G_CALLBACK(city_callback),
+                     GINT_TO_POINTER(i));
+  }
+
+  return vbox;
+#undef NUM_PARAMS
+}
+
+#if 0
+/******************************************************************
+ KILLOFF: this is for demonstration purposes only (and not demonstration of
+          coding goodness to be sure!)
+*******************************************************************/
+static void player_callback(GtkSpinButton *spinbutton, gpointer data)
+{
+}
+#endif
+
+/******************************************************************
+ ...
+*******************************************************************/
+static GtkWidget *create_player_palette(void)
+{
+  GtkWidget *vbox;
+
+  vbox = gtk_vbox_new(FALSE, 5);
+
+  return vbox;
+}
+
+/**************************************************************************
+ fill the tools[]-array with the missing values: pixmaps, buttons, ids
+***************************************************************************/
+static void create_tools(GtkWidget *win, GtkWidget *parent)
+{
+  GtkWidget *button, *table;
+  int i, sig;
+
+  table = gtk_table_new(TOOL_WIDTH, 2, FALSE);
+  gtk_box_pack_start(GTK_BOX(parent), table, FALSE, TRUE, 0);
+
+  for (i = 0; i < TOOL_NUM; i++) {
+    button = gtk_toggle_button_new_with_label(tool_names[i]);
+
+    /* must do this here. we can't call tool_toggled on palette creation */
+    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button),
+                                (i == 0) ? TRUE : FALSE);
+
+    sig = g_signal_connect(button, "toggled",
+                           G_CALLBACK(tool_toggled), GINT_TO_POINTER(i));
+
+    tool_group = g_list_append(tool_group, button);
+
+    /* add this group and the signal id to widget internal data */
+    g_signal_connect(button, "toggled", G_CALLBACK(toggle_group_callback),
+                     (gpointer)tool_group);
+    g_object_set_data(G_OBJECT(button), "sigid", GINT_TO_POINTER(sig));
+
+    /* do the rest for both types of buttons */
+    gtk_table_attach(GTK_TABLE(table), button,
+                     i % TOOL_WIDTH, i % TOOL_WIDTH + 1, i / TOOL_WIDTH,
+                     i / TOOL_WIDTH + 1, GTK_FILL, GTK_FILL, 1, 1);
+
+  }
+
+  gtk_widget_show_all(table);
+}
+
+/******************************************************************
+...
+*******************************************************************/
+static void create_toolsdlg(void)
+{
+  GtkWidget *palette, *vbox;
+
+  if (toolwin) {
+    return;
+  }
+
+  tools_init();
+
+  toolwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title(GTK_WINDOW(toolwin), "Tools");
+  gtk_container_set_border_width(GTK_CONTAINER(toolwin), 5);
+  gtk_window_set_policy(GTK_WINDOW(toolwin), FALSE, FALSE, FALSE);
+  g_signal_connect(toolwin, "delete_event", G_CALLBACK(hide_tools), NULL);
+
+  vbox = gtk_vbox_new(FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(toolwin), vbox);
+
+  create_tools(toolwin, vbox);
+  notebook = gtk_notebook_new(); /* apparently, it must be here: set_page... */
+  gtk_box_pack_start(GTK_BOX(vbox), gtk_hseparator_new(), FALSE, FALSE, 2);
+
+  gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
+  gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
+  gtk_box_pack_start(GTK_BOX(vbox), notebook, FALSE, FALSE, 0);
+
+  palette = create_map_palette();
+  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), palette, NULL);
+
+  palette = create_units_palette();
+  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), palette, NULL);
+
+  palette = create_city_palette();
+  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), palette, NULL);
+
+  palette = create_player_palette();
+  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), palette, NULL);
+
+  gtk_widget_show_all(toolwin);
+}
+
+/****************************************************************************
+  callback for button that is in a group. we want to untoggle all the
+  other buttons in the group
+*****************************************************************************/
+static void toggle_group_callback(GtkWidget *w, gpointer data)
+{
+  int i;
+  GList *group = (GList *)data;
+
+  /* untoggle all the other buttons in the group toggle this one */
+  for (i = 0 ; i < g_list_length(group); i++) {
+    GtkWidget *button = (GtkWidget *)g_list_nth_data(group, i);
+    int id = (int)g_object_get_data(G_OBJECT(button), "sigid");
+
+    g_signal_handlers_block_by_func(button,
+                                    G_CALLBACK(toggle_group_callback), data);
+    g_signal_handler_block(button, id);
+    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), (button == w));
+    g_signal_handlers_unblock_by_func(button,
+                                      G_CALLBACK(toggle_group_callback), data);
+    g_signal_handler_unblock(button, id);
+  }
+}
+
+/****************************************************************************
+ select a paint type and depress the particular button
+*****************************************************************************/
+static void set_selected_paint(GtkWidget *w, gpointer data)
+{
+  int id = GPOINTER_TO_INT(data);
+  enum paint_type paint = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(w),
+                                                              "paint"));
+
+  set_selected_paint_type(paint);
+
+  switch(paint){
+  case PAINT_TERRAIN:
+    set_selected_terrain(get_terrain(terrains[id].paint));
+    break;
+  case PAINT_SPECIAL:
+    set_selected_special(specials[id].paint);
+    break;
+  default:
+    break;
+  }
+}
+
+/*****************************************************************************
+ handle the toggle buttons' toggle events
+*****************************************************************************/
+static void tool_toggled(GtkWidget *widget, int tool)
+{
+  set_selected_tool_type(tool);
+  /* switch pages if necessary */
+  gtk_notebook_set_page(GTK_NOTEBOOK(notebook), tool);
+}
+
Index: client/gui-gtk-2.0/toolsdlg.h
===================================================================
RCS file: client/gui-gtk-2.0/toolsdlg.h
diff -N client/gui-gtk-2.0/toolsdlg.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ client/gui-gtk-2.0/toolsdlg.h       4 Aug 2005 20:48:23 -0000
@@ -0,0 +1,22 @@
+/********************************************************************** 
+ Freeciv - Copyright (C) 2005 - The Freeciv Project
+   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__TOOLSDLG_H
+#define FC__TOOLSDLG_H
+
+#include <gtk/gtk.h>
+
+#include "shared.h"
+
+void show_tools(void);
+
+#endif  /* FC__TOOLSDLG_H */
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.363
diff -p -u -r1.363 city.c
--- common/city.c       1 Aug 2005 23:09:36 -0000       1.363
+++ common/city.c       4 Aug 2005 20:48:24 -0000
@@ -2411,7 +2411,15 @@ struct city *create_city_virtual(struct 
   /* Set up the worklist */
   init_worklist(&pcity->worklist);
 
-  {
+  if (!ptile) {
+    /* HACK: if a "dummy" city is created with no tile, the regular
+     * operations to choose a build target would fail.  This situation
+     * probably should be forbidden, but currently it might happen during
+     * map editing.  This fallback may also be dangerous if it gives an
+     * invalid production. */
+    pcity->production.is_unit = TRUE;
+    pcity->production.value = 0;
+  } else {
     struct unit_type *u = best_role_unit(pcity, L_FIRSTBUILD);
 
     if (u) {
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.147
diff -p -u -r1.147 packets.def
--- common/packets.def  1 Aug 2005 22:38:25 -0000       1.147
+++ common/packets.def  4 Aug 2005 20:48:24 -0000
@@ -197,6 +197,8 @@ type BV_FLAGS               = bitvector(bv_flags)
 type BV_ROLES          = bitvector(bv_roles)
 type BV_TERRAIN_FLAGS  = bitvector(bv_terrain_flags)
 type BV_CITY_OPTIONS    = bitvector(bv_city_options)
+type BV_SPECIAL         = bitvector(bv_special)
+type BV_PLAYER          = bitvector(bv_player)
 type DIPLSTATE         = diplstate(struct player_diplstate)
 type VISION            = uint32(unsigned int)
 
@@ -240,7 +242,7 @@ grouped together. There are the followin
   Spaceship
   Ruleset
 
-The last used packet number is 116.
+The last used packet number is 120.
 ****************************************************/
 
 
@@ -1349,3 +1351,126 @@ PACKET_RULESET_EFFECT_REQ=123;sc,lsend
   BOOL negated;
 end
 
+/************** Editing hash packets **********************/
+
+PACKET_EDIT_TILE=120;cs,handle-per-conn,dsend
+  COORD x, y; key
+
+  TERRAIN terrain;
+  BV_SPECIAL special;
+end
+
+PACKET_EDIT_UNIT=117;cs,handle-per-conn,lsend
+  UNIT id; key
+  BOOL create_new;
+  PLAYER owner;
+  COORD x,y;
+  CITY homecity;
+
+  UINT8 veteran;
+  BOOL ai, paradropped;
+  BOOL transported, done_moving;
+
+  UNIT_TYPE type;
+  UNIT transported_by; /* Only valid if transported is set. */
+  UINT8 movesleft, hp, fuel, activity_count;
+  UINT8 unhappiness, upkeep[O_MAX], occupy;
+  COORD goto_dest_x,goto_dest_y;
+  ACTIVITY activity;
+  SPECIAL activity_target;
+
+  BOOL has_orders;
+  UINT16 orders_length, orders_index;
+  BOOL orders_repeat, orders_vigilant;
+  ORDERS orders[MAX_LEN_ROUTE:orders_length];
+  DIRECTION orders_dirs[MAX_LEN_ROUTE:orders_length];
+  ACTIVITY orders_activities[MAX_LEN_ROUTE:orders_length];
+end
+
+PACKET_EDIT_CITY=118;cs,handle-per-conn,lsend
+  CITY id; key
+  PLAYER owner;
+  COORD x,y;
+  STRING name[MAX_LEN_NAME];
+  UINT8 size;
+
+  UINT8 ppl_happy[5], ppl_content[5], ppl_unhappy[5], ppl_angry[5];
+
+  UINT8 specialists_size;
+  UINT8 specialists[SP_MAX:specialists_size];
+
+  SINT16 surplus[O_MAX];
+  UINT16 waste[O_MAX];
+  SINT16 unhappy_penalty[O_MAX];
+  UINT16 prod[O_MAX];
+  SINT16 citizen_base[O_MAX];
+  SINT16 usage[O_MAX];
+  UINT16 food_stock, shield_stock;
+
+  UINT16 trade[NUM_TRADEROUTES];
+  UINT8 trade_value[NUM_TRADEROUTES];
+
+  UINT16 pollution;
+
+  UINT8 currently_building;
+  BOOL is_building_unit;
+
+  TURN turn_last_built;
+  UINT8 changed_from_id;
+  BOOL changed_from_is_unit;
+  UINT16 before_change_shields;
+  UINT16 disbanded_shields;
+  UINT16 caravan_shields;
+  UINT16 last_turns_shield_surplus;
+  
+  WORKLIST worklist;
+
+  BIT_STRING improvements[B_LAST+1];
+  CITY_MAP city_map[CITY_MAP_SIZE * CITY_MAP_SIZE];
+
+  BOOL did_buy, did_sell, was_happy, airlift, diplomat_investigate;
+
+  BV_CITY_OPTIONS city_options;
+  TURN turn_founded;
+end
+
+PACKET_EDIT_PLAYER=119;cs,handle-per-conn,lsend
+  PLAYER playerno; key 
+  STRING name[MAX_LEN_NAME];
+  STRING username[MAX_LEN_NAME];
+
+  BOOL is_observer;
+  BOOL is_male;
+  GOVERNMENT government;
+  GOVERNMENT target_government;
+  BV_PLAYER embassy;
+  UINT8 city_style;
+  NATION nation;
+  TEAM team;
+  BOOL phase_done;
+  TURN nturns_idle;
+  BOOL is_alive;
+
+  DIPLSTATE diplstates[MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS];
+  
+  GOLD gold;
+  PERCENT tax, science,luxury;
+
+  UINT16 bulbs_last_turn;
+  UINT32 bulbs_researched;
+  UINT32 techs_researched;
+  UINT8 researching;
+  UINT16 science_cost;
+
+  UINT16 future_tech;
+  UINT8 tech_goal;
+  BOOL is_connected;
+  TURN revolution_finishes;
+  BOOL ai;
+  UINT8 barbarian_type;
+  uint32(unsigned int) gives_shared_vision;
+  BIT_STRING inventions[A_LAST+1];
+  SINT16 love[MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS];
+
+  UINT16 small_wonders[B_LAST]; diff
+end
Index: common/packets_gen.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets_gen.c,v
retrieving revision 1.146
diff -p -u -r1.146 packets_gen.c
--- common/packets_gen.c        1 Aug 2005 22:38:25 -0000       1.146
+++ common/packets_gen.c        4 Aug 2005 20:48:25 -0000
@@ -386,6 +386,18 @@ void *get_packet_from_connection_helper(
   case PACKET_RULESET_EFFECT_REQ:
     return receive_packet_ruleset_effect_req(pc, type);
 
+  case PACKET_EDIT_TILE:
+    return receive_packet_edit_tile(pc, type);
+
+  case PACKET_EDIT_UNIT:
+    return receive_packet_edit_unit(pc, type);
+
+  case PACKET_EDIT_CITY:
+    return receive_packet_edit_city(pc, type);
+
+  case PACKET_EDIT_PLAYER:
+    return receive_packet_edit_player(pc, type);
+
   default:
     freelog(LOG_ERROR, "unknown packet type %d received from %s",
            type, conn_description(pc));
@@ -740,6 +752,18 @@ const char *get_packet_name(enum packet_
   case PACKET_RULESET_EFFECT_REQ:
     return "PACKET_RULESET_EFFECT_REQ";
 
+  case PACKET_EDIT_TILE:
+    return "PACKET_EDIT_TILE";
+
+  case PACKET_EDIT_UNIT:
+    return "PACKET_EDIT_UNIT";
+
+  case PACKET_EDIT_CITY:
+    return "PACKET_EDIT_CITY";
+
+  case PACKET_EDIT_PLAYER:
+    return "PACKET_EDIT_PLAYER";
+
   default:
     return "unknown";
   }
@@ -28272,3 +28296,2654 @@ void lsend_packet_ruleset_effect_req(str
   } conn_list_iterate_end;
 }
 
+static unsigned int hash_packet_edit_tile_100(const void *vkey, unsigned int 
num_buckets)
+{
+  const struct packet_edit_tile *key = (const struct packet_edit_tile *) vkey;
+
+  return (((key->x << 8) ^ key->y) % num_buckets);
+}
+
+static int cmp_packet_edit_tile_100(const void *vkey1, const void *vkey2)
+{
+  const struct packet_edit_tile *key1 = (const struct packet_edit_tile *) 
vkey1;
+  const struct packet_edit_tile *key2 = (const struct packet_edit_tile *) 
vkey2;
+  int diff;
+
+  diff = key1->x - key2->x;
+  if (diff != 0) {
+    return diff;
+  }
+
+  diff = key1->y - key2->y;
+  if (diff != 0) {
+    return diff;
+  }
+
+  return 0;
+}
+
+BV_DEFINE(packet_edit_tile_100_fields, 2);
+
+static struct packet_edit_tile *receive_packet_edit_tile_100(struct connection 
*pc, enum packet_type type)
+{
+  packet_edit_tile_100_fields fields;
+  struct packet_edit_tile *old;
+  struct hash_table **hash = &pc->phs.received[type];
+  struct packet_edit_tile *clone;
+  RECEIVE_PACKET_START(packet_edit_tile, real_packet);
+
+  DIO_BV_GET(&din, fields);
+  {
+    int readin;
+  
+    dio_get_uint8(&din, &readin);
+    real_packet->x = readin;
+  }
+  {
+    int readin;
+  
+    dio_get_uint8(&din, &readin);
+    real_packet->y = readin;
+  }
+
+
+  if (!*hash) {
+    *hash = hash_new(hash_packet_edit_tile_100, cmp_packet_edit_tile_100);
+  }
+  old = hash_delete_entry(*hash, real_packet);
+
+  if (old) {
+    *real_packet = *old;
+  } else {
+    int x = real_packet->x;
+    int y = real_packet->y;
+
+    memset(real_packet, 0, sizeof(*real_packet));
+
+    real_packet->x = x;
+    real_packet->y = y;
+  }
+
+  if (BV_ISSET(fields, 0)) {
+    {
+      int readin;
+    
+      dio_get_sint16(&din, &readin);
+      real_packet->terrain = readin;
+    }
+  }
+  if (BV_ISSET(fields, 1)) {
+    DIO_BV_GET(&din, real_packet->special);
+  }
+
+  clone = fc_malloc(sizeof(*clone));
+  *clone = *real_packet;
+  if (old) {
+    free(old);
+  }
+  hash_insert(*hash, clone, clone);
+
+  RECEIVE_PACKET_END(real_packet);
+}
+
+static int send_packet_edit_tile_100(struct connection *pc, const struct 
packet_edit_tile *packet)
+{
+  const struct packet_edit_tile *real_packet = packet;
+  packet_edit_tile_100_fields fields;
+  struct packet_edit_tile *old, *clone;
+  bool differ, old_from_hash, force_send_of_unchanged = TRUE;
+  struct hash_table **hash = &pc->phs.sent[PACKET_EDIT_TILE];
+  int different = 0;
+  SEND_PACKET_START(PACKET_EDIT_TILE);
+
+  if (!*hash) {
+    *hash = hash_new(hash_packet_edit_tile_100, cmp_packet_edit_tile_100);
+  }
+  BV_CLR_ALL(fields);
+
+  old = hash_lookup_data(*hash, real_packet);
+  old_from_hash = (old != NULL);
+  if (!old) {
+    old = fc_malloc(sizeof(*old));
+    memset(old, 0, sizeof(*old));
+    force_send_of_unchanged = TRUE;
+  }
+
+  differ = (old->terrain != real_packet->terrain);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 0);}
+
+  differ = !BV_ARE_EQUAL(old->special, real_packet->special);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 1);}
+
+  if (different == 0 && !force_send_of_unchanged) {
+    return 0;
+  }
+
+  DIO_BV_PUT(&dout, fields);
+  dio_put_uint8(&dout, real_packet->x);
+  dio_put_uint8(&dout, real_packet->y);
+
+  if (BV_ISSET(fields, 0)) {
+    dio_put_sint16(&dout, real_packet->terrain);
+  }
+  if (BV_ISSET(fields, 1)) {
+  DIO_BV_PUT(&dout, packet->special);
+  }
+
+
+  if (old_from_hash) {
+    hash_delete_entry(*hash, old);
+  }
+
+  clone = old;
+
+  *clone = *real_packet;
+  hash_insert(*hash, clone, clone);
+  SEND_PACKET_END;
+}
+
+static void ensure_valid_variant_packet_edit_tile(struct connection *pc)
+{
+  int variant = -1;
+
+  if(pc->phs.variant[PACKET_EDIT_TILE] != -1) {
+    return;
+  }
+
+  if(FALSE) {
+  } else if(TRUE) {
+    variant = 100;
+  } else {
+    die("unknown variant");
+  }
+  pc->phs.variant[PACKET_EDIT_TILE] = variant;
+}
+
+struct packet_edit_tile *receive_packet_edit_tile(struct connection *pc, enum 
packet_type type)
+{
+  if(!pc->used) {
+    freelog(LOG_ERROR,
+           "WARNING: trying to read data from the closed connection %s",
+           conn_description(pc));
+    return NULL;
+  }
+  assert(pc->phs.variant != NULL);
+  if (!pc->is_server) {
+    freelog(LOG_ERROR, "Receiving packet_edit_tile at the client.");
+  }
+  ensure_valid_variant_packet_edit_tile(pc);
+
+  switch(pc->phs.variant[PACKET_EDIT_TILE]) {
+    case 100: return receive_packet_edit_tile_100(pc, type);
+    default: die("unknown variant"); return NULL;
+  }
+}
+
+int send_packet_edit_tile(struct connection *pc, const struct packet_edit_tile 
*packet)
+{
+  if(!pc->used) {
+    freelog(LOG_ERROR,
+           "WARNING: trying to send data to the closed connection %s",
+           conn_description(pc));
+    return -1;
+  }
+  assert(pc->phs.variant != NULL);
+  if (pc->is_server) {
+    freelog(LOG_ERROR, "Sending packet_edit_tile from the server.");
+  }
+  ensure_valid_variant_packet_edit_tile(pc);
+
+  switch(pc->phs.variant[PACKET_EDIT_TILE]) {
+    case 100: return send_packet_edit_tile_100(pc, packet);
+    default: die("unknown variant"); return -1;
+  }
+}
+
+int dsend_packet_edit_tile(struct connection *pc, int x, int y, 
Terrain_type_id terrain, bv_special special)
+{
+  struct packet_edit_tile packet, *real_packet = &packet;
+
+  real_packet->x = x;
+  real_packet->y = y;
+  real_packet->terrain = terrain;
+  real_packet->special = special;
+  
+  return send_packet_edit_tile(pc, real_packet);
+}
+
+static unsigned int hash_packet_edit_unit_100(const void *vkey, unsigned int 
num_buckets)
+{
+  const struct packet_edit_unit *key = (const struct packet_edit_unit *) vkey;
+
+  return ((key->id) % num_buckets);
+}
+
+static int cmp_packet_edit_unit_100(const void *vkey1, const void *vkey2)
+{
+  const struct packet_edit_unit *key1 = (const struct packet_edit_unit *) 
vkey1;
+  const struct packet_edit_unit *key2 = (const struct packet_edit_unit *) 
vkey2;
+  int diff;
+
+  diff = key1->id - key2->id;
+  if (diff != 0) {
+    return diff;
+  }
+
+  return 0;
+}
+
+BV_DEFINE(packet_edit_unit_100_fields, 31);
+
+static struct packet_edit_unit *receive_packet_edit_unit_100(struct connection 
*pc, enum packet_type type)
+{
+  packet_edit_unit_100_fields fields;
+  struct packet_edit_unit *old;
+  struct hash_table **hash = &pc->phs.received[type];
+  struct packet_edit_unit *clone;
+  RECEIVE_PACKET_START(packet_edit_unit, real_packet);
+
+  DIO_BV_GET(&din, fields);
+  {
+    int readin;
+  
+    dio_get_uint16(&din, &readin);
+    real_packet->id = readin;
+  }
+
+
+  if (!*hash) {
+    *hash = hash_new(hash_packet_edit_unit_100, cmp_packet_edit_unit_100);
+  }
+  old = hash_delete_entry(*hash, real_packet);
+
+  if (old) {
+    *real_packet = *old;
+  } else {
+    int id = real_packet->id;
+
+    memset(real_packet, 0, sizeof(*real_packet));
+
+    real_packet->id = id;
+  }
+
+  real_packet->create_new = BV_ISSET(fields, 0);
+  if (BV_ISSET(fields, 1)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->owner = readin;
+    }
+  }
+  if (BV_ISSET(fields, 2)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->x = readin;
+    }
+  }
+  if (BV_ISSET(fields, 3)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->y = readin;
+    }
+  }
+  if (BV_ISSET(fields, 4)) {
+    {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->homecity = readin;
+    }
+  }
+  if (BV_ISSET(fields, 5)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->veteran = readin;
+    }
+  }
+  real_packet->ai = BV_ISSET(fields, 6);
+  real_packet->paradropped = BV_ISSET(fields, 7);
+  real_packet->transported = BV_ISSET(fields, 8);
+  real_packet->done_moving = BV_ISSET(fields, 9);
+  if (BV_ISSET(fields, 10)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->type = readin;
+    }
+  }
+  if (BV_ISSET(fields, 11)) {
+    {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->transported_by = readin;
+    }
+  }
+  if (BV_ISSET(fields, 12)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->movesleft = readin;
+    }
+  }
+  if (BV_ISSET(fields, 13)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->hp = readin;
+    }
+  }
+  if (BV_ISSET(fields, 14)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->fuel = readin;
+    }
+  }
+  if (BV_ISSET(fields, 15)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->activity_count = readin;
+    }
+  }
+  if (BV_ISSET(fields, 16)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->unhappiness = readin;
+    }
+  }
+  if (BV_ISSET(fields, 17)) {
+    
+    {
+      int i;
+    
+      for (i = 0; i < O_MAX; i++) {
+        {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->upkeep[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 18)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->occupy = readin;
+    }
+  }
+  if (BV_ISSET(fields, 19)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->goto_dest_x = readin;
+    }
+  }
+  if (BV_ISSET(fields, 20)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->goto_dest_y = readin;
+    }
+  }
+  if (BV_ISSET(fields, 21)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->activity = readin;
+    }
+  }
+  if (BV_ISSET(fields, 22)) {
+    {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->activity_target = readin;
+    }
+  }
+  real_packet->has_orders = BV_ISSET(fields, 23);
+  if (BV_ISSET(fields, 24)) {
+    {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->orders_length = readin;
+    }
+  }
+  if (BV_ISSET(fields, 25)) {
+    {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->orders_index = readin;
+    }
+  }
+  real_packet->orders_repeat = BV_ISSET(fields, 26);
+  real_packet->orders_vigilant = BV_ISSET(fields, 27);
+  if (BV_ISSET(fields, 28)) {
+    
+    {
+      int i;
+    
+      if(real_packet->orders_length > MAX_LEN_ROUTE) {
+        freelog(LOG_ERROR, "packets_gen.c: WARNING: truncation array");
+        real_packet->orders_length = MAX_LEN_ROUTE;
+      }
+      for (i = 0; i < real_packet->orders_length; i++) {
+        {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->orders[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 29)) {
+    
+    {
+      int i;
+    
+      if(real_packet->orders_length > MAX_LEN_ROUTE) {
+        freelog(LOG_ERROR, "packets_gen.c: WARNING: truncation array");
+        real_packet->orders_length = MAX_LEN_ROUTE;
+      }
+      for (i = 0; i < real_packet->orders_length; i++) {
+        {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->orders_dirs[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 30)) {
+    
+    {
+      int i;
+    
+      if(real_packet->orders_length > MAX_LEN_ROUTE) {
+        freelog(LOG_ERROR, "packets_gen.c: WARNING: truncation array");
+        real_packet->orders_length = MAX_LEN_ROUTE;
+      }
+      for (i = 0; i < real_packet->orders_length; i++) {
+        {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->orders_activities[i] = readin;
+    }
+      }
+    }
+  }
+
+  clone = fc_malloc(sizeof(*clone));
+  *clone = *real_packet;
+  if (old) {
+    free(old);
+  }
+  hash_insert(*hash, clone, clone);
+
+  RECEIVE_PACKET_END(real_packet);
+}
+
+static int send_packet_edit_unit_100(struct connection *pc, const struct 
packet_edit_unit *packet)
+{
+  const struct packet_edit_unit *real_packet = packet;
+  packet_edit_unit_100_fields fields;
+  struct packet_edit_unit *old, *clone;
+  bool differ, old_from_hash, force_send_of_unchanged = TRUE;
+  struct hash_table **hash = &pc->phs.sent[PACKET_EDIT_UNIT];
+  int different = 0;
+  SEND_PACKET_START(PACKET_EDIT_UNIT);
+
+  if (!*hash) {
+    *hash = hash_new(hash_packet_edit_unit_100, cmp_packet_edit_unit_100);
+  }
+  BV_CLR_ALL(fields);
+
+  old = hash_lookup_data(*hash, real_packet);
+  old_from_hash = (old != NULL);
+  if (!old) {
+    old = fc_malloc(sizeof(*old));
+    memset(old, 0, sizeof(*old));
+    force_send_of_unchanged = TRUE;
+  }
+
+  differ = (old->create_new != real_packet->create_new);
+  if(differ) {different++;}
+  if(packet->create_new) {BV_SET(fields, 0);}
+
+  differ = (old->owner != real_packet->owner);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 1);}
+
+  differ = (old->x != real_packet->x);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 2);}
+
+  differ = (old->y != real_packet->y);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 3);}
+
+  differ = (old->homecity != real_packet->homecity);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 4);}
+
+  differ = (old->veteran != real_packet->veteran);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 5);}
+
+  differ = (old->ai != real_packet->ai);
+  if(differ) {different++;}
+  if(packet->ai) {BV_SET(fields, 6);}
+
+  differ = (old->paradropped != real_packet->paradropped);
+  if(differ) {different++;}
+  if(packet->paradropped) {BV_SET(fields, 7);}
+
+  differ = (old->transported != real_packet->transported);
+  if(differ) {different++;}
+  if(packet->transported) {BV_SET(fields, 8);}
+
+  differ = (old->done_moving != real_packet->done_moving);
+  if(differ) {different++;}
+  if(packet->done_moving) {BV_SET(fields, 9);}
+
+  differ = (old->type != real_packet->type);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 10);}
+
+  differ = (old->transported_by != real_packet->transported_by);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 11);}
+
+  differ = (old->movesleft != real_packet->movesleft);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 12);}
+
+  differ = (old->hp != real_packet->hp);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 13);}
+
+  differ = (old->fuel != real_packet->fuel);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 14);}
+
+  differ = (old->activity_count != real_packet->activity_count);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 15);}
+
+  differ = (old->unhappiness != real_packet->unhappiness);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 16);}
+
+
+    {
+      differ = (O_MAX != O_MAX);
+      if(!differ) {
+        int i;
+        for (i = 0; i < O_MAX; i++) {
+          if (old->upkeep[i] != real_packet->upkeep[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 17);}
+
+  differ = (old->occupy != real_packet->occupy);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 18);}
+
+  differ = (old->goto_dest_x != real_packet->goto_dest_x);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 19);}
+
+  differ = (old->goto_dest_y != real_packet->goto_dest_y);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 20);}
+
+  differ = (old->activity != real_packet->activity);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 21);}
+
+  differ = (old->activity_target != real_packet->activity_target);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 22);}
+
+  differ = (old->has_orders != real_packet->has_orders);
+  if(differ) {different++;}
+  if(packet->has_orders) {BV_SET(fields, 23);}
+
+  differ = (old->orders_length != real_packet->orders_length);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 24);}
+
+  differ = (old->orders_index != real_packet->orders_index);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 25);}
+
+  differ = (old->orders_repeat != real_packet->orders_repeat);
+  if(differ) {different++;}
+  if(packet->orders_repeat) {BV_SET(fields, 26);}
+
+  differ = (old->orders_vigilant != real_packet->orders_vigilant);
+  if(differ) {different++;}
+  if(packet->orders_vigilant) {BV_SET(fields, 27);}
+
+
+    {
+      differ = (old->orders_length != real_packet->orders_length);
+      if(!differ) {
+        int i;
+        for (i = 0; i < real_packet->orders_length; i++) {
+          if (old->orders[i] != real_packet->orders[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 28);}
+
+
+    {
+      differ = (old->orders_length != real_packet->orders_length);
+      if(!differ) {
+        int i;
+        for (i = 0; i < real_packet->orders_length; i++) {
+          if (old->orders_dirs[i] != real_packet->orders_dirs[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 29);}
+
+
+    {
+      differ = (old->orders_length != real_packet->orders_length);
+      if(!differ) {
+        int i;
+        for (i = 0; i < real_packet->orders_length; i++) {
+          if (old->orders_activities[i] != real_packet->orders_activities[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 30);}
+
+  if (different == 0 && !force_send_of_unchanged) {
+    return 0;
+  }
+
+  DIO_BV_PUT(&dout, fields);
+  dio_put_uint16(&dout, real_packet->id);
+
+  /* field 0 is folded into the header */
+  if (BV_ISSET(fields, 1)) {
+    dio_put_uint8(&dout, real_packet->owner);
+  }
+  if (BV_ISSET(fields, 2)) {
+    dio_put_uint8(&dout, real_packet->x);
+  }
+  if (BV_ISSET(fields, 3)) {
+    dio_put_uint8(&dout, real_packet->y);
+  }
+  if (BV_ISSET(fields, 4)) {
+    dio_put_uint16(&dout, real_packet->homecity);
+  }
+  if (BV_ISSET(fields, 5)) {
+    dio_put_uint8(&dout, real_packet->veteran);
+  }
+  /* field 6 is folded into the header */
+  /* field 7 is folded into the header */
+  /* field 8 is folded into the header */
+  /* field 9 is folded into the header */
+  if (BV_ISSET(fields, 10)) {
+    dio_put_uint8(&dout, real_packet->type);
+  }
+  if (BV_ISSET(fields, 11)) {
+    dio_put_uint16(&dout, real_packet->transported_by);
+  }
+  if (BV_ISSET(fields, 12)) {
+    dio_put_uint8(&dout, real_packet->movesleft);
+  }
+  if (BV_ISSET(fields, 13)) {
+    dio_put_uint8(&dout, real_packet->hp);
+  }
+  if (BV_ISSET(fields, 14)) {
+    dio_put_uint8(&dout, real_packet->fuel);
+  }
+  if (BV_ISSET(fields, 15)) {
+    dio_put_uint8(&dout, real_packet->activity_count);
+  }
+  if (BV_ISSET(fields, 16)) {
+    dio_put_uint8(&dout, real_packet->unhappiness);
+  }
+  if (BV_ISSET(fields, 17)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < O_MAX; i++) {
+        dio_put_uint8(&dout, real_packet->upkeep[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 18)) {
+    dio_put_uint8(&dout, real_packet->occupy);
+  }
+  if (BV_ISSET(fields, 19)) {
+    dio_put_uint8(&dout, real_packet->goto_dest_x);
+  }
+  if (BV_ISSET(fields, 20)) {
+    dio_put_uint8(&dout, real_packet->goto_dest_y);
+  }
+  if (BV_ISSET(fields, 21)) {
+    dio_put_uint8(&dout, real_packet->activity);
+  }
+  if (BV_ISSET(fields, 22)) {
+    dio_put_uint16(&dout, real_packet->activity_target);
+  }
+  /* field 23 is folded into the header */
+  if (BV_ISSET(fields, 24)) {
+    dio_put_uint16(&dout, real_packet->orders_length);
+  }
+  if (BV_ISSET(fields, 25)) {
+    dio_put_uint16(&dout, real_packet->orders_index);
+  }
+  /* field 26 is folded into the header */
+  /* field 27 is folded into the header */
+  if (BV_ISSET(fields, 28)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < real_packet->orders_length; i++) {
+        dio_put_uint8(&dout, real_packet->orders[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 29)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < real_packet->orders_length; i++) {
+        dio_put_uint8(&dout, real_packet->orders_dirs[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 30)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < real_packet->orders_length; i++) {
+        dio_put_uint8(&dout, real_packet->orders_activities[i]);
+      }
+    } 
+  }
+
+
+  if (old_from_hash) {
+    hash_delete_entry(*hash, old);
+  }
+
+  clone = old;
+
+  *clone = *real_packet;
+  hash_insert(*hash, clone, clone);
+  SEND_PACKET_END;
+}
+
+static void ensure_valid_variant_packet_edit_unit(struct connection *pc)
+{
+  int variant = -1;
+
+  if(pc->phs.variant[PACKET_EDIT_UNIT] != -1) {
+    return;
+  }
+
+  if(FALSE) {
+  } else if(TRUE) {
+    variant = 100;
+  } else {
+    die("unknown variant");
+  }
+  pc->phs.variant[PACKET_EDIT_UNIT] = variant;
+}
+
+struct packet_edit_unit *receive_packet_edit_unit(struct connection *pc, enum 
packet_type type)
+{
+  if(!pc->used) {
+    freelog(LOG_ERROR,
+           "WARNING: trying to read data from the closed connection %s",
+           conn_description(pc));
+    return NULL;
+  }
+  assert(pc->phs.variant != NULL);
+  if (!pc->is_server) {
+    freelog(LOG_ERROR, "Receiving packet_edit_unit at the client.");
+  }
+  ensure_valid_variant_packet_edit_unit(pc);
+
+  switch(pc->phs.variant[PACKET_EDIT_UNIT]) {
+    case 100: return receive_packet_edit_unit_100(pc, type);
+    default: die("unknown variant"); return NULL;
+  }
+}
+
+int send_packet_edit_unit(struct connection *pc, const struct packet_edit_unit 
*packet)
+{
+  if(!pc->used) {
+    freelog(LOG_ERROR,
+           "WARNING: trying to send data to the closed connection %s",
+           conn_description(pc));
+    return -1;
+  }
+  assert(pc->phs.variant != NULL);
+  if (pc->is_server) {
+    freelog(LOG_ERROR, "Sending packet_edit_unit from the server.");
+  }
+  ensure_valid_variant_packet_edit_unit(pc);
+
+  switch(pc->phs.variant[PACKET_EDIT_UNIT]) {
+    case 100: return send_packet_edit_unit_100(pc, packet);
+    default: die("unknown variant"); return -1;
+  }
+}
+
+void lsend_packet_edit_unit(struct conn_list *dest, const struct 
packet_edit_unit *packet)
+{
+  conn_list_iterate(dest, pconn) {
+    send_packet_edit_unit(pconn, packet);
+  } conn_list_iterate_end;
+}
+
+static unsigned int hash_packet_edit_city_100(const void *vkey, unsigned int 
num_buckets)
+{
+  const struct packet_edit_city *key = (const struct packet_edit_city *) vkey;
+
+  return ((key->id) % num_buckets);
+}
+
+static int cmp_packet_edit_city_100(const void *vkey1, const void *vkey2)
+{
+  const struct packet_edit_city *key1 = (const struct packet_edit_city *) 
vkey1;
+  const struct packet_edit_city *key2 = (const struct packet_edit_city *) 
vkey2;
+  int diff;
+
+  diff = key1->id - key2->id;
+  if (diff != 0) {
+    return diff;
+  }
+
+  return 0;
+}
+
+BV_DEFINE(packet_edit_city_100_fields, 41);
+
+static struct packet_edit_city *receive_packet_edit_city_100(struct connection 
*pc, enum packet_type type)
+{
+  packet_edit_city_100_fields fields;
+  struct packet_edit_city *old;
+  struct hash_table **hash = &pc->phs.received[type];
+  struct packet_edit_city *clone;
+  RECEIVE_PACKET_START(packet_edit_city, real_packet);
+
+  DIO_BV_GET(&din, fields);
+  {
+    int readin;
+  
+    dio_get_uint16(&din, &readin);
+    real_packet->id = readin;
+  }
+
+
+  if (!*hash) {
+    *hash = hash_new(hash_packet_edit_city_100, cmp_packet_edit_city_100);
+  }
+  old = hash_delete_entry(*hash, real_packet);
+
+  if (old) {
+    *real_packet = *old;
+  } else {
+    int id = real_packet->id;
+
+    memset(real_packet, 0, sizeof(*real_packet));
+
+    real_packet->id = id;
+  }
+
+  if (BV_ISSET(fields, 0)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->owner = readin;
+    }
+  }
+  if (BV_ISSET(fields, 1)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->x = readin;
+    }
+  }
+  if (BV_ISSET(fields, 2)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->y = readin;
+    }
+  }
+  if (BV_ISSET(fields, 3)) {
+    dio_get_string(&din, real_packet->name, sizeof(real_packet->name));
+  }
+  if (BV_ISSET(fields, 4)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->size = readin;
+    }
+  }
+  if (BV_ISSET(fields, 5)) {
+    
+    {
+      int i;
+    
+      for (i = 0; i < 5; i++) {
+        {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->ppl_happy[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 6)) {
+    
+    {
+      int i;
+    
+      for (i = 0; i < 5; i++) {
+        {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->ppl_content[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 7)) {
+    
+    {
+      int i;
+    
+      for (i = 0; i < 5; i++) {
+        {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->ppl_unhappy[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 8)) {
+    
+    {
+      int i;
+    
+      for (i = 0; i < 5; i++) {
+        {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->ppl_angry[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 9)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->specialists_size = readin;
+    }
+  }
+  if (BV_ISSET(fields, 10)) {
+    
+    {
+      int i;
+    
+      if(real_packet->specialists_size > SP_MAX) {
+        freelog(LOG_ERROR, "packets_gen.c: WARNING: truncation array");
+        real_packet->specialists_size = SP_MAX;
+      }
+      for (i = 0; i < real_packet->specialists_size; i++) {
+        {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->specialists[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 11)) {
+    
+    {
+      int i;
+    
+      for (i = 0; i < O_MAX; i++) {
+        {
+      int readin;
+    
+      dio_get_sint16(&din, &readin);
+      real_packet->surplus[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 12)) {
+    
+    {
+      int i;
+    
+      for (i = 0; i < O_MAX; i++) {
+        {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->waste[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 13)) {
+    
+    {
+      int i;
+    
+      for (i = 0; i < O_MAX; i++) {
+        {
+      int readin;
+    
+      dio_get_sint16(&din, &readin);
+      real_packet->unhappy_penalty[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 14)) {
+    
+    {
+      int i;
+    
+      for (i = 0; i < O_MAX; i++) {
+        {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->prod[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 15)) {
+    
+    {
+      int i;
+    
+      for (i = 0; i < O_MAX; i++) {
+        {
+      int readin;
+    
+      dio_get_sint16(&din, &readin);
+      real_packet->citizen_base[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 16)) {
+    
+    {
+      int i;
+    
+      for (i = 0; i < O_MAX; i++) {
+        {
+      int readin;
+    
+      dio_get_sint16(&din, &readin);
+      real_packet->usage[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 17)) {
+    {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->food_stock = readin;
+    }
+  }
+  if (BV_ISSET(fields, 18)) {
+    {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->shield_stock = readin;
+    }
+  }
+  if (BV_ISSET(fields, 19)) {
+    
+    {
+      int i;
+    
+      for (i = 0; i < NUM_TRADEROUTES; i++) {
+        {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->trade[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 20)) {
+    
+    {
+      int i;
+    
+      for (i = 0; i < NUM_TRADEROUTES; i++) {
+        {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->trade_value[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 21)) {
+    {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->pollution = readin;
+    }
+  }
+  if (BV_ISSET(fields, 22)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->currently_building = readin;
+    }
+  }
+  real_packet->is_building_unit = BV_ISSET(fields, 23);
+  if (BV_ISSET(fields, 24)) {
+    {
+      int readin;
+    
+      dio_get_sint16(&din, &readin);
+      real_packet->turn_last_built = readin;
+    }
+  }
+  if (BV_ISSET(fields, 25)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->changed_from_id = readin;
+    }
+  }
+  real_packet->changed_from_is_unit = BV_ISSET(fields, 26);
+  if (BV_ISSET(fields, 27)) {
+    {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->before_change_shields = readin;
+    }
+  }
+  if (BV_ISSET(fields, 28)) {
+    {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->disbanded_shields = readin;
+    }
+  }
+  if (BV_ISSET(fields, 29)) {
+    {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->caravan_shields = readin;
+    }
+  }
+  if (BV_ISSET(fields, 30)) {
+    {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->last_turns_shield_surplus = readin;
+    }
+  }
+  if (BV_ISSET(fields, 31)) {
+    dio_get_worklist(&din, &real_packet->worklist);
+  }
+  if (BV_ISSET(fields, 32)) {
+    dio_get_bit_string(&din, real_packet->improvements, 
sizeof(real_packet->improvements));
+  }
+  if (BV_ISSET(fields, 33)) {
+    
+    {
+      int i;
+    
+      for (i = 0; i < CITY_MAP_SIZE * CITY_MAP_SIZE; i++) {
+        {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->city_map[i] = readin;
+    }
+      }
+    }
+  }
+  real_packet->did_buy = BV_ISSET(fields, 34);
+  real_packet->did_sell = BV_ISSET(fields, 35);
+  real_packet->was_happy = BV_ISSET(fields, 36);
+  real_packet->airlift = BV_ISSET(fields, 37);
+  real_packet->diplomat_investigate = BV_ISSET(fields, 38);
+  if (BV_ISSET(fields, 39)) {
+    DIO_BV_GET(&din, real_packet->city_options);
+  }
+  if (BV_ISSET(fields, 40)) {
+    {
+      int readin;
+    
+      dio_get_sint16(&din, &readin);
+      real_packet->turn_founded = readin;
+    }
+  }
+
+  clone = fc_malloc(sizeof(*clone));
+  *clone = *real_packet;
+  if (old) {
+    free(old);
+  }
+  hash_insert(*hash, clone, clone);
+
+  RECEIVE_PACKET_END(real_packet);
+}
+
+static int send_packet_edit_city_100(struct connection *pc, const struct 
packet_edit_city *packet)
+{
+  const struct packet_edit_city *real_packet = packet;
+  packet_edit_city_100_fields fields;
+  struct packet_edit_city *old, *clone;
+  bool differ, old_from_hash, force_send_of_unchanged = TRUE;
+  struct hash_table **hash = &pc->phs.sent[PACKET_EDIT_CITY];
+  int different = 0;
+  SEND_PACKET_START(PACKET_EDIT_CITY);
+
+  if (!*hash) {
+    *hash = hash_new(hash_packet_edit_city_100, cmp_packet_edit_city_100);
+  }
+  BV_CLR_ALL(fields);
+
+  old = hash_lookup_data(*hash, real_packet);
+  old_from_hash = (old != NULL);
+  if (!old) {
+    old = fc_malloc(sizeof(*old));
+    memset(old, 0, sizeof(*old));
+    force_send_of_unchanged = TRUE;
+  }
+
+  differ = (old->owner != real_packet->owner);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 0);}
+
+  differ = (old->x != real_packet->x);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 1);}
+
+  differ = (old->y != real_packet->y);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 2);}
+
+  differ = (strcmp(old->name, real_packet->name) != 0);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 3);}
+
+  differ = (old->size != real_packet->size);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 4);}
+
+
+    {
+      differ = (5 != 5);
+      if(!differ) {
+        int i;
+        for (i = 0; i < 5; i++) {
+          if (old->ppl_happy[i] != real_packet->ppl_happy[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 5);}
+
+
+    {
+      differ = (5 != 5);
+      if(!differ) {
+        int i;
+        for (i = 0; i < 5; i++) {
+          if (old->ppl_content[i] != real_packet->ppl_content[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 6);}
+
+
+    {
+      differ = (5 != 5);
+      if(!differ) {
+        int i;
+        for (i = 0; i < 5; i++) {
+          if (old->ppl_unhappy[i] != real_packet->ppl_unhappy[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 7);}
+
+
+    {
+      differ = (5 != 5);
+      if(!differ) {
+        int i;
+        for (i = 0; i < 5; i++) {
+          if (old->ppl_angry[i] != real_packet->ppl_angry[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 8);}
+
+  differ = (old->specialists_size != real_packet->specialists_size);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 9);}
+
+
+    {
+      differ = (old->specialists_size != real_packet->specialists_size);
+      if(!differ) {
+        int i;
+        for (i = 0; i < real_packet->specialists_size; i++) {
+          if (old->specialists[i] != real_packet->specialists[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 10);}
+
+
+    {
+      differ = (O_MAX != O_MAX);
+      if(!differ) {
+        int i;
+        for (i = 0; i < O_MAX; i++) {
+          if (old->surplus[i] != real_packet->surplus[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 11);}
+
+
+    {
+      differ = (O_MAX != O_MAX);
+      if(!differ) {
+        int i;
+        for (i = 0; i < O_MAX; i++) {
+          if (old->waste[i] != real_packet->waste[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 12);}
+
+
+    {
+      differ = (O_MAX != O_MAX);
+      if(!differ) {
+        int i;
+        for (i = 0; i < O_MAX; i++) {
+          if (old->unhappy_penalty[i] != real_packet->unhappy_penalty[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 13);}
+
+
+    {
+      differ = (O_MAX != O_MAX);
+      if(!differ) {
+        int i;
+        for (i = 0; i < O_MAX; i++) {
+          if (old->prod[i] != real_packet->prod[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 14);}
+
+
+    {
+      differ = (O_MAX != O_MAX);
+      if(!differ) {
+        int i;
+        for (i = 0; i < O_MAX; i++) {
+          if (old->citizen_base[i] != real_packet->citizen_base[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 15);}
+
+
+    {
+      differ = (O_MAX != O_MAX);
+      if(!differ) {
+        int i;
+        for (i = 0; i < O_MAX; i++) {
+          if (old->usage[i] != real_packet->usage[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 16);}
+
+  differ = (old->food_stock != real_packet->food_stock);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 17);}
+
+  differ = (old->shield_stock != real_packet->shield_stock);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 18);}
+
+
+    {
+      differ = (NUM_TRADEROUTES != NUM_TRADEROUTES);
+      if(!differ) {
+        int i;
+        for (i = 0; i < NUM_TRADEROUTES; i++) {
+          if (old->trade[i] != real_packet->trade[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 19);}
+
+
+    {
+      differ = (NUM_TRADEROUTES != NUM_TRADEROUTES);
+      if(!differ) {
+        int i;
+        for (i = 0; i < NUM_TRADEROUTES; i++) {
+          if (old->trade_value[i] != real_packet->trade_value[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 20);}
+
+  differ = (old->pollution != real_packet->pollution);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 21);}
+
+  differ = (old->currently_building != real_packet->currently_building);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 22);}
+
+  differ = (old->is_building_unit != real_packet->is_building_unit);
+  if(differ) {different++;}
+  if(packet->is_building_unit) {BV_SET(fields, 23);}
+
+  differ = (old->turn_last_built != real_packet->turn_last_built);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 24);}
+
+  differ = (old->changed_from_id != real_packet->changed_from_id);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 25);}
+
+  differ = (old->changed_from_is_unit != real_packet->changed_from_is_unit);
+  if(differ) {different++;}
+  if(packet->changed_from_is_unit) {BV_SET(fields, 26);}
+
+  differ = (old->before_change_shields != real_packet->before_change_shields);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 27);}
+
+  differ = (old->disbanded_shields != real_packet->disbanded_shields);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 28);}
+
+  differ = (old->caravan_shields != real_packet->caravan_shields);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 29);}
+
+  differ = (old->last_turns_shield_surplus != 
real_packet->last_turns_shield_surplus);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 30);}
+
+  differ = !are_worklists_equal(&old->worklist, &real_packet->worklist);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 31);}
+
+  differ = (strcmp(old->improvements, real_packet->improvements) != 0);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 32);}
+
+
+    {
+      differ = (CITY_MAP_SIZE * CITY_MAP_SIZE != CITY_MAP_SIZE * 
CITY_MAP_SIZE);
+      if(!differ) {
+        int i;
+        for (i = 0; i < CITY_MAP_SIZE * CITY_MAP_SIZE; i++) {
+          if (old->city_map[i] != real_packet->city_map[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 33);}
+
+  differ = (old->did_buy != real_packet->did_buy);
+  if(differ) {different++;}
+  if(packet->did_buy) {BV_SET(fields, 34);}
+
+  differ = (old->did_sell != real_packet->did_sell);
+  if(differ) {different++;}
+  if(packet->did_sell) {BV_SET(fields, 35);}
+
+  differ = (old->was_happy != real_packet->was_happy);
+  if(differ) {different++;}
+  if(packet->was_happy) {BV_SET(fields, 36);}
+
+  differ = (old->airlift != real_packet->airlift);
+  if(differ) {different++;}
+  if(packet->airlift) {BV_SET(fields, 37);}
+
+  differ = (old->diplomat_investigate != real_packet->diplomat_investigate);
+  if(differ) {different++;}
+  if(packet->diplomat_investigate) {BV_SET(fields, 38);}
+
+  differ = !BV_ARE_EQUAL(old->city_options, real_packet->city_options);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 39);}
+
+  differ = (old->turn_founded != real_packet->turn_founded);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 40);}
+
+  if (different == 0 && !force_send_of_unchanged) {
+    return 0;
+  }
+
+  DIO_BV_PUT(&dout, fields);
+  dio_put_uint16(&dout, real_packet->id);
+
+  if (BV_ISSET(fields, 0)) {
+    dio_put_uint8(&dout, real_packet->owner);
+  }
+  if (BV_ISSET(fields, 1)) {
+    dio_put_uint8(&dout, real_packet->x);
+  }
+  if (BV_ISSET(fields, 2)) {
+    dio_put_uint8(&dout, real_packet->y);
+  }
+  if (BV_ISSET(fields, 3)) {
+    dio_put_string(&dout, real_packet->name);
+  }
+  if (BV_ISSET(fields, 4)) {
+    dio_put_uint8(&dout, real_packet->size);
+  }
+  if (BV_ISSET(fields, 5)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < 5; i++) {
+        dio_put_uint8(&dout, real_packet->ppl_happy[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 6)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < 5; i++) {
+        dio_put_uint8(&dout, real_packet->ppl_content[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 7)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < 5; i++) {
+        dio_put_uint8(&dout, real_packet->ppl_unhappy[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 8)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < 5; i++) {
+        dio_put_uint8(&dout, real_packet->ppl_angry[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 9)) {
+    dio_put_uint8(&dout, real_packet->specialists_size);
+  }
+  if (BV_ISSET(fields, 10)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < real_packet->specialists_size; i++) {
+        dio_put_uint8(&dout, real_packet->specialists[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 11)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < O_MAX; i++) {
+        dio_put_sint16(&dout, real_packet->surplus[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 12)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < O_MAX; i++) {
+        dio_put_uint16(&dout, real_packet->waste[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 13)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < O_MAX; i++) {
+        dio_put_sint16(&dout, real_packet->unhappy_penalty[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 14)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < O_MAX; i++) {
+        dio_put_uint16(&dout, real_packet->prod[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 15)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < O_MAX; i++) {
+        dio_put_sint16(&dout, real_packet->citizen_base[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 16)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < O_MAX; i++) {
+        dio_put_sint16(&dout, real_packet->usage[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 17)) {
+    dio_put_uint16(&dout, real_packet->food_stock);
+  }
+  if (BV_ISSET(fields, 18)) {
+    dio_put_uint16(&dout, real_packet->shield_stock);
+  }
+  if (BV_ISSET(fields, 19)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < NUM_TRADEROUTES; i++) {
+        dio_put_uint16(&dout, real_packet->trade[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 20)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < NUM_TRADEROUTES; i++) {
+        dio_put_uint8(&dout, real_packet->trade_value[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 21)) {
+    dio_put_uint16(&dout, real_packet->pollution);
+  }
+  if (BV_ISSET(fields, 22)) {
+    dio_put_uint8(&dout, real_packet->currently_building);
+  }
+  /* field 23 is folded into the header */
+  if (BV_ISSET(fields, 24)) {
+    dio_put_sint16(&dout, real_packet->turn_last_built);
+  }
+  if (BV_ISSET(fields, 25)) {
+    dio_put_uint8(&dout, real_packet->changed_from_id);
+  }
+  /* field 26 is folded into the header */
+  if (BV_ISSET(fields, 27)) {
+    dio_put_uint16(&dout, real_packet->before_change_shields);
+  }
+  if (BV_ISSET(fields, 28)) {
+    dio_put_uint16(&dout, real_packet->disbanded_shields);
+  }
+  if (BV_ISSET(fields, 29)) {
+    dio_put_uint16(&dout, real_packet->caravan_shields);
+  }
+  if (BV_ISSET(fields, 30)) {
+    dio_put_uint16(&dout, real_packet->last_turns_shield_surplus);
+  }
+  if (BV_ISSET(fields, 31)) {
+    dio_put_worklist(&dout, &real_packet->worklist);
+  }
+  if (BV_ISSET(fields, 32)) {
+    dio_put_bit_string(&dout, real_packet->improvements);
+  }
+  if (BV_ISSET(fields, 33)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < CITY_MAP_SIZE * CITY_MAP_SIZE; i++) {
+        dio_put_uint8(&dout, real_packet->city_map[i]);
+      }
+    } 
+  }
+  /* field 34 is folded into the header */
+  /* field 35 is folded into the header */
+  /* field 36 is folded into the header */
+  /* field 37 is folded into the header */
+  /* field 38 is folded into the header */
+  if (BV_ISSET(fields, 39)) {
+  DIO_BV_PUT(&dout, packet->city_options);
+  }
+  if (BV_ISSET(fields, 40)) {
+    dio_put_sint16(&dout, real_packet->turn_founded);
+  }
+
+
+  if (old_from_hash) {
+    hash_delete_entry(*hash, old);
+  }
+
+  clone = old;
+
+  *clone = *real_packet;
+  hash_insert(*hash, clone, clone);
+  SEND_PACKET_END;
+}
+
+static void ensure_valid_variant_packet_edit_city(struct connection *pc)
+{
+  int variant = -1;
+
+  if(pc->phs.variant[PACKET_EDIT_CITY] != -1) {
+    return;
+  }
+
+  if(FALSE) {
+  } else if(TRUE) {
+    variant = 100;
+  } else {
+    die("unknown variant");
+  }
+  pc->phs.variant[PACKET_EDIT_CITY] = variant;
+}
+
+struct packet_edit_city *receive_packet_edit_city(struct connection *pc, enum 
packet_type type)
+{
+  if(!pc->used) {
+    freelog(LOG_ERROR,
+           "WARNING: trying to read data from the closed connection %s",
+           conn_description(pc));
+    return NULL;
+  }
+  assert(pc->phs.variant != NULL);
+  if (!pc->is_server) {
+    freelog(LOG_ERROR, "Receiving packet_edit_city at the client.");
+  }
+  ensure_valid_variant_packet_edit_city(pc);
+
+  switch(pc->phs.variant[PACKET_EDIT_CITY]) {
+    case 100: return receive_packet_edit_city_100(pc, type);
+    default: die("unknown variant"); return NULL;
+  }
+}
+
+int send_packet_edit_city(struct connection *pc, const struct packet_edit_city 
*packet)
+{
+  if(!pc->used) {
+    freelog(LOG_ERROR,
+           "WARNING: trying to send data to the closed connection %s",
+           conn_description(pc));
+    return -1;
+  }
+  assert(pc->phs.variant != NULL);
+  if (pc->is_server) {
+    freelog(LOG_ERROR, "Sending packet_edit_city from the server.");
+  }
+  ensure_valid_variant_packet_edit_city(pc);
+
+  switch(pc->phs.variant[PACKET_EDIT_CITY]) {
+    case 100: return send_packet_edit_city_100(pc, packet);
+    default: die("unknown variant"); return -1;
+  }
+}
+
+void lsend_packet_edit_city(struct conn_list *dest, const struct 
packet_edit_city *packet)
+{
+  conn_list_iterate(dest, pconn) {
+    send_packet_edit_city(pconn, packet);
+  } conn_list_iterate_end;
+}
+
+static unsigned int hash_packet_edit_player_100(const void *vkey, unsigned int 
num_buckets)
+{
+  const struct packet_edit_player *key = (const struct packet_edit_player *) 
vkey;
+
+  return ((key->playerno) % num_buckets);
+}
+
+static int cmp_packet_edit_player_100(const void *vkey1, const void *vkey2)
+{
+  const struct packet_edit_player *key1 = (const struct packet_edit_player *) 
vkey1;
+  const struct packet_edit_player *key2 = (const struct packet_edit_player *) 
vkey2;
+  int diff;
+
+  diff = key1->playerno - key2->playerno;
+  if (diff != 0) {
+    return diff;
+  }
+
+  return 0;
+}
+
+BV_DEFINE(packet_edit_player_100_fields, 33);
+
+static struct packet_edit_player *receive_packet_edit_player_100(struct 
connection *pc, enum packet_type type)
+{
+  packet_edit_player_100_fields fields;
+  struct packet_edit_player *old;
+  struct hash_table **hash = &pc->phs.received[type];
+  struct packet_edit_player *clone;
+  RECEIVE_PACKET_START(packet_edit_player, real_packet);
+
+  DIO_BV_GET(&din, fields);
+  {
+    int readin;
+  
+    dio_get_uint8(&din, &readin);
+    real_packet->playerno = readin;
+  }
+
+
+  if (!*hash) {
+    *hash = hash_new(hash_packet_edit_player_100, cmp_packet_edit_player_100);
+  }
+  old = hash_delete_entry(*hash, real_packet);
+
+  if (old) {
+    *real_packet = *old;
+  } else {
+    int playerno = real_packet->playerno;
+
+    memset(real_packet, 0, sizeof(*real_packet));
+
+    real_packet->playerno = playerno;
+  }
+
+  if (BV_ISSET(fields, 0)) {
+    dio_get_string(&din, real_packet->name, sizeof(real_packet->name));
+  }
+  if (BV_ISSET(fields, 1)) {
+    dio_get_string(&din, real_packet->username, sizeof(real_packet->username));
+  }
+  real_packet->is_observer = BV_ISSET(fields, 2);
+  real_packet->is_male = BV_ISSET(fields, 3);
+  if (BV_ISSET(fields, 4)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->government = readin;
+    }
+  }
+  if (BV_ISSET(fields, 5)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->target_government = readin;
+    }
+  }
+  if (BV_ISSET(fields, 6)) {
+    DIO_BV_GET(&din, real_packet->embassy);
+  }
+  if (BV_ISSET(fields, 7)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->city_style = readin;
+    }
+  }
+  if (BV_ISSET(fields, 8)) {
+    {
+      int readin;
+    
+      dio_get_sint16(&din, &readin);
+      real_packet->nation = readin;
+    }
+  }
+  if (BV_ISSET(fields, 9)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->team = readin;
+    }
+  }
+  real_packet->phase_done = BV_ISSET(fields, 10);
+  if (BV_ISSET(fields, 11)) {
+    {
+      int readin;
+    
+      dio_get_sint16(&din, &readin);
+      real_packet->nturns_idle = readin;
+    }
+  }
+  real_packet->is_alive = BV_ISSET(fields, 12);
+  if (BV_ISSET(fields, 13)) {
+    
+    {
+      int i;
+    
+      for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
+        dio_get_diplstate(&din, &real_packet->diplstates[i]);
+      }
+    }
+  }
+  if (BV_ISSET(fields, 14)) {
+    {
+      int readin;
+    
+      dio_get_uint32(&din, &readin);
+      real_packet->gold = readin;
+    }
+  }
+  if (BV_ISSET(fields, 15)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->tax = readin;
+    }
+  }
+  if (BV_ISSET(fields, 16)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->science = readin;
+    }
+  }
+  if (BV_ISSET(fields, 17)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->luxury = readin;
+    }
+  }
+  if (BV_ISSET(fields, 18)) {
+    {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->bulbs_last_turn = readin;
+    }
+  }
+  if (BV_ISSET(fields, 19)) {
+    {
+      int readin;
+    
+      dio_get_uint32(&din, &readin);
+      real_packet->bulbs_researched = readin;
+    }
+  }
+  if (BV_ISSET(fields, 20)) {
+    {
+      int readin;
+    
+      dio_get_uint32(&din, &readin);
+      real_packet->techs_researched = readin;
+    }
+  }
+  if (BV_ISSET(fields, 21)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->researching = readin;
+    }
+  }
+  if (BV_ISSET(fields, 22)) {
+    {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->science_cost = readin;
+    }
+  }
+  if (BV_ISSET(fields, 23)) {
+    {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->future_tech = readin;
+    }
+  }
+  if (BV_ISSET(fields, 24)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->tech_goal = readin;
+    }
+  }
+  real_packet->is_connected = BV_ISSET(fields, 25);
+  if (BV_ISSET(fields, 26)) {
+    {
+      int readin;
+    
+      dio_get_sint16(&din, &readin);
+      real_packet->revolution_finishes = readin;
+    }
+  }
+  real_packet->ai = BV_ISSET(fields, 27);
+  if (BV_ISSET(fields, 28)) {
+    {
+      int readin;
+    
+      dio_get_uint8(&din, &readin);
+      real_packet->barbarian_type = readin;
+    }
+  }
+  if (BV_ISSET(fields, 29)) {
+    {
+      int readin;
+    
+      dio_get_uint32(&din, &readin);
+      real_packet->gives_shared_vision = readin;
+    }
+  }
+  if (BV_ISSET(fields, 30)) {
+    dio_get_bit_string(&din, real_packet->inventions, 
sizeof(real_packet->inventions));
+  }
+  if (BV_ISSET(fields, 31)) {
+    
+    {
+      int i;
+    
+      for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
+        {
+      int readin;
+    
+      dio_get_sint16(&din, &readin);
+      real_packet->love[i] = readin;
+    }
+      }
+    }
+  }
+  if (BV_ISSET(fields, 32)) {
+    
+    for (;;) {
+      int i;
+    
+      dio_get_uint8(&din, &i);
+      if(i == 255) {
+        break;
+      }
+      if(i > B_LAST) {
+        freelog(LOG_ERROR, "packets_gen.c: WARNING: ignoring intra array 
diff");
+      } else {
+        {
+      int readin;
+    
+      dio_get_uint16(&din, &readin);
+      real_packet->small_wonders[i] = readin;
+    }
+      }
+    }
+  }
+
+  clone = fc_malloc(sizeof(*clone));
+  *clone = *real_packet;
+  if (old) {
+    free(old);
+  }
+  hash_insert(*hash, clone, clone);
+
+  RECEIVE_PACKET_END(real_packet);
+}
+
+static int send_packet_edit_player_100(struct connection *pc, const struct 
packet_edit_player *packet)
+{
+  const struct packet_edit_player *real_packet = packet;
+  packet_edit_player_100_fields fields;
+  struct packet_edit_player *old, *clone;
+  bool differ, old_from_hash, force_send_of_unchanged = TRUE;
+  struct hash_table **hash = &pc->phs.sent[PACKET_EDIT_PLAYER];
+  int different = 0;
+  SEND_PACKET_START(PACKET_EDIT_PLAYER);
+
+  if (!*hash) {
+    *hash = hash_new(hash_packet_edit_player_100, cmp_packet_edit_player_100);
+  }
+  BV_CLR_ALL(fields);
+
+  old = hash_lookup_data(*hash, real_packet);
+  old_from_hash = (old != NULL);
+  if (!old) {
+    old = fc_malloc(sizeof(*old));
+    memset(old, 0, sizeof(*old));
+    force_send_of_unchanged = TRUE;
+  }
+
+  differ = (strcmp(old->name, real_packet->name) != 0);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 0);}
+
+  differ = (strcmp(old->username, real_packet->username) != 0);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 1);}
+
+  differ = (old->is_observer != real_packet->is_observer);
+  if(differ) {different++;}
+  if(packet->is_observer) {BV_SET(fields, 2);}
+
+  differ = (old->is_male != real_packet->is_male);
+  if(differ) {different++;}
+  if(packet->is_male) {BV_SET(fields, 3);}
+
+  differ = (old->government != real_packet->government);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 4);}
+
+  differ = (old->target_government != real_packet->target_government);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 5);}
+
+  differ = !BV_ARE_EQUAL(old->embassy, real_packet->embassy);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 6);}
+
+  differ = (old->city_style != real_packet->city_style);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 7);}
+
+  differ = (old->nation != real_packet->nation);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 8);}
+
+  differ = (old->team != real_packet->team);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 9);}
+
+  differ = (old->phase_done != real_packet->phase_done);
+  if(differ) {different++;}
+  if(packet->phase_done) {BV_SET(fields, 10);}
+
+  differ = (old->nturns_idle != real_packet->nturns_idle);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 11);}
+
+  differ = (old->is_alive != real_packet->is_alive);
+  if(differ) {different++;}
+  if(packet->is_alive) {BV_SET(fields, 12);}
+
+
+    {
+      differ = (MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS != MAX_NUM_PLAYERS + 
MAX_NUM_BARBARIANS);
+      if(!differ) {
+        int i;
+        for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
+          if (!are_diplstates_equal(&old->diplstates[i], 
&real_packet->diplstates[i])) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 13);}
+
+  differ = (old->gold != real_packet->gold);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 14);}
+
+  differ = (old->tax != real_packet->tax);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 15);}
+
+  differ = (old->science != real_packet->science);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 16);}
+
+  differ = (old->luxury != real_packet->luxury);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 17);}
+
+  differ = (old->bulbs_last_turn != real_packet->bulbs_last_turn);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 18);}
+
+  differ = (old->bulbs_researched != real_packet->bulbs_researched);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 19);}
+
+  differ = (old->techs_researched != real_packet->techs_researched);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 20);}
+
+  differ = (old->researching != real_packet->researching);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 21);}
+
+  differ = (old->science_cost != real_packet->science_cost);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 22);}
+
+  differ = (old->future_tech != real_packet->future_tech);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 23);}
+
+  differ = (old->tech_goal != real_packet->tech_goal);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 24);}
+
+  differ = (old->is_connected != real_packet->is_connected);
+  if(differ) {different++;}
+  if(packet->is_connected) {BV_SET(fields, 25);}
+
+  differ = (old->revolution_finishes != real_packet->revolution_finishes);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 26);}
+
+  differ = (old->ai != real_packet->ai);
+  if(differ) {different++;}
+  if(packet->ai) {BV_SET(fields, 27);}
+
+  differ = (old->barbarian_type != real_packet->barbarian_type);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 28);}
+
+  differ = (old->gives_shared_vision != real_packet->gives_shared_vision);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 29);}
+
+  differ = (strcmp(old->inventions, real_packet->inventions) != 0);
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 30);}
+
+
+    {
+      differ = (MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS != MAX_NUM_PLAYERS + 
MAX_NUM_BARBARIANS);
+      if(!differ) {
+        int i;
+        for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
+          if (old->love[i] != real_packet->love[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 31);}
+
+
+    {
+      differ = (B_LAST != B_LAST);
+      if(!differ) {
+        int i;
+        for (i = 0; i < B_LAST; i++) {
+          if (old->small_wonders[i] != real_packet->small_wonders[i]) {
+            differ = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  if(differ) {different++;}
+  if(differ) {BV_SET(fields, 32);}
+
+  if (different == 0 && !force_send_of_unchanged) {
+    return 0;
+  }
+
+  DIO_BV_PUT(&dout, fields);
+  dio_put_uint8(&dout, real_packet->playerno);
+
+  if (BV_ISSET(fields, 0)) {
+    dio_put_string(&dout, real_packet->name);
+  }
+  if (BV_ISSET(fields, 1)) {
+    dio_put_string(&dout, real_packet->username);
+  }
+  /* field 2 is folded into the header */
+  /* field 3 is folded into the header */
+  if (BV_ISSET(fields, 4)) {
+    dio_put_uint8(&dout, real_packet->government);
+  }
+  if (BV_ISSET(fields, 5)) {
+    dio_put_uint8(&dout, real_packet->target_government);
+  }
+  if (BV_ISSET(fields, 6)) {
+  DIO_BV_PUT(&dout, packet->embassy);
+  }
+  if (BV_ISSET(fields, 7)) {
+    dio_put_uint8(&dout, real_packet->city_style);
+  }
+  if (BV_ISSET(fields, 8)) {
+    dio_put_sint16(&dout, real_packet->nation);
+  }
+  if (BV_ISSET(fields, 9)) {
+    dio_put_uint8(&dout, real_packet->team);
+  }
+  /* field 10 is folded into the header */
+  if (BV_ISSET(fields, 11)) {
+    dio_put_sint16(&dout, real_packet->nturns_idle);
+  }
+  /* field 12 is folded into the header */
+  if (BV_ISSET(fields, 13)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
+        dio_put_diplstate(&dout, &real_packet->diplstates[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 14)) {
+    dio_put_uint32(&dout, real_packet->gold);
+  }
+  if (BV_ISSET(fields, 15)) {
+    dio_put_uint8(&dout, real_packet->tax);
+  }
+  if (BV_ISSET(fields, 16)) {
+    dio_put_uint8(&dout, real_packet->science);
+  }
+  if (BV_ISSET(fields, 17)) {
+    dio_put_uint8(&dout, real_packet->luxury);
+  }
+  if (BV_ISSET(fields, 18)) {
+    dio_put_uint16(&dout, real_packet->bulbs_last_turn);
+  }
+  if (BV_ISSET(fields, 19)) {
+    dio_put_uint32(&dout, real_packet->bulbs_researched);
+  }
+  if (BV_ISSET(fields, 20)) {
+    dio_put_uint32(&dout, real_packet->techs_researched);
+  }
+  if (BV_ISSET(fields, 21)) {
+    dio_put_uint8(&dout, real_packet->researching);
+  }
+  if (BV_ISSET(fields, 22)) {
+    dio_put_uint16(&dout, real_packet->science_cost);
+  }
+  if (BV_ISSET(fields, 23)) {
+    dio_put_uint16(&dout, real_packet->future_tech);
+  }
+  if (BV_ISSET(fields, 24)) {
+    dio_put_uint8(&dout, real_packet->tech_goal);
+  }
+  /* field 25 is folded into the header */
+  if (BV_ISSET(fields, 26)) {
+    dio_put_sint16(&dout, real_packet->revolution_finishes);
+  }
+  /* field 27 is folded into the header */
+  if (BV_ISSET(fields, 28)) {
+    dio_put_uint8(&dout, real_packet->barbarian_type);
+  }
+  if (BV_ISSET(fields, 29)) {
+    dio_put_uint32(&dout, real_packet->gives_shared_vision);
+  }
+  if (BV_ISSET(fields, 30)) {
+    dio_put_bit_string(&dout, real_packet->inventions);
+  }
+  if (BV_ISSET(fields, 31)) {
+  
+    {
+      int i;
+
+      for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
+        dio_put_sint16(&dout, real_packet->love[i]);
+      }
+    } 
+  }
+  if (BV_ISSET(fields, 32)) {
+  
+    {
+      int i;
+
+      assert(B_LAST < 255);
+
+      for (i = 0; i < B_LAST; i++) {
+        if(old->small_wonders[i] != real_packet->small_wonders[i]) {
+          dio_put_uint8(&dout, i);
+          dio_put_uint16(&dout, real_packet->small_wonders[i]);
+        }
+      }
+      dio_put_uint8(&dout, 255);
+    } 
+  }
+
+
+  if (old_from_hash) {
+    hash_delete_entry(*hash, old);
+  }
+
+  clone = old;
+
+  *clone = *real_packet;
+  hash_insert(*hash, clone, clone);
+  SEND_PACKET_END;
+}
+
+static void ensure_valid_variant_packet_edit_player(struct connection *pc)
+{
+  int variant = -1;
+
+  if(pc->phs.variant[PACKET_EDIT_PLAYER] != -1) {
+    return;
+  }
+
+  if(FALSE) {
+  } else if(TRUE) {
+    variant = 100;
+  } else {
+    die("unknown variant");
+  }
+  pc->phs.variant[PACKET_EDIT_PLAYER] = variant;
+}
+
+struct packet_edit_player *receive_packet_edit_player(struct connection *pc, 
enum packet_type type)
+{
+  if(!pc->used) {
+    freelog(LOG_ERROR,
+           "WARNING: trying to read data from the closed connection %s",
+           conn_description(pc));
+    return NULL;
+  }
+  assert(pc->phs.variant != NULL);
+  if (!pc->is_server) {
+    freelog(LOG_ERROR, "Receiving packet_edit_player at the client.");
+  }
+  ensure_valid_variant_packet_edit_player(pc);
+
+  switch(pc->phs.variant[PACKET_EDIT_PLAYER]) {
+    case 100: return receive_packet_edit_player_100(pc, type);
+    default: die("unknown variant"); return NULL;
+  }
+}
+
+int send_packet_edit_player(struct connection *pc, const struct 
packet_edit_player *packet)
+{
+  if(!pc->used) {
+    freelog(LOG_ERROR,
+           "WARNING: trying to send data to the closed connection %s",
+           conn_description(pc));
+    return -1;
+  }
+  assert(pc->phs.variant != NULL);
+  if (pc->is_server) {
+    freelog(LOG_ERROR, "Sending packet_edit_player from the server.");
+  }
+  ensure_valid_variant_packet_edit_player(pc);
+
+  switch(pc->phs.variant[PACKET_EDIT_PLAYER]) {
+    case 100: return send_packet_edit_player_100(pc, packet);
+    default: die("unknown variant"); return -1;
+  }
+}
+
+void lsend_packet_edit_player(struct conn_list *dest, const struct 
packet_edit_player *packet)
+{
+  conn_list_iterate(dest, pconn) {
+    send_packet_edit_player(pconn, packet);
+  } conn_list_iterate_end;
+}
+
Index: common/packets_gen.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets_gen.h,v
retrieving revision 1.129
diff -p -u -r1.129 packets_gen.h
--- common/packets_gen.h        1 Aug 2005 22:38:25 -0000       1.129
+++ common/packets_gen.h        4 Aug 2005 20:48:26 -0000
@@ -1032,6 +1032,130 @@ struct packet_ruleset_effect_req {
   bool negated;
 };
 
+struct packet_edit_tile {
+  int x;
+  int y;
+  Terrain_type_id terrain;
+  bv_special special;
+};
+
+struct packet_edit_unit {
+  int id;
+  bool create_new;
+  int owner;
+  int x;
+  int y;
+  int homecity;
+  int veteran;
+  bool ai;
+  bool paradropped;
+  bool transported;
+  bool done_moving;
+  Unit_type_id type;
+  int transported_by;
+  int movesleft;
+  int hp;
+  int fuel;
+  int activity_count;
+  int unhappiness;
+  int upkeep[O_MAX];
+  int occupy;
+  int goto_dest_x;
+  int goto_dest_y;
+  enum unit_activity activity;
+  enum tile_special_type activity_target;
+  bool has_orders;
+  int orders_length;
+  int orders_index;
+  bool orders_repeat;
+  bool orders_vigilant;
+  enum unit_orders orders[MAX_LEN_ROUTE];
+  enum direction8 orders_dirs[MAX_LEN_ROUTE];
+  enum unit_activity orders_activities[MAX_LEN_ROUTE];
+};
+
+struct packet_edit_city {
+  int id;
+  int owner;
+  int x;
+  int y;
+  char name[MAX_LEN_NAME];
+  int size;
+  int ppl_happy[5];
+  int ppl_content[5];
+  int ppl_unhappy[5];
+  int ppl_angry[5];
+  int specialists_size;
+  int specialists[SP_MAX];
+  int surplus[O_MAX];
+  int waste[O_MAX];
+  int unhappy_penalty[O_MAX];
+  int prod[O_MAX];
+  int citizen_base[O_MAX];
+  int usage[O_MAX];
+  int food_stock;
+  int shield_stock;
+  int trade[NUM_TRADEROUTES];
+  int trade_value[NUM_TRADEROUTES];
+  int pollution;
+  int currently_building;
+  bool is_building_unit;
+  int turn_last_built;
+  int changed_from_id;
+  bool changed_from_is_unit;
+  int before_change_shields;
+  int disbanded_shields;
+  int caravan_shields;
+  int last_turns_shield_surplus;
+  struct worklist worklist;
+  char improvements[B_LAST+1];
+  enum city_tile_type city_map[CITY_MAP_SIZE * CITY_MAP_SIZE];
+  bool did_buy;
+  bool did_sell;
+  bool was_happy;
+  bool airlift;
+  bool diplomat_investigate;
+  bv_city_options city_options;
+  int turn_founded;
+};
+
+struct packet_edit_player {
+  int playerno;
+  char name[MAX_LEN_NAME];
+  char username[MAX_LEN_NAME];
+  bool is_observer;
+  bool is_male;
+  int government;
+  int target_government;
+  bv_player embassy;
+  int city_style;
+  Nation_type_id nation;
+  int team;
+  bool phase_done;
+  int nturns_idle;
+  bool is_alive;
+  struct player_diplstate diplstates[MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS];
+  int gold;
+  int tax;
+  int science;
+  int luxury;
+  int bulbs_last_turn;
+  int bulbs_researched;
+  int techs_researched;
+  int researching;
+  int science_cost;
+  int future_tech;
+  int tech_goal;
+  bool is_connected;
+  int revolution_finishes;
+  bool ai;
+  int barbarian_type;
+  unsigned int gives_shared_vision;
+  char inventions[A_LAST+1];
+  int love[MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS];
+  int small_wonders[B_LAST];
+};
+
 enum packet_type {
   PACKET_PROCESSING_STARTED,             /* 0 */
   PACKET_PROCESSING_FINISHED,
@@ -1145,6 +1269,10 @@ enum packet_type {
   PACKET_OPTIONS_SETTABLE,
   PACKET_RULESET_CHOICES = 115,
   PACKET_PLAYER_READY,
+  PACKET_EDIT_UNIT,
+  PACKET_EDIT_CITY,
+  PACKET_EDIT_PLAYER,
+  PACKET_EDIT_TILE,                      /* 120 */
   PACKET_RULESET_EFFECT = 122,
   PACKET_RULESET_EFFECT_REQ,
 
@@ -1619,6 +1747,22 @@ struct packet_ruleset_effect_req *receiv
 int send_packet_ruleset_effect_req(struct connection *pc, const struct 
packet_ruleset_effect_req *packet);
 void lsend_packet_ruleset_effect_req(struct conn_list *dest, const struct 
packet_ruleset_effect_req *packet);
 
+struct packet_edit_tile *receive_packet_edit_tile(struct connection *pc, enum 
packet_type type);
+int send_packet_edit_tile(struct connection *pc, const struct packet_edit_tile 
*packet);
+int dsend_packet_edit_tile(struct connection *pc, int x, int y, 
Terrain_type_id terrain, bv_special special);
+
+struct packet_edit_unit *receive_packet_edit_unit(struct connection *pc, enum 
packet_type type);
+int send_packet_edit_unit(struct connection *pc, const struct packet_edit_unit 
*packet);
+void lsend_packet_edit_unit(struct conn_list *dest, const struct 
packet_edit_unit *packet);
+
+struct packet_edit_city *receive_packet_edit_city(struct connection *pc, enum 
packet_type type);
+int send_packet_edit_city(struct connection *pc, const struct packet_edit_city 
*packet);
+void lsend_packet_edit_city(struct conn_list *dest, const struct 
packet_edit_city *packet);
+
+struct packet_edit_player *receive_packet_edit_player(struct connection *pc, 
enum packet_type type);
+int send_packet_edit_player(struct connection *pc, const struct 
packet_edit_player *packet);
+void lsend_packet_edit_player(struct conn_list *dest, const struct 
packet_edit_player *packet);
+
 
 void delta_stats_report(void);
 void delta_stats_reset(void);
Index: server/Makefile.am
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/Makefile.am,v
retrieving revision 1.43
diff -p -u -r1.43 Makefile.am
--- server/Makefile.am  23 Jun 2005 21:58:23 -0000      1.43
+++ server/Makefile.am  4 Aug 2005 20:48:26 -0000
@@ -36,6 +36,8 @@ libcivserver_a_SOURCES = \
                diplhand.h      \
                diplomats.c     \
                diplomats.h     \
+               edithand.c      \
+               edithand.h      \
                gamehand.c      \
                gamehand.h      \
                gamelog.c       \
Index: server/edithand.c
===================================================================
RCS file: server/edithand.c
diff -N server/edithand.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ server/edithand.c   4 Aug 2005 20:48:26 -0000
@@ -0,0 +1,294 @@
+/********************************************************************** 
+ Freeciv - Copyright (C) 2005 - The Freeciv Project
+   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 <config.h>
+#endif
+
+#include <assert.h>
+#include <stdio.h> /* DEBUGGING */
+
+#include "fcintl.h"
+#include "log.h"
+#include "shared.h"
+#include "support.h"
+
+#include "game.h"
+#include "map.h"
+#include "terrain.h"
+
+#include "citytools.h"
+#include "plrhand.h"
+#include "unittools.h"
+#include "hand_gen.h"
+#include "maphand.h"
+
+/**************************************************************************
+ right now there are no checks whatsoever in the server. beware.
+***************************************************************************/
+void handle_edit_tile(struct connection *pc, int x, int y,
+                      Terrain_type_id terrain, bv_special special)
+{
+  struct tile *ptile = map_pos_to_tile(x, y);
+  struct terrain *pterrain = get_terrain(terrain);
+
+  if (pc->access_level != ALLOW_HACK
+      || !ptile || !pterrain) {
+    return;
+  }
+
+  ptile->special = special;
+  tile_change_terrain(ptile, pterrain);
+
+  /* update playertiles and send updates to the clients */
+  update_tile_knowledge(ptile);
+  send_tile_info(NULL, ptile);
+}
+
+/**************************************************************************
+ right now there are no checks whatsoever in the server. beware.
+***************************************************************************/
+void handle_edit_unit(struct connection *pc, struct packet_edit_unit *packet)
+{
+  struct tile *ptile = map_pos_to_tile(packet->x, packet->y);
+  struct unit_type *punittype = get_unit_type(packet->type);
+  struct unit *punit;
+
+  if (pc->access_level != ALLOW_HACK
+      || !ptile || !punittype) {
+    return;
+  }
+
+  /* check if a unit with this id already exists on this tile, if
+   * so, then this is an edit, otherwise, we create a new unit */
+  if (packet->create_new) {
+    punit = create_unit(get_player(packet->owner), ptile, punittype,
+                        packet->veteran, packet->homecity, packet->movesleft);
+  } else {
+    punit = find_unit_by_id(packet->id);
+    if (!punit) {
+      freelog(LOG_ERROR, "can't find unit to edit!");
+      return;
+    } 
+  }
+
+  /* copied from packhand.c:unpackage_unit() probably should go into common */
+  
+  punit->hp = packet->hp;
+  punit->activity = packet->activity;
+  punit->activity_count = packet->activity_count;
+  punit->unhappiness = packet->unhappiness;
+  output_type_iterate(o) {
+    punit->upkeep[o] = packet->upkeep[o];
+  } output_type_iterate_end;
+  punit->ai.control = packet->ai;
+  punit->fuel = packet->fuel;
+  if (is_normal_map_pos(packet->goto_dest_x, packet->goto_dest_y)) {
+    punit->goto_tile = map_pos_to_tile(packet->goto_dest_x,
+                                       packet->goto_dest_y);
+  } else {
+    punit->goto_tile = NULL;
+  }
+  punit->activity_target = packet->activity_target;
+  punit->paradropped = packet->paradropped;
+  punit->done_moving = packet->done_moving;
+  punit->occupy = packet->occupy;
+  if (packet->transported) {
+    punit->transported_by = packet->transported_by;
+  } else {
+    punit->transported_by = -1;
+  }
+  punit->has_orders = packet->has_orders;
+  punit->orders.length = packet->orders_length;
+  punit->orders.index = packet->orders_index;
+  punit->orders.repeat = packet->orders_repeat;
+  punit->orders.vigilant = packet->orders_vigilant;
+  if (punit->has_orders) {
+    int i;
+
+    punit->orders.list
+      = fc_malloc(punit->orders.length * sizeof(*punit->orders.list));
+    for (i = 0; i < punit->orders.length; i++) {
+      punit->orders.list[i].order = packet->orders[i];
+      punit->orders.list[i].dir = packet->orders_dirs[i];
+      punit->orders.list[i].activity = packet->orders_activities[i];
+    }
+  }
+
+  /* update playertiles and send updates to the clients */
+  update_tile_knowledge(ptile);
+  send_tile_info(NULL, ptile);
+
+}
+
+/**************************************************************************
+ right now there are no checks whatsoever in the server. beware.
+***************************************************************************/
+void handle_edit_city(struct connection *pc, struct packet_edit_city *packet)
+{
+  struct tile *ptile = map_pos_to_tile(packet->x, packet->y);
+  struct city *pcity;
+  int i;
+
+  if (pc->access_level != ALLOW_HACK) {
+    return;
+  }
+
+  if ((pcity = tile_get_city(ptile))) {
+    sz_strlcpy(pcity->name, packet->name);
+  } else {
+    /* new city */
+    create_city(get_player(packet->owner), ptile, packet->name);
+    pcity = tile_get_city(ptile);
+  }
+
+  pcity->size = packet->size;
+  for (i = 0; i < 5; i++) {
+    pcity->ppl_happy[i] = packet->ppl_happy[i];
+    pcity->ppl_content[i] = packet->ppl_content[i];
+    pcity->ppl_unhappy[i] = packet->ppl_unhappy[i];
+    pcity->ppl_angry[i] = packet->ppl_angry[i];
+  }
+  specialist_type_iterate(sp) {
+    pcity->specialists[sp] = packet->specialists[sp];
+  } specialist_type_iterate_end;
+
+  pcity->city_options = packet->city_options;
+
+  for (i = 0; i < NUM_TRADEROUTES; i++) {
+    pcity->trade[i]=packet->trade[i];
+    pcity->trade_value[i]=packet->trade_value[i];
+  }
+
+  output_type_iterate(o) {
+    pcity->surplus[o] = packet->surplus[o];
+    pcity->waste[o] = packet->waste[o];
+    pcity->unhappy_penalty[o] = packet->unhappy_penalty[o];
+    pcity->prod[o] = packet->prod[o];
+    pcity->citizen_base[o] = packet->citizen_base[o];
+    pcity->usage[o] = packet->usage[o];
+  } output_type_iterate_end;
+
+  pcity->food_stock = packet->food_stock;
+  pcity->shield_stock = packet->shield_stock;
+  pcity->pollution = packet->pollution;
+
+  pcity->production.is_unit = packet->is_building_unit;
+  pcity->production.value = packet->currently_building;
+
+  copy_worklist(&pcity->worklist, &packet->worklist);
+  pcity->did_buy = packet->did_buy;
+  pcity->did_sell = packet->did_sell;
+  pcity->was_happy = packet->was_happy;
+  pcity->airlift = packet->airlift;
+
+  pcity->turn_last_built = packet->turn_last_built;
+  pcity->turn_founded = packet->turn_founded;
+  pcity->changed_from.is_unit = packet->changed_from_is_unit;
+  pcity->changed_from.value = packet->changed_from_id;
+  pcity->before_change_shields = packet->before_change_shields;
+  pcity->disbanded_shields = packet->disbanded_shields;
+  pcity->caravan_shields = packet->caravan_shields;
+  pcity->last_turns_shield_surplus = packet->last_turns_shield_surplus;
+
+  /* FIXME: and probably a bunch more stuff here */
+
+  /* make everything sane */
+  generic_city_refresh(pcity, TRUE, send_unit_info);
+
+  /* send update back to client */
+  send_city_info(NULL, pcity);  
+}
+
+/**************************************************************************
+ right now there are no checks whatsoever in the server. beware.
+***************************************************************************/
+void handle_edit_player(struct connection *pc, 
+                        struct packet_edit_player *packet)
+{
+  struct player *pplayer;
+  struct player_research *research;
+  int i;
+
+  if (pc->access_level != ALLOW_HACK) {
+    return;
+  }
+
+  pplayer = get_player(packet->playerno);
+
+  if (!pplayer) { 
+    freelog(LOG_ERROR, "can't find player to edit!");
+    return;
+  } 
+
+  sz_strlcpy(pplayer->name, packet->name);
+  sz_strlcpy(pplayer->username, packet->username);  
+
+  pplayer->is_observer = packet->is_observer;
+  pplayer->nation = get_nation_by_idx(packet->nation);
+  pplayer->is_male=packet->is_male;
+  pplayer->team = team_get_by_id(packet->team);
+
+  pplayer->economic.gold=packet->gold;
+  pplayer->economic.tax=packet->tax;
+  pplayer->economic.science=packet->science;
+  pplayer->economic.luxury=packet->luxury;
+  pplayer->government=packet->government;
+  pplayer->target_government = packet->target_government;
+  pplayer->embassy=packet->embassy;
+  pplayer->gives_shared_vision = packet->gives_shared_vision;
+  pplayer->city_style=packet->city_style;
+  for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
+    pplayer->ai.love[i] = packet->love[i];
+  } 
+  
+  for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
+    pplayer->diplstates[i].type = 
+      packet->diplstates[i].type;
+    pplayer->diplstates[i].turns_left =
+      packet->diplstates[i].turns_left;
+    pplayer->diplstates[i].contact_turns_left =
+      packet->diplstates[i].contact_turns_left;
+    pplayer->diplstates[i].has_reason_to_cancel =
+      packet->diplstates[i].has_reason_to_cancel;
+  }
+
+#if 0 /* Reputation no longer exists */
+  pplayer->reputation = packet->reputation;
+#endif
+
+  for (i = 0; i < B_LAST/*game.num_impr_types*/; i++) {
+     pplayer->small_wonders[i] = packet->small_wonders[i];
+  }
+  
+  pplayer->ai.science_cost = packet->science_cost;
+
+  pplayer->bulbs_last_turn = packet->bulbs_last_turn;
+
+  research = get_player_research(pplayer);
+  research->bulbs_researched = packet->bulbs_researched;
+  research->techs_researched = packet->techs_researched;
+  research->researching = packet->researching;
+  research->future_tech = packet->future_tech;
+  research->tech_goal = packet->tech_goal;
+
+  pplayer->is_alive = packet->is_alive;
+  pplayer->ai.barbarian_type = packet->barbarian_type;
+  pplayer->revolution_finishes = packet->revolution_finishes;
+  pplayer->ai.control = packet->ai;
+
+  /* FIXME: and probably a bunch more stuff here */
+
+  /* send update back to client */
+  send_player_info(NULL, pplayer);  
+}
Index: server/edithand.h
===================================================================
RCS file: server/edithand.h
diff -N server/edithand.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ server/edithand.h   4 Aug 2005 20:48:26 -0000
@@ -0,0 +1,22 @@
+/********************************************************************** 
+ Freeciv - Copyright (C) 2005 - The Freeciv Project
+   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__EDITHAND_H
+#define FC__EDITHAND_H
+
+#include "shared.h"
+
+#include "fc_types.h"
+
+
+#endif  /* FC__EDITHAND_H */
Index: server/hand_gen.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/hand_gen.c,v
retrieving revision 1.13
diff -p -u -r1.13 hand_gen.c
--- server/hand_gen.c   22 Jul 2005 15:37:39 -0000      1.13
+++ server/hand_gen.c   4 Aug 2005 20:48:26 -0000
@@ -306,6 +306,26 @@ bool server_handle_packet(enum packet_ty
       ((struct packet_spaceship_place *)packet)->num);
     return TRUE;
 
+  case PACKET_EDIT_TILE:
+    handle_edit_tile(pconn,
+      ((struct packet_edit_tile *)packet)->x,
+      ((struct packet_edit_tile *)packet)->y,
+      ((struct packet_edit_tile *)packet)->terrain,
+      ((struct packet_edit_tile *)packet)->special);
+    return TRUE;
+
+  case PACKET_EDIT_UNIT:
+    handle_edit_unit(pconn, packet);
+    return TRUE;
+
+  case PACKET_EDIT_CITY:
+    handle_edit_city(pconn, packet);
+    return TRUE;
+
+  case PACKET_EDIT_PLAYER:
+    handle_edit_player(pconn, packet);
+    return TRUE;
+
   default:
     return FALSE;
   }
Index: server/hand_gen.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/hand_gen.h,v
retrieving revision 1.16
diff -p -u -r1.16 hand_gen.h
--- server/hand_gen.h   22 Jul 2005 15:37:39 -0000      1.16
+++ server/hand_gen.h   4 Aug 2005 20:48:26 -0000
@@ -72,5 +72,12 @@ void handle_report_req(struct connection
 void handle_conn_pong(struct connection *pc);
 void handle_spaceship_launch(struct player *pplayer);
 void handle_spaceship_place(struct player *pplayer, enum spaceship_place_type 
type, int num);
+void handle_edit_tile(struct connection *pc, int x, int y, Terrain_type_id 
terrain, bv_special special);
+struct packet_edit_unit;
+void handle_edit_unit(struct connection *pc, struct packet_edit_unit *packet);
+struct packet_edit_city;
+void handle_edit_city(struct connection *pc, struct packet_edit_city *packet);
+struct packet_edit_player;
+void handle_edit_player(struct connection *pc, struct packet_edit_player 
*packet);
 
 #endif /* FC__HAND_GEN_H */
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.282
diff -p -u -r1.282 srv_main.c
--- server/srv_main.c   26 Jul 2005 17:21:53 -0000      1.282
+++ server/srv_main.c   4 Aug 2005 20:48:26 -0000
@@ -1004,6 +1004,7 @@ bool handle_packet_input(struct connecti
   pplayer->nturns_idle=0;
 
   if((!pplayer->is_alive || pconn->observer)
+     && pconn->access_level != ALLOW_HACK
      && !(type == PACKET_REPORT_REQ || type == PACKET_CONN_PONG)) {
     freelog(LOG_ERROR, _("Got a packet of type %d from a "
                         "dead or observer player"), type);

[Prev in Thread] Current Thread [Next in Thread]