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 java.util.concurrent.CopyOnWriteArrayList; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.entity.LivingEntity; import com.github.jamesnorris.ablockalypse.Ablockalypse; import com.github.jamesnorris.ablockalypse.DataContainer; import com.github.jamesnorris.ablockalypse.behavior.MapDatable; import com.github.jamesnorris.ablockalypse.behavior.Targettable; import com.github.jamesnorris.ablockalypse.enumerated.ZAEffect; import com.github.jamesnorris.ablockalypse.enumerated.ZASound; import com.github.jamesnorris.ablockalypse.threading.Task; import com.github.jamesnorris.ablockalypse.threading.inherent.BarrierBreakTask; import com.github.jamesnorris.ablockalypse.threading.inherent.BarrierFixTask; import com.github.jamesnorris.ablockalypse.utility.AblockalypseUtility; import com.github.jamesnorris.ablockalypse.utility.BukkitUtility; import com.github.jamesnorris.ablockalypse.utility.Cube; import com.github.jamesnorris.ablockalypse.utility.SerialLocation; import com.github.jamesnorris.mcshot.Zone; public class Barrier extends SpecificGameAspect implements MapDatable, Targettable { private CopyOnWriteArrayList<BlockState> states = new CopyOnWriteArrayList<BlockState>(); private Zone zone; private Location center, spawnloc; private boolean correct; private DataContainer data = Ablockalypse.getData(); private Game game; private int hp = 5; private UUID uuid = UUID.randomUUID(); private Task warning; /** * Creates a new instance of a Barrier, where center is the center of the 3x3 barrier. * * @param center The center of the barrier * @param game The game to involve this barrier in */ public Barrier(Location center, Game game) { super(game, new Cube(center, 1).getLocations(), !game.hasStarted()); this.center = center; this.game = game; spawnloc = BukkitUtility.getNearbyLocation(center, 2, 5, 0, 0, 2, 5); for (Location loc : new Cube(center, 1).getLocations()) { Block b = loc.getBlock(); if (b != null && !b.isEmpty() && b.getType() != null) { states.add(b.getState()); } } load(); setIsCorrectlySetup(states.size() >= 9); } public Barrier(Map<String, Object> savings) { this(SerialLocation.returnLocation((SerialLocation) savings.get("center_location")), Ablockalypse.getData().getGame((String) savings.get("game_name"), true)); List<BlockState> blocks = new CopyOnWriteArrayList<BlockState>(); @SuppressWarnings("unchecked") List<SerialLocation> serialBlockLocations = (List<SerialLocation>) savings.get("all_block_locations"); for (SerialLocation serialLoc : serialBlockLocations) { blocks.add(serialLoc.getWorld().getBlockAt(SerialLocation.returnLocation(serialLoc)).getState()); } states = (CopyOnWriteArrayList<BlockState>) blocks; center = SerialLocation.returnLocation((SerialLocation) savings.get("center_location")); spawnloc = SerialLocation.returnLocation((SerialLocation) savings.get("spawn_location")); correct = (Boolean) savings.get("setup_is_correct"); game = Ablockalypse.getData().getGame((String) savings.get("game_name"), true); uuid = savings.get("uuid") == null ? uuid : (UUID) savings.get("uuid"); } /** * Slowly breaks the blocks of the barrier. * * @param liveEntity The entityliving that is breaking the barrier */ public void breakBarrier(LivingEntity liveEntity) { super.setBlinking(false); new BarrierBreakTask(this, liveEntity, true); } /** * Changes all blocks within the barrier to air. */ public void breakPanels() { for (BlockState state : states) { state.getBlock().setType(Material.AIR); ZAEffect.SMOKE.play(state.getLocation()); } hp = 0; } /** * Slowly fixes the blocks of the barrier. * * @param zap The ZAPlayer that is going to be fixing this barrier */ public void fixBarrier(ZAPlayer zap) { super.setBlinking(false); new BarrierFixTask(this, zap, true); } @SuppressWarnings("serial") @Override public List<Block> getBlinkerBlocks() { if (center == null) { return super.getBlinkerBlocks(); } return new ArrayList<Block>() { { add(center.getBlock()); } }; } /** * Returns the list of blocks in the barrier. * * @return A list of blocks located in the barrier */ public CopyOnWriteArrayList<Block> getBlocks() { CopyOnWriteArrayList<Block> blocks = new CopyOnWriteArrayList<Block>(); for (BlockState state : states) { blocks.add(state.getBlock()); } return blocks; } /** * Gets the center location of the barrier. * * @return The center of the barrier */ public Location getCenter() { return getDefiningBlock().getLocation(); } @Override public Block getDefiningBlock() { if (center == null) { return super.getDefiningBlock(); } return center.getBlock(); } /** * Gets the blocks that defines this object as an object. * * @return The blocks assigned to this object */ @Override public List<Block> getDefiningBlocks() { if (states == null) { return super.getDefiningBlocks(); } ArrayList<Block> blockArray = new ArrayList<Block>(); for (BlockState state : states) { blockArray.add(state.getBlock()); } return blockArray; } public int getHP() { return hp; } @Override public int getLoadPriority() { return 2; } @Override public Location getPointClosestToOrigin() { Location origin = new Location(center.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()); List<SerialLocation> serialBlocks = new ArrayList<SerialLocation>(); for (BlockState state : states) { serialBlocks.add(new SerialLocation(state.getBlock().getLocation())); } savings.put("all_block_locations", serialBlocks); savings.put("center_location", center == null ? null : new SerialLocation(center)); savings.put("spawn_location", spawnloc == null ? null : new SerialLocation(spawnloc)); savings.put("setup_is_correct", correct); savings.put("game_name", game.getName()); return savings; } /** * Gets the mob spawn location for this barrier. * * @return The mob spawn location around this barrier */ public Location getSpawnLocation() { return spawnloc; } @Override public UUID getUUID() { return uuid; } public Zone getZone() { return zone; } /** * Tells whether or not the barrier has any missing blocks. * * @return Whether or not the barrier is broken */ public boolean isBroken() { if (center.getBlock().isEmpty()) { return true; } return false; } /** * Checks if the barrier is setup correctly or not. * * @return Whether or not the barrier is setup correctly */ public boolean isCorrect() { return correct; } @Override public boolean isResponsive() { return hp != 0; } @Override public boolean isTargettedBy(ZAMob mob) { return false; } @Override public void onGameEnd() { replacePanels(); setBlinking(true); } @Override public void onGameStart() { setBlinking(false); } @Override public void paste(Location pointClosestToOrigin) { Location old = getPointClosestToOrigin(); Location toLoc = pointClosestToOrigin.add(center.getX() - old.getX(), center.getY() - old.getY(), center.getZ() - old.getZ()); center = toLoc; spawnloc = BukkitUtility.getNearbyLocation(center, 2, 5, 0, 0, 2, 5); refreshBlinker(); } /** * Removes the barrier. */ @Override public void remove() { replacePanels(); if (warning != null) { data.objects.remove(warning); } super.remove(); } /** * Replaces all holes in the barrier. */ public void replacePanels() { for (BlockState state : states) { state.update(true); ZAEffect.SMOKE.play(state.getLocation()); } ZASound.BARRIER_REPAIR.play(center); hp = 5; } public void setHP(int hp) { if (hp < 0) { hp = 0; return; } if (warning != null) { data.objects.remove(warning); } if (hp < 5) { warning = AblockalypseUtility.scheduleNearbyWarning(center, ChatColor.GRAY + "Hold " + ChatColor.AQUA + "SHIFT" + ChatColor.GRAY + " to fix barrier.", 2, 3, 2, 10000); } this.hp = hp; } @Override public Location updateTarget() { return center; } }