Component data improvements & enable

Separated enabling the component from registering it - a component will be always registerd, even if it's disabled
Component data implemented similarily to player data, just kind of better
Bunch of changes, less code repetition
This commit is contained in:
Norbi Peti 2018-11-11 00:58:18 +01:00
parent ae84994025
commit 5ef5bf47a2
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
11 changed files with 246 additions and 37 deletions

View file

@ -1,13 +1,13 @@
<component name="libraryTable">
<library name="Maven: com.github.TBMCPlugins.ButtonCore:Towny:master-v1.0-g8d3b6b6-296">
<library name="Maven: com.github.TBMCPlugins.ButtonCore:Towny:master-248b0d8d0a-1">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/com/github/TBMCPlugins/ButtonCore/Towny/master-v1.0-g8d3b6b6-296/Towny-master-v1.0-g8d3b6b6-296.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/github/TBMCPlugins/ButtonCore/Towny/master-248b0d8d0a-1/Towny-master-248b0d8d0a-1.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/com/github/TBMCPlugins/ButtonCore/Towny/master-v1.0-g8d3b6b6-296/Towny-master-v1.0-g8d3b6b6-296-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/github/TBMCPlugins/ButtonCore/Towny/master-248b0d8d0a-1/Towny-master-248b0d8d0a-1-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/com/github/TBMCPlugins/ButtonCore/Towny/master-v1.0-g8d3b6b6-296/Towny-master-v1.0-g8d3b6b6-296-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/github/TBMCPlugins/ButtonCore/Towny/master-248b0d8d0a-1/Towny-master-248b0d8d0a-1-sources.jar!/" />
</SOURCES>
</library>
</component>

View file

@ -1,13 +1,13 @@
<component name="libraryTable">
<library name="Maven: com.github.milkbowl:VaultAPI:master-c8cb88f27a-1">
<library name="Maven: com.github.milkbowl:VaultAPI:master-431c5273c2-1">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/com/github/milkbowl/VaultAPI/master-c8cb88f27a-1/VaultAPI-master-c8cb88f27a-1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/github/milkbowl/VaultAPI/master-431c5273c2-1/VaultAPI-master-431c5273c2-1.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/com/github/milkbowl/VaultAPI/master-c8cb88f27a-1/VaultAPI-master-c8cb88f27a-1-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/github/milkbowl/VaultAPI/master-431c5273c2-1/VaultAPI-master-431c5273c2-1-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/com/github/milkbowl/VaultAPI/master-c8cb88f27a-1/VaultAPI-master-c8cb88f27a-1-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/github/milkbowl/VaultAPI/master-431c5273c2-1/VaultAPI-master-431c5273c2-1-sources.jar!/" />
</SOURCES>
</library>
</component>

View file

@ -1,13 +1,13 @@
<component name="libraryTable">
<library name="Maven: org.bukkit:bukkit:1.13.1-R0.1-SNAPSHOT">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/bukkit/bukkit/1.13.1-R0.1-SNAPSHOT/bukkit-1.13.1-R0.1-20181003.105254-89.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/bukkit/bukkit/1.13.1-R0.1-SNAPSHOT/bukkit-1.13.1-R0.1-20181022.190036-99.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/bukkit/bukkit/1.13.1-R0.1-SNAPSHOT/bukkit-1.13.1-R0.1-20181003.105254-89-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/bukkit/bukkit/1.13.1-R0.1-SNAPSHOT/bukkit-1.13.1-R0.1-20181022.190036-99-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/bukkit/bukkit/1.13.1-R0.1-SNAPSHOT/bukkit-1.13.1-R0.1-20181003.105254-89-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/bukkit/bukkit/1.13.1-R0.1-SNAPSHOT/bukkit-1.13.1-R0.1-20181022.190036-99-sources.jar!/" />
</SOURCES>
</library>
</component>

View file

@ -1,13 +1,13 @@
<component name="libraryTable">
<library name="Maven: org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/spigotmc/spigot-api/1.12.2-R0.1-SNAPSHOT/spigot-api-1.12.2-R0.1-20180712.012057-156.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/spigotmc/spigot-api/1.12.2-R0.1-SNAPSHOT/spigot-api-1.12.2-R0.1-SNAPSHOT.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/spigotmc/spigot-api/1.12.2-R0.1-SNAPSHOT/spigot-api-1.12.2-R0.1-20180712.012057-156-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/spigotmc/spigot-api/1.12.2-R0.1-SNAPSHOT/spigot-api-1.12.2-R0.1-SNAPSHOT-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/spigotmc/spigot-api/1.12.2-R0.1-SNAPSHOT/spigot-api-1.12.2-R0.1-20180712.012057-156-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/spigotmc/spigot-api/1.12.2-R0.1-SNAPSHOT/spigot-api-1.12.2-R0.1-SNAPSHOT-sources.jar!/" />
</SOURCES>
</library>
</component>

View file

