Handle inventory move event for protection.

This commit is contained in:
sk89q 2014-08-24 15:24:52 -07:00
parent c126a0ac38
commit ee022d7cd7
3 changed files with 142 additions and 2 deletions

View File

@ -31,8 +31,10 @@
import com.sk89q.worldguard.bukkit.event.entity.SpawnEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.UseEntityEvent;
import com.sk89q.worldguard.bukkit.event.inventory.UseItemEvent;
import com.sk89q.worldguard.bukkit.listener.debounce.AbstractEventDebounce.Entry;
import com.sk89q.worldguard.bukkit.listener.debounce.BlockEntityEventDebounce;
import com.sk89q.worldguard.bukkit.listener.debounce.EntityEntityEventDebounce;
import com.sk89q.worldguard.bukkit.listener.debounce.InventoryMoveItemEventDebounce;
import com.sk89q.worldguard.bukkit.util.BlockStateAsBlockFunction;
import com.sk89q.worldguard.bukkit.util.Blocks;
import com.sk89q.worldguard.bukkit.util.Events;
@ -43,6 +45,7 @@
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.DoubleChest;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.FallingBlock;
@ -83,6 +86,7 @@
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
import org.bukkit.event.hanging.HangingBreakEvent;
import org.bukkit.event.hanging.HangingPlaceEvent;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.event.player.PlayerBedEnterEvent;
import org.bukkit.event.player.PlayerBucketEmptyEvent;
import org.bukkit.event.player.PlayerBucketFillEvent;
@ -96,6 +100,7 @@
import org.bukkit.event.vehicle.VehicleDamageEvent;
import org.bukkit.event.vehicle.VehicleDestroyEvent;
import org.bukkit.event.world.StructureGrowEvent;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.Dispenser;
import org.bukkit.material.MaterialData;
@ -114,6 +119,7 @@ public class EventAbstractionListener extends AbstractListener {
private final BlockEntityEventDebounce interactDebounce = new BlockEntityEventDebounce(10000);
private final EntityEntityEventDebounce pickupDebounce = new EntityEntityEventDebounce(10000);
private final BlockEntityEventDebounce entityBreakBlockDebounce = new BlockEntityEventDebounce(10000);
private final InventoryMoveItemEventDebounce moveItemDebounce = new InventoryMoveItemEventDebounce(30000);
/**
* Construct the listener.
@ -599,6 +605,35 @@ public void onVehicleEnter(VehicleDamageEvent event) {
// Composite events
//-------------------------------------------------------------------------
@EventHandler(ignoreCancelled = true)
public void onInventoryMoveItem(InventoryMoveItemEvent event) {
InventoryHolder causeHolder = event.getInitiator().getHolder();
InventoryHolder sourceHolder = event.getSource().getHolder();
InventoryHolder targetHolder = event.getDestination().getHolder();
Entry entry;
if ((entry = moveItemDebounce.tryDebounce(event)) != null) {
Cause cause;
if (causeHolder instanceof Entity) {
cause = create(causeHolder);
} else if (causeHolder instanceof BlockState) {
cause = create(((BlockState) causeHolder).getBlock());
} else {
cause = Cause.unknown();
}
if (!causeHolder.equals(sourceHolder)) {
handleInventoryHolderUse(event, cause, sourceHolder);
}
handleInventoryHolderUse(event, cause, targetHolder);
entry.setCancelled(event.isCancelled());
}
}
@EventHandler(ignoreCancelled = true)
public void onPotionSplash(PotionSplashEvent event) {
Entity entity = event.getEntity();
@ -683,6 +718,20 @@ private static <T extends Event & Cancellable> void handleBlockRightClick(T even
}
}
// TODO: Inventory events?
@SuppressWarnings("unchecked")
private static <T extends Event & Cancellable> void handleInventoryHolderUse(T originalEvent, Cause cause, InventoryHolder holder) {
if (originalEvent.isCancelled()) {
return;
}
if (holder instanceof Entity) {
Events.fireToCancel(originalEvent, new UseEntityEvent(originalEvent, cause, (Entity) holder));
} else if (holder instanceof BlockState) {
Events.fireToCancel(originalEvent, new UseBlockEvent(originalEvent, cause, ((BlockState) holder).getBlock()));
} else if (holder instanceof DoubleChest) {
Events.fireToCancel(originalEvent, new UseBlockEvent(originalEvent, cause, ((BlockState) ((DoubleChest) holder).getLeftSide()).getBlock()));
Events.fireToCancel(originalEvent, new UseBlockEvent(originalEvent, cause, ((BlockState) ((DoubleChest) holder).getRightSide()).getBlock()));
}
}
}

View File

@ -26,6 +26,7 @@
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import javax.annotation.Nullable;
import java.util.concurrent.TimeUnit;
public class AbstractEventDebounce<K> {
@ -60,8 +61,25 @@ protected <T extends Event & Cancellable> void debounce(K key, Cancellable origi
}
}
private static class Entry {
@Nullable
protected <T extends Event & Cancellable> Entry getEntry(K key, Cancellable originalEvent) {
Entry entry = cache.getUnchecked(key);
if (entry.cancelled != null) {
if (entry.cancelled) {
originalEvent.setCancelled(true);
}
return null;
} else {
return entry;
}
}
public static class Entry {
private Boolean cancelled;
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}
}

View File

@ -0,0 +1,73 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.listener.debounce;
import com.sk89q.worldguard.bukkit.listener.debounce.InventoryMoveItemEventDebounce.Key;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.inventory.InventoryHolder;
public class InventoryMoveItemEventDebounce extends AbstractEventDebounce<Key> {
public InventoryMoveItemEventDebounce(int debounceTime) {
super(debounceTime);
}
public Entry tryDebounce(InventoryMoveItemEvent event) {
return super.getEntry(new Key(event), event);
}
protected static class Key {
private final InventoryHolder cause;
private final InventoryHolder source;
private final InventoryHolder target;
public Key(InventoryMoveItemEvent event) {
cause = event.getInitiator().getHolder();
source = event.getSource().getHolder();
target = event.getDestination().getHolder();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key key = (Key) o;
if (cause != null ? !cause.equals(key.cause) : key.cause != null)
return false;
if (source != null ? !source.equals(key.source) : key.source != null)
return false;
if (target != null ? !target.equals(key.target) : key.target != null)
return false;
return true;
}
@Override
public int hashCode() {
int result = cause != null ? cause.hashCode() : 0;
result = 31 * result + (source != null ? source.hashCode() : 0);
result = 31 * result + (target != null ? target.hashCode() : 0);
return result;
}
}
}