[Freeciv-Dev] (PR#13605) editing the terrain
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=13605 >
Here is a patch with more improvements.
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 11 Aug 2005 20:37:10 -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 11 Aug 2005 20:37:10 -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 11 Aug 2005 20:37:10 -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 11 Aug 2005 20:37:10 -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 11 Aug 2005 20:37:10 -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 11 Aug 2005 20:37:10 -0000
@@ -0,0 +1,315 @@
+/**********************************************************************
+ 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 editor_tool_type selected_tool = ETOOL_PAINT;
+static enum tile_special_type selected_special = S_LAST;
+static struct terrain *selected_terrain = NULL;
+static enum editor_paint_type selected_paint_type = EPAINT_TERRAIN;
+static struct unit *selected_unit;
+static struct city *selected_city;
+
+/******************************************************************
+ ...
+*******************************************************************/
+void editor_init_tools(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, "");
+ }
+}
+
+/****************************************************************************
+ accessor function
+****************************************************************************/
+void editor_set_selected_tool_type(enum editor_tool_type type)
+{
+ selected_tool = type;
+}
+
+/****************************************************************************
+ accessor function
+****************************************************************************/
+void editor_set_selected_paint_type(enum editor_paint_type type)
+{
+ selected_paint_type = type;
+}
+
+/****************************************************************************
+ accessor function
+****************************************************************************/
+void editor_set_selected_terrain(struct terrain *pterrain)
+{
+ selected_terrain = pterrain;
+}
+
+/****************************************************************************
+ accessor function
+****************************************************************************/
+void editor_set_selected_special(enum tile_special_type special)
+{
+ selected_special = special;
+}
+
+/****************************************************************************
+ accessor function
+****************************************************************************/
+struct unit *editor_get_selected_unit(void)
+{
+ return selected_unit;
+}
+
+/****************************************************************************
+ accessor function
+****************************************************************************/
+struct city *editor_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 EPAINT_TERRAIN:
+ tile.terrain = selected_terrain;
+ break;
+ case EPAINT_SPECIAL:
+ /* add new special to existing specials on the tile */
+ if (selected_special == S_LAST) {
+ tile_clear_all_specials(&tile);
+ } else {
+ tile_clear_special(&tile, selected_special);
+ }
+ break;
+ case EPAINT_LAST:
+ break;
+ }
+
+ /* send the result to the server for changing */
+ dsend_packet_edit_tile(&aconnection, ptile->x, ptile->y,
+ tile.terrain->index, ptile->special);
+}
+
+/****************************************************************************
+ if the client is in edit_mode, then this function captures clicks on the
+ map canvas.
+****************************************************************************/
+void editor_do_click(struct tile *ptile)
+{
+ switch(selected_tool) {
+ case ETOOL_PAINT:
+ do_paint(ptile);
+ break;
+ case ETOOL_UNIT:
+ do_unit(ptile);
+ break;
+ case ETOOL_CITY:
+ do_city(ptile);
+ break;
+ case ETOOL_PLAYER:
+ case ETOOL_DELETE:
+ case ETOOL_LAST:
+ 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 11 Aug 2005 20:37:10 -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 editor_tool_type {
+ ETOOL_PAINT,
+ ETOOL_UNIT,
+ ETOOL_CITY,
+ ETOOL_PLAYER,
+ ETOOL_DELETE,
+ ETOOL_LAST
+};
+
+enum editor_paint_type {
+ EPAINT_TERRAIN,
+ EPAINT_SPECIAL,
+ EPAINT_LAST
+};
+
+typedef void (*ToolFunction)(struct tile *ptile);
+
+void editor_init_tools(void);
+void editor_show_tools(void);
+
+void editor_set_selected_tool_type(enum editor_tool_type type);
+void editor_set_selected_paint_type(enum editor_paint_type type);
+void editor_set_selected_terrain(struct terrain *pterrain);
+void editor_set_selected_special(enum tile_special_type special);
+
+struct unit *editor_get_selected_unit(void);
+struct city *editor_get_selected_city(void);
+
+void editor_do_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 11 Aug 2005 20:37:11 -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) {
+ editor_do_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 11 Aug 2005 20:37:11 -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/dialogs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/dialogs.c,v
retrieving revision 1.114
diff -p -u -r1.114 dialogs.c
--- client/gui-gtk-2.0/dialogs.c 26 Jul 2005 16:35:57 -0000 1.114
+++ client/gui-gtk-2.0/dialogs.c 11 Aug 2005 20:37:11 -0000
@@ -52,6 +52,7 @@
#include "tilespec.h"
#include "dialogs.h"
+#include "editdlg.h"
#include "wldlg.h"
/******************************************************************/
@@ -2192,5 +2193,6 @@ gboolean taxrates_callback(GtkWidget * w
void popdown_all_game_dialogs(void)
{
gui_dialog_destroy_all();
+ editdlg_hide_tools();
}
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 11 Aug 2005 20:37:11 -0000
@@ -0,0 +1,481 @@
+/**********************************************************************
+ Freeciv - Copyright (C) 2005 - The Freeciv Project
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "fcintl.h"
+#include "shared.h"
+#include "support.h"
+
+#include "game.h"
+#include "government.h"
+#include "packets.h"
+
+#include "editor.h"
+
+#include "editdlg.h"
+#include "gui_main.h"
+#include "gui_stuff.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[] = {
+ { N_("clear all"), 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[ETOOL_LAST] = {
+ 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;
+
+/*****************************************************************************
+ handle the toggle buttons' toggle events
+*****************************************************************************/
+static void tool_toggled(GtkWidget *widget, int tool)
+{
+ editor_set_selected_tool_type(tool);
+ /* switch pages if necessary */
+ gtk_notebook_set_page(GTK_NOTEBOOK(notebook), tool);
+}
+
+/****************************************************************************
+ 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);
+ }
+}
+
+/**************************************************************************
+ 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 < ETOOL_LAST; 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);
+}
+
+/****************************************************************************
+ 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 editor_paint_type paint
+ = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(w), "paint"));
+
+ editor_set_selected_paint_type(paint);
+
+ assert(paint >= 0 && paint < EPAINT_LAST);
+ switch(paint){
+ case EPAINT_TERRAIN:
+ editor_set_selected_terrain(get_terrain(terrains[id].paint));
+ break;
+ case EPAINT_SPECIAL:
+ editor_set_selected_special(specials[id].paint);
+ break;
+ case EPAINT_LAST:
+ break;
+ }
+}
+
+/******************************************************************
+ 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 = editor_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;
+ }
+}
+
+/******************************************************************
+ 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 = editor_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;
+ }
+}
+
+#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_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[EPAINT_LAST] = { 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 < EPAINT_LAST; i++) {
+ for(j = 0; j < types_num[i]; j++) {
+ paint_item *item = &ptype[i][j];
+
+ switch(i) {
+ case EPAINT_TERRAIN:
+ item->paint = j;
+ item->name = get_terrain(item->paint)->name;
+ break;
+ case EPAINT_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));
+ }
+ }
+
+ editor_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;
+}
+
+/******************************************************************
+ ...
+*******************************************************************/
+static GtkWidget *create_units_palette(void)
+{
+#define NUM_PARAMS 6
+
+ GtkWidget *hbox, *vbox, *label, *sb;
+ GtkAdjustment *adj;
+ int i;
+ struct unit *punit = editor_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
+}
+
+/******************************************************************
+ ...
+*******************************************************************/
+static GtkWidget *create_city_palette(void)
+{
+#define NUM_PARAMS 5
+
+ GtkWidget *hbox, *vbox, *label, *sb;
+ GtkAdjustment *adj;
+ int i;
+ struct city *pcity = editor_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
+}
+
+/******************************************************************
+ ...
+*******************************************************************/
+static GtkWidget *create_player_palette(void)
+{
+ GtkWidget *vbox;
+
+ vbox = gtk_vbox_new(FALSE, 5);
+
+ return vbox;
+}
+
+/******************************************************************
+...
+*******************************************************************/
+static void create_toolsdlg(void)
+{
+ GtkWidget *palette, *vbox;
+
+ if (toolwin) {
+ return;
+ }
+
+ editor_init_tools();
+
+ toolwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ setup_dialog(toolwin, toplevel);
+ gtk_window_set_title(GTK_WINDOW(toolwin), _("Editing 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(editdlg_hide_tools), NULL);
+ g_signal_connect(toolwin, "destroy",
+ GTK_SIGNAL_FUNC(gtk_widget_destroyed),
+ &toolwin);
+
+ 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);
+}
+
+/****************************************************************************
+ show the editor toolbox window
+****************************************************************************/
+void editdlg_show_tools(void)
+{
+ if (!toolwin) {
+ create_toolsdlg();
+ }
+ gtk_widget_show(toolwin);
+}
+
+/****************************************************************************
+ hide the editor toolbox window
+****************************************************************************/
+void editdlg_hide_tools(void)
+{
+ if (toolwin) {
+ gtk_widget_hide(toolwin);
+ }
+}
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 11 Aug 2005 20:37:11 -0000
@@ -0,0 +1,23 @@
+/**********************************************************************
+ 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 editdlg_show_tools(void);
+void editdlg_hide_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.83
diff -p -u -r1.83 menu.c
--- client/gui-gtk-2.0/menu.c 8 Aug 2005 16:30:22 -0000 1.83
+++ client/gui-gtk-2.0/menu.c 11 Aug 2005 20:37:11 -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"
@@ -156,6 +157,9 @@ enum MenuID {
MENU_REPORT_MESSAGES,
MENU_REPORT_DEMOGRAPHIC,
MENU_REPORT_SPACESHIP,
+
+ MENU_EDITOR_TOGGLE,
+ MENU_EDITOR_TOOLS,
MENU_HELP_LANGUAGES,
MENU_HELP_CONNECTING,
@@ -559,6 +563,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:
+ editdlg_show_tools();
+ break;
+ }
+}
/****************************************************************
...
@@ -882,6 +901,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>" },
@@ -1271,6 +1299,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 11 Aug 2005 20:37:12 -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.150
diff -p -u -r1.150 packets.def
--- common/packets.def 11 Aug 2005 04:43:25 -0000 1.150
+++ common/packets.def 11 Aug 2005 20:37:12 -0000
@@ -198,6 +198,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)
@@ -241,7 +243,7 @@ grouped together. There are the followin
Spaceship
Ruleset
-The last used packet number is 116.
+The last used packet number is 120.
****************************************************/
@@ -1354,3 +1356,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/terrain.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/terrain.h,v
retrieving revision 1.41
diff -p -u -r1.41 terrain.h
--- common/terrain.h 1 Aug 2005 22:38:25 -0000 1.41
+++ common/terrain.h 11 Aug 2005 20:37:12 -0000
@@ -43,6 +43,17 @@ extern enum tile_special_type infrastruc
BV_DEFINE(bv_special, S_LAST);
+#define specials_iterate(special) \
+{ \
+ enum tile_special_type special; \
+ \
+ for (special = 0; special < S_LAST; special++) {
+
+#define specials_iterate_end \
+ } \
+}
+
+
#define T_NONE (NULL) /* A special flag meaning no terrain type. */
#define T_UNKNOWN (NULL) /* An unknown terrain. */
Index: common/tile.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/tile.c,v
retrieving revision 1.12
diff -p -u -r1.12 tile.c
--- common/tile.c 11 Aug 2005 17:26:27 -0000 1.12
+++ common/tile.c 11 Aug 2005 20:37:12 -0000
@@ -219,9 +219,9 @@ void tile_change_terrain(struct tile *pt
tile_clear_infrastructure(ptile);
tile_clear_dirtiness(ptile);
- /* FIXME: When rest of code can handle
- * rivers in oceans, then maybe we can leave it in place. */
+ /* The code can't handle these specials in ocean. */
tile_clear_special(ptile, S_RIVER);
+ tile_clear_special(ptile, S_HUT);
}
/* Clear mining/irrigation if resulting terrain type cannot support
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 11 Aug 2005 20:37:12 -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 11 Aug 2005 20:37:12 -0000
@@ -0,0 +1,304 @@
+/**********************************************************************
+ 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), *old_terrain;
+
+ if (pc->access_level != ALLOW_HACK
+ || !ptile || !pterrain) {
+ return;
+ }
+
+ old_terrain = ptile->terrain;
+
+ specials_iterate(s) {
+ if (contains_special(special, s) && !tile_has_special(ptile, s)) {
+ tile_add_special(ptile, s);
+ } else if (!contains_special(special, s) && tile_has_special(ptile, s)) {
+ tile_remove_special(ptile, s);
+ }
+ } specials_iterate_end;
+ tile_change_terrain(ptile, pterrain);
+
+ /* Handle global side effects. */
+ check_terrain_change(ptile, old_terrain);
+
+ /* 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/maphand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/maphand.c,v
retrieving revision 1.171
diff -p -u -r1.171 maphand.c
--- server/maphand.c 4 Aug 2005 15:47:11 -0000 1.171
+++ server/maphand.c 11 Aug 2005 20:37:13 -0000
@@ -17,16 +17,18 @@
#include <assert.h>
-#include "events.h"
#include "fcintl.h"
-#include "game.h"
#include "log.h"
-#include "map.h"
#include "mem.h"
-#include "nation.h"
-#include "packets.h"
#include "rand.h"
#include "support.h"
+
+#include "events.h"
+#include "game.h"
+#include "map.h"
+#include "movement.h"
+#include "nation.h"
+#include "packets.h"
#include "unit.h"
#include "citytools.h"
@@ -1517,32 +1519,147 @@ static void ocean_to_land_fix_rivers(str
} cardinal_adjc_iterate_end;
}
-/**************************************************************************
- Checks for terrain change between ocean and land. Handles side-effects.
- (Should be called after any potential ocean/land terrain changes.)
- Also, returns an enum ocean_land_change, describing the change, if any.
+/****************************************************************************
+ Call this after check_terrain_land_ocean_change to move units out of the
+ way.
+****************************************************************************/
+static void bounce_land_units_from_ocean(struct tile *ptile)
+{
+ unit_list_iterate_safe(ptile->units, punit) {
+ if (is_ground_unit(punit)) {
+ /* look for nearby land */
+ adjc_iterate(ptile, ptile2) {
+ if (!is_ocean(ptile2->terrain)
+ && !is_non_allied_unit_tile(ptile2, unit_owner(punit))) {
+ freelog(LOG_VERBOSE,
+ "Moved %s's %s due to changing land to sea at (%d, %d).",
+ unit_owner(punit)->name, unit_name(punit->type),
+ punit->tile->x, punit->tile->y);
+ notify_player_ex(unit_owner(punit),
+ punit->tile, E_UNIT_RELOCATED,
+ _("Moved your %s due to changing"
+ " land to sea."), unit_name(punit->type));
+ (void) move_unit(punit, ptile2, 0);
+ if (punit->activity == ACTIVITY_SENTRY) {
+ handle_unit_activity_request(punit, ACTIVITY_IDLE);
+ }
+ }
+ } adjc_iterate_end;
+ /* look for nearby transport */
+ adjc_iterate(ptile, ptile2) {
+ if (is_ocean(ptile2->terrain)
+ && ground_unit_transporter_capacity(ptile2,
+ unit_owner(punit)) > 0) {
+ freelog(LOG_VERBOSE,
+ "Embarked %s's %s due to changing land to sea at (%d, %d).",
+ unit_owner(punit)->name, unit_name(punit->type),
+ punit->tile->x, punit->tile->x);
+ notify_player_ex(unit_owner(punit),
+ punit->tile, E_UNIT_RELOCATED,
+ _("Embarked your %s due to changing"
+ " land to sea."), unit_name(punit->type));
+ (void) move_unit(punit, ptile2, 0);
+ if (punit->activity == ACTIVITY_SENTRY) {
+ handle_unit_activity_request(punit, ACTIVITY_IDLE);
+ }
+ }
+ } adjc_iterate_end;
- if we did a land change, we try to avoid reassigning
- continent numbers.
-**************************************************************************/
-enum ocean_land_change check_terrain_ocean_land_change(struct tile *ptile,
- struct terrain *oldter)
+ /* if we get here we could not move punit */
+ freelog(LOG_VERBOSE,
+ "Disbanded %s's %s due to changing land to sea at (%d, %d).",
+ unit_owner(punit)->name, unit_name(punit->type),
+ punit->tile->x, punit->tile->y);
+ notify_player_ex(unit_owner(punit),
+ punit->tile, E_UNIT_LOST,
+ _("Disbanded your %s due to changing"
+ " land to sea."), unit_name(punit->type));
+ wipe_unit_spec_safe(punit, FALSE);
+ }
+ } unit_list_iterate_safe_end;
+}
+
+/****************************************************************************
+ Call this after check_terrain_land_ocean_change to move units out of the
+ way.
+****************************************************************************/
+static void bounce_ocean_units_from_land(struct tile *ptile)
+{
+ unit_list_iterate_safe(ptile->units, punit) {
+ if (is_sailing_unit(punit)) {
+ /* look for nearby water */
+ adjc_iterate(ptile, ptile2) {
+ if (is_ocean(ptile2->terrain)
+ && !is_non_allied_unit_tile(ptile2, unit_owner(punit))) {
+ freelog(LOG_VERBOSE,
+ "Moved %s's %s due to changing sea to land at (%d, %d).",
+ unit_owner(punit)->name, unit_name(punit->type),
+ punit->tile->x, punit->tile->y);
+ notify_player_ex(unit_owner(punit),
+ punit->tile, E_UNIT_RELOCATED,
+ _("Moved your %s due to changing"
+ " sea to land."), unit_name(punit->type));
+ (void) move_unit(punit, ptile2, 0);
+ if (punit->activity == ACTIVITY_SENTRY) {
+ handle_unit_activity_request(punit, ACTIVITY_IDLE);
+ }
+ }
+ } adjc_iterate_end;
+ /* look for nearby port */
+ adjc_iterate(ptile, ptile2) {
+ if (is_allied_city_tile(ptile2, unit_owner(punit))
+ && !is_non_allied_unit_tile(ptile2, unit_owner(punit))) {
+ freelog(LOG_VERBOSE,
+ "Docked %s's %s due to changing sea to land at (%d, %d).",
+ unit_owner(punit)->name, unit_name(punit->type),
+ punit->tile->x, punit->tile->y);
+ notify_player_ex(unit_owner(punit),
+ punit->tile, E_UNIT_RELOCATED,
+ _("Docked your %s due to changing"
+ " sea to land."), unit_name(punit->type));
+ (void) move_unit(punit, ptile2, 0);
+ if (punit->activity == ACTIVITY_SENTRY) {
+ handle_unit_activity_request(punit, ACTIVITY_IDLE);
+ }
+ }
+ } adjc_iterate_end;
+
+ /* if we get here we could not move punit */
+ freelog(LOG_VERBOSE,
+ "Disbanded %s's %s due to changing sea to land at (%d, %d).",
+ unit_owner(punit)->name, unit_name(punit->type),
+ punit->tile->x, punit->tile->y);
+ notify_player_ex(unit_owner(punit),
+ punit->tile, E_UNIT_LOST,
+ _("Disbanded your %s due to changing"
+ " sea to land."), unit_name(punit->type));
+ wipe_unit_spec_safe(punit, FALSE);
+ }
+ } unit_list_iterate_safe_end;
+}
+
+/****************************************************************************
+ Handles global side effects for a terrain change. Call this in the
+ server immediately after calling tile_change_terrain.
+****************************************************************************/
+void check_terrain_change(struct tile *ptile, struct terrain *oldter)
{
struct terrain *newter = tile_get_terrain(ptile);
- enum ocean_land_change change_type = OLC_NONE;
+ bool ocean_toggled = FALSE;
if (is_ocean(oldter) && !is_ocean(newter)) {
/* ocean to land ... */
ocean_to_land_fix_rivers(ptile);
city_landlocked_sell_coastal_improvements(ptile);
-
- change_type = OLC_OCEAN_TO_LAND;
+ bounce_ocean_units_from_land(ptile);
+ ocean_toggled = TRUE;
} else if (!is_ocean(oldter) && is_ocean(newter)) {
/* land to ocean ... */
- change_type = OLC_LAND_TO_OCEAN;
+ bounce_land_units_from_ocean(ptile);
+ ocean_toggled = TRUE;
}
- if (change_type != OLC_NONE) {
+ if (ocean_toggled) {
assign_continent_numbers(FALSE);
/* New continent numbers for all tiles to all players */
@@ -1550,8 +1667,6 @@ enum ocean_land_change check_terrain_oce
map_update_borders_landmass_change(ptile);
}
-
- return change_type;
}
/*************************************************************************
Index: server/maphand.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/maphand.h,v
retrieving revision 1.60
diff -p -u -r1.60 maphand.h
--- server/maphand.h 4 Aug 2005 15:47:12 -0000 1.60
+++ server/maphand.h 11 Aug 2005 20:37:13 -0000
@@ -20,8 +20,6 @@
#include "hand_gen.h"
-enum ocean_land_change { OLC_NONE, OLC_OCEAN_TO_LAND, OLC_LAND_TO_OCEAN };
-
struct section_file;
struct conn_list;
@@ -104,8 +102,7 @@ void map_update_borders_city_change(stru
void map_update_borders_landmass_change(struct tile *ptile);
void map_calculate_borders(void);
-enum ocean_land_change check_terrain_ocean_land_change(struct tile *ptile,
- struct terrain *oldter);
+void check_terrain_change(struct tile *ptile, struct terrain *oldter);
int get_continent_size(Continent_id id);
int get_ocean_size(Continent_id id);
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.284
diff -p -u -r1.284 srv_main.c
--- server/srv_main.c 8 Aug 2005 16:30:24 -0000 1.284
+++ server/srv_main.c 11 Aug 2005 20:37:13 -0000
@@ -1006,6 +1006,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);
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.374
diff -p -u -r1.374 unittools.c
--- server/unittools.c 4 Aug 2005 02:50:35 -0000 1.374
+++ server/unittools.c 11 Aug 2005 20:37:14 -0000
@@ -73,8 +73,6 @@ static void update_unit_activity(struct
static void wakeup_neighbor_sentries(struct unit *punit);
static void do_upgrade_effects(struct player *pplayer);
-static void sentry_transported_idle_units(struct unit *ptrans);
-
static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit);
static int hp_gain_coord(struct unit *punit);
@@ -622,7 +620,6 @@ static void update_unit_activity(struct
int id = punit->id;
bool unit_activity_done = FALSE;
enum unit_activity activity = punit->activity;
- enum ocean_land_change solvency = OLC_NONE;
struct tile *ptile = punit->tile;
bool check_adjacent_units = FALSE;
@@ -779,7 +776,7 @@ static void update_unit_activity(struct
struct terrain *old = tile_get_terrain(ptile);
tile_apply_activity(ptile, ACTIVITY_IRRIGATE);
- solvency = check_terrain_ocean_land_change(ptile, old);
+ check_terrain_change(ptile, old);
unit_activity_done = TRUE;
}
}
@@ -807,7 +804,7 @@ static void update_unit_activity(struct
struct terrain *old = tile_get_terrain(ptile);
tile_apply_activity(ptile, ACTIVITY_MINE);
- solvency = check_terrain_ocean_land_change(ptile, old);
+ check_terrain_change(ptile, old);
unit_activity_done = TRUE;
check_adjacent_units = TRUE;
}
@@ -819,7 +816,7 @@ static void update_unit_activity(struct
struct terrain *old = tile_get_terrain(ptile);
tile_apply_activity(ptile, ACTIVITY_TRANSFORM);
- solvency = check_terrain_ocean_land_change(ptile, old);
+ check_terrain_change(ptile, old);
unit_activity_done = TRUE;
check_adjacent_units = TRUE;
}
@@ -880,144 +877,6 @@ UNIT_LOG(LOG_ERROR, punit, "using old go
handle_unit_activity_request(punit2, ACTIVITY_IDLE);
}
} unit_list_iterate_end;
-
- /* Any units that landed in water or boats that landed on land as a
- result of settlers changing terrain must be moved back into their
- right environment.
- We advance the unit_list iterator passed into this routine from
- update_unit_activities() if we delete the unit it points to.
- We go to START each time we moved a unit to avoid problems with the
- tile unit list getting corrupted.
-
- FIXME: We shouldn't do this at all! There seems to be another
- bug which is expressed when units wind up on the "wrong" terrain;
- this is the bug that should be fixed. Also, introduction of the
- "amphibious" movement category would allow the definition of units
- that can "safely" change land<->ocean -- in which case all others
- would (here) be summarily disbanded (suicide to accomplish their
- task, for the greater good :). --jjm
- */
- START:
- switch (solvency) {
- case OLC_NONE:
- break; /* nothing */
-
- case OLC_LAND_TO_OCEAN:
- unit_list_iterate(ptile->units, punit2) {
- if (is_ground_unit(punit2)) {
- /* look for nearby land */
- adjc_iterate(ptile, ptile2) {
- if (!is_ocean(ptile2->terrain)
- && !is_non_allied_unit_tile(ptile2, unit_owner(punit2))) {
- if (get_transporter_capacity(punit2) > 0)
- sentry_transported_idle_units(punit2);
- freelog(LOG_VERBOSE,
- "Moved %s's %s due to changing land to sea at (%d, %d).",
- unit_owner(punit2)->name, unit_name(punit2->type),
- punit2->tile->x, punit2->tile->y);
- notify_player_ex(unit_owner(punit2),
- punit2->tile, E_UNIT_RELOCATED,
- _("Moved your %s due to changing"
- " land to sea."), unit_name(punit2->type));
- (void) move_unit(punit2, ptile2, 0);
- if (punit2->activity == ACTIVITY_SENTRY)
- handle_unit_activity_request(punit2, ACTIVITY_IDLE);
- goto START;
- }
- } adjc_iterate_end;
- /* look for nearby transport */
- adjc_iterate(ptile, ptile2) {
- if (is_ocean(ptile2->terrain)
- && ground_unit_transporter_capacity(ptile2,
- unit_owner(punit2)) > 0) {
- if (get_transporter_capacity(punit2) > 0)
- sentry_transported_idle_units(punit2);
- freelog(LOG_VERBOSE,
- "Embarked %s's %s due to changing land to sea at (%d, %d).",
- unit_owner(punit2)->name, unit_name(punit2->type),
- punit2->tile->x, punit2->tile->x);
- notify_player_ex(unit_owner(punit2),
- punit2->tile, E_UNIT_RELOCATED,
- _("Embarked your %s due to changing"
- " land to sea."), unit_name(punit2->type));
- (void) move_unit(punit2, ptile2, 0);
- if (punit2->activity == ACTIVITY_SENTRY)
- handle_unit_activity_request(punit2, ACTIVITY_IDLE);
- goto START;
- }
- } adjc_iterate_end;
- /* if we get here we could not move punit2 */
- freelog(LOG_VERBOSE,
- "Disbanded %s's %s due to changing land to sea at (%d, %d).",
- unit_owner(punit2)->name, unit_name(punit2->type),
- punit2->tile->x, punit2->tile->y);
- notify_player_ex(unit_owner(punit2),
- punit2->tile, E_UNIT_LOST,
- _("Disbanded your %s due to changing"
- " land to sea."), unit_name(punit2->type));
- wipe_unit_spec_safe(punit2, FALSE);
- goto START;
- }
- } unit_list_iterate_end;
- break;
- case OLC_OCEAN_TO_LAND:
- unit_list_iterate(ptile->units, punit2) {
- if (is_sailing_unit(punit2)) {
- /* look for nearby water */
- adjc_iterate(ptile, ptile2) {
- if (is_ocean(ptile2->terrain)
- && !is_non_allied_unit_tile(ptile2, unit_owner(punit2))) {
- if (get_transporter_capacity(punit2) > 0)
- sentry_transported_idle_units(punit2);
- freelog(LOG_VERBOSE,
- "Moved %s's %s due to changing sea to land at (%d, %d).",
- unit_owner(punit2)->name, unit_name(punit2->type),
- punit2->tile->x, punit2->tile->y);
- notify_player_ex(unit_owner(punit2),
- punit2->tile, E_UNIT_RELOCATED,
- _("Moved your %s due to changing"
- " sea to land."), unit_name(punit2->type));
- (void) move_unit(punit2, ptile2, 0);
- if (punit2->activity == ACTIVITY_SENTRY)
- handle_unit_activity_request(punit2, ACTIVITY_IDLE);
- goto START;
- }
- } adjc_iterate_end;
- /* look for nearby port */
- adjc_iterate(ptile, ptile2) {
- if (is_allied_city_tile(ptile2, unit_owner(punit2))
- && !is_non_allied_unit_tile(ptile2, unit_owner(punit2))) {
- if (get_transporter_capacity(punit2) > 0)
- sentry_transported_idle_units(punit2);
- freelog(LOG_VERBOSE,
- "Docked %s's %s due to changing sea to land at (%d, %d).",
- unit_owner(punit2)->name, unit_name(punit2->type),
- punit2->tile->x, punit2->tile->y);
- notify_player_ex(unit_owner(punit2),
- punit2->tile, E_UNIT_RELOCATED,
- _("Docked your %s due to changing"
- " sea to land."), unit_name(punit2->type));
- (void) move_unit(punit2, ptile2, 0);
- if (punit2->activity == ACTIVITY_SENTRY)
- handle_unit_activity_request(punit2, ACTIVITY_IDLE);
- goto START;
- }
- } adjc_iterate_end;
- /* if we get here we could not move punit2 */
- freelog(LOG_VERBOSE,
- "Disbanded %s's %s due to changing sea to land at (%d, %d).",
- unit_owner(punit2)->name, unit_name(punit2->type),
- punit2->tile->x, punit2->tile->y);
- notify_player_ex(unit_owner(punit2),
- punit2->tile, E_UNIT_LOST,
- _("Disbanded your %s due to changing"
- " sea to land."), unit_name(punit2->type));
- wipe_unit_spec_safe(punit2, FALSE);
- goto START;
- }
- } unit_list_iterate_end;
- break;
- }
}
/**************************************************************************
@@ -2058,25 +1917,6 @@ void send_all_known_units(struct conn_li
flush_packets();
}
-
-/**************************************************************************
-For all units which are transported by the given unit and that are
-currently idle, sentry them.
-**************************************************************************/
-static void sentry_transported_idle_units(struct unit *ptrans)
-{
- struct tile *ptile = ptrans->tile;
-
- unit_list_iterate(ptile->units, pcargo) {
- if (pcargo->transported_by == ptrans->id
- && pcargo->id != ptrans->id
- && pcargo->activity == ACTIVITY_IDLE) {
- pcargo->activity = ACTIVITY_SENTRY;
- send_unit_info(unit_owner(pcargo), pcargo);
- }
- } unit_list_iterate_end;
-}
-
/**************************************************************************
Nuke a square: 1) remove all units on the square, and 2) halve the
size of the city on the square.
|
|