[Change] Major rewrite of space.c. Let's pray we don't have a ton of bugs.

This commit is contained in:
Allanis 2013-12-07 22:16:01 +00:00
parent da4b261de7
commit 5a42e63e4a
3 changed files with 317 additions and 233 deletions

View File

@ -166,12 +166,12 @@ int input_getKeybind(char* keybind, KeybindType* type, int* reverse) {
* @param value The value of the keypress (defined above). * @param value The value of the keypress (defined above).
* @param abs Whether or not it's an absolute value (for the joystick). * @param abs Whether or not it's an absolute value (for the joystick).
*/ */
#define KEY(s) (strcmp(input_keybinds[keynum]->name, s)==0) #define KEY(s) (strcmp(input_keybinds[keynum]->name, s)==0) /**< Shortcut for ease. */
#define INGAME() (!toolkit) #define INGAME() (!toolkit) /**< Make sure player is in game. */
#define NOHYP() \ #define NOHYP() \
(player && !pilot_isFlag(player, PILOT_HYP_PREP) && \ (player && !pilot_isFlag(player, PILOT_HYP_PREP) && \
!pilot_isFlag(player, PILOT_HYP_BEGIN) && \ !pilot_isFlag(player, PILOT_HYP_BEGIN) && \
!pilot_isFlag(player, PILOT_HYPERSPACE)) !pilot_isFlag(player, PILOT_HYPERSPACE)) /**< Make sure player isn't jumping. */
static void input_key(int keynum, double value, int kabs) { static void input_key(int keynum, double value, int kabs) {
unsigned int t; unsigned int t;

View File

@ -34,8 +34,10 @@
#define PLANET_GFX_EXTERIOR_W 400 #define PLANET_GFX_EXTERIOR_W 400
#define PLANET_GFX_EXTERIOR_H 400 #define PLANET_GFX_EXTERIOR_H 400
/* Overcome warning due to zero value. */ #define CHUNK_SIZE 32 /**< Size to allocate by. */
#define CHUNK_SIZE_SMALL 8 /**< Smaller size to allocate chunks by. */
/* Overcome warning due to zero value. */
#define FLAG_XSET (1<<0) #define FLAG_XSET (1<<0)
#define FLAG_YSET (1<<1) #define FLAG_YSET (1<<1)
#define FLAG_ASTEROIDSSET (1<<2) #define FLAG_ASTEROIDSSET (1<<2)
@ -48,11 +50,19 @@
static char** planetname_stack = NULL; static char** planetname_stack = NULL;
static char** systemname_stack = NULL; static char** systemname_stack = NULL;
static int spacename_nstack = 0; static int spacename_nstack = 0;
static int spacename_mstack = 0; /**< Size of memory in planet <->system stack. */
/* Star system stack and co. */ /* Star system stack. */
StarSystem* systems_stack = NULL; /* Star system stack. */ StarSystem* systems_stack = NULL; /* Star system stack. */
int systems_nstack = 0; /* Number of star systems. */ int systems_nstack = 0; /* Number of star systems. */
static int total_planets = 0; /* Total number of loaded planets - A little silly. */ static int systems_mstack = 0; /**< Number of memory allocated for star system stack. */
/* Planet Stack. */
static Planet* planet_stack = NULL; /**< Planet stack. */
static int planet_nstack = 0; /**< Planet stack size. */
static int planet_mstack = 0; /**< Memory size of planet stack. */
/* Misc. */
StarSystem* cur_system = NULL; /* Current star system. */ StarSystem* cur_system = NULL; /* Current star system. */
/* Fleet spawn rate. */ /* Fleet spawn rate. */
@ -71,14 +81,19 @@ static int nstars = 0; /* Total stars. */
static int mstars = 0; /* Memory stars are taking. */ static int mstars = 0; /* Memory stars are taking. */
/* Intern. */ /* Intern. */
static Planet* planet_pull(const char* name); /* Planet load. */
static int planet_parse(Planet* planet, const xmlNodePtr parent);
/* System load. */
static int systems_load(void);
static StarSystem* system_parse(StarSystem* system, const xmlNodePtr parent);
static void systemJumps(const xmlNodePtr parent);
/* Misc. */
static void space_renderStars(const double dt); static void space_renderStars(const double dt);
static void space_addFleet(Fleet* fleet, int init); static void space_addFleet(Fleet* fleet, int init);
static StarSystem* system_parse(const xmlNodePtr parent);
static void system_parseJumps(const xmlNodePtr parent);
static PlanetClass planetclass_get(const char a); static PlanetClass planetclass_get(const char a);
/* Extern. */ /* Extern. */
extern void player_message(const char* fmt, ...); extern void player_message(const char* fmt, ...);
void planets_minimap(const double res, const double w, void planets_minimap(const double res, const double w,
const double h, const RadarShape shape); const double h, const RadarShape shape);
int space_sysSave(xmlTextWriterPtr writer); int space_sysSave(xmlTextWriterPtr writer);
@ -100,16 +115,16 @@ void planets_minimap(const double res, const double w,
glBegin(GL_POINTS); glBegin(GL_POINTS);
for(i = 0; i < cur_system->nplanets; i++) { for(i = 0; i < cur_system->nplanets; i++) {
planet = &cur_system->planets[i]; planet = cur_system->planets[i];
col = faction_getColour(planet->faction); col = faction_getColour(planet->faction);
if((col != &cHostile) && !planet_hasService(planet, PLANET_SERVICE_BASIC)) if((col != &cHostile) && !planet_hasService(planet, PLANET_SERVICE_BASIC))
col = &cInert; /* Override non-hostile planets without services. */ col = &cInert; /* Override non-hostile planets without services. */
COLOUR(*col); COLOUR(*col);
r = (int)(cur_system->planets[i].gfx_space->sw / res); r = (int)(cur_system->planets[i]->gfx_space->sw / res);
cx = (int)((cur_system->planets[i].pos.x - player->solid->pos.x) / res); cx = (int)((cur_system->planets[i]->pos.x - player->solid->pos.x) / res);
cy = (int)((cur_system->planets[i].pos.y - player->solid->pos.y) / res); cy = (int)((cur_system->planets[i]->pos.y - player->solid->pos.y) / res);
x = 0; x = 0;
y = r; y = r;
@ -238,7 +253,7 @@ int space_canHyperspace(Pilot* p) {
if(p->fuel < HYPERSPACE_FUEL) return 0; if(p->fuel < HYPERSPACE_FUEL) return 0;
for(i = 0; i < cur_system->nplanets; i++) { for(i = 0; i < cur_system->nplanets; i++) {
d = vect_dist(&p->solid->pos, &cur_system->planets[i].pos); d = vect_dist(&p->solid->pos, &cur_system->planets[i]->pos);
if(d < MIN_HYPERSPACE_DIST) if(d < MIN_HYPERSPACE_DIST)
return 0; return 0;
} }
@ -270,7 +285,7 @@ char** space_getFactionPlanet(int* nplanets, int* factions, int nfactions) {
for(i = 0; i < systems_nstack; i++) for(i = 0; i < systems_nstack; i++)
for(j = 0; j < systems_stack[i].nplanets; j++) { for(j = 0; j < systems_stack[i].nplanets; j++) {
planet = &systems_stack[i].planets[j]; planet = systems_stack[i].planets[j];
for(k = 0; k < nfactions; k++) for(k = 0; k < nfactions; k++)
if(planet->faction == factions[k]) { if(planet->faction == factions[k]) {
ntmp++; ntmp++;
@ -305,7 +320,7 @@ char* space_getRndPlanet(void) {
mtmp += 25; mtmp += 25;
tmp = realloc(tmp, sizeof(char*) * mtmp); tmp = realloc(tmp, sizeof(char*) * mtmp);
} }
tmp[ntmp-1] = systems_stack[i].planets[j].name; tmp[ntmp-1] = systems_stack[i].planets[j]->name;
} }
res = tmp[RNG(0, ntmp-1)]; res = tmp[RNG(0, ntmp-1)];
@ -353,15 +368,11 @@ char* planet_getSystem(char* planetname) {
/* Get a planet based on it's name. */ /* Get a planet based on it's name. */
Planet* planet_get(char* planetname) { Planet* planet_get(char* planetname) {
int i; int i;
char* sysname;
StarSystem* sys;
sysname = planet_getSystem(planetname); for(i = 0; i < planet_nstack; i++)
sys = system_get(sysname); if(strcmp(planet_stack[i].name, planetname)==0)
return &planet_stack[i];
for(i = 0; i < sys->nplanets; i++)
if(strcmp(planetname, sys->planets[i].name)==0)
return &sys->planets[i];
DEBUG("Planet '%s' not found in the universe", planetname); DEBUG("Planet '%s' not found in the universe", planetname);
return NULL; return NULL;
} }
@ -441,9 +452,9 @@ static void space_addFleet(Fleet* fleet, int init) {
/* Get friendly planet to land on. */ /* Get friendly planet to land on. */
planet = NULL; planet = NULL;
for(i = 0; i < cur_system->nplanets; i++) for(i = 0; i < cur_system->nplanets; i++)
if(planet_hasService(&cur_system->planets[i], PLANET_SERVICE_BASIC) && if(planet_hasService(cur_system->planets[i], PLANET_SERVICE_BASIC) &&
!areEnemies(fleet->faction, cur_system->planets[i].faction)) { !areEnemies(fleet->faction, cur_system->planets[i]->faction)) {
planet = &cur_system->planets[i]; planet = cur_system->planets[i];
break; break;
} }
@ -534,128 +545,49 @@ void space_init(const char* sysname) {
sys_setFlag(cur_system, SYSTEM_KNOWN); sys_setFlag(cur_system, SYSTEM_KNOWN);
} }
/* Load the planets of name 'name'. */ /**
static Planet* planet_pull(const char* name) { * @fn static int planets_load(void)
int i; *
* @brief Load all the planets in the game.
Planet* tmp = NULL; * @return 0 on success.
*/
char str[PATH_MAX] = "\0"; static int planets_load(void) {
char* tstr;
uint32_t flags = 0;
uint32_t bufsize; uint32_t bufsize;
char* buf = pack_readfile(DATA, PLANET_DATA, &bufsize); char* buf;
xmlNodePtr node;
xmlDocPtr doc;
xmlNodePtr node, cur, ccur; buf = pack_readfile(DATA, PLANET_DATA, &bufsize);
xmlDocPtr doc = xmlParseMemory(buf, bufsize); doc = xmlParseMemory(buf, bufsize);
node = doc->xmlChildrenNode; node = doc->xmlChildrenNode;
if(strcmp((char*)node->name, XML_PLANET_ID)) { if(strcmp((char*)node->name, XML_PLANET_ID)) {
ERR("Malformed "PLANET_DATA" file: missing root element '"XML_PLANET_ID"'"); ERR("Malformed "PLANET_DATA" file: missing root element '"XML_PLANET_ID"'");
return NULL; return -1;
} }
node = node->xmlChildrenNode; /* First system node. */ node = node->xmlChildrenNode; /* First system node. */
if(node == NULL) { if(node == NULL) {
ERR("Malformed "PLANET_DATA" file: does not contain elements"); ERR("Malformed "PLANET_DATA" file: does not contain elements");
return NULL; return -1;
}
/* Initialize stack if needed. */
if(planet_stack == NULL) {
planet_mstack = CHUNK_SIZE;
planet_stack = malloc(sizeof(Planet) * planet_mstack);
planet_nstack = 0;
} }
do { do {
if(xml_isNode(node, XML_PLANET_TAG)) { if(xml_isNode(node, XML_PLANET_TAG)) {
tstr = xml_nodeProp(node, "name"); /* See if stack must grow. */
if(strcmp(tstr, name)==0) { /* Found. */ planet_nstack++;
tmp = CALLOC_L(Planet); if(planet_nstack > planet_mstack) {
tmp->faction = -1; /* No faction. */ planet_mstack += CHUNK_SIZE;
tmp->name = tstr; planet_stack = realloc(planet_stack, sizeof(Planet) * planet_mstack);
}
node = node->xmlChildrenNode; planet_parse(&planet_stack[planet_nstack-1], node);
do {
if(xml_isNode(node, "GFX")) {
cur = node->children;
do {
if(xml_isNode(cur, "space")) {
/* Load space gfx. */
snprintf(str, PATH_MAX, PLANET_GFX_SPACE"%s", xml_get(cur));
tmp->gfx_space = gl_newImage(str);
}
else if(xml_isNode(cur, "exterior")) {
/* Load land gfx. */
tmp->gfx_exterior = malloc(strlen(xml_get(cur))+sizeof(PLANET_GFX_EXTERIOR));
snprintf(tmp->gfx_exterior, strlen(xml_get(cur))+sizeof(PLANET_GFX_EXTERIOR),
PLANET_GFX_EXTERIOR"%s", xml_get(cur));
}
} while(xml_nextNode(cur));
}
else if(xml_isNode(node, "pos")) {
cur = node->children;
do {
if(xml_isNode(cur, "x")) {
flags |= FLAG_XSET;
tmp->pos.x = xml_getFloat(cur);
}
else if(xml_isNode(cur, "y")) {
flags |= FLAG_YSET;
tmp->pos.y = xml_getFloat(cur);
}
} while(xml_nextNode(cur));
}
else if(xml_isNode(node, "general")) {
cur = node->children;
do {
if(xml_isNode(cur, "class"))
tmp->class = planetclass_get(cur->children->content[0]);
else if(xml_isNode(cur, "faction")) {
flags |= FLAG_FACTIONSET;
tmp->faction = faction_get(xml_get(cur));
}
else if(xml_isNode(cur, "description"))
tmp->description = strdup(xml_get(cur));
else if(xml_isNode(cur, "bar"))
tmp->bar_description = strdup(xml_get(cur));
else if(xml_isNode(cur, "services")) {
flags |= FLAG_SERVICESET;
tmp->services = xml_getInt(cur);
}
else if(xml_isNode(cur, "tech")) {
ccur = cur->children;
do {
if(xml_isNode(ccur, "main")) {
flags |= FLAG_TECHSET;
tmp->tech[0] = xml_getInt(ccur);
}
else if(xml_isNode(ccur, "special")) {
for(i = 1; i < PLANET_TECH_MAX; i++)
if(tmp->tech[i]==0) {
tmp->tech[i] = xml_getInt(ccur);
break;
}
if(i == PLANET_TECH_MAX) WARN("Planet '%s' has too many"
"'special tech' entries", tmp->name);
}
} while(xml_nextNode(ccur));
}
else if(xml_isNode(cur, "commodities")) {
ccur = cur->children;
do {
if(xml_isNode(ccur, "commodity")) {
tmp->commodities = realloc(tmp->commodities,
(tmp->ncommodities+1) * sizeof(Commodity*));
tmp->commodities[tmp->ncommodities] =
commodity_get(xml_get(ccur));
tmp->ncommodities++;
}
} while(xml_nextNode(ccur));
}
} while(xml_nextNode(cur));
}
} while(xml_nextNode(node));
break;
} else
free(tstr); /* xmlGetProp mallocs the string. */
} }
} while(xml_nextNode(node)); } while(xml_nextNode(node));
@ -663,47 +595,155 @@ static Planet* planet_pull(const char* name) {
free(buf); free(buf);
xmlCleanupParser(); xmlCleanupParser();
/* Check elements. */ return 0;
if(tmp) { }
#define MELEMENT(o,s) if(o) WARN("Planet '%s' missing '"s"' element", tmp->name)
MELEMENT(tmp->gfx_space==NULL, "GFX_space");
MELEMENT(planet_hasService(tmp, PLANET_SERVICE_LAND) &&
tmp->gfx_exterior==NULL, "GFX exterior");
MELEMENT((flags&FLAG_XSET)==0, "x");
MELEMENT((flags&FLAG_YSET)==0, "y");
MELEMENT(tmp->class==PLANET_CLASS_NULL, "class");
MELEMENT(planet_hasService(tmp, PLANET_SERVICE_LAND) &&
tmp->description==NULL, "description");
MELEMENT(planet_hasService(tmp, PLANET_SERVICE_BASIC) &&
tmp->bar_description==NULL, "bar");
MELEMENT(planet_hasService(tmp, PLANET_SERVICE_BASIC) &&
(flags & FLAG_FACTIONSET)==0, "faction");
MELEMENT((flags&FLAG_SERVICESET)==0, "services");
MELEMENT((planet_hasService(tmp, PLANET_SERVICE_OUTFITS) || /**
planet_hasService(tmp, PLANET_SERVICE_SHIPYARD)) && * @fn static int planet_parse(Planet* planet, const xmlNodePtr parent)
(flags&FLAG_TECHSET)==0, "tech"); *
MELEMENT(planet_hasService(tmp, PLANET_SERVICE_COMMODITY) && * @brief Parses a planet from an xml node.
(tmp->ncommodities==0), "commodity"); * @param planet Planet to fill up.
* @param parent Node that contains planet data.
* @return 0 on success.
*/
static int planet_parse(Planet* planet, const xmlNodePtr parent) {
int i;
char str[PATH_MAX];
xmlNodePtr node, cur, ccur;
int len;
unsigned int flags;
/* Clear up memory for sane defaults. */
memset(planet, 0, sizeof(Planet));
str[0] = '\0';
flags = 0;
/* Get the name. */
xmlr_attr(parent, "name", planet->name);
node = parent->xmlChildrenNode;
do {
if(xml_isNode(node, "GFX")) {
cur = node->children;
do {
if(xml_isNode(cur, "space")) { /* Load space gfx. */
snprintf(str, PATH_MAX, PLANET_GFX_SPACE"%s", xml_get(cur));
planet->gfx_space = gl_newImage(str);
}
else if(xml_isNode(cur, "exterior")) { /* Load land gfx. */
len = strlen(xml_get(cur)) + sizeof(PLANET_GFX_EXTERIOR);
planet->gfx_exterior = malloc(len);
snprintf(planet->gfx_exterior, len, PLANET_GFX_EXTERIOR"%s", xml_get(cur));
}
} while(xml_nextNode(cur));
}
else if(xml_isNode(node, "pos")) {
cur = node->children;
do {
if(xml_isNode(cur, "x")) {
flags |= FLAG_XSET;
planet->pos.x = xml_getFloat(cur);
}
else if(xml_isNode(cur, "y")) {
flags |= FLAG_YSET;
planet->pos.y = xml_getFloat(cur);
}
} while(xml_nextNode(cur));
}
else if(xml_isNode(node, "general")) {
cur = node->children;
do {
if(xml_isNode(cur, "class"))
planet->class = planetclass_get(cur->children->content[0]);
else if(xml_isNode(cur, "faction")) {
flags |= FLAG_FACTIONSET;
planet->faction = faction_get(xml_get(cur));
}
else if(xml_isNode(cur, "description"))
planet->description = strdup(xml_get(cur));
else if(xml_isNode(cur, "bar"))
planet->bar_description = strdup(xml_get(cur));
else if(xml_isNode(cur, "services")) {
flags |= FLAG_SERVICESET;
planet->services = xml_getInt(cur); /* Flags gotten by data. */
}
else if(xml_isNode(cur, "tech")) {
ccur = cur->children;
do {
if(xml_isNode(ccur, "main")) {
flags |= FLAG_TECHSET;
planet->tech[0] = xml_getInt(ccur);
}
else if(xml_isNode(ccur, "special")) {
for(i = 1; i < PLANET_TECH_MAX; i++)
if(planet->tech[i] == 0) {
planet->tech[i] = xml_getInt(ccur);
break;
}
if(i == PLANET_TECH_MAX) WARN("Planet '%s' has too many"
"'special tech' entries", planet->name);
}
} while(xml_nextNode(ccur));
}
else if(xml_isNode(cur, "commodities")) {
ccur = cur->children;
do {
if(xml_isNode(ccur, "commodity")) {
planet->commodities = realloc(planet->commodities,
(planet->ncommodities+1) * sizeof(Commodity*));
planet->commodities[planet->ncommodities] =
commodity_get(xml_get(ccur));
planet->ncommodities++;
}
} while(xml_nextNode(ccur));
}
} while(xml_nextNode(cur));
}
} while(xml_nextNode(node));
/* Verification. */
#define MELEMENT(o,s) if(o) WARN("Planet '%s' missing '"s"' element", planet->name)
MELEMENT(planet->gfx_space==NULL, "GFX space");
MELEMENT(planet_hasService(planet, PLANET_SERVICE_LAND) &&
planet->gfx_exterior==NULL, "GFX exterior");
MELEMENT((flags&FLAG_XSET)==0, "x");
MELEMENT((flags&FLAG_YSET)==0, "y");
MELEMENT(planet->class==PLANET_CLASS_NULL, "class");
MELEMENT(planet_hasService(planet, PLANET_SERVICE_LAND) &&
planet->description==NULL, "description");
MELEMENT(planet_hasService(planet, PLANET_SERVICE_BASIC) &&
planet->bar_description==NULL, "bar");
MELEMENT(planet_hasService(planet, PLANET_SERVICE_BASIC) &&
(flags&FLAG_FACTIONSET)==0, "faction");
MELEMENT((flags&FLAG_SERVICESET)==0, "services");
MELEMENT((planet_hasService(planet, PLANET_SERVICE_OUTFITS) ||
planet_hasService(planet, PLANET_SERVICE_SHIPYARD)) &&
(flags&FLAG_TECHSET)==0, "tech");
MELEMENT(planet_hasService(planet, PLANET_SERVICE_COMMODITY) &&
(planet->ncommodities==0), "commodity");
#undef MELEMENT #undef MELEMENT
} else
WARN("No planet found matching name '%s'", name);
return tmp; return 0;
} }
/* Parse node 'parent' which should be the node of a system. */ /* Parse node 'parent' which should be the node of a system. */
/* Return the StarSystem fully loaded. */ /* Return the StarSystem fully loaded. */
static StarSystem* system_parse(const xmlNodePtr parent) { static StarSystem* system_parse(StarSystem* sys, const xmlNodePtr parent) {
Planet* planet = NULL; Planet* planet;
SystemFleet* fleet = NULL; SystemFleet* fleet;
StarSystem* tmp = CALLOC_L(StarSystem);
char* ptrc; char* ptrc;
xmlNodePtr cur, node; xmlNodePtr cur, node;
uint32_t flags; uint32_t flags;
int size;
tmp->name = xml_nodeProp(parent, "name"); /* Already mallocs. */ /* Clear memory for sane defaults. */
memset(sys, 0, sizeof(StarSystem));
planet = NULL;
fleet = NULL;
size = 0;
sys->name = xml_nodeProp(parent, "name"); /* Already mallocs. */
node = parent->xmlChildrenNode; node = parent->xmlChildrenNode;
@ -714,11 +754,11 @@ static StarSystem* system_parse(const xmlNodePtr parent) {
do { do {
if(xml_isNode(cur, "x")) { if(xml_isNode(cur, "x")) {
flags |= FLAG_XSET; flags |= FLAG_XSET;
tmp->pos.x = xml_getFloat(cur); sys->pos.x = xml_getFloat(cur);
} }
if(xml_isNode(cur, "y")) { if(xml_isNode(cur, "y")) {
flags |= FLAG_YSET; flags |= FLAG_YSET;
tmp->pos.y = xml_getFloat(cur); sys->pos.y = xml_getFloat(cur);
} }
} while(xml_nextNode(cur)); } while(xml_nextNode(cur));
} }
@ -726,22 +766,22 @@ static StarSystem* system_parse(const xmlNodePtr parent) {
cur = node->children; cur = node->children;
do { do {
if(xml_isNode(cur, "stars")) /* Non-zero. */ if(xml_isNode(cur, "stars")) /* Non-zero. */
tmp->stars = xml_getInt(cur); sys->stars = xml_getInt(cur);
else if(xml_isNode(cur, "asteroids")) { else if(xml_isNode(cur, "asteroids")) {
flags |= FLAG_ASTEROIDSSET; flags |= FLAG_ASTEROIDSSET;
tmp->asteroids = xml_getInt(cur); sys->asteroids = xml_getInt(cur);
} }
else if(xml_isNode(cur, "interference")) { else if(xml_isNode(cur, "interference")) {
flags |= FLAG_INTEFERENCESET; flags |= FLAG_INTEFERENCESET;
tmp->interference = xml_getFloat(cur)/100; sys->interference = xml_getFloat(cur)/100;
} }
else if(xml_isNode(cur, "nebulae")) { else if(xml_isNode(cur, "nebulae")) {
ptrc = xml_nodeProp(cur, "volatility"); ptrc = xml_nodeProp(cur, "volatility");
if(ptrc != NULL) { /* Has volatility. */ if(ptrc != NULL) { /* Has volatility. */
tmp->nebu_volatility = atof(ptrc); sys->nebu_volatility = atof(ptrc);
free(ptrc); free(ptrc);
} }
tmp->nebu_density = xml_getFloat(cur); sys->nebu_density = xml_getFloat(cur);
} }
}while(xml_nextNode(cur)); }while(xml_nextNode(cur));
} }
@ -751,20 +791,26 @@ static StarSystem* system_parse(const xmlNodePtr parent) {
do { do {
if(cur && xml_isNode(cur, "planet")) { if(cur && xml_isNode(cur, "planet")) {
/* Add planet to system. */ /* Add planet to system. */
total_planets++; /* Increase planet counter. */ sys->nplanets++;
planet = planet_pull(xml_get(cur)); if(sys->nplanets > size) {
tmp->planets = realloc(tmp->planets, sizeof(Planet)*(++tmp->nplanets)); size += CHUNK_SIZE_SMALL;
memcpy(tmp->planets+(tmp->nplanets-1), planet, sizeof(Planet)); sys->planets = realloc(sys->planets, sizeof(Planet*) * size);
}
planet = planet_get(xml_get(cur));
sys->planets[sys->nplanets-1] = planet;
/* Add planet <-> star system to name stack. */ /* Add planet <-> star system to name stack. */
spacename_nstack++; spacename_nstack++;
planetname_stack = realloc(planetname_stack, if(spacename_nstack > spacename_mstack) {
sizeof(char*)*spacename_nstack); spacename_mstack += CHUNK_SIZE;
systemname_stack = realloc(systemname_stack, planetname_stack = realloc(planetname_stack,
sizeof(char*)*spacename_nstack); sizeof(char*) * spacename_mstack);
systemname_stack = realloc(systemname_stack,
sizeof(char*) * spacename_mstack);
}
planetname_stack[spacename_nstack-1] = planet->name; planetname_stack[spacename_nstack-1] = planet->name;
systemname_stack[spacename_nstack-1] = tmp->name;
free(planet); systemname_stack[spacename_nstack-1] = sys->name;
} }
} while(xml_nextNode(cur)); } while(xml_nextNode(cur));
} }
@ -776,17 +822,17 @@ static StarSystem* system_parse(const xmlNodePtr parent) {
fleet = CALLOC_L(SystemFleet); fleet = CALLOC_L(SystemFleet);
fleet->fleet = fleet_get(xml_get(cur)); fleet->fleet = fleet_get(xml_get(cur));
if(fleet->fleet == NULL) if(fleet->fleet == NULL)
WARN("Fleet %s for Star System %s not found", xml_get(cur), tmp->name); WARN("Fleet %s for Star System %s not found", xml_get(cur), sys->name);
ptrc = xml_nodeProp(cur, "chance"); /* Malloc ptrc. */ ptrc = xml_nodeProp(cur, "chance"); /* Malloc ptrc. */
fleet->chance = atoi(ptrc); fleet->chance = atoi(ptrc);
if(fleet->chance == 0) if(fleet->chance == 0)
WARN("Fleet %s for Star System %s has 0%% chance to appear", WARN("Fleet %s for Star System %s has 0%% chance to appear",
fleet->fleet->name, tmp->name); fleet->fleet->name, sys->name);
if(ptrc) free(ptrc); /* Free the ptrc. */ if(ptrc) free(ptrc); /* Free the ptrc. */
tmp->fleets = realloc(tmp->fleets, sizeof(SystemFleet)*(++tmp->nfleets)); sys->fleets = realloc(sys->fleets, sizeof(SystemFleet)*(++sys->nfleets));
memcpy(tmp->fleets+(tmp->nfleets-1), fleet, sizeof(SystemFleet)); memcpy(sys->fleets+(sys->nfleets-1), fleet, sizeof(SystemFleet));
free(fleet); free(fleet);
} }
} while(xml_nextNode(cur)); } while(xml_nextNode(cur));
@ -794,19 +840,21 @@ static StarSystem* system_parse(const xmlNodePtr parent) {
} while(xml_nextNode(node)); } while(xml_nextNode(node));
/* Check elements. */ /* Check elements. */
#define MELEMENT(o,s) if((o) == 0) WARN("Star System '%s' missing '"s"' element", tmp->name) #define MELEMENT(o,s) if((o) == 0) WARN("Star System '%s' missing '"s"' element", sys->name)
if(sys->name == NULL) WARN("Star System '%s' missing 'name' tag", sys->name);
MELEMENT(flags&FLAG_XSET, "x"); MELEMENT(flags&FLAG_XSET, "x");
MELEMENT(flags&FLAG_YSET, "y"); MELEMENT(flags&FLAG_YSET, "y");
MELEMENT(tmp->stars, "stars"); MELEMENT(sys->stars, "stars");
MELEMENT(flags&FLAG_ASTEROIDSSET, "asteroids"); /* Can be 0. */ MELEMENT(flags&FLAG_ASTEROIDSSET, "asteroids"); /* Can be 0. */
MELEMENT(flags&FLAG_INTEFERENCESET, "inteference"); MELEMENT(flags&FLAG_INTEFERENCESET, "inteference");
#undef MELEMENT #undef MELEMENT
/* Post processing. */ /* Post processing. */
if(tmp->nplanets > 0) if(sys->nplanets > 0)
/**< @todo Make dependant on overall planet faction. */ /**< @todo Make dependant on overall planet faction. */
tmp->faction = tmp->planets[0].faction; sys->faction = sys->planets[0]->faction;
return tmp;
return 0;
} }
/* Load the jumps into a system. */ /* Load the jumps into a system. */
@ -849,14 +897,38 @@ static void system_parseJumps(const xmlNodePtr parent) {
} while(xml_nextNode(node)); } while(xml_nextNode(node));
} }
/* Load the ENTIRE universe into RAM. -- WOAH! */ /**
/* -- Used a two system pass to first load the star systems_stack and then set jump routes. */ * @fn int space_load(void)
*
* @brief Load the ENTIRE universe into RAM. -- WOAH!
* @return 0 on success.
*/
int space_load(void) { int space_load(void) {
int ret;
ret = planets_load();
if(ret < 0)
return ret;
ret = systems_load();
if(ret < 0)
return ret;
return 0;
}
/**
* @fn int systems_load(void)
*
* @brief Load the entire systems, needs to be called after planets_load.
*
* Uses a two system pass to first load the star systems_stack and then set
* jump routes.
* @return 0 on success.
*/
static int systems_load(void) {
uint32_t bufsize; uint32_t bufsize;
char* buf = pack_readfile(DATA, SYSTEM_DATA, &bufsize); char* buf = pack_readfile(DATA, SYSTEM_DATA, &bufsize);
StarSystem* tmp;
xmlNodePtr node; xmlNodePtr node;
xmlDocPtr doc = xmlParseMemory(buf, bufsize); xmlDocPtr doc = xmlParseMemory(buf, bufsize);
@ -870,13 +942,24 @@ int space_load(void) {
ERR("Malformed "SYSTEM_DATA" file: does not contain elements"); ERR("Malformed "SYSTEM_DATA" file: does not contain elements");
return -1; return -1;
} }
/* Allocate if needed. */
if(systems_stack == NULL) {
systems_mstack = CHUNK_SIZE;
systems_stack = malloc(sizeof(StarSystem) * systems_mstack);
systems_nstack = 0;
}
/* Fist pass - Load all the star systems_stack. */ /* Fist pass - Load all the star systems_stack. */
do { do {
if(xml_isNode(node, XML_SYSTEM_TAG)) { if(xml_isNode(node, XML_SYSTEM_TAG)) {
tmp = system_parse(node); /* Check if memory needs to grow. */
systems_stack = realloc(systems_stack, sizeof(StarSystem)*(++systems_nstack)); systems_nstack++;
memcpy(systems_stack+systems_nstack-1, tmp, sizeof(StarSystem)); if(systems_nstack > systems_mstack) {
free(tmp); systems_mstack += CHUNK_SIZE;
systems_stack = realloc(systems_stack, sizeof(StarSystem) * systems_mstack);
}
system_parse(&systems_stack[systems_nstack-1], node);
} }
} while(xml_nextNode(node)); } while(xml_nextNode(node));
@ -894,7 +977,7 @@ int space_load(void) {
DEBUG("Loaded %d star system%s with %d planet%s", DEBUG("Loaded %d star system%s with %d planet%s",
systems_nstack, (systems_nstack==1) ? "" : "s", systems_nstack, (systems_nstack==1) ? "" : "s",
total_planets, (total_planets==1) ? "" : "s"); planet_nstack, (planet_nstack==1) ? "" : "s");
return 0; return 0;
} }
@ -996,27 +1079,43 @@ void planets_render(void) {
int i; int i;
for(i = 0; i < cur_system->nplanets; i++) for(i = 0; i < cur_system->nplanets; i++)
gl_blitSprite(cur_system->planets[i].gfx_space, gl_blitSprite(cur_system->planets[i]->gfx_space,
cur_system->planets[i].pos.x, cur_system->planets[i].pos.y, 0, 0, NULL); cur_system->planets[i]->pos.x, cur_system->planets[i]->pos.y,
0, 0, NULL);
} }
/* Clean up the system. */ /* Clean up the system. */
void space_exit(void) { void space_exit(void) {
int i,j; int i;
/* Free the names. */ /* Free the names. */
/*if(planetname_stack) free(planetname_stack); */ if(planetname_stack) free(planetname_stack);
/*if(systemname_stack) free(systemname_stack); */ if(systemname_stack) free(systemname_stack);
if(planetname_stack) {
free(planetname_stack);
planetname_stack = NULL;
}
if(systemname_stack) {
free(systemname_stack);
systemname_stack = NULL;
}
spacename_nstack = 0; spacename_nstack = 0;
/* Free the planets. */
for(i = 0; i < planet_nstack; i++) {
free(planet_stack[i].name);
if(planet_stack[i].description)
free(planet_stack[i].description);
if(planet_stack[i].bar_description)
free(planet_stack[i].bar_description);
/* Graphics. */
if(planet_stack[i].gfx_space)
gl_freeTexture(planet_stack[i].gfx_space);
if(planet_stack[i].gfx_exterior)
free(planet_stack[i].gfx_exterior);
/* Commodities. */
free(planet_stack[i].commodities);
}
free(planet_stack);
planet_stack = NULL;
planet_nstack = 0;
planet_mstack = 0;
/* Free the systems. */ /* Free the systems. */
for(i = 0; i < systems_nstack; i++) { for(i = 0; i < systems_nstack; i++) {
free(systems_stack[i].name); free(systems_stack[i].name);
@ -1025,33 +1124,18 @@ void space_exit(void) {
if(systems_stack[i].jumps) if(systems_stack[i].jumps)
free(systems_stack[i].jumps); free(systems_stack[i].jumps);
/* Free some planets. */
for(j = 0; j < systems_stack[i].nplanets; j++) {
free(systems_stack[i].planets[j].name);
if(systems_stack[i].planets[j].description)
free(systems_stack[i].planets[j].description);
if(systems_stack[i].planets[j].bar_description)
free(systems_stack[i].planets[j].bar_description);
/* Graphics. */
if(systems_stack[i].planets[j].gfx_space)
gl_freeTexture(systems_stack[i].planets[j].gfx_space);
if(systems_stack[i].planets[j].gfx_exterior)
free(systems_stack[i].planets[j].gfx_exterior);
/* Commodities. */
free(systems_stack[i].planets[j].commodities);
}
free(systems_stack[i].planets); free(systems_stack[i].planets);
} }
free(systems_stack); free(systems_stack);
systems_stack = NULL; systems_stack = NULL;
systems_nstack = 0; systems_nstack = 0;
systems_mstack = 0;
/* Stars must be set free too. */ /* Stars must be free too. */
if(stars) free(stars); if(stars) free(stars);
stars = NULL; stars = NULL;
nstars = 0; nstars = 0;
mstars = 0;
} }
/* Clear all system knowledge. */ /* Clear all system knowledge. */

View File

@ -115,7 +115,7 @@ typedef struct StarSystem_ {
int faction; /**< Overall faction. */ int faction; /**< Overall faction. */
Planet* planets; /**< Planets. */ Planet** planets; /**< Planets. */
int nplanets; /**< Total number of planets. */ int nplanets; /**< Total number of planets. */
SystemFleet* fleets; /**< Fleets that can appear in the current system. */ SystemFleet* fleets; /**< Fleets that can appear in the current system. */