Merge pull request #54 from TBMCPlugins/dev

First release of the 'redesign', organizing most features into components
This commit is contained in:
Norbi Peti 2019-01-03 21:38:03 +01:00 committed by GitHub
commit 814a5c7eb9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 797 additions and 101 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

@ -4,6 +4,7 @@
<modules>
<module fileurl="file://$PROJECT_DIR$/BuildConfigUpdater/BuildConfigUpdater.iml" filepath="$PROJECT_DIR$/BuildConfigUpdater/BuildConfigUpdater.iml" />
<module fileurl="file://$PROJECT_DIR$/ButtonCore/ButtonCore (1) (com.github.TBMCPlugins.ButtonCore).iml" filepath="$PROJECT_DIR$/ButtonCore/ButtonCore (1) (com.github.TBMCPlugins.ButtonCore).iml" />
<module fileurl="file://$PROJECT_DIR$/ButtonCore/ButtonCore (1) (com.github.TBMCPlugins.ButtonCore).iml" filepath="$PROJECT_DIR$/ButtonCore/ButtonCore (1) (com.github.TBMCPlugins.ButtonCore).iml" />
<module fileurl="file://$PROJECT_DIR$/ButtonProcessor/ButtonProcessor.iml" filepath="$PROJECT_DIR$/ButtonProcessor/ButtonProcessor.iml" />
</modules>
</component>

124
.idea/uiDesigner.xml Normal file
View file

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

View file

@ -12,7 +12,6 @@
<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

@ -1,4 +1,4 @@
import buttondevteam.lib.PluginUpdater;
import buttondevteam.component.updater.PluginUpdater;
import java.util.List;
import java.util.stream.Collectors;

1
ButtonCore/lombok.config Normal file
View file

@ -0,0 +1 @@
lombok.var.flagUsage = ALLOW

View file

@ -72,6 +72,26 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<useSystemClassLoader>false
</useSystemClassLoader> <!-- https://stackoverflow.com/a/53012553/2703239 -->
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>

View file

@ -0,0 +1,15 @@
package buttondevteam.component.commands;
import buttondevteam.lib.architecture.Component;
public class CommandComponent extends Component { //TODO: Do we just move everything here?
@Override
public void enable() {
}
@Override
public void disable() {
}
}

View file

@ -0,0 +1,20 @@
package buttondevteam.component.restart;
import buttondevteam.core.PrimeRestartCommand;
import buttondevteam.core.ScheduledRestartCommand;
import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.chat.TBMCChatAPI;
public class RestartComponent extends Component {
@Override
public void enable() {
//TODO: Permissions for the commands
TBMCChatAPI.AddCommand(getPlugin(), ScheduledRestartCommand.class);
TBMCChatAPI.AddCommand(getPlugin(), PrimeRestartCommand.class);
}
@Override
public void disable() {
}
}

View file

