2010-08-08 10:06:34 +02:00
|
|
|
#include <platform.h>
|
|
|
|
#include <kernel/config.h>
|
|
|
|
#include "group.h"
|
|
|
|
|
|
|
|
/* kernel includes */
|
2012-06-30 20:07:28 +02:00
|
|
|
#include "ally.h"
|
2010-08-08 10:06:34 +02:00
|
|
|
#include "faction.h"
|
2012-06-30 20:07:28 +02:00
|
|
|
#include "unit.h"
|
2017-09-22 17:19:55 +02:00
|
|
|
#include "objtypes.h"
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
|
|
/* attrib includes */
|
|
|
|
#include <attributes/raceprefix.h>
|
|
|
|
|
|
|
|
/* util includes */
|
2018-09-29 11:37:17 +02:00
|
|
|
#include <kernel/attrib.h>
|
2010-08-08 10:06:34 +02:00
|
|
|
#include <util/base36.h>
|
2018-09-29 13:21:46 +02:00
|
|
|
#include <kernel/gamedata.h>
|
2010-08-08 10:06:34 +02:00
|
|
|
#include <util/resolve.h>
|
2017-12-28 18:29:40 +01:00
|
|
|
#include <util/strings.h>
|
2010-08-08 10:06:34 +02:00
|
|
|
#include <util/unicode.h>
|
|
|
|
|
2013-12-31 10:06:28 +01:00
|
|
|
#include <storage.h>
|
|
|
|
|
2010-08-08 10:06:34 +02:00
|
|
|
/* libc includes */
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <wctype.h>
|
|
|
|
|
|
|
|
#define GMAXHASH 2039
|
2011-03-07 08:02:35 +01:00
|
|
|
static group *ghash[GMAXHASH];
|
2010-08-08 10:06:34 +02:00
|
|
|
static int maxgid;
|
|
|
|
|
2019-08-25 17:43:18 +02:00
|
|
|
group *create_group(faction * f, const char *name, int gid)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-10-31 15:13:05 +01:00
|
|
|
group **gp = &f->groups;
|
|
|
|
int index = gid % GMAXHASH;
|
2018-10-26 21:49:58 +02:00
|
|
|
group *g = calloc(1, sizeof(group));
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2018-12-15 19:38:40 +01:00
|
|
|
if (!g) abort();
|
2014-10-31 15:13:05 +01:00
|
|
|
while (*gp)
|
|
|
|
gp = &(*gp)->next;
|
|
|
|
*gp = g;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2019-01-24 17:50:58 +01:00
|
|
|
if (gid > maxgid) maxgid = gid;
|
2017-12-28 18:29:40 +01:00
|
|
|
g->name = str_strdup(name);
|
2014-10-31 15:13:05 +01:00
|
|
|
g->gid = gid;
|
2019-08-25 17:43:18 +02:00
|
|
|
g->f = f;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-10-31 15:13:05 +01:00
|
|
|
g->nexthash = ghash[index];
|
|
|
|
return ghash[index] = g;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
static void init_group(faction * f, group * g)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2018-10-31 17:54:40 +01:00
|
|
|
g->allies = allies_clone(f->allies);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
static group *find_groupbyname(group * g, const char *name)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-10-31 15:13:05 +01:00
|
|
|
while (g && unicode_utf8_strcasecmp(name, g->name) != 0)
|
|
|
|
g = g->next;
|
|
|
|
return g;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
static group *find_group(int gid)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-10-31 15:13:05 +01:00
|
|
|
int index = gid % GMAXHASH;
|
|
|
|
group *g = ghash[index];
|
|
|
|
while (g && g->gid != gid)
|
|
|
|
g = g->nexthash;
|
|
|
|
return g;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2018-02-09 21:20:43 +01:00
|
|
|
static int read_group(variant *var, void *owner, gamedata *data)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2016-02-13 13:42:02 +01:00
|
|
|
struct storage *store = data->store;
|
2014-10-31 15:13:05 +01:00
|
|
|
group *g;
|
2019-08-25 17:43:18 +02:00
|
|
|
unit * u = (unit *)owner;
|
2014-10-31 15:13:05 +01:00
|
|
|
int gid;
|
|
|
|
|
|
|
|
READ_INT(store, &gid);
|
2018-02-09 21:20:43 +01:00
|
|
|
var->v = g = find_group(gid);
|
2019-08-25 17:43:18 +02:00
|
|
|
if (g != NULL) {
|
|
|
|
if (g->f != u->faction) {
|
|
|
|
return AT_READ_FAIL;
|
|
|
|
}
|
2014-10-31 15:13:05 +01:00
|
|
|
g->members++;
|
|
|
|
return AT_READ_OK;
|
|
|
|
}
|
|
|
|
return AT_READ_FAIL;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2018-02-09 21:20:43 +01:00
|
|
|
write_group(const variant *var, const void *owner, struct storage *store)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2018-02-09 21:20:43 +01:00
|
|
|
group *g = (group *)var->v;
|
2014-10-31 15:13:05 +01:00
|
|
|
WRITE_INT(store, g->gid);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
attrib_type at_group = { /* attribute for units assigned to a group */
|
2014-10-31 15:13:05 +01:00
|
|
|
"grp",
|
2011-03-07 08:02:35 +01:00
|
|
|
DEFAULT_INIT,
|
2016-02-09 06:43:19 +01:00
|
|
|
DEFAULT_FINALIZE, DEFAULT_AGE, write_group, read_group, NULL, ATF_UNIQUE };
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
|
|
void free_group(group * g)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2016-09-08 17:40:17 +02:00
|
|
|
int index;
|
|
|
|
group **g_ptr;
|
|
|
|
assert(g);
|
|
|
|
index = g->gid % GMAXHASH;
|
|
|
|
g_ptr = ghash + index;
|
|
|
|
while (*g_ptr && (*g_ptr)->gid != g->gid) {
|
2014-10-31 15:13:05 +01:00
|
|
|
g_ptr = &(*g_ptr)->nexthash;
|
2016-09-08 17:40:17 +02:00
|
|
|
}
|
2014-10-31 15:13:05 +01:00
|
|
|
assert(*g_ptr == g);
|
|
|
|
*g_ptr = g->nexthash;
|
|
|
|
|
2016-03-10 22:30:19 +01:00
|
|
|
if (g->attribs) {
|
|
|
|
a_removeall(&g->attribs, NULL);
|
|
|
|
}
|
2018-10-26 21:49:58 +02:00
|
|
|
allies_free(g->allies);
|
2014-10-31 15:13:05 +01:00
|
|
|
free(g->name);
|
|
|
|
free(g);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2012-06-07 18:47:02 +02:00
|
|
|
group * get_group(const struct unit *u)
|
|
|
|
{
|
2014-10-31 15:13:05 +01:00
|
|
|
if (fval(u, UFL_GROUP)) {
|
|
|
|
attrib * a = a_find(u->attribs, &at_group);
|
|
|
|
if (a) {
|
|
|
|
return (group *)a->data.v;
|
|
|
|
}
|
2012-06-07 18:47:02 +02:00
|
|
|
}
|
2014-10-31 15:13:05 +01:00
|
|
|
return 0;
|
2012-06-07 18:47:02 +02:00
|
|
|
}
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
void set_group(struct unit *u, struct group *g)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-10-31 15:13:05 +01:00
|
|
|
attrib *a = NULL;
|
|
|
|
|
|
|
|
if (fval(u, UFL_GROUP)) {
|
|
|
|
a = a_find(u->attribs, &at_group);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a) {
|
|
|
|
group *og = (group *)a->data.v;
|
|
|
|
if (og == g)
|
|
|
|
return;
|
|
|
|
--og->members;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g) {
|
|
|
|
if (!a) {
|
|
|
|
a = a_add(&u->attribs, a_new(&at_group));
|
|
|
|
fset(u, UFL_GROUP);
|
|
|
|
}
|
|
|
|
a->data.v = g;
|
|
|
|
g->members++;
|
|
|
|
}
|
|
|
|
else if (a) {
|
|
|
|
a_remove(&u->attribs, a);
|
|
|
|
freset(u, UFL_GROUP);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-16 07:30:26 +01:00
|
|
|
group *join_group(unit * u, const char *name)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-10-31 15:13:05 +01:00
|
|
|
group *g = NULL;
|
|
|
|
|
|
|
|
if (name && name[0]) {
|
|
|
|
g = find_groupbyname(u->faction->groups, name);
|
|
|
|
if (g == NULL) {
|
2019-08-25 17:43:18 +02:00
|
|
|
g = create_group(u->faction, name, ++maxgid);
|
2014-10-31 15:13:05 +01:00
|
|
|
init_group(u->faction, g);
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2014-10-31 15:13:05 +01:00
|
|
|
set_group(u, g);
|
2016-02-16 07:30:26 +01:00
|
|
|
return g;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2018-10-26 21:49:58 +02:00
|
|
|
void write_groups(struct gamedata *data, const faction * f)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-11-03 18:10:05 +01:00
|
|
|
group *g;
|
2018-10-26 21:49:58 +02:00
|
|
|
storage *store = data->store;
|
2015-01-30 20:37:14 +01:00
|
|
|
for (g = f->groups; g; g = g->next) {
|
2014-10-31 15:13:05 +01:00
|
|
|
WRITE_INT(store, g->gid);
|
|
|
|
WRITE_STR(store, g->name);
|
2018-10-26 21:49:58 +02:00
|
|
|
write_allies(data, g->allies);
|
2014-10-31 15:13:05 +01:00
|
|
|
a_write(store, g->attribs, g);
|
|
|
|
WRITE_SECTION(store);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
2013-12-31 10:06:28 +01:00
|
|
|
WRITE_INT(store, 0);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2016-02-13 13:42:02 +01:00
|
|
|
void read_groups(gamedata *data, faction * f)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2016-02-13 13:42:02 +01:00
|
|
|
struct storage *store = data->store;
|
2010-08-08 10:06:34 +02:00
|
|
|
for (;;) {
|
2014-10-31 15:13:05 +01:00
|
|
|
group *g;
|
|
|
|
int gid;
|
|
|
|
char buf[1024];
|
|
|
|
|
|
|
|
READ_INT(store, &gid);
|
|
|
|
if (gid == 0)
|
|
|
|
break;
|
|
|
|
READ_STR(store, buf, sizeof(buf));
|
2019-08-25 17:43:18 +02:00
|
|
|
g = create_group(f, buf, gid);
|
2018-10-26 19:47:50 +02:00
|
|
|
read_allies(data, &g->allies);
|
2016-02-13 13:42:02 +01:00
|
|
|
read_attribs(data, &g->attribs, g);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|