package com.github.jamesnorris.ablockalypse.aspect; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockState; import com.github.jamesnorris.ablockalypse.Ablockalypse; import com.github.jamesnorris.ablockalypse.behavior.MapDatable; import com.github.jamesnorris.ablockalypse.enumerated.ZAEffect; import com.github.jamesnorris.ablockalypse.enumerated.ZASound; import com.github.jamesnorris.ablockalypse.utility.Cuboid; import com.github.jamesnorris.ablockalypse.utility.SerialLocation; public class Passage extends SpecificGameAspect implements MapDatable { private Location loc1, loc2; private ArrayList<BlockState> states = new ArrayList<BlockState>(); private boolean opened; private Cuboid rectangle; private Game game; private UUID uuid = UUID.randomUUID(); /** * Creates a new Passage instance that is represented by a rectangular prism. * * @param game The game that should use this passage * @param loc1 The first corner of the rectangular prism * @param loc2 The second corner of the rectangular prism */ @SuppressWarnings("serial") public Passage(Game game, final Location loc1, final Location loc2) { super(game, new ArrayList<Location>() { { add(loc1); add(loc2); } }, !game.hasStarted()); rectangle = new Cuboid(loc1, loc2); this.loc1 = loc1; this.loc2 = loc2; this.game = game; opened = false; for (Location l : rectangle.getLocations()) { states.add(l.getBlock().getState()); } load(); } public Passage(Map<String, Object> savings) { this(Ablockalypse.getData().getGame((String) savings.get("game_name"), true), SerialLocation.returnLocation((SerialLocation) savings.get("location_1")), SerialLocation.returnLocation((SerialLocation) savings.get("location_2"))); opened = (Boolean) savings.get("is_open"); if (opened) { open(); } else { close(); } uuid = savings.get("uuid") == null ? uuid : (UUID) savings.get("uuid"); } /** * Replaces the passage. */ public void close() { opened = false; for (BlockState state : states) { ZAEffect.SMOKE.play(state.getLocation()); state.update(true, true); } } @Override public List<Block> getBlinkerBlocks() { List<Block> blocks = new ArrayList<Block>(); for (Location location : new Cuboid(loc1, loc2).getBorder()) { blocks.add(location.getBlock()); } return blocks; } /** * Gets the blocks around the border of the passage. * * @return The blocks around the border */ public List<Location> getBorder() { return rectangle.getBorder(); } @Override public List<Block> getDefiningBlocks() { List<Block> blocks = new ArrayList<Block>(); for (Location location : new Cuboid(loc1, loc2).getLocations()) { blocks.add(location.getBlock()); } return blocks; } @Override public int getLoadPriority() { return 2; } /** * Gets a point from the passage. This must be between 1 and 2. * * @param i The point to get * @return The location of the point */ public Location getPoint(int i) { Location loc = i == 1 ? loc1 : loc2; return loc; } @Override public Location getPointClosestToOrigin() { Location origin = new Location(loc1.getWorld(), 0, 0, 0, 0, 0); Location loc = null; for (BlockState state : states) { Block block = state.getBlock(); if (loc == null || block.getLocation().distanceSquared(origin) <= loc.distanceSquared(origin)) { loc = block.getLocation(); } } return loc; } @Override public Map<String, Object> getSave() { Map<String, Object> savings = new HashMap<String, Object>(); savings.put("uuid", getUUID()); savings.put("location_1", loc1 == null ? null : new SerialLocation(loc1)); savings.put("location_2", loc2 == null ? null : new SerialLocation(loc2)); savings.put("is_open", opened); savings.put("game_name", game.getName()); return savings; } @Override public UUID getUUID() { return uuid; } /** * Returns if the passage is opened or not. * * @return Whether or not the passage has been opened */ public boolean isOpened() { return opened; } @Override public void onGameEnd() { close(); setBlinking(true); } @Override public void onGameStart() { setBlinking(false); } /** * Removes the passage. */ public void open() { for (BlockState state : states) { state.getBlock().setType(Material.AIR); ZAEffect.SMOKE.play(state.getLocation()); } ZASound.AREA_BUY.play(loc1); opened = true; } @Override public void paste(Location pointClosestToOrigin) { Location old = getPointClosestToOrigin(); loc1 = pointClosestToOrigin.add(loc1.getX() - old.getX(), loc1.getY() - old.getY(), loc1.getZ() - old.getZ()); loc2 = pointClosestToOrigin.add(loc2.getX() - old.getX(), loc2.getY() - old.getY(), loc2.getZ() - old.getZ()); close(); states.clear(); for (Location l : rectangle.getLocations()) { states.add(l.getBlock().getState()); } refreshBlinker(); } /** * Removes the passage. */ @Override public void remove() { close(); super.remove(); } /** * Sets the first or second location of the passage. * * @param loc The location to set * @param n A number between 1 and 2 */ public void setLocation(Location loc, int n) { if (n == 1) { loc1 = loc; } else if (n == 2) { loc2 = loc; } if (n == 1 || n == 2) { rectangle = new Cuboid(loc1, loc2); } } @Override public void setPowered(boolean power) { if (!opened && power) { open(); } else if (opened && !power) { close(); } super.setPowered(power); } }