onTabComplete(CommandSender sender, String[] args);
+
+ /**
+ * @return the string to show on the above help menu. (describing the subcommand)
+ */
+ String getHelpText();
+
+}
diff --git a/src/com/sekwah/advancedportals/core/api/destination/Destination.java b/src/com/sekwah/advancedportals/core/api/destination/Destination.java
new file mode 100644
index 00000000..cbad38c7
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/destination/Destination.java
@@ -0,0 +1,13 @@
+package com.sekwah.advancedportals.core.api.destination;
+
+/**
+ * Possibly look at adding the ability to add some tags to destinations such as permissions. Would make it easier
+ * to add permissions to block access to certain areas and such. Could be a different permission system or just
+ * it takes the tags on the destination and automatically applies them when a portal wants to warp to there.
+ * (Of course it would not work cross server unless the data was communicated and checked first however that
+ * could effect performance and would definitely effect speed)
+ *
+ * @author sekwah41
+ */
+public class Destination {
+}
diff --git a/src/com/sekwah/advancedportals/core/api/effect/TestEffect.java b/src/com/sekwah/advancedportals/core/api/effect/TestEffect.java
new file mode 100644
index 00000000..397aac84
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/effect/TestEffect.java
@@ -0,0 +1,21 @@
+package com.sekwah.advancedportals.core.api.effect;
+
+import com.sekwah.advancedportals.core.api.portal.Portal;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+
+/**
+ * @author sekwah41
+ */
+public class TestEffect implements WarpEffect {
+
+ @Override
+ public void onWarp(Player player, Location loc, Action action, Portal portal) {
+
+ }
+
+ @Override
+ public Type getType() {
+ return null;
+ }
+}
diff --git a/src/com/sekwah/advancedportals/core/api/effect/WarpEffect.java b/src/com/sekwah/advancedportals/core/api/effect/WarpEffect.java
new file mode 100644
index 00000000..7ddcd8ef
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/effect/WarpEffect.java
@@ -0,0 +1,32 @@
+package com.sekwah.advancedportals.core.api.effect;
+
+import com.sekwah.advancedportals.core.api.portal.Portal;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+
+/**
+ * Effects to be registered to the list.
+ *
+ * Fires once at each end.
+ *
+ * Can be a Visual effect or a Sound. Just register to the correct one
+ *
+ * @author sekwah41
+ */
+public interface WarpEffect {
+
+ void onWarp(Player player, Location loc, Action action, Portal portal);
+
+ Type getType();
+
+ enum Action {
+ ENTER,
+ EXIT;
+ }
+
+ enum Type {
+ SOUND,
+ VISUAL;
+ }
+
+}
diff --git a/src/com/sekwah/advancedportals/core/api/events/PortalEditEvent.java b/src/com/sekwah/advancedportals/core/api/events/PortalEditEvent.java
new file mode 100644
index 00000000..c795bc18
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/events/PortalEditEvent.java
@@ -0,0 +1,21 @@
+package com.sekwah.advancedportals.core.api.events;
+
+/**
+ * Activated when something about the event is edited.
+ *
+ * @author sekwah41
+ */
+public class PortalEditEvent {
+
+ public class TagChange {
+
+ }
+
+ public class Renamed {
+
+ }
+
+ public class Moved {
+
+ }
+}
diff --git a/src/com/sekwah/advancedportals/core/api/events/PortalsLoadedEvent.java b/src/com/sekwah/advancedportals/core/api/events/PortalsLoadedEvent.java
new file mode 100644
index 00000000..1fb73a62
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/events/PortalsLoadedEvent.java
@@ -0,0 +1,16 @@
+package com.sekwah.advancedportals.core.api.events;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+/**
+ * Triggered once all the portals are loaded
+ *
+ * @author sekwah41
+ */
+public class PortalsLoadedEvent extends Event {
+ @Override
+ public HandlerList getHandlers() {
+ return null;
+ }
+}
diff --git a/src/com/sekwah/advancedportals/core/api/events/WarpEvent.java b/src/com/sekwah/advancedportals/core/api/events/WarpEvent.java
new file mode 100644
index 00000000..ada9ca33
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/events/WarpEvent.java
@@ -0,0 +1,76 @@
+package com.sekwah.advancedportals.bukkit.api.events;
+
+import com.sekwah.advancedportals.bukkit.portals.AdvancedPortal;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+/**
+ * Trigered whenever a player activates the warp after the tags are handled.
+ */
+public class WarpEvent extends Event implements Cancellable {
+
+ private static HandlerList handlers = new HandlerList();
+
+ private boolean cancelled = false;
+
+ private final Player player;
+
+ @SuppressWarnings("unused")
+ private final AdvancedPortal portalData;
+
+ private boolean hasWarped = false;
+
+ /*public WarpEvent(Player player, AdvancedPortal portalData) {
+ this.player = player;
+ this.portalData = portalData;
+ }*/
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ /**
+ * Returns if the event has been cancelled
+ *
+ * @return cancelled
+ */
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ public void setCancelled(boolean cancel) {
+ cancelled = cancel;
+ }
+
+ /*public AdvancedPortal getPortalData() {
+ return portalData;
+ }*/
+
+ /**
+ * This will return true if another plugin has warped the player(and set this to true)
+ *
+ * @return hasWarped
+ */
+ public boolean getHasWarped() {
+ return hasWarped;
+ }
+
+ /**
+ * If the
+ *
+ * @param warped
+ */
+ public void setHasWarped(boolean warped) {
+ this.hasWarped = warped;
+ }
+
+ public Player getPlayer() {
+ return player;
+ }
+
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+}
diff --git a/src/com/sekwah/advancedportals/core/api/managers/DestinationManager.java b/src/com/sekwah/advancedportals/core/api/managers/DestinationManager.java
new file mode 100644
index 00000000..c60339ad
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/managers/DestinationManager.java
@@ -0,0 +1,7 @@
+package com.sekwah.advancedportals.core.api.managers;
+
+/**
+ * @author sekwah41
+ */
+public class DestinationManager {
+}
diff --git a/src/com/sekwah/advancedportals/core/api/managers/PortalManager.java b/src/com/sekwah/advancedportals/core/api/managers/PortalManager.java
new file mode 100644
index 00000000..17606182
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/managers/PortalManager.java
@@ -0,0 +1,50 @@
+package com.sekwah.advancedportals.core.api.managers;
+
+import com.sekwah.advancedportals.core.api.portal.Portal;
+import org.bukkit.entity.Player;
+
+import java.util.HashMap;
+
+/**
+ * When a player leaves the server any data stored on them is removed to free memory.
+ *
+ * @author sekwah41
+ */
+public class PortalManager {
+
+ /**
+ * Cooldown time for players to try entering portals.
+ */
+ private static final int COOLDOWN = 0;
+
+ private static PortalManager instance = new PortalManager();
+ /**
+ * Store data of when the player last entered the portal
+ */
+ private HashMap lastAttempt = new HashMap();
+ /**
+ * Tracks what portal a player has selected
+ */
+ private HashMap selectedPortal = new HashMap();
+
+ public PortalManager() {
+ this.loadPortals();
+ }
+
+ /**
+ * A player has left the server
+ *
+ * @param player
+ */
+ public static void playerLeave(Player player) {
+ instance.lastAttempt.remove(player);
+ instance.selectedPortal.remove(player);
+ }
+
+ /**
+ * Load the default data into the portals.
+ */
+ private void loadPortals() {
+
+ }
+}
diff --git a/src/com/sekwah/advancedportals/core/api/portal/Portal.java b/src/com/sekwah/advancedportals/core/api/portal/Portal.java
new file mode 100644
index 00000000..5919a911
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/portal/Portal.java
@@ -0,0 +1,7 @@
+package com.sekwah.advancedportals.core.api.portal;
+
+/**
+ * @author sekwah41
+ */
+public class Portal {
+}
diff --git a/src/com/sekwah/advancedportals/core/api/portal/PortalTag.java b/src/com/sekwah/advancedportals/core/api/portal/PortalTag.java
new file mode 100644
index 00000000..9868a5a2
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/portal/PortalTag.java
@@ -0,0 +1,16 @@
+package com.sekwah.advancedportals.core.api.portal;
+
+public class PortalTag {
+
+ public final String NAME;
+ public final String VALUE;
+ //public final int type;
+
+ public PortalTag(String argName, String value/*, int type*/) {
+ this.NAME = argName;
+ this.VALUE = value;
+ // may be used if values need to be 100% not string
+ //this.type = type;
+ }
+
+}
diff --git a/src/com/sekwah/advancedportals/core/api/registry/DestinationSubCommandRegistry.java b/src/com/sekwah/advancedportals/core/api/registry/DestinationSubCommandRegistry.java
new file mode 100644
index 00000000..8546a2f1
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/registry/DestinationSubCommandRegistry.java
@@ -0,0 +1,9 @@
+package com.sekwah.advancedportals.core.api.registry;
+
+/**
+ * Designed to let addons add new command sections to access, edit or add new functonality.
+ *
+ * @author sekwah41
+ */
+public class DestinationSubCommandRegistry extends SubCommandRegistry {
+}
diff --git a/src/com/sekwah/advancedportals/core/api/registry/PortalSubCommandRegistry.java b/src/com/sekwah/advancedportals/core/api/registry/PortalSubCommandRegistry.java
new file mode 100644
index 00000000..f379f7a6
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/registry/PortalSubCommandRegistry.java
@@ -0,0 +1,11 @@
+package com.sekwah.advancedportals.core.api.registry;
+
+/**
+ * Designed to let addons add new command sections to access, edit or add new functonality.
+ *
+ * @author sekwah41
+ */
+public class PortalSubCommandRegistry extends SubCommandRegistry {
+
+
+}
diff --git a/src/com/sekwah/advancedportals/core/api/registry/SubCommandRegistry.java b/src/com/sekwah/advancedportals/core/api/registry/SubCommandRegistry.java
new file mode 100644
index 00000000..b0205aee
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/registry/SubCommandRegistry.java
@@ -0,0 +1,84 @@
+package com.sekwah.advancedportals.core.api.registry;
+
+import com.sekwah.advancedportals.core.AdvancedPortalsCore;
+import com.sekwah.advancedportals.core.api.commands.SubCommand;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Do not register to here. Register to the sprcific subcommand registry classes.
+ *
+ * Designed to let addons add new command sections to access, edit or add new functonality.
+ *
+ * @author sekwah41
+ */
+public class SubCommandRegistry {
+
+ private Map subCommandMap = new HashMap<>();
+
+ private static final SubCommandRegistry instance = new SubCommandRegistry();
+
+ /**
+ * List of subcommand names which should be in order alphabetically
+ */
+ private ArrayList subCommands = new ArrayList<>();
+
+ /**
+ * @param arg argument needed to activate
+ * @param subCommand
+ * @return if the subcommand is registered or not
+ */
+ public static boolean registerSubCommand(String arg, SubCommand subCommand) {
+
+ if (subCommand == null) {
+ AdvancedPortalsCore.getInfoLogger().logWarning("The subcommand '" + arg + "' cannot be null.");
+ return false;
+ }
+
+ if(!instance.subCommandMap.containsKey(arg)){
+ AdvancedPortalsCore.getInfoLogger().logWarning("The subcommand '" + arg + "' already exists.");
+ return false;
+ }
+
+ instance.subCommandMap.put(arg.toLowerCase(), subCommand);
+
+ instance.subCommands.add(arg.toLowerCase());
+
+ Collections.sort(instance.subCommands);
+
+ return true;
+ }
+
+ /**
+ * @return a list of arguments of registered subcommands
+ */
+ public static ArrayList getSubCommands(){
+ return instance.subCommands;
+ }
+
+ /**
+ * I may be wrong but for larger lists containsKey is faster with a hashmap than arraylist.
+ *
+ * Though im not sure at what size it becomes more efficient.
+ * @param arg
+ * @return if the argument is registered
+ */
+ public static boolean isArgRegistered(String arg){
+ return instance.subCommandMap.containsKey(arg.toLowerCase());
+ }
+
+ /**
+ * Gets the subcommand corresponding to the string argument
+ * @param arg
+ * @return the subcommand linked to the arg
+ */
+ public static SubCommand getSubCommand(String arg){
+ if(instance.subCommandMap.containsKey(arg.toLowerCase())){
+ return instance.subCommandMap.get(arg.toLowerCase());
+ }
+ return null;
+ }
+}
diff --git a/src/com/sekwah/advancedportals/core/api/registry/TagRegistry.java b/src/com/sekwah/advancedportals/core/api/registry/TagRegistry.java
new file mode 100644
index 00000000..6079cf45
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/registry/TagRegistry.java
@@ -0,0 +1,123 @@
+package com.sekwah.advancedportals.api.registry;
+
+import com.sekwah.advancedportals.api.warphandler.TagHandler;
+import com.sekwah.advancedportals.core.AdvancedPortalsCore;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Allows a portal to register a tag and add a handler. If a plugin wants to add functionality
+ * to someone elses tag then they should use the events.
+ *
+ * @author sekwah41
+ */
+public class TagRegistry {
+
+ // TODO the event can be used for general data detection and management, but use a TagHandler to make it so they can register
+ // the individual class to handle.
+ private static TagRegistry instance = new TagRegistry();
+
+ /**
+ * List of tag names which should be in order alphabetically
+ */
+ private ArrayList tags = new ArrayList();
+ /**
+ * Description of tags for help commands
+ */
+ private Map tagDesc = new HashMap();
+ private Map activationHandlers = new HashMap();
+ private Map creationHandlers = new HashMap();
+ private Map statusHandlers = new HashMap();
+
+ /**
+ *
+ * @param tag
+ * @param desc
+ * @param tagHandler
+ * @return if the tag was registered
+ */
+ public static boolean registerTag(String tag, String desc, TagHandler tagHandler) {
+ if (registerTag(tag, tagHandler)) {
+ instance.tagDesc.put(tag, desc);
+ }
+ return false;
+ }
+
+
+ /**
+ * It is reccomended that you use the taghandlers to add tag functionality. However
+ * if needed such as extra data for a tag then this is here.
+ *
+ * @param tag
+ * @return if the tag was registered
+ */
+ public static boolean registerTag(String tag) {
+ if (tag.contains(" ")) {
+ AdvancedPortalsCore.getInfoLogger().logWarning("The tag '"
+ + tag + "' is invalid as it contains spaces.");
+ return false;
+ }
+ if (instance.tags.contains(tag)) {
+ AdvancedPortalsCore.getInfoLogger().logWarning("The tag "
+ + tag + " has already been registered.");
+ return false;
+ }
+ instance.tags.add(tag);
+ Collections.sort(instance.tags);
+ return true;
+ }
+
+ /**
+ * Same as registerTag(String tag) but allows a description to be added.
+ *
+ * @param tag Tag to be used on command line
+ * @param desc
+ * @return if the tag was registered
+ */
+ public static boolean registerTag(String tag, String desc) {
+ if (registerTag(tag)) {
+ instance.tagDesc.put(tag, desc);
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isTagRegistered(String tag){
+ return instance.tagDesc.containsKey(tag);
+ }
+
+ /**
+ * @return if the tag has been registered or if it already exists.
+ */
+ public static boolean registerTag(String tag, TagHandler tagHandler) {
+
+ if (tag == null) {
+ AdvancedPortalsCore.getInfoLogger().logWarning("A tag cannot be null.");
+ return false;
+ }
+
+ if (!registerTag(tag)) {
+ return false;
+ }
+
+ if (tagHandler != null && !(tagHandler instanceof TagHandler.Activation) && !(tagHandler instanceof TagHandler.TagStatus) &&
+ !(tagHandler instanceof TagHandler.Creation)) {
+ AdvancedPortalsCore.getInfoLogger().logWarning("Error with tag: " + tag + ". A tag handler must implement one of the handlers. Not just extend.");
+ if (tagHandler instanceof TagHandler.Activation) {
+ instance.activationHandlers.put(tag, (TagHandler.Activation) tagHandler);
+ }
+ if (tagHandler instanceof TagHandler.TagStatus) {
+ instance.statusHandlers.put(tag, (TagHandler.TagStatus) tagHandler);
+ }
+ if (tagHandler instanceof TagHandler.Creation) {
+ instance.creationHandlers.put(tag, (TagHandler.Creation) tagHandler);
+ }
+ }
+ return true;
+ }
+
+
+}
diff --git a/src/com/sekwah/advancedportals/core/api/registry/WarpEffectRegistry.java b/src/com/sekwah/advancedportals/core/api/registry/WarpEffectRegistry.java
new file mode 100644
index 00000000..f32b62d9
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/registry/WarpEffectRegistry.java
@@ -0,0 +1,76 @@
+package com.sekwah.advancedportals.core.api.registry;
+
+import com.sekwah.advancedportals.core.AdvancedPortalsCore;
+import com.sekwah.advancedportals.core.api.effect.WarpEffect;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author sekwah41
+ */
+public class WarpEffectRegistry {
+
+
+ private Map visualEffects = new HashMap();
+
+ private Map soundEffects = new HashMap();
+
+ private static final WarpEffectRegistry instance = new WarpEffectRegistry();
+
+ /**
+ * Register a new warp effect.
+ *
+ * @param name
+ * @param effect
+ * @return if the effect was registered
+ */
+ public static boolean registerEffect(String name, WarpEffect effect) {
+ if(name == null){
+ return false;
+ }
+ Map list = null;
+ switch (effect.getType()){
+ case SOUND:
+ list = instance.soundEffects;
+ break;
+ case VISUAL:
+ list = instance.visualEffects;
+ break;
+ default:
+ AdvancedPortalsCore.getInfoLogger().logWarning(effect.getType().toString()
+ + " effect type not recognised");
+ return false;
+ }
+ if(list.containsKey(name)){
+ return false;
+ }
+ list.put(name, effect);
+ return true;
+ }
+
+ public static WarpEffect getEffect(String name, WarpEffect.Type type){
+ Map list = null;
+ switch (type){
+ case SOUND:
+ list = instance.soundEffects;
+ break;
+ case VISUAL:
+ list = instance.visualEffects;
+ break;
+ default:
+ AdvancedPortalsCore.getInfoLogger().logWarning(type.toString()
+ + " effect type not recognised");
+ return null;
+ }
+ if(list.containsKey(name)) {
+ return list.get(name);
+ }
+ else{
+ AdvancedPortalsCore.getInfoLogger().logWarning("No effect of type:"
+ + type.toString() + " was registered with the name: " + name);
+ return null;
+ }
+ }
+
+}
diff --git a/src/com/sekwah/advancedportals/core/api/warphandler/ActivationData.java b/src/com/sekwah/advancedportals/core/api/warphandler/ActivationData.java
new file mode 100644
index 00000000..9dad3933
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/warphandler/ActivationData.java
@@ -0,0 +1,60 @@
+package com.sekwah.advancedportals.bukkit.api.warphandler;
+
+import com.sekwah.advancedportals.bukkit.portals.Portal;
+
+public class ActivationData {
+
+ private boolean warpAllowed = true;
+
+ private WarpedStatus warpStatus = WarpedStatus.INACTIVE;
+
+ private final Portal activePortal;
+
+ /*public ActivationData(Portal portal){
+ this.activePortal = portal;
+ }
+*/
+ public WarpedStatus getWarped() {
+ return this.warpStatus;
+ }
+
+ public void setWarpStatus(WarpedStatus warped){
+ if(this.warpStatus == WarpedStatus.WARPED || this.warpStatus == WarpedStatus.INACTIVE){
+ return;
+ }
+ this.warpStatus = warped;
+ }
+
+ /**
+ * In case you need to set the status back down a step for whatever reason. However it is not recommended.
+ *
+ * @param warped
+ */
+ public void setWarpStatusAbsolute(WarpedStatus warped) {
+ this.warpStatus = warped;
+ }
+
+ public boolean getAllowed() {
+ return this.warpAllowed;
+ }
+
+ public void setAllowed(boolean allowed) {
+ this.warpAllowed = allowed;
+ }
+
+ public enum WarpedStatus {
+ /**
+ * Player has moved or something major has happened. (only one of these should activate)
+ */
+ WARPED,
+ /**
+ * Shows that the portal has been activated even if a major function is not performed.
+ */
+ ACTIVATED,
+ /**
+ * Nothing has activated on the portal.
+ */
+ INACTIVE
+ }
+
+}
diff --git a/src/com/sekwah/advancedportals/core/api/warphandler/TagHandler.java b/src/com/sekwah/advancedportals/core/api/warphandler/TagHandler.java
new file mode 100644
index 00000000..c7a04b96
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/api/warphandler/TagHandler.java
@@ -0,0 +1,96 @@
+package com.sekwah.advancedportals.bukkit.api.warphandler;
+
+import org.bukkit.entity.Player;
+
+public class TagHandler {
+
+ /**
+ * When the user wants to activate the tag, not all will support this of course. its just a _ before or after the tag
+ * to specify
+ */
+ public enum ActivatePref{
+ BEFORE,
+ AFTER,
+ DEFAULT;
+ }
+
+ public interface Creation {
+
+ /**
+ * Example if the player does not have access to use a tag on the portal.
+ *
+ * @param player if null the portal has been created by the server or a plugin
+ * @param activeData
+ * @param argData
+ * @return if the portal can be created.
+ */
+ boolean portalCreated(@Nullable Player player, ActivationData activeData, String argData);
+
+ /**
+ * Example if the player does not have access to remove the portal.
+ *
+ * @param player if null the portal has been destroyed by the server or a plugin
+ * @param activeData
+ * @param argData
+ * @return if the portal can be destroyed.
+ */
+ boolean portalDestroyed(@Nullable Player player, ActivationData activeData, String argData);
+
+ }
+
+ public interface Activation {
+
+ /**
+ * Activates before the main part of portal activation.
+ *
+ * @param player
+ * @param activeData
+ * @param argData
+ */
+ void portalPreActivated(Player player, ActivationData activeData, String argData);
+
+ /**
+ * Activates after portal activation
+ *
+ * @param player
+ * @param activeData
+ * @param argData
+ */
+ void portalPostActivated(Player player, ActivationData activeData, String argData);
+
+ /**
+ * Activates if the portal is allowed from pre
+ *
+ * @param player
+ * @param activeData
+ * @param argData
+ */
+ void portalActivated(Player player, ActivationData activeData, String argData);
+
+ }
+
+ public interface TagStatus {
+
+ /**
+ * If the user has access to add the tag
+ *
+ * @param player
+ * @param activeData
+ * @param argData
+ * @return if the tag will be added.
+ */
+ boolean tagAdded(@Nullable Player player, ActivationData activeData, String argData);
+
+ /**
+ * If the user has access to remove the tag
+ *
+ * @param player
+ * @param activeData
+ * @param argData
+ * @return if the tag will be removed.
+ */
+ boolean tagRemoved(Player player, ActivationData activeData, String argData);
+
+ }
+
+}
diff --git a/src/com/sekwah/advancedportals/core/util/DataStorage.java b/src/com/sekwah/advancedportals/core/util/DataStorage.java
new file mode 100644
index 00000000..2ab7434f
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/util/DataStorage.java
@@ -0,0 +1,97 @@
+package com.sekwah.advancedportals.core.util;
+
+import com.sekwah.advancedportals.core.AdvancedPortalsCore;
+
+import java.io.*;
+
+public abstract class DataStorage {
+
+ protected File dataFolder;
+
+ /**
+ * Copies the default file, defaults to true to keep true to the name
+ *
+ * @param fileLoc
+ * @return
+ */
+ public boolean copyDefaultFile(String fileLoc) {
+ return this.copyDefaultFile(fileLoc, true);
+ }
+
+ public void copyDefaultFiles(boolean override, String... fileLocs) {
+ for (String fileLoc : fileLocs) {
+ this.copyDefaultFile(fileLoc, override);
+ }
+ }
+
+ /**
+ * Copies the specified file out of the plugin and into the plugins folder.
+ *
+ * @param fileLoc
+ * @return if the file is copied, will be false if override is false and the file already existed.
+ */
+ public boolean copyDefaultFile(String fileLoc, boolean overwrite) {
+ File outFile = new File(this.dataFolder, fileLoc);
+ if (!outFile.exists()) {
+ outFile.getParentFile().mkdirs();
+ }
+ if (!outFile.exists() || overwrite) {
+ try {
+ InputStream inputStream = DataStorage.class.getClassLoader().getResourceAsStream(fileLoc);
+ FileOutputStream outStream = new FileOutputStream(outFile);
+
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = inputStream.read(buf)) > 0) {
+ outStream.write(buf, 0, len);
+ }
+ inputStream.close();
+ outStream.close();
+ } catch (NullPointerException e) {
+ e.printStackTrace();
+ AdvancedPortalsCore.getInfoLogger().logWarning("Could not load " + fileLoc + ". The file does" +
+ "not exist or there has been an error reading the file.");
+ return false;
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ AdvancedPortalsCore.getInfoLogger().logWarning("Could not create " + fileLoc);
+ } catch (IOException e) {
+ e.printStackTrace();
+ AdvancedPortalsCore.getInfoLogger().logWarning("File error reading " + fileLoc);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * A method to try to grab the files from the plugin and if its in the plugin folder load from there instead.
+ *
+ * TODO add loading from the plugin folder first rather than straight from the plugin.
+ *
+ * @param lang
+ * @param location
+ * @return
+ */
+ public InputStream loadResource(Lang lang, String location) {
+ File inFile = new File(dataFolder, location);
+ if (inFile.exists() && !inFile.isDirectory()) {
+ try {
+ return new FileInputStream(inFile);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ return null;
+ }
+ } else {
+ try {
+ copyDefaultFile(location, false);
+ return lang.getClass().getClassLoader().getResourceAsStream(location);
+ } catch (NullPointerException e) {
+ e.printStackTrace();
+ AdvancedPortalsCore.getInfoLogger().logWarning("Could not load " + location + ". The file does" +
+ "not exist or there has been an error reading the file.");
+ return null;
+ }
+ }
+ }
+
+}
diff --git a/src/com/sekwah/advancedportals/core/util/InfoLogger.java b/src/com/sekwah/advancedportals/core/util/InfoLogger.java
new file mode 100644
index 00000000..5289cb7e
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/util/InfoLogger.java
@@ -0,0 +1,5 @@
+package com.sekwah.advancedportals.core.util;
+
+public abstract class InfoLogger {
+ public abstract void logWarning(String s);
+}
diff --git a/src/com/sekwah/advancedportals/core/util/Lang.java b/src/com/sekwah/advancedportals/core/util/Lang.java
new file mode 100644
index 00000000..c480d499
--- /dev/null
+++ b/src/com/sekwah/advancedportals/core/util/Lang.java
@@ -0,0 +1,113 @@
+package com.sekwah.advancedportals.core.util;
+
+import com.google.common.collect.Maps;
+import com.sekwah.advancedportals.core.AdvancedPortalsCore;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+import java.util.Scanner;
+
+/**
+ * @author sekwah41
+ *
+ * The language translation file for the game. Will always load english first
+ * so that if the translations are missing any then they are still readable and can then be translated.
+ * (Its better than a raw translate string)
+ *
+ * TODO add a loaddefault where it only loads from the plugins version of the data rather than paying attention to any
+ * possible changed versions in the lang folder.
+ */
+public class Lang {
+
+ private static final Lang instance = new Lang();
+ private final Map languageMap = Maps.newHashMap();
+ private final String DEFAULT_LANG = "en_GB";
+
+ public Lang() {
+ injectTranslations(this, DEFAULT_LANG);
+ }
+
+ public static void loadLanguage(String fileName) {
+ instance.injectTranslations(instance, fileName);
+ }
+
+ public static String translate(String s) {
+ if (instance.languageMap.containsKey(s)) {
+ return instance.languageMap.get(s);
+ } else {
+ return s;
+ }
+ }
+
+ public static String translateInsertVariables(String s, String... args) {
+ String translation = instance.translate(s);
+ for (int i = 1; i <= args.length; i++) {
+ translation = translation.replaceAll("%" + i + "$s", args[i]);
+ }
+ return translation;
+ }
+
+ public static String translateInsertVariablesColor(String s, String... args) {
+ String translation = instance.translateColor(s);
+ for (int i = 1; i <= args.length; i++) {
+ translation = translation.replaceAll("%" + i + "$s", args[i]);
+ }
+ return translation;
+ }
+
+ public static String translateColor(String s) {
+ String translation = instance.translate(s);
+ translation = translation.replaceAll("\\\\u00A7", "\u00A7");
+ return translation;
+ }
+
+ private void injectTranslations(Lang lang, String fileName) {
+ try {
+ //URL url = lang.getClass().getClassLoader().getResource("lang/" + fileName + ".lang");
+ //System.out.println(url);
+ //Map newLangMap = lang.parseLang(url.openStream());
+ InputStream stream = AdvancedPortalsCore.getDataStorage().loadResource(lang, "lang/" + fileName + ".lang");
+ if (stream != null) {
+ Map newLangMap = lang.parseLang(stream);
+ if (newLangMap != null) {
+ lang.languageMap.putAll(newLangMap);
+ }
+ }
+ } catch (NullPointerException e) {
+ e.printStackTrace();
+ AdvancedPortalsCore.getInfoLogger().logWarning("Could not load " + fileName + ".lang The file does" +
+ "not exist or there has been an error reading the file. Canceled loading language file.");
+ }
+ }
+
+ private Map parseLang(InputStream inputStream) {
+ Scanner scanner = new Scanner(inputStream, "UTF-8");
+ String line = getNextLine(scanner);
+ Map newMap = Maps.newHashMap();
+ while (scanner != null && line != null) {
+ //System.out.println(line);
+ if (!line.startsWith("#") && line.indexOf('=') > -1) {
+ int split = line.indexOf('=');
+ String key = line.substring(0, split);
+ String value = line.substring(split + 1, line.length());
+ newMap.put(key, value);
+ }
+ line = getNextLine(scanner);
+ // TODO add split code at the first = and also conversion of strings/codes which are constants like colors.
+ }
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return newMap;
+ }
+
+ private String getNextLine(Scanner scanner) {
+ if (scanner.hasNextLine()) {
+ return scanner.nextLine();
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/sekwah/advancedportals/bukkit/api/events/WarpEvent.java b/src/main/java/com/sekwah/advancedportals/bukkit/api/events/WarpEvent.java
index f09164f5..ada9ca33 100644
--- a/src/main/java/com/sekwah/advancedportals/bukkit/api/events/WarpEvent.java
+++ b/src/main/java/com/sekwah/advancedportals/bukkit/api/events/WarpEvent.java
@@ -6,13 +6,12 @@ import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
-public final class WarpEvent extends Event implements Cancellable {
+/**
+ * Trigered whenever a player activates the warp after the tags are handled.
+ */
+public class WarpEvent extends Event implements Cancellable {
- /**
- * Use listeners so you can add new triggers easier and also other plugins can listen for the event
- * and add their own triggers
- */
- private static final HandlerList handlers = new HandlerList();
+ private static HandlerList handlers = new HandlerList();
private boolean cancelled = false;
@@ -23,10 +22,10 @@ public final class WarpEvent extends Event implements Cancellable {
private boolean hasWarped = false;
- public WarpEvent(Player player, AdvancedPortal portalData) {
+ /*public WarpEvent(Player player, AdvancedPortal portalData) {
this.player = player;
this.portalData = portalData;
- }
+ }*/
public static HandlerList getHandlerList() {
return handlers;
@@ -45,9 +44,9 @@ public final class WarpEvent extends Event implements Cancellable {
cancelled = cancel;
}
- public AdvancedPortal getPortalData() {
+ /*public AdvancedPortal getPortalData() {
return portalData;
- }
+ }*/
/**
* This will return true if another plugin has warped the player(and set this to true)
@@ -63,7 +62,6 @@ public final class WarpEvent extends Event implements Cancellable {
*
* @param warped
*/
- @SuppressWarnings("unused")
public void setHasWarped(boolean warped) {
this.hasWarped = warped;
}
diff --git a/src/main/java/com/sekwah/advancedportals/bukkit/api/warphandler/ActivationData.java b/src/main/java/com/sekwah/advancedportals/bukkit/api/warphandler/ActivationData.java
index 039bb078..9dad3933 100644
--- a/src/main/java/com/sekwah/advancedportals/bukkit/api/warphandler/ActivationData.java
+++ b/src/main/java/com/sekwah/advancedportals/bukkit/api/warphandler/ActivationData.java
@@ -10,11 +10,11 @@ public class ActivationData {
private final Portal activePortal;
- public ActivationData(Portal portal){
+ /*public ActivationData(Portal portal){
this.activePortal = portal;
}
-
- public WarpedStatus getWarped(){
+*/
+ public WarpedStatus getWarped() {
return this.warpStatus;
}
@@ -27,21 +27,22 @@ public class ActivationData {
/**
* In case you need to set the status back down a step for whatever reason. However it is not recommended.
+ *
* @param warped
*/
- public void setWarpStatusAbsolute(WarpedStatus warped){
+ public void setWarpStatusAbsolute(WarpedStatus warped) {
this.warpStatus = warped;
}
- public boolean getAllowed(){
+ public boolean getAllowed() {
return this.warpAllowed;
}
- public void setAllowed(boolean allowed){
+ public void setAllowed(boolean allowed) {
this.warpAllowed = allowed;
}
- public enum WarpedStatus{
+ public enum WarpedStatus {
/**
* Player has moved or something major has happened. (only one of these should activate)
*/
diff --git a/src/main/java/com/sekwah/advancedportals/bukkit/api/warphandler/TagHandler.java b/src/main/java/com/sekwah/advancedportals/bukkit/api/warphandler/TagHandler.java
index 28f1b862..c7a04b96 100644
--- a/src/main/java/com/sekwah/advancedportals/bukkit/api/warphandler/TagHandler.java
+++ b/src/main/java/com/sekwah/advancedportals/bukkit/api/warphandler/TagHandler.java
@@ -4,32 +4,45 @@ import org.bukkit.entity.Player;
public class TagHandler {
- public interface Creation{
+ /**
+ * When the user wants to activate the tag, not all will support this of course. its just a _ before or after the tag
+ * to specify
+ */
+ public enum ActivatePref{
+ BEFORE,
+ AFTER,
+ DEFAULT;
+ }
+
+ public interface Creation {
/**
* Example if the player does not have access to use a tag on the portal.
- * @param player
+ *
+ * @param player if null the portal has been created by the server or a plugin
* @param activeData
* @param argData
* @return if the portal can be created.
*/
- boolean portalCreated(Player player, ActivationData activeData, String argData);
+ boolean portalCreated(@Nullable Player player, ActivationData activeData, String argData);
/**
* Example if the player does not have access to remove the portal.
- * @param player
+ *
+ * @param player if null the portal has been destroyed by the server or a plugin
* @param activeData
* @param argData
* @return if the portal can be destroyed.
*/
- boolean portalDestroyed(Player player, ActivationData activeData, String argData);
+ boolean portalDestroyed(@Nullable Player player, ActivationData activeData, String argData);
}
- public interface Activation{
+ public interface Activation {
/**
* Activates before the main part of portal activation.
+ *
* @param player
* @param activeData
* @param argData
@@ -38,6 +51,7 @@ public class TagHandler {
/**
* Activates after portal activation
+ *
* @param player
* @param activeData
* @param argData
@@ -46,6 +60,7 @@ public class TagHandler {
/**
* Activates if the portal is allowed from pre
+ *
* @param player
* @param activeData
* @param argData
@@ -54,19 +69,21 @@ public class TagHandler {
}
- public interface TagStatus{
+ public interface TagStatus {
/**
* If the user has access to add the tag
+ *
* @param player
* @param activeData
* @param argData
* @return if the tag will be added.
*/
- boolean tagAdded(Player player, ActivationData activeData, String argData);
+ boolean tagAdded(@Nullable Player player, ActivationData activeData, String argData);
/**
* If the user has access to remove the tag
+ *
* @param player
* @param activeData
* @param argData