diff --git a/README.md b/README.md index 9566cf4..b2f825f 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,34 @@ -Advanced Portals ![Build Status](https://travis-ci.org/Plugineers/Advanced-Portals.svg?branch=portals-old) -================ -

Build Instructions

-

(This part is mostly aimed for beginners in case they haven't seen a maven project) -

You must have maven installed then run "gradle build". Once the build is complete you will have a useable jar file in the folder named "build/lib" listed as Advanced-Portals-x.x.x-snapshot.jar

+![Advanced Portals](https://i.imgur.com/UIF6cQR.png) -

Plugin Info

-

NOTE: This is the old version of Advanced Portals, look in the appropriate branch for the newer versions.

+Advanced Portals [![Build Status](https://travis-ci.org/sekwah41/Advanced-Portals.svg?branch=master)](https://travis-ci.org/sekwah41/Advanced-Portals/branches) +============== +An advanced portals plugin for bukkit made by sekwah41 designed to have a wide range of features which are easy to use. It adds a bunch of commands to create and edit portals and destinations. This plugin not only enable normal teleportation but also cross server teleportation for networks using bungee. -

An advanced portals plugin for bukkit made by sekwah41 designed to have a wide range of features which are easy to use. It adds a bunch of commands to create and edit portals and destinations. This plugin not only enable normal teleportation but also cross server teleportation for networks using bungee.

+# Branch Layout + * [master](https://github.com/sekwah41/Advanced-Portals/) (Release Build) [![Build Status](https://travis-ci.org/sekwah41/Advanced-Portals.svg?branch=master)](https://travis-ci.org/sekwah41/Advanced-Portals/branches) + * [dev](https://github.com/sekwah41/Advanced-Portals/tree/dev) (Dev Build) [![Build Status](https://travis-ci.org/sekwah41/Advanced-Portals.svg?branch=dev)](https://travis-ci.org/sekwah41/Advanced-Portals/branches) + * [recode](https://github.com/sekwah41/Advanced-Portals/tree/recode) (Recode) [![Build Status](https://travis-ci.org/sekwah41/Advanced-Portals.svg?branch=recode)](https://travis-ci.org/sekwah41/Advanced-Portals/branches) -List Of Commands +Once the recode is done the master branch will be releases and the dev branch will be where work is done. -Spigot Page +# Build Instructions +You must have gradle installed then run "gradle build". Once the build is complete you will have a useable jar file in the folder named "build/lib" listed as Advanced-Portals-x.x.x-snapshot.jar -Bukkit Page -
-
-

Usage Data

+# Help +[List Of Commands](https://github.com/sekwah41/Advanced-Portals/wiki/Commands) -Global Plugin Stats +[Spigot Page](https://www.spigotmc.org/resources/advanced-portals.14356/) +[Bukkit Page](http://dev.bukkit.org/bukkit-plugins/advanced-portals/) + +# Usage Data +![Global Plugin Stats](http://i.mcstats.org/AdvancedPortals/Global+Statistics.borderless.png) The api isn't implemented in this version, sorry for any inconvenience. Check the recode tree for possibly a working recode at some point. -

To get the needed bukkit versions download the spigot buildtools and run the appropriate commands for the versions listed in the pom file.

-

e.g. "java -jar BuildTools.jar --rev 1.10.2" (Enter this into git bash)

+To get the needed bukkit versions download the spigot buildtools and run the appropriate commands for the versions listed in the pom file. +e.g. "java -jar BuildTools.jar --rev 1.10.2" (Enter this into git bash) -

Use the versions to test code before you turn it into reflection or suggest it to be turned into reflection.

+Use the versions to test code before you turn it into reflection or suggest it to be turned into reflection. -

You should never use direct craftbukkit references in public builds as it would only work in one spigot version

+You should never use direct craftbukkit references in public builds as it would only work in one spigot version diff --git a/build.gradle b/build.gradle index c1e86e7..4d4da74 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ apply plugin: 'idea' apply plugin: 'eclipse' group = 'com.sekwah.advancedportals' -version = '0.0.49-snapshot' +version = getPluginData("version") + '-snapshot' description = "" @@ -15,6 +15,19 @@ tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } +String getPluginData(String tag) { + File file = new File("src/main/resources/plugin.yml") + String version = "notfound" + file.readLines("UTF-8").each {String line -> + line = line.trim() + if(line.startsWith(tag)) { + version = line.substring(tag.length() + 2, line.length()) + } + } + println "Advanced Portals v" + version + return version +} + configurations { // configuration that holds jars to copy into lib includeLibs @@ -27,15 +40,39 @@ repositories { // includeLibs just says to include the library in the final jar dependencies { - compile "org.bukkit:bukkit:1.13-R0.1-SNAPSHOT" + compile "org.bukkit:bukkit:1.14.1-R0.1-SNAPSHOT" compile "io.netty:netty-all:4.0.4.Final" } +task copyPlugin { + doLast { + copy { + if(System.env.MC_SERVER_LOC == null) { + throw new GradleException('You must set the server location and jar to use') + } + println "$buildDir/libs/Advanced-Portals-${version}.jar" + println "${System.env.MC_SERVER_LOC}/plugins/Advanced-Portals-${version}.jar" + try { + delete fileTree("${System.env.MC_SERVER_LOC}/plugins/") { + include "*.jar" + } + } + catch(UnableToDeleteFileException e) { + println e.getLocalizedMessage() + } + from file("$buildDir/libs/Advanced-Portals-${version}.jar") + into file("${System.env.MC_SERVER_LOC}/plugins/") + } + } +} // Set SPIGOT_LOC to the location of your server and SPIGOT_JAR as the name of the jar file in the server you want to run // DIReallyKnowWhatIAmDoingISwear is to remove the stupid pause spigot has at the start task runJar() { doLast { + if(System.env.MC_SERVER_LOC == null || System.env.MC_SERVER_JAR == null) { + throw new GradleException('You must set the server location and jar to use') + } javaexec { main "-jar" args "${System.env.MC_SERVER_LOC}\\${System.env.MC_SERVER_JAR}.jar" diff --git a/out/production/resources/config.yml b/out/production/resources/config.yml deleted file mode 100644 index aac0b82..0000000 --- a/out/production/resources/config.yml +++ /dev/null @@ -1,88 +0,0 @@ -# Advanced Portals Config - -# To set this file back to its default state just delete it and reload the server or restart it! - - - -# Set to true if you want the normal axes to work normally but the ones gived with /portals selector or wand will still work though -# It can be usefull if people with permission want to use an iron axe on a survival server -UseOnlyServerMadeAxe: false - -# Preferably an item and not a block but it shouldnt matter -AxeItemId: IRON_AXE - -# Will be implemented so you can give yourself the portal block and build manually with it so its easier to make portals with the portal block. -CanBuildPortalBlock: true - -# Defines if portals protect themselves -PortalProtection: true - -# How many blocks around the portals will be protected from griefing or destruction -PortalProtectionRadius: 5 - -# What the default trigger block is for portals if nothing is defined. -DefaultPortalTriggerBlock: PORTAL - -# This stops all water flowing inside a portal area(can be disabled if something like world edit is handelling the water flow or you dont want it active) -# you want to -StopWaterFlow: true - -# This must be a placeable block or it will not work and may even crash -ShowSelectionBlockID: RED_STAINED_GLASS - -# WarpEffect -# 0 = disabled(no particles) -# 1 = Eye of ender explode effect(loads of portal particles) -# adding more soon and may create some custom ones -WarpParticles: 1 - -# WarpSound generally suggested to keep the same as warpeffect but can usually be used for just the sound and no particle effects -# 0 = disabled(no sound) -# 1 = Enderman Warp Sound -# adding more soon -WarpSound: 1 - -# In case you want to show the bungee attempting warp message -ShowBungeeWarpMessage: false - -# This changes how long the show seletion lasts in seconds - -ShowSelectionShowDuration: 10 - -# Where to display the message 0 = disabled(replaces PortalWarpMessages), 1 = in chat and 2 = action bar(1.8 and above only, anything lower will print the message that would -# generally on the action bar in the chat without a prefix or extra chat formatting) -WarpMessageDisplay: 2 - -# Use plugin name in the warp messages -UseWarpPrefix: true - -# If this is true a custom prefix can be used, (not fully coded yet!!) - -UseCustomPrefix: false - -CustomPrefix: '&a[&eAdvancedPortals&a]' - -CustomPrefixFail: '&c[&7AdvancedPortals&c]' - -BlockSpectatorMode: false - -PortalCooldown: 5 # How long after trying to enter a portal until the player can try to enter another. 0 or lower to deactivate. -ThrowbackAmount: 0.7 # How fast to throw them back, 0 or lower to disable throwback - -DisableGatewayBeam: true - -# Letters are flags. Include them to activate. n always disables everything, remove if you want it to work. -# Lettering may not make too much sense but meh its useful. Examples are "ocpk" or "cop" (doesnt matter order) -# -# Remember enabling this means potentially admins could leave a portal lying around which could let them reop themselves. -# If you think this may be an issue use a permission plugin and specifically give the users you trust permissions. -# -# n Disabled none, best just put this to really make sure the fact none are here is specified. It disables any others too -# o Admin Heighten Enabled Permission advancedportals.createportal.commandlevel.op -# p Perm Heighten Enabled Permission advancedportals.createportal.commandlevel.perms -# c Console Heighten Enabled Permission advancedportals.createportal.commandlevel.console -# h Ops can create admin commands without special perms -# e Ops can create all perm commands without special perms -# k Ops can create console commands without special perms -# -CommandLevels: opchek diff --git a/out/production/resources/destinations.yml b/out/production/resources/destinations.yml deleted file mode 100644 index 2d66a84..0000000 --- a/out/production/resources/destinations.yml +++ /dev/null @@ -1,7 +0,0 @@ - -# ExampleDestination: -# world: it will be the world name -# pos: -# X: -# Y: -# Z: diff --git a/out/production/resources/plugin.yml b/out/production/resources/plugin.yml deleted file mode 100644 index da5e481..0000000 --- a/out/production/resources/plugin.yml +++ /dev/null @@ -1,55 +0,0 @@ -main: com.sekwah.advancedportals.AdvancedPortalsPlugin -name: AdvancedPortals -version: 0.0.48 -author: sekwah41 -description: An advanced portals plugin for bukkit. -api-version: 1.13 -commands: - advancedportals: - description: The main command for the advanced portals - aliases: [portals, aportals, portal, ap] - usage: / - destination: - description: Can be used to access portal destinations. - aliases: [desti] - usage: / -permissions: - advancedportals.*: - description: Gives access to all commands - default: op - children: - advancedportals.createportal: true - advancedportals.portal: true - advancedportals.build: true - advancedportals.desti: true - advancedportals.createportal: - description: Allows you to create portals - default: op - advancedportals.createportal.commandlevel.*: - description: Gives access to all level raisers - default: false - children: - advancedportals.createportal.commandlevel.op: true - advancedportals.createportal.commandlevel.perms: true - advancedportals.createportal.commandlevel.console: true - advancedportals.createportal.commandlevel.op: - description: Allows you to increase the users level temporaily to op - default: false - advancedportals.createportal.commandlevel.perms: - description: Allows you to increase the users level temporaily to have all perms - default: false - advancedportals.createportal.commandlevel.console: - description: Executes command in the console - default: false - advancedportals.portal: - description: Allows use of portal commands - default: op - advancedportals.build: - description: Allows you to build in the portal regions - default: op - advancedportals.desti: - description: Gives access to all desti commands - default: op - advancedportals.warp.*: - description: Access to all warps (not really used tbh) - default: op diff --git a/out/production/resources/portals.yml b/out/production/resources/portals.yml deleted file mode 100644 index 2238a58..0000000 --- a/out/production/resources/portals.yml +++ /dev/null @@ -1,19 +0,0 @@ - -# ExamplePortal: -# world: it will be the world name -# triggerblock: LAVA # will only be used if the hastriggerblock is true and can be id or text -# pos1: # dont mess with the data here, if you do it may stop the portal from working. -# X: -# Y: -# Z: -# pos2: -# X: -# Y: -# Z: -# destination: -# issetpoint: true # if this was false point name would not be used and the coordinates would be saved here, it just adds more customisation. -# pointname: examplepoint # if issetpoint is false this wont be here and tppos will be. -# tppos: -# X: -# Y: -# Z: diff --git a/src/main/java/com/sekwah/advancedportals/AdvancedPortalsCommand.java b/src/main/java/com/sekwah/advancedportals/AdvancedPortalsCommand.java index 3e20db6..9a94f3f 100644 --- a/src/main/java/com/sekwah/advancedportals/AdvancedPortalsCommand.java +++ b/src/main/java/com/sekwah/advancedportals/AdvancedPortalsCommand.java @@ -18,10 +18,11 @@ import org.bukkit.material.Wool; import org.bukkit.metadata.FixedMetadataValue; import java.util.*; +import java.util.stream.Collectors; public class AdvancedPortalsCommand implements CommandExecutor, TabCompleter { - private final ArrayList blockMaterialList = new ArrayList<>(); + private final List blockMaterialList; private AdvancedPortalsPlugin plugin; private int portalArgsStringLength = 0; @@ -33,10 +34,9 @@ public class AdvancedPortalsCommand implements CommandExecutor, TabCompleter { public AdvancedPortalsCommand(AdvancedPortalsPlugin plugin) { this.plugin = plugin; + this.blockMaterialList = Arrays.stream(Material.values()).filter(Material::isBlock).map(Enum::name) + .collect(Collectors.toList()); - for(Material material : Material.values()) { - this.blockMaterialList.add("triggerblock:" + material.name()); - } plugin.getCommand("advancedportals").setExecutor(this); } @@ -86,7 +86,7 @@ public class AdvancedPortalsCommand implements CommandExecutor, TabCompleter { ItemMeta selectorname = regionselector.getItemMeta(); selectorname.setDisplayName("\u00A7ePortal Region Selector"); selectorname.setLore(Arrays.asList("\u00A7rThis wand with has the power to help" - , "\u00A7r create portals bistowed upon it!")); + , "\u00A7r create portals bestowed upon it!")); regionselector.setItemMeta(selectorname); inventory.addItem(regionselector); @@ -142,6 +142,7 @@ public class AdvancedPortalsCommand implements CommandExecutor, TabCompleter { boolean hasDestination = false; boolean isBungeePortal = false; boolean needsPermission = false; + boolean delayed = false; boolean executesCommand = false; String destination = null; String portalName = null; @@ -152,6 +153,7 @@ public class AdvancedPortalsCommand implements CommandExecutor, TabCompleter { ArrayList extraData = new ArrayList<>(); + // Is completely changed in the recode but for now im leaving it as this horrible mess... for (int i = 1; i < args.length; i++) { if (args[i].toLowerCase().startsWith("name:") && args[i].length() > 5) { hasName = true; @@ -178,6 +180,9 @@ public class AdvancedPortalsCommand implements CommandExecutor, TabCompleter { needsPermission = true; permission = args[i].toLowerCase().replaceFirst("permission:", ""); extraData.add(new PortalArg("permission", permission)); + } else if (args[i].toLowerCase().startsWith("delayed:") && args[i].length() > 8) { + delayed = Boolean.parseBoolean(args[i].toLowerCase().replaceFirst("delayed:", "")); + extraData.add(new PortalArg("delayed", Boolean.toString(delayed))); } else if (args[i].toLowerCase().startsWith("command:") && args[i].length() > 8) { executesCommand = true; portalCommand = parseArgVariable(args, i, "command:"); @@ -243,24 +248,24 @@ public class AdvancedPortalsCommand implements CommandExecutor, TabCompleter { player.sendMessage("\u00A7apermission: \u00A7e(none needed)"); } + player.sendMessage("\u00A7adelayed: \u00A7e" + delayed); + if (executesCommand) { player.sendMessage("\u00A7acommand: \u00A7e" + portalCommand); } - Material triggerBlockMat; if (hasTriggerBlock) { - triggerBlockMat = Material.getMaterial(triggerBlock.toUpperCase()); - if (triggerBlockMat != null) { + Set materialSet = Portal.getMaterialSet(triggerBlock.toUpperCase().split(",")); + if (materialSet.size() != 0) { player.sendMessage("\u00A7atriggerBlock: \u00A7e" + triggerBlock.toUpperCase()); PortalArg[] portalArgs = new PortalArg[extraData.size()]; portalArgs = extraData.toArray(portalArgs); - player.sendMessage(Portal.create(pos1, pos2, portalName, destination, triggerBlockMat, serverName, portalArgs)); + player.sendMessage(Portal.create(pos1, pos2, portalName, destination, materialSet, serverName, portalArgs)); } else { - hasTriggerBlock = false; ConfigAccessor Config = new ConfigAccessor(plugin, "config.yml"); player.sendMessage("\u00A7ctriggerBlock: \u00A7edefault(" + Config.getConfig().getString("DefaultPortalTriggerBlock") + ")"); - player.sendMessage("\u00A7cThe block " + triggerBlock.toUpperCase() + " is not a valid block name in minecraft so the trigger block has been set to the default!"); + player.sendMessage("\u00A7c" + triggerBlock.toUpperCase() + " no valid blocks were listed so the default has been set."); PortalArg[] portalArgs = new PortalArg[extraData.size()]; portalArgs = extraData.toArray(portalArgs); player.sendMessage(Portal.create(pos1, pos2, portalName, destination, serverName, portalArgs)); @@ -661,6 +666,7 @@ public class AdvancedPortalsCommand implements CommandExecutor, TabCompleter { boolean hasName = false; boolean hasTriggerBlock = false; boolean hasDestination = false; + boolean hasDelay = false; boolean isBungeePortal = false; boolean needsPermission = false; boolean hasCommand = false; @@ -690,6 +696,9 @@ public class AdvancedPortalsCommand implements CommandExecutor, TabCompleter { case "permission": needsPermission = true; break; + case "delayed": + hasDelay = true; + break; case "command": hasCommand = true; break; @@ -714,6 +723,9 @@ public class AdvancedPortalsCommand implements CommandExecutor, TabCompleter { if (!needsPermission) { autoComplete.add("permission:"); } + if (!hasDelay) { + autoComplete.add("delayed:"); + } if (!hasCommand) { autoComplete.add("command:"); } @@ -727,8 +739,21 @@ public class AdvancedPortalsCommand implements CommandExecutor, TabCompleter { } } } - if(args[args.length-1].startsWith("triggerblock:")) { - autoComplete.addAll(this.blockMaterialList); + String triggerBlock = "triggerblock:"; + if(args[args.length-1].toLowerCase().startsWith(triggerBlock)) { + String currentArg = args[args.length-1]; + int length = currentArg.lastIndexOf(','); + String startString; + if(triggerBlock.length() > length) { + startString = triggerBlock; + } + else { + startString = currentArg.substring(0, length+1); + } + autoComplete.addAll(blockMaterialList.stream().map(value -> startString + value).collect(Collectors.toList())); + } + if(args[args.length-1].startsWith("delayed:")) { + autoComplete.addAll(Arrays.asList("delayed:true", "delayed:false")); } if(args[args.length-1].startsWith("desti:") || args[args.length-1].startsWith("destination:")) { String tagStart = args[args.length-1].startsWith("desti:") ? "desti:" : "destination:"; diff --git a/src/main/java/com/sekwah/advancedportals/AdvancedPortalsPlugin.java b/src/main/java/com/sekwah/advancedportals/AdvancedPortalsPlugin.java index 6342b97..f1facb6 100644 --- a/src/main/java/com/sekwah/advancedportals/AdvancedPortalsPlugin.java +++ b/src/main/java/com/sekwah/advancedportals/AdvancedPortalsPlugin.java @@ -8,6 +8,7 @@ import com.sekwah.advancedportals.injector.PacketInjector; import com.sekwah.advancedportals.listeners.*; import com.sekwah.advancedportals.metrics.Metrics; import com.sekwah.advancedportals.portals.Portal; +import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.io.*; @@ -39,9 +40,10 @@ public class AdvancedPortalsPlugin extends JavaPlugin { ConfigAccessor config = new ConfigAccessor(this, "config.yml"); - if(config.getConfig().getBoolean("DisableGatewayBeam", true)) { + // TODO reenable and finish but probably focus on the recode first + /*if(config.getConfig().getBoolean("DisableGatewayBeam", true)) { new PacketInjector(this, version); - } + }*/ ConfigAccessor portalConfig = new ConfigAccessor(this, "portals.yml"); portalConfig.saveDefaultConfig(); @@ -82,6 +84,12 @@ public class AdvancedPortalsPlugin extends JavaPlugin { this.setEnabled(false); } + for (Player player: + this.getServer().getOnlinePlayers()) { + player.removeMetadata("hasWarped", this); + player.removeMetadata("lavaWarped", this); + } + // thanks to the new config accessor code the config.saveDefaultConfig(); will now // only copy the file if it doesnt exist! } diff --git a/src/main/java/com/sekwah/advancedportals/compat/CraftBukkit.java b/src/main/java/com/sekwah/advancedportals/compat/CraftBukkit.java index 38ca8db..98b3c3c 100644 --- a/src/main/java/com/sekwah/advancedportals/compat/CraftBukkit.java +++ b/src/main/java/com/sekwah/advancedportals/compat/CraftBukkit.java @@ -34,15 +34,6 @@ public class CraftBukkit { private Method sendPacket; - // Data for beacon - private Class endGatewayClass; - private Class tileEntityEndGatewayClass; - private Constructor blockPositionConstructor; - private Method getWorldHandleMethod; - private Method getTileEntityMethod; - private Field getEntityTimeoutField; - - public CraftBukkit(AdvancedPortalsPlugin plugin, String bukkitImpl) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException { this.plugin = plugin; @@ -70,23 +61,6 @@ public class CraftBukkit { Class packet = Class.forName(minecraftPackage + "Packet"); this.sendPacket = playerConnection.getType().getMethod("sendPacket", packet); - // Data for beacon - this.endGatewayClass = Class.forName(craftBukkitPackage + "block.CraftEndGateway"); - this.tileEntityEndGatewayClass = Class.forName(minecraftPackage + "TileEntityEndGateway"); - - Class blockPos = Class.forName(minecraftPackage + "BlockPosition"); - - this.blockPositionConstructor = blockPos.getConstructor(int.class, int.class, int.class); - - getWorldHandleMethod = Class.forName(craftBukkitPackage + "CraftWorld").getMethod("getHandle"); - - //getTileEntityMethod = Class.forName(minecraftPackage + "WorldServer").getMethod("getTileEntity", blockPos); - - /*getEntityTimeoutField = ReflectionHelper.getFieldByType(Class.forName(minecraftPackage + "TileEntityEndGateway"), int.class, false); - if(getEntityTimeoutField != null) { - this.plugin.getLogger().info("Got field " + getEntityTimeoutField.getName() + " from TileEntityEndGateway"); - }*/ - } catch (Exception e) { e.printStackTrace(); plugin.getLogger().warning("Attempting to use backup porekit locations"); diff --git a/src/main/java/com/sekwah/advancedportals/listeners/Listeners.java b/src/main/java/com/sekwah/advancedportals/listeners/Listeners.java index 558db9b..e504578 100644 --- a/src/main/java/com/sekwah/advancedportals/listeners/Listeners.java +++ b/src/main/java/com/sekwah/advancedportals/listeners/Listeners.java @@ -28,8 +28,7 @@ import org.bukkit.metadata.FixedMetadataValue; import java.util.UUID; public class Listeners implements Listener { - // The needed config values will be stored so they are easier to access later - // an example is in the interact event in this if statement if((!UseOnlyServerAxe || event.getItem().getItemMeta().getDisplayName().equals("\u00A7eP... + private static boolean UseOnlyServerAxe = false; private static Material WandMaterial; @@ -106,36 +105,47 @@ public class Listeners implements Listener { } Player player = event.getPlayer(); - //Location fromloc = event.getFrom(); + Location loc = event.getTo(); Location eyeLoc = new Location(loc.getWorld(), loc.getX(), loc.getY() + player.getEyeHeight(), loc.getZ()); + + checkTriggerLocations(player, false, loc, eyeLoc); + + } + + public void checkTriggerLocations(Player player, boolean useDelayed, Location... locations) { for (AdvancedPortal portal : Portal.portals) { - if (Portal.locationInPortalTrigger(portal, loc) || Portal.locationInPortalTrigger(portal, eyeLoc)) { - if (portal.getTrigger().equals(Material.NETHER_PORTAL)) { - if (player.getGameMode().equals(GameMode.CREATIVE)) { - player.setMetadata("hasWarped", new FixedMetadataValue(plugin, true)); - Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new RemoveWarpData(player), 10); - } - } else if (portal.getTrigger().equals(Material.LAVA)) { - player.setMetadata("lavaWarped", new FixedMetadataValue(plugin, true)); - Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new RemoveLavaData(player), 10); + boolean delayed = portal.hasArg("delayed") && portal.getArg("delayed").equalsIgnoreCase("true"); + for (Location loc : locations) { + if (delayed == useDelayed) { + if (delayed ? Portal.locationInPortal(portal, loc, 1) : Portal.locationInPortalTrigger(portal, loc)) { + if (portal.getTriggers().contains(Material.NETHER_PORTAL)) { + if (player.getGameMode().equals(GameMode.CREATIVE)) { + player.setMetadata("hasWarped", new FixedMetadataValue(plugin, true)); + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new RemoveWarpData(player), 10); + } + } + if (portal.getTriggers().contains(Material.LAVA)) { + player.setMetadata("lavaWarped", new FixedMetadataValue(plugin, true)); + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new RemoveLavaData(player), 10); + } + if (portal.inPortal.contains(player.getUniqueId())) return; + WarpEvent warpEvent = new WarpEvent(player, portal); + plugin.getServer().getPluginManager().callEvent(warpEvent); + + if (!warpEvent.isCancelled()) Portal.activate(player, portal); + + if (!delayed) portal.inPortal.add(player.getUniqueId()); + return; + } else if (!delayed) portal.inPortal.remove(player.getUniqueId()); } - if (portal.inPortal.contains(player.getUniqueId())) return; - WarpEvent warpEvent = new WarpEvent(player, portal); - plugin.getServer().getPluginManager().callEvent(warpEvent); - - if (!warpEvent.isCancelled()) Portal.activate(player, portal); - - portal.inPortal.add(player.getUniqueId()); - } else portal.inPortal.remove(player.getUniqueId()); + } } - } // These are here because java 7 can only take finals straight into a runnable class RemoveLavaData implements Runnable{ - private Player player; public RemoveLavaData(Player player){ @@ -164,7 +174,7 @@ public class Listeners implements Listener { player.removeMetadata("hasWarped", plugin); } } - }; + } @EventHandler(ignoreCancelled = true) public void onCombustEntityEvent(EntityCombustEvent event) { @@ -183,7 +193,18 @@ public class Listeners implements Listener { @EventHandler(ignoreCancelled = true) public void onPortalEvent(PlayerPortalEvent event) { + if (event.isCancelled()) { + return; + } Player player = event.getPlayer(); + + if (!player.hasMetadata("hasWarped")) { + Location loc = event.getFrom(); + Location eyeLoc = new Location(loc.getWorld(), loc.getX(), loc.getY() + player.getEyeHeight(), loc.getZ()); + + checkTriggerLocations(player, true, loc, eyeLoc); + } + if (player.hasMetadata("hasWarped") | Portal.inPortalRegion(event.getFrom(),1)) event.setCancelled(true); } @@ -212,16 +233,6 @@ public class Listeners implements Listener { if (player.hasPermission("advancedportals.createportal")) { - // UseOnlyServerMadeAxe being set to true makes is so only the axe generated by the server can be used so other iron axes can be used normally, - // by default its false but it is a nice feature in case the user wants to use the axe normally too, such as a admin playing survival or it being used - // as a weapon. - // Null pointer exeption detected here on some servers(try decompiling the jar file to double check) - /*try { - // Use this to surround the code if needed - } - catch(NullPointerException e){ - - }*/ if (event.getItem() != null && event.getItem().getType() == WandMaterial // was type id && (!UseOnlyServerAxe || (checkItemForName(event.getItem()) && event.getItem().getItemMeta().getDisplayName().equals("\u00A7ePortal Region Selector")))) { diff --git a/src/main/java/com/sekwah/advancedportals/listeners/PortalPlacer.java b/src/main/java/com/sekwah/advancedportals/listeners/PortalPlacer.java index ffde9d9..d8026be 100644 --- a/src/main/java/com/sekwah/advancedportals/listeners/PortalPlacer.java +++ b/src/main/java/com/sekwah/advancedportals/listeners/PortalPlacer.java @@ -58,18 +58,6 @@ public class PortalPlacer implements Listener { } - /*@EventHandler - public void onChunkLoad(ChunkLoadEvent event) { - if(!this.DISABLE_GATEWAY_BEAM) { - return; - } - BlockState[] tileEntities = event.getChunk().getTileEntities(); - for(BlockState block : tileEntities) { - this.plugin.compat.setGatewayAgeHigh(block.getBlock()); - } - //event.getHandlers(); - }*/ - @EventHandler(priority = EventPriority.HIGHEST) public void onBlockPhysics(BlockPhysicsEvent event) { Block block = event.getBlock(); diff --git a/src/main/java/com/sekwah/advancedportals/portals/AdvancedPortal.java b/src/main/java/com/sekwah/advancedportals/portals/AdvancedPortal.java index 2898d86..60db8c9 100644 --- a/src/main/java/com/sekwah/advancedportals/portals/AdvancedPortal.java +++ b/src/main/java/com/sekwah/advancedportals/portals/AdvancedPortal.java @@ -3,14 +3,12 @@ package com.sekwah.advancedportals.portals; import com.sekwah.advancedportals.api.portaldata.PortalArg; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.entity.Player; -import java.util.HashSet; -import java.util.UUID; +import java.util.*; public class AdvancedPortal { - private Material trigger = null; + private Set triggers = null; private String worldName = null; @@ -47,8 +45,12 @@ public class AdvancedPortal { } public AdvancedPortal(String portalName, Material trigger, Location pos1, Location pos2, String worldName, PortalArg... portalArgs) { + this(portalName, new HashSet<>(Collections.singletonList(trigger)), pos1, pos2, worldName, portalArgs); + } + + public AdvancedPortal(String portalName, Set triggers, Location pos1, Location pos2, String worldName, PortalArg... portalArgs) { this.portalName = portalName; - this.trigger = trigger; + this.triggers = triggers; this.pos1 = pos1; this.pos2 = pos2; this.worldName = worldName; @@ -72,8 +74,8 @@ public class AdvancedPortal { return this.getArg(arg) != null; } - public Material getTrigger() { - return this.trigger; + public Set getTriggers() { + return this.triggers; } public String getWorldName() { diff --git a/src/main/java/com/sekwah/advancedportals/portals/Portal.java b/src/main/java/com/sekwah/advancedportals/portals/Portal.java index 083bb4f..af76a98 100644 --- a/src/main/java/com/sekwah/advancedportals/portals/Portal.java +++ b/src/main/java/com/sekwah/advancedportals/portals/Portal.java @@ -20,11 +20,9 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.PermissionAttachment; import org.bukkit.util.Vector; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Random; -import java.util.Set; +import java.util.*; import java.util.logging.Level; +import java.util.stream.Collectors; public class Portal { @@ -41,6 +39,8 @@ public class Portal { private static int portalProtectionRadius; private static boolean blockSpectatorMode; + private static Random random = new Random(); + public Portal(AdvancedPortalsPlugin plugin) { ConfigAccessor config = new ConfigAccessor(plugin, "config.yml"); this.showBungeeMessage = config.getConfig().getBoolean("ShowBungeeWarpMessage", false); @@ -80,18 +80,12 @@ public class Portal { ConfigurationSection portalConfigSection = portalData.getConfig().getConfigurationSection(portal.toString()); - Material blockType = Material.NETHER_PORTAL; - String BlockID = portalConfigSection.getString("triggerblock"); + String[] blockTypesString = portalConfigSection.getString("triggerblock").split(","); - try { - Integer.parseInt(BlockID); - plugin.getLogger().info("Block names must be given not IDs"); - } catch (NumberFormatException e) { - blockType = Material.getMaterial(BlockID); - } + HashSet blockTypes = getMaterialSet(blockTypesString); - if (blockType == null) { - blockType = Material.NETHER_PORTAL; + if(blockTypes.size() == 0) { + blockTypes.add(Material.NETHER_PORTAL); } ConfigurationSection portalArgsConf = portalConfigSection.getConfigurationSection("portalArgs"); @@ -118,7 +112,7 @@ public class Portal { PortalArg[] portalArgs = new PortalArg[extraData.size()]; extraData.toArray(portalArgs); - portals[portalId] = new AdvancedPortal(portal.toString(), blockType, pos1, pos2, worldName, portalArgs); + portals[portalId] = new AdvancedPortal(portal.toString(), blockTypes, pos1, pos2, worldName, portalArgs); portals[portalId].setBungee(portalConfigSection.getString("bungee")); @@ -141,11 +135,23 @@ public class Portal { } } - public static String create(Location pos1, Location pos2, String name, String destination, Material triggerBlock, PortalArg... extraData) { - return create(pos1, pos2, name, destination, triggerBlock, null, extraData); + public static HashSet getMaterialSet(String[] blockTypesString) { + HashSet blockTypes = new HashSet<>(); + + for(String blockType : blockTypesString) { + Material material = Material.getMaterial(blockType); + if(material != null) { + blockTypes.add(material); + } + } + return blockTypes; } - public static String create(Location pos1, Location pos2, String name, String destination, Material triggerBlock, String serverName, PortalArg... portalArgs) { + public static String create(Location pos1, Location pos2, String name, String destination, Set triggerBlocks, PortalArg... extraData) { + return create(pos1, pos2, name, destination, triggerBlocks, null, extraData); + } + + public static String create(Location pos1, Location pos2, String name, String destination, Set triggerBlocks, String serverName, PortalArg... portalArgs) { if (!pos1.getWorld().equals(pos2.getWorld())) { plugin.getLogger().log(Level.WARNING, "pos1 and pos2 must be in the same world!"); @@ -192,7 +198,8 @@ public class Portal { portalData.getConfig().set(name + ".world", pos1.getWorld().getName()); - portalData.getConfig().set(name + ".triggerblock", triggerBlock.toString()); + String store = triggerBlocks.stream().map(Enum::name).collect(Collectors.joining(",")); + portalData.getConfig().set(name + ".triggerblock", store); portalData.getConfig().set(name + ".destination", destination); @@ -270,7 +277,6 @@ public class Portal { return false; } - @SuppressWarnings("deprecation") public static String create(Location pos1, Location pos2, String name, String destination, String serverName, PortalArg... extraData) { // add stuff for destination names or coordinates ConfigAccessor config = new ConfigAccessor(plugin, "config.yml"); @@ -282,7 +288,7 @@ public class Portal { triggerBlockType = Material.NETHER_PORTAL; } - return create(pos1, pos2, name, destination, triggerBlockType, serverName, extraData); + return create(pos1, pos2, name, destination, new HashSet<>(Collections.singletonList(triggerBlockType)), serverName, extraData); } public static void redefine(Location pos1, Location pos2, String name) { @@ -365,22 +371,14 @@ public class Portal { public static boolean activate(Player player, AdvancedPortal portal) { - // add other variables or filter code here, or somehow have a way to register them - - // TODO on load and unload recode the permissions to try to register themselves - // https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/plugin/PluginManager.html#addPermission(org.bukkit.permissions.Permission) - // check they havent been registered before too and store a list of ones made by this plugin to remove when portals are unloaded. - // When a portal is added or removed it reloads all portals(i think) so add code for unloading too. - if(blockSpectatorMode && player.getGameMode() == GameMode.SPECTATOR) { player.sendMessage(PluginMessages.customPrefixFail + "\u00A7c You cannot enter a portal in spectator mode!"); return false; } String permission = portal.getArg("permission"); - /*if((permission == null || (permission != null && player.hasPermission(permission)) || player.isOp())){*/ - // 3 checks, 1st is if it doesnt need perms. 2nd is if it does do they have it. And third is are they op. - if (!(permission == null || (permission != null && player.hasPermission(permission)) || player.isOp())) { + + if (!(permission == null || player.hasPermission(permission) || player.isOp())) { player.sendMessage(PluginMessages.customPrefixFail + "\u00A7c You do not have permission to use this portal!"); failSound(player, portal); throwPlayerBack(player); @@ -402,12 +400,15 @@ public class Portal { //plugin.getLogger().info(portal.getName() + ":" + portal.getDestiation()); boolean warped = false; if (portal.getBungee() != null) { + String[] bungeeServers = portal.getBungee().split(","); + String bungeeServer = bungeeServers[random.nextInt(bungeeServers.length)]; if (showBungeeMessage) { - player.sendMessage(PluginMessages.customPrefix + "\u00A7a Attempting to warp to \u00A7e" + portal.getBungee() + "\u00A7a."); + player.sendMessage(PluginMessages.customPrefix + "\u00A7a Attempting to warp to \u00A7e" + bungeeServer + "\u00A7a."); } ByteArrayDataOutput out = ByteStreams.newDataOutput(); out.writeUTF("Connect"); - out.writeUTF(portal.getBungee()); + out.writeUTF(bungeeServer); + portal.inPortal.add(player.getUniqueId()); player.sendPluginMessage(plugin, "BungeeCord", out.toByteArray()); // Down to bungee to sort out the teleporting but yea theoretically they should warp. } @@ -430,6 +431,7 @@ public class Portal { } if (portal.hasArg("command.1")) { + warped = true; int commandLine = 1; String command = portal.getArg("command." + commandLine);//portalData.getConfig().getString(portal.getName()+ ".portalArgs.command." + commandLine); do { @@ -477,7 +479,7 @@ public class Portal { } private static void failSound(Player player, AdvancedPortal portal) { - if(!(portal.getTrigger() == Material.NETHER_PORTAL && player.getGameMode() == GameMode.CREATIVE)){ + if(!(portal.getTriggers().contains(Material.NETHER_PORTAL) && player.getGameMode() == GameMode.CREATIVE)){ player.playSound(player.getLocation(), portalSound, 0.2f, new Random().nextFloat() * 0.4F + 0.8F); } } @@ -531,8 +533,12 @@ public class Portal { return false; } + public static boolean locationInPortalTrigger(AdvancedPortal portal, Location loc, int additionalArea) { + return portal.getTriggers().contains(loc.getBlock().getType()) && locationInPortal(portal, loc, additionalArea); + } + public static boolean locationInPortalTrigger(AdvancedPortal portal, Location loc) { - return portal.getTrigger().equals(loc.getBlock().getType()) && locationInPortal(portal, loc, 0); + return locationInPortalTrigger(portal, loc, 0); } public static boolean inPortalRegion(Location loc, int additionalArea) { @@ -549,6 +555,10 @@ public class Portal { return false; } + public static boolean locationInPortal(AdvancedPortal portal, Location loc) { + return locationInPortal(portal, loc); + } + public static boolean locationInPortal(AdvancedPortal portal, Location loc, int additionalArea) { if (!portalsActive) return false; diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index a856cff..6121325 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ main: com.sekwah.advancedportals.AdvancedPortalsPlugin name: AdvancedPortals -version: 0.0.49 +version: 0.1.0 author: sekwah41 description: An advanced portals plugin for bukkit. api-version: 1.13