/** * @brief Allocates space for and populates a list of asset mods from a unistate xml tree. * * @param rootNode A node pointer to the root node of unistate tree * @return A pointer to the first node of the linked list. */ assetStatePtr unistate_populateList(xmlNodePtr root) { assetStatePtr listHead = NULL, curElement = NULL; xmlNodePtr elementNode = NULL, listNode = NULL; #ifdef UNISTATE_DEBUG char debugBuffer[PATH_MAX]; #endif //no root node? if(!root) return NULL; //root has no children? if(!(listNode = root->children)) return NULL; //iterate over assets do { //if the node is named right if(xml_isNode(listNode, "asset")) { elementNode = listNode->children; //set up list element curElement = malloc(sizeof(assetState)); curElement->next = listHead; listHead = curElement; curElement->name = curElement->faction = NULL; curElement->presence = -1; //get info from file xmlr_attr(listNode, "name", curElement->name); //debug stuff #ifdef UNISTATE_DEBUG snprintf(debugBuffer, sizeof(char) * (PATH_MAX - 1),\ "UniState Debug: Asset name '%s' parsed\n", curElement->name); logprintf(stdout, debugBuffer); #endif do { xml_onlyNodes(elementNode); xmlr_strd(elementNode, "faction", curElement->faction); xmlr_int(elementNode, "presence", curElement->presence); xmlr_int(elementNode, "presence_range", curElement->range); } while(xml_nextNode(elementNode)); //more debug stuff #ifdef UNISTATE_DEBUG snprintf(debugBuffer, sizeof(char) * (PATH_MAX - 1),\ "UniState Debug: Asset faction '%s' and Asset presence '%i' parsed\n",\ (curElement->faction == NULL ? "<Default>" : curElement->faction), curElement->presence); logprintf(stdout, debugBuffer); #endif } } while(xml_nextNode(listNode)); //return the list return listHead; }
/** * @brief Loads a commodity. * * @param temp Commodity to load data into. * @param parent XML node to load from. * @return Commodity loaded from parent. */ static int commodity_parse( Commodity *temp, xmlNodePtr parent ) { xmlNodePtr node; /* Clear memory. */ memset( temp, 0, sizeof(Commodity) ); temp->name = (char*)xmlGetProp(parent,(xmlChar*)"name"); if (temp->name == NULL) WARN("Commodity from "COMMODITY_DATA" has invalid or no name"); node = parent->xmlChildrenNode; do { xmlr_strd(node, "description", temp->description); xmlr_int(node, "price", temp->price); } while (xml_nextNode(node)); #if 0 /* shouldn't be needed atm */ #define MELEMENT(o,s) if (o) WARN("Commodity '%s' missing '"s"' element", temp->name) MELEMENT(temp->description==NULL,"description"); MELEMENT(temp->high==0,"high"); MELEMENT(temp->medium==0,"medium"); MELEMENT(temp->low==0,"low"); #undef MELEMENT #endif return 0; }
/** * @brief Parses the modification tidbits of the outfit. * * @param temp Outfit to finish loading. * @param parent Outfit's parent node. */ static void outfit_parseSMod( Outfit* temp, const xmlNodePtr parent ) { xmlNodePtr node; node = parent->children; do { /* load all the data */ /* movement */ xmlr_float(node,"thrust",temp->u.mod.thrust); xmlr_float(node,"turn",temp->u.mod.turn); xmlr_float(node,"speed",temp->u.mod.speed); /* health */ xmlr_float(node,"armour",temp->u.mod.armour); xmlr_float(node,"shield",temp->u.mod.shield); xmlr_float(node,"energy",temp->u.mod.energy); xmlr_float(node,"fuel",temp->u.mod.fuel); if (xml_isNode(node,"armour_regen")) temp->u.mod.armour_regen = xml_getFloat(node)/60.0; else if (xml_isNode(node,"shield_regen")) temp->u.mod.shield_regen = xml_getFloat(node)/60.0; else if (xml_isNode(node,"energy_regen")) temp->u.mod.energy_regen = xml_getFloat(node)/60.0; /* misc */ xmlr_int(node,"cargo",temp->u.mod.cargo); } while (xml_nextNode(node)); }
/** * @brief Parses the map tidbits of the outfit. * * @param temp Outfit to finish loading. * @param parent Outfit's parent node. */ static void outfit_parseSMap( Outfit *temp, const xmlNodePtr parent ) { xmlNodePtr node; node = parent->children; do { xmlr_int(node,"radius",temp->u.map.radius); } while (xml_nextNode(node)); if (temp->u.map.radius==0) WARN("Outfit '%s' missing/invalid 'radius' element", temp->name); }
/** * @brief Parses the fighter bay tidbits of the outfit. * * @param temp Outfit to finish loading. * @param parent Outfit's parent node. */ static void outfit_parseSFighterBay( Outfit *temp, const xmlNodePtr parent ) { xmlNodePtr node; node = parent->children; do { xmlr_int(node,"delay",temp->u.bay.delay); xmlr_strd(node,"ammo",temp->u.bay.ammo_name); } while (xml_nextNode(node)); #define MELEMENT(o,s) \ if (o) WARN("Outfit '%s' missing/invalid '"s"' element", temp->name) /**< Define to help check for data errors. */ MELEMENT(temp->u.bay.delay==0,"delay"); MELEMENT(temp->u.bay.ammo_name==NULL,"ammo"); #undef MELEMENT }
/** * @brief Parses the specific area for a launcher and loads it into Outfit. * * @param temp Outfit to finish loading. * @param parent Outfit's parent node. */ static void outfit_parseSLauncher( Outfit* temp, const xmlNodePtr parent ) { xmlNodePtr node; node = parent->xmlChildrenNode; do { /* load all the data */ xmlr_int(node,"delay",temp->u.lau.delay); xmlr_strd(node,"ammo",temp->u.lau.ammo_name); } while (xml_nextNode(node)); #define MELEMENT(o,s) \ if (o) WARN("Outfit '%s' missing '"s"' element", temp->name) /**< Define to help check for data errors. */ MELEMENT(temp->u.lau.ammo_name==NULL,"ammo"); MELEMENT(temp->u.lau.delay==0,"delay"); #undef MELEMENT }
/** * @brief Loads the module start data. * * @return 0 on success. */ int start_load (void) { uint32_t bufsize; char *buf; xmlNodePtr node, cur, tmp; xmlDocPtr doc; int scu, stp, stu; /* Defaults. */ scu = -1; stp = -1; stu = -1; /* Try to read the file. */ buf = ndata_read( START_DATA_PATH, &bufsize ); if (buf == NULL) return -1; /* Load the XML file. */ doc = xmlParseMemory( buf, bufsize ); node = doc->xmlChildrenNode; if (!xml_isNode(node,XML_START_ID)) { ERR("Malformed '"START_DATA_PATH"' file: missing root element '"XML_START_ID"'"); return -1; } node = node->xmlChildrenNode; /* first system node */ if (node == NULL) { ERR("Malformed '"START_DATA_PATH"' file: does not contain elements"); return -1; } do { xml_onlyNodes(node); xmlr_strd( node, "name", start_data.name ); if (xml_isNode(node, "player")) { /* we are interested in the player */ cur = node->children; do { xml_onlyNodes(cur); xmlr_uint( cur, "credits", start_data.credits ); xmlr_strd( cur, "mission", start_data.mission ); xmlr_strd( cur, "event", start_data.event ); if (xml_isNode(cur,"ship")) { xmlr_attr( cur, "name", start_data.shipname); xmlr_strd( cur, "ship", start_data.ship ); } else if (xml_isNode(cur,"system")) { tmp = cur->children; do { xml_onlyNodes(tmp); /** system name, @todo percent chance */ xmlr_strd( tmp, "name", start_data.system ); /* position */ xmlr_float( tmp, "x", start_data.x ); xmlr_float( tmp, "y", start_data.y ); WARN("'"START_DATA_PATH"' has unknown system node '%s'.", tmp->name); } while (xml_nextNode(tmp)); continue; } WARN("'"START_DATA_PATH"' has unknown player node '%s'.", cur->name); } while (xml_nextNode(cur)); continue; } if (xml_isNode(node,"date")) { cur = node->children; do { xml_onlyNodes(cur); xmlr_int( cur, "scu", scu ); xmlr_int( cur, "stp", stp ); xmlr_int( cur, "stu", stu ); WARN("'"START_DATA_PATH"' has unknown date node '%s'.", cur->name); } while (xml_nextNode(cur)); continue; } if (xml_isNode(node,"tutorial")) { cur = node->children; do { xml_onlyNodes(cur); xmlr_strd( cur, "mission", start_data.tutmisn ); xmlr_strd( cur, "event", start_data.tutevt ); if (xml_isNode(cur,"system")) { tmp = cur->children; do { xml_onlyNodes(tmp); /** system name, @todo percent chance */ xmlr_strd( tmp, "name", start_data.tutsys ); /* position */ xmlr_float( tmp, "x", start_data.tutx ); xmlr_float( tmp, "y", start_data.tuty ); WARN("'"START_DATA_PATH"' has unknown system node '%s'.", tmp->name); } while (xml_nextNode(tmp)); continue; } WARN("'"START_DATA_PATH"' has unknown tutorial node '%s'.", cur->name); } while (xml_nextNode(cur)); continue; } WARN("'"START_DATA_PATH"' has unknown node '%s'.", node->name); } while (xml_nextNode(node)); /* Clean up. */ xmlFreeDoc(doc); free(buf); /* Sanity checking. */ #define MELEMENT(o,s) \ if (o) WARN("Module start data missing/invalid '"s"' element") /**< Define to help check for data errors. */ MELEMENT( start_data.name==NULL, "name" ); MELEMENT( start_data.credits==0, "credits" ); MELEMENT( start_data.ship==NULL, "ship" ); MELEMENT( start_data.system==NULL, "player system" ); MELEMENT( start_data.tutsys==NULL, "tutorial system" ); MELEMENT( scu<0, "scu" ); MELEMENT( stp<0, "stp" ); MELEMENT( stu<0, "stu" ); #undef MELEMENT /* Post process. */ start_data.date = ntime_create( scu, stp, stu ); return 0; }
/** * @brief Parses a node of a mission. * * @param temp Data to load into. * @param parent Node containing the mission. * @return 0 on success. */ static int mission_parse( MissionData* temp, const xmlNodePtr parent ) { xmlNodePtr cur, node; #ifdef DEBUGGING /* To check if mission is valid. */ lua_State *L; int ret; char *buf; uint32_t len; #endif /* DEBUGGING */ /* Clear memory. */ memset( temp, 0, sizeof(MissionData) ); /* Defaults. */ temp->avail.priority = 5; /* get the name */ temp->name = xml_nodeProp(parent,"name"); if (temp->name == NULL) WARN("Mission in "MISSION_DATA_PATH" has invalid or no name"); node = parent->xmlChildrenNode; char str[PATH_MAX] = "\0"; do { /* load all the data */ /* Only handle nodes. */ xml_onlyNodes(node); if (xml_isNode(node,"lua")) { nsnprintf( str, PATH_MAX, MISSION_LUA_PATH"%s.lua", xml_get(node) ); temp->lua = strdup( str ); str[0] = '\0'; #ifdef DEBUGGING /* Check to see if syntax is valid. */ L = luaL_newstate(); buf = ndata_read( temp->lua, &len ); ret = luaL_loadbuffer(L, buf, len, temp->name ); if (ret == LUA_ERRSYNTAX) { WARN("Mission Lua '%s' of mission '%s' syntax error: %s", temp->name, temp->lua, lua_tostring(L,-1) ); } free(buf); lua_close(L); #endif /* DEBUGGING */ continue; } else if (xml_isNode(node,"flags")) { /* set the various flags */ cur = node->children; do { xml_onlyNodes(cur); if (xml_isNode(cur,"unique")) { mis_setFlag(temp,MISSION_UNIQUE); continue; } WARN("Mission '%s' has unknown flag node '%s'.", temp->name, cur->name); } while (xml_nextNode(cur)); continue; } else if (xml_isNode(node,"avail")) { /* mission availability */ cur = node->children; do { xml_onlyNodes(cur); if (xml_isNode(cur,"location")) { temp->avail.loc = mission_location( xml_get(cur) ); continue; } xmlr_int(cur,"chance",temp->avail.chance); xmlr_strd(cur,"planet",temp->avail.planet); xmlr_strd(cur,"system",temp->avail.system); if (xml_isNode(cur,"faction")) { temp->avail.factions = realloc( temp->avail.factions, sizeof(int) * ++temp->avail.nfactions ); temp->avail.factions[temp->avail.nfactions-1] = faction_get( xml_get(cur) ); continue; } xmlr_strd(cur,"cond",temp->avail.cond); xmlr_strd(cur,"done",temp->avail.done); xmlr_int(cur,"priority",temp->avail.priority); WARN("Mission '%s' has unknown avail node '%s'.", temp->name, cur->name); } while (xml_nextNode(cur)); continue; } DEBUG("Unknown node '%s' in mission '%s'",node->name,temp->name); } while (xml_nextNode(node)); #define MELEMENT(o,s) \ if (o) WARN("Mission '%s' missing/invalid '"s"' element", temp->name) MELEMENT(temp->lua==NULL,"lua"); MELEMENT(temp->avail.loc==-1,"location"); MELEMENT((temp->avail.loc!=MIS_AVAIL_NONE) && (temp->avail.chance==0),"chance"); #undef MELEMENT return 0; }
/** * @brief Parses and returns Outfit from parent node. * * @param temp Outfit to load into. * @param parent Parent node to parse outfit from. * @return 0 on success. */ static int outfit_parse( Outfit* temp, const xmlNodePtr parent ) { xmlNodePtr cur, node; char *prop; /* Clear data. */ memset( temp, 0, sizeof(Outfit) ); temp->name = xml_nodeProp(parent,"name"); /* already mallocs */ if (temp->name == NULL) WARN("Outfit in "OUTFIT_DATA" has invalid or no name"); node = parent->xmlChildrenNode; do { /* load all the data */ if (xml_isNode(node,"general")) { cur = node->children; do { xmlr_int(cur,"max",temp->max); xmlr_int(cur,"tech",temp->tech); xmlr_strd(cur,"license",temp->license); xmlr_int(cur,"mass",temp->mass); xmlr_int(cur,"price",temp->price); xmlr_strd(cur,"description",temp->description); if (xml_isNode(cur,"gfx_store")) { temp->gfx_store = xml_parseTexture( cur, OUTFIT_GFX"store/%s.png", 1, 1, 0 ); } } while (xml_nextNode(cur)); } else if (xml_isNode(node,"specific")) { /* has to be processed seperately */ /* get the type */ prop = xml_nodeProp(node,"type"); if (prop == NULL) ERR("Outfit '%s' element 'specific' missing property 'type'",temp->name); temp->type = outfit_strToOutfitType(prop); free(prop); /* is secondary weapon? */ prop = xml_nodeProp(node,"secondary"); if (prop != NULL) { if ((int)atoi(prop)) outfit_setProp(temp, OUTFIT_PROP_WEAP_SECONDARY); free(prop); } if (temp->type==OUTFIT_TYPE_NULL) WARN("Outfit '%s' is of type NONE", temp->name); else if (outfit_isBolt(temp)) outfit_parseSBolt( temp, node ); else if (outfit_isBeam(temp)) outfit_parseSBeam( temp, node ); else if (outfit_isLauncher(temp)) outfit_parseSLauncher( temp, node ); else if (outfit_isAmmo(temp)) outfit_parseSAmmo( temp, node ); else if (outfit_isMod(temp)) outfit_parseSMod( temp, node ); else if (outfit_isAfterburner(temp)) outfit_parseSAfterburner( temp, node ); else if (outfit_isJammer(temp)) outfit_parseSJammer( temp, node ); else if (outfit_isFighterBay(temp)) outfit_parseSFighterBay( temp, node ); else if (outfit_isFighter(temp)) outfit_parseSFighter( temp, node ); else if (outfit_isMap(temp)) outfit_parseSMap( temp, node ); else if (outfit_isLicense(temp)) outfit_parseSLicense( temp, node ); } } while (xml_nextNode(node)); #define MELEMENT(o,s) \ if (o) WARN("Outfit '%s' missing/invalid '"s"' element", temp->name) /**< Define to help check for data errors. */ MELEMENT(temp->name==NULL,"name"); MELEMENT(temp->max==0,"max"); MELEMENT(temp->tech==0,"tech"); MELEMENT(temp->gfx_store==NULL,"gfx_store"); /*MELEMENT(temp->mass==0,"mass"); Not really needed */ MELEMENT(temp->type==0,"type"); MELEMENT(temp->price==0,"price"); MELEMENT(temp->description==NULL,"description"); #undef MELEMENT return 0; }