/** * @brief Loads the player's faction standings. * * @param parent Parent xml node to read from. * @return 0 on success. */ int pfaction_load( xmlNodePtr parent ) { xmlNodePtr node, cur; char *str; int faction; node = parent->xmlChildrenNode; do { if (xml_isNode(node,"factions")) { cur = node->xmlChildrenNode; do { if (xml_isNode(cur,"faction")) { xmlr_attr(cur,"name",str); faction = faction_get(str); if (faction != -1) /* Faction is valid. */ faction_stack[faction].player = xml_getFloat(cur); free(str); } } while (xml_nextNode(cur)); } } while (xml_nextNode(node)); return 0; }
/** * @brief Loads the player's faction standings. * * @param parent Parent xml node to read from. * @return 0 on success. */ int pfaction_load( xmlNodePtr parent ) { xmlNodePtr node, cur; char *str; int faction; node = parent->xmlChildrenNode; do { if (xml_isNode(node,"factions")) { cur = node->xmlChildrenNode; do { if (xml_isNode(cur,"faction")) { xmlr_attr(cur,"name",str); faction = faction_get(str); if (faction != -1) { /* Faction is valid. */ /* Must not be static. */ if (!faction_isFlag( &faction_stack[faction], FACTION_STATIC )) faction_stack[faction].player = xml_getFloat(cur); } free(str); } } while (xml_nextNode(cur)); } } while (xml_nextNode(node)); 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 actual individual event nodes. * * @param parent Parent node to parse. * @return 0 on success. */ static int events_parseActive( xmlNodePtr parent ) { char *buf; unsigned int id; int data; xmlNodePtr node, cur; Event_t *ev; node = parent->xmlChildrenNode; do { if (!xml_isNode(node,"event")) continue; xmlr_attr(node,"name",buf); if (buf==NULL) { WARN("Event has missing 'name' attribute, skipping."); continue; } data = event_dataID( buf ); if (data < 0) { WARN("Event in save has name '%s' but event data not found matching name. Skipping.", buf); free(buf); continue; } free(buf); xmlr_attr(node,"id",buf); if (buf==NULL) { WARN("Event with data '%s' has missing 'id' attribute, skipping.", event_dataName(data)); continue; } id = atoi(buf); free(buf); if (id==0) { WARN("Event with data '%s' has invalid 'id' attribute, skipping.", event_dataName(data)); continue; } /* Create the event. */ event_create( data, &id ); ev = event_get( id ); if (ev == NULL) { WARN("Event with data '%s' was not created, skipping.", event_dataName(data)); continue; } ev->save = 1; /* Should save by default again. */ /* Get the data. */ cur = node->xmlChildrenNode; do { if (xml_isNode(cur,"lua")) nxml_unpersistLua( ev->L, cur ); } while (xml_nextNode(cur)); /* Claims. */ if (xml_isNode(node,"claims")) ev->claims = claim_xmlLoad( node ); } while (xml_nextNode(node)); return 0; }
/** * @brief Parses the social tidbits of a faction: allies and enemies. * * @param parent Node containing the faction. */ static void faction_parseSocial( xmlNodePtr parent ) { xmlNodePtr node, cur; char *buf; Faction *base; int mod; int mem; buf = xml_nodeProp(parent,"name"); base = &faction_stack[faction_get(buf)]; free(buf); node = parent->xmlChildrenNode; do { /* Grab the allies */ if (xml_isNode(node,"allies")) { cur = node->xmlChildrenNode; mem = 0; do { if (xml_isNode(cur,"ally")) { mod = faction_get(xml_get(cur)); base->nallies++; if (base->nallies > mem) { mem += CHUNK_SIZE; base->allies = realloc(base->allies, sizeof(int)*mem); } base->allies[base->nallies-1] = mod; } } while (xml_nextNode(cur)); if (base->nallies > 0) base->allies = realloc(base->allies, sizeof(int)*base->nallies); } /* Grab the enemies */ if (xml_isNode(node,"enemies")) { cur = node->xmlChildrenNode; mem = 0; do { if (xml_isNode(cur,"enemy")) { mod = faction_get(xml_get(cur)); base->nenemies++; if (base->nenemies > mem) { mem += CHUNK_SIZE; base->enemies = realloc(base->enemies, sizeof(int)*mem); } base->enemies[base->nenemies-1] = mod; } } while (xml_nextNode(cur)); if (base->nenemies > 0) base->enemies = realloc(base->enemies, sizeof(int)*base->nenemies); } } while (xml_nextNode(node)); }
/** * @brief Loads the dtype stack. * * @return 0 on success. */ int dtype_load (void) { int mem; uint32_t bufsize; char *buf; xmlNodePtr node; xmlDocPtr doc; /* Load and read the data. */ buf = ndata_read( DTYPE_DATA, &bufsize ); doc = xmlParseMemory( buf, bufsize ); /* Check to see if document exists. */ node = doc->xmlChildrenNode; if (!xml_isNode(node,DTYPE_XML_ID)) { ERR("Malformed '"DTYPE_DATA"' file: missing root element '"DTYPE_XML_ID"'"); return -1; } /* Check to see if is populated. */ node = node->xmlChildrenNode; /* first system node */ if (node == NULL) { ERR("Malformed '"DTYPE_DATA"' file: does not contain elements"); return -1; } /* Load up the individual damage types. */ mem = 0; do { xml_onlyNodes(node); if (!xml_isNode(node,DTYPE_XML_TAG)) { WARN("'"DTYPE_DATA"' has unknown node '%s'.", node->name); continue; } dtype_ntypes++; if (dtype_ntypes > mem) { if (mem == 0) mem = DTYPE_CHUNK_MIN; else mem *= 2; dtype_types = realloc(dtype_types, sizeof(DTYPE)*mem); } DTYPE_parse( &dtype_types[dtype_ntypes-1], node ); } while (xml_nextNode(node)); /* Shrink back to minimum - shouldn't change ever. */ dtype_types = realloc(dtype_types, sizeof(DTYPE) * dtype_ntypes); /* Clean up. */ xmlFreeDoc(doc); free(buf); return 0; }
/** * @brief Loads the spfx stack. * * @return 0 on success. * * @todo Make spfx not hardcoded. */ int spfx_load (void) { int mem; uint32_t bufsize; char *buf; xmlNodePtr node; xmlDocPtr doc; /* Load and read the data. */ buf = ndata_read( SPFX_DATA, &bufsize ); doc = xmlParseMemory( buf, bufsize ); /* Check to see if document exists. */ node = doc->xmlChildrenNode; if (!xml_isNode(node,SPFX_XML_ID)) { ERR("Malformed '"SPFX_DATA"' file: missing root element '"SPFX_XML_ID"'"); return -1; } /* Check to see if is populated. */ node = node->xmlChildrenNode; /* first system node */ if (node == NULL) { ERR("Malformed '"SPFX_DATA"' file: does not contain elements"); return -1; } /* First pass, loads up ammunition. */ mem = 0; do { if (xml_isNode(node,SPFX_XML_TAG)) { spfx_neffects++; if (spfx_neffects > mem) { mem += CHUNK_SIZE; spfx_effects = realloc(spfx_effects, sizeof(SPFX_Base)*mem); } spfx_base_parse( &spfx_effects[spfx_neffects-1], node ); } } while (xml_nextNode(node)); /* Shrink back to minimum - shouldn't change ever. */ spfx_effects = realloc(spfx_effects, sizeof(SPFX_Base) * spfx_neffects); /* Clean up. */ xmlFreeDoc(doc); free(buf); /* * Now initialize force feedback. */ spfx_hapticInit(); return 0; }
/** * @brief Loads all the mission data. * * @return 0 on success. */ int missions_load (void) { int i, m; uint32_t bufsize; char *buf; for (i=0; i<MISSION_MAX; i++) player_missions[i] = calloc(1, sizeof(Mission)); buf = ndata_read( MISSION_DATA_PATH, &bufsize ); xmlNodePtr node; xmlDocPtr doc = xmlParseMemory( buf, bufsize ); node = doc->xmlChildrenNode; if (!xml_isNode(node,XML_MISSION_ID)) { ERR("Malformed '"MISSION_DATA_PATH"' file: missing root element '"XML_MISSION_ID"'"); return -1; } node = node->xmlChildrenNode; /* first mission node */ if (node == NULL) { ERR("Malformed '"MISSION_DATA_PATH"' file: does not contain elements"); return -1; } m = 0; do { if (xml_isNode(node,XML_MISSION_TAG)) { /* See if must grow. */ mission_nstack++; if (mission_nstack > m) { m += MISSION_CHUNK; mission_stack = realloc(mission_stack, sizeof(MissionData)*m); } /* Load it. */ mission_parse( &mission_stack[mission_nstack-1], node ); } } while (xml_nextNode(node)); /* Shrink to minimum. */ mission_stack = realloc(mission_stack, sizeof(MissionData)*mission_nstack); /* Clean up. */ xmlFreeDoc(doc); free(buf); DEBUG("Loaded %d Mission%s", mission_nstack, (mission_nstack==1) ? "" : "s" ); return 0; }
/** * @brief Loads all the outfits. * * @return 0 on success. */ int outfit_load (void) { int i, mem; uint32_t bufsize; char *buf = ndata_read( OUTFIT_DATA, &bufsize ); xmlNodePtr node; xmlDocPtr doc = xmlParseMemory( buf, bufsize ); node = doc->xmlChildrenNode; if (!xml_isNode(node,XML_OUTFIT_ID)) { ERR("Malformed '"OUTFIT_DATA"' file: missing root element '"XML_OUTFIT_ID"'"); return -1; } node = node->xmlChildrenNode; /* first system node */ if (node == NULL) { ERR("Malformed '"OUTFIT_DATA"' file: does not contain elements"); return -1; } /* First pass, loads up ammunition. */ mem = 0; do { if (xml_isNode(node,XML_OUTFIT_TAG)) { outfit_nstack++; if (outfit_nstack > mem) { mem += CHUNK_SIZE; outfit_stack = realloc(outfit_stack, sizeof(Outfit)*mem); } outfit_parse( &outfit_stack[outfit_nstack-1], node ); } } while (xml_nextNode(node)); /* Shrink back to minimum - shouldn't change ever. */ outfit_stack = realloc(outfit_stack, sizeof(Outfit) * outfit_nstack); /* Second pass, sets up ammunition relationships. */ for (i=0; i<outfit_nstack; i++) { if (outfit_isLauncher(&outfit_stack[i])) outfit_stack[i].u.lau.ammo = outfit_get( outfit_stack[i].u.lau.ammo_name ); else if (outfit_isFighterBay(&outfit_stack[i])) outfit_stack[i].u.bay.ammo = outfit_get( outfit_stack[i].u.bay.ammo_name ); } xmlFreeDoc(doc); free(buf); DEBUG("Loaded %d Outfit%s", outfit_nstack, (outfit_nstack==1) ? "" : "s" ); return 0; }
/** * @brief Parses a single faction, but doesn't set the allies/enemies bit. * * @param temp Faction to load data into. * @param parent Parent node to extract faction from. * @return Faction created from parent node. */ static int faction_parse( Faction* temp, xmlNodePtr parent ) { xmlNodePtr node; int player; char buf[PATH_MAX]; /* Clear memory. */ memset( temp, 0, sizeof(Faction) ); temp->name = xml_nodeProp(parent,"name"); if (temp->name == NULL) WARN("Faction from "FACTION_DATA" has invalid or no name"); player = 0; node = parent->xmlChildrenNode; do { /* Can be 0 or negative, so we have to take that into account. */ if (xml_isNode(node,"player")) { temp->player_def = xml_getFloat(node); player = 1; continue; } xmlr_strd(node,"longname",temp->longname); if (xml_isNode(node, "colour")) temp->colour = col_fromName(xml_raw(node)); if (xml_isNode(node,"logo")) { snprintf( buf, PATH_MAX, FACTION_LOGO_PATH"%s_small.png", xml_get(node)); temp->logo_small = gl_newImage(buf, 0); continue; } if (xml_isNode(node,"static")) { faction_setFlag(temp, FACTION_STATIC); continue; } if (xml_isNode(node,"invisible")) { faction_setFlag(temp, FACTION_INVISIBLE); continue; } } while (xml_nextNode(node)); if (player==0) DEBUG("Faction '%s' missing player tag.", temp->name); return 0; }
/** * @brief Loads a claim. * * @param parent Parent node containing the claim data. * @return The system claim. */ SysClaim_t *claim_xmlLoad( xmlNodePtr parent ) { SysClaim_t *claim; xmlNodePtr node; StarSystem *sys; /* Create the claim. */ claim = claim_create(); /* Load the nodes. */ node = parent->xmlChildrenNode; do { if (xml_isNode(node,"sys")) { sys = system_get( xml_get(node) ); if (sys != NULL) claim_add( claim, system_index(sys) ); else WARN("System Claim trying to load system '%s' which doesn't exist.", xml_get(node)); } } while (xml_nextNode(node)); /* Activate the claim. */ claim_activate( claim ); return claim; }
/** * @brief Parses an xml node containing a SPFX. * * @param temp Address to load SPFX into. * @param parent XML Node containing the SPFX data. * @return 0 on success. */ static int spfx_base_parse( SPFX_Base *temp, const xmlNodePtr parent ) { xmlNodePtr node; /* Clear data. */ memset( temp, 0, sizeof(SPFX_Base) ); /* Get the name (mallocs). */ temp->name = xml_nodeProp(parent,"name"); /* Extract the data. */ node = parent->xmlChildrenNode; do { xmlr_float(node, "anim", temp->anim); xmlr_float(node, "ttl", temp->ttl); if (xml_isNode(node,"gfx")) temp->gfx = xml_parseTexture( node, SPFX_GFX_PRE"%s"SPFX_GFX_SUF, 6, 5, 0 ); } while (xml_nextNode(node)); /* Convert from ms to s. */ temp->anim /= 1000.; temp->ttl /= 1000.; if (temp->ttl == 0.) temp->ttl = temp->anim; #define MELEMENT(o,s) \ if (o) WARN("SPFX '%s' missing/invalid '"s"' element", temp->name) /**< Define to help check for data errors. */ MELEMENT(temp->anim==0.,"anim"); MELEMENT(temp->ttl==0.,"ttl"); MELEMENT(temp->gfx==NULL,"gfx"); #undef MELEMENT return 0; }
/** * @brief Loads all the commodity data. * * @return 0 on success. */ int commodity_load (void) { uint32_t bufsize; char *buf; xmlNodePtr node; xmlDocPtr doc; /* Load the file. */ buf = ndata_read( COMMODITY_DATA, &bufsize); if (buf == NULL) return -1; /* Handle the XML. */ doc = xmlParseMemory( buf, bufsize ); if (doc == NULL) { WARN("'%s' is not valid XML.", COMMODITY_DATA); return -1; } node = doc->xmlChildrenNode; /* Commoditys node */ if (strcmp((char*)node->name,XML_COMMODITY_ID)) { ERR("Malformed "COMMODITY_DATA" file: missing root element '"XML_COMMODITY_ID"'"); return -1; } node = node->xmlChildrenNode; /* first faction node */ if (node == NULL) { ERR("Malformed "COMMODITY_DATA" file: does not contain elements"); return -1; } do { if (xml_isNode(node, XML_COMMODITY_TAG)) { /* Make room for commodity. */ commodity_stack = realloc(commodity_stack, sizeof(Commodity)*(++commodity_nstack)); /* Load commodity. */ commodity_parse(&commodity_stack[commodity_nstack-1], node); /* See if should get added to commodity list. */ if (commodity_stack[commodity_nstack-1].price > 0.) { econ_nprices++; econ_comm = realloc(econ_comm, econ_nprices * sizeof(int)); econ_comm[econ_nprices-1] = commodity_nstack-1; } } } while (xml_nextNode(node)); xmlFreeDoc(doc); free(buf); DEBUG("Loaded %d Commodit%s", commodity_nstack, (commodity_nstack==1) ? "y" : "ies" ); return 0; }
/** * @brief Applies a diff to the universe. * * @param name Diff to apply. * @return 0 on success. */ int diff_apply( const char *name ) { xmlNodePtr node; xmlDocPtr doc; size_t bufsize; char *buf; char *diffname; /* Check if already applied. */ if (diff_isApplied(name)) return 0; buf = ndata_read( DIFF_DATA_PATH, &bufsize ); doc = xmlParseMemory( buf, bufsize ); node = doc->xmlChildrenNode; if (strcmp((char*)node->name,"unidiffs")) { ERR(_("Malformed unidiff file: missing root element 'unidiffs'")); return 0; } node = node->xmlChildrenNode; /* first system node */ if (node == NULL) { ERR(_("Malformed unidiff file: does not contain elements")); return 0; } do { if (xml_isNode(node,"unidiff")) { /* Check to see if it's the diff we're looking for. */ xmlr_attr(node,"name",diffname); if (strcmp(diffname,name)==0) { /* Apply it. */ diff_patch( node ); /* Clean up. */ free(diffname); xmlFreeDoc(doc); free(buf); economy_execQueued(); return 0; } free(diffname); } } while (xml_nextNode(node)); /* More clean up. */ xmlFreeDoc(doc); free(buf); WARN(_("UniDiff '%s' not found in %s."), name, DIFF_DATA_PATH); return -1; }
/** * @brief Loads the diffs. * * @param parent Parent node containing diffs. * @return 0 on success. */ int diff_load( xmlNodePtr parent ) { xmlNodePtr node, cur; diff_clear(); node = parent->xmlChildrenNode; do { if (xml_isNode(node,"diffs")) { cur = node->xmlChildrenNode; do { if (xml_isNode(cur,"diff")) diff_apply( xml_get(cur) ); } while (xml_nextNode(cur)); } } while (xml_nextNode(node)); return 0; }
/** * @brief Parses the afterburner tidbits of the outfit. * * @param temp Outfit to finish loading. * @param parent Outfit's parent node. */ static void outfit_parseSAfterburner( Outfit* temp, const xmlNodePtr parent ) { xmlNodePtr node; node = parent->children; /* must be >= 1. */ temp->u.afb.thrust_perc = 1.; temp->u.afb.speed_perc = 1.; do { /* parse the data */ xmlr_float(node,"rumble",temp->u.afb.rumble); if (xml_isNode(node,"sound")) temp->u.afb.sound = sound_get( xml_get(node) ); if (xml_isNode(node,"thrust_perc")) temp->u.afb.thrust_perc = 1. + xml_getFloat(node)/100.; xmlr_float(node,"thrust_abs",temp->u.afb.thrust_abs); if (xml_isNode(node,"speed_perc")) temp->u.afb.speed_perc = 1. + xml_getFloat(node)/100.; xmlr_float(node,"speed_abs",temp->u.afb.speed_abs); xmlr_float(node,"energy",temp->u.afb.energy); } while (xml_nextNode(node)); }
/** * @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 the player's active missions from a save. * * @param parent Node containing the player's active missions. * @return 0 on success. */ int missions_loadActive( xmlNodePtr parent ) { xmlNodePtr node; /* cleanup old missions */ missions_cleanup(); node = parent->xmlChildrenNode; do { if (xml_isNode(node,"missions")) if (missions_parseActive( node ) < 0) return -1; } while (xml_nextNode(node)); return 0; }
/** * @brief Loads the player's active events from a save. * * @param parent Node containing the player's active events. * @return 0 on success. */ int events_loadActive( xmlNodePtr parent ) { xmlNodePtr node; /* cleanup old events */ events_cleanup(); node = parent->xmlChildrenNode; do { if (xml_isNode(node,"events")) if (events_parseActive( node ) < 0) return -1; } while (xml_nextNode(node)); return 0; }
/** * @brief Loads all the fleets. * * @return 0 on success. */ static int fleet_loadFleets (void) { int mem; uint32_t bufsize; char *buf; xmlNodePtr node; xmlDocPtr doc; /* Load the data. */ buf = ndata_read( FLEET_DATA, &bufsize); doc = xmlParseMemory( buf, bufsize ); node = doc->xmlChildrenNode; /* fleets node */ if (strcmp((char*)node->name,"Fleets")) { ERR("Malformed "FLEET_DATA" file: missing root element 'Fleets'."); return -1; } node = node->xmlChildrenNode; /* first fleet node */ if (node == NULL) { ERR("Malformed "FLEET_DATA" file: does not contain elements."); return -1; } mem = 0; do { if (xml_isNode(node,"fleet")) { /* See if memory must grow. */ nfleets++; if (nfleets > mem) { mem += CHUNK_SIZE; fleet_stack = realloc(fleet_stack, sizeof(Fleet) * mem); } /* Load the fleet. */ fleet_parse( &fleet_stack[nfleets-1], node ); } } while (xml_nextNode(node)); /* Shrink to minimum. */ fleet_stack = realloc(fleet_stack, sizeof(Fleet) * nfleets); xmlFreeDoc(doc); free(buf); return 0; }
/** * @brief Patches a asset. * * @param diff Diff that is doing the patching. * @param node Node containing the asset. * @return 0 on success. */ static int diff_patchAsset( UniDiff_t *diff, xmlNodePtr node ) { UniHunk_t base, hunk; xmlNodePtr cur; /* Set the target. */ memset(&base, 0, sizeof(UniHunk_t)); base.target.type = HUNK_TARGET_ASSET; xmlr_attr(node,"name",base.target.u.name); if (base.target.u.name==NULL) { WARN(_("Unidiff '%s' has an target node without a 'name' tag"), diff->name); return -1; } /* Now parse the possible changes. */ cur = node->xmlChildrenNode; do { xml_onlyNodes(cur); if (xml_isNode(cur,"faction")) { hunk.target.type = base.target.type; hunk.target.u.name = strdup(base.target.u.name); /* Outfit type is constant. */ hunk.type = HUNK_TYPE_ASSET_FACTION; /* Get the data. */ hunk.u.name = xml_getStrd(cur); /* Apply diff. */ if (diff_patchHunk( &hunk ) < 0) diff_hunkFailed( diff, &hunk ); else diff_hunkSuccess( diff, &hunk ); continue; } WARN(_("Unidiff '%s' has unknown node '%s'."), diff->name, node->name); } while (xml_nextNode(cur)); /* Clean up some stuff. */ free(base.target.u.name); base.target.u.name = NULL; return 0; }
/** * @brief Loads the state of the universe into an xml file (Used in load.c) * * @param rootNode pointer to the root node of the game save file we are loading off of * @return 0 on success */ int unistate_load(xmlNodePtr rootNode) { if(!rootNode) return -1; assetStatePtr cur = NULL; xmlNodePtr elementNode = NULL; Planet *p; int f_id; elementNode = rootNode->children; do { if(xml_isNode(elementNode, "uni_state")) { //populate list if(!(unistateList = unistate_populateList(elementNode))) return -1; cur = unistateList; while(cur != NULL) { //Get planet struct and faction ID. If either return errors, bail. if((p = planet_get(cur->name)) == NULL) { WARN("Invalid planet or faction passed"); cur = cur->next; continue; } //Change the faction of the planet if(cur->faction != NULL && (f_id = faction_get(cur->faction)) != -1) planet_setFaction(p, f_id); //Change presence of planet if(cur->presence != -1) p->presenceAmount = (double)cur->presence; //Change range of presence if(cur->range != -1) p->presenceRange = (double)cur->range; //update the universe space_reconstructPresences(); //move along cur = cur->next; } return 0; } } while(xml_nextNode(elementNode)); //if it fell through to here then it didn't find what we were looking for return -2; }
/** * @brief Parses a damage node. * * Example damage node would be: * @code * <damage type="kinetic">10</damage> * @endcode * * @param[out] dtype Stores the damage type here. * @param[out] dmg Storse the damage here. * @param[in] node Node to parse damage from. * @return 0 on success. */ static int outfit_parseDamage( DamageType *dtype, double *dmg, xmlNodePtr node ) { char *buf; if (xml_isNode(node,"damage")) { /* Get type */ xmlr_attr(node,"type",buf); (*dtype) = outfit_strToDamageType(buf); if (buf) free(buf); /* Get damage */ (*dmg) = xml_getFloat(node); return 0; } /* Unknown type */ (*dtype) = DAMAGE_TYPE_NULL; (*dmg) = 0; WARN("Trying to parse non-damage node as damage node!"); return 1; }
/** * @brief Parses an XML tech node. */ static int tech_parseNodeData( tech_group_t *tech, xmlNodePtr parent ) { xmlNodePtr node; char *buf, *name; int ret; /* Parse the data. */ node = parent->xmlChildrenNode; do { xml_onlyNodes(node); if (xml_isNode(node,"item")) { /* Must have name. */ name = xml_get( node ); if (name == NULL) { WARN("Tech group '%s' has an item without a value.", tech->name); continue; } /* Try to find hardcoded type. */ buf = xml_nodeProp( node, "type" ); if (buf == NULL) { ret = 1; if (ret) ret = tech_addItemGroup( tech, name ); if (ret) ret = tech_addItemOutfit( tech, name ); if (ret) ret = tech_addItemShip( tech, name ); if (ret) ret = tech_addItemCommodity( tech, name ); if (ret) { WARN("Generic item '%s' not found in tech group '%s'", name, tech->name ); continue; } } else if (strcmp(buf,"group")==0) { if (!tech_addItemGroup( tech, name )) { WARN("Group item '%s' not found in tech group '%s'.", name, tech->name ); continue; } } else if (strcmp(buf,"outfit")==0) { if (!tech_addItemGroup( tech, name )) { WARN("Outfit item '%s' not found in tech group '%s'.", name, tech->name ); continue; } } else if (strcmp(buf,"ship")==0) { if (!tech_addItemGroup( tech, name )) { WARN("Ship item '%s' not found in tech group '%s'.", name, tech->name ); continue; } } else if (strcmp(buf,"commodity")==0) { if (!tech_addItemGroup( tech, name )) { WARN("Commodity item '%s' not found in tech group '%s'.", name, tech->name ); continue; } } continue; } WARN("Tech group '%s' has unknown node '%s'.", tech->name, node->name); } while (xml_nextNode( node )); return 0; }
/** * @brief Loads all the events. * * @return 0 on success. */ int events_load (void) { int m; uint32_t bufsize; char *buf; xmlNodePtr node; xmlDocPtr doc; /* Load the data. */ buf = ndata_read( EVENT_DATA, &bufsize ); if (buf == NULL) { WARN("Unable to read data from '%s'", EVENT_DATA); return -1; } /* Load the document. */ doc = xmlParseMemory( buf, bufsize ); if (doc == NULL) { WARN("Unable to parse document '%s'", EVENT_DATA); return -1; } /* Get the root node. */ node = doc->xmlChildrenNode; if (!xml_isNode(node,XML_EVENT_ID)) { WARN("Malformed '"EVENT_DATA"' file: missing root element '"XML_EVENT_ID"'"); return -1; } /* Get the first node. */ node = node->xmlChildrenNode; /* first mission node */ if (node == NULL) { WARN("Malformed '"EVENT_DATA"' file: does not contain elements"); return -1; } m = 0; do { if (xml_isNode(node,XML_EVENT_TAG)) { /* See if must grow. */ event_ndata++; if (event_ndata > m) { m += EVENT_CHUNK; event_data = realloc(event_data, sizeof(EventData_t)*m); } /* Load it. */ event_parse( &event_data[event_ndata-1], node ); } } while (xml_nextNode(node)); /* Shrink to minimum. */ event_data = realloc(event_data, sizeof(EventData_t)*event_ndata); /* Clean up. */ xmlFreeDoc(doc); free(buf); DEBUG("Loaded %d Event%s", event_ndata, (event_ndata==1) ? "" : "s" ); return 0; }
/** * @brief Loads up an event from an XML node. * * @param temp Event to load up. * @param parent Event parent node. * @return 0 on success. */ static int event_parse( EventData_t *temp, const xmlNodePtr parent ) { xmlNodePtr node, cur; char str[PATH_MAX] = "\0"; char *buf; #ifdef DEBUGGING /* To check if mission is valid. */ lua_State *L; int ret; uint32_t len; #endif /* DEBUGGING */ memset( temp, 0, sizeof(EventData_t) ); /* get the name */ temp->name = xml_nodeProp(parent,"name"); if (temp->name == NULL) WARN("Event in "EVENT_DATA" has invalid or no name"); node = parent->xmlChildrenNode; do { /* load all the data */ /* Only check nodes. */ xml_onlyNodes(node); if (xml_isNode(node,"lua")) { snprintf( str, PATH_MAX, EVENT_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("Event Lua '%s' of mission '%s' syntax error: %s", temp->name, temp->lua, lua_tostring(L,-1) ); } free(buf); lua_close(L); #endif /* DEBUGGING */ continue; } /* Trigger. */ else if (xml_isNode(node,"trigger")) { buf = xml_get(node); if (buf == NULL) WARN("Event '%s': Null trigger type.", temp->name); else if (strcmp(buf,"enter")==0) temp->trigger = EVENT_TRIGGER_ENTER; else if (strcmp(buf,"land")==0) temp->trigger = EVENT_TRIGGER_LAND; else WARN("Event '%s' has invalid 'trigger' parameter: %s", temp->name, buf); continue; } /* Flags. */ else if (xml_isNode(node,"flags")) { /* set the various flags */ cur = node->children; do { if (xml_isNode(cur,"unique")) temp->flags |= EVENT_FLAG_UNIQUE; } while (xml_nextNode(cur)); continue; } /* Condition. */ xmlr_strd(node,"cond",temp->cond); /* Get chance. */ xmlr_float(node,"chance",temp->chance); DEBUG("Unknown node '%s' in event '%s'", node->name, temp->name); } while (xml_nextNode(node)); /* Process. */ temp->chance /= 100.; #define MELEMENT(o,s) \ if (o) WARN("Mission '%s' missing/invalid '"s"' element", temp->name) MELEMENT(temp->lua==NULL,"lua"); MELEMENT(temp->chance==0.,"chance"); MELEMENT(temp->trigger==EVENT_TRIGGER_NULL,"trigger"); #undef MELEMENT return 0; }
/** * @brief Loads the tech information. */ int tech_load (void) { int i, ret, s; uint32_t bufsize; char *buf, *data; xmlNodePtr node, parent; xmlDocPtr doc; tech_group_t *tech; /* Load the data. */ data = ndata_read( TECH_DATA, &bufsize ); if (data == NULL) return -1; /* Load the document. */ doc = xmlParseMemory( data, bufsize ); if (doc == NULL) { WARN("'%s' is not a valid XML file.", TECH_DATA); return -1; } /* Load root element. */ parent = doc->xmlChildrenNode; if (!xml_isNode(parent,XML_TECH_ID)) { WARN("Malformed "TECH_DATA" file: missing root element '"XML_TECH_ID"'"); return -1; } /* Get first node. */ node = parent->xmlChildrenNode; if (node == NULL) { WARN("Malformed "TECH_DATA" file: does not contain elements"); return -1; } /* Create the array. */ tech_groups = array_create( tech_group_t ); /* First pass create the groups - needed to reference them later. */ ret = 0; tech = NULL; do { xml_onlyNodes(node); /* Must match tag. */ if (!xml_isNode(node, XML_TECH_TAG)) { WARN("'"XML_TECH_ID"' has unknown node '%s'.", node->name); continue; } if (ret==0) /* Write over failures. */ tech = &array_grow( &tech_groups ); ret = tech_parseNode( tech, node ); } while (xml_nextNode(node)); array_shrink( &tech_groups ); /* Now we load the data. */ node = parent->xmlChildrenNode; s = array_size( tech_groups ); do { /* Must match tag. */ if (!xml_isNode(node, XML_TECH_TAG)) continue; /* Must avoid warning by checking explicit NULL. */ xmlr_attr( node, "name", buf ); if (buf == NULL) continue; /* Load next tech. */ for (i=0; i<s; i++) { tech = &tech_groups[i]; if (strcmp(tech->name, buf)==0) tech_parseNodeData( tech, node ); } /* Free memory. */ free(buf); } while (xml_nextNode(node)); /* Info. */ DEBUG("Loaded %d tech group%s", s, (s == 1) ? "" : "s" ); /* Free memory. */ free(data); xmlFreeDoc(doc); return 0; }
/** * @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 Loads up all the factions from the data file. * * @return 0 on success. */ int factions_load (void) { int mem; uint32_t bufsize; char *buf = ndata_read( FACTION_DATA_PATH, &bufsize); xmlNodePtr factions, node; xmlDocPtr doc = xmlParseMemory( buf, bufsize ); node = doc->xmlChildrenNode; /* Factions node */ if (!xml_isNode(node,XML_FACTION_ID)) { ERR("Malformed "FACTION_DATA_PATH" file: missing root element '"XML_FACTION_ID"'"); return -1; } factions = node->xmlChildrenNode; /* first faction node */ if (factions == NULL) { ERR("Malformed "FACTION_DATA_PATH" file: does not contain elements"); return -1; } /* player faction is hard-coded */ faction_stack = calloc( 1, sizeof(Faction) ); faction_stack[0].name = strdup("Player"); faction_stack[0].flags = FACTION_STATIC | FACTION_INVISIBLE; faction_nstack++; /* First pass - gets factions */ node = factions; mem = 0; do { if (xml_isNode(node,XML_FACTION_TAG)) { /* See if must grow memory. */ faction_nstack++; if (faction_nstack > mem) { mem += CHUNK_SIZE; faction_stack = realloc(faction_stack, sizeof(Faction)*mem); } /* Load faction. */ faction_parse(&faction_stack[faction_nstack-1], node); } } while (xml_nextNode(node)); /* Shrink to minimum size. */ faction_stack = realloc(faction_stack, sizeof(Faction)*faction_nstack); /* Second pass - sets allies and enemies */ node = factions; do { if (xml_isNode(node,XML_FACTION_TAG)) faction_parseSocial(node); } while (xml_nextNode(node)); #ifdef DEBUGGING int i, j, k, r; Faction *f, *sf; /* Third pass, makes sure allies/enemies are sane. */ for (i=0; i<faction_nstack; i++) { f = &faction_stack[i]; /* First run over allies and make sure it's mutual. */ for (j=0; j < f->nallies; j++) { sf = &faction_stack[ f->allies[j] ]; r = 0; for (k=0; k < sf->nallies; k++) if (sf->allies[k] == i) r = 1; if (r == 0) WARN("Faction: %s and %s aren't completely mutual allies!", f->name, sf->name ); } /* Now run over enemies. */ for (j=0; j < f->nenemies; j++) { sf = &faction_stack[ f->enemies[j] ]; r = 0; for (k=0; k < sf->nenemies; k++) if (sf->enemies[k] == i) r = 1; if (r == 0) WARN("Faction: %s and %s aren't completely mutual enemies!", f->name, sf->name ); } } #endif /* DEBUGGING */ xmlFreeDoc(doc); free(buf); DEBUG("Loaded %d Faction%s", faction_nstack, (faction_nstack==1) ? "" : "s" ); return 0; }
/** * @brief Parses a single faction, but doesn't set the allies/enemies bit. * * @param temp Faction to load data into. * @param parent Parent node to extract faction from. * @return Faction created from parent node. */ static int faction_parse( Faction* temp, xmlNodePtr parent ) { xmlNodePtr node; int player; char buf[PATH_MAX], *dat; uint32_t ndat; /* Clear memory. */ memset( temp, 0, sizeof(Faction) ); temp->name = xml_nodeProp(parent,"name"); if (temp->name == NULL) WARN("Faction from "FACTION_DATA_PATH" has invalid or no name"); player = 0; node = parent->xmlChildrenNode; do { /* Only care about nodes. */ xml_onlyNodes(node); /* Can be 0 or negative, so we have to take that into account. */ if (xml_isNode(node,"player")) { temp->player_def = xml_getFloat(node); player = 1; continue; } xmlr_strd(node,"longname",temp->longname); xmlr_strd(node,"display",temp->displayname); if (xml_isNode(node, "colour")) { temp->colour = col_fromName(xml_raw(node)); continue; } if (xml_isNode(node, "spawn")) { if (temp->sched_state != NULL) WARN("Faction '%s' has duplicate 'spawn' tag.", temp->name); nsnprintf( buf, sizeof(buf), "dat/factions/spawn/%s.lua", xml_raw(node) ); temp->sched_state = nlua_newState(); nlua_loadStandard( temp->sched_state, 0 ); dat = ndata_read( buf, &ndat ); if (luaL_dobuffer(temp->sched_state, dat, ndat, buf) != 0) { WARN("Failed to run spawn script: %s\n" "%s\n" "Most likely Lua file has improper syntax, please check", buf, lua_tostring(temp->sched_state,-1)); lua_close( temp->sched_state ); temp->sched_state = NULL; } free(dat); continue; } if (xml_isNode(node, "standing")) { if (temp->state != NULL) WARN("Faction '%s' has duplicate 'standing' tag.", temp->name); nsnprintf( buf, sizeof(buf), "dat/factions/standing/%s.lua", xml_raw(node) ); temp->state = nlua_newState(); nlua_loadStandard( temp->state, 0 ); dat = ndata_read( buf, &ndat ); if (luaL_dobuffer(temp->state, dat, ndat, buf) != 0) { WARN("Failed to run standing script: %s\n" "%s\n" "Most likely Lua file has improper syntax, please check", buf, lua_tostring(temp->state,-1)); lua_close( temp->state ); temp->state = NULL; } free(dat); continue; } if (xml_isNode(node, "known")) { faction_setFlag(temp, FACTION_KNOWN); continue; } if (xml_isNode(node, "equip")) { if (temp->equip_state != NULL) WARN("Faction '%s' has duplicate 'equip' tag.", temp->name); nsnprintf( buf, sizeof(buf), "dat/factions/equip/%s.lua", xml_raw(node) ); temp->equip_state = nlua_newState(); nlua_loadStandard( temp->equip_state, 0 ); dat = ndata_read( buf, &ndat ); if (luaL_dobuffer(temp->equip_state, dat, ndat, buf) != 0) { WARN("Failed to run equip script: %s\n" "%s\n" "Most likely Lua file has improper syntax, please check", buf, lua_tostring(temp->equip_state,-1)); lua_close( temp->equip_state ); temp->equip_state = NULL; } free(dat); continue; } if (xml_isNode(node,"logo")) { if (temp->logo_small != NULL) WARN("Faction '%s' has duplicate 'logo' tag.", temp->name); nsnprintf( buf, PATH_MAX, FACTION_LOGO_PATH"%s_small.png", xml_get(node)); temp->logo_small = gl_newImage(buf, 0); nsnprintf( buf, PATH_MAX, FACTION_LOGO_PATH"%s_tiny.png", xml_get(node)); temp->logo_tiny = gl_newImage(buf, 0); continue; } if (xml_isNode(node,"static")) { faction_setFlag(temp, FACTION_STATIC); continue; } if (xml_isNode(node,"invisible")) { faction_setFlag(temp, FACTION_INVISIBLE); continue; } /* Avoid warnings. */ if (xml_isNode(node,"allies") || xml_isNode(node,"enemies")) continue; DEBUG("Unknown node '%s' in faction '%s'",node->name,temp->name); } while (xml_nextNode(node)); if (player==0) DEBUG("Faction '%s' missing player tag.", temp->name); if ((temp->state!=NULL) && faction_isFlag( temp, FACTION_STATIC )) WARN("Faction '%s' has Lua and is static!", temp->name); if ((temp->state==NULL) && !faction_isFlag( temp, FACTION_STATIC )) WARN("Faction '%s' has no Lua and isn't static!", temp->name); return 0; }