empserver/src/util/empdump.c
Markus Armbruster 3e370da58c Get rid of ship and land unit load counters
Load counters are redundant; they can be computed from the carrier
uids.  Keeping them up-to-date as the carriers change is a pain, and
we never got that quite complete.

Computing load counters straight from the carrier uids every time we
need them would be rather inefficient, but computing them from cargo
lists is not.  So do that.

Remove the load counters: struct shpstr members shp_nplane,
shp_nchoppers, shp_nxlight, shp_nland, and struct lndstr members
lnd_nxlight and lnd_nland.

Don't compute/update load counters in build_ship(), build_land(),
land(), ldump(), load_plane_ship(), load_land_ship(),
load_plane_land(), load_land_land(), lstat(), sdump(), shi(), sstat(),
tend_land(), check_trade(), put_combat(), pln_oneway_to_carrier_ok),
pln_newlanding(), fit_plane_on_ship(), fit_plane_on_land(),
unit_list().

Nothing left in fit_plane_off_ship(), fit_plane_off_land(), so remove
them.

load_land_ship(), load_land_land(), check_trade(), pln_newlanding(),
put_plane_on_ship(), take_plane_off_ship(), put_plane_on_land(),
take_plane_off_land() no longer change the carrier, so don't put it.

Remove functions to recompute the load counters from carrier uids:
count_units(), lnd_count_units(), count_planes(), count_land_planes(),
pln_fixup() and lnd_fixup(), along with the latter two's private
copies of fit_plane_on_ship() and fit_plane_on_land().

New cargo list functions to compute load counts: unit_cargo_count()
and unit_nplane(), with convenience wrappers shp_nplane(),
shp_nland(), lnd_nxlight(), lnd_nland().

Use them to make ship selectors nplane, nchoppers, nxlight, nland
virtual.  They now reflect what is loaded, not how the load uses the
available slots.  This makes a difference when x-light planes or
choppers use plane slots.

Use them to make land unit selectors nxlight and nland virtual.

Use them to get load counts in land(), ldump(), load_plane_ship(),
load_land_ship(), load_plane_land(), load_land_land(), sdump(), shi(),
tend_land(), fit_plane_on_land(), trade_desc(), unit_list().

Rewrite fit_plane_on_ship() and could_be_on_ship() to use
shp_nplane().  could_be_on_ship() now takes load count arguments, as
computed by shp_nplane(), so it can be used for checking against an
existing load as well.
2008-09-08 21:32:56 -04:00

225 lines
5.1 KiB
C

/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure
*
* 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 of the License, 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ---
*
* See files README, COPYING and CREDITS in the root of the source
* tree for related information and legal notices. It is expected
* that future projects/authors will amend these files as needed.
*
* ---
*
* empdump.c: Export/import Empire game state
*
* Known contributors to this file:
* Markus Armbruster, 2008
*/
#include <config.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "file.h"
#include "optlist.h"
#include "nat.h"
#include "prototypes.h"
#include "version.h"
#include "xdump.h"
static void exit_bad_arg(char *, ...)
ATTRIBUTE((noreturn, format (printf, 1, 2)));
static void dump_table(int, int);
int
main(int argc, char *argv[])
{
char *config_file = NULL;
char *import = NULL;
int export = 0;
int private = 0;
int human = 1;
int opt, i, lineno, type;
FILE *impf = NULL;
int dirty[EF_MAX];
while ((opt = getopt(argc, argv, "e:i:mnxhv")) != EOF) {
switch (opt) {
case 'e':
config_file = optarg;
break;
case 'i':
import = optarg;
break;
case 'm':
human = 0;
break;
case 'n':
private = EFF_PRIVATE;
break;
case 'x':
export = 1;
break;
case 'h':
printf("Usage: %s [OPTION]...\n"
" -e CONFIG-FILE configuration file\n"
" (default %s)\n"
" -i DUMP-FILE import from DUMP-FILE\n"
" -m use machine-readable format\n"
" -n dry run, don't update game state\n"
" -x export to standard output\n"
" -h display this help and exit\n"
" -v display version information and exit\n",
argv[0], dflt_econfig);
exit(0);
case 'v':
printf("%s\n\n%s", version, legal);
exit(0);
default:
exit_bad_arg(NULL);
}
}
if (argv[optind])
exit_bad_arg("%s: extra operand %s\n", argv[0], argv[optind]);
if (!import && !export)
exit_bad_arg("%s: nothing to do!\n", argv[0]);
if (import) {
impf = fopen(import, "r");
if (!impf) {
fprintf(stderr, "%s: Can't open %s for reading (%s)\n",
argv[0], import, strerror(errno));
exit(1);
}
} else
private = EFF_PRIVATE;
/* read configuration & initialize */
empfile_init();
if (emp_config(config_file) < 0)
exit(1);
empfile_fixup();
nsc_init();
if (read_builtin_tables() < 0)
exit(1);
if (read_custom_tables() < 0)
exit(1);
if (chdir(gamedir)) {
fprintf(stderr, "%s: Can't chdir to %s (%s)\n",
argv[0], gamedir, strerror(errno));
exit(1);
}
global_init();
for (i = 0; i < EF_MAX; i++) {
if (!EF_IS_GAME_STATE(i))
continue;
if (!ef_open(i, EFF_MEM | private, -1))
exit(1);
}
/* import from IMPORT */
memset(dirty, 0, sizeof(dirty));
if (import) {
lineno = 1;
while ((type = xundump(impf, import, &lineno, EF_BAD)) >= 0)
dirty[type] = 1;
if (type == EF_BAD)
exit(1);
}
if (ef_verify() < 0)
exit(1);
/* export to stdout */
if (export) {
for (i = 0; i < EF_MAX; i++) {
if (!EF_IS_GAME_STATE(i))
continue;
dump_table(i, human);
}
if (fclose(stdout) != 0) {
fprintf(stderr, "%s: error writing export (%s)\n",
argv[0], strerror(errno));
exit(1);
}
}
/* write out imported data */
for (i = 0; i < EF_MAX; i++) {
if (!EF_IS_GAME_STATE(i))
continue;
if (!private && dirty[i]) {
if (!ef_close(i))
exit(1);
}
}
return 0;
}
static void
exit_bad_arg(char *complaint, ...)
{
va_list ap;
if (complaint) {
va_start(ap, complaint);
vfprintf(stderr, complaint, ap);
va_end(ap);
}
fprintf(stderr, "Try -h for help.\n");
exit(1);
}
static void
printf_wrapper(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
static void
dump_table(int type, int human)
{
struct xdstr xd;
struct castr *ca;
int i;
void *p;
ca = ef_cadef(type);
if (!ca)
return;
xdinit(&xd, NATID_BAD, human, printf_wrapper);
xdhdr(&xd, ef_nameof(type), 0);
xdcolhdr(&xd, ca);
for (i = 0; (p = ef_ptr(type, i)); i++) {
xdflds(&xd, ca, p);
printf("\n");
}
xdftr(&xd, i);
}