/*
* This file is part of NucleusFramework for Bukkit, licensed under the MIT License (MIT).
*
* Copyright (c) JCThePants (www.jcwhatever.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.jcwhatever.nucleus.internal.listeners;
import com.jcwhatever.nucleus.Nucleus;
import com.jcwhatever.nucleus.events.anvil.AnvilEnchantItemEvent;
import com.jcwhatever.nucleus.events.anvil.AnvilRenameItemEvent;
import com.jcwhatever.nucleus.events.anvil.AnvilRepairItemEvent;
import com.jcwhatever.nucleus.events.manager.EventManager;
import com.jcwhatever.nucleus.events.signs.SignInteractEvent;
import com.jcwhatever.nucleus.internal.regions.InternalRegionManager;
import com.jcwhatever.nucleus.internal.regions.RegionEventReason;
import com.jcwhatever.nucleus.managed.scheduler.Scheduler;
import com.jcwhatever.nucleus.managed.resourcepacks.sounds.playlist.PlayList;
import com.jcwhatever.nucleus.regions.options.LeaveRegionReason;
import com.jcwhatever.nucleus.utils.items.ItemStackUtils;
import com.jcwhatever.nucleus.utils.items.ItemStackUtils.DisplayNameOption;
import com.jcwhatever.nucleus.utils.materials.Materials;
import com.jcwhatever.nucleus.utils.potions.PotionUtils;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Sign;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
public final class JCGEventListener implements Listener {
private final InternalRegionManager _regionManager;
public JCGEventListener(InternalRegionManager regionManager) {
_regionManager = regionManager;
}
@EventHandler
private void onPluginDisable(PluginDisableEvent event) {
// unregister all event handlers associated with the plugin
EventManager.unregisterPlugin(event.getPlugin());
if (Nucleus.getPlugin().isEnabled()) {
Nucleus.getScriptApiRepo().unregisterPlugin(event.getPlugin());
}
}
@EventHandler(priority=EventPriority.LOWEST)
private void onPlayerJoin(PlayerJoinEvent event) {
final Player p = event.getPlayer();
// tell player missed important messages
Nucleus.getMessengerFactory().tellImportant(p, true);
_regionManager.getPlayerWatcher()
.updatePlayerLocation(p, RegionEventReason.JOIN_SERVER);
}
@EventHandler(priority=EventPriority.MONITOR, ignoreCancelled = true)
private void onPlayerMove(PlayerMoveEvent event) {
_regionManager.getPlayerWatcher()
.updatePlayerLocation(event.getPlayer(), event.getTo(), RegionEventReason.MOVE);
}
@EventHandler(priority=EventPriority.MONITOR)
private void onPlayerDeath(PlayerDeathEvent event) {
// check for "cancelled" event
if (event.getEntity().getHealth() > 0)
return;
_regionManager.getPlayerWatcher()
.updatePlayerLocation(event.getEntity(), LeaveRegionReason.DEAD);
}
@EventHandler(priority=EventPriority.MONITOR)
private void onPlayerRespawn(PlayerRespawnEvent event) {
_regionManager.getPlayerWatcher()
.updatePlayerLocation(event.getPlayer(), event.getRespawnLocation(), RegionEventReason.RESPAWN);
}
@EventHandler(priority=EventPriority.LOWEST) // first priority
private void onPlayerQuit(PlayerQuitEvent event) {
PlayList.clearQueue(event.getPlayer());
_regionManager.getPlayerWatcher()
.updatePlayerLocation(event.getPlayer(), LeaveRegionReason.QUIT_SERVER);
}
@EventHandler(priority=EventPriority.MONITOR, ignoreCancelled = true)
private void onPlayerTeleport(PlayerTeleportEvent event) {
if (event.getFrom() == null || event.getTo() == null)
return;
// player teleporting to a different world
if (!event.getFrom().getWorld().equals(event.getTo().getWorld())) {
PlayList.clearQueue(event.getPlayer());
}
if (event.getCause() != TeleportCause.UNKNOWN) {
_regionManager.getPlayerWatcher()
.updatePlayerLocation(event.getPlayer(), event.getTo(), RegionEventReason.TELEPORT);
}
}
@EventHandler(priority=EventPriority.NORMAL, ignoreCancelled = true)
private void onPlayerInteract(PlayerInteractEvent event) {
if (!event.hasBlock()) {
return;
}
Block clicked = event.getClickedBlock();
// Signs
if (clicked != null && (clicked.getType() == Material.WALL_SIGN
|| clicked.getType() == Material.SIGN_POST)) {
Action action = event.getAction();
BlockState signState = clicked.getState();
if (action != Action.LEFT_CLICK_BLOCK && action != Action.RIGHT_CLICK_BLOCK)
return;
if (!(signState instanceof Sign))
return;
Sign sign = (Sign)signState;
SignInteractEvent signInteractEvent = new SignInteractEvent(event, sign);
Nucleus.getEventManager().callBukkit(this, signInteractEvent);
}
}
@EventHandler(priority=EventPriority.NORMAL, ignoreCancelled = true)
private void onInventoryClick(InventoryClickEvent event) {
HumanEntity entity = event.getWhoClicked();
if (!(entity instanceof Player))
return;
final Player p = (Player)entity;
Inventory inventory = event.getInventory();
if (!(inventory instanceof AnvilInventory))
return;
final AnvilInventory anvilInventory = (AnvilInventory)inventory;
InventoryView view = event.getView();
int rawSlot = event.getRawSlot();
if (rawSlot != view.convertSlot(rawSlot) || rawSlot != 2)
return;
ItemStack resultItem = anvilInventory.getItem(2);
if (resultItem == null)
return;
ItemStack slot1 = anvilInventory.getItem(0);
ItemStack slot2 = anvilInventory.getItem(1);
ItemStack slot1Clone = slot1 == null ? null : slot1.clone();
ItemStack slot2Clone = slot2 == null ? null : slot2.clone();
// check for rename
String originalName = slot1 != null
? ItemStackUtils.getDisplayName(slot1, DisplayNameOption.OPTIONAL)
: null;
String newName = ItemStackUtils.getDisplayName(resultItem, DisplayNameOption.OPTIONAL);
if (newName != null && !newName.equals(originalName)) {
AnvilRenameItemEvent renameEvent = new AnvilRenameItemEvent(
p, anvilInventory, resultItem, newName, originalName);
Nucleus.getEventManager().callBukkit(this, renameEvent);
if (renameEvent.isCancelled()) {
cancelAnvilEvent(p, anvilInventory, slot1Clone, slot2Clone);
return;
}
ItemStackUtils.setDisplayName(resultItem, renameEvent.getNewName());
}
if (slot2 == null || slot2.getType() == Material.AIR)
return;
if (slot2.getType() == Material.ENCHANTED_BOOK) {
AnvilEnchantItemEvent enchantEvent = new AnvilEnchantItemEvent(p, anvilInventory);
Nucleus.getEventManager().callBukkit(this, enchantEvent);
if (enchantEvent.isCancelled()) {
cancelAnvilEvent(p, anvilInventory, slot1Clone, slot2Clone);
}
}
else {
AnvilRepairItemEvent repairEvent = new AnvilRepairItemEvent(p, anvilInventory, resultItem);
Nucleus.getEventManager().callBukkit(this, repairEvent);
if (repairEvent.isCancelled()) {
cancelAnvilEvent(p, anvilInventory, slot1Clone, slot2Clone);
}
}
}
// detect cancelled thrown item and re-insert into inventory
// so that it does not become invisible in the players inventory.
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = false)
private void onItemThrow(PlayerInteractEvent event) {
if (!event.isCancelled())
return;
Player player = event.getPlayer();
if (event.getAction() != Action.RIGHT_CLICK_BLOCK &&
event.getAction() != Action.RIGHT_CLICK_AIR) {
return;
}
ItemStack thrown = player.getItemInHand();
Material material = thrown.getType();
if (!Materials.isThrowable(material))
return;
if (material == Material.POTION && !PotionUtils.isSplash(thrown.getDurability()))
return;
// set same item in hand, causes packets to be sent to client
// "reminding" it that there is still an item in the players hand.
player.setItemInHand(thrown);
}
private void cancelAnvilEvent(final Player player, final Inventory inventory,
final ItemStack original1, final ItemStack original2) {
player.setItemOnCursor(null);
Scheduler.runTaskLater(Nucleus.getPlugin(), new Runnable() {
@Override
public void run() {
inventory.setItem(0, original1);
inventory.setItem(1, original2);
inventory.setItem(2, null);
player.setItemOnCursor(null);
}
});
}
}