From c61b0fc1bc13c72bce6f4e4234deaa37a5228e2a Mon Sep 17 00:00:00 2001 From: bloodshot Date: Thu, 2 Jan 2020 21:33:21 -0500 Subject: [PATCH] sponge: Add support for fake player interacts. --- .../griefdefender/internal/util/NMSUtil.java | 2 +- .../listener/EntityEventHandler.java | 10 ++++- .../listener/PlayerEventHandler.java | 44 ++++++++++++++++--- .../permission/GDPermissionManager.java | 6 ++- .../util/CauseContextHelper.java | 28 ++++++++++++ 5 files changed, 80 insertions(+), 10 deletions(-) diff --git a/sponge/src/main/java/com/griefdefender/internal/util/NMSUtil.java b/sponge/src/main/java/com/griefdefender/internal/util/NMSUtil.java index f6ddffd..e2f384f 100644 --- a/sponge/src/main/java/com/griefdefender/internal/util/NMSUtil.java +++ b/sponge/src/main/java/com/griefdefender/internal/util/NMSUtil.java @@ -205,7 +205,7 @@ public boolean isEntityAnimal(Entity entity) { return SpongeImplHooks.isCreatureOfType((net.minecraft.entity.Entity) entity, EnumCreatureType.CREATURE); } - public boolean isFakePlayer(Entity entity) { + public boolean isFakePlayer(Object entity) { if (!(entity instanceof EntityPlayer)) { return false; } diff --git a/sponge/src/main/java/com/griefdefender/listener/EntityEventHandler.java b/sponge/src/main/java/com/griefdefender/listener/EntityEventHandler.java index be4f7eb..998232c 100644 --- a/sponge/src/main/java/com/griefdefender/listener/EntityEventHandler.java +++ b/sponge/src/main/java/com/griefdefender/listener/EntityEventHandler.java @@ -405,7 +405,7 @@ public void onEntityDamage(DamageEntityEvent event, @First DamageSource damageSo if (protectEntity(event, event.getTargetEntity(), event.getCause(), damageSource)) { event.setCancelled(true); } - event.getTargetEntity().setCreator(null); + GDTimings.ENTITY_DAMAGE_EVENT.stopTimingIfSync(); } @@ -923,18 +923,21 @@ private boolean getPvpProtectResult(Event event, GDClaim claim, GDPermissionUser if (sourceInCombat && targetInCombat && (source.getInternalPlayerData().lastPvpTimestamp == target.getInternalPlayerData().lastPvpTimestamp)) { source.getInternalPlayerData().lastPvpTimestamp = Instant.now(); target.getInternalPlayerData().lastPvpTimestamp = Instant.now(); + GDPermissionManager.getInstance().addEventLogEntry(event, targetPlayer.getLocation(), source, targetPlayer, source, Flags.ENTITY_DAMAGE, "pvp-combat", Tristate.TRUE); return false; } // Check target claim if (!claim.isPvpEnabled()) { GriefDefenderPlugin.sendMessage(sourcePlayer, MessageCache.getInstance().PVP_CLAIM_NOT_ALLOWED); + GDPermissionManager.getInstance().addEventLogEntry(event, targetPlayer.getLocation(), source, targetPlayer, source, Flags.ENTITY_DAMAGE, "pvp", Tristate.FALSE); return true; } // Check source claim final GDClaim sourceClaim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(source.getInternalPlayerData(), sourcePlayer.getLocation()); if (!sourceClaim.isPvpEnabled()) { GriefDefenderPlugin.sendMessage(sourcePlayer, MessageCache.getInstance().PVP_CLAIM_NOT_ALLOWED); + GDPermissionManager.getInstance().addEventLogEntry(event, targetPlayer.getLocation(), source, targetPlayer, source, Flags.ENTITY_DAMAGE, "pvp", Tristate.FALSE); return true; } @@ -943,10 +946,12 @@ private boolean getPvpProtectResult(Event event, GDClaim claim, GDPermissionUser Tristate targetResult = GDPermissionManager.getInstance().getFinalPermission(event, sourcePlayer.getLocation(), claim, Flags.ENTITY_DAMAGE, targetPlayer, sourcePlayer, targetPlayer, true); if (sourceResult == Tristate.FALSE) { GriefDefenderPlugin.sendMessage(sourcePlayer, MessageCache.getInstance().PVP_SOURCE_NOT_ALLOWED); + GDPermissionManager.getInstance().addEventLogEntry(event, targetPlayer.getLocation(), source, targetPlayer, source, Flags.ENTITY_DAMAGE, "pvp", Tristate.FALSE); return true; } if (targetResult == Tristate.FALSE) { GriefDefenderPlugin.sendMessage(sourcePlayer, MessageCache.getInstance().PVP_TARGET_NOT_ALLOWED); + GDPermissionManager.getInstance().addEventLogEntry(event, targetPlayer.getLocation(), source, targetPlayer, source, Flags.ENTITY_DAMAGE, "pvp", Tristate.FALSE); return true; } @@ -961,16 +966,19 @@ private boolean getPvpProtectResult(Event event, GDClaim claim, GDPermissionUser } if (sourceResult == Tristate.FALSE) { GriefDefenderPlugin.sendMessage(sourcePlayer, MessageCache.getInstance().PVP_SOURCE_NOT_ALLOWED); + GDPermissionManager.getInstance().addEventLogEntry(event, targetPlayer.getLocation(), source, targetPlayer, source, Options.PVP.getPermission(), "pvp", Tristate.FALSE); return true; } if (targetResult == Tristate.FALSE) { GriefDefenderPlugin.sendMessage(sourcePlayer, MessageCache.getInstance().PVP_TARGET_NOT_ALLOWED); + GDPermissionManager.getInstance().addEventLogEntry(event, targetPlayer.getLocation(), source, targetPlayer, source, Options.PVP.getPermission(), "pvp", Tristate.FALSE); return true; } final Instant now = Instant.now(); source.getInternalPlayerData().lastPvpTimestamp = now; target.getInternalPlayerData().lastPvpTimestamp = now; + GDPermissionManager.getInstance().addEventLogEntry(event, targetPlayer.getLocation(), source, targetPlayer, source, Flags.ENTITY_DAMAGE, "pvp", Tristate.TRUE); return false; } } diff --git a/sponge/src/main/java/com/griefdefender/listener/PlayerEventHandler.java b/sponge/src/main/java/com/griefdefender/listener/PlayerEventHandler.java index 65937a0..fb6ab9b 100644 --- a/sponge/src/main/java/com/griefdefender/listener/PlayerEventHandler.java +++ b/sponge/src/main/java/com/griefdefender/listener/PlayerEventHandler.java @@ -62,6 +62,7 @@ import com.griefdefender.permission.flag.GDFlags; import com.griefdefender.provider.NucleusProvider; import com.griefdefender.storage.BaseStorage; +import com.griefdefender.util.CauseContextHelper; import com.griefdefender.util.EconomyUtil; import com.griefdefender.util.PaginationUtil; import com.griefdefender.util.PlayerUtil; @@ -885,8 +886,18 @@ public void onPlayerInteractBlockPrimary(InteractBlockEvent.Primary.MainHand eve } @Listener(order = Order.FIRST, beforeModifications = true) - public void onPlayerInteractBlockSecondary(InteractBlockEvent.Secondary event, @First Player player) { - // Run our item hook since Sponge no longer fires InteractItemEvent when targetting a non-air block + public void onPlayerInteractBlockSecondary(InteractBlockEvent.Secondary event) { + User user = CauseContextHelper.getEventUser(event); + final Object source = CauseContextHelper.getEventFakePlayerSource(event); + final Player player = source instanceof Player ? (Player) source : null; + if (player == null || NMSUtil.getInstance().isFakePlayer(player)) { + if (user == null) { + user = player; + } + this.handleFakePlayerInteractBlockSecondary(event, user, source); + return; + } + final HandType handType = event.getHandType(); final ItemStack itemInHand = player.getItemInHand(handType).orElse(ItemStack.empty()); if (handleItemInteract(event, player, player.getWorld(), itemInHand).isCancelled()) { @@ -903,9 +914,8 @@ public void onPlayerInteractBlockSecondary(InteractBlockEvent.Secondary event, @ GDTimings.PLAYER_INTERACT_BLOCK_SECONDARY_EVENT.startTimingIfSync(); final BlockSnapshot clickedBlock = event.getTargetBlock(); - final Object source = player; // Check if item is banned - final GDPlayerData playerData = this.dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId()); + final GDPlayerData playerData = this.dataStore.getOrCreatePlayerData(player.getWorld(), user.getUniqueId()); final Location location = clickedBlock.getLocation().orElse(null); final GDClaim claim = this.dataStore.getClaimAt(location); @@ -913,7 +923,7 @@ public void onPlayerInteractBlockSecondary(InteractBlockEvent.Secondary event, @ final TileEntity tileEntity = clickedBlock.getLocation().get().getTileEntity().orElse(null); final TrustType trustType = (tileEntity != null && NMSUtil.getInstance().containsInventory(tileEntity)) ? TrustTypes.CONTAINER : TrustTypes.ACCESSOR; if (GDFlags.INTERACT_BLOCK_SECONDARY && playerData != null) { - Tristate result = GDPermissionManager.getInstance().getFinalPermission(event, location, claim, Flags.INTERACT_BLOCK_SECONDARY, source, event.getTargetBlock(), player, trustType, true); + Tristate result = GDPermissionManager.getInstance().getFinalPermission(event, location, claim, Flags.INTERACT_BLOCK_SECONDARY, source, event.getTargetBlock(), user, trustType, true); if (result == Tristate.FALSE) { // if player is holding an item, check if it can be placed if (GDFlags.BLOCK_PLACE && !itemInHand.isEmpty() && NMSUtil.getInstance().isItemBlock(itemInHand)) { @@ -921,7 +931,7 @@ public void onPlayerInteractBlockSecondary(InteractBlockEvent.Secondary event, @ GDTimings.PLAYER_INTERACT_BLOCK_SECONDARY_EVENT.stopTimingIfSync(); return; } - if (GDPermissionManager.getInstance().getFinalPermission(event, location, claim, Flags.BLOCK_PLACE, source, itemInHand, player, TrustTypes.BUILDER, true) == Tristate.TRUE) { + if (GDPermissionManager.getInstance().getFinalPermission(event, location, claim, Flags.BLOCK_PLACE, source, itemInHand, user, TrustTypes.BUILDER, true) == Tristate.TRUE) { GDTimings.PLAYER_INTERACT_BLOCK_SECONDARY_EVENT.stopTimingIfSync(); return; } @@ -945,6 +955,28 @@ public void onPlayerInteractBlockSecondary(InteractBlockEvent.Secondary event, @ GDTimings.PLAYER_INTERACT_BLOCK_SECONDARY_EVENT.stopTimingIfSync(); } + private void handleFakePlayerInteractBlockPrimary(InteractBlockEvent event, User user, Object source) { + final BlockSnapshot clickedBlock = event.getTargetBlock(); + final Location location = clickedBlock.getLocation().orElse(null); + final GDClaim claim = this.dataStore.getClaimAt(location); + final Tristate result = GDPermissionManager.getInstance().getFinalPermission(event, location, claim, Flags.INTERACT_BLOCK_PRIMARY, source, event.getTargetBlock(), user, TrustTypes.BUILDER, true); + if (result == Tristate.FALSE) { + event.setCancelled(true); + } + } + + private void handleFakePlayerInteractBlockSecondary(InteractBlockEvent event, User user, Object source) { + final BlockSnapshot clickedBlock = event.getTargetBlock(); + final Location location = clickedBlock.getLocation().orElse(null); + final GDClaim claim = this.dataStore.getClaimAt(location); + final TileEntity tileEntity = clickedBlock.getLocation().get().getTileEntity().orElse(null); + final TrustType trustType = (tileEntity != null && NMSUtil.getInstance().containsInventory(tileEntity)) ? TrustTypes.CONTAINER : TrustTypes.ACCESSOR; + final Tristate result = GDPermissionManager.getInstance().getFinalPermission(event, location, claim, Flags.INTERACT_BLOCK_SECONDARY, source, event.getTargetBlock(), user, trustType, true); + if (result == Tristate.FALSE) { + event.setCancelled(true); + } + } + public InteractEvent handleItemInteract(InteractEvent event, Player player, World world, ItemStack itemInHand) { final ItemType itemType = itemInHand.getType(); final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId()); diff --git a/sponge/src/main/java/com/griefdefender/permission/GDPermissionManager.java b/sponge/src/main/java/com/griefdefender/permission/GDPermissionManager.java index 9f03e8c..67878df 100644 --- a/sponge/src/main/java/com/griefdefender/permission/GDPermissionManager.java +++ b/sponge/src/main/java/com/griefdefender/permission/GDPermissionManager.java @@ -516,14 +516,16 @@ public void addEventLogEntry(Event event, Location location, Object sourc // Used for situations where events are skipped for perf reasons public void addEventLogEntry(Event event, Location location, Object source, Object target, GDPermissionHolder permissionSubject, Flag flag, String trust, Tristate result) { + this.addEventLogEntry(event, location, source, target, permissionSubject, flag.getPermission(), trust, result); + } + public void addEventLogEntry(Event event, Location location, Object source, Object target, GDPermissionHolder permissionSubject, String permission, String trust, Tristate result) { if (GriefDefenderPlugin.debugActive) { String sourceId = getPermissionIdentifier(source, true); - String targetPermission = flag.getPermission(); String targetId = getPermissionIdentifier(target); if (permissionSubject == null) { permissionSubject = GriefDefenderPlugin.DEFAULT_HOLDER; } - GriefDefenderPlugin.addEventLogEntry(event, location, sourceId, targetId, permissionSubject, targetPermission, trust, result); + GriefDefenderPlugin.addEventLogEntry(event, location, sourceId, targetId, permissionSubject, permission, trust, result); } } diff --git a/sponge/src/main/java/com/griefdefender/util/CauseContextHelper.java b/sponge/src/main/java/com/griefdefender/util/CauseContextHelper.java index 01bc63a..7ef3d2b 100644 --- a/sponge/src/main/java/com/griefdefender/util/CauseContextHelper.java +++ b/sponge/src/main/java/com/griefdefender/util/CauseContextHelper.java @@ -30,10 +30,12 @@ import com.griefdefender.api.permission.Context; import com.griefdefender.api.permission.option.Options; import com.griefdefender.cache.MessageCache; +import com.griefdefender.cache.PermissionHolderCache; import com.griefdefender.claim.GDClaim; import com.griefdefender.internal.util.NMSUtil; import com.griefdefender.permission.ContextGroupKeys; import com.griefdefender.permission.ContextGroups; +import com.griefdefender.permission.GDPermissionUser; import com.griefdefender.permission.GDPermissions; import net.kyori.text.TextComponent; import org.spongepowered.api.Sponge; @@ -54,6 +56,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -61,6 +64,7 @@ public class CauseContextHelper { public static User getEventUser(Event event) { final Cause cause = event.getCause(); + final Object source = event.getSource(); final EventContext context = event.getContext(); // Don't attempt to set user for leaf decay if (context.containsKey(EventContextKeys.LEAVES_DECAY)) { @@ -71,6 +75,10 @@ public static User getEventUser(Event event) { User fakePlayer = null; if (cause != null) { user = cause.first(User.class).orElse(null); + if (user == null) { + // check for FakePlayer in context + user = cause.getContext().get(EventContextKeys.FAKE_PLAYER).orElse(null); + } if (user != null && user instanceof Entity && NMSUtil.getInstance().isFakePlayer((Entity) user)) { fakePlayer = user; } @@ -90,6 +98,15 @@ public static User getEventUser(Event event) { .orElse(context.get(EventContextKeys.CREATOR) .orElse(null))); } else { + // Check entity + final Entity entity = cause.last(Entity.class).orElse(null); + if (entity != null && entity != fakePlayer) { + final UUID creator = entity.getCreator().orElse(null); + if (creator != null) { + final GDPermissionUser gdUser = PermissionHolderCache.getInstance().getOrCreateUser(creator); + return gdUser.getOfflinePlayer(); + } + } user = context.get(EventContextKeys.NOTIFIER) .orElse(context.get(EventContextKeys.OWNER) .orElse(context.get(EventContextKeys.CREATOR) @@ -112,6 +129,17 @@ public static User getEventUser(Event event) { return user; } + public static Object getEventFakePlayerSource(Event event) { + Object source = event.getSource(); + if (source instanceof net.minecraft.entity.Entity && NMSUtil.getInstance().isFakePlayer(source)) { + final Object actualSource = event.getCause().last(Object.class).orElse(null); + if (actualSource != source && (actualSource instanceof TileEntity || actualSource instanceof Entity)) { + return actualSource; + } + } + return source; + } + // Credit to digitok of freenode for the regex assistance //final String CONTEXT_PATTERN2 = "^contexts?\\[ *(?:[\\w.-]+:[\\w.-]+:[\\w\\/.-]+ *(?:, *(?!\\]$)|(?=\\]$)))+ *\\]$"; //private static final Pattern CONTEXT_PATTERN = Pattern.compile("^context?\\[ *(?:[\\w.-]+:[\\w.-]+:[\\w\\/.-]+ *(?:, *(?!\\]$)|(?=\\]$)))+ *\\]$");