Destructive hot fix for item duplication via end portals.

Configurable. Falling blocks, piston, end portal, roughly. Destructive:
the entity is removed.

(In addition some of the feature tags are added regardless activation
flags, because 'ncp reload' could change things anyway.)

Feel free to suggest alternatives/variations...
This commit is contained in:
asofold 2016-06-13 00:11:33 +02:00
parent 5e15dc8c9b
commit d948357b46
6 changed files with 134 additions and 10 deletions

View File

@ -0,0 +1,87 @@
package fr.neatmonster.nocheatplus.checks.inventory;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.FallingBlock;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityPortalEnterEvent;
import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.checks.moving.location.LocUtil;
import fr.neatmonster.nocheatplus.compat.MCAccess;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
import fr.neatmonster.nocheatplus.components.MCAccessHolder;
import fr.neatmonster.nocheatplus.logging.Streams;
import fr.neatmonster.nocheatplus.utilities.BlockCache;
import fr.neatmonster.nocheatplus.utilities.BlockProperties;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
/**
* Hot fix for 1.9 and 1.10 (possibly later?): falling block duplication via end
* portals + pistons.
* <hr>
* For registration use NoCheatPlusAPI.addComponent.
*
* @author asofold
*
*/
public class HotFixFallingBlockPortalEnter implements Listener, MCAccessHolder {
public static void testAvailability() {
if (ReflectionUtil.getClass("org.bukkit.event.entity.EntityPortalEnterEvent") == null
|| ReflectionUtil.getClass("org.bukkit.entity.FallingBlock") == null) {
throw new RuntimeException("Not available.");
}
if (!ServerVersion.isMinecraftVersionUnknown() && ServerVersion.compareMinecraftVersion("1.9") < 0) {
throw new RuntimeException("Not needed.");
}
}
/** Temporary use only: setWorld(null) after use. */
private final Location useLoc = new Location(null, 0, 0, 0);
private MCAccess mcAccess;
private BlockCache blockCache;
public HotFixFallingBlockPortalEnter() {
testAvailability();
}
@EventHandler(priority=EventPriority.MONITOR)
public void onEntityPortalEnter(EntityPortalEnterEvent event) {
final Entity entity = event.getEntity();
if (entity instanceof FallingBlock) {
final Location loc = entity.getLocation(useLoc);
final World world = loc.getWorld();
if (InventoryConfig.getConfig(world).hotFixFallingBlockEndPortalActive) {
blockCache.setAccess(world);
final boolean nearbyPortal = BlockProperties.collidesId(blockCache, loc.getX() - 2.0, loc.getY() - 2.0, loc.getZ() - 2.0, loc.getX() + 3.0, loc.getY() + 3.0, loc.getZ() + 3.0, Material.ENDER_PORTAL);
blockCache.cleanup();
if (nearbyPortal) {
// On remove: Looks like setDropItem(false) wouldn't suffice.
entity.remove();
// TODO: STATUS: should have another stream for violations/protection.
final String message = "[INVENTORY_HOTFIX] Remove falling block entering a portal near an end portal: " + ((FallingBlock) entity).getMaterial() + " at " + world.getName() + "/" + LocUtil.simpleFormatPosition(loc);
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().info(Streams.STATUS, message);
}
}
useLoc.setWorld(null);
}
}
@Override
public void setMCAccess(MCAccess mcAccess) {
this.mcAccess = mcAccess;
this.blockCache = mcAccess.getBlockCache(null);
}
@Override
public MCAccess getMCAccess() {
return mcAccess;
}
}

View File

