package com.bitwaffle.spaceguts.util.xml; import java.util.StringTokenizer; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.lwjgl.util.vector.Quaternion; import org.lwjgl.util.vector.Vector3f; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.bitwaffle.spaceguts.entities.Camera; import com.bitwaffle.spaceguts.entities.DynamicEntity; import com.bitwaffle.spaceguts.entities.Entities; import com.bitwaffle.spaceout.entities.dynamic.Planet; import com.bitwaffle.spaceout.entities.passive.AsteroidField; import com.bitwaffle.spaceout.entities.passive.Skybox; import com.bitwaffle.spaceout.entities.passive.Sun; import com.bitwaffle.spaceout.entities.passive.particles.Debris; import com.bitwaffle.spaceout.entities.player.Player; import com.bitwaffle.spaceout.resources.Models; import com.bitwaffle.spaceout.resources.Textures; import com.bitwaffle.spaceout.ship.Ship; /** * Loads entities from an XML file and puts them into the ArrayList * Entities.entities * * @author TranquilMarmot * @see Entities * */ public class EntitiesParser { /** * Loads entities from an XML file * * @param file * The file to load */ public static void loadEntitiesFromXmlFile(String file) { // list of all the nodes NodeList nodes = null; // create a new DocumentBuilderFactory to read the XML file DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); // The document builder DocumentBuilder db; // The actual document Document doc; try { // create a new document builder from the factory db = dbf.newDocumentBuilder(); // tell the document builder to parse the file doc = db.parse(file); // create an element from the document Element docEle = doc.getDocumentElement(); // grab all the other nodes nodes = docEle.getChildNodes(); } catch (Exception e) { e.printStackTrace(); } /* * Grab the rest of the entities in the file */ if (nodes != null && nodes.getLength() > 0) { Entities.camera = new Camera(); Entities.skybox = new Skybox(Entities.camera); // loop through all the nodes for (int i = 0; i < nodes.getLength(); i++) { /* * any node with the name #text is, well, text so we skip it we * also skip the player's node becayse we already grabbed it */ if (nodes.item(i).getNodeType() == Node.ELEMENT_NODE) { // grab the element Element ele = (Element) nodes.item(i); // get the entity makeEntity(ele); } } if (Entities.player != null) { Entities.camera.following = Entities.player; Entities.camera.freeMode = false; } } else { System.out.println("Error in XMLParser! Either there was nothing in the given file (" + file + ") or the parser simply just didn't want to work"); } } /** * Gets and entity from a given XML element * * @param ele * The element to create the entity from * @return An entity representing the element */ private static void makeEntity(Element ele) { String type = ele.getNodeName().toLowerCase(); if (type.equals("player")) { makePlayer(ele); } else if (type.equals("debris")) { makeDebris(ele); } else if (type.equals("sun")) { makeSun(ele); } else if (type.equals("planet")) { makePlanet(ele); } else if (type.equals("saucer")) { makeSaucer(ele); } else if (type.equals("asteroids")){ makeAsteroidField(ele); } } private static void makeAsteroidField(Element ele){ Vector3f location = getVector3f(ele, "location"); Vector3f range = getVector3f(ele, "range"); Vector3f asteroidSpeed = getVector3f(ele, "asteroidSpeed"); int numAsteroids = getInt(ele, "numAsteroids"); int initialAsteroids = getInt(ele, "initialAsteroids"); float releaseInterval = getFloat(ele, "releaseInterval"); int minSize = getInt(ele, "minSize"); int maxSize = getInt(ele, "maxSize"); AsteroidField field = new AsteroidField(location, range, asteroidSpeed, numAsteroids, initialAsteroids, releaseInterval, minSize, maxSize); Entities.addPassiveEntity(field); } private static void makeSaucer(Element ele) { Vector3f location = getVector3f(ele, "location"); Quaternion rotation = getRotation(ele); float mass = getFloat(ele, "mass"); float restitution = getFloat(ele, "restitution"); DynamicEntity saucer = new DynamicEntity(location, rotation, Models.SAUCER, mass, restitution); saucer.type = "Saucer"; Entities.addDynamicEntity(saucer); } private static void makePlayer(Element ele) { Vector3f location = getVector3f(ele, "location"); Quaternion rotation = getRotation(ele); float mass = getFloat(ele, "mass"); float restitution = getFloat(ele, "restitution"); Ship ship; NodeList nl = ele.getElementsByTagName("ship"); if(nl != null && nl.getLength() > 0){ if(nl.getLength() > 1){ System.out.println("Found more than one ship in player XML node! Using first result."); } Element el = (Element) nl.item(0); ship = makeShip(el); } else{ System.out.println("Couldn't find ship info in player XML node! Using default values."); // default ship values String shipName = "WingX"; Models shipModel = Models.SAUCER; int shipHealth = 100; float shipMass = 50.0f; float shipRestitution = 0.01f; Vector3f shipAcceleration = new Vector3f(5000.0f, 5000.0f, 5000.0f); Vector3f shipBoostSpeed = new Vector3f(100000.0f, 100000.0f, 100000.0f); float shipTopSpeed = 300.0f; float shipStopSpeed = 0.25f; float shipRollSpeed = 25.0f; float shipTurnSpeed = 50.0f; ship = new Ship(shipName, shipModel, shipHealth, shipMass, shipRestitution, shipAcceleration, shipBoostSpeed, shipTopSpeed, shipStopSpeed, shipRollSpeed, shipTurnSpeed); } Player player = new Player(location, rotation, ship, mass, restitution); player.type = "dynamicPlayer"; Entities.player = player; } private static Ship makeShip(Element ele){ String shipName = getString(ele, "name"); Models shipModel = Models.valueOf(getString(ele, "model")); int shipHealth = getInt(ele, "health"); float shipMass = getFloat(ele, "mass"); float shipRestitution = getFloat(ele, "restitution"); Vector3f shipAcceleration = getVector3f(ele, "acceleration"); Vector3f shipBoostSpeed = getVector3f(ele, "boostSpeed"); float shipTopSpeed = getFloat(ele, "topSpeed"); float shipStopSpeed = getFloat(ele, "stopSpeed"); float shipRollSpeed = getFloat(ele, "rollSpeed"); float shipTurnSpeed = getFloat(ele, "turnSpeed"); return new Ship(shipName, shipModel, shipHealth, shipMass, shipRestitution, shipAcceleration, shipBoostSpeed, shipTopSpeed, shipStopSpeed, shipRollSpeed, shipTurnSpeed); } private static void makeDebris(Element ele) { int numStars = getInt(ele, "numStars"); float range = getFloat(ele, "range"); long seed = 1337420L; Debris debris = new Debris(Entities.camera, numStars, range, seed); Entities.addPassiveEntity(debris); } private static void makeSun(Element ele) { Vector3f location = getVector3f(ele, "location"); float size = getFloat(ele, "size"); Vector3f intensity = getVector3f(ele, "intensity"); Sun sun = new Sun(location, size, intensity); Entities.addLight(sun); } private static void makePlanet(Element ele) { Textures texture = Textures.CHECKERS; String name = getString(ele, "name"); if (name.equals("Earth")) texture = Textures.EARTH; else if (name.equals("Mercury")) texture = Textures.MERCURY; else if (name.equals("Venus")) texture = Textures.VENUS; else if (name.equals("Mars")) texture = Textures.MARS; else System.out .println("Error! Didn't find texture while creating Planet " + name + " in XMLParser!"); Vector3f location = getVector3f(ele, "location"); Quaternion rotation = getRotation(ele); float mass = getFloat(ele, "mass"); float size = getFloat(ele, "size"); float restitution = getFloat(ele, "restitution"); Planet p = new Planet(location, rotation, size, mass, restitution, texture); p.type = name; Entities.addDynamicEntity(p); } /** * Gets a vector3f representing a location * * @param ele * The element to get the location from * @return A vector representing he location */ private static Vector3f getVector3f(Element ele, String tag) { String loc = getString(ele, tag); StringTokenizer toker = new StringTokenizer(loc, ","); float x = Float.parseFloat(toker.nextToken()); float y = Float.parseFloat(toker.nextToken()); float z = Float.parseFloat(toker.nextToken()); return new Vector3f(x, y, z); } /** * Gets a quaternion representing a rotation * * @param ele * The element to get the rotation from * @return A quaternion representing the rotation */ private static Quaternion getRotation(Element ele) { String rot = getString(ele, "rotation"); StringTokenizer toker = new StringTokenizer(rot, ","); float x = Float.parseFloat(toker.nextToken()); float y = Float.parseFloat(toker.nextToken()); float z = Float.parseFloat(toker.nextToken()); float w = Float.parseFloat(toker.nextToken()); return new Quaternion(x, y, z, w); } /** * Returns a float array of 3 values given a string formatted like * "1.0f,1.0f,1.0f" or similar three numbers * * @param ele * The element to get the color array from * @param tag * The tag to get the color from * @return A float array containing the color */ /* private static Vector3f getColor(Element ele, String tag) { String text = getString(ele, tag); StringTokenizer toker = new StringTokenizer(text, ","); float r = Float.parseFloat(toker.nextToken()); float g = Float.parseFloat(toker.nextToken()); float b = Float.parseFloat(toker.nextToken()); return new Vector3f(r, g, b); } */ /** * Gets a string from an element * * @param ele * The element to get the string from * @param tagName * The tag to get the string from * @return The string from the element */ private static String getString(Element ele, String tagName) { String textVal = null; NodeList nl = ele.getElementsByTagName(tagName); if (nl != null && nl.getLength() > 0) { Element el = (Element) nl.item(0); textVal = el.getFirstChild().getNodeValue(); } return textVal; } /** * Gets a boolean from an element * * @param ele * The element to get the boolean from * @param tagName * The tag to get the boolean from * @return The boolean from the element */ @SuppressWarnings("unused") private static boolean getBoolean(Element ele, String tagName) { return Boolean.parseBoolean(getString(ele, tagName)); } /** * Gets an int from an element * * @param ele * The element to get the int from * @param tagName * The tag to get the int from * @return The int from the element */ private static int getInt(Element ele, String tagName) { return Integer.parseInt(getString(ele, tagName)); } private static float getFloat(Element ele, String tagName) { return Float.parseFloat(getString(ele, tagName)); } }