forked from github/server
198 lines
3.6 KiB
C
198 lines
3.6 KiB
C
/* vi: set ts=2:
|
|
*
|
|
*
|
|
* Eressea PB(E)M host Copyright (C) 1998-2003
|
|
* Christian Schlittchen (corwin@amber.kn-bremen.de)
|
|
* Katja Zedel (katze@felidae.kn-bremen.de)
|
|
* Henning Peters (faroul@beyond.kn-bremen.de)
|
|
* Enno Rehling (enno@eressea-pbem.de)
|
|
* Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
|
|
*
|
|
* This program may not be used, modified or distributed without
|
|
* prior permission by the authors of Eressea.
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include "eressea.h"
|
|
#include "group.h"
|
|
|
|
/* kernel includes */
|
|
#include "unit.h"
|
|
#include "faction.h"
|
|
#include "save.h"
|
|
|
|
/* attrib includes */
|
|
#include <attributes/raceprefix.h>
|
|
|
|
/* util includes */
|
|
#include <resolve.h>
|
|
#include <base36.h>
|
|
|
|
/* libc includes */
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define GMAXHASH 2039
|
|
static group * ghash[GMAXHASH];
|
|
static int maxgid;
|
|
|
|
static group *
|
|
new_group(faction * f, const char * name, int gid)
|
|
{
|
|
group ** gp = &f->groups;
|
|
int index = gid % GMAXHASH;
|
|
group * g = calloc(sizeof(group), 1);
|
|
|
|
while (*gp) gp = &(*gp)->next;
|
|
*gp = g;
|
|
|
|
maxgid = max(gid, maxgid);
|
|
g->name = strdup(name);
|
|
g->gid = gid;
|
|
|
|
g->nexthash = ghash[index];
|
|
return ghash[index] = g;
|
|
}
|
|
|
|
static void
|
|
init_group(faction * f, group * g)
|
|
{
|
|
ally * a, ** an;
|
|
|
|
an = &g->allies;
|
|
for (a=f->allies;a;a=a->next) if (a->faction) {
|
|
ally * ga = calloc(sizeof(ally), 1);
|
|
*ga = *a;
|
|
*an = ga;
|
|
an = &ga->next;
|
|
}
|
|
}
|
|
|
|
static group *
|
|
find_groupbyname(group * g, const char * name)
|
|
{
|
|
while (g && strcasecmp(name, g->name)) g = g->next;
|
|
return g;
|
|
}
|
|
|
|
static group *
|
|
find_group(int gid)
|
|
{
|
|
int index = gid % GMAXHASH;
|
|
group * g = ghash[index];
|
|
while (g && g->gid!=gid) g = g->nexthash;
|
|
return g;
|
|
}
|
|
|
|
static int
|
|
read_group(attrib * a, FILE * f)
|
|
{
|
|
int gid;
|
|
group * g;
|
|
fscanf(f, "%d ", &gid);
|
|
a->data.v = g = find_group(gid);
|
|
if (g!=0) {
|
|
g->members++;
|
|
return AT_READ_OK;
|
|
}
|
|
return AT_READ_FAIL;
|
|
}
|
|
|
|
static void
|
|
write_group(const attrib * a, FILE * f)
|
|
{
|
|
group * g = (group*)a->data.v;
|
|
fprintf(f, "%d ", g->gid);
|
|
}
|
|
|
|
attrib_type
|
|
at_group = { /* attribute for units assigned to a group */
|
|
"grp",
|
|
DEFAULT_INIT,
|
|
DEFAULT_FINALIZE,
|
|
DEFAULT_AGE,
|
|
write_group,
|
|
read_group,
|
|
ATF_UNIQUE
|
|
};
|
|
|
|
void
|
|
free_group(group * g)
|
|
{
|
|
while (g->allies) {
|
|
ally * a = g->allies;
|
|
g->allies = a->next;
|
|
free(a);
|
|
}
|
|
free(g->name);
|
|
free(g);
|
|
}
|
|
|
|
boolean
|
|
join_group(unit * u, const char * name)
|
|
{
|
|
attrib * a = a_find(u->attribs, &at_group);
|
|
group * g;
|
|
|
|
if (a) ((group *)(a->data.v))->members--;
|
|
if (!name || !strlen(name)) {
|
|
if (a) a_remove(&u->attribs, a);
|
|
return true;
|
|
}
|
|
g = find_groupbyname(u->faction->groups, name);
|
|
if (!g) {
|
|
g = new_group(u->faction, name, ++maxgid);
|
|
init_group(u->faction, g);
|
|
}
|
|
if (!a) a = a_add(&u->attribs, a_new(&at_group));
|
|
a->data.v = g;
|
|
g->members++;
|
|
return true;
|
|
}
|
|
|
|
void
|
|
write_groups(FILE * F, group * g)
|
|
{
|
|
while (g) {
|
|
ally * a;
|
|
fprintf(F, "%d \"%s\" ", g->gid, g->name);
|
|
for (a=g->allies;a;a=a->next) if (a->faction)
|
|
fprintf(F, "%s %d ", factionid(a->faction), a->status);
|
|
fputs("0 ", F);
|
|
a_write(F, g->attribs);
|
|
fputs("\n", F);
|
|
g=g->next;
|
|
}
|
|
fputs("0\n", F);
|
|
}
|
|
|
|
void
|
|
read_groups(FILE * F, faction * f)
|
|
{
|
|
for(;;) {
|
|
ally ** pa;
|
|
group * g;
|
|
int gid;
|
|
fscanf(F, "%d ", &gid);
|
|
if (!gid) break;
|
|
rsf(F, buf, 1024);
|
|
g = new_group(f, buf, gid);
|
|
pa = &g->allies;
|
|
for (;;) {
|
|
ally * a;
|
|
int aid;
|
|
fscanf(F, "%s ", buf);
|
|
aid = atoi36(buf);
|
|
if (aid==0) break;
|
|
a = calloc(sizeof(ally), 1);
|
|
*pa = a;
|
|
pa = &a->next;
|
|
fscanf(F, "%d ", &a->status);
|
|
a->faction = findfaction(aid);
|
|
if (!a->faction) ur_add((void*)aid, (void**)&a->faction, resolve_faction);
|
|
}
|
|
if(global.data_version >= GROUPATTRIB_VERSION) {
|
|
a_read(F, &g->attribs);
|
|
}
|
|
}
|
|
}
|