aritzh.waywia.universe.World.java Source code

Java tutorial

Introduction

Here is the source code for aritzh.waywia.universe.World.java

Source

/*
 * Copyright (c) 2013 Aritzh (Aritz Lopez)
 *
 * This game 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 game 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
 * game. If not, see http://www.gnu.org/licenses/.
 */

package aritzh.waywia.universe;

import aritzh.waywia.blocks.BackgroundBlock;
import aritzh.waywia.blocks.Block;
import aritzh.waywia.core.Game;
import aritzh.waywia.entity.Entity;
import aritzh.waywia.entity.player.Player;
import com.google.common.base.CaseFormat;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import io.github.aritzhack.util.bds.BDSCompound;
import io.github.aritzhack.util.bds.BDSInt;
import io.github.aritzhack.util.bds.BDSStorable;
import io.github.aritzhack.util.bds.BDSString;
import io.github.aritzhack.util.collections.Matrix;
import io.github.aritzhack.util.collections.ParametrizedFunction;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.geom.Rectangle;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

/**
 * @author Aritz Lopez
 */
public class World implements BDSStorable {

    private static final ParametrizedFunction<Block, Object> blockUpdate = (input, args) -> {
        input.update((int) args[0], (int) args[1], (int) args[2], (World) args[3]);
        return null;
    };
    private static final ParametrizedFunction<Block, BDSCompound> blockSave = (input, args) -> {
        BDSCompound ret = input.toBDS();
        ret.add(new BDSInt((int) args[0], "x"));
        ret.add(new BDSInt((int) args[1], "y"));
        return ret;
    };
    private static final ParametrizedFunction<Block, Object> blockRender = (input, args) -> {
        input.render((int) args[0], (int) args[1], (Graphics) args[2], (World) args[3]);
        return null;
    };
    private final File root;
    private final Multimap<String, Entity> entities;
    private final HashMap<String, Player> players;
    private final Matrix<Block> blocks;
    private final BDSCompound customData;
    private final String worldName;
    private Player player;

    private World(String name, File root, BDSCompound customData, Multimap<String, Entity> entities,
            HashMap<String, Player> players, Matrix<Block> blocks) {
        this.worldName = name;
        this.root = root;
        this.customData = customData;
        this.entities = entities;
        this.players = players;
        this.blocks = blocks;
    }

    public static World newWorld(String name, File universeFolder) throws IOException {
        String folderName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, name);
        File root = new File(universeFolder, folderName);

        if (!root.exists() && !root.mkdirs())
            throw new IOException("Could not create folder for new world at: " + root.getAbsolutePath());

        BDSCompound customData = new BDSCompound("CustomData");
        Multimap<String, Entity> entities = ArrayListMultimap.create();
        HashMap<String, Player> player = Maps.newHashMap();
        Matrix<Block> blocks = new Matrix<>(50, 38, new BackgroundBlock());

