/*******************************************************************************
* Copyright (c) 2013 Philip Collin.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* Philip Collin - initial API and implementation
******************************************************************************/
package com.lyeeedar.Roguelike3D.Game.Level.XML;
import java.util.ArrayList;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;
import org.w3c.dom.Node;
import com.badlogic.gdx.graphics.Color;
import com.lyeeedar.Roguelike3D.Game.Level.AbstractObject;
import com.lyeeedar.Roguelike3D.Game.Level.AbstractRoom;
import com.lyeeedar.Roguelike3D.Game.Level.DungeonRoom.RoomType;
public class RoomReader extends XMLReader {
public static final String ROOM_DEFINITIONS = "room_definitions";
public static final String GLOBAL = "GLOBAL";
public static final String WIDTH = "width";
public static final String HEIGHT = "height";
public static final String DEPTH_MIN = "depth_min";
public static final String DEPTH_MAX = "depth_max";
public static final String START = "START";
public static final String END = "END";
public static final String MAIN = "MAIN";
public static final String SPECIAL = "SPECIAL";
public static final String OTHER = "OTHER";
public static final String DEFINITIONS = "definitions";
public static final String SYMBOL = "symbol";
public static final String CHAR = "char";
public static final String TYPE = "type";
public static final String VISIBLE = "visible";
public static final String SHORT_DESCRIPTION = "short_description";
public static final String LONG_DESCRIPTION = "long_description";
public static final String MODEL = "model";
public static final String MODEL_TYPE = "type";
public static final String MODEL_NAME = "name";
public static final String MODEL_SCALE = "scale";
public static final String DIMENSIONS = "dimensions";
public static final String DIMENSIONS_NUMBER = "number";
public static final String DIMENSIONS_D = "d";
public static final String TEXTURE = "texture";
public static final String COLOUR = "colour";
public static final String RED = "red";
public static final String GREEN = "green";
public static final String BLUE = "blue";
public static final String ROOM = "room";
public static final String ROW = "row";
public static final String META = "meta";
public static final String DATA = "data";
public static final String NAME = "name";
public static final String CONTENTS = "contents";
Node biome;
int depth;
public RoomReader(String biome, int depth)
{
super("data/xml/"+biome+".data");
this.depth = depth;
this.biome = getNode(ROOM_DEFINITIONS, root_node.getChildNodes());
}
public AbstractRoom getRoom(RoomType rtype, int width, int height, boolean flippable)
{
Node roomType = getRoomNode(rtype);
SortedMap<Integer, ArrayList<Node>> valid = new TreeMap<Integer, ArrayList<Node>>();
for (int i = 0; i < roomType.getChildNodes().getLength(); i++)
{
Node n = roomType.getChildNodes().item(i);
if (n.getNodeType() == Node.TEXT_NODE) continue;
int w = Integer.parseInt(getNodeValue(WIDTH, n.getChildNodes()));
int h = Integer.parseInt(getNodeValue(HEIGHT, n.getChildNodes()));
if (w <= width)
{
if (h <= height)
{
int priority = (width-w)+(height-h);
if (valid.containsKey(priority))
{
valid.get(priority).add(n);
}
else
{
ArrayList<Node> ns = new ArrayList<Node>();
ns.add(n);
valid.put(priority, ns);
}
}
}
else if (h <= width)
{
if (w <= height)
{
int depth_offset = 0;
int room_depth_min = Integer.parseInt(getNodeValue(DEPTH_MIN, n.getChildNodes()));
int room_depth_max = Integer.parseInt(getNodeValue(DEPTH_MAX, n.getChildNodes()));
if (room_depth_max < depth) depth_offset = depth-room_depth_max;
else if (room_depth_min > depth) depth_offset = room_depth_min-depth;
int priority = (width-h)+(height-w)+(depth_offset*2);
if (valid.containsKey(priority))
{
valid.get(priority).add(n);
}
else
{
ArrayList<Node> ns = new ArrayList<Node>();
ns.add(n);
valid.put(priority, ns);
}
}
}
}
if (valid.size() == 0)
{
return null;
}
int pos = 0;
Random ran = new Random();
while (true)
{
if (pos == valid.size())
{
pos--;
break;
}
if (ran.nextInt(100) < 50)
{
pos++;
}
else
{
break;
}
}
ArrayList<Node> ns = valid.get(valid.keySet().toArray()[pos]);
Node chosen = ns.get(ran.nextInt(ns.size()));
int rheight = Integer.parseInt(getNodeValue(WIDTH, chosen.getChildNodes()));
int rwidth = Integer.parseInt(getNodeValue(HEIGHT, chosen.getChildNodes()));
AbstractRoom room = null;
if (rwidth <= width && rheight <= height) room = new AbstractRoom(rwidth, rheight, false, flippable);
else room = new AbstractRoom(rwidth, rheight, true, flippable);
Node roomGraphics = getNode(ROOM, chosen.getChildNodes());
int roomIndex = 0;
for (int i = 0; i < roomGraphics.getChildNodes().getLength(); i++)
{
Node n = roomGraphics.getChildNodes().item(i);
if (!n.getNodeName().equalsIgnoreCase(ROW)) continue;
room.setRow(roomIndex, n.getTextContent().toCharArray());
roomIndex++;
}
room.finaliseContents();
Node define = getNode(DEFINITIONS, chosen.getChildNodes());
if (define != null)
{
for (int i = 0; i < define.getChildNodes().getLength(); i++)
{
Node symbol = define.getChildNodes().item(i);
if (!symbol.getNodeName().equalsIgnoreCase(SYMBOL)) continue;
char character = getNodeValue(CHAR, symbol.getChildNodes()).charAt(0);
String type = getNodeValue(TYPE, symbol.getChildNodes());
boolean visible = Boolean.parseBoolean(getNodeValue(VISIBLE, symbol.getChildNodes()));
String shortDesc = getNodeValue(SHORT_DESCRIPTION, symbol.getChildNodes());
if (shortDesc == null) {
System.out.println(character + " " + type);
shortDesc = " ";
}
String longDesc = getNodeValue(LONG_DESCRIPTION, symbol.getChildNodes());
if (longDesc == null) longDesc = " ";
AbstractObject ao = new AbstractObject(character, type, visible, shortDesc, longDesc);
Node meta = getNode(META, symbol.getChildNodes());
if (meta != null)
{
for (int j = 0; j < meta.getChildNodes().getLength(); j++)
{
Node n = meta.getChildNodes().item(j);
if (!n.getNodeName().equalsIgnoreCase(DATA)) continue;
ao.addMeta(getNodeValue(NAME, n.getChildNodes()), getNodeValue(CONTENTS, n.getChildNodes()));
}
}
if (visible)
{
Node model = getNode(MODEL, symbol.getChildNodes());
String modelType = getNodeValue(MODEL_TYPE, model.getChildNodes());
String modelName = getNodeValue(MODEL_NAME, model.getChildNodes());
String ms = getNodeValue(MODEL_SCALE, model.getChildNodes());
float modelScale = 1.0f;
if (ms != null && ms.length() > 0) modelScale = Float.parseFloat(ms);
Node dimensions = getNode(DIMENSIONS, model.getChildNodes());
int number = 0;
if (dimensions != null) number = Integer.parseInt(getNodeValue(DIMENSIONS_NUMBER, dimensions.getChildNodes()));
float[] dim = new float[number];
for (int j = 1; j < number+1; j++)
{
dim[j-1] = Float.parseFloat(getNodeValue(DIMENSIONS_D+j, dimensions.getChildNodes()));
}
String texture = getNodeValue(TEXTURE, symbol.getChildNodes());
Node colour = getNode(COLOUR, symbol.getChildNodes());
float red = Float.parseFloat(getNodeValue(RED, colour.getChildNodes()));
float green = Float.parseFloat(getNodeValue(GREEN, colour.getChildNodes()));
float blue = Float.parseFloat(getNodeValue(BLUE, colour.getChildNodes()));
Color col = new Color(red, green, blue, 1.0f);
ao.setModel(modelType, modelName, modelScale, texture, col, dim);
}
room.addObject(ao);
}
}
Node global = getNode(GLOBAL, biome.getChildNodes());
for (int i = 0; i < global.getChildNodes().getLength(); i++)
{
Node symbol = global.getChildNodes().item(i);
if (!symbol.getNodeName().equalsIgnoreCase(SYMBOL)) continue;
char character = getNodeValue(CHAR, symbol.getChildNodes()).charAt(0);
String type = getNodeValue(TYPE, symbol.getChildNodes());
boolean visible = Boolean.parseBoolean(getNodeValue(VISIBLE, symbol.getChildNodes()));
String shortDesc = getNodeValue(SHORT_DESCRIPTION, symbol.getChildNodes());
String longDesc = getNodeValue(LONG_DESCRIPTION, symbol.getChildNodes());
AbstractObject ao = new AbstractObject(character, type, visible, shortDesc, longDesc);
Node meta = getNode(META, symbol.getChildNodes());
if (meta != null)
{
for (int j = 0; j < meta.getChildNodes().getLength(); j++)
{
Node n = meta.getChildNodes().item(j);
if (!n.getNodeName().equalsIgnoreCase(DATA)) continue;
ao.addMeta(getNodeValue(NAME, n.getChildNodes()), getNodeValue(CONTENTS, n.getChildNodes()));
}
}
if (visible)
{
Node model = getNode(MODEL, symbol.getChildNodes());
String modelType = getNodeValue(MODEL_TYPE, model.getChildNodes());
String modelName = getNodeValue(MODEL_NAME, model.getChildNodes());
String ms = getNodeValue(MODEL_SCALE, model.getChildNodes());
float modelScale = 1.0f;
if (ms != null && ms.length() > 0) modelScale = Float.parseFloat(ms);
Node dimensions = getNode(DIMENSIONS, model.getChildNodes());
int number = Integer.parseInt(getNodeValue(DIMENSIONS_NUMBER, dimensions.getChildNodes()));
float[] dim = new float[number];
for (int j = 1; j < number+1; j++)
{
dim[j-1] = Float.parseFloat(getNodeValue(DIMENSIONS_D+j, dimensions.getChildNodes()));
}
String texture = getNodeValue(TEXTURE, symbol.getChildNodes());
Node colour = getNode(COLOUR, symbol.getChildNodes());
float red = Float.parseFloat(getNodeValue(RED, colour.getChildNodes()));
float green = Float.parseFloat(getNodeValue(GREEN, colour.getChildNodes()));
float blue = Float.parseFloat(getNodeValue(BLUE, colour.getChildNodes()));
Color col = new Color(red, green, blue, 1.0f);
ao.setModel(modelType, modelName, modelScale, texture, col, dim);
}
room.addObject(ao);
}
Node meta = getNode(META, chosen.getChildNodes());
if (meta != null)
{
for (int j = 0; j < meta.getChildNodes().getLength(); j++)
{
Node n = meta.getChildNodes().item(j);
if (!n.getNodeName().equalsIgnoreCase(DATA)) continue;
room.addMeta(getNodeValue(NAME, n.getChildNodes()), getNodeValue(CONTENTS, n.getChildNodes()));
}
}
return room;
}
private Node getRoomNode(RoomType rtype)
{
String rname = null;
if (rtype == RoomType.START)
{
rname = START;
}
else if (rtype == RoomType.END)
{
rname = END;
}
else if (rtype == RoomType.MAIN)
{
rname = MAIN;
}
else if (rtype == RoomType.SPECIAL)
{
rname = SPECIAL;
}
else if (rtype == RoomType.OTHER)
{
rname = OTHER;
}
return getNode(rname, biome.getChildNodes());
}
}