@ -1,5 +1,6 @@
package buttondevteam.lib;
package buttondevteam.component.updater;
import buttondevteam.lib.TBMCCoreAPI;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@ -136,7 +137,7 @@ public class PluginUpdater {
public static List<String> GetPluginNames() {
List<String> ret = new ArrayList<>();
try {
String resp = TBMCCoreAPI.DownloadString("https://api.github.com/orgs/TBMCPlugins/repos");
String resp = TBMCCoreAPI.DownloadString("https://api.github.com/orgs/" + "TBMCPlugins" + "/repos"); //TODO: PluginUpdater
JsonArray arr = new JsonParser().parse(resp).getAsJsonArray();
for (JsonElement obj : arr) {
JsonObject jobj = obj.getAsJsonObject();

View file

@ -0,0 +1,16 @@
package buttondevteam.component.updater;
import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.chat.TBMCChatAPI;
public class PluginUpdaterComponent extends Component {
@Override
public void enable() {
TBMCChatAPI.AddCommand(getPlugin(), UpdatePluginCommand.class);
}
@Override
public void disable() { //TODO: Unregister commands and such
}
}

View file

@ -1,6 +1,6 @@
package buttondevteam.core;
package buttondevteam.component.updater;
import buttondevteam.lib.PluginUpdater;
import buttondevteam.core.MainPlugin;
import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.chat.TBMCCommandBase;

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,57 @@
package buttondevteam.core;
import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.architecture.Component;
import lombok.val;
public final class ComponentManager {
private ComponentManager() {}
private static boolean componentsEnabled = false;
/**
* This flag is used to enable components registered after the others were enabled.
* @return Whether already registered components have been enabled
*/
public static boolean areComponentsEnabled() { return componentsEnabled; }
/**
* Enables components based on a configuration - any component registered afterwards will be also enabled
*/
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 (Exception e) {
TBMCCoreAPI.SendException("Failed to enable one of the components: " + c.getClass().getSimpleName(), e);
}
});
componentsEnabled = true;
}
/**
* 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 (Exception e) {
TBMCCoreAPI.SendException("Failed to disable one of the components: " + c.getClass().getSimpleName(), e);
}
});
componentsEnabled = false;
}
/**
* Will also return false if the component is not registered.
*
* @param cl The component class
* @return Whether the component is registered and enabled
*/
public static boolean isEnabled(Class<? extends Component> cl) {
val c = Component.getComponents().get(cl);
return c != null && c.isEnabled();
}
}

View file

@ -1,7 +1,10 @@
package buttondevteam.core;
import buttondevteam.lib.PluginUpdater;
import buttondevteam.component.restart.RestartComponent;
import buttondevteam.component.updater.PluginUpdater;
import buttondevteam.component.updater.PluginUpdaterComponent;
import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.chat.Channel;
import buttondevteam.lib.chat.ChatRoom;
import buttondevteam.lib.chat.Color;
@ -47,9 +50,9 @@ public class MainPlugin extends JavaPlugin {
setupPermissions();
Test = getConfig().getBoolean("test", true);
saveConfig();
TBMCChatAPI.AddCommand(this, UpdatePluginCommand.class);
TBMCChatAPI.AddCommand(this, ScheduledRestartCommand.class);
TBMCChatAPI.AddCommand(this, PrimeRestartCommand.class);
Component.registerComponent(this, new PluginUpdaterComponent());
Component.registerComponent(this, new RestartComponent());
ComponentManager.enableComponents();
TBMCChatAPI.AddCommand(this, MemberCommand.class);
TBMCCoreAPI.RegisterEventsForExceptions(new PlayerListener(), this);
ChromaGamerBase.addConverter(commandSender -> Optional.ofNullable(commandSender instanceof ConsoleCommandSender || commandSender instanceof BlockCommandSender
@ -82,6 +85,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,7 +1,7 @@
package buttondevteam.core;
import buttondevteam.lib.TBMCSystemChatEvent;
import buttondevteam.lib.chat.IDiscordSender;
import buttondevteam.lib.chat.IFakePlayer;
import buttondevteam.lib.player.TBMCPlayerBase;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@ -43,7 +43,7 @@ public class PlayerListener implements Listener {
if (PrimeRestartCommand.isLoud())
Bukkit.broadcastMessage("§cNobody is online anymore. Restarting.");
Bukkit.spigot().restart();
} else if (!(event.getPlayer() instanceof IDiscordSender) && System.nanoTime() - 10 * 1000000000L - lasttime > 0) { //Ten seconds passed since last reminder
} else if (!(event.getPlayer() instanceof IFakePlayer) && System.nanoTime() - 10 * 1000000000L - lasttime > 0) { //Ten seconds passed since last reminder
lasttime = System.nanoTime();
if (PrimeRestartCommand.isLoud())
Bukkit.broadcastMessage(ChatColor.DARK_RED + "The server will restart as soon as nobody is online.");

View file

@ -1,8 +1,9 @@
package buttondevteam.lib;
import buttondevteam.lib.chat.Channel;
import buttondevteam.lib.player.ChromaGamerBase;
import buttondevteam.lib.chat.ChatMessage;
import lombok.Getter;
import lombok.experimental.Delegate;
import org.bukkit.command.CommandSender;
import org.bukkit.event.HandlerList;
@ -16,28 +17,19 @@ import javax.annotation.Nullable;
*/
@Getter
public class TBMCChatEvent extends TBMCChatEventBase {
public TBMCChatEvent(CommandSender sender, ChromaGamerBase user, Channel channel, String message, int score, boolean fromcmd, String groupid) {
super(channel, message, score, groupid);
this.sender = sender;
this.fromcmd = fromcmd;
this.ignoreSenderPermissions = false;
this.user = user;
}
public TBMCChatEvent(CommandSender sender, ChromaGamerBase user, Channel channel, String message, int score, boolean fromcmd, String groupid, boolean ignoreSenderPermissions) {
super(channel, message, score, groupid);
this.sender = sender;
this.user = user;
this.fromcmd = fromcmd;
this.ignoreSenderPermissions = ignoreSenderPermissions;
public TBMCChatEvent(Channel channel, ChatMessage cm, Channel.RecipientTestResult rtr) {
super(channel, cm.getMessage(), rtr.score, rtr.groupID);
this.cm = cm;
}
private static final HandlerList handlers = new HandlerList();
private final CommandSender sender;
private final boolean fromcmd;
private final boolean ignoreSenderPermissions;
private final ChromaGamerBase user;
@Delegate //<-- Backwards compatibility
private ChatMessage cm;
private boolean isIgnoreSenderPermissions() {
return cm.getPermCheck() != cm.getSender();
}
// TODO: Message object with data?
/**
@ -45,7 +37,7 @@ public class TBMCChatEvent extends TBMCChatEventBase {
*/
@Override
public boolean shouldSendTo(CommandSender sender) {
if (isIgnoreSenderPermissions() && sender.equals(this.sender))
if (isIgnoreSenderPermissions() && sender.equals(this.cm.getSender()))
return true; //Allow sending the message no matter what
return super.shouldSendTo(sender);
}
@ -55,7 +47,7 @@ public class TBMCChatEvent extends TBMCChatEventBase {
*/
@Override
public int getMCScore(CommandSender sender) {
if (isIgnoreSenderPermissions() && sender.equals(this.sender))
if (isIgnoreSenderPermissions() && sender.equals(this.cm.getSender()))
return getScore(); //Send in the correct group no matter what
return super.getMCScore(sender);
}
@ -66,7 +58,7 @@ public class TBMCChatEvent extends TBMCChatEventBase {
@Nullable
@Override
public String getGroupID(CommandSender sender) {
if (isIgnoreSenderPermissions() && sender.equals(this.sender))
if (isIgnoreSenderPermissions() && sender.equals(this.cm.getSender()))
return getGroupID(); //Send in the correct group no matter what
return super.getGroupID(sender);
}

View file

@ -1,5 +1,6 @@
package buttondevteam.lib;
import buttondevteam.component.updater.PluginUpdater;
import buttondevteam.core.MainPlugin;
import buttondevteam.lib.player.ChromaGamerBase;
import buttondevteam.lib.potato.DebugPotato;

View file

@ -0,0 +1,52 @@
package buttondevteam.lib.architecture;
import buttondevteam.lib.TBMCCoreAPI;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
public abstract class ButtonPlugin extends JavaPlugin {
private final HashMap<String, ConfigData<?>> datamap = new HashMap<>();
private ConfigurationSection section;
protected abstract void pluginEnable();
protected abstract void pluginDisable();
@Override
public void onEnable() {
section = getConfig().getConfigurationSection("global");
if (section == null) section = getConfig().createSection("global");
try {
pluginEnable();
} catch (Exception e) {
TBMCCoreAPI.SendException("Error while enabling plugin " + getName() + "!", e);
}
}
@Override
public void onDisable() {
try {
pluginDisable();
} catch (Exception e) {
TBMCCoreAPI.SendException("Error while disabling plugin " + getName() + "!", e);
}
}
/**
* @see IHaveConfig#getData(Map, ConfigurationSection, String, Object)
*/
protected <T> ConfigData<T> getData(String path, T def) {
return IHaveConfig.getData(datamap, section, path, def);
}
/**
* @see IHaveConfig#getData(Map, ConfigurationSection, String, Object, Function, Function)
*/
protected <T> ConfigData<T> getData(String path, T def, Function<Object, T> getter, Function<T, Object> setter) {
return IHaveConfig.getData(datamap, section, path, def, getter, setter);
}
}

View file

@ -0,0 +1,221 @@
package buttondevteam.lib.architecture;
import buttondevteam.core.ComponentManager;
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.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 = 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<>();
/**
* @see IHaveConfig#getData(Map, ConfigurationSection, String, Object)
*/
protected <T> ConfigData<T> getData(String path, T def) {
return IHaveConfig.getData(datamap, config, path, def);
}
/**
* @see IHaveConfig#getData(Map, ConfigurationSection, String, Object, Function, Function)
*/
protected <T> ConfigData<T> getData(String path, T def, Function<Object, T> getter, Function<T, Object> setter) {
return IHaveConfig.getData(datamap, config, path, def, getter, setter);
}
/**
* Registers a component checking it's dependencies and calling {@link #register(JavaPlugin)}.<br>
* Make sure to register the dependencies first.<br>
* The component will be enabled automatically, regardless of when it was registered.
*
* @param component The component to register
* @return Whether the component is registered successfully (it may have failed to enable)
*/
public static boolean registerComponent(JavaPlugin plugin, Component component) {
return registerUnregisterComponent(plugin, component, true);
}
/**
* Unregisters a component by calling {@link #unregister(JavaPlugin)}.<br>
* Make sure to unregister the dependencies last.
*
* @param componentClass The component class to unregister
* @return Whether the component is unregistered successfully (it also got disabled)
*/
public static boolean unregisterComponent(JavaPlugin plugin, Class<? extends Component> componentClass) {
val component = components.get(componentClass);
if (component == null)
return false; //Failed to load
return registerUnregisterComponent(plugin, component, false);
}
public static boolean registerUnregisterComponent(JavaPlugin plugin, Component component, boolean register) {
try {
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 ? "" : "un") + "register component " + component.getClassName() + " as a required dependency is missing/disabled: " + dep.getSimpleName());
return false;
}
}
}
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);
if (ComponentManager.areComponentsEnabled() && component.shouldBeEnabled().get()) {
try { //Enable components registered after the previous ones getting enabled
setComponentEnabled(component, true);
return true;
} catch (Exception | NoClassDefFoundError e) {
TBMCCoreAPI.SendException("Failed to enable component " + component.getClassName() + "!", e);
return true;
}
}
return true;
} else {
if (component.enabled) {
try {
component.disable();
component.enabled = false;
} catch (Exception | NoClassDefFoundError e) {
TBMCCoreAPI.SendException("Failed to disable component " + component.getClassName() + "!", e);
return false; //If failed to disable, won't unregister either
}
}
component.unregister(plugin);
components.remove(component.getClass());
return true;
}
} catch (Exception e) {
TBMCCoreAPI.SendException("Failed to " + (register ? "" : "un") + "register component " + component.getClassName() + "!", e);
return false;
}
}
/**
* Registers a component checking it's dependencies and calling {@link #register(JavaPlugin)}.<br>
* Make sure to register the dependencies first.
*
* @param component The component to register
*/
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);
}
/**
* Registers the module, when called by the JavaPlugin class.
* This gets fired when the plugin is enabled. Use {@link #enable()} to register commands and such.
*
* @param plugin Plugin object
*/
protected void register(JavaPlugin plugin) {
}
/**
* Unregisters the module, when called by the JavaPlugin class.
* This gets fired when the plugin is disabled.
* Do any cleanups needed within this method.
*
* @param plugin Plugin object
*/
protected 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}.
*
* @param plugin Main plugin responsible for stuff
* @param commandBase Custom coded command class
*/
protected void registerCommand(JavaPlugin plugin, TBMCCommandBase commandBase) {
TBMCChatAPI.AddCommand(plugin, commandBase);
}
/**
* Registers a Listener to this plugin
*
* @param plugin Main plugin responsible for stuff
* @param listener The event listener to register
* @return The provided listener
*/
protected Listener registerListener(JavaPlugin plugin, Listener listener) {
TBMCCoreAPI.RegisterEventsForExceptions(listener, plugin);
return listener;
}
private String getClassName() {
Class<?> enclosingClass = getClass().getEnclosingClass();
String className;
if (enclosingClass != null) {
className = (enclosingClass.getName());
} else {
className = (getClass().getName());
}
return className;
}
}

