From cbd5e3524ffc66431c603f9d7a7be1029bf48235 Mon Sep 17 00:00:00 2001 From: cnaude Date: Fri, 9 Nov 2012 08:35:04 -0700 Subject: [PATCH] Updates for 1.4.2. --- src/config.yml | 30 +++ src/net/spoothie/chairs/Chairs.java | 88 ++++++++ src/net/spoothie/chairs/EventListener.java | 232 +++++++++++++++++++++ src/plugin.yml | 9 + 4 files changed, 359 insertions(+) create mode 100644 src/config.yml create mode 100644 src/net/spoothie/chairs/Chairs.java create mode 100644 src/net/spoothie/chairs/EventListener.java create mode 100644 src/plugin.yml diff --git a/src/config.yml b/src/config.yml new file mode 100644 index 0000000..f1a6efa --- /dev/null +++ b/src/config.yml @@ -0,0 +1,30 @@ +# Configuration of the Chairs plugin for Craftbukkit +# ------ +# A list of all compatible block and item names: http://bit.ly/AmJgMb. +# ------ +# allowed-blocks: Set the blocks you want to be able to sit down on. Currently, only stairs-blocks are working. +# item: Set the item you want to sit on (default is LEVER, because it is quite small so that you can't really see it). +# auto-rotate: If set to true, you are automatically rotated to the descending face of the stairs-block when sitting down. +# sneaking: If set to true, you have to sneak to sit down on a chair. +# max-chair-width: Define how many blocks a chair can be long (set to number <= 0 for unlimited width). +# sign-check: If set to true, you will only be able to sit down when there are signs on both of the ends of the chair. +# distance: The maximum distance between the chair (the center of the block) and the player to be able to sit down (to prevent glitching through walls, etc.). +# sitting-height: Set how high you are sitting 'in' the stairs block (default is 0.7). +# ------ +allowed-blocks: + - WOOD_STAIRS + - SPRUCE_WOOD_STAIRS + - JUNGLE_WOOD_STAIRS + - BIRCH_WOOD_STAIRS + - SANDSTONE_STAIRS + - COBBLESTONE_STAIRS + - BRICK_STAIRS + - SMOOTH_STAIRS + - NETHER_BRICK_STAIRS +item: LEVER +auto-rotate: true +sneaking: true +max-chair-width: 3 +sign-check: false +distance: 2 +sitting-height: 0.7 \ No newline at end of file diff --git a/src/net/spoothie/chairs/Chairs.java b/src/net/spoothie/chairs/Chairs.java new file mode 100644 index 0000000..0062e8b --- /dev/null +++ b/src/net/spoothie/chairs/Chairs.java @@ -0,0 +1,88 @@ +package net.spoothie.chairs; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import org.bukkit.Material; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; + +public class Chairs extends JavaPlugin { + + public List allowedBlocks = new ArrayList(); + public Material item; + public boolean sneaking, autorotate, signcheck; + public double sittingheight, distance; + public int maxchairwidth; + private File pluginFolder; + private File configFile; + + @Override + public void onEnable() { + pluginFolder = getDataFolder(); + configFile = new File(pluginFolder, "config.yml"); + createConfig(); + this.getConfig().options().copyDefaults(true); + saveConfig(); + loadConfig(); + EventListener eventListener = new EventListener(this); + getServer().getPluginManager().registerEvents(eventListener, this); + } + + @Override + public void onDisable() { + } + + private void createConfig() { + if (!pluginFolder.exists()) { + try { + pluginFolder.mkdir(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (!configFile.exists()) { + try { + configFile.createNewFile(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private void loadConfig() { + item = Material.getMaterial(getConfig().getString("item")); + autorotate = getConfig().getBoolean("auto-rotate"); + sneaking = getConfig().getBoolean("sneaking"); + signcheck = getConfig().getBoolean("sign-check"); + sittingheight = getConfig().getDouble("sitting-height"); + distance = getConfig().getDouble("distance"); + maxchairwidth = getConfig().getInt("max-chair-width"); + + for (String type : getConfig().getStringList("allowed-blocks")) { + allowedBlocks.add(Material.getMaterial(type)); + } + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (command.getName().equalsIgnoreCase("chairs")) { + if (sender instanceof Player && !((Player) sender).hasPermission("chairs.reload")) { + return true; + } + + if (args.length > 0 && args[0].equalsIgnoreCase("reload")) { + reloadConfig(); + loadConfig(); + sender.sendMessage("Chairs configuration file reloaded."); + } else { + sender.sendMessage("Use '/chairs reload' to reload the configuration file."); + } + } + + return true; + } +} diff --git a/src/net/spoothie/chairs/EventListener.java b/src/net/spoothie/chairs/EventListener.java new file mode 100644 index 0000000..aad3857 --- /dev/null +++ b/src/net/spoothie/chairs/EventListener.java @@ -0,0 +1,232 @@ +package net.spoothie.chairs; + +import java.util.ArrayList; +import java.util.List; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.event.Event.Result; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.material.Stairs; +import org.bukkit.util.Vector; + +public class EventListener implements Listener { + + public Chairs plugin; + + public EventListener(Chairs plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.hasBlock() && event.getAction() == Action.RIGHT_CLICK_BLOCK) { + Block block = event.getClickedBlock(); + //event.getPlayer().sendMessage("Block: " + block.getType()); + if (plugin.allowedBlocks.contains(block.getType())) { + Player player = event.getPlayer(); + Stairs stairs = (Stairs) block.getState().getData(); + int chairwidth = 1; + + // Check if block beneath chair is solid. + if (block.getRelative(BlockFace.DOWN).getType() == Material.AIR) { + return; + } + if (block.getRelative(BlockFace.DOWN).getType() == Material.WATER) { + return; + } + if (block.getRelative(BlockFace.DOWN).getType() == Material.LAVA) { + return; + } + if (!net.minecraft.server.Block.byId[block.getTypeId()].material.isSolid()) { + return; + } + + // Permissions Check + if (!player.hasPermission("chairs.sit")) { + return; + } + + // Check if player is sitting. + if (!player.isSneaking() && player.getVehicle() != null) { + player.getVehicle().remove(); + return; + } + + // Check for distance distance between player and chair. + if (plugin.distance > 0 && player.getLocation().distance(block.getLocation().add(0.5, 0, 0.5)) > plugin.distance) { + return; + } + + // Check for signs. + if (plugin.signcheck == true) { + boolean sign1 = false; + boolean sign2 = false; + + if (stairs.getDescendingDirection() == BlockFace.NORTH || stairs.getDescendingDirection() == BlockFace.SOUTH) { + sign1 = checkSign(block, BlockFace.EAST); + sign2 = checkSign(block, BlockFace.WEST); + } else if (stairs.getDescendingDirection() == BlockFace.EAST || stairs.getDescendingDirection() == BlockFace.WEST) { + sign1 = checkSign(block, BlockFace.NORTH); + sign2 = checkSign(block, BlockFace.SOUTH); + } + + if (!(sign1 == true && sign2 == true)) { + return; + } + } + + // Check for maximal chair width. + if (plugin.maxchairwidth > 0) { + if (stairs.getDescendingDirection() == BlockFace.NORTH || stairs.getDescendingDirection() == BlockFace.SOUTH) { + chairwidth += getChairWidth(block, BlockFace.EAST); + chairwidth += getChairWidth(block, BlockFace.WEST); + } else if (stairs.getDescendingDirection() == BlockFace.EAST || stairs.getDescendingDirection() == BlockFace.WEST) { + chairwidth += getChairWidth(block, BlockFace.NORTH); + chairwidth += getChairWidth(block, BlockFace.SOUTH); + } + + if (chairwidth > plugin.maxchairwidth) { + return; + } + } + + // Sit-down process. + if (plugin.sneaking == false || (plugin.sneaking == true && event.getPlayer().isSneaking())) { + if (player.getVehicle() != null) { + player.getVehicle().remove(); + } + + Item drop = dropSeat(block); + List drops = checkChair(drop); + + if (drops != null) { + drop.remove(); + return; + } + + // Rotate the player's view to the descending side of the block. + if (plugin.autorotate == true) { + Location plocation = player.getLocation(); + + switch (stairs.getDescendingDirection()) { + case NORTH: + plocation.setYaw(90); + break; + case EAST: + plocation.setYaw(180); + break; + case SOUTH: + plocation.setYaw(270); + break; + case WEST: + plocation.setYaw(0); + } + + player.teleport(plocation); + } + + // Changing the drop material is only necessary for the item merge feature of CB++ + // The client won't update the material, though. + drop.setItemStack(new ItemStack(Material.PUMPKIN_STEM)); + drop.setPassenger(player); + + // Cancel BlockPlaceEvent Result, if player is rightclicking with a block in his hand. + event.setUseInteractedBlock(Result.DENY); + } + } + } + } + + @EventHandler + public void onBlockBreak(BlockBreakEvent event) { + if (plugin.allowedBlocks.contains(event.getBlock().getType())) { + Item drop = dropSeat(event.getBlock()); + + for (Entity e : drop.getNearbyEntities(0.2, 0.2, 0.2)) { + if (e != null && e instanceof Item && e.getPassenger() != null) { + e.remove(); + } + } + + drop.remove(); + } + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + Entity vehicle = event.getPlayer().getVehicle(); + + // Let players stand up when leaving the server. + if (vehicle != null && vehicle instanceof Item) { + vehicle.remove(); + } + } + + private Item dropSeat(Block chair) { + Location location = chair.getLocation().add(0.5, (plugin.sittingheight - 0.5), 0.5); + Item drop = location.getWorld().dropItemNaturally(location, new ItemStack(plugin.item)); + drop.setPickupDelay(Integer.MAX_VALUE); + drop.teleport(location); + drop.setVelocity(new Vector(0, 0, 0)); + return drop; + } + + private List checkChair(Item drop) { + List drops = new ArrayList(); + + // Check for already existing chair items. + for (Entity e : drop.getNearbyEntities(0.2, 0.2, 0.2)) { + if (e != null && e instanceof Item && e.getPassenger() != null) { + drops.add(drop); + } + } + + if (drops.isEmpty() == false) { + return drops; + } + + return null; + } + + private int getChairWidth(Block block, BlockFace face) { + int width = 0; + + // Go through the blocks next to the clicked block and check if there are any further stairs. + for (int i = 1; i <= plugin.maxchairwidth; i++) { + Block relative = block.getRelative(face, i); + + if (plugin.allowedBlocks.contains(relative.getType()) && ((Stairs) relative.getState().getData()).getDescendingDirection() == ((Stairs) block.getState().getData()).getDescendingDirection()) { + width++; + } else { + break; + } + } + + return width; + } + + private boolean checkSign(Block block, BlockFace face) { + // Go through the blocks next to the clicked block and check if are signs on the end. + for (int i = 1; true; i++) { + Block relative = block.getRelative(face, i); + if (!plugin.allowedBlocks.contains(relative.getType()) || (block instanceof Stairs && ((Stairs) relative.getState().getData()).getDescendingDirection() != ((Stairs) block.getState().getData()).getDescendingDirection())) { + if (relative.getType() == Material.SIGN || relative.getType() == Material.WALL_SIGN || relative.getType() == Material.SIGN_POST) { + return true; + } else { + return false; + } + } + } + } +} \ No newline at end of file diff --git a/src/plugin.yml b/src/plugin.yml new file mode 100644 index 0000000..f857a02 --- /dev/null +++ b/src/plugin.yml @@ -0,0 +1,9 @@ +name: Chairs +version: 1.5a +description: Let players sit on stairs and slabs. +author: spoothie +main: net.spoothie.chairs.Chairs +commands: + chairs: + description: Reloads the Chairs configuration file. + usage: /chairs reload \ No newline at end of file