neon.editor.Editor.java Source code

Java tutorial

Introduction

Here is the source code for neon.editor.Editor.java

Source

/*
 *   Neon, a roguelike engine.
 *   Copyright (C) 2017-2018 - 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.editor;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jdom2.Element;

import com.google.common.collect.Multimap;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;

import javafx.application.Application;
import javafx.stage.Stage;
import neon.common.files.FileUtils;
import neon.common.files.NeonFileSystem;
import neon.common.files.XMLTranslator;
import neon.common.logging.NeonLogFormatter;
import neon.common.resources.RModule;
import neon.common.resources.ResourceException;
import neon.common.resources.ResourceManager;
import neon.common.resources.loaders.CreatureLoader;
import neon.common.resources.loaders.ItemLoader;
import neon.common.resources.loaders.ModuleLoader;
import neon.common.resources.loaders.TerrainLoader;
import neon.editor.resource.CEditor;
import neon.editor.resource.MapLoader;
import neon.editor.ui.UserInterface;

/**
 * The neon roguelike editor.
 * 
 * @author mdriesen
 *
 */
public class Editor extends Application {
    private static final Logger logger = Logger.getGlobal();

    private final NeonFileSystem files = new NeonFileSystem();
    private final ResourceManager resources = new ResourceManager();
    private final EventBus bus = new EventBus("Editor Bus");
    private final UserInterface ui; // where all JavaFX business takes place
    private final CEditor config = new CEditor();

    /**
     * Initializes this {@code Editor}.
     */
    public Editor() {
        bus.register(this);
        ui = new UserInterface(files, resources, bus, config);

        try {
            files.setTemporaryFolder(Paths.get("temp"));
        } catch (IOException e) {
            logger.severe("could not set the temporary folder");
        }

        // add all resource loaders
        resources.addLoader(new ModuleLoader(files));
        resources.addLoader(new MapLoader(files, resources));
        resources.addLoader(new CreatureLoader(files));
        resources.addLoader(new ItemLoader(files));
        resources.addLoader(new TerrainLoader(files));
    }

    @Override
    public void start(Stage stage) {
        ui.start(stage);
    }

    /**
     * Creates a new module.
     * 
     * @param event
     * @throws IOException
     * @throws MissingLoaderException
     */
    @Subscribe
    private void createModule(LoadEvent.Create event) throws IOException {
        Path path = event.getPath();
        String id = path.getFileName().toString();

        // create the new module
        Files.createDirectories(path);
        // editing is done in temp, so don't add the actual module folder to the file system
        RModule.Builder builder = new RModule.Builder(id);
        RModule module = builder.setTitle(id).build();
        resources.addResource(module);
        config.setActiveModule(module);
    }

    /**
     * Loads an existing module for editing.
     * 
     * @param event
     * @throws FileNotFoundException
     * @throws ResourceException 
     */
    @Subscribe
    private void loadModule(LoadEvent.Load event) throws FileNotFoundException, ResourceException {
        // set the active module id
        File file = event.getFile();
        String module = file.getName();

        // add the parent modules to the file system
        Path path = Paths.get(file.getPath(), module + ".xml");
        try (InputStream in = Files.newInputStream(path)) {
            Element root = new XMLTranslator().translate(in).getRootElement();
            for (Element parent : root.getChild("parents").getChildren()) {
                files.addModule(parent.getText());
            }
        } catch (IOException e) {
            throw new FileNotFoundException("module <" + module + "> not found");
        }

        // keep track of all resources defined in parent modules
        Multimap<String, Card> cards = event.getCards();
        for (String id : resources.listResources("creatures")) {
            Card card = new Card("creatures", id, resources, true);
            cards.put("creatures", card);
        }
        for (String id : resources.listResources("items")) {
            Card card = new Card("items", id, resources, true);
            cards.put("items", card);
        }
        for (String id : resources.listResources("maps")) {
            Card card = new Card("maps", id, resources, true);
            cards.put("maps", card);
        }
        for (String id : resources.listResources("terrain")) {
            Card card = new Card("terrain", id, resources, true);
            cards.put("terrain", card);
        }

        // editing is done in temp, so don't add the actual module folder to the file system
        FileUtils.copyFolder(file.toPath(), Paths.get("temp"));
        config.setActiveModule(resources.getResource(module));

        // keep track of all resources (re)defined in the active module
        for (String id : FileUtils.listFiles(Paths.get("temp", "creatures"))) {
            Card card = new Card("creatures", id.replaceAll(".xml", ""), resources, false);
            if (cards.get("creatures").contains(card)) {
                cards.remove("creatures", card);
                card = new Card("creatures", id.replaceAll(".xml", ""), resources, true);
                card.setRedefined(true);
            }
            cards.put("creatures", card);
        }
        for (String id : FileUtils.listFiles(Paths.get("temp", "items"))) {
            Card card = new Card("items", id.replaceAll(".xml", ""), resources, false);
            if (cards.get("items").contains(card)) {
                cards.remove("items", card);
                card = new Card("items", id.replaceAll(".xml", ""), resources, true);
                card.setRedefined(true);
            }
            cards.put("items", card);
        }
        for (String id : FileUtils.listFiles(Paths.get("temp", "terrain"))) {
            Card card = new Card("terrain", id.replaceAll(".xml", ""), resources, false);
            if (cards.get("terrain").contains(card)) {
                cards.remove("terrain", card);
                card = new Card("terrain", id.replaceAll(".xml", ""), resources, true);
                card.setRedefined(true);
            }
            cards.put("terrain", card);
        }
        for (String id : FileUtils.listFiles(Paths.get("temp", "maps"))) {
            Card card = new Card("maps", id.replaceAll(".xml", ""), resources, false);
            if (cards.get("maps").contains(card)) {
                cards.remove("maps", card);
                card = new Card("maps", id.replaceAll(".xml", ""), resources, true);
                card.setRedefined(true);
            }
            cards.put("maps", card);
        }

        logger.fine("loaded module " + module);
    }

    /**
     * Saves the module that is currently being edited to disk.
     * 
     * @param event
     */
    @Subscribe
    private void saveModule(SaveEvent.Module event) {
        String id = config.getActiveModule().id;
        FileUtils.clearFolder(Paths.get("data", id));
        FileUtils.moveFolder(Paths.get("temp"), Paths.get("data", id));
        logger.fine("saved module " + id);
    }

    /**
     * Saves an edited resource to disk.
     * 
     * @param event
     */
    @Subscribe
    private void saveResource(SaveEvent.Resources event) {
        try {
            resources.addResource(event.getResource());
            logger.fine("saved resource " + event.getResource().id);
        } catch (IOException e) {
            logger.severe("failed to save resource " + event.getResource().id);
        }
    }

    public static void main(String[] args) {
        // set up logging
        logger.setLevel(Level.ALL);
        logger.setUseParentHandlers(false);
        Handler handler = new ConsoleHandler();
        handler.setLevel(Level.ALL);
        handler.setFormatter(new NeonLogFormatter());
        logger.addHandler(handler);

        launch(args);
    }
}