From 5a42e63e4a083aae5abd1c631c4ea063ef16c8cc Mon Sep 17 00:00:00 2001 From: Allanis Date: Sat, 7 Dec 2013 22:16:01 +0000 Subject: [PATCH] [Change] Major rewrite of space.c. Let's pray we don't have a ton of bugs. --- src/input.c | 6 +- src/space.c | 542 ++++++++++++++++++++++++++++++---------------------- src/space.h | 2 +- 3 files changed, 317 insertions(+), 233 deletions(-) diff --git a/src/input.c b/src/input.c index 57dfb4e..39d34a6 100644 --- a/src/input.c +++ b/src/input.c @@ -166,12 +166,12 @@ int input_getKeybind(char* keybind, KeybindType* type, int* reverse) { * @param value The value of the keypress (defined above). * @param abs Whether or not it's an absolute value (for the joystick). */ -#define KEY(s) (strcmp(input_keybinds[keynum]->name, s)==0) -#define INGAME() (!toolkit) +#define KEY(s) (strcmp(input_keybinds[keynum]->name, s)==0) /**< Shortcut for ease. */ +#define INGAME() (!toolkit) /**< Make sure player is in game. */ #define NOHYP() \ (player && !pilot_isFlag(player, PILOT_HYP_PREP) && \ !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) { unsigned int t; diff --git a/src/space.c b/src/space.c index c9441d9..3b5b47c 100644 --- a/src/space.c +++ b/src/space.c @@ -34,8 +34,10 @@ #define PLANET_GFX_EXTERIOR_W 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_YSET (1<<1) #define FLAG_ASTEROIDSSET (1<<2) @@ -48,11 +50,19 @@ static char** planetname_stack = NULL; static char** systemname_stack = NULL; 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. */ 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. */ /* Fleet spawn rate. */ @@ -71,14 +81,19 @@ static int nstars = 0; /* Total stars. */ static int mstars = 0; /* Memory stars are taking. */ /* 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_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); /* Extern. */ extern void player_message(const char* fmt, ...); + void planets_minimap(const double res, const double w, const double h, const RadarShape shape); int space_sysSave(xmlTextWriterPtr writer); @@ -100,16 +115,16 @@ void planets_minimap(const double res, const double w, glBegin(GL_POINTS); for(i = 0; i < cur_system->nplanets; i++) { - planet = &cur_system->planets[i]; + planet = cur_system->planets[i]; col = faction_getColour(planet->faction); if((col != &cHostile) && !planet_hasService(planet, PLANET_SERVICE_BASIC)) col = &cInert; /* Override non-hostile planets without services. */ COLOUR(*col); - r = (int)(cur_system->planets[i].gfx_space->sw / 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); + r = (int)(cur_system->planets[i]->gfx_space->sw / 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); x = 0; y = r; @@ -238,7 +253,7 @@ int space_canHyperspace(Pilot* p) { if(p->fuel < HYPERSPACE_FUEL) return 0; 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) return 0; } @@ -270,7 +285,7 @@ char** space_getFactionPlanet(int* nplanets, int* factions, int nfactions) { for(i = 0; i < systems_nstack; i++) 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++) if(planet->faction == factions[k]) { ntmp++; @@ -305,7 +320,7 @@ char* space_getRndPlanet(void) { mtmp += 25; 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)]; @@ -353,15 +368,11 @@ char* planet_getSystem(char* planetname) { /* Get a planet based on it's name. */ Planet* planet_get(char* planetname) { int i; - char* sysname; - StarSystem* sys; - sysname = planet_getSystem(planetname); - sys = system_get(sysname); + for(i = 0; i < planet_nstack; i++) + 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); return NULL; } @@ -441,9 +452,9 @@ static void space_addFleet(Fleet* fleet, int init) { /* Get friendly planet to land on. */ planet = NULL; for(i = 0; i < cur_system->nplanets; i++) - if(planet_hasService(&cur_system->planets[i], PLANET_SERVICE_BASIC) && - !areEnemies(fleet->faction, cur_system->planets[i].faction)) { - planet = &cur_system->planets[i]; + if(planet_hasService(cur_system->planets[i], PLANET_SERVICE_BASIC) && + !areEnemies(fleet->faction, cur_system->planets[i]->faction)) { + planet = cur_system->planets[i]; break; } @@ -534,128 +545,49 @@ void space_init(const char* sysname) { sys_setFlag(cur_system, SYSTEM_KNOWN); } -/* Load the planets of name 'name'. */ -static Planet* planet_pull(const char* name) { - int i; - - Planet* tmp = NULL; - - char str[PATH_MAX] = "\0"; - char* tstr; - - uint32_t flags = 0; - +/** + * @fn static int planets_load(void) + * + * @brief Load all the planets in the game. + * @return 0 on success. + */ +static int planets_load(void) { uint32_t bufsize; - char* buf = pack_readfile(DATA, PLANET_DATA, &bufsize); + char* buf; + xmlNodePtr node; + xmlDocPtr doc; - xmlNodePtr node, cur, ccur; - xmlDocPtr doc = xmlParseMemory(buf, bufsize); + buf = pack_readfile(DATA, PLANET_DATA, &bufsize); + doc = xmlParseMemory(buf, bufsize); node = doc->xmlChildrenNode; if(strcmp((char*)node->name, XML_PLANET_ID)) { ERR("Malformed "PLANET_DATA" file: missing root element '"XML_PLANET_ID"'"); - return NULL; + return -1; } node = node->xmlChildrenNode; /* First system node. */ if(node == NULL) { 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 { if(xml_isNode(node, XML_PLANET_TAG)) { - tstr = xml_nodeProp(node, "name"); - if(strcmp(tstr, name)==0) { /* Found. */ - tmp = CALLOC_L(Planet); - tmp->faction = -1; /* No faction. */ - tmp->name = tstr; - - node = node->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)); - 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. */ + /* See if stack must grow. */ + planet_nstack++; + if(planet_nstack > planet_mstack) { + planet_mstack += CHUNK_SIZE; + planet_stack = realloc(planet_stack, sizeof(Planet) * planet_mstack); + } + planet_parse(&planet_stack[planet_nstack-1], node); } } while(xml_nextNode(node)); @@ -663,47 +595,155 @@ static Planet* planet_pull(const char* name) { free(buf); xmlCleanupParser(); - /* Check elements. */ - 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"); + return 0; +} - MELEMENT((planet_hasService(tmp, PLANET_SERVICE_OUTFITS) || - planet_hasService(tmp, PLANET_SERVICE_SHIPYARD)) && - (flags&FLAG_TECHSET)==0, "tech"); - MELEMENT(planet_hasService(tmp, PLANET_SERVICE_COMMODITY) && - (tmp->ncommodities==0), "commodity"); +/** + * @fn static int planet_parse(Planet* planet, const xmlNodePtr parent) + * + * @brief Parses a planet from an xml node. + * @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 - } else - WARN("No planet found matching name '%s'", name); - return tmp; + return 0; } /* Parse node 'parent' which should be the node of a system. */ /* Return the StarSystem fully loaded. */ -static StarSystem* system_parse(const xmlNodePtr parent) { - Planet* planet = NULL; - SystemFleet* fleet = NULL; - StarSystem* tmp = CALLOC_L(StarSystem); +static StarSystem* system_parse(StarSystem* sys, const xmlNodePtr parent) { + Planet* planet; + SystemFleet* fleet; char* ptrc; xmlNodePtr cur, node; 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; @@ -714,11 +754,11 @@ static StarSystem* system_parse(const xmlNodePtr parent) { do { if(xml_isNode(cur, "x")) { flags |= FLAG_XSET; - tmp->pos.x = xml_getFloat(cur); + sys->pos.x = xml_getFloat(cur); } if(xml_isNode(cur, "y")) { flags |= FLAG_YSET; - tmp->pos.y = xml_getFloat(cur); + sys->pos.y = xml_getFloat(cur); } } while(xml_nextNode(cur)); } @@ -726,22 +766,22 @@ static StarSystem* system_parse(const xmlNodePtr parent) { cur = node->children; do { if(xml_isNode(cur, "stars")) /* Non-zero. */ - tmp->stars = xml_getInt(cur); + sys->stars = xml_getInt(cur); else if(xml_isNode(cur, "asteroids")) { flags |= FLAG_ASTEROIDSSET; - tmp->asteroids = xml_getInt(cur); + sys->asteroids = xml_getInt(cur); } else if(xml_isNode(cur, "interference")) { flags |= FLAG_INTEFERENCESET; - tmp->interference = xml_getFloat(cur)/100; + sys->interference = xml_getFloat(cur)/100; } else if(xml_isNode(cur, "nebulae")) { ptrc = xml_nodeProp(cur, "volatility"); if(ptrc != NULL) { /* Has volatility. */ - tmp->nebu_volatility = atof(ptrc); + sys->nebu_volatility = atof(ptrc); free(ptrc); } - tmp->nebu_density = xml_getFloat(cur); + sys->nebu_density = xml_getFloat(cur); } }while(xml_nextNode(cur)); } @@ -751,20 +791,26 @@ static StarSystem* system_parse(const xmlNodePtr parent) { do { if(cur && xml_isNode(cur, "planet")) { /* Add planet to system. */ - total_planets++; /* Increase planet counter. */ - planet = planet_pull(xml_get(cur)); - tmp->planets = realloc(tmp->planets, sizeof(Planet)*(++tmp->nplanets)); - memcpy(tmp->planets+(tmp->nplanets-1), planet, sizeof(Planet)); + sys->nplanets++; + if(sys->nplanets > size) { + size += CHUNK_SIZE_SMALL; + 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. */ spacename_nstack++; - planetname_stack = realloc(planetname_stack, - sizeof(char*)*spacename_nstack); - systemname_stack = realloc(systemname_stack, - sizeof(char*)*spacename_nstack); + if(spacename_nstack > spacename_mstack) { + spacename_mstack += CHUNK_SIZE; + planetname_stack = realloc(planetname_stack, + sizeof(char*) * spacename_mstack); + systemname_stack = realloc(systemname_stack, + sizeof(char*) * spacename_mstack); + } 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)); } @@ -776,17 +822,17 @@ static StarSystem* system_parse(const xmlNodePtr parent) { fleet = CALLOC_L(SystemFleet); fleet->fleet = fleet_get(xml_get(cur)); 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. */ fleet->chance = atoi(ptrc); if(fleet->chance == 0) 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. */ - tmp->fleets = realloc(tmp->fleets, sizeof(SystemFleet)*(++tmp->nfleets)); - memcpy(tmp->fleets+(tmp->nfleets-1), fleet, sizeof(SystemFleet)); + sys->fleets = realloc(sys->fleets, sizeof(SystemFleet)*(++sys->nfleets)); + memcpy(sys->fleets+(sys->nfleets-1), fleet, sizeof(SystemFleet)); free(fleet); } } while(xml_nextNode(cur)); @@ -794,19 +840,21 @@ static StarSystem* system_parse(const xmlNodePtr parent) { } while(xml_nextNode(node)); /* 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_YSET, "y"); - MELEMENT(tmp->stars, "stars"); + MELEMENT(sys->stars, "stars"); MELEMENT(flags&FLAG_ASTEROIDSSET, "asteroids"); /* Can be 0. */ MELEMENT(flags&FLAG_INTEFERENCESET, "inteference"); #undef MELEMENT /* Post processing. */ - if(tmp->nplanets > 0) + if(sys->nplanets > 0) /**< @todo Make dependant on overall planet faction. */ - tmp->faction = tmp->planets[0].faction; - return tmp; + sys->faction = sys->planets[0]->faction; + + return 0; } /* Load the jumps into a system. */ @@ -849,14 +897,38 @@ static void system_parseJumps(const xmlNodePtr parent) { } 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 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; char* buf = pack_readfile(DATA, SYSTEM_DATA, &bufsize); - StarSystem* tmp; - xmlNodePtr node; xmlDocPtr doc = xmlParseMemory(buf, bufsize); @@ -870,13 +942,24 @@ int space_load(void) { ERR("Malformed "SYSTEM_DATA" file: does not contain elements"); 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. */ do { if(xml_isNode(node, XML_SYSTEM_TAG)) { - tmp = system_parse(node); - systems_stack = realloc(systems_stack, sizeof(StarSystem)*(++systems_nstack)); - memcpy(systems_stack+systems_nstack-1, tmp, sizeof(StarSystem)); - free(tmp); + /* Check if memory needs to grow. */ + systems_nstack++; + if(systems_nstack > systems_mstack) { + 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)); @@ -894,7 +977,7 @@ int space_load(void) { DEBUG("Loaded %d star system%s with %d planet%s", systems_nstack, (systems_nstack==1) ? "" : "s", - total_planets, (total_planets==1) ? "" : "s"); + planet_nstack, (planet_nstack==1) ? "" : "s"); return 0; } @@ -996,27 +1079,43 @@ void planets_render(void) { int i; for(i = 0; i < cur_system->nplanets; i++) - gl_blitSprite(cur_system->planets[i].gfx_space, - cur_system->planets[i].pos.x, cur_system->planets[i].pos.y, 0, 0, NULL); + gl_blitSprite(cur_system->planets[i]->gfx_space, + cur_system->planets[i]->pos.x, cur_system->planets[i]->pos.y, + 0, 0, NULL); } /* Clean up the system. */ void space_exit(void) { - int i,j; + int i; /* Free the names. */ - /*if(planetname_stack) free(planetname_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; - } + if(planetname_stack) free(planetname_stack); + if(systemname_stack) free(systemname_stack); 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. */ for(i = 0; i < systems_nstack; i++) { free(systems_stack[i].name); @@ -1025,33 +1124,18 @@ void space_exit(void) { if(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); - systems_stack = NULL; - systems_nstack = 0; + systems_stack = NULL; + systems_nstack = 0; + systems_mstack = 0; - /* Stars must be set free too. */ + /* Stars must be free too. */ if(stars) free(stars); - stars = NULL; - nstars = 0; + stars = NULL; + nstars = 0; + mstars = 0; } /* Clear all system knowledge. */ diff --git a/src/space.h b/src/space.h index c277e5a..5958749 100644 --- a/src/space.h +++ b/src/space.h @@ -115,7 +115,7 @@ typedef struct StarSystem_ { int faction; /**< Overall faction. */ - Planet* planets; /**< Planets. */ + Planet** planets; /**< Planets. */ int nplanets; /**< Total number of planets. */ SystemFleet* fleets; /**< Fleets that can appear in the current system. */