@ -12,6 +12,7 @@
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="ButtonCore (1) (com.github.TBMCPlugins.ButtonCore)" />
<orderEntry type="module" module-name="ButtonCore (1) (com.github.TBMCPlugins.ButtonCore)" />
<orderEntry type="library" name="Maven: org.reflections:reflections:0.9.10" level="project" />
<orderEntry type="library" name="Maven: com.google.code.findbugs:annotations:2.0.1" level="project" />
<orderEntry type="library" name="Maven: org.javassist:javassist:3.20.0-GA" level="project" />

View file

@ -0,0 +1,30 @@
package buttondevteam.core;
import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.chat.TBMCCommandBase;
import org.bukkit.command.CommandSender;
@CommandClass(modOnly = true)
public class ComponentCommand extends TBMCCommandBase {
@Override
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
if (args.length < 2)
return false;
switch (args[0]) {
case "enable":
break;
case "disable":
break;
case "list":
break;
default:
return false;
}
return true;
}
@Override
public String[] GetHelpText(String alias) {
return new String[0];
}
}

View file

@ -0,0 +1,33 @@
package buttondevteam.core;
import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.architecture.exceptions.UnregisteredComponentException;
public final class ComponentManager {
private ComponentManager() {}
/**
* Enables components based on a configuration
*/
public static void enableComponents() {
//Component.getComponents().values().stream().filter(c->cs.getConfigurationSection(c.getClass().getSimpleName()).getBoolean("enabled")).forEach(c-> {
Component.getComponents().values().stream().filter(c -> c.shouldBeEnabled().get()).forEach(c -> {
try {
Component.setComponentEnabled(c, true);
} catch (UnregisteredComponentException ignored) { //This *should* never happen
}
});
}
/**
* Disables all components that are enabled
*/
public static void disableComponents() {
Component.getComponents().values().stream().filter(Component::isEnabled).forEach(c -> {
try {
Component.setComponentEnabled(c, false);
} catch (UnregisteredComponentException ignored) { //This *should* never happen
}
});
}
}

View file

