Java tutorial
/** * This file is part of JukeIt * * Copyright (C) 2011-2012 Chris Churchwell * * 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 com.chrischurchwell.jukeit.material.blocks; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.logging.Level; import org.apache.commons.lang.ArrayUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.util.Vector; import org.getspout.spoutapi.SpoutManager; import org.getspout.spoutapi.block.SpoutBlock; import org.getspout.spoutapi.inventory.SpoutItemStack; import org.getspout.spoutapi.inventory.SpoutShapedRecipe; import org.getspout.spoutapi.material.MaterialData; import org.getspout.spoutapi.material.block.GenericCustomBlock; import org.getspout.spoutapi.particle.Particle; import org.getspout.spoutapi.particle.Particle.ParticleType; import org.getspout.spoutapi.player.SpoutPlayer; import com.chrischurchwell.jukeit.JukeIt; import com.chrischurchwell.jukeit.database.DiscData; import com.chrischurchwell.jukeit.database.RPStorageData; import com.chrischurchwell.jukeit.database.RepeaterChipData; import com.chrischurchwell.jukeit.gui.recordplayer.RecordPlayerGUI; import com.chrischurchwell.jukeit.material.Blocks; import com.chrischurchwell.jukeit.material.DiscColor; import com.chrischurchwell.jukeit.material.blocks.designs.RPIndicator; import com.chrischurchwell.jukeit.material.blocks.designs.RPNeedle; import com.chrischurchwell.jukeit.material.blocks.designs.RecordPlayerDesign; import com.chrischurchwell.jukeit.material.items.BurnedDisc; import com.chrischurchwell.jukeit.permission.CraftPermissible; import com.chrischurchwell.jukeit.permission.UsePermissible; import com.chrischurchwell.jukeit.sound.Sound; import com.chrischurchwell.jukeit.sound.SoundEffect; import com.chrischurchwell.jukeit.util.Debug; //TODO This needs to be cleaned up a LOT public class RecordPlayer extends GenericCustomBlock implements WireConnector, CraftPermissible, UsePermissible { public static HashMap<String, Integer> designIds = new HashMap<String, Integer>(); public RecordPlayer() { super(JukeIt.getInstance(), "Record Player", 5); //load custom designs. int n = 0; //reverse the disc color values so that NONE is the first in the array DiscColor[] discs = DiscColor.values(); ArrayUtils.reverse(discs); for (DiscColor disc : discs) { for (RPNeedle needle : RPNeedle.values()) { for (RPIndicator indicator : RPIndicator.values()) { RecordPlayerDesign d = new RecordPlayerDesign(needle, disc, indicator); designIds.put(d.getDesignTypeId(), n); this.setBlockDesign(d, n); n++; } } } //load recipes setRecipe(); } /** * updates a block design in the world by grabbing the rp data * @param block */ public static void updateBlockDesign(SpoutBlock block) { updateBlockDesign(block, RPStorageData.getOrCreateEntry(block)); } /** * updates a block design in the world with manual rp data * @param block */ public static void updateBlockDesign(SpoutBlock block, RPStorageData data) { Debug.debug("Updating Block Design"); DiscColor disc; RPIndicator indicator; RPNeedle needle; if (data.hasDisc()) { disc = DiscColor.getByIdentifier(data.getColor()); } else { disc = DiscColor.NONE; } //get indicator info if (isPoweredUp(block)) { indicator = RPIndicator.GREEN; } else { indicator = RPIndicator.RED; } //get needle info needle = RPNeedle.getById(data.getNeedle()); //get design id String designName = RecordPlayerDesign.getDesignTypeId(needle, disc, indicator); int designId = designIds.get(designName); SpoutManager.getMaterialManager().overrideBlock(block, Blocks.recordPlayer, (byte) designId); } /** * Event fired when a player right clicks on a block. * Lots of things to do here. if theres a disc in it, the disc needs to be ejected, and if the player * is holding the right items in their hand, then those select items may be taken by this block. */ public boolean onBlockInteract(org.bukkit.World world, int x, int y, int z, SpoutPlayer player) { player.getMainScreen() .attachPopupScreen(new RecordPlayerGUI(player, (SpoutBlock) world.getBlockAt(x, y, z))); return false; } public void onBlockClicked(World world, int x, int y, int z, SpoutPlayer player) { SpoutBlock block = (SpoutBlock) world.getBlockAt(x, y, z); if (player != null) { if (!player.hasPermission(getUsePermission())) { player.sendMessage("You do not have permission to perform this action."); player.sendMessage("(" + getUsePermission() + ")"); return; } } RPStorageData rpdata = RPStorageData.getOrCreateEntry(block); if (rpdata.hasDisc() && !RPNeedle.getById(rpdata.getNeedle()).equals(RPNeedle.NONE)) { playMusic(rpdata.getUrl(), block.getLocation(), RPNeedle.getById(rpdata.getNeedle())); Location location = new Location(world, (double) x, (double) y, (double) z); long repeat = getRepeatChipTime(block); if (repeat > 0) { Debug.debug("Set to repeat in: ", repeat); RepeaterChipBlock.addRepeatToQueue(block, repeat); } } } public static boolean isPoweredUp(SpoutBlock block) { if (block.getData("recordplayer.powered") != null && ((Integer) block.getData("recordplayer.powered")) == 1) { return true; } return false; } /** * Event fires when a neighboring block updates, like a Neighboring redstone becomes powered. * We can use this to detemind if this block is now powered. */ public void onNeighborBlockChange(org.bukkit.World world, int x, int y, int z, int changedId) { Debug.debug("RecordPlayer: Neighboring Block Change Event. changedId=", changedId); SpoutBlock block = (SpoutBlock) world.getBlockAt(x, y, z); if ((block.getData("recordplayer.powered") == null || (Integer) block.getData("recordplayer.powered") == 0) && block.isBlockPowered() == true) { block.setData("recordplayer.powered", 1); Debug.debug("RecordPlayer: Redstone Activated"); updateBlockDesign(block); onBlockClicked(world, x, y, z, null); } else if (block.getData("recordplayer.powered") != null && (Integer) block.getData("recordplayer.powered") == 1 && block.isBlockPowered() == true) { Debug.debug("RecordPlayer: New Redstone Power source, but block is already powered."); } else if (block.getData("recordplayer.powered") != null && (Integer) block.getData("recordplayer.powered") == 1 && block.isBlockPowered() == false) { block.setData("recordplayer.powered", 0); Debug.debug("RecordPlayer: Lost Redstone Power."); updateBlockDesign(block); } else { block.setData("recordplayer.powered", 0); Debug.debug("RecordPlayer: Not Powered, and not powering"); } } /** * Event Fired when this block is destroyed. * Firstly, if this player has any items in it, like a record, or a needle, then those items need * to be spawned into the world. * lastly, remove the block data we have saved in the database to keep it nice and tidy. */ public void onBlockDestroyed(org.bukkit.World world, int x, int y, int z) { Block block = world.getBlockAt(x, y, z); Location spawnLoc = block.getLocation(); spawnLoc.setY(spawnLoc.getY() + 1); //get data RPStorageData rpdata = RPStorageData.getOrCreateEntry(block); //drop needle if there is one if (!RPNeedle.getById(rpdata.getNeedle()).equals(RPNeedle.NONE)) { world.dropItem(spawnLoc, new SpoutItemStack(RPNeedle.getById(rpdata.getNeedle()).getItem(), 1)); } //drop disc if there is a disc. if (rpdata.hasDisc()) { ItemStack disc = BurnedDisc.createDisc(rpdata); spawnLoc.getWorld().dropItem(spawnLoc, disc); stopMusic(block.getLocation(), RPNeedle.getById(rpdata.getNeedle())); } RPStorageData.deleteEntries(block); } public static int getRange() { return 10; } public static int getRange(Location location, RPNeedle needle) { int range = getRange(); HashMap<BlockFace, Speaker> blocks = getConnectedBlocks(location); if (blocks.size() == 1) { range = range + 20; } else if (blocks.size() > 1) { range = range + 40; } Debug.debug("Needle modifier is: ", needle.rangeModifier()); range = range + ((int) Math.floor((double) range * needle.rangeModifier())); return range; } public void playMusic(String url, Location location, RPNeedle needle) { url = JukeIt.finishIncompleteURL(url); Particle particle = new Particle(ParticleType.NOTE, location, new Vector(0, 10, 0)); particle.setMaxAge(10); particle.setGravity(1F); particle.spawn(); int range = getRange(location, needle); Debug.debug("Playing audio with range: ", range); if (!isPoweredUp((SpoutBlock) location.getBlock())) { new Sound(SoundEffect.RECORD_PLAYER_START, location, 8).play(); } //get players in radius of the jukebox and start it for only those players for (Player p : location.getWorld().getPlayers()) { double distance = location.toVector().distance(p.getLocation().toVector()); if (distance <= (double) range) { SpoutPlayer sp = SpoutManager.getPlayer(p); if (sp.isSpoutCraftEnabled()) { try { SpoutManager.getSoundManager().playCustomMusic(JukeIt.getInstance(), sp, url, true, location, range); } catch (Exception e) { //the disc has an error. SpoutManager.getSoundManager().playGlobalCustomSoundEffect(JukeIt.getInstance(), "jb_error.wav", false, location, 8); } } } } } public static void stopMusic(Location location, RPNeedle needle) { stopMusic(location, needle, true); } public static void stopMusic(Location location, RPNeedle needle, boolean playSoundEffect) { int range = getRange(location, needle); Debug.debug("Stopping audio with range: ", range); //get players in radius of the jukebox and start it for only those players for (Player p : location.getWorld().getPlayers()) { double distance = location.toVector().distance(p.getLocation().toVector()); if (distance <= (double) range) { SpoutPlayer sp = SpoutManager.getPlayer(p); if (sp.isSpoutCraftEnabled()) { SpoutManager.getSoundManager().stopMusic(sp); } } } if (playSoundEffect) { new Sound(SoundEffect.RECORD_PLAYER_STOP, location, 8).play(); } } public static long getRepeatChipTime(SpoutBlock block) { List<BlockFace> toCheck = Arrays.asList(BlockFace.SOUTH, BlockFace.WEST, BlockFace.NORTH, BlockFace.EAST); for (BlockFace face : toCheck) { if (((SpoutBlock) block.getRelative(face)).getCustomBlock() instanceof RepeaterChipBlock) { RepeaterChipData data = RepeaterChipData.getData((SpoutBlock) block.getRelative(face)); return data.getTime(); } } return 0; } public static HashMap<BlockFace, Speaker> getConnectedBlocks(Location location) { HashMap<BlockFace, Speaker> blocks = new HashMap<BlockFace, Speaker>(); Block block = location.getBlock(); Block check; //nothing can be on top //check = block.getRelative(BlockFace.UP); //if ( ((SpoutBlock)check).isCustomBlock() && ((SpoutBlock)check).getCustomBlock() instanceof Speaker ) { // blocks.put(BlockFace.UP, (Speaker)((SpoutBlock)check).getCustomBlock()); //} check = block.getRelative(BlockFace.DOWN); if (((SpoutBlock) check).getCustomBlock() != null && ((SpoutBlock) check).getCustomBlock() instanceof Speaker) { blocks.put(BlockFace.DOWN, (Speaker) ((SpoutBlock) check).getCustomBlock()); } check = block.getRelative(BlockFace.NORTH); if (((SpoutBlock) check).getCustomBlock() != null && ((SpoutBlock) check).getCustomBlock() instanceof Speaker) { blocks.put(BlockFace.NORTH, (Speaker) ((SpoutBlock) check).getCustomBlock()); } check = block.getRelative(BlockFace.SOUTH); if (((SpoutBlock) check).getCustomBlock() != null && ((SpoutBlock) check).getCustomBlock() instanceof Speaker) { blocks.put(BlockFace.SOUTH, (Speaker) ((SpoutBlock) check).getCustomBlock()); } check = block.getRelative(BlockFace.EAST); if (((SpoutBlock) check).getCustomBlock() != null && ((SpoutBlock) check).getCustomBlock() instanceof Speaker) { blocks.put(BlockFace.EAST, (Speaker) ((SpoutBlock) check).getCustomBlock()); } check = block.getRelative(BlockFace.WEST); if (((SpoutBlock) check).getCustomBlock() != null && ((SpoutBlock) check).getCustomBlock() instanceof Speaker) { blocks.put(BlockFace.WEST, (Speaker) ((SpoutBlock) check).getCustomBlock()); } return blocks; } @Override public String getCraftPermission() { return "jukeit.craft.recordplayer"; } @Override public String getUsePermission() { return "jukeit.use.recordplayer"; } public void setRecipe() { SpoutShapedRecipe r = new SpoutShapedRecipe(new SpoutItemStack(this, 1)); r.shape("sps", "njn", "www"); r.setIngredient('s', MaterialData.oakWoodSlab); r.setIngredient('p', MaterialData.stonePressurePlate); r.setIngredient('n', Blocks.speaker); r.setIngredient('j', MaterialData.jukebox); r.setIngredient('w', MaterialData.wood); SpoutManager.getMaterialManager().registerSpoutRecipe(r); } }