View file

@ -0,0 +1,12 @@
package buttondevteam.lib.architecture;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentMetadata {
Class<? extends Component>[] depends();
}

View file

@ -0,0 +1,48 @@
package buttondevteam.lib.architecture;
import lombok.AccessLevel;
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.<br>
* Use {@link Component#getData(String, Object)} or {@link ButtonPlugin#getData(String, Object)} to get an instance.
*/
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
@AllArgsConstructor(access = AccessLevel.PACKAGE)
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) {
T hmm = getter.apply(val);
if (hmm == null) hmm = def; //Set if the getter returned null
return hmm;
}
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,45 @@
package buttondevteam.lib.architecture;
import org.bukkit.configuration.ConfigurationSection;
import java.util.Map;
import java.util.function.Function;
/**
* Members of this interface should be protected (access level)
*/
final class IHaveConfig {
private IHaveConfig() {}
/**
* 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 static <T> ConfigData<T> getData(Map<String, ConfigData<?>> datamap, ConfigurationSection config, 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 static <T> ConfigData<T> getData(Map<String, ConfigData<?>> datamap, ConfigurationSection config, 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;
}
}

View file

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

View file

@ -34,7 +34,7 @@ public class Channel {
/**
* Filters both the sender and the targets
*/
public final Function<CommandSender, RecipientTestResult> filteranderrormsg;
private final Function<CommandSender, RecipientTestResult> filteranderrormsg;
private static final List<Channel> channels = new ArrayList<>();
@ -87,10 +87,7 @@ public class Channel {
* Note: Errors are sent to the sender automatically
*/
public int getMCScore(CommandSender sender) {
if (filteranderrormsg == null)
return SCORE_SEND_OK;
RecipientTestResult result = filteranderrormsg.apply(sender);
return result.errormessage == null ? result.score : SCORE_SEND_NOPE;
return getRTR(sender).score; //No need to check if there was an error
}
/**
@ -100,10 +97,13 @@ public class Channel {
*/
@Nullable
public String getGroupID(CommandSender sender) {
return getRTR(sender).groupID; //No need to check if there was an error
}
public RecipientTestResult getRTR(CommandSender sender) {
if (filteranderrormsg == null)
return GROUP_EVERYONE;
RecipientTestResult result = filteranderrormsg.apply(sender);
return result.errormessage == null ? result.groupID : null;
return new RecipientTestResult(SCORE_SEND_OK, GROUP_EVERYONE);
return filteranderrormsg.apply(sender);
}
public static List<Channel> getChannels() {
@ -143,9 +143,10 @@ public class Channel {
}
public static class RecipientTestResult {
public String errormessage = null;
public int score = SCORE_SEND_NOPE; // Anything below 0 is "never send"
public String groupID = null;
public final String errormessage;
public final int score; // Anything below 0 is "never send"
public final String groupID;
public static final RecipientTestResult ALL = new RecipientTestResult(SCORE_SEND_OK, GROUP_EVERYONE);
/**
* Creates a result that indicates an <b>error</b>
@ -154,6 +155,8 @@ public class Channel {
*/
public RecipientTestResult(String errormessage) {
this.errormessage = errormessage;
this.score = SCORE_SEND_NOPE;
this.groupID = null;
}
/**
@ -163,8 +166,10 @@ public class Channel {
* @param groupID The ID of the target group.
*/
public RecipientTestResult(int score, String groupID) {
if (score < 0) throw new IllegalArgumentException("Score must be non-negative!");
this.score = score;
this.groupID = groupID;
this.errormessage = null;
}
}
}

View file

@ -4,39 +4,54 @@ import buttondevteam.lib.player.ChromaGamerBase;
import lombok.Builder;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import org.bukkit.command.CommandSender;
@Builder
@Getter
public class ChatMessage {
/**
* The sender which sends the message.
*/
private final CommandSender sender;
/**
* The Chroma user which sends the message.
*/
private final ChromaGamerBase user;
/**
* The message to send as the user.
*/
private final String message;
/**
* Indicates whether the message comes from running a command (like /tableflip). Implemented to be used from Discord.
*/
private boolean fromCommand;
/**
* The sender which we should check for permissions. Same as {@link #sender} by default.
*/
private CommandSender permCheck;
/**
* The sender which sends the message.
*/
private final CommandSender sender;
/**
* The Chroma user which sends the message.
*/
private final ChromaGamerBase user;
/**
* The message to send as the user.
*/
@Setter
private String message;
/**
* Indicates whether the message comes from running a command (like /tableflip). Implemented to be used from Discord.
*/
private boolean fromCommand;
/**
* The sender which we should check for permissions. Same as {@link #sender} by default.
*/
private CommandSender permCheck;
/**
* The origin of the message, "Minecraft" or "Discord" for example. May be displayed to the user.<br>
* <b>This is the user class capitalized folder name.</b>
*/
private final String origin;
private static ChatMessageBuilder builder() {
return new ChatMessageBuilder();
}
/**
* The sender which we should check for permissions. Same as {@link #sender} by default.
*
* @return The perm check or the sender
*/
public CommandSender getPermCheck() {
return permCheck == null ? sender : permCheck;
}
@NonNull
public static ChatMessageBuilder builder(CommandSender sender, ChromaGamerBase user, String message) {
return builder().sender(sender).user(user).message(message);
}
private static ChatMessageBuilder builder() {
return new ChatMessageBuilder();
}
@NonNull
public static ChatMessageBuilder builder(CommandSender sender, ChromaGamerBase user, String message) {
return builder().sender(sender).user(user).message(message).origin(user.getFolder().substring(0, 1).toUpperCase() + user.getFolder().substring(1));
}
}

View file

@ -15,11 +15,11 @@ public class ChatRoom extends Channel {
public void joinRoom(CommandSender sender) {
usersInRoom.add(sender);
TBMCChatAPI.SendSystemMessage(this, 0, "everyone", sender.getName() + " joined the room");
TBMCChatAPI.SendSystemMessage(this, RecipientTestResult.ALL, sender.getName() + " joined the room");
}
public void leaveRoom(CommandSender sender) {
usersInRoom.remove(sender);
TBMCChatAPI.SendSystemMessage(this, 0, "everyone", sender.getName() + " left the room");
TBMCChatAPI.SendSystemMessage(this, RecipientTestResult.ALL, sender.getName() + " left the room");
}
}

View file

@ -7,6 +7,6 @@ import org.bukkit.command.CommandSender;
* @author Norbi
*
*/
public interface IDiscordSender extends CommandSender {
public interface IFakePlayer extends CommandSender {
}

View file

@ -35,7 +35,7 @@ public class TBMCChatAPI {
/**
* Returns messages formatted for Minecraft chat listing the subcommands of the command.
*
*
* @param command
* The command which we want the subcommands of
* @param sender
@ -49,7 +49,7 @@ public class TBMCChatAPI {
/**
* Returns messages formatted for Minecraft chat listing the subcommands of the command.<br>
* Returns a header if subcommands were found, otherwise returns an empty array.
*
*
* @param command
* The command which we want the subcommands of
* @param sender
@ -228,17 +228,18 @@ public class TBMCChatAPI {
public static boolean SendChatMessage(ChatMessage cm, Channel channel) {
if (!Channel.getChannels().contains(channel))
throw new RuntimeException("Channel " + channel.DisplayName + " not registered!");
val permcheck = cm.getPermCheck() == null ? cm.getSender() : cm.getPermCheck();
val permcheck = cm.getPermCheck();
RecipientTestResult rtr = getScoreOrSendError(channel, permcheck);
int score = rtr.score;
if (score == -1 || rtr.groupID == null)
if (score == Channel.SCORE_SEND_NOPE || rtr.groupID == null)
return true;
TBMCChatPreprocessEvent eventPre = new TBMCChatPreprocessEvent(cm.getSender(), channel, cm.getMessage());
Bukkit.getPluginManager().callEvent(eventPre);
if (eventPre.isCancelled())
return true;
cm.setMessage(eventPre.getMessage());
TBMCChatEvent event;
event = new TBMCChatEvent(cm.getSender(), cm.getUser(), channel, eventPre.getMessage(), score, cm.isFromCommand(), rtr.groupID, permcheck != cm.getSender());
event = new TBMCChatEvent(channel, cm, rtr);
Bukkit.getPluginManager().callEvent(event);
return event.isCancelled();
}
@ -248,29 +249,25 @@ public class TBMCChatAPI {
*
* @param channel
* The channel to send to
* @param score
* The score to use to find the group - use 0 if the channel doesn't have scores
* @param rtr
* The score&group to use to find the group - use {@link RecipientTestResult#ALL} if the channel doesn't have scores
* @param message
* The message to send
* @return The event cancelled state
*/
public static boolean SendSystemMessage(Channel channel, int score, String groupid, String message) {
public static boolean SendSystemMessage(Channel channel, RecipientTestResult rtr, String message) {
if (!Channel.getChannels().contains(channel))
throw new RuntimeException("Channel " + channel.DisplayName + " not registered!");
TBMCSystemChatEvent event = new TBMCSystemChatEvent(channel, message, score, groupid);
TBMCSystemChatEvent event = new TBMCSystemChatEvent(channel, message, rtr.score, rtr.groupID);
Bukkit.getPluginManager().callEvent(event);
return event.isCancelled();
}
private static RecipientTestResult getScoreOrSendError(Channel channel, CommandSender sender) {
if (channel.filteranderrormsg == null)
return new RecipientTestResult(0, "everyone");
else {
RecipientTestResult result = channel.filteranderrormsg.apply(sender);
if (result.errormessage != null)
sender.sendMessage("§c" + result.errormessage);
return result;
}
RecipientTestResult result = channel.getRTR(sender);
if (result.errormessage != null)
sender.sendMessage("§c" + result.errormessage);
return result;
}
/**

View file

@ -8,6 +8,7 @@ import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import javax.annotation.Nullable;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
@ -203,6 +204,7 @@ public abstract class ChromaGamerBase implements AutoCloseable {
* @return The player as a {@link T} object or null if not having an account there
*/
@SuppressWarnings("unchecked")
@Nullable
public <T extends ChromaGamerBase> T getAs(Class<T> cl) { // TODO: Provide a way to use TBMCPlayerBase's loaded players
if (cl.getSimpleName().equals(getClass().getSimpleName()))
return (T) this;

View file

@ -13,7 +13,7 @@ import java.lang.annotation.*;
@Inherited
public @interface UserClass {
/**
* Indicates which folder should the player files be saved in.
* Indicates which folder should the player files be saved in. Must be lowercase.
*/
String foldername();
}

View file

@ -23,6 +23,14 @@
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<useSystemClassLoader>false
</useSystemClassLoader> <!-- https://stackoverflow.com/a/53012553/2703239 -->
</configuration>
</plugin>
</plugins>
</build>