neon.maps.MapLoader.java Source code

Java tutorial

Introduction

Here is the source code for neon.maps.MapLoader.java

Source

/*
 *   Neon, a roguelike engine.
 *   Copyright (C) 2013 - Maarten Driesen
 * 
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package neon.maps;

import org.jdom2.*;

import java.awt.Point;

import neon.core.*;
import neon.entities.Container;
import neon.entities.Creature;
import neon.entities.Door;
import neon.entities.EntityFactory;
import neon.entities.Item;
import neon.entities.components.Enchantment;
import neon.entities.components.Lock;
import neon.resources.RDungeonTheme;
import neon.resources.RItem;
import neon.resources.RRegionTheme;
import neon.resources.RSpell;
import neon.resources.RTerrain;
import neon.resources.RZoneTheme;
import neon.systems.files.FileSystem;
import neon.systems.files.XMLTranslator;

/**
 * This class loads a map from an xml file.
 * 
 * @author mdriesen
 */
public class MapLoader {
    /**
     * Returns a map described in an xml file with the given name.
     * 
     * @param path      the pathname of a map file
     * @param uid      the unique identifier of this map
     * @return      the <code>Map</code> described by the map file
     */
    public static Map loadMap(String[] path, int uid, FileSystem files) {
        Document doc = files.getFile(new XMLTranslator(), path);
        Element root = doc.getRootElement();
        //      System.out.println("loadmap(" + path + ")");
        if (root.getName().equals("world")) {
            return loadWorld(root, uid);
        } else {
            return loadDungeon(root, uid);
        }
    }

    /**
     * Loads a dungeon behind a themed door.
     * 
     * @param theme
     * @return
     */
    public static Dungeon loadDungeon(String theme) {
        return loadThemedDungeon(theme, theme, Engine.getGame().getStore().createNewMapUID());
    }

    private static World loadWorld(Element root, int uid) {
        //      System.out.println("maploader: " + uid);
        World world = new World(root.getChild("header").getChildText("name"), uid);
        loadZone(root, world, 0, uid); // outdoor heeft maar 1 zone, namelijk 0
        return world;
    }

    private static Dungeon loadDungeon(Element root, int uid) {
        if (root.getChild("header").getAttribute("theme") != null) {
            String name = root.getChild("header").getChildText("name");
            return loadThemedDungeon(name, root.getChild("header").getAttributeValue("theme"), uid);
        }

        Dungeon map = new Dungeon(root.getChild("header").getChildText("name"), uid);

        for (Element l : root.getChildren("level")) {
            int level = Integer.parseInt(l.getAttributeValue("l"));
            String name = l.getAttributeValue("name");
            if (l.getAttribute("theme") != null) {
                RZoneTheme theme = (RZoneTheme) Engine.getResources().getResource(l.getAttributeValue("theme"),
                        "theme");
                map.addZone(level, name, theme);
                if (l.getAttribute("out") != null) {
                    String[] connections = l.getAttributeValue("out").split(",");
                    for (String connection : connections) {
                        map.addConnection(level, Integer.parseInt(connection));
                    }
                }
            } else {
                map.addZone(level, name);
                loadZone(l, map, level, uid);
            }
        }

        return map;
    }

    private static Dungeon loadThemedDungeon(String name, String dungeon, int uid) {
        Dungeon map = new Dungeon(name, uid);
        RDungeonTheme theme = (RDungeonTheme) Engine.getResources().getResource(dungeon, "theme");

        int minZ = theme.min;
        int maxZ = theme.max;
        float branch = theme.branching;
        String[] types = theme.zones.split(";");

        int[] zones = new int[MapUtils.random(minZ, maxZ)];
        int z = zones.length - 1;
        while (z > -1) {
            int t = MapUtils.random(0, types.length - 1);
            zones[z] = 1;
            RZoneTheme rzt = (RZoneTheme) Engine.getResources().getResource(types[t], "theme");
            map.addZone(z, "zone " + z, rzt);
            z--;
        }

        zones[0] = 0;
        for (z = 1; z < zones.length; z++) {
            // verbinden met reeds bezocht zone
            int to = MapUtils.random((int) Math.max(0, z - branch), z - 1);
            map.addConnection(z, to);
            zones[z] = 0;
        }

        return map;
    }

    private static void loadZone(Element root, Map map, int l, int uid) {
        for (Element region : root.getChild("regions").getChildren()) { // regions laden
            map.getZone(l).addRegion(loadRegion(region));
        }
        if (root.getChild("creatures") != null) { // creatures laden
            for (Element c : root.getChild("creatures").getChildren()) {
                String species = c.getAttributeValue("id");
                int x = Integer.parseInt(c.getAttributeValue("x"));
                int y = Integer.parseInt(c.getAttributeValue("y"));
                long creatureUID = UIDStore.getObjectUID(uid, Integer.parseInt(c.getAttributeValue("uid")));
                Creature creature = EntityFactory.getCreature(species, x, y, creatureUID);
                Engine.getGame().getStore().addEntity(creature);
                map.getZone(l).addCreature(creature);
            }
        }
        if (root.getChild("items") != null) { // items laden
            for (Element i : root.getChild("items").getChildren()) {
                long itemUID = UIDStore.getObjectUID(uid, Integer.parseInt(i.getAttributeValue("uid")));
                String id = i.getAttributeValue("id");
                int x = Integer.parseInt(i.getAttributeValue("x"));
                int y = Integer.parseInt(i.getAttributeValue("y"));
                Item item = null;
                if (i.getName().equals("container")) {
                    item = loadContainer(i, id, x, y, itemUID, uid); // omdat containers lastig zijn
                } else if (i.getName().equals("door")) {
                    item = loadDoor(i, id, x, y, itemUID, uid); // omdat deuren ook lastig zijn
                } else {
                    item = EntityFactory.getItem(id, x, y, itemUID);
                }
                map.getZone(l).addItem(item);
                Engine.getGame().getStore().addEntity(item);
            }
        }
    }

    /*
     * dit gaat mottig worden, met ganse if-then-else mesthoop
     */
    private static Door loadDoor(Element door, String id, int x, int y, long itemUID, int mapUID) {
        Door d = (Door) EntityFactory.getItem(id, x, y, itemUID);

        // lock difficulty
        int lock = 0;
        if (door.getAttribute("lock") != null) {
            lock = Integer.parseInt(door.getAttributeValue("lock"));
            d.lock.setLockDC(lock);
        }
        // sleutel
        if (door.getAttribute("key") != null) {
            RItem key = (RItem) Engine.getResources().getResource(door.getAttributeValue("key"));
            d.lock.setKey(key);
        }
        // state van de deur (open, dicht of gesloten)
        if (door.getAttributeValue("state").equals("locked")) {
            if (lock > 0) {
                d.lock.setState(Lock.LOCKED);
            } else { // als er geen lock is, state in closed veranderen
                d.lock.setState(Lock.CLOSED);
            }
        } else if (door.getAttributeValue("state").equals("closed")) {
            d.lock.setState(Lock.CLOSED);
        }

        // trap
        int trap = 0;
        if (door.getAttribute("trap") != null) {
            trap = Integer.parseInt(door.getAttributeValue("trap"));
            d.trap.setTrapDC(trap);
        }
        // spell
        if (door.getAttribute("spell") != null) {
            String spell = door.getAttributeValue("spell");
            RSpell.Enchantment enchantment = (RSpell.Enchantment) Engine.getResources().getResource(spell, "magic");
            d.setMagicComponent(new Enchantment(enchantment, 0, d.getUID()));
        }

        // bestemming van de deur
        Element dest = door.getChild("dest");
        Point destPos = null;
        int destLevel = 0;
        int destMapUID = 0;
        String theme = null;
        String sign = null;
        if (door.getChild("dest") != null) {
            int destX = -1;
            int destY = -1;
            if (dest.getAttribute("x") != null) {
                destX = Integer.parseInt(dest.getAttributeValue("x"));
            }
            if (dest.getAttribute("y") != null) {
                destY = Integer.parseInt(dest.getAttributeValue("y"));
            }
            if (destX > -1 && destY > -1) {
                destPos = new Point(destX, destY);
            }
            if (dest.getAttributeValue("z") != null) {
                destLevel = Integer.parseInt(dest.getAttributeValue("z"));
            }
            if (dest.getAttributeValue("map") != null) {
                destMapUID = (mapUID & 0xFFFF0000) + Integer.parseInt(dest.getAttributeValue("map"));
            }
            theme = dest.getAttributeValue("theme");
            sign = dest.getAttributeValue("sign");
        }

        if (dest != null) {
            d.portal.setDestination(destPos, destLevel, destMapUID);
        }
        d.portal.setDestTheme(theme);
        d.setSign(sign);
        return d;
    }

    private static Container loadContainer(Element container, String id, int x, int y, long itemUID, int mapUID) {
        Container cont = (Container) EntityFactory.getItem(id, x, y, itemUID);

        // lock difficulty
        if (container.getAttribute("lock") != null) {
            int lock = Integer.parseInt(container.getAttributeValue("lock"));
            cont.lock.setLockDC(lock);
            cont.lock.setState(Lock.LOCKED);
        }
        // sleutel
        RItem key = null;
        if (container.getAttribute("key") != null) {
            key = (RItem) Engine.getResources().getResource(container.getAttributeValue("key"));
            cont.lock.setKey(key);
        }

        // trap
        int trap = 0;
        if (container.getAttribute("trap") != null) {
            trap = Integer.parseInt(container.getAttributeValue("trap"));
            cont.trap.setTrapDC(trap);
        }
        // spell
        if (container.getAttribute("spell") != null) {
            String spell = container.getAttributeValue("spell");
            RSpell.Enchantment enchantment = (RSpell.Enchantment) Engine.getResources().getResource(spell, "magic");
            cont.setMagicComponent(new Enchantment(enchantment, 0, cont.getUID()));
        }

        if (!container.getChildren("item").isEmpty()) { // indien items in map file
            for (Element e : container.getChildren("item")) {
                long contentUID = UIDStore.getObjectUID(mapUID, Integer.parseInt(e.getAttributeValue("uid")));
                Engine.getGame().getStore().addEntity(EntityFactory.getItem(e.getAttributeValue("id"), contentUID));
                cont.addItem(contentUID);
            }
        } else { // en anders default items
            for (String s : ((RItem.Container) cont.resource).contents) {
                Item i = EntityFactory.getItem(s, Engine.getGame().getStore().createNewEntityUID());
                Engine.getGame().getStore().addEntity(i);
                cont.addItem(i.getUID());
            }
        }

        return cont;
    }

    private static Region loadRegion(Element element) {
        int x = Integer.parseInt(element.getAttributeValue("x"));
        int y = Integer.parseInt(element.getAttributeValue("y"));
        int w = Integer.parseInt(element.getAttributeValue("w"));
        int h = Integer.parseInt(element.getAttributeValue("h"));
        byte order = Byte.parseByte(element.getAttributeValue("l"));

        String text = element.getAttributeValue("text");
        RRegionTheme theme = (RRegionTheme) Engine.getResources().getResource(element.getAttributeValue("random"),
                "theme");

        RTerrain rt = (RTerrain) Engine.getResources().getResource(text, "terrain");
        Region r = new Region(text, x, y, w, h, theme, order, rt);
        r.setLabel(element.getAttributeValue("label"));
        for (Element e : element.getChildren("script")) {
            r.addScript(e.getAttributeValue("id"), false);
        }

        return r;
    }
}