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 19:18:38 -0700
Reply-to: bugs@xxxxxxxxxxx

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

This version does some renaming and moving stuff around.

-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  5 Aug 2005 02:15:34 -0000
@@ -145,6 +145,8 @@ civclient_SOURCES = $(ESD_FILES) $(SDL_F
        colors_common.h         \
        control.c       \
        control.h       \
+       editor.c                \
+       editor.h                \
        goto.c          \
        goto.h          \
        helpdata.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  5 Aug 2005 02:15:34 -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  5 Aug 2005 02:15:34 -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    5 Aug 2005 02:15:35 -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    5 Aug 2005 02:15:35 -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/editor.c
===================================================================
RCS file: client/editor.c
diff -N client/editor.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ client/editor.c     5 Aug 2005 02:15:35 -0000
@@ -0,0 +1,370 @@
+/********************************************************************** 
+ 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 <string.h>
+
+#include "support.h"
+
+#include "game.h"
+#include "map.h"
+#include "packets.h"
+
+#include "clinet.h"
+#include "control.h"
+#include "editor.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;
+
+/******************************************************************
+ ...
+*******************************************************************/
+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;
+}
+
+/****************************************************************************
+ 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
+
+/****************************************************************************
+ 
+****************************************************************************/
+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;
+  } 
+}
+/****************************************************************************
+ 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;
+  }
+}
Index: client/editor.h
===================================================================
RCS file: client/editor.h
diff -N client/editor.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ client/editor.h     5 Aug 2005 02:15:35 -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/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     5 Aug 2005 02:15:35 -0000
@@ -31,16 +31,16 @@
 #include "clinet.h"
 #include "cma_core.h"
 #include "control.h"
+#include "editor.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"
-
 /* Selection Rectangle */
 static int rec_anchor_x, rec_anchor_y;  /* canvas coordinates for anchor */
 static struct tile *rec_canvas_center_tile;
@@ -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/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      5 Aug 2005 02:15:35 -0000
@@ -40,6 +40,8 @@ libguiclient_a_SOURCES = \
        dialogs.h       \
        diplodlg.c      \
        diplodlg.h      \
+       editdlg.c       \
+       editdlg.h       \
        finddlg.c       \
        finddlg.h       \
        gamedlgs.c      \
Index: client/gui-gtk-2.0/editdlg.c
===================================================================
RCS file: client/gui-gtk-2.0/editdlg.c
diff -N client/gui-gtk-2.0/editdlg.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ client/gui-gtk-2.0/editdlg.c        5 Aug 2005 02:15:35 -0000
@@ -0,0 +1,482 @@
+/********************************************************************** 
+ 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 "shared.h"
+#include "support.h"
+
+#include "fcintl.h"
+#include "game.h"
+#include "government.h"
+#include "packets.h"
+
+#include "editor.h"
+
+#include "editdlg.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/editdlg.h
===================================================================
RCS file: client/gui-gtk-2.0/editdlg.h
diff -N client/gui-gtk-2.0/editdlg.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ client/gui-gtk-2.0/editdlg.h        5 Aug 2005 02:15:35 -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: 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   5 Aug 2005 02:15:36 -0000
@@ -39,6 +39,7 @@
 #include "connectdlg.h"
 #include "control.h"
 #include "dialogs.h"
+#include "editdlg.h"
 #include "finddlg.h"
 #include "gotodlg.h"
 #include "graphics.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: 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       5 Aug 2005 02:15:36 -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  5 Aug 2005 02:15:36 -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        5 Aug 2005 02:15:38 -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        5 Aug 2005 02:15:38 -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  5 Aug 2005 02:15:39 -0000
@@ -36,6 +36,7 @@ libcivserver_a_SOURCES = \
                diplhand.h      \
                diplomats.c     \
                diplomats.h     \
+               edithand.c      \
                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   5 Aug 2005 02:15:39 -0000
@@ -0,0 +1,293 @@
+/********************************************************************** 
+ 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 "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/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   5 Aug 2005 02:15:39 -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   5 Aug 2005 02:15:39 -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   5 Aug 2005 02:15:40 -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]