@ -40,6 +40,7 @@ public class MainPlugin extends JavaPlugin {
setupPermissions();
Test = getConfig().getBoolean("test", true);
saveConfig();
ComponentManager.enableComponents();
TBMCCoreAPI.RegisterEventsForExceptions(new PlayerListener(), this);
TBMCCoreAPI.RegisterUserClass(TBMCPlayerBase.class);
TBMCChatAPI.RegisterChatChannel(Channel.GlobalChat = new Channel("§fOOC§f", Color.White, "ooc", null));
@ -67,6 +68,7 @@ public class MainPlugin extends JavaPlugin {
@Override
public void onDisable() {
ComponentManager.disableComponents();
logger.info("Saving player data...");
TBMCPlayerBase.savePlayers();
logger.info("Player data saved.");

View file

@ -1,17 +1,75 @@
package buttondevteam.lib.architecture;
import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.architecture.exceptions.UnregisteredComponentException;
import buttondevteam.lib.chat.TBMCChatAPI;
import buttondevteam.lib.chat.TBMCCommandBase;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
import lombok.experimental.var;
import lombok.val;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
/**
* Configuration is based on class name
*/
public abstract class Component {
private static HashMap<Class<? extends Component>, Component> components;
private static HashMap<Class<? extends Component>, Component> components = new HashMap<>();
@Getter
private boolean enabled = false;
@Getter(value = AccessLevel.PROTECTED)
@NonNull
private JavaPlugin plugin;
@NonNull
private ConfigurationSection config;
public ConfigData<Boolean> shouldBeEnabled() {
return getData("enabled", true);
}
private HashMap<String, ConfigData<?>> datamap = new HashMap<>();
/**
* This method overload should only be used with primitves or String.
*
* @param path The path in config to use
* @param def The value to use by default
* @param <T> The type of this variable (only use primitives or String)
* @return The data object that can be used to get or set the value
*/
@SuppressWarnings("unchecked")
protected <T> ConfigData<T> getData(String path, T def) {
ConfigData<?> data = datamap.get(path);
if (data == null) datamap.put(path, data = new ConfigData<>(config, path, def));
return (ConfigData<T>) data;
}
/**
* This method overload may be used with any class.
*
* @param path The path in config to use
* @param def The value to use by default
* @param getter A function that converts a primitive representation to the correct value
* @param setter A function that converts a value to a primitive representation
* @param <T> The type of this variable (can be any class)
* @return The data object that can be used to get or set the value
*/
@SuppressWarnings("unchecked")
protected <T> ConfigData<T> getData(String path, T def, Function<Object, T> getter, Function<T, Object> setter) {
ConfigData<?> data = datamap.get(path);
if (data == null) datamap.put(path, data = new ConfigData<>(config, path, def, getter, setter));
return (ConfigData<T>) data;
}
/**
* Registers a component checking it's dependencies and calling {@link #register(JavaPlugin)}.<br>
@ -20,18 +78,7 @@ public abstract class Component {
* @param component The component to register
*/
public static void registerComponent(JavaPlugin plugin, Component component) {
val metaAnn = component.getClass().getAnnotation(ComponentMetadata.class);
if (metaAnn != null) {
Class<? extends Component>[] dependencies = metaAnn.depends();
for (val dep : dependencies) {
if (!components.containsKey(dep)) {
plugin.getLogger().warning("Failed to register component " + component.getClassName() + " as a required dependency is missing/disabled: " + dep.getSimpleName());
return;
}
}
}
component.register(plugin);
components.put(component.getClass(), component);
registerUnregisterComponent(plugin, component, true);
}
/**
@ -44,27 +91,56 @@ public abstract class Component {
val component = components.get(componentClass);
if (component == null)
return; //Failed to load
val metaAnn = componentClass.getAnnotation(ComponentMetadata.class);
registerUnregisterComponent(plugin, component, false);
}
public static void registerUnregisterComponent(JavaPlugin plugin, Component component, boolean register) {
val metaAnn = component.getClass().getAnnotation(ComponentMetadata.class);
if (metaAnn != null) {
Class<? extends Component>[] dependencies = metaAnn.depends();
for (val dep : dependencies) {
if (!components.containsKey(dep)) {
plugin.getLogger().warning("Failed to unregister component " + component.getClassName() + " as a required dependency is missing/disabled: " + dep.getSimpleName());
plugin.getLogger().warning("Failed to " + (register ? "" : "un") + "register component " + component.getClassName() + " as a required dependency is missing/disabled: " + dep.getSimpleName());
return;
}
}
}
component.unregister(plugin);
components.remove(componentClass);
if (register) {
component.plugin = plugin;
var compconf = plugin.getConfig().getConfigurationSection("components");
if (compconf == null) compconf = plugin.getConfig().createSection("components");
component.config = compconf.getConfigurationSection(component.getClassName());
if (component.config == null) component.config = compconf.createSection(component.getClassName());
component.register(plugin);
components.put(component.getClass(), component);
} else {
component.unregister(plugin);
components.remove(component.getClass());
}
}
/**
* This is used to send a warning if there are registered components on shutdown.<br>
* Registers a component checking it's dependencies and calling {@link #register(JavaPlugin)}.<br>
* Make sure to register the dependencies first.
*
* @return If there are any registered components
* @param component The component to register
*/
public static boolean haveRegisteredComponents() {
return components.size() > 0;
public static void setComponentEnabled(Component component, boolean enabled) throws UnregisteredComponentException {
if (!components.containsKey(component.getClass()))
throw new UnregisteredComponentException(component);
if (component.enabled = enabled)
component.enable();
else
component.disable();
}
/**
* Returns the currently registered components<br>
*
* @return The currently registered components
*/
public static Map<Class<? extends Component>, Component> getComponents() {
return Collections.unmodifiableMap(components);
}
/**
@ -73,7 +149,7 @@ public abstract class Component {
*
* @param plugin Plugin class called to register commands and listeners
*/
public abstract void register(JavaPlugin plugin);
protected abstract void register(JavaPlugin plugin);
/**
* Unregisters the module, when called by the JavaPlugin class. Do
@ -81,7 +157,21 @@ public abstract class Component {
*
* @param plugin Plugin class called to register commands and listeners
*/
public abstract void unregister(JavaPlugin plugin);
protected abstract void unregister(JavaPlugin plugin);
/**
* Enables the module, when called by the JavaPlugin class. Call
* registerCommand() and registerListener() within this method.<br>
* To access the plugin, use {@link #getPlugin()}.
*/
protected abstract void enable();
/**
* Disables the module, when called by the JavaPlugin class. Do
* any cleanups needed within this method.
* To access the plugin, use {@link #getPlugin()}.
*/
protected abstract void disable();
/**
* Registers a TBMCCommand to the plugin. Make sure to add it to plugin.yml and use {@link buttondevteam.lib.chat.CommandClass}.

View file

@ -0,0 +1,43 @@
package buttondevteam.lib.architecture;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import java.util.function.Function;
/**
* Use the getter/setter constructor if {@link T} isn't a primitive type or String.
*/
@RequiredArgsConstructor
@AllArgsConstructor
public class ConfigData<T> { //TODO: Save after a while
private final ConfigurationSection config;
private final String path;
private final T def;
/**
* The parameter is of a primitive type as returned by {@link YamlConfiguration#get(String)}
*/
private Function<Object, T> getter;
/**
* The result should be a primitive type or string that can be retrieved correctly later
*/
private Function<T, Object> setter;
@SuppressWarnings("unchecked")
public T get() {
Object val = config.get(path, def);
if (getter != null)
return getter.apply(val);
return (T) val;
}
public void set(T value) {
Object val;
if (setter != null)
val = setter.apply(value);
else val = value;
config.set(path, val);
}
}

View file

@ -0,0 +1,10 @@
package buttondevteam.lib.architecture.exceptions;
import buttondevteam.lib.architecture.Component;
public class UnregisteredComponentException extends Throwable {
public UnregisteredComponentException(Component component) {
super("The component '" + component.getClass().getSimpleName() + "' isn't registered!");
}
}