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.
225 lines
5.1 KiB
C
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);
|
|
}
|