@ -20,6 +20,7 @@ import java.util.Map;
import java.util.Set;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.actions.ActionList;
@ -70,10 +71,20 @@ public class InventoryConfig extends ACheckConfig {
* @return the configuration
*/
public static InventoryConfig getConfig(final Player player) {
if (!worldsMap.containsKey(player.getWorld().getName()))
worldsMap.put(player.getWorld().getName(), new InventoryConfig(
ConfigManager.getConfigFile(player.getWorld().getName())));
return worldsMap.get(player.getWorld().getName());
return getConfig(player.getWorld());
}
public static InventoryConfig getConfig(final World world) {
return getWorldConfig(world.getName());
}
public static final InventoryConfig getWorldConfig(final String worldName) {
InventoryConfig cc = worldsMap.get(worldName);
if (cc == null) {
cc = new InventoryConfig(ConfigManager.getConfigFile(worldName));
worldsMap.put(worldName, cc);
}
return cc;
}
public final boolean dropCheck;
@ -111,6 +122,9 @@ public class InventoryConfig extends ACheckConfig {
public final boolean openClose;
public final boolean openCancelOther;
// Hot fixes.
public final boolean hotFixFallingBlockEndPortalActive;
/**
* Instantiates a new inventory configuration.
*
@ -153,6 +167,8 @@ public class InventoryConfig extends ACheckConfig {
openCheck = data.getBoolean(ConfPaths.INVENTORY_OPEN_CHECK);
openClose = data.getBoolean(ConfPaths.INVENTORY_OPEN_CLOSE);
openCancelOther = data.getBoolean(ConfPaths.INVENTORY_OPEN_CANCELOTHER);
hotFixFallingBlockEndPortalActive = data.getBoolean(ConfPaths.INVENTORY_HOTFIX_DUPE_FALLINGBLOCKENDPORTAL);
}
/*

View File

@ -363,4 +363,13 @@ public class LocUtil {
return "x=" + loc.getX() + ",y=" + loc.getY() + ",z=" + loc.getZ() + ",pitch=" + loc.getPitch() + ",yaw=" + loc.getYaw();
}
/**
* Just the coordinates, no world/yaw/pitch.
* @param loc
* @return
*/
public static String simpleFormatPosition(Location loc) {
return "x=" + loc.getX() + ",y=" + loc.getY() + ",z=" + loc.getZ();
}
}

View File

@ -552,6 +552,11 @@ public abstract class ConfPaths {
public static final String INVENTORY_OPEN_CLOSE = INVENTORY_OPEN + "close";
public static final String INVENTORY_OPEN_CANCELOTHER = INVENTORY_OPEN + "cancelother";
// Inventory hot-fix.
private static final String INVENTORY_HOTFIX = INVENTORY + "hotfix.";
private static final String INVENTORY_HOTFIX_DUPE = INVENTORY_HOTFIX + "duplication.";
public static final String INVENTORY_HOTFIX_DUPE_FALLINGBLOCKENDPORTAL = INVENTORY_HOTFIX_DUPE + "fallingblockendportal";
public static final String MOVING = CHECKS + "moving.";
private static final String MOVING_CREATIVEFLY = MOVING + "creativefly.";

View File

@ -366,6 +366,8 @@ public class DefaultConfig extends ConfigFile {
set(ConfPaths.INVENTORY_OPEN_CLOSE, true);
set(ConfPaths.INVENTORY_OPEN_CANCELOTHER, true);
set (ConfPaths.INVENTORY_HOTFIX_DUPE_FALLINGBLOCKENDPORTAL, true);
// MOVING
set(ConfPaths.MOVING_CREATIVEFLY_CHECK, true);
set(ConfPaths.MOVING_CREATIVEFLY_IGNOREALLOWFLIGHT, true);

View File

@ -26,6 +26,7 @@ import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.NoCheatPlus;
import fr.neatmonster.nocheatplus.checks.inventory.FastConsume;
import fr.neatmonster.nocheatplus.checks.inventory.Gutenberg;
import fr.neatmonster.nocheatplus.checks.inventory.HotFixFallingBlockPortalEnter;
import fr.neatmonster.nocheatplus.checks.net.protocollib.ProtocolLibComponent;
import fr.neatmonster.nocheatplus.compat.versions.GenericVersion;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
@ -57,9 +58,7 @@ public class DefaultComponentFactory {
// TODO: Static test methods !?
FastConsume.testAvailability();
available.add(new FastConsume());
if (ConfigManager.isTrueForAnyConfig(ConfPaths.INVENTORY_FASTCONSUME_CHECK)) {
NCPAPIProvider.getNoCheatPlusAPI().addFeatureTags("checks", Arrays.asList(FastConsume.class.getSimpleName()));
}
NCPAPIProvider.getNoCheatPlusAPI().addFeatureTags("checks", Arrays.asList(FastConsume.class.getSimpleName()));
}
catch (Throwable t){
StaticLog.logInfo("Inventory checks: FastConsume is not available.");
@ -69,13 +68,19 @@ public class DefaultComponentFactory {
try {
Gutenberg.testAvailability();
available.add(new Gutenberg());
if (ConfigManager.isTrueForAnyConfig(ConfPaths.INVENTORY_GUTENBERG_CHECK)) {
NCPAPIProvider.getNoCheatPlusAPI().addFeatureTags("checks", Arrays.asList(Gutenberg.class.getSimpleName()));
}
NCPAPIProvider.getNoCheatPlusAPI().addFeatureTags("checks", Arrays.asList(Gutenberg.class.getSimpleName()));
} catch (Throwable t) {
StaticLog.logInfo("Inventory checks: Gutenberg is not available.");
}
// Hot fix: falling block end portal.
try {
HotFixFallingBlockPortalEnter.testAvailability();
available.add(new HotFixFallingBlockPortalEnter());
NCPAPIProvider.getNoCheatPlusAPI().addFeatureTags("checks", Arrays.asList(HotFixFallingBlockPortalEnter.class.getSimpleName()));
}
catch (RuntimeException e) {}
// Version dependent activation of components.
final String vServerLc = Bukkit.getServer().getVersion().toLowerCase();
// TODO: Consider using a class for confining plugin vs. server versions.