mirror of
https://github.com/TotalFreedomMC/TF-ProjectKorra.git
synced 2024-12-23 00:15:05 +00:00
Setup ability registry
This commit is contained in:
parent
ad148a7881
commit
809c451461
7 changed files with 261 additions and 322 deletions
|
@ -57,7 +57,6 @@ import java.util.jar.JarFile;
|
|||
public abstract class Ability<Config extends AbilityConfig> {
|
||||
|
||||
private static final double DEFAULT_COLLISION_RADIUS = 0.3;
|
||||
private static final List<String> ADDON_PLUGINS = new ArrayList<>();
|
||||
private static final Map<Class<? extends Ability>, Map<String, Field>> ATTRIBUTE_FIELDS = new HashMap<>();
|
||||
|
||||
private static int idCounter;
|
||||
|
@ -94,7 +93,7 @@ public abstract class Ability<Config extends AbilityConfig> {
|
|||
* @see #ABILITIES_BY_NAME
|
||||
* @see #getAbility(String)
|
||||
*/
|
||||
public Ability() {
|
||||
private Ability() {
|
||||
for (final Field field : this.getClass().getDeclaredFields()) {
|
||||
if (field.isAnnotationPresent(Attribute.class)) {
|
||||
final Attribute attribute = field.getAnnotation(Attribute.class);
|
||||
|
@ -113,7 +112,9 @@ public abstract class Ability<Config extends AbilityConfig> {
|
|||
* @see #start()
|
||||
*/
|
||||
public Ability(final Config config, final Player player) {
|
||||
if (player == null || !this.isEnabled()) {
|
||||
this();
|
||||
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -143,7 +144,7 @@ public abstract class Ability<Config extends AbilityConfig> {
|
|||
* @see #isRemoved()
|
||||
*/
|
||||
public final void start() {
|
||||
if (this.player == null || !this.isEnabled()) {
|
||||
if (this.player == null) {
|
||||
return;
|
||||
}
|
||||
final AbilityStartEvent event = new AbilityStartEvent(this);
|
||||
|
@ -188,152 +189,6 @@ public abstract class Ability<Config extends AbilityConfig> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ability keeps track of plugins that have registered abilities to use
|
||||
* for bending reload purposes <br>
|
||||
* <b>This isn't a simple list, external use isn't recommended</b>
|
||||
*
|
||||
* @return a list of entrys with the plugin name and path abilities can be
|
||||
* found at
|
||||
*/
|
||||
public static List<String> getAddonPlugins() {
|
||||
return ADDON_PLUGINS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans a JavaPlugin and registers Ability class files.
|
||||
*
|
||||
* @param plugin a JavaPlugin containing Ability class files
|
||||
* @param packageBase a prefix of the package name, used to increase
|
||||
* performance
|
||||
* @see #getAbilities()
|
||||
* @see #getAbility(String)
|
||||
*/
|
||||
public static void registerPluginAbilities(final JavaPlugin plugin, final String packageBase) {
|
||||
final com.projectkorra.projectkorra.ability.loader.AbilityLoader<Ability> abilityLoader = new com.projectkorra.projectkorra.ability.loader.AbilityLoader<Ability>(plugin, packageBase);
|
||||
final List<Ability> loadedAbilities = abilityLoader.load(Ability.class, Ability.class);
|
||||
final String entry = plugin.getName() + "::" + packageBase;
|
||||
if (!ADDON_PLUGINS.contains(entry)) {
|
||||
ADDON_PLUGINS.add(entry);
|
||||
}
|
||||
|
||||
for (final Ability coreAbil : loadedAbilities) {
|
||||
if (!coreAbil.isEnabled()) {
|
||||
plugin.getLogger().info(coreAbil.getName() + " is disabled");
|
||||
continue;
|
||||
}
|
||||
|
||||
final String name = coreAbil.getName();
|
||||
|
||||
if (name == null) {
|
||||
plugin.getLogger().warning("Ability " + coreAbil.getClass().getName() + " has no name?");
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
ABILITIES_BY_NAME.put(name.toLowerCase(), coreAbil);
|
||||
ABILITIES_BY_CLASS.put(coreAbil.getClass(), coreAbil);
|
||||
|
||||
if (coreAbil instanceof ComboAbility) {
|
||||
final ComboAbility combo = (ComboAbility) coreAbil;
|
||||
if (combo.getCombination() != null) {
|
||||
ComboManager.getComboAbilities().put(name, new ComboManager.ComboAbilityInfo(name, combo.getCombination(), combo));
|
||||
ComboManager.getDescriptions().put(name, coreAbil.getDescription());
|
||||
ComboManager.getInstructions().put(name, coreAbil.getInstructions());
|
||||
}
|
||||
}
|
||||
|
||||
if (coreAbil instanceof MultiAbility) {
|
||||
final MultiAbility multiAbil = (MultiAbility) coreAbil;
|
||||
MultiAbilityManager.multiAbilityList.add(new MultiAbilityInfo(name, multiAbil.getMultiAbilities()));
|
||||
}
|
||||
|
||||
if (coreAbil instanceof PassiveAbility) {
|
||||
PassiveAbility passive = (PassiveAbility) coreAbil;
|
||||
coreAbil.setHiddenAbility(true);
|
||||
PassiveManager.getPassives().put(name, coreAbil);
|
||||
if (!PassiveManager.getPassiveClasses().containsKey(passive)) {
|
||||
PassiveManager.getPassiveClasses().put(passive, coreAbil.getClass());
|
||||
}
|
||||
}
|
||||
} catch (Exception | Error e) {
|
||||
plugin.getLogger().warning("The ability " + coreAbil.getName() + " was not able to load, if this message shows again please remove it!");
|
||||
e.printStackTrace();
|
||||
ABILITIES_BY_NAME.remove(name.toLowerCase());
|
||||
ABILITIES_BY_CLASS.remove(coreAbil.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans all of the Jar files inside of /ProjectKorra/folder and registers
|
||||
* all of the Ability class files that were found.
|
||||
*
|
||||
* @param folder the name of the folder to scan
|
||||
* @see #getAbilities()
|
||||
* @see #getAbility(String)
|
||||
*/
|
||||
public static void registerAddonAbilities(final String folder) {
|
||||
final ProjectKorra plugin = ProjectKorra.plugin;
|
||||
final File path = new File(plugin.getDataFolder().toString() + folder);
|
||||
if (!path.exists()) {
|
||||
path.mkdir();
|
||||
return;
|
||||
}
|
||||
|
||||
final com.projectkorra.projectkorra.ability.loader.AddonAbilityLoader<Ability> abilityLoader = new AddonAbilityLoader<Ability>(plugin, path);
|
||||
final List<Ability> loadedAbilities = abilityLoader.load(Ability.class, Ability.class);
|
||||
|
||||
for (final Ability coreAbil : loadedAbilities) {
|
||||
if (!(coreAbil instanceof AddonAbility)) {
|
||||
plugin.getLogger().warning(coreAbil.getName() + " is an addon ability and must implement the AddonAbility interface");
|
||||
continue;
|
||||
} else if (!coreAbil.isEnabled()) {
|
||||
plugin.getLogger().info(coreAbil.getName() + " is disabled");
|
||||
continue;
|
||||
}
|
||||
|
||||
final AddonAbility addon = (AddonAbility) coreAbil;
|
||||
final String name = coreAbil.getName();
|
||||
|
||||
try {
|
||||
addon.load();
|
||||
ABILITIES_BY_NAME.put(name.toLowerCase(), coreAbil);
|
||||
ABILITIES_BY_CLASS.put(coreAbil.getClass(), coreAbil);
|
||||
|
||||
if (coreAbil instanceof ComboAbility) {
|
||||
final ComboAbility combo = (ComboAbility) coreAbil;
|
||||
if (combo.getCombination() != null) {
|
||||
ComboManager.getComboAbilities().put(name, new ComboManager.ComboAbilityInfo(name, combo.getCombination(), combo));
|
||||
ComboManager.getDescriptions().put(name, coreAbil.getDescription());
|
||||
ComboManager.getInstructions().put(name, coreAbil.getInstructions());
|
||||
ComboManager.getAuthors().put(name, addon.getAuthor());
|
||||
}
|
||||
}
|
||||
|
||||
if (coreAbil instanceof MultiAbility) {
|
||||
final MultiAbility multiAbil = (MultiAbility) coreAbil;
|
||||
MultiAbilityManager.multiAbilityList.add(new MultiAbilityInfo(name, multiAbil.getMultiAbilities()));
|
||||
}
|
||||
|
||||
if (coreAbil instanceof PassiveAbility) {
|
||||
PassiveAbility passive = (PassiveAbility) coreAbil;
|
||||
coreAbil.setHiddenAbility(true);
|
||||
PassiveManager.getPassives().put(name, coreAbil);
|
||||
if (!PassiveManager.getPassiveClasses().containsKey(passive)) {
|
||||
PassiveManager.getPassiveClasses().put(passive, coreAbil.getClass());
|
||||
}
|
||||
}
|
||||
} catch (Exception | Error e) {
|
||||
plugin.getLogger().warning("The ability " + coreAbil.getName() + " was not able to load, if this message shows again please remove it!");
|
||||
e.printStackTrace();
|
||||
addon.stop();
|
||||
ABILITIES_BY_NAME.remove(name.toLowerCase());
|
||||
ABILITIES_BY_CLASS.remove(coreAbil.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public long getStartTime() {
|
||||
return this.startTime;
|
||||
}
|
||||
|
@ -380,21 +235,21 @@ public abstract class Ability<Config extends AbilityConfig> {
|
|||
return config.Description;
|
||||
}
|
||||
|
||||
public String getMovePreview(final Player player) {
|
||||
final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player);
|
||||
String displayedMessage = "";
|
||||
if (bPlayer.isOnCooldown(this)) {
|
||||
final long cooldown = bPlayer.getCooldown(this.getName()) - System.currentTimeMillis();
|
||||
displayedMessage = this.getElement().getColor() + "" + ChatColor.STRIKETHROUGH + this.getName() + "" + this.getElement().getColor() + " - " + TimeUtil.formatTime(cooldown);
|
||||
} else {
|
||||
if (bPlayer.getStance() != null && bPlayer.getStance().getName().equals(this.getName())) {
|
||||
displayedMessage = this.getElement().getColor() + "" + ChatColor.UNDERLINE + this.getName();
|
||||
} else {
|
||||
displayedMessage = this.getElement().getColor() + this.getName();
|
||||
}
|
||||
}
|
||||
return displayedMessage;
|
||||
}
|
||||
// public String getMovePreview(final Player player) {
|
||||
// final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player);
|
||||
// String displayedMessage = "";
|
||||
// if (bPlayer.isOnCooldown(this)) {
|
||||
// final long cooldown = bPlayer.getCooldown(this.getName()) - System.currentTimeMillis();
|
||||
// displayedMessage = this.getElement().getColor() + "" + ChatColor.STRIKETHROUGH + this.getName() + "" + this.getElement().getColor() + " - " + TimeUtil.formatTime(cooldown);
|
||||
// } else {
|
||||
// if (bPlayer.getStance() != null && bPlayer.getStance().getName().equals(this.getName())) {
|
||||
// displayedMessage = this.getElement().getColor() + "" + ChatColor.UNDERLINE + this.getName();
|
||||
// } else {
|
||||
// displayedMessage = this.getElement().getColor() + this.getName();
|
||||
// }
|
||||
// }
|
||||
// return displayedMessage;
|
||||
// }
|
||||
|
||||
public Player getPlayer() {
|
||||
return this.player;
|
||||
|
@ -406,57 +261,57 @@ public abstract class Ability<Config extends AbilityConfig> {
|
|||
*
|
||||
* @param target The player who now controls the ability
|
||||
*/
|
||||
public void setPlayer(final Player target) {
|
||||
if (target == this.player) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Class<? extends Ability> clazz = this.getClass();
|
||||
|
||||
// The mapping from player UUID to a map of the player's instances.
|
||||
Map<UUID, Map<Integer, Ability>> classMap = INSTANCES_BY_PLAYER.get(clazz);
|
||||
|
||||
if (classMap != null) {
|
||||
// The map of AbilityId to Ability for the current player.
|
||||
final Map<Integer, Ability> playerMap = classMap.get(this.player.getUniqueId());
|
||||
|
||||
if (playerMap != null) {
|
||||
// Remove the ability from the current player's map.
|
||||
playerMap.remove(this.id);
|
||||
|
||||
if (playerMap.isEmpty()) {
|
||||
// Remove the player's empty ability map from global instances map.
|
||||
classMap.remove(this.player.getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
if (classMap.isEmpty()) {
|
||||
INSTANCES_BY_PLAYER.remove(this.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
// Add a new map for the current ability if it doesn't exist in the global map.
|
||||
if (!INSTANCES_BY_PLAYER.containsKey(clazz)) {
|
||||
INSTANCES_BY_PLAYER.put(clazz, new ConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
classMap = INSTANCES_BY_PLAYER.get(clazz);
|
||||
|
||||
// Create an AbilityId to Ability map for the target player if it doesn't exist.
|
||||
if (!classMap.containsKey(target.getUniqueId())) {
|
||||
classMap.put(target.getUniqueId(), new ConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
// Add the current instance to the target player's ability map.
|
||||
classMap.get(target.getUniqueId()).put(this.getId(), this);
|
||||
|
||||
this.player = target;
|
||||
|
||||
final BendingPlayer newBendingPlayer = BendingPlayer.getBendingPlayer(target);
|
||||
if (newBendingPlayer != null) {
|
||||
this.bPlayer = newBendingPlayer;
|
||||
}
|
||||
}
|
||||
// public void setPlayer(final Player target) {
|
||||
// if (target == this.player) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// final Class<? extends Ability> clazz = this.getClass();
|
||||
//
|
||||
// // The mapping from player UUID to a map of the player's instances.
|
||||
// Map<UUID, Map<Integer, Ability>> classMap = INSTANCES_BY_PLAYER.get(clazz);
|
||||
//
|
||||
// if (classMap != null) {
|
||||
// // The map of AbilityId to Ability for the current player.
|
||||
// final Map<Integer, Ability> playerMap = classMap.get(this.player.getUniqueId());
|
||||
//
|
||||
// if (playerMap != null) {
|
||||
// // Remove the ability from the current player's map.
|
||||
// playerMap.remove(this.id);
|
||||
//
|
||||
// if (playerMap.isEmpty()) {
|
||||
// // Remove the player's empty ability map from global instances map.
|
||||
// classMap.remove(this.player.getUniqueId());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (classMap.isEmpty()) {
|
||||
// INSTANCES_BY_PLAYER.remove(this.getClass());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Add a new map for the current ability if it doesn't exist in the global map.
|
||||
// if (!INSTANCES_BY_PLAYER.containsKey(clazz)) {
|
||||
// INSTANCES_BY_PLAYER.put(clazz, new ConcurrentHashMap<>());
|
||||
// }
|
||||
//
|
||||
// classMap = INSTANCES_BY_PLAYER.get(clazz);
|
||||
//
|
||||
// // Create an AbilityId to Ability map for the target player if it doesn't exist.
|
||||
// if (!classMap.containsKey(target.getUniqueId())) {
|
||||
// classMap.put(target.getUniqueId(), new ConcurrentHashMap<>());
|
||||
// }
|
||||
//
|
||||
// // Add the current instance to the target player's ability map.
|
||||
// classMap.get(target.getUniqueId()).put(this.getId(), this);
|
||||
//
|
||||
// this.player = target;
|
||||
//
|
||||
// final BendingPlayer newBendingPlayer = BendingPlayer.getBendingPlayer(target);
|
||||
// if (newBendingPlayer != null) {
|
||||
// this.bPlayer = newBendingPlayer;
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Used by the CollisionManager to check if two instances can collide with
|
||||
|
@ -589,44 +444,44 @@ public abstract class Ability<Config extends AbilityConfig> {
|
|||
* Returns a String used to debug potential Ability memory that can be
|
||||
* caused by a developer forgetting to call {@link #remove()}
|
||||
*/
|
||||
public static String getDebugString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
int playerCounter = 0;
|
||||
final HashMap<String, Integer> classCounter = new HashMap<>();
|
||||
|
||||
for (final Map<UUID, Map<Integer, Ability>> map1 : INSTANCES_BY_PLAYER.values()) {
|
||||
playerCounter++;
|
||||
for (final Map<Integer, Ability> map2 : map1.values()) {
|
||||
for (final Ability coreAbil : map2.values()) {
|
||||
final String simpleName = coreAbil.getClass().getSimpleName();
|
||||
|
||||
if (classCounter.containsKey(simpleName)) {
|
||||
classCounter.put(simpleName, classCounter.get(simpleName) + 1);
|
||||
} else {
|
||||
classCounter.put(simpleName, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (final Set<Ability> set : INSTANCES_BY_CLASS.values()) {
|
||||
for (final Ability coreAbil : set) {
|
||||
final String simpleName = coreAbil.getClass().getSimpleName();
|
||||
if (classCounter.containsKey(simpleName)) {
|
||||
classCounter.put(simpleName, classCounter.get(simpleName) + 1);
|
||||
} else {
|
||||
classCounter.put(simpleName, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sb.append("Class->UUID's in memory: " + playerCounter + "\n");
|
||||
sb.append("Abilities in memory:\n");
|
||||
for (final String className : classCounter.keySet()) {
|
||||
sb.append(className + ": " + classCounter.get(className) + "\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
// public static String getDebugString() {
|
||||
// final StringBuilder sb = new StringBuilder();
|
||||
// int playerCounter = 0;
|
||||
// final HashMap<String, Integer> classCounter = new HashMap<>();
|
||||
//
|
||||
// for (final Map<UUID, Map<Integer, Ability>> map1 : INSTANCES_BY_PLAYER.values()) {
|
||||
// playerCounter++;
|
||||
// for (final Map<Integer, Ability> map2 : map1.values()) {
|
||||
// for (final Ability coreAbil : map2.values()) {
|
||||
// final String simpleName = coreAbil.getClass().getSimpleName();
|
||||
//
|
||||
// if (classCounter.containsKey(simpleName)) {
|
||||
// classCounter.put(simpleName, classCounter.get(simpleName) + 1);
|
||||
// } else {
|
||||
// classCounter.put(simpleName, 1);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// for (final Set<Ability> set : INSTANCES_BY_CLASS.values()) {
|
||||
// for (final Ability coreAbil : set) {
|
||||
// final String simpleName = coreAbil.getClass().getSimpleName();
|
||||
// if (classCounter.containsKey(simpleName)) {
|
||||
// classCounter.put(simpleName, classCounter.get(simpleName) + 1);
|
||||
// } else {
|
||||
// classCounter.put(simpleName, 1);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// sb.append("Class->UUID's in memory: " + playerCounter + "\n");
|
||||
// sb.append("Abilities in memory:\n");
|
||||
// for (final String className : classCounter.keySet()) {
|
||||
// sb.append(className + ": " + classCounter.get(className) + "\n");
|
||||
// }
|
||||
// return sb.toString();
|
||||
// }
|
||||
|
||||
public abstract void progress();
|
||||
|
||||
|
|
|
@ -26,6 +26,16 @@ public @interface AbilityData {
|
|||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* @return The class used to register this ability.
|
||||
*/
|
||||
Class<? extends AbilityLoader> abilityLoader();
|
||||
|
||||
/**
|
||||
* @return true if this is a hidden ability.
|
||||
*/
|
||||
boolean hidden() default false;
|
||||
|
||||
/**
|
||||
* @return the name of the author of this AddonAbility
|
||||
*/
|
||||
|
@ -35,9 +45,4 @@ public @interface AbilityData {
|
|||
* @return The version of the ability as a String.
|
||||
*/
|
||||
String version() default "1.0";
|
||||
|
||||
/**
|
||||
* @return The class used to register this ability.
|
||||
*/
|
||||
Class<? extends AbilityLoader> abilityLoader();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package com.projectkorra.projectkorra.ability;
|
||||
|
||||
public class AbilityException extends RuntimeException {
|
||||
|
||||
public AbilityException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public AbilityException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public AbilityException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
|
@ -4,18 +4,20 @@ import co.aikar.timings.lib.MCTiming;
|
|||
import com.projectkorra.projectkorra.ProjectKorra;
|
||||
import com.projectkorra.projectkorra.ability.api.PassiveAbility;
|
||||
import com.projectkorra.projectkorra.ability.loader.*;
|
||||
import com.projectkorra.projectkorra.ability.util.AbilityRegistery;
|
||||
import com.projectkorra.projectkorra.ability.util.AddonAbilityRegistery;
|
||||
import com.projectkorra.projectkorra.configuration.ConfigManager;
|
||||
import com.projectkorra.projectkorra.configuration.configs.abilities.AbilityConfig;
|
||||
import com.projectkorra.projectkorra.element.Element;
|
||||
import com.projectkorra.projectkorra.element.SubElement;
|
||||
import com.projectkorra.projectkorra.event.AbilityProgressEvent;
|
||||
import com.projectkorra.projectkorra.firebending.FireBlast;
|
||||
import com.projectkorra.projectkorra.module.Module;
|
||||
import com.projectkorra.projectkorra.module.ModuleManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
|
@ -31,6 +33,8 @@ public class AbilityManager extends Module {
|
|||
private final Set<Ability> abilitySet = new HashSet<>();
|
||||
private final Map<UUID, Map<Class<? extends Ability>, LinkedList<Ability>>> abilityMap = new HashMap<>();
|
||||
|
||||
private final Set<String> addonPlugins = new HashSet<>();
|
||||
|
||||
public AbilityManager() {
|
||||
super("Ability");
|
||||
|
||||
|
@ -99,30 +103,76 @@ public class AbilityManager extends Module {
|
|||
this.abilitySet.clear();
|
||||
this.abilityMap.clear();
|
||||
|
||||
Ability.registerPluginAbilities(getPlugin(), "com.projectkorra");
|
||||
Ability.registerAddonAbilities("/Abilities/");
|
||||
registerPluginAbilities("com.projectkorra");
|
||||
registerAddonAbilities("Abilities");
|
||||
|
||||
registerAbility(FireBlast.class);
|
||||
// registerAbility(FireBlast.class);
|
||||
}
|
||||
|
||||
private <T extends Ability> void registerAbility(Class<T> abilityClass) throws IllegalAccessException, InstantiationException {
|
||||
AbilityData abilityData = abilityClass.getDeclaredAnnotation(AbilityData.class);
|
||||
/**
|
||||
* Scans a JavaPlugin and registers Ability class files.
|
||||
*
|
||||
* @param plugin a JavaPlugin containing Ability class files
|
||||
* @param packageBase a prefix of the package name, used to increase
|
||||
* performance
|
||||
* @see #getAbilities()
|
||||
* @see #getAbility(String)
|
||||
*/
|
||||
public void registerPluginAbilities(String packageBase) {
|
||||
AbilityRegistery<Ability> abilityRegistery = new AbilityRegistery<>(getPlugin(), packageBase);
|
||||
List<Class<Ability>> loadedAbilities = abilityRegistery.load(Ability.class, Ability.class);
|
||||
|
||||
if (abilityData == null) {
|
||||
getPlugin().getLogger().warning("Ability " + abilityClass.getName() + " has no AbilityData annotation");
|
||||
String entry = getPlugin().getName() + "::" + packageBase;
|
||||
this.addonPlugins.add(entry);
|
||||
|
||||
for (Class<Ability> abilityClass : loadedAbilities) {
|
||||
AbilityData abilityData = getAbilityData(abilityClass);
|
||||
AbilityLoader abilityLoader = getAbilityLoader(abilityData);
|
||||
|
||||
registerAbility(abilityClass, abilityData, abilityLoader);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans all of the Jar files inside of /ProjectKorra/folder and registers
|
||||
* all of the Ability class files that were found.
|
||||
*
|
||||
* @param folder the name of the folder to scan
|
||||
* @see #getAbilities()
|
||||
* @see #getAbility(String)
|
||||
*/
|
||||
public void registerAddonAbilities(String folder) {
|
||||
File file = new File(getPlugin().getDataFolder(), folder);
|
||||
|
||||
if (!file.exists()) {
|
||||
file.mkdir();
|
||||
return;
|
||||
}
|
||||
|
||||
AddonAbilityRegistery<Ability> abilityRegistery = new AddonAbilityRegistery<>(getPlugin(), file);
|
||||
List<Class<Ability>> loadedAbilities = abilityRegistery.load(Ability.class, Ability.class);
|
||||
|
||||
for (Class<Ability> abilityClass : loadedAbilities) {
|
||||
AbilityData abilityData = getAbilityData(abilityClass);
|
||||
AbilityLoader abilityLoader = getAbilityLoader(abilityData);
|
||||
|
||||
if (!(abilityLoader instanceof AddonAbilityLoader)) {
|
||||
throw new AbilityException(abilityClass.getName() + " must have an AddonAbilityLoader");
|
||||
}
|
||||
|
||||
registerAbility(abilityClass, abilityData, abilityLoader);
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends Ability> void registerAbility(Class<T> abilityClass, AbilityData abilityData, AbilityLoader abilityLoader) throws AbilityException {
|
||||
AbilityConfig abilityConfig = getAbilityConfig(abilityClass);
|
||||
|
||||
String abilityName = abilityData.name();
|
||||
|
||||
if (abilityName == null) {
|
||||
getPlugin().getLogger().warning("Ability " + abilityClass.getName() + " has no name?");
|
||||
return;
|
||||
throw new AbilityException("Ability " + abilityClass.getName() + " has no name");
|
||||
}
|
||||
|
||||
AbilityLoader abilityLoader = abilityData.abilityLoader().newInstance();
|
||||
AbilityConfig abilityConfig = ConfigManager.getConfig(((Class<? extends AbilityConfig>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]));
|
||||
|
||||
if (!abilityConfig.Enabled) {
|
||||
getPlugin().getLogger().info(abilityName + " is disabled");
|
||||
return;
|
||||
|
@ -141,18 +191,12 @@ public class AbilityManager extends Module {
|
|||
}
|
||||
|
||||
this.comboAbilityManager.registerAbility(abilityClass, abilityData, comboAbilityLoader);
|
||||
|
||||
// ComboManager.getComboAbilities().put(abilityName, new ComboManager.ComboAbilityInfo(abilityName, comboAbilityLoader.getCombination(), ));
|
||||
// ComboManager.getDescriptions().put(abilityName, abilityConfig.Description);
|
||||
// ComboManager.getInstructions().put(abilityName, abilityConfig.Instructions);
|
||||
}
|
||||
|
||||
if (abilityLoader instanceof MultiAbilityLoader) {
|
||||
MultiAbilityLoader multiAbilityLoader = (MultiAbilityLoader) abilityLoader;
|
||||
|
||||
this.multiAbilityManager.registerAbility(abilityClass, abilityData, multiAbilityLoader);
|
||||
|
||||
// MultiAbilityManager.multiAbilityList.add(new MultiAbilityManager.MultiAbilityInfo(abilityName, multiAbilityLoader.getMultiAbilities()));
|
||||
}
|
||||
|
||||
if (abilityLoader instanceof PassiveAbilityLoader) {
|
||||
|
@ -164,16 +208,40 @@ public class AbilityManager extends Module {
|
|||
}
|
||||
}
|
||||
|
||||
public <T extends Ability> T createAbility(Player player, Class<T> abilityClass) {
|
||||
private AbilityData getAbilityData(Class<? extends Ability> abilityClass) throws AbilityException {
|
||||
AbilityData abilityData = abilityClass.getDeclaredAnnotation(AbilityData.class);
|
||||
|
||||
if (abilityData == null) {
|
||||
throw new AbilityException("Ability " + abilityClass.getName() + " has missing AbilityData annotation");
|
||||
}
|
||||
|
||||
return abilityData;
|
||||
}
|
||||
|
||||
private AbilityLoader getAbilityLoader(AbilityData abilityData) throws AbilityException {
|
||||
try {
|
||||
return abilityData.abilityLoader().newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
throw new AbilityException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private AbilityConfig getAbilityConfig(Class<? extends Ability> abilityClass) throws AbilityException {
|
||||
try {
|
||||
return ConfigManager.getConfig(((Class<? extends AbilityConfig>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]));
|
||||
} catch (Exception e) {
|
||||
throw new AbilityException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends Ability> T createAbility(Player player, Class<T> abilityClass) throws AbilityException {
|
||||
try {
|
||||
Constructor<T> constructor = abilityClass.getDeclaredConstructor(Player.class);
|
||||
|
||||
return constructor.newInstance(player);
|
||||
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
throw new AbilityException(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void startAbility(Ability ability) {
|
||||
|
@ -270,4 +338,16 @@ public class AbilityManager extends Module {
|
|||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link AbilityManager} keeps track of plugins that have registered abilities to use
|
||||
* for bending reload purposes <br>
|
||||
* <b>This isn't a simple list, external use isn't recommended</b>
|
||||
*
|
||||
* @return a list of entrys with the plugin name and path abilities can be
|
||||
* found at
|
||||
*/
|
||||
public Set<String> getAddonPlugins() {
|
||||
return this.addonPlugins;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package com.projectkorra.projectkorra.ability.util;
|
||||
|
||||
import com.projectkorra.projectkorra.ProjectKorra;
|
||||
import com.projectkorra.projectkorra.event.AbilityLoadEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
|
@ -12,22 +16,14 @@ import java.util.List;
|
|||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import sun.reflect.ReflectionFactory;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.projectkorra.projectkorra.ProjectKorra;
|
||||
import com.projectkorra.projectkorra.event.AbilityLoadEvent;
|
||||
|
||||
public class AbilityLoader<T> {
|
||||
public class AbilityRegistery<T> {
|
||||
|
||||
private final Plugin plugin;
|
||||
private ClassLoader loader;
|
||||
private JarFile jar;
|
||||
private String path;
|
||||
|
||||
public AbilityLoader(final JavaPlugin plugin, final String packageBase) {
|
||||
public AbilityRegistery(final JavaPlugin plugin, final String packageBase) {
|
||||
this.plugin = plugin;
|
||||
this.loader = plugin.getClass().getClassLoader();
|
||||
this.path = packageBase.replace('.', '/');
|
||||
|
@ -60,8 +56,8 @@ public class AbilityLoader<T> {
|
|||
* {@code Object.class} for classes without a type.
|
||||
* @return
|
||||
*/
|
||||
public List<T> load(final Class<?> classType, final Class<?> parentClass) {
|
||||
final ArrayList<T> loadables = new ArrayList<>();
|
||||
public List<Class<T>> load(final Class<?> classType, final Class<?> parentClass) {
|
||||
final ArrayList<Class<T>> loadables = new ArrayList<>();
|
||||
|
||||
if (this.loader == null || this.jar == null) {
|
||||
return loadables;
|
||||
|
@ -89,16 +85,10 @@ public class AbilityLoader<T> {
|
|||
continue;
|
||||
}
|
||||
|
||||
final ReflectionFactory rf = ReflectionFactory.getReflectionFactory();
|
||||
final Constructor<?> objDef = parentClass.getDeclaredConstructor();
|
||||
final Constructor<?> intConstr = rf.newConstructorForSerialization(clazz, objDef);
|
||||
final T loadable = (T) clazz.cast(intConstr.newInstance());
|
||||
|
||||
if (loadable == null) {
|
||||
continue;
|
||||
}
|
||||
Class<T> loadable = (Class<T>) clazz;
|
||||
|
||||
loadables.add(loadable);
|
||||
|
||||
final AbilityLoadEvent<T> event = new AbilityLoadEvent<T>(this.plugin, loadable, this.jar);
|
||||
this.plugin.getServer().getPluginManager().callEvent(event);
|
||||
} catch (Exception | Error e) {
|
|
@ -1,8 +1,11 @@
|
|||
package com.projectkorra.projectkorra.ability.util;
|
||||
|
||||
import com.projectkorra.projectkorra.event.AbilityLoadEvent;
|
||||
import com.projectkorra.projectkorra.util.FileExtensionFilter;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
@ -14,21 +17,14 @@ import java.util.jar.JarEntry;
|
|||
import java.util.jar.JarFile;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import sun.reflect.ReflectionFactory;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.projectkorra.projectkorra.event.AbilityLoadEvent;
|
||||
import com.projectkorra.projectkorra.util.FileExtensionFilter;
|
||||
|
||||
public class AddonAbilityLoader<T> {
|
||||
public class AddonAbilityRegistery<T> {
|
||||
|
||||
private final Plugin plugin;
|
||||
private final File directory;
|
||||
private final ArrayList<File> files;
|
||||
private ClassLoader loader;
|
||||
|
||||
public AddonAbilityLoader(final Plugin plugin, final File directory) {
|
||||
public AddonAbilityRegistery(final Plugin plugin, final File directory) {
|
||||
this.plugin = plugin;
|
||||
this.directory = directory;
|
||||
this.files = new ArrayList<File>();
|
||||
|
@ -59,8 +55,8 @@ public class AddonAbilityLoader<T> {
|
|||
* @return A list of all of the T objects that were loaded from the jar
|
||||
* files within @param directory
|
||||
*/
|
||||
public List<T> load(final Class<?> classType, final Class<?> parentClass) {
|
||||
final ArrayList<T> loadables = new ArrayList<>();
|
||||
public List<Class<T>> load(final Class<?> classType, final Class<?> parentClass) {
|
||||
final ArrayList<Class<T>> loadables = new ArrayList<>();
|
||||
|
||||
for (final File file : this.files) {
|
||||
JarFile jarFile = null;
|
||||
|
@ -86,10 +82,7 @@ public class AddonAbilityLoader<T> {
|
|||
continue;
|
||||
}
|
||||
|
||||
final ReflectionFactory rf = ReflectionFactory.getReflectionFactory();
|
||||
final Constructor<?> objDef = parentClass.getDeclaredConstructor();
|
||||
final Constructor<?> intConstr = rf.newConstructorForSerialization(clazz, objDef);
|
||||
final T loadable = (T) clazz.cast(intConstr.newInstance());
|
||||
Class<T> loadable = (Class<T>) clazz;
|
||||
|
||||
loadables.add(loadable);
|
||||
final AbilityLoadEvent<T> event = new AbilityLoadEvent<T>(this.plugin, loadable, jarFile);
|
|
@ -14,7 +14,7 @@ public class AbilityLoadEvent<T> extends Event {
|
|||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final Plugin plugin;
|
||||
private final T loadable;
|
||||
private final Class<T> loadable;
|
||||
private final JarFile jarFile;
|
||||
|
||||
/**
|
||||
|
@ -24,7 +24,7 @@ public class AbilityLoadEvent<T> extends Event {
|
|||
* @param loadable The class that was loaded
|
||||
* @param jarFile The JarFile the class was loaded from
|
||||
*/
|
||||
public AbilityLoadEvent(final Plugin plugin, final T loadable, final JarFile jarFile) {
|
||||
public AbilityLoadEvent(final Plugin plugin, final Class<T> loadable, final JarFile jarFile) {
|
||||
this.plugin = plugin;
|
||||
this.loadable = loadable;
|
||||
this.jarFile = jarFile;
|
||||
|
@ -53,7 +53,7 @@ public class AbilityLoadEvent<T> extends Event {
|
|||
*
|
||||
* @return The loaded class
|
||||
*/
|
||||
public T getLoadable() {
|
||||
public Class<T> getLoadable() {
|
||||
return this.loadable;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue