Merge pull request #66 from TBMCPlugins/dev
Permission and config improvements, fixes
This commit is contained in:
commit
0523ebe214
18 changed files with 394 additions and 166 deletions
|
@ -1,5 +1,10 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="EntryPointsManager">
|
||||||
|
<list size="1">
|
||||||
|
<item index="0" class="java.lang.String" itemvalue="org.bukkit.event.EventHandler" />
|
||||||
|
</list>
|
||||||
|
</component>
|
||||||
<component name="MavenProjectsManager">
|
<component name="MavenProjectsManager">
|
||||||
<option name="originalFiles">
|
<option name="originalFiles">
|
||||||
<list>
|
<list>
|
||||||
|
|
|
@ -13,6 +13,12 @@
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<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="module" module-name="ButtonCore (1) (com.github.TBMCPlugins.ButtonCore)" />
|
<orderEntry type="module" module-name="ButtonCore (1) (com.github.TBMCPlugins.ButtonCore)" />
|
||||||
|
<orderEntry type="module" module-name="ButtonCore (1) (com.github.TBMCPlugins.ButtonCore)" />
|
||||||
|
<orderEntry type="module" module-name="ButtonCore (1) (com.github.TBMCPlugins.ButtonCore)" />
|
||||||
|
<orderEntry type="module" module-name="ButtonCore (1) (com.github.TBMCPlugins.ButtonCore)" />
|
||||||
|
<orderEntry type="module" module-name="ButtonCore (1) (com.github.TBMCPlugins.ButtonCore)" />
|
||||||
|
<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: 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: com.google.code.findbugs:annotations:2.0.1" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.javassist:javassist:3.20.0-GA" level="project" />
|
<orderEntry type="library" name="Maven: org.javassist:javassist:3.20.0-GA" level="project" />
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4">
|
|
||||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
|
||||||
<output url="file://$MODULE_DIR$/target/classes" />
|
|
||||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
<orderEntry type="library" name="Maven: org.reflections:reflections:0.9.10" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.google.guava:guava:15.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.google.code.findbugs:annotations:2.0.1" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: commons-lang:commons-lang:2.6" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.gson:gson:2.8.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.19" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.md-5:bungeecord-chat:1.12-SNAPSHOT" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: commons-io:commons-io:1.3.2" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.github.TBMCPlugins.ButtonCore:Towny:master-f8fd481f46-1" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.github.milkbowl:VaultAPI:master-68f14eca20-1" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.bukkit:bukkit:1.13.1-R0.1-SNAPSHOT" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.javassist:javassist:3.20.0-GA" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.mockito:mockito-core:2.7.20" level="project" />
|
|
||||||
<orderEntry type="library" scope="RUNTIME" name="Maven: net.bytebuddy:byte-buddy:1.6.11" level="project" />
|
|
||||||
<orderEntry type="library" scope="RUNTIME" name="Maven: net.bytebuddy:byte-buddy-agent:1.6.11" level="project" />
|
|
||||||
<orderEntry type="library" scope="RUNTIME" name="Maven: org.objenesis:objenesis:2.5" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.projectlombok:lombok:1.16.16" level="project" />
|
|
||||||
<orderEntry type="module" module-name="ButtonProcessor" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.ess3:Essentials:2.13.1" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.vexsoftware:nuvotifier-universal:2.3.4" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:3.8.1" level="project" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
|
@ -38,7 +38,7 @@ public final class ComponentManager {
|
||||||
public static <T extends ButtonPlugin> void unregComponents(T plugin) {
|
public static <T extends ButtonPlugin> void unregComponents(T plugin) {
|
||||||
while (!plugin.getComponentStack().empty()) //Unregister in reverse order
|
while (!plugin.getComponentStack().empty()) //Unregister in reverse order
|
||||||
Component.unregisterComponent(plugin, (Component<T>) plugin.getComponentStack().pop()); //Components are pushed on register
|
Component.unregisterComponent(plugin, (Component<T>) plugin.getComponentStack().pop()); //Components are pushed on register
|
||||||
componentsEnabled = false;
|
//componentsEnabled = false; - continue enabling new components after a plugin gets disabled
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -46,7 +46,6 @@ import java.util.logging.Logger;
|
||||||
public class MainPlugin extends ButtonPlugin {
|
public class MainPlugin extends ButtonPlugin {
|
||||||
public static MainPlugin Instance;
|
public static MainPlugin Instance;
|
||||||
public static Permission permission;
|
public static Permission permission;
|
||||||
public static boolean Test;
|
|
||||||
public static Essentials ess;
|
public static Essentials ess;
|
||||||
|
|
||||||
private Logger logger;
|
private Logger logger;
|
||||||
|
@ -69,6 +68,10 @@ public class MainPlugin extends ButtonPlugin {
|
||||||
"{channel}] <{name}> {message}");
|
"{channel}] <{name}> {message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ConfigData<Boolean> test() {
|
||||||
|
return getIConfig().getData("test", true);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pluginEnable() {
|
public void pluginEnable() {
|
||||||
// Logs "Plugin Enabled", registers commands
|
// Logs "Plugin Enabled", registers commands
|
||||||
|
@ -79,7 +82,6 @@ public class MainPlugin extends ButtonPlugin {
|
||||||
throw new NullPointerException("No permission plugin found!");
|
throw new NullPointerException("No permission plugin found!");
|
||||||
if (!setupEconomy()) //Though Essentials always provides economy so this shouldn't happen
|
if (!setupEconomy()) //Though Essentials always provides economy so this shouldn't happen
|
||||||
getLogger().warning("No economy plugin found! Components using economy will not be registered.");
|
getLogger().warning("No economy plugin found! Components using economy will not be registered.");
|
||||||
Test = getConfig().getBoolean("test", true);
|
|
||||||
saveConfig();
|
saveConfig();
|
||||||
Component.registerComponent(this, new PluginUpdaterComponent());
|
Component.registerComponent(this, new PluginUpdaterComponent());
|
||||||
Component.registerComponent(this, new RestartComponent());
|
Component.registerComponent(this, new RestartComponent());
|
||||||
|
@ -120,7 +122,7 @@ public class MainPlugin extends ButtonPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ess = Essentials.getPlugin(Essentials.class);
|
ess = Essentials.getPlugin(Essentials.class);
|
||||||
logger.info(pdf.getName() + " has been Enabled (V." + pdf.getVersion() + ") Test: " + Test + ".");
|
logger.info(pdf.getName() + " has been Enabled (V." + pdf.getVersion() + ") Test: " + test().get() + ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class Channel {
|
||||||
*/
|
*/
|
||||||
public final ConfigData<String> DisplayName() {
|
public final ConfigData<String> DisplayName() {
|
||||||
throwGame();
|
throwGame();
|
||||||
return component.getConfig().getData(ID + ".displayName", defDisplayName);
|
return component.getConfig().getData(ID + ".displayName", defDisplayName); //TODO: Use config map
|
||||||
}
|
}
|
||||||
|
|
||||||
public final ConfigData<Color> Color() {
|
public final ConfigData<Color> Color() {
|
||||||
|
|
|
@ -54,9 +54,12 @@ public class MemberComponent extends Component<MainPlugin> implements Listener {
|
||||||
if (permission != null && !permission.playerInGroup(event.getPlayer(), memberGroup().get())
|
if (permission != null && !permission.playerInGroup(event.getPlayer(), memberGroup().get())
|
||||||
&& (new Date(event.getPlayer().getFirstPlayed()).toInstant().plus(registeredForDays().get(), ChronoUnit.DAYS).isBefore(Instant.now())
|
&& (new Date(event.getPlayer().getFirstPlayed()).toInstant().plus(registeredForDays().get(), ChronoUnit.DAYS).isBefore(Instant.now())
|
||||||
|| event.getPlayer().getStatistic(Statistic.PLAY_ONE_TICK) > 20 * 3600 * playedHours().get())) {
|
|| event.getPlayer().getStatistic(Statistic.PLAY_ONE_TICK) > 20 * 3600 * playedHours().get())) {
|
||||||
permission.playerAddGroup(null, event.getPlayer(), memberGroup().get());
|
if (permission.playerAddGroup(null, event.getPlayer(), memberGroup().get())) {
|
||||||
event.getPlayer().sendMessage("§bYou are a member now. YEEHAW");
|
event.getPlayer().sendMessage("§bYou are a member now. YEEHAW");
|
||||||
MainPlugin.Instance.getLogger().info("Added " + event.getPlayer().getName() + " as a member.");
|
MainPlugin.Instance.getLogger().info("Added " + event.getPlayer().getName() + " as a member.");
|
||||||
|
} else {
|
||||||
|
MainPlugin.Instance.getLogger().warning("Failed to assign the member role! Please make sure the member group exists or disable the component if it's unused.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.util.Map.Entry;
|
||||||
public class TBMCCoreAPI {
|
public class TBMCCoreAPI {
|
||||||
static final List<String> coders = new ArrayList<String>() {
|
static final List<String> coders = new ArrayList<String>() {
|
||||||
private static final long serialVersionUID = -4462159250738367334L;
|
private static final long serialVersionUID = -4462159250738367334L;
|
||||||
|
|
||||||
{
|
{
|
||||||
add("Alisolarflare");
|
add("Alisolarflare");
|
||||||
add("NorbiPeti");
|
add("NorbiPeti");
|
||||||
|
@ -36,10 +37,8 @@ public class TBMCCoreAPI {
|
||||||
/**
|
/**
|
||||||
* Updates or installs the specified plugin. The plugin must use Maven.
|
* Updates or installs the specified plugin. The plugin must use Maven.
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name The plugin's repository name.
|
||||||
* The plugin's repository name.
|
* @param sender The command sender (if not console, messages will be printed to console as well).
|
||||||
* @param sender
|
|
||||||
* The command sender (if not console, messages will be printed to console as well).
|
|
||||||
*/
|
*/
|
||||||
public static void UpdatePlugin(String name, CommandSender sender) {
|
public static void UpdatePlugin(String name, CommandSender sender) {
|
||||||
UpdatePlugin(name, sender, "master");
|
UpdatePlugin(name, sender, "master");
|
||||||
|
@ -48,12 +47,9 @@ public class TBMCCoreAPI {
|
||||||
/**
|
/**
|
||||||
* Updates or installs the specified plugin from the specified branch. The plugin must use Maven.
|
* Updates or installs the specified plugin from the specified branch. The plugin must use Maven.
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name The plugin's repository name.
|
||||||
* The plugin's repository name.
|
* @param sender The command sender (if not console, messages will be printed to console as well).
|
||||||
* @param sender
|
* @param branch The branch to download the plugin from.
|
||||||
* The command sender (if not console, messages will be printed to console as well).
|
|
||||||
* @param branch
|
|
||||||
* The branch to download the plugin from.
|
|
||||||
* @return Success or not
|
* @return Success or not
|
||||||
*/
|
*/
|
||||||
public static boolean UpdatePlugin(String name, CommandSender sender, String branch) {
|
public static boolean UpdatePlugin(String name, CommandSender sender, String branch) {
|
||||||
|
@ -78,10 +74,8 @@ public class TBMCCoreAPI {
|
||||||
/**
|
/**
|
||||||
* Send exception to the {@link TBMCExceptionEvent}.
|
* Send exception to the {@link TBMCExceptionEvent}.
|
||||||
*
|
*
|
||||||
* @param sourcemsg
|
* @param sourcemsg A message that is shown at the top of the exception (before the exception's message)
|
||||||
* A message that is shown at the top of the exception (before the exception's message)
|
* @param e The exception to send
|
||||||
* @param e
|
|
||||||
* The exception to send
|
|
||||||
*/
|
*/
|
||||||
public static void SendException(String sourcemsg, Throwable e) {
|
public static void SendException(String sourcemsg, Throwable e) {
|
||||||
SendException(sourcemsg, e, false);
|
SendException(sourcemsg, e, false);
|
||||||
|
@ -98,7 +92,7 @@ public class TBMCCoreAPI {
|
||||||
Bukkit.getLogger().warning(sourcemsg);
|
Bukkit.getLogger().warning(sourcemsg);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
if (debugPotato) {
|
if (debugPotato) {
|
||||||
List<Player> devsOnline = new ArrayList<Player>();
|
List<Player> devsOnline = new ArrayList<>();
|
||||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
if (coders.contains(player.getName())) {
|
if (coders.contains(player.getName())) {
|
||||||
devsOnline.add(player);
|
devsOnline.add(player);
|
||||||
|
@ -106,10 +100,10 @@ public class TBMCCoreAPI {
|
||||||
}
|
}
|
||||||
if (!devsOnline.isEmpty()) {
|
if (!devsOnline.isEmpty()) {
|
||||||
DebugPotato potato = new DebugPotato()
|
DebugPotato potato = new DebugPotato()
|
||||||
.setMessage(new String[] { //
|
.setMessage(new String[]{ //
|
||||||
"§b§o" + e.getClass().getSimpleName(), //
|
"§b§o" + e.getClass().getSimpleName(), //
|
||||||
"§c§o" + sourcemsg, //
|
"§c§o" + sourcemsg, //
|
||||||
"§a§oFind a dev to fix this issue" })
|
"§a§oFind a dev to fix this issue"})
|
||||||
.setType(e instanceof IOException ? "Throwable Potato"
|
.setType(e instanceof IOException ? "Throwable Potato"
|
||||||
: e instanceof ClassCastException ? "Squished Potato"
|
: e instanceof ClassCastException ? "Squished Potato"
|
||||||
: e instanceof NullPointerException ? "Plain Potato"
|
: e instanceof NullPointerException ? "Plain Potato"
|
||||||
|
@ -134,10 +128,8 @@ public class TBMCCoreAPI {
|
||||||
/**
|
/**
|
||||||
* Registers Bukkit events, handling the exceptions occurring in those events
|
* Registers Bukkit events, handling the exceptions occurring in those events
|
||||||
*
|
*
|
||||||
* @param listener
|
* @param listener The class that handles the events
|
||||||
* The class that handles the events
|
* @param plugin The plugin which the listener belongs to
|
||||||
* @param plugin
|
|
||||||
* The plugin which the listener belongs to
|
|
||||||
*/
|
*/
|
||||||
public static void RegisterEventsForExceptions(Listener listener, Plugin plugin) {
|
public static void RegisterEventsForExceptions(Listener listener, Plugin plugin) {
|
||||||
EventExceptionHandler.registerEvents(listener, plugin, new EventExceptionCoreHandler());
|
EventExceptionHandler.registerEvents(listener, plugin, new EventExceptionCoreHandler());
|
||||||
|
@ -183,6 +175,7 @@ public class TBMCCoreAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean IsTestServer() {
|
public static boolean IsTestServer() {
|
||||||
return MainPlugin.Test;
|
if (MainPlugin.Instance == null) return true;
|
||||||
|
return MainPlugin.Instance.test().get();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,6 +9,11 @@ import lombok.Getter;
|
||||||
import lombok.experimental.var;
|
import lombok.experimental.var;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
@HasConfig
|
@HasConfig
|
||||||
|
@ -47,6 +52,8 @@ public abstract class ButtonPlugin extends JavaPlugin {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
TBMCCoreAPI.SendException("Error while enabling plugin " + getName() + "!", e);
|
TBMCCoreAPI.SendException("Error while enabling plugin " + getName() + "!", e);
|
||||||
}
|
}
|
||||||
|
if (configGenAllowed(this)) //If it's not disabled (by default it's not)
|
||||||
|
IHaveConfig.pregenConfig(this, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadConfig() {
|
private void loadConfig() {
|
||||||
|
@ -90,4 +97,15 @@ public abstract class ButtonPlugin extends JavaPlugin {
|
||||||
loaded = true; //Needed because for the first time it uses reloadConfig() to load it
|
loaded = true; //Needed because for the first time it uses reloadConfig() to load it
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
public @interface ConfigOpts {
|
||||||
|
boolean disableConfigGen() default false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean configGenAllowed(Object obj) {
|
||||||
|
return !Optional.ofNullable(obj.getClass().getAnnotation(ConfigOpts.class))
|
||||||
|
.map(ConfigOpts::disableConfigGen).orElse(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,6 +133,8 @@ public abstract class Component<TP extends JavaPlugin> {
|
||||||
if (component.enabled = enabled) {
|
if (component.enabled = enabled) {
|
||||||
updateConfig(component.getPlugin(), component);
|
updateConfig(component.getPlugin(), component);
|
||||||
component.enable();
|
component.enable();
|
||||||
|
if (ButtonPlugin.configGenAllowed(component))
|
||||||
|
IHaveConfig.pregenConfig(component, null);
|
||||||
} else {
|
} else {
|
||||||
component.disable();
|
component.disable();
|
||||||
component.plugin.saveConfig();
|
component.plugin.saveConfig();
|
||||||
|
@ -228,14 +230,15 @@ public abstract class Component<TP extends JavaPlugin> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a map of configs that are under the given key.
|
* Returns a map of configs that are under the given key.
|
||||||
|
*
|
||||||
* @param key The key to use
|
* @param key The key to use
|
||||||
* @param defaultProvider A mapping between config paths and config generators
|
* @param defaultProvider A mapping between config paths and config generators
|
||||||
* @return A map containing configs
|
* @return A map containing configs
|
||||||
*/
|
*/
|
||||||
protected Map<String, IHaveConfig> getConfigMap(String key, Map<String, Consumer<IHaveConfig>> defaultProvider) {
|
protected Map<String, IHaveConfig> getConfigMap(String key, Map<String, Consumer<IHaveConfig>> defaultProvider) {
|
||||||
val c=getConfig().getConfig();
|
val c = getConfig().getConfig();
|
||||||
var cs=c.getConfigurationSection(key);
|
var cs = c.getConfigurationSection(key);
|
||||||
if(cs==null) cs=c.createSection(key);
|
if (cs == null) cs = c.createSection(key);
|
||||||
val res = cs.getValues(false).entrySet().stream().filter(e -> e.getValue() instanceof ConfigurationSection)
|
val res = cs.getValues(false).entrySet().stream().filter(e -> e.getValue() instanceof ConfigurationSection)
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey, kv -> new IHaveConfig((ConfigurationSection) kv.getValue(), getPlugin()::saveConfig)));
|
.collect(Collectors.toMap(Map.Entry::getKey, kv -> new IHaveConfig((ConfigurationSection) kv.getValue(), getPlugin()::saveConfig)));
|
||||||
if (res.size() == 0) {
|
if (res.size() == 0) {
|
||||||
|
|
|
@ -4,7 +4,8 @@ import buttondevteam.core.MainPlugin;
|
||||||
import buttondevteam.lib.ThorpeUtils;
|
import buttondevteam.lib.ThorpeUtils;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.configuration.Configuration;
|
import org.bukkit.configuration.Configuration;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
@ -21,7 +22,6 @@ import java.util.function.Function;
|
||||||
* Use the getter/setter constructor if {@link T} isn't a primitive type or String.<br>
|
* Use the getter/setter constructor if {@link T} isn't a primitive type or String.<br>
|
||||||
* Use {@link Component#getConfig()} or {@link ButtonPlugin#getIConfig()} then {@link IHaveConfig#getData(String, Object)} to get an instance.
|
* Use {@link Component#getConfig()} or {@link ButtonPlugin#getIConfig()} then {@link IHaveConfig#getData(String, Object)} to get an instance.
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
|
||||||
//@AllArgsConstructor(access = AccessLevel.PACKAGE)
|
//@AllArgsConstructor(access = AccessLevel.PACKAGE)
|
||||||
public class ConfigData<T> {
|
public class ConfigData<T> {
|
||||||
private static final HashMap<Configuration, SaveTask> saveTasks = new HashMap<>();
|
private static final HashMap<Configuration, SaveTask> saveTasks = new HashMap<>();
|
||||||
|
@ -29,7 +29,9 @@ public class ConfigData<T> {
|
||||||
* May be null for testing
|
* May be null for testing
|
||||||
*/
|
*/
|
||||||
private final ConfigurationSection config;
|
private final ConfigurationSection config;
|
||||||
private final String path;
|
@Getter
|
||||||
|
@Setter(AccessLevel.PACKAGE)
|
||||||
|
private String path;
|
||||||
private final T def;
|
private final T def;
|
||||||
private final Object primitiveDef;
|
private final Object primitiveDef;
|
||||||
private final Runnable saveAction;
|
private final Runnable saveAction;
|
||||||
|
@ -52,14 +54,23 @@ public class ConfigData<T> {
|
||||||
private boolean saved = false;
|
private boolean saved = false;
|
||||||
|
|
||||||
//This constructor is needed because it sets the getter and setter
|
//This constructor is needed because it sets the getter and setter
|
||||||
public ConfigData(ConfigurationSection config, String path, T def, Object primitiveDef, Function<Object, T> getter, Function<T, Object> setter, Runnable saveAction) {
|
ConfigData(ConfigurationSection config, String path, T def, Object primitiveDef, Function<Object, T> getter, Function<T, Object> setter, Runnable saveAction) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.def = def;
|
this.def = def;
|
||||||
this.primitiveDef = primitiveDef;
|
this.primitiveDef = primitiveDef;
|
||||||
this.getter = getter;
|
this.getter = getter;
|
||||||
this.setter = setter;
|
this.setter = setter;
|
||||||
this.saveAction=saveAction;
|
this.saveAction = saveAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.beans.ConstructorProperties({"config", "path", "def", "primitiveDef", "saveAction"})
|
||||||
|
ConfigData(ConfigurationSection config, String path, T def, Object primitiveDef, Runnable saveAction) {
|
||||||
|
this.config = config;
|
||||||
|
this.path = path;
|
||||||
|
this.def = def;
|
||||||
|
this.primitiveDef = primitiveDef;
|
||||||
|
this.saveAction = saveAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -98,13 +109,15 @@ public class ConfigData<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(T value) {
|
public void set(T value) {
|
||||||
|
if (this instanceof ReadOnlyConfigData)
|
||||||
|
return; //Safety for Discord channel/role data
|
||||||
Object val;
|
Object val;
|
||||||
if (setter != null && value != null)
|
if (setter != null && value != null)
|
||||||
val = setter.apply(value);
|
val = setter.apply(value);
|
||||||
else val = value;
|
else val = value;
|
||||||
if (config != null) {
|
if (config != null) {
|
||||||
config.set(path, val);
|
config.set(path, val);
|
||||||
if(!saveTasks.containsKey(config.getRoot())) {
|
if (!saveTasks.containsKey(config.getRoot())) {
|
||||||
synchronized (saveTasks) {
|
synchronized (saveTasks) {
|
||||||
saveTasks.put(config.getRoot(), new SaveTask(Bukkit.getScheduler().runTaskLaterAsynchronously(MainPlugin.Instance, () -> {
|
saveTasks.put(config.getRoot(), new SaveTask(Bukkit.getScheduler().runTaskLaterAsynchronously(MainPlugin.Instance, () -> {
|
||||||
synchronized (saveTasks) {
|
synchronized (saveTasks) {
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
package buttondevteam.lib.architecture;
|
package buttondevteam.lib.architecture;
|
||||||
|
|
||||||
|
import buttondevteam.core.MainPlugin;
|
||||||
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import javax.annotation.Nullable;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A config system
|
* A config system
|
||||||
|
@ -26,7 +29,7 @@ public final class IHaveConfig {
|
||||||
*/
|
*/
|
||||||
IHaveConfig(ConfigurationSection section, Runnable saveAction) {
|
IHaveConfig(ConfigurationSection section, Runnable saveAction) {
|
||||||
config = section;
|
config = section;
|
||||||
this.saveAction=saveAction;
|
this.saveAction = saveAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,6 +83,24 @@ public final class IHaveConfig {
|
||||||
return (ConfigData<T>) data;
|
return (ConfigData<T>) data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method overload may be used with any class. The given default value will be run through the getter.
|
||||||
|
*
|
||||||
|
* @param path The path in config to use
|
||||||
|
* @param primitiveDef The <b>primitive</b> 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")
|
||||||
|
public <T> ReadOnlyConfigData<T> getReadOnlyDataPrimDef(String path, Object primitiveDef, Function<Object, T> getter, Function<T, Object> setter) {
|
||||||
|
ConfigData<?> data = datamap.get(path);
|
||||||
|
if (data == null)
|
||||||
|
datamap.put(path, data = new ReadOnlyConfigData<>(config, path, getter.apply(primitiveDef), primitiveDef, getter, setter, saveAction));
|
||||||
|
return (ReadOnlyConfigData<T>) data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method overload should only be used with primitves or String.
|
* This method overload should only be used with primitves or String.
|
||||||
*
|
*
|
||||||
|
@ -117,4 +138,47 @@ public final class IHaveConfig {
|
||||||
}
|
}
|
||||||
return (ConfigData<T>) data;
|
return (ConfigData<T>) data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the config YAML.
|
||||||
|
*
|
||||||
|
* @param obj The object which has config methods
|
||||||
|
* @param configMap The result from {@link Component#getConfigMap(String, Map)}. May be null.
|
||||||
|
*/
|
||||||
|
public static void pregenConfig(Object obj, @Nullable Map<String, IHaveConfig> configMap) {
|
||||||
|
val ms = obj.getClass().getDeclaredMethods();
|
||||||
|
for (val m : ms) {
|
||||||
|
if (!m.getReturnType().getName().equals(ConfigData.class.getName())) continue;
|
||||||
|
try {
|
||||||
|
m.setAccessible(true);
|
||||||
|
List<ConfigData<?>> configList;
|
||||||
|
if (m.getParameterCount() == 0) {
|
||||||
|
configList = Collections.singletonList((ConfigData<?>) m.invoke(obj));
|
||||||
|
} else if (m.getParameterCount() == 1 && m.getParameterTypes()[0] == IHaveConfig.class) {
|
||||||
|
if (configMap == null) continue; //Hope it will get called with the param later
|
||||||
|
configList = configMap.entrySet().stream().map(kv ->
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return (ConfigData<?>) m.invoke(obj, kv.getValue());
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
|
TBMCCoreAPI.SendException("Failed to pregenerate " + m.getName() + " for " + obj + " using config " + kv.getKey() + "!", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}).filter(Objects::nonNull).collect(Collectors.toList());
|
||||||
|
} else {
|
||||||
|
MainPlugin.Instance.getLogger().warning("Method " + m.getName() + " returns a config but its parameters are unknown: " + Arrays.toString(m.getParameterTypes()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (val c : configList) {
|
||||||
|
if (c.getPath().length() == 0)
|
||||||
|
c.setPath(m.getName());
|
||||||
|
else if (!c.getPath().equals(m.getName()))
|
||||||
|
MainPlugin.Instance.getLogger().warning("Config name does not match: " + c.getPath() + " instead of " + m.getName());
|
||||||
|
c.get(); //Saves the default value if needed - also checks validity
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
TBMCCoreAPI.SendException("Failed to pregenerate " + m.getName() + " for " + obj + "!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package buttondevteam.lib.architecture;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class ReadOnlyConfigData<T> extends ConfigData<T> {
|
||||||
|
ReadOnlyConfigData(ConfigurationSection config, String path, T def, Object primitiveDef, Function<Object, T> getter, Function<T, Object> setter, Runnable saveAction) {
|
||||||
|
super(config, path, def, primitiveDef, getter, setter, saveAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadOnlyConfigData(ConfigurationSection config, String path, T def, Object primitiveDef, Runnable saveAction) {
|
||||||
|
super(config, path, def, primitiveDef, saveAction);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package buttondevteam.lib.chat;
|
package buttondevteam.lib.chat;
|
||||||
|
|
||||||
|
import buttondevteam.core.MainPlugin;
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
import buttondevteam.lib.ThorpeUtils;
|
import buttondevteam.lib.ThorpeUtils;
|
||||||
import buttondevteam.lib.player.ChromaGamerBase;
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
|
@ -9,7 +10,9 @@ import lombok.AllArgsConstructor;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.experimental.var;
|
import lombok.experimental.var;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
|
@ -20,9 +23,7 @@ import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,10 +49,21 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Subcommand {
|
public @interface Subcommand {
|
||||||
|
/**
|
||||||
|
* Allowed for OPs only by default
|
||||||
|
*/
|
||||||
|
String MOD_GROUP = "mod";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Help text to show players. A usage message will be also shown below it.
|
* Help text to show players. A usage message will be also shown below it.
|
||||||
*/
|
*/
|
||||||
String[] helpText() default {};
|
String[] helpText() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main permission which allows using this command (individual access can be still granted with "thorpe.command.X").
|
||||||
|
* Used to be "tbmc.admin". The {@link #MOD_GROUP} is provided to use with this.
|
||||||
|
*/
|
||||||
|
String permGroup() default ""; //TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
@Target(ElementType.PARAMETER)
|
@Target(ElementType.PARAMETER)
|
||||||
|
@ -66,6 +78,31 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
public String[] helpText;
|
public String[] helpText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static class SubcommandHelpData<T extends ICommand2> extends SubcommandData<T> {
|
||||||
|
private final TreeSet<String> ht = new TreeSet<>();
|
||||||
|
private BukkitTask task;
|
||||||
|
|
||||||
|
public SubcommandHelpData(Method method, T command, String[] helpText) {
|
||||||
|
super(method, command, helpText);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSubcommand(String command) {
|
||||||
|
ht.add(command);
|
||||||
|
if (task == null)
|
||||||
|
task = Bukkit.getScheduler().runTask(MainPlugin.Instance, () -> {
|
||||||
|
helpText = new String[ht.size() + 1]; //This will only run after the server is started List<E> list = new ArrayList<E>(size());
|
||||||
|
helpText[0] = "§6---- Subcommands ----"; //TODO: There may be more to the help text
|
||||||
|
int i = 1;
|
||||||
|
for (Iterator<String> iterator = ht.iterator();
|
||||||
|
iterator.hasNext() && i < helpText.length; i++) {
|
||||||
|
String e = iterator.next();
|
||||||
|
helpText[i] = e;
|
||||||
|
}
|
||||||
|
task = null; //Run again, if needed
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
protected static class ParamConverter<T> {
|
protected static class ParamConverter<T> {
|
||||||
public final Function<String, T> converter;
|
public final Function<String, T> converter;
|
||||||
|
@ -98,7 +135,7 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
sender.sendMessage(sd.helpText);
|
sender.sendMessage(sd.helpText);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!hasPermission(sender, sd.command)) {
|
if (!hasPermission(sender, sd.command, sd.method)) {
|
||||||
sender.sendMessage("§cYou don't have permission to use this command");
|
sender.sendMessage("§cYou don't have permission to use this command");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -155,10 +192,8 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
continue;
|
continue;
|
||||||
} else if (Number.class.isAssignableFrom(cl) || cl.isPrimitive()) {
|
} else if (Number.class.isAssignableFrom(cl) || cl.isPrimitive()) {
|
||||||
try {
|
try {
|
||||||
//System.out.println("Converting "+param+" param to "+cl.getSimpleName());
|
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
Number n = ThorpeUtils.convertNumber(NumberFormat.getInstance().parse(param), (Class<? extends Number>) cl);
|
Number n = ThorpeUtils.convertNumber(NumberFormat.getInstance().parse(param), (Class<? extends Number>) cl);
|
||||||
//System.out.println(n.getClass().getSimpleName()+" with value "+n);
|
|
||||||
params.add(n);
|
params.add(n);
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
sender.sendMessage("§c'" + param + "' is not a number.");
|
sender.sendMessage("§c'" + param + "' is not a number.");
|
||||||
|
@ -176,7 +211,6 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
}
|
}
|
||||||
params.add(cparam);
|
params.add(cparam);
|
||||||
}
|
}
|
||||||
//System.out.println("Our params: "+params);
|
|
||||||
try {
|
try {
|
||||||
val ret = sd.method.invoke(sd.command, params.toArray()); //I FORGOT TO TURN IT INTO AN ARRAY (for a long time)
|
val ret = sd.method.invoke(sd.command, params.toArray()); //I FORGOT TO TURN IT INTO AN ARRAY (for a long time)
|
||||||
if (ret instanceof Boolean) {
|
if (ret instanceof Boolean) {
|
||||||
|
@ -276,7 +310,7 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
||||||
return ht;
|
return ht;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean hasPermission(TP sender, TC command);
|
public abstract boolean hasPermission(TP sender, TC command, Method subcommand);
|
||||||
|
|
||||||
public String[] getCommandsText() {
|
public String[] getCommandsText() {
|
||||||
return commandHelp.toArray(new String[0]);
|
return commandHelp.toArray(new String[0]);
|
||||||
|
|
|
@ -1,21 +1,60 @@
|
||||||
package buttondevteam.lib.chat;
|
package buttondevteam.lib.chat;
|
||||||
|
|
||||||
import buttondevteam.core.MainPlugin;
|
import buttondevteam.core.MainPlugin;
|
||||||
|
import lombok.experimental.var;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.command.ConsoleCommandSender;
|
||||||
|
import org.bukkit.permissions.Permission;
|
||||||
|
import org.bukkit.permissions.PermissionDefault;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class Command2MC extends Command2<ICommand2MC, Command2MCSender> {
|
public class Command2MC extends Command2<ICommand2MC, Command2MCSender> {
|
||||||
@Override
|
@Override
|
||||||
public void registerCommand(ICommand2MC command) {
|
public void registerCommand(ICommand2MC command) {
|
||||||
super.registerCommand(command, '/');
|
super.registerCommand(command, '/');
|
||||||
|
var perm = "thorpe.command." + command.getCommandPath().replace(' ', '.');
|
||||||
|
if (Bukkit.getPluginManager().getPermission(perm) == null) //Check needed for plugin reset
|
||||||
|
Bukkit.getPluginManager().addPermission(new Permission(perm,
|
||||||
|
modOnly(command) ? PermissionDefault.OP : PermissionDefault.TRUE)); //Allow commands by default, unless it's mod only - TODO: Test
|
||||||
|
for (val method : command.getClass().getMethods()) {
|
||||||
|
if (!method.isAnnotationPresent(Subcommand.class)) continue;
|
||||||
|
String pg = permGroup(command, method);
|
||||||
|
if (pg.length() == 0) continue;
|
||||||
|
perm = "thorpe." + pg;
|
||||||
|
if (Bukkit.getPluginManager().getPermission(perm) == null) //It may occur multiple times
|
||||||
|
Bukkit.getPluginManager().addPermission(new Permission(perm,
|
||||||
|
//pg.equals(Subcommand.MOD_GROUP) ? PermissionDefault.OP : PermissionDefault.TRUE)); //Allow commands by default, unless it's mod only
|
||||||
|
PermissionDefault.OP)); //Do not allow any commands that belong to a group
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasPermission(Command2MCSender sender, ICommand2MC command) {
|
public boolean hasPermission(Command2MCSender sender, ICommand2MC command, Method method) {
|
||||||
return modOnly(command)
|
if (sender.getSender() instanceof ConsoleCommandSender) return true; //Always allow the console
|
||||||
? MainPlugin.permission.has(sender.getSender(), "tbmc.admin") //TODO: Change when groups are implemented
|
String pg;
|
||||||
: MainPlugin.permission.has(sender.getSender(), "thorpe.command." + command.getCommandPath().replace(' ', '.'));
|
boolean p = true;
|
||||||
|
String[] perms = {
|
||||||
|
"thorpe.command." + command.getCommandPath().replace(' ', '.'),
|
||||||
|
(pg = permGroup(command, method)).length() > 0 ? "thorpe." + pg : null,
|
||||||
|
modOnly(command) ? "tbmc.admin" : null
|
||||||
|
};
|
||||||
|
for (String perm : perms) {
|
||||||
|
if (perm != null) {
|
||||||
|
if (p) { //Use OfflinePlayer to avoid fetching player data
|
||||||
|
if (sender.getSender() instanceof OfflinePlayer)
|
||||||
|
p = MainPlugin.permission.playerHas(null, (OfflinePlayer) sender.getSender(), perm);
|
||||||
|
else
|
||||||
|
p = MainPlugin.permission.playerHas(null, Bukkit.getOfflinePlayer(new UUID(0, 0)), perm);
|
||||||
|
} else break; //If any of the permissions aren't granted then don't allow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,11 +64,41 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> {
|
||||||
* @return Whether the command is mod only
|
* @return Whether the command is mod only
|
||||||
*/
|
*/
|
||||||
private boolean modOnly(ICommand2MC command) {
|
private boolean modOnly(ICommand2MC command) {
|
||||||
for (Class<?> cl = command.getClass(); cl != null; cl = cl.getSuperclass()) {
|
return getAnnForValue(command.getClass(), CommandClass.class, CommandClass::modOnly, false);
|
||||||
val cc = command.getClass().getAnnotation(CommandClass.class);
|
|
||||||
if (cc != null && cc.modOnly()) return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
/**
|
||||||
|
* Returns true if this class or <u>any</u> of the superclasses are mod only.
|
||||||
|
*
|
||||||
|
* @param method The subcommand to check
|
||||||
|
* @return The permission group for the subcommand or empty string
|
||||||
|
*/
|
||||||
|
private String permGroup(ICommand2MC command, Method method) {
|
||||||
|
val sc = method.getAnnotation(Subcommand.class);
|
||||||
|
if (sc != null && sc.permGroup().length() > 0) {
|
||||||
|
return sc.permGroup();
|
||||||
|
}
|
||||||
|
return getAnnForValue(command.getClass(), CommandClass.class, CommandClass::permGroup, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loops until it finds a value that is <b>not</b> the same as def
|
||||||
|
*
|
||||||
|
* @param sourceCl The class which has the annotation
|
||||||
|
* @param annCl The annotation to get
|
||||||
|
* @param annMethod The annotation method to check
|
||||||
|
* @param def The value to ignore when looking for the result
|
||||||
|
* @param <T> The annotation type
|
||||||
|
* @param <V> The type of the value
|
||||||
|
* @return The value returned by the first superclass or def
|
||||||
|
*/
|
||||||
|
private <T extends Annotation, V> V getAnnForValue(Class<?> sourceCl, Class<T> annCl, Function<T, V> annMethod, V def) {
|
||||||
|
for (Class<?> cl = sourceCl; cl != null; cl = cl.getSuperclass()) {
|
||||||
|
val cc = cl.getAnnotation(annCl);
|
||||||
|
V r;
|
||||||
|
if (cc != null && (r = annMethod.apply(cc)) != def) return r;
|
||||||
|
}
|
||||||
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -44,4 +44,10 @@ public @interface CommandClass {
|
||||||
* @return The help text
|
* @return The help text
|
||||||
*/
|
*/
|
||||||
String[] helpText() default {};
|
String[] helpText() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main permission which allows using this command (individual access can be still granted with "thorpe.command.X").
|
||||||
|
* Used to be "tbmc.admin"
|
||||||
|
*/
|
||||||
|
String permGroup() default ""; //TODO: A single annotation instead of these two
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package buttondevteam.lib.chat;
|
||||||
|
|
||||||
import buttondevteam.lib.architecture.ButtonPlugin;
|
import buttondevteam.lib.architecture.ButtonPlugin;
|
||||||
|
|
||||||
public class ICommand2MC extends ICommand2<Command2MCSender> {
|
public abstract class ICommand2MC extends ICommand2<Command2MCSender> {
|
||||||
public ICommand2MC() {
|
public ICommand2MC() {
|
||||||
super(ButtonPlugin.getCommand2MC());
|
super(ButtonPlugin.getCommand2MC());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,43 +1,78 @@
|
||||||
package buttondevteam.buttonproc;
|
package buttondevteam.buttonproc;
|
||||||
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
|
|
||||||
import javax.annotation.processing.ProcessingEnvironment;
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
|
import javax.lang.model.element.ExecutableElement;
|
||||||
import javax.lang.model.element.Modifier;
|
import javax.lang.model.element.Modifier;
|
||||||
|
import javax.lang.model.type.DeclaredType;
|
||||||
|
import javax.lang.model.type.TypeKind;
|
||||||
|
import javax.lang.model.type.TypeMirror;
|
||||||
import javax.tools.FileObject;
|
import javax.tools.FileObject;
|
||||||
import javax.tools.StandardLocation;
|
import javax.tools.StandardLocation;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class ConfigProcessor {
|
public class ConfigProcessor {
|
||||||
private final ProcessingEnvironment procEnv;
|
private final ProcessingEnvironment procEnv;
|
||||||
private final YamlConfiguration yaml;
|
private final FileWriter sw;
|
||||||
private final File file;
|
|
||||||
|
|
||||||
public ConfigProcessor(ProcessingEnvironment procEnv) {
|
public ConfigProcessor(ProcessingEnvironment procEnv) {
|
||||||
this.procEnv = procEnv;
|
this.procEnv = procEnv;
|
||||||
FileObject file = null;
|
FileWriter sw = null;
|
||||||
try {
|
try {
|
||||||
file = procEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", "config.yml");
|
FileObject file = procEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", "configHelp.md");
|
||||||
|
sw = new FileWriter(new File(file.toUri()));
|
||||||
|
System.out.println(file.toUri());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
yaml = new YamlConfiguration();
|
this.sw = sw;
|
||||||
this.file = new File(file.toUri());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(Element targetcl) {
|
public void process(Element targetcl) {
|
||||||
if (targetcl.getModifiers().contains(Modifier.ABSTRACT)) return;
|
if (targetcl.getModifiers().contains(Modifier.ABSTRACT)) return;
|
||||||
String javadoc = procEnv.getElementUtils().getDocComment(targetcl);
|
final String path = "components." + targetcl.getSimpleName();
|
||||||
if (javadoc == null) return;
|
for (Element e : targetcl.getEnclosedElements()) {
|
||||||
System.out.println("JAVADOC"); //TODO: Config methods
|
/*System.out.println("Element: "+e);
|
||||||
System.out.println(javadoc);
|
System.out.println("Type: "+e.getClass()+" - "+e.getKind());
|
||||||
yaml.set("components." + targetcl.getSimpleName() + "._doc", javadoc);
|
if(e instanceof ExecutableElement)
|
||||||
|
System.out.println("METHOD!");*/
|
||||||
|
if (!(e instanceof ExecutableElement)) continue;
|
||||||
|
TypeMirror tm = ((ExecutableElement) e).getReturnType();
|
||||||
|
if (tm.getKind() != TypeKind.DECLARED) continue;
|
||||||
|
DeclaredType dt = (DeclaredType) tm;
|
||||||
|
if (!dt.asElement().getSimpleName().contentEquals("ConfigData"))
|
||||||
|
continue; //Ahhha! There was a return here! (MinecraftChatModule getListener())
|
||||||
|
System.out.println("Config: " + e.getSimpleName());
|
||||||
|
|
||||||
|
String doc = procEnv.getElementUtils().getDocComment(e);
|
||||||
|
if (doc == null) continue;
|
||||||
|
System.out.println("DOC: " + doc);
|
||||||
try {
|
try {
|
||||||
yaml.save(file);
|
sw.append(path).append(".").append(String.valueOf(e.getSimpleName())).append(System.lineSeparator()).append(System.lineSeparator());
|
||||||
|
sw.append(doc.trim()).append(System.lineSeparator()).append(System.lineSeparator());
|
||||||
|
} catch (IOException e1) {
|
||||||
|
e1.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String javadoc = procEnv.getElementUtils().getDocComment(targetcl);
|
||||||
|
try {
|
||||||
|
if (javadoc != null) {
|
||||||
|
System.out.println("JAVADOC");
|
||||||
|
System.out.println(javadoc.trim());
|
||||||
|
sw.append(path).append(System.lineSeparator()).append(System.lineSeparator());
|
||||||
|
sw.append(javadoc).append(System.lineSeparator()).append(System.lineSeparator());
|
||||||
|
}
|
||||||
|
sw.flush();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void finalize() throws Throwable {
|
||||||
|
sw.close();
|
||||||
|
super.finalize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue