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.
This commit is contained in:
Trent Hensler 2019-04-28 15:04:01 -07:00
parent b221b7d3e8
commit e726c73a33
7 changed files with 138 additions and 20 deletions

View File

@ -4,7 +4,7 @@
<groupId>com.massivecraft</groupId> <groupId>com.massivecraft</groupId>
<artifactId>Factions</artifactId> <artifactId>Factions</artifactId>
<version>1.6.9.5-U0.3.0</version> <version>1.6.9.5-U0.4.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Factions</name> <name>Factions</name>

View File

@ -8,6 +8,8 @@ import com.massivecraft.factions.cmd.FCmdRoot;
import com.massivecraft.factions.integration.*; import com.massivecraft.factions.integration.*;
import com.massivecraft.factions.integration.dynmap.EngineDynmap; import com.massivecraft.factions.integration.dynmap.EngineDynmap;
import com.massivecraft.factions.listeners.*; 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.struct.ChatMode;
import com.massivecraft.factions.util.*; import com.massivecraft.factions.util.*;
import com.massivecraft.factions.util.material.FactionMaterial; 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 FactionsExploitListener(), this);
getServer().getPluginManager().registerEvents(new FactionsBlockListener(this), 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 // since some other plugins execute commands directly through this command interface, provide it
this.getCommand(refCommand).setExecutor(cmdBase); this.getCommand(refCommand).setExecutor(cmdBase);

View File

@ -7,7 +7,6 @@ import com.massivecraft.factions.util.MiscUtil;
import com.massivecraft.factions.zcore.util.TL; import com.massivecraft.factions.zcore.util.TL;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.TravelAgent;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.*; import org.bukkit.entity.*;
import org.bukkit.entity.minecart.ExplosiveMinecart; 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;
import org.bukkit.event.hanging.HangingBreakEvent.RemoveCause; import org.bukkit.event.hanging.HangingBreakEvent.RemoveCause;
import org.bukkit.event.hanging.HangingPlaceEvent; 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.PotionEffect;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import org.bukkit.projectiles.ProjectileSource; 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 @EventHandler
public void onTravel(PlayerPortalEvent event) { public void onTravel(PlayerPortalEvent event) {
if (!P.p.getConfig().getBoolean("portals.limit", false)) { if (!P.p.getConfig().getBoolean("portals.limit", false)) {
@ -573,6 +587,7 @@ public class FactionsEntityListener implements Listener {
} }
} }
} }
*/
private boolean stopEndermanBlockManipulation(Location loc) { private boolean stopEndermanBlockManipulation(Location loc) {
if (loc == null) { if (loc == null) {

View File

@ -12,6 +12,7 @@ import com.massivecraft.factions.struct.Role;
import com.massivecraft.factions.util.FactionGUI; import com.massivecraft.factions.util.FactionGUI;
import com.massivecraft.factions.util.VisualizeUtil; import com.massivecraft.factions.util.VisualizeUtil;
import com.massivecraft.factions.util.material.FactionMaterial; 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.Access;
import com.massivecraft.factions.zcore.fperms.PermissableAction; import com.massivecraft.factions.zcore.fperms.PermissableAction;
import com.massivecraft.factions.zcore.persist.MemoryFPlayer; 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(); String name = player.getName();
if (Conf.playersWhoBypassAllProtection.contains(name)) { if (Conf.playersWhoBypassAllProtection.contains(name)) {
return true; return true;
@ -399,7 +400,7 @@ public class FactionsPlayerListener implements Listener {
return true; 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())) { if (Conf.playersWhoBypassAllProtection.contains(player.getName())) {
return true; return true;
} }
@ -476,21 +477,12 @@ public class FactionsPlayerListener implements Listener {
// Dupe fix. // Dupe fix.
Faction myFaction = me.getFaction(); Faction myFaction = me.getFaction();
Relation rel = myFaction.getRelationTo(otherFaction); Relation rel = myFaction.getRelationTo(otherFaction);
if (!rel.isMember() || !otherFaction.playerHasOwnershipRights(me, loc) && player.getItemInHand() != null) { if (!rel.isMember() || !otherFaction.playerHasOwnershipRights(me, loc)) {
switch (player.getItemInHand().getType()) { Material mainHand = player.getItemInHand().getType();
case CHEST:
case SIGN: // Check if material is at risk for dupe in either hand.
case TRAPPED_CHEST: if (isDupeMaterial(mainHand)) {
case DARK_OAK_DOOR:
case ACACIA_DOOR:
case BIRCH_DOOR:
case JUNGLE_DOOR:
case OAK_DOOR:
case SPRUCE_DOOR:
case IRON_DOOR:
return false; return false;
default:
break;
} }
} }
@ -526,6 +518,29 @@ public class FactionsPlayerListener implements Listener {
return true; 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) @EventHandler(priority = EventPriority.HIGH)
public void onPlayerRespawn(PlayerRespawnEvent event) { public void onPlayerRespawn(PlayerRespawnEvent event) {
FPlayer me = FPlayers.getInstance().getByPlayer(event.getPlayer()); FPlayer me = FPlayers.getInstance().getByPlayer(event.getPlayer());

View File

@ -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);
}
}
}
}

View File

@ -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<Block> 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;
}
}
}
}

View File

@ -52,6 +52,10 @@ public class MaterialProvider {
return null; return null;
} }
public boolean isSign(Material mat) {
return mat.name().toUpperCase().contains("SIGN");
}
public class MaterialData { public class MaterialData {
@SerializedName("material") @SerializedName("material")