commit 2692f76dc26f4d02d7668e205da635987f37410a
parent f3f641aa7c315240672545c824c3524764dd71b7
Author: typable <contact@typable.dev>
Date: Tue, 10 Jan 2023 16:55:54 +0100
Organized code and removed unused imports
Diffstat:
21 files changed, 1572 insertions(+), 1564 deletions(-)
diff --git a/README.md b/README.md
@@ -1,5 +1,5 @@
-# minecraft-hub
-A Minecraft Server Management Plugin
+# poppy
+A Minecraft server management plugin
### Export as JAR file
diff --git a/hook.sh b/hook.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+cd /home/andreas/git/poppy
+
+git --git-dir=../poppy/.git --work-tree=../poppy pull origin main
+
+/opt/gradle/gradle-7.6/bin/gradle build
+
+cp build/libs/poppy.jar /srv/minecraft/plugins/
diff --git a/res/plugin.yml b/res/plugin.yml
@@ -1,7 +1,7 @@
-main: de.typable.minecrafthub.Main
-name: MinecraftHub
+main: poppy.Main
+name: poppy
version: 0.0.1
-author: typable
+author: typable, chunksize
api-version: 1.16
commands:
head:
@@ -10,7 +10,7 @@ commands:
spawn:
usage: /spawn
invsee:
- usage: /invsee <name> <enderchest>
+ usage: /invsee <name>
sethome:
home:
setwarp:
diff --git a/src/de/typable/minecrafthub/Main.java b/src/de/typable/minecrafthub/Main.java
@@ -1,301 +0,0 @@
-package de.typable.minecrafthub;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.BindException;
-import java.net.ServerSocket;
-import java.net.Socket;
-
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.GameMode;
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.World;
-import org.bukkit.WorldCreator;
-import org.bukkit.WorldType;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.meta.SkullMeta;
-import org.bukkit.inventory.meta.BookMeta;
-import org.bukkit.material.Tree;
-import org.bukkit.plugin.Plugin;
-import org.bukkit.plugin.PluginManager;
-import org.bukkit.plugin.java.JavaPlugin;
-
-import de.typable.minecrafthub.constant.Constants;
-import de.typable.minecrafthub.event.AutoWorkbenchListener;
-import de.typable.minecrafthub.event.ChairListener;
-import de.typable.minecrafthub.event.DoubleDoorListener;
-import de.typable.minecrafthub.event.EventListener;
-import de.typable.minecrafthub.event.LeavesDecayListener;
-import de.typable.minecrafthub.util.Util;
-import de.typable.minecrafthub.config.Config;
-
-
-public class Main extends JavaPlugin
-{
- private PluginManager pluginManager;
- private DoubleDoorListener doubleDoorListener;
- private ChairListener chairListener;
- private AutoWorkbenchListener autoWorkbenchListener;
- private LeavesDecayListener leavesDecayListener;
- private EventListener eventListener;
-
- private Plugin plugin;
- private Config config;
-
- @Override
- public void onEnable()
- {
- plugin = this;
- config = new Config("config/minecraft-hub.yml");
-
- pluginManager = Bukkit.getPluginManager();
-
- doubleDoorListener = new DoubleDoorListener();
- pluginManager.registerEvents(doubleDoorListener, this);
-
- chairListener = new ChairListener();
- pluginManager.registerEvents(chairListener, this);
-
- autoWorkbenchListener = new AutoWorkbenchListener();
- pluginManager.registerEvents(autoWorkbenchListener, this);
-
- leavesDecayListener = new LeavesDecayListener(this);
- pluginManager.registerEvents(leavesDecayListener, this);
-
- eventListener = new EventListener();
- pluginManager.registerEvents(eventListener, this);
- }
-
- @Override
- public void onDisable()
- {
- chairListener.onDisable();
- }
-
- @Override
- public boolean onCommand(CommandSender sender, Command command, String label, String[] args)
- {
- if(sender instanceof Player)
- {
- Player player = (Player) sender;
-
- switch(label)
- {
- case "head":
- return setItemAsHead(player, args);
- case "skull":
- return getSkullForName(player, args);
- case "invsee":
- return openInventoryForPlayer(player, args);
- case "info":
- return openInfoBook(player, args);
- case "spawn":
- return teleportToSpawn(player, args);
- case "home":
- return teleportToHome(player, args);
- case "warp":
- return teleportToWarppoint(player, args);
- case "sethome":
- return setHome(player, args);
- case "setwarp":
- return addWarppoint(player, args);
- default:
- return false;
- }
- }
-
- return true;
- }
-
- private boolean setItemAsHead(final Player player, final String[] args)
- {
- final ItemStack item = player.getInventory().getItemInMainHand();
- final ItemStack head = player.getInventory().getHelmet();
-
- player.getInventory().setHelmet(item);
- player.getInventory().setItemInMainHand((new ItemStack(Material.AIR)));
-
- if(player.getGameMode() == GameMode.SURVIVAL)
- {
- if(head != null)
- {
- player.getInventory().addItem(head);
- }
- }
-
- return true;
- }
-
- @SuppressWarnings("deprecation")
- private boolean getSkullForName(final Player player, final String[] args)
- {
- if(!player.isOp())
- {
- player.sendMessage(Constants.Messages.NOT_ENOUGH_PERMISSION);
- return true;
- }
-
- if(args.length != 1)
- {
- return false;
- }
-
- final String name = args[0];
- final ItemStack skull = new ItemStack(Material.PLAYER_HEAD);
- final SkullMeta meta = (SkullMeta) skull.getItemMeta();
- meta.setOwner(name);
- skull.setItemMeta(meta);
-
- player.getInventory().addItem(skull);
-
- return true;
- }
-
- private boolean openInventoryForPlayer(final Player player, final String[] args)
- {
- if(args.length == 0)
- {
- return false;
- }
-
- if(!player.isOp())
- {
- player.sendMessage(Constants.Messages.NOT_ENOUGH_PERMISSION);
- return true;
- }
-
- final Player target = Bukkit.getPlayer(args[0]);
-
- if(target == null)
- {
- player.sendMessage(ChatColor.RED + "Player not found!");
- return true;
- }
-
- player.openInventory(target.getInventory());
-
- return true;
- }
-
- private boolean openInfoBook(final Player player, final String[] args)
- {
- final ItemStack book = new ItemStack(Material.WRITTEN_BOOK);
- final BookMeta meta = (BookMeta) book.getItemMeta();
- meta.setTitle("Info");
- meta.setAuthor("Server");
- meta.setPages(config.getInfoPages());
- book.setItemMeta(meta);
-
- player.openBook(book);
-
- return true;
- }
-
- private boolean teleportToSpawn(final Player player, final String[] args)
- {
- final Location location = Bukkit.getWorld("world").getSpawnLocation();
-
- if(Util.travelTo(plugin, player, location))
- {
- player.sendMessage(ChatColor.GRAY + "You've been teleported to spawn.");
- }
-
- return true;
- }
-
- private boolean teleportToHome(final Player player, final String[] args)
- {
- final Location location = config.getHome(player);
-
- if(location == null)
- {
- player.sendMessage(ChatColor.RED + "You've don't have a home point.");
- return true;
- }
-
- if(Util.travelTo(plugin, player, location))
- {
- player.sendMessage(ChatColor.GRAY + "You've been teleported to your home.");
- }
-
- return true;
- }
-
- private boolean teleportToWarppoint(final Player player, final String[] args)
- {
- if(args.length != 1)
- {
- return false;
- }
-
- final String name = args[0];
- final Location location = config.getWarp(name);
-
- if(location == null)
- {
- player.sendMessage(ChatColor.RED + "Warp point " + name + " doesn't exist!");
- return true;
- }
-
- if(Util.travelTo(plugin, player, location))
- {
- player.sendMessage(ChatColor.GRAY + "You've been teleported to warp point " + name + ".");
- }
-
- return true;
- }
-
- private boolean setHome(final Player player, final String[] args)
- {
- try
- {
- config.setHome(player);
- player.sendMessage(ChatColor.YELLOW + "Home point set.");
- }
- catch(Exception ex)
- {
- player.sendMessage(Constants.Messages.FAILED_TO_SAVE_CONFIG_FILE);
- }
-
- return true;
- }
-
- private boolean addWarppoint(final Player player, final String[] args)
- {
- if(args.length != 1)
- {
- return false;
- }
-
- final String name = args[0];
-
- if(!Util.payFee(player, Material.COMPASS, 1))
- {
- player.sendMessage(ChatColor.RED + "The fee for creating a warp point is 1 compass!");
- return true;
- }
-
- try
- {
- if(!config.setWarp(name, player.getLocation()))
- {
- player.sendMessage(ChatColor.RED + "Warp point " + name + " already exists!");
- return true;
- }
-
- player.sendMessage(ChatColor.YELLOW + "Warp point " + name + " set.");
- }
- catch(Exception ex)
- {
- player.sendMessage(Constants.Messages.FAILED_TO_SAVE_CONFIG_FILE);
- }
-
- return true;
- }
-
-}
diff --git a/src/de/typable/minecrafthub/config/Config.java b/src/de/typable/minecrafthub/config/Config.java
@@ -1,86 +0,0 @@
-package de.typable.minecrafthub.config;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-import java.util.ArrayList;
-
-import org.bukkit.configuration.file.FileConfiguration;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.bukkit.entity.Player;
-import org.bukkit.Location;
-
-import de.typable.minecrafthub.util.Util;
-
-public class Config
-{
- private File file;
- private FileConfiguration configuration;
-
- public Config(final String path)
- {
- this.file = new File(path);
- this.configuration = YamlConfiguration.loadConfiguration(this.file);
- }
-
- public void setHome(final Player player) throws IOException
- {
- final String path = "home." + player.getDisplayName();
- final Location location = Util.calcBlockCenter(player.getLocation());
-
- this.configuration.set(path, location);
- this.configuration.save(this.file);
- }
-
- public Location getHome(final Player player)
- {
- final String path = "home." + player.getDisplayName();
-
- return this.configuration.getLocation(path);
- }
-
- public boolean setWarp(final String name, final Location location) throws IOException
- {
- final String path = "warp." + name;
-
- if(this.configuration.getLocation(path) != null)
- {
- return false;
- }
-
- this.configuration.set(path, Util.calcBlockCenter(location));
- this.configuration.save(this.file);
-
- return true;
- }
-
- public Location getWarp(final String name)
- {
- final String path = "warp." + name;
-
- return this.configuration.getLocation(path);
- }
-
- public List<String> getInfoPages()
- {
- final String path = "info";
- List<String> pages = null;
-
- try
- {
- this.configuration.load(this.file);
- pages = (List<String>) this.configuration.getList(path);
- }
- catch(Exception ex)
- {
- // ignore
- }
-
- if(pages == null)
- {
- pages = new ArrayList<>();
- }
-
- return pages;
- }
-}
diff --git a/src/de/typable/minecrafthub/constant/Constants.java b/src/de/typable/minecrafthub/constant/Constants.java
@@ -1,19 +0,0 @@
-package de.typable.minecrafthub.constant;
-
-import org.bukkit.ChatColor;
-
-
-public class Constants
-{
- public static final long TICK = 20;
- public static final int BLOCKS_PER_CHUNK = 16;
- public static final int CHUNKS_PER_EMERALD = 25;
- public static final int MIN_FEE = 1;
- public static final int MAX_FEE = 64;
-
- public static final class Messages
- {
- public static final String NOT_ENOUGH_PERMISSION = ChatColor.RED + "You don't have enough Permission to perform this command!";
- public static final String FAILED_TO_SAVE_CONFIG_FILE = ChatColor.RED + "Failed to save changes!";
- }
-}
diff --git a/src/de/typable/minecrafthub/event/AutoWorkbenchListener.java b/src/de/typable/minecrafthub/event/AutoWorkbenchListener.java
@@ -1,241 +0,0 @@
-package de.typable.minecrafthub.event;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-
-import org.bukkit.Bukkit;
-import org.bukkit.block.Block;
-import org.bukkit.block.BlockFace;
-import org.bukkit.block.Dropper;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.ItemFrame;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.inventory.InventoryMoveItemEvent;
-import org.bukkit.inventory.Inventory;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.Recipe;
-import org.bukkit.inventory.ShapedRecipe;
-import org.bukkit.inventory.ShapelessRecipe;
-
-import de.typable.minecrafthub.util.Util;
-
-
-public class AutoWorkbenchListener implements Listener
-{
- @EventHandler
- public void onItemMove(InventoryMoveItemEvent event)
- {
- Inventory source = event.getSource();
- Inventory target = event.getDestination();
-
- if(source.getHolder() instanceof Dropper)
- {
- Dropper dropper = (Dropper) source.getHolder();
-
- ItemFrame frame = getItemFrame(dropper.getBlock());
-
- if(frame == null)
- {
- return;
- }
-
- ItemStack item = frame.getItem();
-
- Recipe recipe = getCraftingRecipe(item, source, target);
-
- if(recipe != null)
- {
- if(recipe instanceof ShapelessRecipe)
- {
- ShapelessRecipe shapless = (ShapelessRecipe) recipe;
-
- target.addItem(shapless.getResult());
- }
-
- if(recipe instanceof ShapedRecipe)
- {
- ShapedRecipe shaped = (ShapedRecipe) recipe;
-
- target.addItem(shaped.getResult());
- }
- }
-
- event.setCancelled(true);
- }
- }
-
- private Recipe getCraftingRecipe(ItemStack item, Inventory source, Inventory target)
- {
- if(Util.isEmpty(item))
- {
- return null;
- }
-
- Iterator<Recipe> iterator = Bukkit.recipeIterator();
-
- while(iterator.hasNext())
- {
- Recipe recipe = iterator.next();
-
- if(Util.compare(item, recipe.getResult()))
- {
- List<ItemStack> ingredients = null;
-
- if(recipe instanceof ShapelessRecipe)
- {
- ShapelessRecipe shapless = (ShapelessRecipe) recipe;
-
- ingredients = shapless.getIngredientList();
- }
-
- if(recipe instanceof ShapedRecipe)
- {
- ShapedRecipe shaped = (ShapedRecipe) recipe;
-
- ingredients = new ArrayList<>();
-
- for(ItemStack value : shaped.getIngredientMap().values())
- {
- if(ingredients.isEmpty())
- {
- if(!Util.isEmpty(value))
- {
- ingredients.add(value);
- }
- }
- else
- {
- appendUniqueIngredient(ingredients, value);
- }
- }
- }
-
- if(ingredients == null)
- {
- continue;
- }
-
- if(!hasIngredients(source, ingredients))
- {
- continue;
- }
-
- if(Util.isInventoryFull(target, recipe.getResult()))
- {
- return null;
- }
-
- removeIngredients(ingredients, source);
-
- return recipe;
- }
- }
-
- return null;
- }
-
- private void removeIngredients(List<ItemStack> ingredients, Inventory inventory)
- {
- for(ItemStack ingredient : ingredients)
- {
- if(Util.isEmpty(ingredient))
- {
- continue;
- }
-
- int amount = ingredient.getAmount();
-
- ListIterator<ItemStack> iterator = inventory.iterator();
-
- while(iterator.hasNext())
- {
- ItemStack item = iterator.next();
-
- if(Util.isEmpty(item))
- {
- continue;
- }
-
- if(Util.compare(item, ingredient))
- {
- if(item.getAmount() > amount)
- {
- item.setAmount(item.getAmount() - amount);
- amount = 0;
-
- break;
- }
-
- if(item.getAmount() == amount)
- {
- amount = 0;
- inventory.removeItem(item);
-
- break;
- }
-
- if(item.getAmount() < amount)
- {
- amount -= item.getAmount();
- inventory.removeItem(item);
- }
- }
- }
- }
- }
-
- private void appendUniqueIngredient(List<ItemStack> ingredients, ItemStack item)
- {
- for(ItemStack ingredient : ingredients)
- {
- if(Util.compare(item, ingredient))
- {
- ingredient.setAmount(ingredient.getAmount() + item.getAmount());
-
- return;
- }
- }
-
- if(!Util.isEmpty(item))
- {
- ingredients.add(item);
- }
- }
-
- private boolean hasIngredients(Inventory inventory, List<ItemStack> ingredients)
- {
- for(ItemStack ingredient : ingredients)
- {
- if(ingredient != null && !Util.containsAtLeast(inventory, ingredient, ingredient.getAmount()))
- {
- return false;
- }
- }
-
- return true;
- }
-
- private ItemFrame getItemFrame(Block block)
- {
- for(Entity entity : block.getWorld().getNearbyEntities(block.getLocation(), 2, 2, 2))
- {
- if(entity instanceof ItemFrame)
- {
- ItemFrame frame = (ItemFrame) entity;
-
- if(frame.getFacing() == BlockFace.UP)
- {
- if(block.getLocation().add(0.5, 1.03125, 0.5).distance(frame.getLocation()) < 0.2D)
- {
- return frame;
- }
- }
- }
- }
-
- return null;
- }
-}
diff --git a/src/de/typable/minecrafthub/event/ChairListener.java b/src/de/typable/minecrafthub/event/ChairListener.java
@@ -1,215 +0,0 @@
-package de.typable.minecrafthub.event;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.block.Block;
-import org.bukkit.block.data.Bisected.Half;
-import org.bukkit.block.data.type.Stairs;
-import org.bukkit.entity.ArmorStand;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.EntityType;
-import org.bukkit.entity.Player;
-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.util.Vector;
-import org.spigotmc.event.entity.EntityDismountEvent;
-
-import de.typable.minecrafthub.util.Util;
-
-
-public class ChairListener implements Listener
-{
- private static final Material[] CHAIR_TYPE = new Material[]
- {
- Material.OAK_STAIRS,
- Material.SPRUCE_STAIRS,
- Material.BIRCH_STAIRS,
- Material.JUNGLE_STAIRS,
- Material.ACACIA_STAIRS,
- Material.DARK_OAK_STAIRS,
- Material.ACACIA_STAIRS,
- Material.CRIMSON_STAIRS,
- Material.WARPED_STAIRS
- };
-
- private Map<Block, ArmorStand> blockMap = new HashMap<>();
-
- public void onDisable()
- {
- for(ArmorStand armorStand : blockMap.values())
- {
- armorStand.eject();
- armorStand.remove();
- }
- }
-
- @EventHandler
- public void onPlayerInteract(PlayerInteractEvent event)
- {
- Player player = event.getPlayer();
-
- if(event.getAction() == Action.RIGHT_CLICK_BLOCK)
- {
- if(event.getClickedBlock() != null && !event.getPlayer().isSneaking())
- {
- Block block = event.getClickedBlock();
-
- if(isChair(block.getType()))
- {
- if(!isInRange(block, player))
- {
- return;
- }
-
- if(blockMap.containsKey(block))
- {
- return;
- }
-
- if(isCompatible(block))
- {
- ArmorStand armorStand = createMountableChair(block, player);
-
- if(armorStand == null)
- {
- return;
- }
-
- event.setCancelled(true);
-
- blockMap.put(block, armorStand);
- }
- }
- }
- }
- }
-
- @EventHandler
- public void onEntityDismount(EntityDismountEvent event)
- {
- if(event.getEntity() instanceof Player)
- {
- Entity entity = event.getDismounted();
-
- if(entity != null && entity instanceof ArmorStand)
- {
- if(blockMap.containsValue(entity))
- {
- for(Entry<Block, ArmorStand> entry : blockMap.entrySet())
- {
- if(entry.getValue() == entity)
- {
- blockMap.remove(entry.getKey());
-
- break;
- }
- }
- }
-
- Location location = entity.getLocation();
- location.add(0, 1, 0);
-
- for(Entity passenger : entity.getPassengers()) {
- location.setPitch(passenger.getLocation().getPitch());
- location.setYaw(passenger.getLocation().getYaw());
- passenger.teleport(location);
- }
-
- entity.remove();
- }
- }
- }
-
- @EventHandler
- public void onBlockBreak(BlockBreakEvent event)
- {
- Block block = event.getBlock();
-
- if(blockMap.containsKey(block))
- {
- ArmorStand armorStand = blockMap.get(block);
- armorStand.eject();
-
- blockMap.remove(block);
- }
- }
-
- private boolean isInRange(Block block, Player player)
- {
- return block.getLocation().add(0.5, 0.5, 0.5).distance(player.getLocation()) <= 2;
- }
-
- private boolean isChair(Material material)
- {
- for(Material chair : CHAIR_TYPE)
- {
- if(material == chair)
- {
- return true;
- }
- }
-
- return false;
- }
-
- private boolean isCompatible(Block block)
- {
- Block upperBlock = block.getWorld().getBlockAt(block.getLocation().add(0, 1, 0));
-
- if(!Util.isAir(upperBlock.getType()))
- {
- return false;
- }
-
- Stairs stairs = (Stairs) block.getState().getBlockData();
-
- if(stairs.getHalf() != Half.BOTTOM)
- {
- return false;
- }
-
- if(stairs.isWaterlogged())
- {
- return false;
- }
-
- if(stairs.getShape() == Stairs.Shape.INNER_RIGHT || stairs.getShape() == Stairs.Shape.INNER_LEFT)
- {
- return false;
- }
-
- return true;
- }
-
- @SuppressWarnings("deprecation")
- private ArmorStand createMountableChair(Block block, Player player)
- {
- Stairs stairs = (Stairs) block.getState().getBlockData();
-
- Float yaw = Util.convertFacingToYaw(stairs.getFacing());
-
- if(yaw == null)
- {
- return null;
- }
-
- Location location = block.getLocation().add(0.5, -0.4, 0.5);
- location.setYaw(yaw);
-
- ArmorStand armorStand = (ArmorStand) block.getWorld().spawnEntity(location, EntityType.ARMOR_STAND);
- armorStand.setPassenger((Entity) player);
- armorStand.setSmall(true);
- armorStand.setGravity(false);
- armorStand.setInvulnerable(true);
- armorStand.setVisible(false);
-
- return armorStand;
- }
-}
diff --git a/src/de/typable/minecrafthub/event/DoubleDoorListener.java b/src/de/typable/minecrafthub/event/DoubleDoorListener.java
@@ -1,152 +0,0 @@
-package de.typable.minecrafthub.event;
-
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.Sound;
-import org.bukkit.block.Block;
-import org.bukkit.block.BlockState;
-import org.bukkit.block.data.type.Door;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.block.Action;
-import org.bukkit.event.player.PlayerInteractEvent;
-
-import de.typable.minecrafthub.util.Util;
-
-
-public class DoubleDoorListener implements Listener
-{
- private static final Material[] DOOR_TYPE = new Material[] { Material.OAK_DOOR, Material.SPRUCE_DOOR, Material.BIRCH_DOOR, Material.JUNGLE_DOOR, Material.ACACIA_DOOR, Material.DARK_OAK_DOOR, Material.ACACIA_DOOR, Material.CRIMSON_DOOR, Material.WARPED_DOOR };
-
- @EventHandler
- public void onPlayerInteract(PlayerInteractEvent event)
- {
- Player player = event.getPlayer();
-
- if(event.getAction() == Action.RIGHT_CLICK_BLOCK)
- {
- if(event.getClickedBlock() != null)
- {
- Block block = event.getClickedBlock();
-
- if(isDoor(block.getType()))
- {
- if(player.isSneaking())
- {
- if(!Util.isEmpty(player.getInventory().getItemInMainHand()))
- {
- return;
- }
-
- if(!Util.isEmpty(player.getInventory().getItemInOffHand()))
- {
- return;
- }
- }
-
- BlockState state = block.getState();
- Door door = (Door) state.getBlockData();
-
- Location location = getOppositeDoor(door, block.getLocation());
-
- if(location == null)
- {
- return;
- }
-
- Block opposite = block.getWorld().getBlockAt(location);
-
- if(block.getType() != opposite.getType())
- {
- return;
- }
-
- BlockState stateOpposite = opposite.getState();
- Door doorOpposite = (Door) stateOpposite.getBlockData();
-
- if(isCompatible(door, doorOpposite))
- {
- if(door.isOpen() && doorOpposite.isOpen())
- {
- doorOpposite.setOpen(false);
-
- stateOpposite.setBlockData(doorOpposite);
- stateOpposite.update();
-
- player.playSound(player.getLocation(), Sound.BLOCK_WOODEN_DOOR_CLOSE, 1F, 1F);
- }
-
- if(!door.isOpen() && !doorOpposite.isOpen())
- {
- doorOpposite.setOpen(true);
-
- stateOpposite.setBlockData(doorOpposite);
- stateOpposite.update();
-
- player.playSound(player.getLocation(), Sound.BLOCK_WOODEN_DOOR_OPEN, 1F, 1F);
- }
- }
- }
- }
- }
- }
-
- private boolean isDoor(Material material)
- {
- for(Material door : DOOR_TYPE)
- {
- if(material == door)
- {
- return true;
- }
- }
-
- return false;
- }
-
- private Location getOppositeDoor(Door door, Location location)
- {
- int invert = door.getHinge() == Door.Hinge.LEFT ? 1 : -1;
-
- switch(door.getFacing())
- {
- case NORTH:
- location.add(1 * invert, 0, 0);
- break;
- case EAST:
- location.add(0, 0, 1 * invert);
- break;
- case SOUTH:
- location.add(-1 * invert, 0, 0);
- break;
- case WEST:
- location.add(0, 0, -1 * invert);
- break;
- default:
- return null;
- }
-
- return location;
- }
-
- private boolean isCompatible(Door door, Door doorItem)
- {
- if(door.getFacing() != doorItem.getFacing())
- {
- return false;
- }
-
- if(door.getHalf() != doorItem.getHalf())
- {
- return false;
- }
-
- if(door.getHinge() == doorItem.getHinge())
- {
- return false;
- }
-
- return true;
- }
-}
diff --git a/src/de/typable/minecrafthub/event/EventListener.java b/src/de/typable/minecrafthub/event/EventListener.java
@@ -1,180 +0,0 @@
-package de.typable.minecrafthub.event;
-
-import org.bukkit.ChatColor;
-import org.bukkit.Material;
-import org.bukkit.block.Block;
-import org.bukkit.block.BlockFace;
-import org.bukkit.block.data.Ageable;
-import org.bukkit.block.data.BlockData;
-import org.bukkit.block.data.Directional;
-import org.bukkit.entity.ArmorStand;
-import org.bukkit.entity.EntityType;
-import org.bukkit.entity.Player;
-import org.bukkit.entity.Snowball;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.block.Action;
-import org.bukkit.event.entity.EntityDamageByEntityEvent;
-import org.bukkit.event.entity.EntityDeathEvent;
-import org.bukkit.event.entity.EntityExplodeEvent;
-import org.bukkit.event.player.AsyncPlayerChatEvent;
-import org.bukkit.event.player.PlayerInteractAtEntityEvent;
-import org.bukkit.event.player.PlayerInteractEvent;
-import org.bukkit.inventory.EquipmentSlot;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.potion.PotionEffect;
-import org.bukkit.potion.PotionEffectType;
-
-import de.typable.minecrafthub.util.Util;
-
-
-public class EventListener implements Listener
-{
- @EventHandler
- public void onPlayerInteract(PlayerInteractEvent event)
- {
-
- Player player = event.getPlayer();
-
- if(event.getAction() == Action.PHYSICAL)
- {
- if(event.getClickedBlock() != null)
- {
- if(event.getClickedBlock().getType() == Material.FARMLAND)
- {
- event.setCancelled(true);
- }
- }
- }
-
- EquipmentSlot equip = event.getHand();
-
- if(equip.equals(EquipmentSlot.HAND))
- {
-
- if(event.getAction() == Action.RIGHT_CLICK_BLOCK)
- {
- Block block = event.getClickedBlock();
-
- if(block == null)
- {
- return;
- }
-
- Material material = block.getType();
-
- if(player.isSneaking())
- {
- return;
- }
-
- BlockData blockdata = block.getBlockData();
-
- if(blockdata instanceof Ageable)
- {
-
- Ageable ageable = (Ageable) blockdata;
-
- if(Util.isFarmable(material) && ageable.getAge() == ageable.getMaximumAge())
- {
-
- event.setCancelled(true);
-
- if(blockdata instanceof Directional)
- {
- Directional directional = (Directional) blockdata;
- BlockFace blockface = directional.getFacing();
-
- block.breakNaturally(player.getItemInUse());
- block.setType(material);
- directional = (Directional) blockdata;
- ageable.setAge(0);
- directional.setFacing(blockface);
- block.setBlockData(blockdata);
- }
- else
- {
-
- block.breakNaturally(player.getItemInUse());
- block.setType(material);
- }
- }
- }
-
- if(material == Material.MELON && Util.hasStem(block) || material == Material.PUMPKIN && Util.hasStem(block))
- {
- block.breakNaturally(player.getInventory().getItemInMainHand());
- }
- }
- }
- }
-
- @EventHandler
- public void onEntityExplode(EntityExplodeEvent event)
- {
- if(event.getEntityType() == EntityType.CREEPER)
- {
- event.blockList().clear();
- }
- }
-
- @EventHandler
- public void onChat(AsyncPlayerChatEvent event)
- {
- String message = ChatColor.GRAY + event.getMessage().replace("%", "%%");
- String format = ChatColor.WHITE + event.getPlayer().getName() + ": " + message;
- event.setFormat(format);
- }
-
- @EventHandler
- public void onEntityHit(EntityDamageByEntityEvent event)
- {
- if(event.getDamager() instanceof Snowball)
- {
- Snowball snowball = (Snowball) event.getDamager();
-
- if(snowball.getShooter() instanceof Player)
- {
- Player player = (Player) event.getEntity();
-
- player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 20 * 2, 1));
- event.setDamage(1);
- }
- }
- }
-
- @EventHandler
- public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event)
- {
- Player player = event.getPlayer();
-
- if(event.getRightClicked().getType().equals(EntityType.ARMOR_STAND))
- {
- ItemStack item = player.getInventory().getItemInMainHand();
-
- if(item.getType() == Material.STICK && item.getAmount() > 1 && player.isSneaking())
- {
- ArmorStand armorstand = (ArmorStand) event.getRightClicked();
-
- armorstand.setArms(true);
- item.setAmount(item.getAmount() - 2);
-
- event.setCancelled(true);
- }
- }
- }
-
- @EventHandler
- public void onArmorStandDestroy(EntityDeathEvent event)
- {
- if(event.getEntity() instanceof ArmorStand)
- {
- ArmorStand armorstand = (ArmorStand) event.getEntity();
-
- if(armorstand.hasArms())
- {
- event.getDrops().add(new ItemStack(Material.STICK, 2));
- }
- }
- }
-}
-\ No newline at end of file
diff --git a/src/de/typable/minecrafthub/event/LeavesDecayListener.java b/src/de/typable/minecrafthub/event/LeavesDecayListener.java
@@ -1,124 +0,0 @@
-package de.typable.minecrafthub.event;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import org.bukkit.Tag;
-import org.bukkit.block.Block;
-import org.bukkit.block.BlockFace;
-import org.bukkit.block.data.type.Leaves;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.block.BlockBreakEvent;
-import org.bukkit.event.block.LeavesDecayEvent;
-import org.bukkit.plugin.Plugin;
-
-public class LeavesDecayListener implements Listener
-{
- private static final int DELAY = 25;
- private static final List<BlockFace> NEIGHBORS = Arrays.asList(
- BlockFace.UP,
- BlockFace.NORTH,
- BlockFace.EAST,
- BlockFace.SOUTH,
- BlockFace.WEST,
- BlockFace.DOWN
- );
-
- private Plugin plugin;
- private List<Block> scheduled = new ArrayList<>();
-
- public LeavesDecayListener(Plugin plugin)
- {
- this.plugin = plugin;
- }
-
- @EventHandler
- public void onBlockBreak(BlockBreakEvent event)
- {
- onBlockRemove(event.getBlock());
- }
-
- @EventHandler
- public void onLeavesDecay(LeavesDecayEvent event)
- {
- onBlockRemove(event.getBlock());
- }
-
- private void onBlockRemove(Block block)
- {
- if(!Tag.LOGS.isTagged(block.getType()) && !Tag.LEAVES.isTagged(block.getType()))
- {
- return;
- }
-
- Collections.shuffle(NEIGHBORS);
-
- for(BlockFace face : NEIGHBORS)
- {
- final Block neighbor = block.getRelative(face);
-
- if(!Tag.LEAVES.isTagged(neighbor.getType()))
- {
- continue;
- }
-
- Leaves leaves = (Leaves) neighbor.getBlockData();
-
- if(leaves.isPersistent())
- {
- continue;
- }
-
- if(scheduled.contains(neighbor))
- {
- continue;
- }
-
- plugin.getServer().getScheduler().runTaskLater(plugin, () -> decay(neighbor), DELAY);
-
- scheduled.add(neighbor);
- }
- }
-
- private boolean decay(Block block)
- {
- scheduled.remove(block);
-
- if(!block.getWorld().isChunkLoaded(block.getX() >> 4, block.getZ() >> 4))
- {
- return false;
- }
-
- if(!Tag.LEAVES.isTagged(block.getType()))
- {
- return false;
- }
-
- Leaves leaves = (Leaves) block.getBlockData();
-
- if(leaves.isPersistent())
- {
- return false;
- }
-
- if(leaves.getDistance() < 7)
- {
- return false;
- }
-
- LeavesDecayEvent event = new LeavesDecayEvent(block);
- plugin.getServer().getPluginManager().callEvent(event);
-
- if(event.isCancelled())
- {
- return false;
- }
-
- block.breakNaturally();
-
- return true;
- }
-}
diff --git a/src/de/typable/minecrafthub/util/Util.java b/src/de/typable/minecrafthub/util/Util.java
@@ -1,239 +0,0 @@
-package de.typable.minecrafthub.util;
-
-import javax.swing.text.Position;
-
-import org.bukkit.Bukkit;
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.block.Block;
-import org.bukkit.block.BlockFace;
-import org.bukkit.entity.Player;
-import org.bukkit.entity.Entity;
-import org.bukkit.inventory.Inventory;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.plugin.Plugin;
-import org.bukkit.Location;
-import org.bukkit.GameMode;
-import org.bukkit.plugin.Plugin;
-
-import de.typable.minecrafthub.constant.Constants;
-import net.md_5.bungee.api.ChatColor;
-import net.md_5.bungee.api.ChatMessageType;
-import net.md_5.bungee.api.chat.TextComponent;
-
-
-public class Util
-{
- public static boolean isEmpty(ItemStack item)
- {
- return item == null || item.getType() == Material.AIR;
- }
-
- public static boolean isType(ItemStack item, Material type)
- {
- return !isEmpty(item) && item.getType() == type;
- }
-
- public static boolean compare(ItemStack item, ItemStack item2)
- {
- if(item == null || item2 == null)
- {
- return false;
- }
-
- if(item.getType() != item2.getType())
- {
- return false;
- }
-
- return true;
- }
-
- public static boolean isInventoryFull(Inventory inventory, ItemStack result)
- {
- for(ItemStack item : inventory.getContents())
- {
- if(Util.isEmpty(item))
- {
- return false;
- }
-
- if(result.isSimilar(item))
- {
- if(result.getAmount() + item.getAmount() <= item.getMaxStackSize())
- {
- return false;
- }
- }
- }
-
- return true;
- }
-
- public static boolean containsAtLeast(Inventory inventory, ItemStack item, int amount)
- {
- for(int i = 0; i < inventory.getSize(); i++)
- {
- ItemStack current = inventory.getItem(i);
-
- if(Util.compare(item, current))
- {
- amount -= current.getAmount();
-
- if(amount <= 0)
- {
- return true;
- }
- }
- }
-
- return false;
- }
-
- public static void sendActionMessage(Player player, String message)
- {
- player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message));
- }
-
- public static void sendCountdown(Plugin plugin, final String message, final int time, Runnable runnable)
- {
- Bukkit.getScheduler().runTaskTimer(plugin, new Runnable()
- {
- int count = time;
-
- @Override
- public void run()
- {
- if(count == 0)
- {
- runnable.run();
- return;
- }
-
- Bukkit.getServer().broadcastMessage(ChatColor.YELLOW + message + " " + count + " sec");
-
- count--;
- }
- }, 0L, Constants.TICK);
- }
-
- public static Float convertFacingToYaw(BlockFace face)
- {
- switch(face)
- {
- case NORTH:
- return 0F;
- case EAST:
- return 90F;
- case SOUTH:
- return 180F;
- case WEST:
- return -90F;
- default:
- break;
- }
-
- return null;
- }
-
- public static boolean isAir(Material material)
- {
- return material == Material.AIR || material == Material.CAVE_AIR || material == Material.VOID_AIR;
- }
-
- public static boolean isFarmable(Material material)
- {
- return material == Material.WHEAT || material == Material.CARROTS || material == Material.POTATOES || material == Material.BEETROOTS || material == Material.NETHER_WART || material == Material.COCOA;
- }
-
- public static boolean isStem(Material material)
- {
- return material == Material.ATTACHED_PUMPKIN_STEM || material == Material.ATTACHED_MELON_STEM;
- }
-
- public static boolean hasStem(Block block)
- {
- Location blockLocation = block.getLocation();
- Material blockNorth = blockLocation.clone().add(0, 0, -1).getBlock().getType();
- Material blockEast = blockLocation.clone().add(1, 0, 0).getBlock().getType();
- Material blockSouth = blockLocation.clone().add(0, 0, 1).getBlock().getType();
- Material blockWest = blockLocation.clone().add(-1, 0, 0).getBlock().getType();
-
- return isStem(blockNorth) || isStem(blockEast) || isStem(blockSouth) || isStem(blockWest);
- }
-
- public static Location calcBlockCenter(final Location location)
- {
- Location centered = location.clone();
- centered.setX(Location.locToBlock(location.getX()) + 0.5);
- centered.setY(Location.locToBlock(location.getY()));
- centered.setZ(Location.locToBlock(location.getZ()) + 0.5);
-
- return centered;
- }
-
- public static int calcTravelFee(final Location from, final Location to)
- {
- final Double distance = from.distance(to);
- int fee = (int) Math.floor(distance / (Constants.BLOCKS_PER_CHUNK * Constants.CHUNKS_PER_EMERALD));
-
- if(fee < Constants.MIN_FEE)
- {
- fee = Constants.MIN_FEE;
- }
-
- if(fee > Constants.MAX_FEE)
- {
- fee = Constants.MAX_FEE;
- }
-
- return fee;
- }
-
- public static boolean travelTo(final Plugin plugin, final Player player, final Location location)
- {
- final int fee = Util.calcTravelFee(player.getLocation(), location);
- final String unit = fee == 1 ? "emerald" : "emeralds";
-
- if(!payFee(player, Material.EMERALD, fee) && player.getGameMode() == GameMode.SURVIVAL)
- {
- player.sendMessage(ChatColor.RED + "Not enough emeralds to teleport! Travel fee: " + fee + " " + unit);
- return false;
- }
-
- if(player.getVehicle() != null)
- {
- Entity vehicle = player.getVehicle();
- vehicle.eject();
- player.teleport(location);
-
- Bukkit.getScheduler().runTaskLater(plugin, () -> {
- vehicle.teleport(location);
- }, 3);
-
- Bukkit.getScheduler().runTaskLater(plugin, () -> {
- vehicle.addPassenger(player);
- }, 6);
- }
- else
- {
- player.teleport(location);
- }
-
- return true;
- }
-
- public static boolean payFee(final Player player, final Material unit, final int amount)
- {
- final ItemStack item = player.getInventory().getItemInMainHand();
-
- if(item.getType() != unit || item.getAmount() < amount)
- {
- return false;
- }
-
- item.setAmount(item.getAmount() - amount);
-
- return true;
- }
-}
diff --git a/src/poppy/Config.java b/src/poppy/Config.java
@@ -0,0 +1,86 @@
+package poppy;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.entity.Player;
+import org.bukkit.Location;
+
+import poppy.Utils;
+
+public class Config
+{
+ private File file;
+ private FileConfiguration configuration;
+
+ public Config(final String path)
+ {
+ this.file = new File(path);
+ this.configuration = YamlConfiguration.loadConfiguration(this.file);
+ }
+
+ public void setHome(final Player player) throws IOException
+ {
+ final String path = "home." + player.getDisplayName();
+ final Location location = Utils.calcBlockCenter(player.getLocation());
+
+ this.configuration.set(path, location);
+ this.configuration.save(this.file);
+ }
+
+ public Location getHome(final Player player)
+ {
+ final String path = "home." + player.getDisplayName();
+
+ return this.configuration.getLocation(path);
+ }
+
+ public boolean setWarp(final String name, final Location location) throws IOException
+ {
+ final String path = "warp." + name;
+
+ if(this.configuration.getLocation(path) != null)
+ {
+ return false;
+ }
+
+ this.configuration.set(path, Utils.calcBlockCenter(location));
+ this.configuration.save(this.file);
+
+ return true;
+ }
+
+ public Location getWarp(final String name)
+ {
+ final String path = "warp." + name;
+
+ return this.configuration.getLocation(path);
+ }
+
+ public List<String> getInfoPages()
+ {
+ final String path = "info";
+ List<String> pages = null;
+
+ try
+ {
+ this.configuration.load(this.file);
+ pages = (List<String>) this.configuration.getList(path);
+ }
+ catch(Exception ex)
+ {
+ // ignore
+ }
+
+ if(pages == null)
+ {
+ pages = new ArrayList<>();
+ }
+
+ return pages;
+ }
+}
diff --git a/src/poppy/Constants.java b/src/poppy/Constants.java
@@ -0,0 +1,19 @@
+package poppy;
+
+import org.bukkit.ChatColor;
+
+
+public class Constants
+{
+ public static final long TICK = 20;
+ public static final int BLOCKS_PER_CHUNK = 16;
+ public static final int CHUNKS_PER_EMERALD = 25;
+ public static final int MIN_FEE = 1;
+ public static final int MAX_FEE = 64;
+
+ public static final class Messages
+ {
+ public static final String NOT_ENOUGH_PERMISSION = ChatColor.RED + "You don't have enough Permission to perform this command!";
+ public static final String FAILED_TO_SAVE_CONFIG_FILE = ChatColor.RED + "Failed to save changes!";
+ }
+}
diff --git a/src/poppy/Main.java b/src/poppy/Main.java
@@ -0,0 +1,301 @@
+package poppy;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.BindException;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.GameMode;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.World;
+import org.bukkit.WorldCreator;
+import org.bukkit.WorldType;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.SkullMeta;
+import org.bukkit.inventory.meta.BookMeta;
+import org.bukkit.material.Tree;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.PluginManager;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import poppy.Constants;
+import poppy.Config;
+import poppy.Utils;
+import poppy.modules.AutoWorkbenchModule;
+import poppy.modules.ChairModule;
+import poppy.modules.DoubleDoorModule;
+import poppy.modules.CommonModule;
+import poppy.modules.LeavesDecayModule;
+
+
+public class Main extends JavaPlugin
+{
+ private Plugin plugin;
+ private Config config;
+ private PluginManager pluginManager;
+
+ private DoubleDoorModule doubleDoorModule;
+ private ChairModule chairModule;
+ private AutoWorkbenchModule autoWorkbenchModule;
+ private LeavesDecayModule leavesDecayModule;
+ private CommonModule commonModule;
+
+ @Override
+ public void onEnable()
+ {
+ plugin = this;
+ config = new Config("config/minecraft-hub.yml");
+
+ pluginManager = Bukkit.getPluginManager();
+
+ doubleDoorModule = new DoubleDoorModule();
+ pluginManager.registerEvents(doubleDoorModule, this);
+
+ chairModule = new ChairModule();
+ pluginManager.registerEvents(chairModule, this);
+
+ autoWorkbenchModule = new AutoWorkbenchModule();
+ pluginManager.registerEvents(autoWorkbenchModule, this);
+
+ leavesDecayModule = new LeavesDecayModule(this);
+ pluginManager.registerEvents(leavesDecayModule, this);
+
+ commonModule = new CommonModule();
+ pluginManager.registerEvents(commonModule, this);
+ }
+
+ @Override
+ public void onDisable()
+ {
+ chairModule.onDisable();
+ }
+
+ @Override
+ public boolean onCommand(CommandSender sender, Command command, String label, String[] args)
+ {
+ if(sender instanceof Player)
+ {
+ Player player = (Player) sender;
+
+ switch(label)
+ {
+ case "head":
+ return setItemAsHead(player, args);
+ case "skull":
+ return getSkullForName(player, args);
+ case "invsee":
+ return openInventoryForPlayer(player, args);
+ case "info":
+ return openInfoBook(player, args);
+ case "spawn":
+ return teleportToSpawn(player, args);
+ case "home":
+ return teleportToHome(player, args);
+ case "warp":
+ return teleportToWarppoint(player, args);
+ case "sethome":
+ return setHome(player, args);
+ case "setwarp":
+ return addWarppoint(player, args);
+ default:
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean setItemAsHead(final Player player, final String[] args)
+ {
+ final ItemStack item = player.getInventory().getItemInMainHand();
+ final ItemStack head = player.getInventory().getHelmet();
+
+ player.getInventory().setHelmet(item);
+ player.getInventory().setItemInMainHand((new ItemStack(Material.AIR)));
+
+ if(player.getGameMode() == GameMode.SURVIVAL)
+ {
+ if(head != null)
+ {
+ player.getInventory().addItem(head);
+ }
+ }
+
+ return true;
+ }
+
+ @SuppressWarnings("deprecation")
+ private boolean getSkullForName(final Player player, final String[] args)
+ {
+ if(!player.isOp())
+ {
+ player.sendMessage(Constants.Messages.NOT_ENOUGH_PERMISSION);
+ return true;
+ }
+
+ if(args.length != 1)
+ {
+ return false;
+ }
+
+ final String name = args[0];
+ final ItemStack skull = new ItemStack(Material.PLAYER_HEAD);
+ final SkullMeta meta = (SkullMeta) skull.getItemMeta();
+ meta.setOwner(name);
+ skull.setItemMeta(meta);
+
+ player.getInventory().addItem(skull);
+
+ return true;
+ }
+
+ private boolean openInventoryForPlayer(final Player player, final String[] args)
+ {
+ if(args.length == 0)
+ {
+ return false;
+ }
+
+ if(!player.isOp())
+ {
+ player.sendMessage(Constants.Messages.NOT_ENOUGH_PERMISSION);
+ return true;
+ }
+
+ final Player target = Bukkit.getPlayer(args[0]);
+
+ if(target == null)
+ {
+ player.sendMessage(ChatColor.RED + "Player not found!");
+ return true;
+ }
+
+ player.openInventory(target.getInventory());
+
+ return true;
+ }
+
+ private boolean openInfoBook(final Player player, final String[] args)
+ {
+ final ItemStack book = new ItemStack(Material.WRITTEN_BOOK);
+ final BookMeta meta = (BookMeta) book.getItemMeta();
+ meta.setTitle("Info");
+ meta.setAuthor("Server");
+ meta.setPages(config.getInfoPages());
+ book.setItemMeta(meta);
+
+ player.openBook(book);
+
+ return true;
+ }
+
+ private boolean teleportToSpawn(final Player player, final String[] args)
+ {
+ final Location location = Bukkit.getWorld("world").getSpawnLocation();
+
+ if(Utils.travelTo(plugin, player, location))
+ {
+ player.sendMessage(ChatColor.GRAY + "You've been teleported to spawn.");
+ }
+
+ return true;
+ }
+
+ private boolean teleportToHome(final Player player, final String[] args)
+ {
+ final Location location = config.getHome(player);
+
+ if(location == null)
+ {
+ player.sendMessage(ChatColor.RED + "You've don't have a home point.");
+ return true;
+ }
+
+ if(Utils.travelTo(plugin, player, location))
+ {
+ player.sendMessage(ChatColor.GRAY + "You've been teleported to your home.");
+ }
+
+ return true;
+ }
+
+ private boolean teleportToWarppoint(final Player player, final String[] args)
+ {
+ if(args.length != 1)
+ {
+ return false;
+ }
+
+ final String name = args[0];
+ final Location location = config.getWarp(name);
+
+ if(location == null)
+ {
+ player.sendMessage(ChatColor.RED + "Warp point " + name + " doesn't exist!");
+ return true;
+ }
+
+ if(Utils.travelTo(plugin, player, location))
+ {
+ player.sendMessage(ChatColor.GRAY + "You've been teleported to warp point " + name + ".");
+ }
+
+ return true;
+ }
+
+ private boolean setHome(final Player player, final String[] args)
+ {
+ try
+ {
+ config.setHome(player);
+ player.sendMessage(ChatColor.YELLOW + "Home point set.");
+ }
+ catch(Exception ex)
+ {
+ player.sendMessage(Constants.Messages.FAILED_TO_SAVE_CONFIG_FILE);
+ }
+
+ return true;
+ }
+
+ private boolean addWarppoint(final Player player, final String[] args)
+ {
+ if(args.length != 1)
+ {
+ return false;
+ }
+
+ final String name = args[0];
+
+ if(!Utils.payFee(player, Material.COMPASS, 1))
+ {
+ player.sendMessage(ChatColor.RED + "The fee for creating a warp point is 1 compass!");
+ return true;
+ }
+
+ try
+ {
+ if(!config.setWarp(name, player.getLocation()))
+ {
+ player.sendMessage(ChatColor.RED + "Warp point " + name + " already exists!");
+ return true;
+ }
+
+ player.sendMessage(ChatColor.YELLOW + "Warp point " + name + " set.");
+ }
+ catch(Exception ex)
+ {
+ player.sendMessage(Constants.Messages.FAILED_TO_SAVE_CONFIG_FILE);
+ }
+
+ return true;
+ }
+
+}
diff --git a/src/poppy/Utils.java b/src/poppy/Utils.java
@@ -0,0 +1,238 @@
+package poppy;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Entity;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.Location;
+import org.bukkit.GameMode;
+import org.bukkit.plugin.Plugin;
+
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.api.ChatMessageType;
+import net.md_5.bungee.api.chat.TextComponent;
+
+import poppy.Constants;
+
+
+public class Utils
+{
+ public static boolean isEmpty(ItemStack item)
+ {
+ return item == null || item.getType() == Material.AIR;
+ }
+
+ public static boolean isType(ItemStack item, Material type)
+ {
+ return !isEmpty(item) && item.getType() == type;
+ }
+
+ public static boolean compare(ItemStack item, ItemStack item2)
+ {
+ if(item == null || item2 == null)
+ {
+ return false;
+ }
+
+ if(item.getType() != item2.getType())
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public static boolean isInventoryFull(Inventory inventory, ItemStack result)
+ {
+ for(ItemStack item : inventory.getContents())
+ {
+ if(Utils.isEmpty(item))
+ {
+ return false;
+ }
+
+ if(result.isSimilar(item))
+ {
+ if(result.getAmount() + item.getAmount() <= item.getMaxStackSize())
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ public static boolean containsAtLeast(Inventory inventory, ItemStack item, int amount)
+ {
+ for(int i = 0; i < inventory.getSize(); i++)
+ {
+ ItemStack current = inventory.getItem(i);
+
+ if(Utils.compare(item, current))
+ {
+ amount -= current.getAmount();
+
+ if(amount <= 0)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static void sendActionMessage(Player player, String message)
+ {
+ player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message));
+ }
+
+ public static void sendCountdown(Plugin plugin, final String message, final int time, Runnable runnable)
+ {
+ Bukkit.getScheduler().runTaskTimer(plugin, new Runnable()
+ {
+ int count = time;
+
+ @Override
+ public void run()
+ {
+ if(count == 0)
+ {
+ runnable.run();
+ return;
+ }
+
+ Bukkit.getServer().broadcastMessage(ChatColor.YELLOW + message + " " + count + " sec");
+
+ count--;
+ }
+ }, 0L, Constants.TICK);
+ }
+
+ public static Float convertFacingToYaw(BlockFace face)
+ {
+ switch(face)
+ {
+ case NORTH:
+ return 0F;
+ case EAST:
+ return 90F;
+ case SOUTH:
+ return 180F;
+ case WEST:
+ return -90F;
+ default:
+ break;
+ }
+
+ return null;
+ }
+
+ public static boolean isAir(Material material)
+ {
+ return material == Material.AIR || material == Material.CAVE_AIR || material == Material.VOID_AIR;
+ }
+
+ public static boolean isFarmable(Material material)
+ {
+ return material == Material.WHEAT || material == Material.CARROTS || material == Material.POTATOES || material == Material.BEETROOTS || material == Material.NETHER_WART || material == Material.COCOA;
+ }
+
+ public static boolean isStem(Material material)
+ {
+ return material == Material.ATTACHED_PUMPKIN_STEM || material == Material.ATTACHED_MELON_STEM;
+ }
+
+ public static boolean hasStem(Block block)
+ {
+ Location blockLocation = block.getLocation();
+ Material blockNorth = blockLocation.clone().add(0, 0, -1).getBlock().getType();
+ Material blockEast = blockLocation.clone().add(1, 0, 0).getBlock().getType();
+ Material blockSouth = blockLocation.clone().add(0, 0, 1).getBlock().getType();
+ Material blockWest = blockLocation.clone().add(-1, 0, 0).getBlock().getType();
+
+ return isStem(blockNorth) || isStem(blockEast) || isStem(blockSouth) || isStem(blockWest);
+ }
+
+ public static Location calcBlockCenter(final Location location)
+ {
+ Location centered = location.clone();
+ centered.setX(Location.locToBlock(location.getX()) + 0.5);
+ centered.setY(Location.locToBlock(location.getY()));
+ centered.setZ(Location.locToBlock(location.getZ()) + 0.5);
+
+ return centered;
+ }
+
+ public static int calcTravelFee(final Location from, final Location to)
+ {
+ final Double distance = from.distance(to);
+ int fee = (int) Math.floor(distance / (Constants.BLOCKS_PER_CHUNK * Constants.CHUNKS_PER_EMERALD));
+
+ if(fee < Constants.MIN_FEE)
+ {
+ fee = Constants.MIN_FEE;
+ }
+
+ if(fee > Constants.MAX_FEE)
+ {
+ fee = Constants.MAX_FEE;
+ }
+
+ return fee;
+ }
+
+ public static boolean travelTo(final Plugin plugin, final Player player, final Location location)
+ {
+ final int fee = Utils.calcTravelFee(player.getLocation(), location);
+ final String unit = fee == 1 ? "emerald" : "emeralds";
+
+ if(!payFee(player, Material.EMERALD, fee) && player.getGameMode() == GameMode.SURVIVAL)
+ {
+ player.sendMessage(ChatColor.RED + "Not enough emeralds to teleport! Travel fee: " + fee + " " + unit);
+ return false;
+ }
+
+ if(player.getVehicle() != null)
+ {
+ Entity vehicle = player.getVehicle();
+ vehicle.eject();
+ player.teleport(location);
+
+ Bukkit.getScheduler().runTaskLater(plugin, () -> {
+ vehicle.teleport(location);
+ }, 3);
+
+ Bukkit.getScheduler().runTaskLater(plugin, () -> {
+ vehicle.addPassenger(player);
+ }, 6);
+ }
+ else
+ {
+ player.teleport(location);
+ }
+
+ return true;
+ }
+
+ public static boolean payFee(final Player player, final Material unit, final int amount)
+ {
+ final ItemStack item = player.getInventory().getItemInMainHand();
+
+ if(item.getType() != unit || item.getAmount() < amount)
+ {
+ return false;
+ }
+
+ item.setAmount(item.getAmount() - amount);
+
+ return true;
+ }
+}
diff --git a/src/poppy/modules/AutoWorkbenchModule.java b/src/poppy/modules/AutoWorkbenchModule.java
@@ -0,0 +1,241 @@
+package poppy.modules;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.bukkit.Bukkit;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.bukkit.block.Dropper;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.ItemFrame;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.inventory.InventoryMoveItemEvent;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.Recipe;
+import org.bukkit.inventory.ShapedRecipe;
+import org.bukkit.inventory.ShapelessRecipe;
+
+import poppy.Utils;
+
+
+public class AutoWorkbenchModule implements Listener
+{
+ @EventHandler
+ public void onItemMove(InventoryMoveItemEvent event)
+ {
+ Inventory source = event.getSource();
+ Inventory target = event.getDestination();
+
+ if(source.getHolder() instanceof Dropper)
+ {
+ Dropper dropper = (Dropper) source.getHolder();
+
+ ItemFrame frame = getItemFrame(dropper.getBlock());
+
+ if(frame == null)
+ {
+ return;
+ }
+
+ ItemStack item = frame.getItem();
+
+ Recipe recipe = getCraftingRecipe(item, source, target);
+
+ if(recipe != null)
+ {
+ if(recipe instanceof ShapelessRecipe)
+ {
+ ShapelessRecipe shapless = (ShapelessRecipe) recipe;
+
+ target.addItem(shapless.getResult());
+ }
+
+ if(recipe instanceof ShapedRecipe)
+ {
+ ShapedRecipe shaped = (ShapedRecipe) recipe;
+
+ target.addItem(shaped.getResult());
+ }
+ }
+
+ event.setCancelled(true);
+ }
+ }
+
+ private Recipe getCraftingRecipe(ItemStack item, Inventory source, Inventory target)
+ {
+ if(Utils.isEmpty(item))
+ {
+ return null;
+ }
+
+ Iterator<Recipe> iterator = Bukkit.recipeIterator();
+
+ while(iterator.hasNext())
+ {
+ Recipe recipe = iterator.next();
+
+ if(Utils.compare(item, recipe.getResult()))
+ {
+ List<ItemStack> ingredients = null;
+
+ if(recipe instanceof ShapelessRecipe)
+ {
+ ShapelessRecipe shapless = (ShapelessRecipe) recipe;
+
+ ingredients = shapless.getIngredientList();
+ }
+
+ if(recipe instanceof ShapedRecipe)
+ {
+ ShapedRecipe shaped = (ShapedRecipe) recipe;
+
+ ingredients = new ArrayList<>();
+
+ for(ItemStack value : shaped.getIngredientMap().values())
+ {
+ if(ingredients.isEmpty())
+ {
+ if(!Utils.isEmpty(value))
+ {
+ ingredients.add(value);
+ }
+ }
+ else
+ {
+ appendUniqueIngredient(ingredients, value);
+ }
+ }
+ }
+
+ if(ingredients == null)
+ {
+ continue;
+ }
+
+ if(!hasIngredients(source, ingredients))
+ {
+ continue;
+ }
+
+ if(Utils.isInventoryFull(target, recipe.getResult()))
+ {
+ return null;
+ }
+
+ removeIngredients(ingredients, source);
+
+ return recipe;
+ }
+ }
+
+ return null;
+ }
+
+ private void removeIngredients(List<ItemStack> ingredients, Inventory inventory)
+ {
+ for(ItemStack ingredient : ingredients)
+ {
+ if(Utils.isEmpty(ingredient))
+ {
+ continue;
+ }
+
+ int amount = ingredient.getAmount();
+
+ ListIterator<ItemStack> iterator = inventory.iterator();
+
+ while(iterator.hasNext())
+ {
+ ItemStack item = iterator.next();
+
+ if(Utils.isEmpty(item))
+ {
+ continue;
+ }
+
+ if(Utils.compare(item, ingredient))
+ {
+ if(item.getAmount() > amount)
+ {
+ item.setAmount(item.getAmount() - amount);
+ amount = 0;
+
+ break;
+ }
+
+ if(item.getAmount() == amount)
+ {
+ amount = 0;
+ inventory.removeItem(item);
+
+ break;
+ }
+
+ if(item.getAmount() < amount)
+ {
+ amount -= item.getAmount();
+ inventory.removeItem(item);
+ }
+ }
+ }
+ }
+ }
+
+ private void appendUniqueIngredient(List<ItemStack> ingredients, ItemStack item)
+ {
+ for(ItemStack ingredient : ingredients)
+ {
+ if(Utils.compare(item, ingredient))
+ {
+ ingredient.setAmount(ingredient.getAmount() + item.getAmount());
+
+ return;
+ }
+ }
+
+ if(!Utils.isEmpty(item))
+ {
+ ingredients.add(item);
+ }
+ }
+
+ private boolean hasIngredients(Inventory inventory, List<ItemStack> ingredients)
+ {
+ for(ItemStack ingredient : ingredients)
+ {
+ if(ingredient != null && !Utils.containsAtLeast(inventory, ingredient, ingredient.getAmount()))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private ItemFrame getItemFrame(Block block)
+ {
+ for(Entity entity : block.getWorld().getNearbyEntities(block.getLocation(), 2, 2, 2))
+ {
+ if(entity instanceof ItemFrame)
+ {
+ ItemFrame frame = (ItemFrame) entity;
+
+ if(frame.getFacing() == BlockFace.UP)
+ {
+ if(block.getLocation().add(0.5, 1.03125, 0.5).distance(frame.getLocation()) < 0.2D)
+ {
+ return frame;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/src/poppy/modules/ChairModule.java b/src/poppy/modules/ChairModule.java
@@ -0,0 +1,215 @@
+package poppy.modules;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.block.data.Bisected.Half;
+import org.bukkit.block.data.type.Stairs;
+import org.bukkit.entity.ArmorStand;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+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.util.Vector;
+import org.spigotmc.event.entity.EntityDismountEvent;
+
+import poppy.Utils;
+
+
+public class ChairModule implements Listener
+{
+ private static final Material[] CHAIR_TYPE = new Material[]
+ {
+ Material.OAK_STAIRS,
+ Material.SPRUCE_STAIRS,
+ Material.BIRCH_STAIRS,
+ Material.JUNGLE_STAIRS,
+ Material.ACACIA_STAIRS,
+ Material.DARK_OAK_STAIRS,
+ Material.ACACIA_STAIRS,
+ Material.CRIMSON_STAIRS,
+ Material.WARPED_STAIRS
+ };
+
+ private Map<Block, ArmorStand> blockMap = new HashMap<>();
+
+ public void onDisable()
+ {
+ for(ArmorStand armorStand : blockMap.values())
+ {
+ armorStand.eject();
+ armorStand.remove();
+ }
+ }
+
+ @EventHandler
+ public void onPlayerInteract(PlayerInteractEvent event)
+ {
+ Player player = event.getPlayer();
+
+ if(event.getAction() == Action.RIGHT_CLICK_BLOCK)
+ {
+ if(event.getClickedBlock() != null && !event.getPlayer().isSneaking())
+ {
+ Block block = event.getClickedBlock();
+
+ if(isChair(block.getType()))
+ {
+ if(!isInRange(block, player))
+ {
+ return;
+ }
+
+ if(blockMap.containsKey(block))
+ {
+ return;
+ }
+
+ if(isCompatible(block))
+ {
+ ArmorStand armorStand = createMountableChair(block, player);
+
+ if(armorStand == null)
+ {
+ return;
+ }
+
+ event.setCancelled(true);
+
+ blockMap.put(block, armorStand);
+ }
+ }
+ }
+ }
+ }
+
+ @EventHandler
+ public void onEntityDismount(EntityDismountEvent event)
+ {
+ if(event.getEntity() instanceof Player)
+ {
+ Entity entity = event.getDismounted();
+
+ if(entity != null && entity instanceof ArmorStand)
+ {
+ if(blockMap.containsValue(entity))
+ {
+ for(Entry<Block, ArmorStand> entry : blockMap.entrySet())
+ {
+ if(entry.getValue() == entity)
+ {
+ blockMap.remove(entry.getKey());
+
+ break;
+ }
+ }
+ }
+
+ Location location = entity.getLocation();
+ location.add(0, 1, 0);
+
+ for(Entity passenger : entity.getPassengers()) {
+ location.setPitch(passenger.getLocation().getPitch());
+ location.setYaw(passenger.getLocation().getYaw());
+ passenger.teleport(location);
+ }
+
+ entity.remove();
+ }
+ }
+ }
+
+ @EventHandler
+ public void onBlockBreak(BlockBreakEvent event)
+ {
+ Block block = event.getBlock();
+
+ if(blockMap.containsKey(block))
+ {
+ ArmorStand armorStand = blockMap.get(block);
+ armorStand.eject();
+
+ blockMap.remove(block);
+ }
+ }
+
+ private boolean isInRange(Block block, Player player)
+ {
+ return block.getLocation().add(0.5, 0.5, 0.5).distance(player.getLocation()) <= 2;
+ }
+
+ private boolean isChair(Material material)
+ {
+ for(Material chair : CHAIR_TYPE)
+ {
+ if(material == chair)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private boolean isCompatible(Block block)
+ {
+ Block upperBlock = block.getWorld().getBlockAt(block.getLocation().add(0, 1, 0));
+
+ if(!Utils.isAir(upperBlock.getType()))
+ {
+ return false;
+ }
+
+ Stairs stairs = (Stairs) block.getState().getBlockData();
+
+ if(stairs.getHalf() != Half.BOTTOM)
+ {
+ return false;
+ }
+
+ if(stairs.isWaterlogged())
+ {
+ return false;
+ }
+
+ if(stairs.getShape() == Stairs.Shape.INNER_RIGHT || stairs.getShape() == Stairs.Shape.INNER_LEFT)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ @SuppressWarnings("deprecation")
+ private ArmorStand createMountableChair(Block block, Player player)
+ {
+ Stairs stairs = (Stairs) block.getState().getBlockData();
+
+ Float yaw = Utils.convertFacingToYaw(stairs.getFacing());
+
+ if(yaw == null)
+ {
+ return null;
+ }
+
+ Location location = block.getLocation().add(0.5, -0.4, 0.5);
+ location.setYaw(yaw);
+
+ ArmorStand armorStand = (ArmorStand) block.getWorld().spawnEntity(location, EntityType.ARMOR_STAND);
+ armorStand.setPassenger((Entity) player);
+ armorStand.setSmall(true);
+ armorStand.setGravity(false);
+ armorStand.setInvulnerable(true);
+ armorStand.setVisible(false);
+
+ return armorStand;
+ }
+}
diff --git a/src/poppy/modules/CommonModule.java b/src/poppy/modules/CommonModule.java
@@ -0,0 +1,180 @@
+package poppy.modules;
+
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.bukkit.block.data.Ageable;
+import org.bukkit.block.data.BlockData;
+import org.bukkit.block.data.Directional;
+import org.bukkit.entity.ArmorStand;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Snowball;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.entity.EntityDeathEvent;
+import org.bukkit.event.entity.EntityExplodeEvent;
+import org.bukkit.event.player.AsyncPlayerChatEvent;
+import org.bukkit.event.player.PlayerInteractAtEntityEvent;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+
+import poppy.Utils;
+
+
+public class CommonModule implements Listener
+{
+ @EventHandler
+ public void onPlayerInteract(PlayerInteractEvent event)
+ {
+
+ Player player = event.getPlayer();
+
+ if(event.getAction() == Action.PHYSICAL)
+ {
+ if(event.getClickedBlock() != null)
+ {
+ if(event.getClickedBlock().getType() == Material.FARMLAND)
+ {
+ event.setCancelled(true);
+ }
+ }
+ }
+
+ EquipmentSlot equip = event.getHand();
+
+ if(equip.equals(EquipmentSlot.HAND))
+ {
+
+ if(event.getAction() == Action.RIGHT_CLICK_BLOCK)
+ {
+ Block block = event.getClickedBlock();
+
+ if(block == null)
+ {
+ return;
+ }
+
+ Material material = block.getType();
+
+ if(player.isSneaking())
+ {
+ return;
+ }
+
+ BlockData blockdata = block.getBlockData();
+
+ if(blockdata instanceof Ageable)
+ {
+
+ Ageable ageable = (Ageable) blockdata;
+
+ if(Utils.isFarmable(material) && ageable.getAge() == ageable.getMaximumAge())
+ {
+
+ event.setCancelled(true);
+
+ if(blockdata instanceof Directional)
+ {
+ Directional directional = (Directional) blockdata;
+ BlockFace blockface = directional.getFacing();
+
+ block.breakNaturally(player.getItemInUse());
+ block.setType(material);
+ directional = (Directional) blockdata;
+ ageable.setAge(0);
+ directional.setFacing(blockface);
+ block.setBlockData(blockdata);
+ }
+ else
+ {
+
+ block.breakNaturally(player.getItemInUse());
+ block.setType(material);
+ }
+ }
+ }
+
+ if(material == Material.MELON && Utils.hasStem(block) || material == Material.PUMPKIN && Utils.hasStem(block))
+ {
+ block.breakNaturally(player.getInventory().getItemInMainHand());
+ }
+ }
+ }
+ }
+
+ @EventHandler
+ public void onEntityExplode(EntityExplodeEvent event)
+ {
+ if(event.getEntityType() == EntityType.CREEPER)
+ {
+ event.blockList().clear();
+ }
+ }
+
+ @EventHandler
+ public void onChat(AsyncPlayerChatEvent event)
+ {
+ String message = ChatColor.GRAY + event.getMessage().replace("%", "%%");
+ String format = ChatColor.WHITE + event.getPlayer().getName() + ": " + message;
+ event.setFormat(format);
+ }
+
+ @EventHandler
+ public void onEntityHit(EntityDamageByEntityEvent event)
+ {
+ if(event.getDamager() instanceof Snowball)
+ {
+ Snowball snowball = (Snowball) event.getDamager();
+
+ if(snowball.getShooter() instanceof Player)
+ {
+ Player player = (Player) event.getEntity();
+
+ player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 20 * 2, 1));
+ event.setDamage(1);
+ }
+ }
+ }
+
+ @EventHandler
+ public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event)
+ {
+ Player player = event.getPlayer();
+
+ if(event.getRightClicked().getType().equals(EntityType.ARMOR_STAND))
+ {
+ ItemStack item = player.getInventory().getItemInMainHand();
+
+ if(item.getType() == Material.STICK && item.getAmount() > 1 && player.isSneaking())
+ {
+ ArmorStand armorstand = (ArmorStand) event.getRightClicked();
+
+ armorstand.setArms(true);
+ item.setAmount(item.getAmount() - 2);
+
+ event.setCancelled(true);
+ }
+ }
+ }
+
+ @EventHandler
+ public void onArmorStandDestroy(EntityDeathEvent event)
+ {
+ if(event.getEntity() instanceof ArmorStand)
+ {
+ ArmorStand armorstand = (ArmorStand) event.getEntity();
+
+ if(armorstand.hasArms())
+ {
+ event.getDrops().add(new ItemStack(Material.STICK, 2));
+ }
+ }
+ }
+}
+\ No newline at end of file
diff --git a/src/poppy/modules/DoubleDoorModule.java b/src/poppy/modules/DoubleDoorModule.java
@@ -0,0 +1,152 @@
+package poppy.modules;
+
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.Sound;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockState;
+import org.bukkit.block.data.type.Door;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.player.PlayerInteractEvent;
+
+import poppy.Utils;
+
+
+public class DoubleDoorModule implements Listener
+{
+ private static final Material[] DOOR_TYPE = new Material[] { Material.OAK_DOOR, Material.SPRUCE_DOOR, Material.BIRCH_DOOR, Material.JUNGLE_DOOR, Material.ACACIA_DOOR, Material.DARK_OAK_DOOR, Material.ACACIA_DOOR, Material.CRIMSON_DOOR, Material.WARPED_DOOR };
+
+ @EventHandler
+ public void onPlayerInteract(PlayerInteractEvent event)
+ {
+ Player player = event.getPlayer();
+
+ if(event.getAction() == Action.RIGHT_CLICK_BLOCK)
+ {
+ if(event.getClickedBlock() != null)
+ {
+ Block block = event.getClickedBlock();
+
+ if(isDoor(block.getType()))
+ {
+ if(player.isSneaking())
+ {
+ if(!Utils.isEmpty(player.getInventory().getItemInMainHand()))
+ {
+ return;
+ }
+
+ if(!Utils.isEmpty(player.getInventory().getItemInOffHand()))
+ {
+ return;
+ }
+ }
+
+ BlockState state = block.getState();
+ Door door = (Door) state.getBlockData();
+
+ Location location = getOppositeDoor(door, block.getLocation());
+
+ if(location == null)
+ {
+ return;
+ }
+
+ Block opposite = block.getWorld().getBlockAt(location);
+
+ if(block.getType() != opposite.getType())
+ {
+ return;
+ }
+
+ BlockState stateOpposite = opposite.getState();
+ Door doorOpposite = (Door) stateOpposite.getBlockData();
+
+ if(isCompatible(door, doorOpposite))
+ {
+ if(door.isOpen() && doorOpposite.isOpen())
+ {
+ doorOpposite.setOpen(false);
+
+ stateOpposite.setBlockData(doorOpposite);
+ stateOpposite.update();
+
+ player.playSound(player.getLocation(), Sound.BLOCK_WOODEN_DOOR_CLOSE, 1F, 1F);
+ }
+
+ if(!door.isOpen() && !doorOpposite.isOpen())
+ {
+ doorOpposite.setOpen(true);
+
+ stateOpposite.setBlockData(doorOpposite);
+ stateOpposite.update();
+
+ player.playSound(player.getLocation(), Sound.BLOCK_WOODEN_DOOR_OPEN, 1F, 1F);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private boolean isDoor(Material material)
+ {
+ for(Material door : DOOR_TYPE)
+ {
+ if(material == door)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private Location getOppositeDoor(Door door, Location location)
+ {
+ int invert = door.getHinge() == Door.Hinge.LEFT ? 1 : -1;
+
+ switch(door.getFacing())
+ {
+ case NORTH:
+ location.add(1 * invert, 0, 0);
+ break;
+ case EAST:
+ location.add(0, 0, 1 * invert);
+ break;
+ case SOUTH:
+ location.add(-1 * invert, 0, 0);
+ break;
+ case WEST:
+ location.add(0, 0, -1 * invert);
+ break;
+ default:
+ return null;
+ }
+
+ return location;
+ }
+
+ private boolean isCompatible(Door door, Door doorItem)
+ {
+ if(door.getFacing() != doorItem.getFacing())
+ {
+ return false;
+ }
+
+ if(door.getHalf() != doorItem.getHalf())
+ {
+ return false;
+ }
+
+ if(door.getHinge() == doorItem.getHinge())
+ {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/poppy/modules/LeavesDecayModule.java b/src/poppy/modules/LeavesDecayModule.java
@@ -0,0 +1,124 @@
+package poppy.modules;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.bukkit.Tag;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.bukkit.block.data.type.Leaves;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.event.block.LeavesDecayEvent;
+import org.bukkit.plugin.Plugin;
+
+public class LeavesDecayModule implements Listener
+{
+ private static final int DELAY = 25;
+ private static final List<BlockFace> NEIGHBORS = Arrays.asList(
+ BlockFace.UP,
+ BlockFace.NORTH,
+ BlockFace.EAST,
+ BlockFace.SOUTH,
+ BlockFace.WEST,
+ BlockFace.DOWN
+ );
+
+ private Plugin plugin;
+ private List<Block> scheduled = new ArrayList<>();
+
+ public LeavesDecayModule(Plugin plugin)
+ {
+ this.plugin = plugin;
+ }
+
+ @EventHandler
+ public void onBlockBreak(BlockBreakEvent event)
+ {
+ onBlockRemove(event.getBlock());
+ }
+
+ @EventHandler
+ public void onLeavesDecay(LeavesDecayEvent event)
+ {
+ onBlockRemove(event.getBlock());
+ }
+
+ private void onBlockRemove(Block block)
+ {
+ if(!Tag.LOGS.isTagged(block.getType()) && !Tag.LEAVES.isTagged(block.getType()))
+ {
+ return;
+ }
+
+ Collections.shuffle(NEIGHBORS);
+
+ for(BlockFace face : NEIGHBORS)
+ {
+ final Block neighbor = block.getRelative(face);
+
+ if(!Tag.LEAVES.isTagged(neighbor.getType()))
+ {
+ continue;
+ }
+
+ Leaves leaves = (Leaves) neighbor.getBlockData();
+
+ if(leaves.isPersistent())
+ {
+ continue;
+ }
+
+ if(scheduled.contains(neighbor))
+ {
+ continue;
+ }
+
+ plugin.getServer().getScheduler().runTaskLater(plugin, () -> decay(neighbor), DELAY);
+
+ scheduled.add(neighbor);
+ }
+ }
+
+ private boolean decay(Block block)
+ {
+ scheduled.remove(block);
+
+ if(!block.getWorld().isChunkLoaded(block.getX() >> 4, block.getZ() >> 4))
+ {
+ return false;
+ }
+
+ if(!Tag.LEAVES.isTagged(block.getType()))
+ {
+ return false;
+ }
+
+ Leaves leaves = (Leaves) block.getBlockData();
+
+ if(leaves.isPersistent())
+ {
+ return false;
+ }
+
+ if(leaves.getDistance() < 7)
+ {
+ return false;
+ }
+
+ LeavesDecayEvent event = new LeavesDecayEvent(block);
+ plugin.getServer().getPluginManager().callEvent(event);
+
+ if(event.isCancelled())
+ {
+ return false;
+ }
+
+ block.breakNaturally();
+
+ return true;
+ }
+}