package zmaster587.advancedRocketry.util; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import zmaster587.advancedRocketry.AdvancedRocketry; import zmaster587.advancedRocketry.api.dimension.solar.StellarBody; import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.dimension.DimensionProperties; public class XMLPlanetLoader { Document doc; NodeList currentList; int currentNodeIndex; int starId; int offset; HashMap<StellarBody, Integer> maxPlanetNumber = new HashMap<StellarBody, Integer>(); HashMap<StellarBody, Integer> maxGasPlanetNumber = new HashMap<StellarBody, Integer>(); public boolean loadFile(File xmlFile) throws IOException { DocumentBuilder docBuilder; doc = null; try { docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); } catch (ParserConfigurationException e) { return false; } try { doc = docBuilder.parse(xmlFile); } catch (SAXException e) { e.printStackTrace(); return false; } return true; } public XMLPlanetLoader() { doc = null; currentNodeIndex = -1; starId=0; } public boolean isValid() { return doc != null; } public int getMaxNumPlanets(StellarBody body) { return maxPlanetNumber.get(body); } public int getMaxNumGasGiants(StellarBody body) { return maxGasPlanetNumber.get(body); } private List<DimensionProperties> readPlanetFromNode(Node planetNode, StellarBody star) { List<DimensionProperties> list = new ArrayList<DimensionProperties>(); Node planetPropertyNode = planetNode.getFirstChild(); DimensionProperties properties = new DimensionProperties(DimensionManager.getInstance().getNextFreeDim(offset)); if(properties == null) return list; list.add(properties); offset++;//Increment for dealing with child planets //Set name for dimension if exists if(planetNode.hasAttributes()) { Node nameNode = planetNode.getAttributes().getNamedItem("name"); if(nameNode != null && !nameNode.getNodeValue().isEmpty()) { properties.setName(nameNode.getNodeValue()); } nameNode = planetNode.getAttributes().getNamedItem("DIMID"); if(nameNode != null && !nameNode.getNodeValue().isEmpty()) { try { if(nameNode.getTextContent().isEmpty()) throw new NumberFormatException(); properties.setId(Integer.parseInt(nameNode.getTextContent())); //We're not using the offset so decrement to prepare for next planet offset--; } catch (NumberFormatException e) { AdvancedRocketry.logger.warn("Invalid DIMID specified for planet " + properties.getName()); //TODO: more detailed error msg list.remove(properties); offset--; return list; } } nameNode = planetNode.getAttributes().getNamedItem("dimMapping"); if(nameNode != null) { properties.isNativeDimension = false; } nameNode = planetNode.getAttributes().getNamedItem("customIcon"); if(nameNode != null) { properties.customIcon = nameNode.getTextContent(); } } while(planetPropertyNode != null) { if(planetPropertyNode.getNodeName().equalsIgnoreCase("fogcolor")) { String[] colors = planetPropertyNode.getTextContent().split(","); try { if(colors.length >= 3) { float rgb[] = new float[3]; for(int j = 0; j < 3; j++) rgb[j] = Float.parseFloat(colors[j]); properties.fogColor = rgb; } else if(colors.length == 1) { int cols = Integer.parseUnsignedInt(colors[0].substring(2), 16); float rgb[] = new float[3]; rgb[0] = ((cols >>> 16) & 0xff) / 255f; rgb[1] = ((cols >>> 8) & 0xff) / 255f; rgb[2] = (cols & 0xff) / 255f; properties.fogColor = rgb; } else AdvancedRocketry.logger.warn("Invalid number of floats specified for fog color (Required 3, comma sperated)"); //TODO: more detailed error msg } catch (NumberFormatException e) { AdvancedRocketry.logger.warn("Invalid fog color specified"); //TODO: more detailed error msg } } else if(planetPropertyNode.getNodeName().equalsIgnoreCase("skycolor")) { String[] colors = planetPropertyNode.getTextContent().split(","); try { if(colors.length >= 3) { float rgb[] = new float[3]; for(int j = 0; j < 3; j++) rgb[j] = Float.parseFloat(colors[j]); properties.skyColor = rgb; } else if(colors.length == 1) { int cols = Integer.parseUnsignedInt(colors[0].substring(2), 16); float rgb[] = new float[3]; rgb[0] = ((cols >>> 16) & 0xff) / 255f; rgb[1] = ((cols >>> 8) & 0xff) / 255f; rgb[2] = (cols & 0xff) / 255f; properties.skyColor = rgb; } else AdvancedRocketry.logger.warn("Invalid number of floats specified for sky color (Required 3, comma sperated)"); //TODO: more detailed error msg } catch (NumberFormatException e) { AdvancedRocketry.logger.warn("Invalid sky color specified"); //TODO: more detailed error msg } } else if(planetPropertyNode.getNodeName().equalsIgnoreCase("atmosphereDensity")) { try { properties.setAtmosphereDensityDirect(Math.min(Math.max(Integer.parseInt(planetPropertyNode.getTextContent()), DimensionProperties.MIN_ATM_PRESSURE), DimensionProperties.MAX_ATM_PRESSURE)); } catch (NumberFormatException e) { AdvancedRocketry.logger.warn("Invalid atmosphereDensity specified"); //TODO: more detailed error msg } } else if(planetPropertyNode.getNodeName().equalsIgnoreCase("gravitationalmultiplier")) { try { properties.gravitationalMultiplier = Math.min(Math.max(Integer.parseInt(planetPropertyNode.getTextContent()), DimensionProperties.MIN_GRAVITY), DimensionProperties.MAX_GRAVITY)/100f; } catch (NumberFormatException e) { AdvancedRocketry.logger.warn("Invalid gravitationalMultiplier specified"); //TODO: more detailed error msg } } else if(planetPropertyNode.getNodeName().equalsIgnoreCase("orbitaldistance")) { try { properties.orbitalDist = Math.min(Math.max(Integer.parseInt(planetPropertyNode.getTextContent()), DimensionProperties.MIN_DISTANCE), DimensionProperties.MAX_DISTANCE); } catch (NumberFormatException e) { AdvancedRocketry.logger.warn("Invalid orbitalDist specified"); //TODO: more detailed error msg } } else if(planetPropertyNode.getNodeName().equalsIgnoreCase("orbitaltheta")) { try { properties.orbitTheta = (Integer.parseInt(planetPropertyNode.getTextContent()) % 360) * 2/Math.PI; } catch (NumberFormatException e) { AdvancedRocketry.logger.warn("Invalid orbitalTheta specified"); //TODO: more detailed error msg } } else if(planetPropertyNode.getNodeName().equalsIgnoreCase("rotationalperiod")) { try { int rotationalPeriod = Integer.parseInt(planetPropertyNode.getTextContent()); if(properties.rotationalPeriod > 0) properties.rotationalPeriod = rotationalPeriod; else AdvancedRocketry.logger.warn("rotational Period must be greater than 0"); //TODO: more detailed error msg } catch (NumberFormatException e) { AdvancedRocketry.logger.warn("Invalid rotational period specified"); //TODO: more detailed error msg } } else if(planetPropertyNode.getNodeName().equalsIgnoreCase("biomeids")) { String biomeList[] = planetPropertyNode.getTextContent().split(","); for(int j = 0; j < biomeList.length; j++) { try { int biome = Integer.parseInt(biomeList[j]); if(!properties.addBiome(biome)) AdvancedRocketry.logger.warn(biomeList[j] + " is not a valid biome id"); //TODO: more detailed error msg } catch (NumberFormatException e) { AdvancedRocketry.logger.warn(biomeList[j] + " is not a valid biome id"); //TODO: more detailed error msg } } } else if(planetPropertyNode.getNodeName().equalsIgnoreCase("planet")) { List<DimensionProperties> childList = readPlanetFromNode(planetPropertyNode, star); if(childList.size() > 0) { DimensionProperties child = childList.get(childList.size()-1); // Last entry in the list is the child planet properties.addChildPlanet(child); list.addAll(childList); } } else if(planetPropertyNode.getNodeName().equalsIgnoreCase("orbitalPhi")) { try { properties.orbitalPhi = (Integer.parseInt(planetPropertyNode.getTextContent()) % 360) * 2/Math.PI; } catch (NumberFormatException e) { AdvancedRocketry.logger.warn("Invalid orbitalTheta specified"); //TODO: more detailed error msg } } else if(planetPropertyNode.getNodeName().equalsIgnoreCase("oreGen")) { properties.oreProperties = XMLOreLoader.loadOre(planetPropertyNode); } else if(planetPropertyNode.getNodeName().equalsIgnoreCase("GasGiant")) { String text = planetPropertyNode.getTextContent(); if(text != null && !text.isEmpty() && text.equalsIgnoreCase("true")) properties.setGasGiant(); } planetPropertyNode = planetPropertyNode.getNextSibling(); } //Star may not be registered at this time, use ID version instead properties.setStar(star.getId()); //Set temperature properties.averageTemperature = DimensionManager.getInstance().getTemperature(star, properties.getOrbitalDist(), properties.getAtmosphereDensity()); //If no biomes are specified add some! if(properties.getBiomes().isEmpty()) properties.addBiomes(properties.getViableBiomes()); return list; } public StellarBody readStar(Node planetNode) { StellarBody star = new StellarBody(); if(planetNode.hasAttributes()) { Node nameNode = planetNode.getAttributes().getNamedItem("name"); if(nameNode != null && !nameNode.getNodeValue().isEmpty()) { star.setName(nameNode.getNodeValue()); } nameNode = planetNode.getAttributes().getNamedItem("temp"); if(nameNode != null && !nameNode.getNodeValue().isEmpty()) { try { star.setTemperature(Integer.parseInt(nameNode.getNodeValue())); } catch (NumberFormatException e) { AdvancedRocketry.logger.warn("Error Reading star " + star.getName()); } } nameNode = planetNode.getAttributes().getNamedItem("x"); if(nameNode != null && !nameNode.getNodeValue().isEmpty()) { try { star.setPosX(Integer.parseInt(nameNode.getNodeValue())); } catch (NumberFormatException e) { AdvancedRocketry.logger.warn("Error Reading star " + star.getName()); } } nameNode = planetNode.getAttributes().getNamedItem("y"); if(nameNode != null && !nameNode.getNodeValue().isEmpty()) { try { star.setPosZ(Integer.parseInt(nameNode.getNodeValue())); } catch (NumberFormatException e) { AdvancedRocketry.logger.warn("Error Reading star " + star.getName()); } } nameNode = planetNode.getAttributes().getNamedItem("numPlanets"); try { maxPlanetNumber.put(star ,Integer.parseInt(nameNode.getNodeValue())); } catch (Exception e) { AdvancedRocketry.logger.warn("Invalid number of planets specified in xml config!"); } nameNode = planetNode.getAttributes().getNamedItem("numGasGiants"); try { maxGasPlanetNumber.put(star ,Integer.parseInt(nameNode.getNodeValue())); } catch (Exception e) { AdvancedRocketry.logger.warn("Invalid number of planets specified in xml config!"); } } star.setId(starId++); return star; } public DimensionPropertyCoupling readAllPlanets() { DimensionPropertyCoupling coupling = new DimensionPropertyCoupling(); Node masterNode = doc.getElementsByTagName("galaxy").item(0).getFirstChild(); //readPlanetFromNode changes value //Yes it's hacky but that's another reason why it's private offset = DimensionManager.dimOffset; while(masterNode != null) { if(!masterNode.getNodeName().equals("star")) { masterNode = masterNode.getNextSibling(); continue; } StellarBody star = readStar(masterNode); coupling.stars.add(star); NodeList planetNodeList = masterNode.getChildNodes(); Node planetNode = planetNodeList.item(0); while(planetNode != null) { if(planetNode.getNodeName().equalsIgnoreCase("planet")) { coupling.dims.addAll(readPlanetFromNode(planetNode, star)); } planetNode = planetNode.getNextSibling(); } masterNode = masterNode.getNextSibling(); } return coupling; } public static class DimensionPropertyCoupling { public List<StellarBody> stars = new LinkedList<StellarBody>(); public List<DimensionProperties> dims = new LinkedList<DimensionProperties>(); } }