/* * Copyright (C) 2016 eccentric_nz * * 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 me.eccentric_nz.TARDIS.destroyers; import java.util.HashMap; import java.util.List; import me.eccentric_nz.TARDIS.TARDIS; import me.eccentric_nz.TARDIS.chameleon.TARDISChameleonColumn; import me.eccentric_nz.TARDIS.chameleon.TARDISConstructColumn; import me.eccentric_nz.TARDIS.database.ResultSetDoors; import me.eccentric_nz.TARDIS.database.ResultSetPlayerPrefs; import me.eccentric_nz.TARDIS.enumeration.PRESET; import me.eccentric_nz.TARDIS.utility.TARDISBlockSetters; import me.eccentric_nz.TARDIS.utility.TARDISJunkParticles; import me.eccentric_nz.TARDIS.utility.TARDISLocationGetters; import me.eccentric_nz.TARDIS.utility.TARDISSounds; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; /** * A dematerialisation circuit was an essential part of a Type 40 TARDIS which * enabled it to dematerialise from normal space into the Time Vortex and * rematerialise back from it. * * @author eccentric_nz */ public class TARDISDematerialisationPreset implements Runnable { private final TARDIS plugin; private final DestroyData dd; private final int loops; private final PRESET preset; public int task; private int i; private final int cham_id; private final byte cham_data; private final TARDISChameleonColumn column; private final TARDISChameleonColumn stained_column; private final TARDISChameleonColumn glass_column; private byte the_colour; /** * Runnable method to dematerialise the TARDIS Police Box. Tries to mimic * the transparency of dematerialisation by building the Police Box first * with GLASS, then STAINED_GLASS, then the normal preset wall block. * * @param plugin instance of the TARDIS plugin * @param dd the DestroyData * @param preset the Chameleon preset currently in use by the TARDIS * @param cham_id the chameleon block id for the police box * @param cham_data the chameleon block data for the police box * @param loops the number of loops to run */ public TARDISDematerialisationPreset(TARDIS plugin, DestroyData dd, PRESET preset, int cham_id, byte cham_data, int loops) { this.plugin = plugin; this.dd = dd; this.loops = loops; this.preset = preset; this.i = 0; this.cham_id = cham_id; this.cham_data = cham_data; if (this.preset.equals(PRESET.CONSTRUCT)) { column = new TARDISConstructColumn(plugin, dd.getTardisID(), "blueprint", dd.getDirection()).getColumn(); stained_column = new TARDISConstructColumn(plugin, dd.getTardisID(), "stain", dd.getDirection()).getColumn(); glass_column = new TARDISConstructColumn(plugin, dd.getTardisID(), "glass", dd.getDirection()).getColumn(); } else { column = plugin.getPresets().getColumn(preset, dd.getDirection()); stained_column = plugin.getPresets().getStained(preset, dd.getDirection()); glass_column = plugin.getPresets().getGlass(preset, dd.getDirection()); } } @Override public void run() { int[][] ids; byte[][] datas; // get relative locations int x = dd.getLocation().getBlockX(), plusx = dd.getLocation().getBlockX() + 1, minusx = dd.getLocation().getBlockX() - 1; int y; if (preset.equals(PRESET.SUBMERGED)) { y = dd.getLocation().getBlockY() - 1; } else { y = dd.getLocation().getBlockY(); } int z = dd.getLocation().getBlockZ(), plusz = dd.getLocation().getBlockZ() + 1, minusz = dd.getLocation().getBlockZ() - 1; World world = dd.getLocation().getWorld(); if (i < loops) { i++; // expand placed blocks to a police box switch (i % 3) { case 2: // stained ids = stained_column.getId(); datas = stained_column.getData(); break; case 1: // glass ids = glass_column.getId(); datas = glass_column.getData(); break; default: // preset ids = column.getId(); datas = column.getData(); break; } // first run - play sound if (i == 1) { switch (preset) { case GRAVESTONE: // remove flower int flowerx; int flowery = (dd.getLocation().getBlockY() + 1); int flowerz; switch (dd.getDirection()) { case NORTH: flowerx = dd.getLocation().getBlockX(); flowerz = dd.getLocation().getBlockZ() + 1; break; case WEST: flowerx = dd.getLocation().getBlockX() + 1; flowerz = dd.getLocation().getBlockZ(); break; case SOUTH: flowerx = dd.getLocation().getBlockX(); flowerz = dd.getLocation().getBlockZ() - 1; break; default: flowerx = dd.getLocation().getBlockX() - 1; flowerz = dd.getLocation().getBlockZ(); break; } TARDISBlockSetters.setBlock(world, flowerx, flowery, flowerz, 0, (byte) 0); break; case CAKE: plugin.getPresetDestroyer().destroyLamp(dd.getLocation(), preset); break; case JUNK_MODE: plugin.getPresetDestroyer().destroySign(dd.getLocation(), dd.getDirection(), preset); plugin.getPresetDestroyer().destroyHandbrake(dd.getLocation(), dd.getDirection()); break; default: break; } // only play the sound if the player is outside the TARDIS if (dd.isOutside()) { HashMap<String, Object> wherep = new HashMap<String, Object>(); wherep.put("uuid", dd.getPlayer().getUniqueId().toString()); ResultSetPlayerPrefs rsp = new ResultSetPlayerPrefs(plugin, wherep); boolean minecart = false; if (rsp.resultSet()) { minecart = rsp.isMinecartOn(); } if (!minecart) { String sound = (preset.equals(PRESET.JUNK_MODE)) ? "junk_takeoff" : "tardis_takeoff"; TARDISSounds.playTARDISSound(dd.getLocation(), sound); } else { world.playSound(dd.getLocation(), Sound.ENTITY_MINECART_INSIDE, 1.0F, 0.0F); } } the_colour = getWoolColour(dd.getTardisID(), preset); } else if (preset.equals(PRESET.JUNK_MODE) && plugin.getConfig().getBoolean("junk.particles")) { // animate particles for (Entity e : plugin.getUtils().getJunkTravellers(dd.getLocation())) { if (e instanceof Player) { Player p = (Player) e; Location effectsLoc = dd.getLocation().clone().add(0.5d, 0, 0.5d); TARDISJunkParticles.sendVortexParticles(effectsLoc, p); } } } else { // just change the walls int xx, zz; for (int n = 0; n < 9; n++) { int[] colids = ids[n]; byte[] coldatas = datas[n]; switch (n) { case 0: xx = minusx; zz = minusz; break; case 1: xx = x; zz = minusz; break; case 2: xx = plusx; zz = minusz; break; case 3: xx = plusx; zz = z; break; case 4: xx = plusx; zz = plusz; break; case 5: xx = x; zz = plusz; break; case 6: xx = minusx; zz = plusz; break; case 7: xx = minusx; zz = z; break; default: xx = x; zz = z; break; } for (int yy = 0; yy < 4; yy++) { boolean change = true; if (yy == 0 && n == 9) { Block rail = world.getBlockAt(xx, y, zz); if (rail.getType().equals(Material.RAILS) || rail.getType().equals(Material.POWERED_RAIL)) { change = false; } } switch (colids[yy]) { case 2: case 3: int subi = (preset.equals(PRESET.SUBMERGED)) ? cham_id : colids[yy]; byte subd = (preset.equals(PRESET.SUBMERGED)) ? cham_data : coldatas[yy]; TARDISBlockSetters.setBlock(world, xx, (y + yy), zz, subi, subd); break; case 35: // wool int chai = (preset.equals(PRESET.NEW) || preset.equals(PRESET.OLD)) ? cham_id : colids[yy]; byte chad = (preset.equals(PRESET.NEW) || preset.equals(PRESET.OLD)) ? cham_data : coldatas[yy]; if (preset.equals(PRESET.PARTY) || (preset.equals(PRESET.FLOWER) && coldatas[yy] == 0)) { chad = the_colour; } TARDISBlockSetters.setBlock(world, xx, (y + yy), zz, chai, chad); break; case 38: break; case 50: // lamps, glowstone and torches case 89: case 124: Material light = (preset.equals(PRESET.NEW) || preset.equals(PRESET.OLD)) ? dd.getLamp() : Material.getMaterial(colids[yy]); TARDISBlockSetters.setBlock(world, xx, (y + yy), zz, light, coldatas[yy]); break; case 64: case 68: // except the sign and doors case 71: case 193: case 194: case 195: case 196: case 197: break; case 95: if (coldatas[yy] == -1) { if (preset.equals(PRESET.PARTY) || (preset.equals(PRESET.FLOWER) && coldatas[yy] == 0)) { chad = the_colour; } else { // if it was a wool / stained glass / stained clay block get the data from that int[] finalids = column.getId()[n]; byte[] finaldatas = column.getData()[n]; if (finalids[yy] == 35 || finalids[yy] == 95 || finalids[yy] == 159 || finalids[yy] == 160 || finalids[yy] == 171) { if (preset.equals(PRESET.NEW) || preset.equals(PRESET.OLD)) { chad = cham_data; } else { chad = finaldatas[yy]; } } else { chad = plugin.getBuildKeeper().getStainedGlassLookup().getStain().get(cham_id); } } TARDISBlockSetters.setBlock(world, xx, (y + yy), zz, 95, chad); } else { TARDISBlockSetters.setBlock(world, xx, (y + yy), zz, colids[yy], coldatas[yy]); } break; default: // everything else if (change) { TARDISBlockSetters.setBlock(world, xx, (y + yy), zz, colids[yy], coldatas[yy]); } break; } } } } } else { plugin.getServer().getScheduler().cancelTask(task); task = 0; new TARDISDeinstaPreset(plugin).instaDestroyPreset(dd, false, preset); if (preset.equals(PRESET.JUNK_MODE)) { // teleport player(s) to exit (tmd.getFromToLocation()) for (Entity e : getJunkTravellers(1.0d)) { if (e instanceof Player) { final Player p = (Player) e; final Location relativeLoc = getRelativeLocation(p); p.teleport(relativeLoc); plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { p.teleport(relativeLoc); } }, 2L); } } } } } private Location getRelativeLocation(Player p) { Location playerLoc = p.getLocation(); double x = dd.getFromToLocation().getX() + (playerLoc.getX() - dd.getLocation().getX()); double y = dd.getFromToLocation().getY() + (playerLoc.getY() - dd.getLocation().getY()) + 1.1d; double z = dd.getFromToLocation().getZ() + (playerLoc.getZ() - dd.getLocation().getZ()); Location l = new Location(dd.getFromToLocation().getWorld(), x, y, z, playerLoc.getYaw(), playerLoc.getPitch()); while (!l.getChunk().isLoaded()) { l.getChunk().load(); } return l; } private List<Entity> getJunkTravellers(double d) { // spawn an entity Entity orb = dd.getLocation().getWorld().spawnEntity(dd.getLocation(), EntityType.EXPERIENCE_ORB); List<Entity> ents = orb.getNearbyEntities(d, d, d); orb.remove(); return ents; } @SuppressWarnings("deprecation") private byte getWoolColour(int id, PRESET p) { HashMap<String, Object> where = new HashMap<String, Object>(); where.put("tardis_id", id); where.put("door_type", 0); ResultSetDoors rs = new ResultSetDoors(plugin, where, false); if (rs.resultSet()) { Block b = TARDISLocationGetters.getLocationFromDB(rs.getDoor_location(), 0.0F, 0.0F).getBlock(); if (p.equals(PRESET.FLOWER)) { return b.getRelative(BlockFace.UP, 3).getData(); } else { for (BlockFace f : plugin.getGeneralKeeper().getFaces()) { if (b.getRelative(f).getType().equals(Material.WOOL)) { return b.getRelative(f).getData(); } } } } return (byte) 0; } public void setTask(int task) { this.task = task; } }