From e726c73a33c0282feff80b31bdef8917c60314b0 Mon Sep 17 00:00:00 2001 From: Trent Hensler Date: Sun, 28 Apr 2019 15:04:01 -0700 Subject: [PATCH] 1.14 support. Spigot stopped supporting TravelAgents in portal events, limiting our ability to detect portal exploits. We are no longer able to check if a portal being created in a location is by a member of a faction. Because of this, on 1.14 and newer, we will block all portals created anywhere but in wilderness. On older versions, we'll still load up the old way of checking this, but in a legacy listener. --- pom.xml | 2 +- .../java/com/massivecraft/factions/P.java | 11 +++++ .../listeners/FactionsEntityListener.java | 19 ++++++- .../listeners/FactionsPlayerListener.java | 49 ++++++++++++------- .../versionspecific/PortalListenerLegacy.java | 42 ++++++++++++++++ .../versionspecific/PortalListener_114.java | 31 ++++++++++++ .../util/material/MaterialProvider.java | 4 ++ 7 files changed, 138 insertions(+), 20 deletions(-) create mode 100644 src/main/java/com/massivecraft/factions/listeners/versionspecific/PortalListenerLegacy.java create mode 100644 src/main/java/com/massivecraft/factions/listeners/versionspecific/PortalListener_114.java diff --git a/pom.xml b/pom.xml index 8fbdd88b..d9347a74 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.massivecraft Factions - 1.6.9.5-U0.3.0 + 1.6.9.5-U0.4.0 jar Factions diff --git a/src/main/java/com/massivecraft/factions/P.java b/src/main/java/com/massivecraft/factions/P.java index 443a91a1..b18c753d 100644 --- a/src/main/java/com/massivecraft/factions/P.java +++ b/src/main/java/com/massivecraft/factions/P.java @@ -8,6 +8,8 @@ import com.massivecraft.factions.cmd.FCmdRoot; import com.massivecraft.factions.integration.*; import com.massivecraft.factions.integration.dynmap.EngineDynmap; import com.massivecraft.factions.listeners.*; +import com.massivecraft.factions.listeners.versionspecific.PortalListenerLegacy; +import com.massivecraft.factions.listeners.versionspecific.PortalListener_114; import com.massivecraft.factions.struct.ChatMode; import com.massivecraft.factions.util.*; import com.massivecraft.factions.util.material.FactionMaterial; @@ -152,6 +154,15 @@ public class P extends MPlugin { getServer().getPluginManager().registerEvents(new FactionsExploitListener(), this); getServer().getPluginManager().registerEvents(new FactionsBlockListener(this), this); + // Version specific portal listener check. + if (Bukkit.getVersion().contains("1.14")) { + getServer().getPluginManager().registerEvents(new PortalListener_114(), this); + P.p.log(Level.WARNING, "Using 1.14 portal support. This means that we'll block ALL portals from being " + + "created in anything but wilderness."); + } else { + getServer().getPluginManager().registerEvents(new PortalListenerLegacy(), this); + } + // since some other plugins execute commands directly through this command interface, provide it this.getCommand(refCommand).setExecutor(cmdBase); diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java index d048acce..2453a41a 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java @@ -7,7 +7,6 @@ import com.massivecraft.factions.util.MiscUtil; import com.massivecraft.factions.zcore.util.TL; import org.bukkit.Bukkit; import org.bukkit.Location; -import org.bukkit.TravelAgent; import org.bukkit.block.Block; import org.bukkit.entity.*; import org.bukkit.entity.minecart.ExplosiveMinecart; @@ -19,7 +18,7 @@ import org.bukkit.event.hanging.HangingBreakByEntityEvent; import org.bukkit.event.hanging.HangingBreakEvent; import org.bukkit.event.hanging.HangingBreakEvent.RemoveCause; import org.bukkit.event.hanging.HangingPlaceEvent; -import org.bukkit.event.player.PlayerPortalEvent; +import org.bukkit.event.world.PortalCreateEvent; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import org.bukkit.projectiles.ProjectileSource; @@ -546,6 +545,21 @@ public class FactionsEntityListener implements Listener { } } + /* + + We have to disable this event for now because TravelAgents were removed in 1.14. + See https://www.spigotmc.org/threads/bukkit-craftbukkit-spigot-bungeecord-1-14-development-builds.369724/ + + The options are: + 1. PlayerPortalEvent, which doesn't let us know anything about the portal so we can't stop a player from + creating a portal at a location they aren't allowed to. + 2. PortalCreateEvent, which doesn't give us any information about the player that makes the portal, so we can't + stop specific players from creating portals in Faction land. + + So for now, we'll temporarily block ALL portals from being created in anything but wilderness. + Spigot mentioned that TravelAgent might come back, so we'll leave this commented out here for now. + See PortalListenerLegacy and PortalListener_114 for version specific implementations. + @EventHandler public void onTravel(PlayerPortalEvent event) { if (!P.p.getConfig().getBoolean("portals.limit", false)) { @@ -573,6 +587,7 @@ public class FactionsEntityListener implements Listener { } } } + */ private boolean stopEndermanBlockManipulation(Location loc) { if (loc == null) { diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java index fe2457f5..132f785a 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java @@ -12,6 +12,7 @@ import com.massivecraft.factions.struct.Role; import com.massivecraft.factions.util.FactionGUI; import com.massivecraft.factions.util.VisualizeUtil; import com.massivecraft.factions.util.material.FactionMaterial; +import com.massivecraft.factions.util.material.MaterialDb; import com.massivecraft.factions.zcore.fperms.Access; import com.massivecraft.factions.zcore.fperms.PermissableAction; import com.massivecraft.factions.zcore.persist.MemoryFPlayer; @@ -310,7 +311,7 @@ public class FactionsPlayerListener implements Listener { } - public static boolean playerCanUseItemHere(Player player, Location location, Material material, boolean justCheck) { + public boolean playerCanUseItemHere(Player player, Location location, Material material, boolean justCheck) { String name = player.getName(); if (Conf.playersWhoBypassAllProtection.contains(name)) { return true; @@ -399,7 +400,7 @@ public class FactionsPlayerListener implements Listener { return true; } - public static boolean canPlayerUseBlock(Player player, Block block, boolean justCheck) { + public boolean canPlayerUseBlock(Player player, Block block, boolean justCheck) { if (Conf.playersWhoBypassAllProtection.contains(player.getName())) { return true; } @@ -476,21 +477,12 @@ public class FactionsPlayerListener implements Listener { // Dupe fix. Faction myFaction = me.getFaction(); Relation rel = myFaction.getRelationTo(otherFaction); - if (!rel.isMember() || !otherFaction.playerHasOwnershipRights(me, loc) && player.getItemInHand() != null) { - switch (player.getItemInHand().getType()) { - case CHEST: - case SIGN: - case TRAPPED_CHEST: - case DARK_OAK_DOOR: - case ACACIA_DOOR: - case BIRCH_DOOR: - case JUNGLE_DOOR: - case OAK_DOOR: - case SPRUCE_DOOR: - case IRON_DOOR: - return false; - default: - break; + if (!rel.isMember() || !otherFaction.playerHasOwnershipRights(me, loc)) { + Material mainHand = player.getItemInHand().getType(); + + // Check if material is at risk for dupe in either hand. + if (isDupeMaterial(mainHand)) { + return false; } } @@ -526,6 +518,29 @@ public class FactionsPlayerListener implements Listener { return true; } + private boolean isDupeMaterial(Material material) { + if (MaterialDb.getInstance().provider.isSign(material)) { + return true; + } + + switch (material) { + case CHEST: + case TRAPPED_CHEST: + case DARK_OAK_DOOR: + case ACACIA_DOOR: + case BIRCH_DOOR: + case JUNGLE_DOOR: + case OAK_DOOR: + case SPRUCE_DOOR: + case IRON_DOOR: + return true; + default: + break; + } + + return false; + } + @EventHandler(priority = EventPriority.HIGH) public void onPlayerRespawn(PlayerRespawnEvent event) { FPlayer me = FPlayers.getInstance().getByPlayer(event.getPlayer()); diff --git a/src/main/java/com/massivecraft/factions/listeners/versionspecific/PortalListenerLegacy.java b/src/main/java/com/massivecraft/factions/listeners/versionspecific/PortalListenerLegacy.java new file mode 100644 index 00000000..2fc95c74 --- /dev/null +++ b/src/main/java/com/massivecraft/factions/listeners/versionspecific/PortalListenerLegacy.java @@ -0,0 +1,42 @@ +package com.massivecraft.factions.listeners.versionspecific; + +import com.massivecraft.factions.*; +import com.massivecraft.factions.struct.Relation; +import org.bukkit.TravelAgent; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerPortalEvent; + +/* + Supports versions older than 1.14 with TravelAgent. + */ +public class PortalListenerLegacy implements Listener { + + @EventHandler + public void onTravel(PlayerPortalEvent event) { + if (!P.p.getConfig().getBoolean("portals.limit", false)) { + return; // Don't do anything if they don't want us to. + } + + TravelAgent agent = event.getPortalTravelAgent(); + + // If they aren't able to find a portal, it'll try to create one. + if (event.useTravelAgent() && agent.getCanCreatePortal() && agent.findPortal(event.getTo()) == null) { + FLocation loc = new FLocation(event.getTo()); + Faction faction = Board.getInstance().getFactionAt(loc); + if (faction.isWilderness()) { + return; // We don't care about wilderness. + } else if (!faction.isNormal() && !event.getPlayer().isOp()) { + // Don't let non ops make portals in safezone or warzone. + event.setCancelled(true); + return; + } + + FPlayer fp = FPlayers.getInstance().getByPlayer(event.getPlayer()); + String mininumRelation = P.p.getConfig().getString("portals.minimum-relation", "MEMBER"); // Defaults to Neutral if typed wrong. + if (!fp.getFaction().getRelationTo(faction).isAtLeast(Relation.fromString(mininumRelation))) { + event.setCancelled(true); + } + } + } +} diff --git a/src/main/java/com/massivecraft/factions/listeners/versionspecific/PortalListener_114.java b/src/main/java/com/massivecraft/factions/listeners/versionspecific/PortalListener_114.java new file mode 100644 index 00000000..d18e9572 --- /dev/null +++ b/src/main/java/com/massivecraft/factions/listeners/versionspecific/PortalListener_114.java @@ -0,0 +1,31 @@ +package com.massivecraft.factions.listeners.versionspecific; + +import com.massivecraft.factions.Board; +import com.massivecraft.factions.FLocation; +import com.massivecraft.factions.Faction; +import org.bukkit.block.Block; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.world.PortalCreateEvent; + +import java.util.List; + +/* + Blocking all portal creation not in wilderness because we can't properly check if the creator has permission + to create at the target destination. + */ +public class PortalListener_114 implements Listener { + + @EventHandler + public void onPortalCreate(PortalCreateEvent event) { + List blocks = event.getBlocks(); + for (Block block : blocks) { + FLocation loc = new FLocation(block.getLocation()); + Faction faction = Board.getInstance().getFactionAt(loc); + if (!faction.isWilderness()) { + event.setCancelled(true); + return; + } + } + } +} diff --git a/src/main/java/com/massivecraft/factions/util/material/MaterialProvider.java b/src/main/java/com/massivecraft/factions/util/material/MaterialProvider.java index 59dd57ca..034554ad 100644 --- a/src/main/java/com/massivecraft/factions/util/material/MaterialProvider.java +++ b/src/main/java/com/massivecraft/factions/util/material/MaterialProvider.java @@ -52,6 +52,10 @@ public class MaterialProvider { return null; } + public boolean isSign(Material mat) { + return mat.name().toUpperCase().contains("SIGN"); + } + public class MaterialData { @SerializedName("material")