        return new World(name, root, customData, entities, player, blocks);
    }

    public static Set<World> listWorldsInFolder(File root) {
        Set<World> ret = new HashSet<>();
        for (File folder : root.listFiles(Universe.onlyFolders)) {
            World w = World.loadWorld(folder);
            if (w == null) {
                try {
                    Game.logger.w("Folder {} is not a valid world folder", folder.getCanonicalPath());
                } catch (IOException e) {
                    Game.logger.w("Folder {} is not a valid world folder", folder.getAbsolutePath());
                }
                continue;
            }
            ret.add(w);
        }
        return ret;
    }

    public static World loadWorld(File root) {
        BDSCompound worldComp = World.getCompoundFromFolder(root);
        if (worldComp == null)
            return null;

        try {
            String name = worldComp.getString("Name", 0).getData();
            BDSCompound data = worldComp.getComp("CustomData", 0);
            Matrix<Block> blocks = World.readBlocks(worldComp.getComp("Blocks", 0));
            Multimap<String, Entity> entities = World.readEntities(worldComp.getComp("Entities", 0));
            HashMap<String, Player> players = World.readPlayers(worldComp.getComp("Players", 0));

            return new World(name, root, data, entities, players, blocks);
        } catch (NullPointerException ignored) {
        }

        return null;
    }

    private static BDSCompound getCompoundFromFolder(File folder) {
        File f;
        if (folder.exists() && (f = new File(folder, "world.dat")).exists()) {
            try {
                return new BDSCompound(f);
            } catch (IOException ignored) {
            }
        }
        return null;
    }

    private static Matrix<Block> readBlocks(BDSCompound blockComp) {
        Matrix<Block> blocks = new Matrix<>(25, 19, new BackgroundBlock());
        for (BDSCompound comp : blockComp.getAllCompounds()) {
            if (!comp.getName().equals("Block"))
                continue;

            int x = comp.getInt("x", 0).getData();
            int y = comp.getInt("y", 0).getData();

            Block b = Block.fromBDS(comp);
            if (b != null)
                blocks.set(b, x, y);
        }
        return blocks;
    }

    private static Multimap<String, Entity> readEntities(BDSCompound entitiesComp) {
        Multimap<String, Entity> entities = ArrayListMultimap.create();
        for (BDSCompound comp : entitiesComp.getAllCompounds()) {
            if (!comp.getName().equals("Entity"))
                continue;
            try {
                Entity e = Entity.fromBDS(comp);

                if (e != null)
                    entities.put(e.getName(), e);
            } catch (Exception ignored) {
            }
        }
        return entities;
    }

    private static HashMap<String, Player> readPlayers(BDSCompound playersComp) {
        HashMap<String, Player> players = Maps.newHashMap();
        for (BDSCompound comp : playersComp.getAllCompounds()) {
            if (!comp.getName().equals("Player"))
                continue;

            Player p = Player.fromBDS(comp);
            if (p != null)
                players.put(p.getUsername(), p);
        }
        return players;
    }

    public void spanwEntity(Entity e) {
        this.entities.put(e.getName(), e);
    }

    public void removeEntity(Entity e) {
        this.entities.remove(e.getName(), e);
    }

    public void update(int delta) {
        this.blocks.runForEach(World.blockUpdate, delta, this);

        for (Entity e : this.entities.values()) {
            e.update(delta, this);
        }

        for (Player p : this.players.values()) {
            p.update(delta, this);
        }
    }

    public void render(Graphics g) {
        this.blocks.runForEach(World.blockRender, g, this);

        for (Entity e : entities.values()) {
            e.render(g);
        }

        for (Player p : this.players.values()) {
            p.render(g);
        }
    }

    public String getName() {
        return worldName;
    }

    public void save() throws IOException {
        this.toBDS().writeToFile(new File(this.root, "world.dat"));
    }

    @Override
    public BDSCompound toBDS() {
        BDSCompound ret = new BDSCompound("World");

        ret.add(new BDSString(this.worldName, "Name"));
        if (this.customData != null)
            ret.add(this.customData);

        BDSCompound entities = new BDSCompound("Entities");
        for (Entity e : this.entities.values()) {
            if (e instanceof Player)
                continue;
            entities.add(e.toBDS());
        }
        ret.add(entities);

        BDSCompound players = new BDSCompound("Players");
        for (Player p : this.players.values()) {
            players.add(p.toBDS());
        }
        ret.add(players);

        BDSCompound blocks = new BDSCompound("Blocks");
        blocks.addAll(this.blocks.runForEach(blockSave).toFlatArrayList());
        ret.add(blocks);
        return ret;
    }

    public void clicked(int x, int y) {
        float cx = x / (float) Block.SIZE;
        float cy = y / (float) Block.SIZE;
        this.blocks.get((int) cx, (int) cy).clicked(cx, cy, this);
    }

    public Player getPlayer() {
        return this.player;
    }

    public void setPlayer(Player player) {
        this.player = player;
        if (!this.entities.containsValue(this.player))
            this.entities.put(this.player.getUsername(), this.player);
        if (!this.players.containsValue(this.player))
            this.players.put(this.player.getUsername(), this.player);
    }

    public <R> Matrix<R> runForEachBlock(ParametrizedFunction<Block, R> function, Object... args) {
        return this.blocks.runForEach(function, args);
    }

    public boolean anyEntityCollides(Rectangle rect) {
        for (Entity e : this.entities.values()) {
            if (e.getBoundingBox().intersects(rect))
                return true;
        }
        return false;
    }

    public void setBlock(int x, int y, int id) {
        this.blocks.set(Block.getBlock(id), x, y);
    }
}