Remove ComponentData, convert two components
- The new way of replacing configs doesn't actually support having ConfigData fields as they can become obsolete - Fixed KDoc formatting (new lines)
This commit is contained in:
parent
e610dbc0f6
commit
aabc2cd48c
14 changed files with 247 additions and 295 deletions
|
@ -21,7 +21,8 @@ open class Channel
|
||||||
/**
|
/**
|
||||||
* Creates a channel.
|
* Creates a channel.
|
||||||
*
|
*
|
||||||
* @param filterAndErrorMSG Checks all senders against the criteria provided here and sends the message if the index matches the sender's - if no score at all, displays the error.<br></br>
|
* @param filterAndErrorMSG Checks all senders against the criteria provided here and sends the message if the index matches the sender's - if no score at all, displays the error.
|
||||||
|
*
|
||||||
* May be null to send to everyone.
|
* May be null to send to everyone.
|
||||||
*/(
|
*/(
|
||||||
/**
|
/**
|
||||||
|
@ -86,8 +87,7 @@ open class Channel
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: Errors are sent to the sender automatically<br></br>
|
* Note: Errors are sent to the sender automatically
|
||||||
*
|
|
||||||
*
|
*
|
||||||
* Null means don't send
|
* Null means don't send
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,115 +1,101 @@
|
||||||
package buttondevteam.core.component.members;
|
package buttondevteam.core.component.members
|
||||||
|
|
||||||
import buttondevteam.core.MainPlugin;
|
import buttondevteam.core.MainPlugin
|
||||||
import buttondevteam.lib.architecture.Component;
|
import buttondevteam.lib.architecture.Component
|
||||||
import buttondevteam.lib.architecture.ComponentMetadata;
|
import buttondevteam.lib.architecture.ComponentMetadata
|
||||||
import buttondevteam.lib.architecture.ConfigData;
|
import org.bukkit.Statistic
|
||||||
import org.bukkit.Statistic;
|
import org.bukkit.entity.Player
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.event.EventHandler
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.Listener
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.player.PlayerJoinEvent
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import java.time.Instant
|
||||||
|
import java.time.temporal.ChronoUnit
|
||||||
import java.time.Instant;
|
import java.util.*
|
||||||
import java.time.temporal.ChronoUnit;
|
|
||||||
import java.util.AbstractMap;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import static buttondevteam.core.MainPlugin.permission;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows giving a 'member' group over some time elapsed OR played.
|
* Allows giving a 'member' group over some time elapsed OR played.
|
||||||
*/
|
*/
|
||||||
@ComponentMetadata(enabledByDefault = false)
|
@ComponentMetadata(enabledByDefault = false)
|
||||||
public class MemberComponent extends Component<MainPlugin> implements Listener {
|
class MemberComponent : Component<MainPlugin>(), Listener {
|
||||||
/**
|
/**
|
||||||
* The permission group to give to the player
|
* The permission group to give to the player
|
||||||
*/
|
*/
|
||||||
final ConfigData<String> memberGroup = getConfig().getData("memberGroup", "member");
|
val memberGroup get() = config.getData("memberGroup", "member")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The amount of hours needed to play before promotion
|
* The amount of hours needed to play before promotion
|
||||||
*/
|
*/
|
||||||
private final ConfigData<Integer> playedHours = getConfig().getData("playedHours", 12);
|
private val playedHours get() = config.getData("playedHours", 12)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The amount of days passed since first login
|
* The amount of days passed since first login
|
||||||
*/
|
*/
|
||||||
private final ConfigData<Integer> registeredForDays = getConfig().getData("registeredForDays", 7);
|
private val registeredForDays get() = config.getData("registeredForDays", 7)
|
||||||
|
private var playtime: Pair<Statistic, Int>? = null
|
||||||
|
override fun enable() {
|
||||||
|
registerListener(this)
|
||||||
|
registerCommand(MemberCommand())
|
||||||
|
playtime = try {
|
||||||
|
Pair(Statistic.valueOf("PLAY_ONE_MINUTE"), 60) //1.14
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
Pair(Statistic.valueOf("PLAY_ONE_TICK"), 20 * 3600) //1.12
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private AbstractMap.SimpleEntry<Statistic, Integer> playtime;
|
override fun disable() {}
|
||||||
|
|
||||||
@Override
|
@EventHandler
|
||||||
protected void enable() {
|
fun onPlayerJoin(event: PlayerJoinEvent) {
|
||||||
registerListener(this);
|
if (checkNotMember(event.player) && (checkRegTime(event.player) || checkPlayTime(event.player))) {
|
||||||
registerCommand(new MemberCommand());
|
addPlayerAsMember(event.player)
|
||||||
try {
|
}
|
||||||
playtime = new AbstractMap.SimpleEntry<>(Statistic.valueOf("PLAY_ONE_MINUTE"), 60); //1.14
|
}
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
playtime = new AbstractMap.SimpleEntry<>(Statistic.valueOf("PLAY_ONE_TICK"), 20 * 3600); //1.12
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
fun addPlayerAsMember(player: Player): Boolean? {
|
||||||
protected void disable() {
|
return try {
|
||||||
}
|
if (MainPlugin.permission.playerAddGroup(null, player, memberGroup.get())) {
|
||||||
|
player.sendMessage("\${ChatColor.AQUA}You are a member now!")
|
||||||
|
log("Added " + player.name + " as a member.")
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
logWarn("Failed to assign the member role! Please make sure the member group exists or disable the component if it's unused.")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} catch (e: UnsupportedOperationException) {
|
||||||
|
logWarn("Failed to assign the member role! Groups are not supported by the permissions implementation.")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler
|
fun checkNotMember(player: Player?): Boolean {
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
return !MainPlugin.permission.playerInGroup(player, memberGroup.get())
|
||||||
if (checkNotMember(event.getPlayer()) && (checkRegTime(event.getPlayer()) || checkPlayTime(event.getPlayer()))) {
|
}
|
||||||
addPlayerAsMember(event.getPlayer());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean addPlayerAsMember(Player player) {
|
fun checkRegTime(player: Player): Boolean {
|
||||||
try {
|
return getRegTime(player) == -1L
|
||||||
if (permission.playerAddGroup(null, player, memberGroup.get())) {
|
}
|
||||||
player.sendMessage("${ChatColor.AQUA}You are a member now!");
|
|
||||||
log("Added " + player.getName() + " as a member.");
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
logWarn("Failed to assign the member role! Please make sure the member group exists or disable the component if it's unused.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} catch (UnsupportedOperationException e) {
|
|
||||||
logWarn("Failed to assign the member role! Groups are not supported by the permissions implementation.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean checkNotMember(Player player) {
|
fun checkPlayTime(player: Player): Boolean {
|
||||||
return permission != null && !permission.playerInGroup(player, memberGroup.get());
|
return getPlayTime(player) > playtime!!.second * playedHours.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkRegTime(Player player) {
|
/**
|
||||||
return getRegTime(player) == -1;
|
* Returns milliseconds
|
||||||
}
|
*/
|
||||||
|
fun getRegTime(player: Player): Long {
|
||||||
|
val date = Date(player.firstPlayed).toInstant().plus(registeredForDays.get().toLong(), ChronoUnit.DAYS)
|
||||||
|
return if (date.isAfter(Instant.now())) date.toEpochMilli() - Instant.now().toEpochMilli() else -1
|
||||||
|
}
|
||||||
|
|
||||||
public boolean checkPlayTime(Player player) {
|
fun getPlayTimeTotal(player: Player): Int {
|
||||||
return getPlayTime(player) > playtime.getValue() * playedHours.get();
|
return player.getStatistic(playtime!!.first)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns milliseconds
|
|
||||||
*/
|
|
||||||
public long getRegTime(Player player) {
|
|
||||||
Instant date = new Date(player.getFirstPlayed()).toInstant().plus(registeredForDays.get(), ChronoUnit.DAYS);
|
|
||||||
if (date.isAfter(Instant.now()))
|
|
||||||
return date.toEpochMilli() - Instant.now().toEpochMilli();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPlayTimeTotal(Player player) {
|
|
||||||
return player.getStatistic(playtime.getKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns hours
|
|
||||||
*/
|
|
||||||
public double getPlayTime(Player player) {
|
|
||||||
double pt = playedHours.get() - (double) getPlayTimeTotal(player) / playtime.getValue();
|
|
||||||
if (pt < 0) return -1;
|
|
||||||
return pt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns hours
|
||||||
|
*/
|
||||||
|
fun getPlayTime(player: Player): Double {
|
||||||
|
val pt = playedHours.get() - getPlayTimeTotal(player).toDouble() / playtime!!.second
|
||||||
|
return if (pt < 0) (-1).toDouble() else pt
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ class RestartComponent : Component<MainPlugin>(), Listener {
|
||||||
/**
|
/**
|
||||||
* Specifies the hour of day when the server should be restarted. Set to -1 to disable.
|
* Specifies the hour of day when the server should be restarted. Set to -1 to disable.
|
||||||
*/
|
*/
|
||||||
private val restartAt = config.getData("restartAt", 12)
|
private val restartAt get() = config.getData("restartAt", 12)
|
||||||
private var lasttime: Long = 0
|
private var lasttime: Long = 0
|
||||||
|
|
||||||
var isPlsrestart = false
|
var isPlsrestart = false
|
||||||
|
|
|
@ -1,133 +1,110 @@
|
||||||
package buttondevteam.core.component.spawn;
|
package buttondevteam.core.component.spawn
|
||||||
|
|
||||||
import buttondevteam.core.MainPlugin;
|
import buttondevteam.core.MainPlugin
|
||||||
import buttondevteam.lib.architecture.Component;
|
import buttondevteam.lib.architecture.Component
|
||||||
import buttondevteam.lib.architecture.ComponentMetadata;
|
import buttondevteam.lib.architecture.ComponentMetadata
|
||||||
import buttondevteam.lib.architecture.ConfigData;
|
import buttondevteam.lib.chat.Command2.Subcommand
|
||||||
import buttondevteam.lib.chat.Command2;
|
import buttondevteam.lib.chat.CommandClass
|
||||||
import buttondevteam.lib.chat.CommandClass;
|
import buttondevteam.lib.chat.ICommand2MC
|
||||||
import buttondevteam.lib.chat.ICommand2MC;
|
import com.earth2me.essentials.Trade
|
||||||
import com.earth2me.essentials.Trade;
|
import com.google.common.io.ByteStreams
|
||||||
import com.google.common.io.ByteArrayDataInput;
|
import com.onarandombox.MultiverseCore.MultiverseCore
|
||||||
import com.google.common.io.ByteArrayDataOutput;
|
import org.bukkit.Bukkit
|
||||||
import com.google.common.io.ByteStreams;
|
import org.bukkit.Location
|
||||||
import com.onarandombox.MultiverseCore.MultiverseCore;
|
import org.bukkit.entity.Player
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.event.player.PlayerTeleportEvent
|
||||||
import org.bukkit.Location;
|
import org.bukkit.plugin.messaging.PluginMessageListener
|
||||||
import org.bukkit.entity.Player;
|
import java.io.*
|
||||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
import java.math.BigDecimal
|
||||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a /spawn command that works with BungeeCord. Make sure to set up on each server.
|
* Provides a /spawn command that works with BungeeCord. Make sure to set up on each server.
|
||||||
|
* Requires Multiverse-Core.
|
||||||
*/
|
*/
|
||||||
@ComponentMetadata(enabledByDefault = false)
|
@ComponentMetadata(enabledByDefault = false)
|
||||||
public class SpawnComponent extends Component<MainPlugin> implements PluginMessageListener {
|
class SpawnComponent : Component<MainPlugin>(), PluginMessageListener {
|
||||||
@Override
|
override fun enable() {
|
||||||
protected void enable() {
|
registerCommand(SpawnCommand())
|
||||||
registerCommand(new SpawnCommand());
|
if (targetServer.get().isEmpty()) {
|
||||||
if (targetServer.get().length() == 0) {
|
spawnloc = MultiverseCore.getPlugin(MultiverseCore::class.java).mvWorldManager.firstSpawnWorld.spawnLocation
|
||||||
spawnloc = MultiverseCore.getPlugin(MultiverseCore.class).getMVWorldManager().getFirstSpawnWorld()
|
}
|
||||||
.getSpawnLocation();
|
Bukkit.getServer().messenger.registerOutgoingPluginChannel(plugin, "BungeeCord")
|
||||||
}
|
Bukkit.getServer().messenger.registerIncomingPluginChannel(plugin, "BungeeCord", this)
|
||||||
|
}
|
||||||
|
|
||||||
Bukkit.getServer().getMessenger().registerOutgoingPluginChannel(getPlugin(), "BungeeCord");
|
override fun disable() {
|
||||||
Bukkit.getServer().getMessenger().registerIncomingPluginChannel(getPlugin(), "BungeeCord", this);
|
Bukkit.getServer().messenger.unregisterIncomingPluginChannel(plugin, "BungeeCord")
|
||||||
}
|
Bukkit.getServer().messenger.unregisterOutgoingPluginChannel(plugin, "BungeeCord")
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
override fun onPluginMessageReceived(channel: String, player: Player, message: ByteArray) {
|
||||||
protected void disable() {
|
if (channel != "BungeeCord") {
|
||||||
Bukkit.getServer().getMessenger().unregisterIncomingPluginChannel(getPlugin(), "BungeeCord");
|
return
|
||||||
Bukkit.getServer().getMessenger().unregisterOutgoingPluginChannel(getPlugin(), "BungeeCord");
|
}
|
||||||
}
|
if (targetServer.get().isNotEmpty()) return
|
||||||
|
val `in` = ByteStreams.newDataInput(message)
|
||||||
|
val subchannel = `in`.readUTF()
|
||||||
|
if ("ChromaCore-Spawn" == subchannel) {
|
||||||
|
// Use the code sample in the 'Response' sections below to read
|
||||||
|
// the data.
|
||||||
|
val len = `in`.readShort()
|
||||||
|
val msgbytes = ByteArray(len.toInt())
|
||||||
|
`in`.readFully(msgbytes)
|
||||||
|
try {
|
||||||
|
val msgin = DataInputStream(ByteArrayInputStream(msgbytes))
|
||||||
|
val somedata = msgin.readUTF() // Read the data in the same way you wrote it
|
||||||
|
if ("SendToSpawn" != somedata) {
|
||||||
|
println("somedata: $somedata")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
player.teleport(spawnloc!!)
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
} else println("Subchannel: $subchannel")
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
|
* The BungeeCord server that has the spawn. Set to empty if this server is the target.
|
||||||
if (!channel.equals("BungeeCord")) {
|
*/
|
||||||
return;
|
private val targetServer get() = config.getData("targetServer", "")
|
||||||
}
|
private var spawnloc: Location? = null
|
||||||
if (targetServer.get().length() != 0)
|
|
||||||
return;
|
|
||||||
ByteArrayDataInput in = ByteStreams.newDataInput(message);
|
|
||||||
String subchannel = in.readUTF();
|
|
||||||
if ("ChromaCore-Spawn".equals(subchannel)) {
|
|
||||||
// Use the code sample in the 'Response' sections below to read
|
|
||||||
// the data.
|
|
||||||
short len = in.readShort();
|
|
||||||
byte[] msgbytes = new byte[len];
|
|
||||||
in.readFully(msgbytes);
|
|
||||||
|
|
||||||
try {
|
@CommandClass(helpText = ["Spawn", "Teleport to spawn."])
|
||||||
DataInputStream msgin = new DataInputStream(new ByteArrayInputStream(msgbytes));
|
inner class SpawnCommand : ICommand2MC() {
|
||||||
String somedata = msgin.readUTF(); // Read the data in the same way you wrote it
|
@Subcommand
|
||||||
if (!"SendToSpawn".equals(somedata)) {
|
fun def(player: Player) {
|
||||||
System.out.println("somedata: " + somedata);
|
if (targetServer.get().isEmpty()) {
|
||||||
return;
|
player.sendMessage("\${ChatColor.AQUA}Teleporting to spawn...")
|
||||||
}
|
try {
|
||||||
player.teleport(spawnloc);
|
if (MainPlugin.ess != null) MainPlugin.ess!!.getUser(player).teleport
|
||||||
} catch (IOException e) {
|
.teleport(spawnloc, Trade(BigDecimal.ZERO, MainPlugin.ess), PlayerTeleportEvent.TeleportCause.COMMAND) else player.teleport(spawnloc!!)
|
||||||
e.printStackTrace();
|
} catch (e: Exception) {
|
||||||
}
|
player.sendMessage("\${ChatColor.RED}Failed to teleport: $e")
|
||||||
} else
|
}
|
||||||
System.out.println("Subchannel: " + subchannel);
|
return
|
||||||
}
|
}
|
||||||
|
val out = ByteStreams.newDataOutput()
|
||||||
/**
|
out.writeUTF("Connect")
|
||||||
* The BungeeCord server that has the spawn. Set to empty if this server is the target.
|
out.writeUTF(targetServer.get())
|
||||||
*/
|
player.sendPluginMessage(plugin, "BungeeCord", out.toByteArray())
|
||||||
private final ConfigData<String> targetServer = getConfig().getData("targetServer", "");
|
Bukkit.getScheduler().runTask(plugin, Runnable {
|
||||||
|
//Delay it a bit
|
||||||
private Location spawnloc;
|
val outt = ByteStreams.newDataOutput()
|
||||||
|
outt.writeUTF("ForwardToPlayer") // So BungeeCord knows to forward it
|
||||||
@CommandClass(helpText = {
|
outt.writeUTF(player.name)
|
||||||
"Spawn",
|
outt.writeUTF("ChromaCore-Spawn") // The channel name to check if this your data
|
||||||
"Teleport to spawn."
|
val msgbytes = ByteArrayOutputStream()
|
||||||
})
|
val msgout = DataOutputStream(msgbytes)
|
||||||
public class SpawnCommand extends ICommand2MC {
|
try {
|
||||||
@SuppressWarnings("UnstableApiUsage")
|
msgout.writeUTF("SendToSpawn") // You can do anything you want with msgout
|
||||||
@Command2.Subcommand
|
} catch (exception: IOException) {
|
||||||
public void def(Player player) {
|
exception.printStackTrace()
|
||||||
if (targetServer.get().length() == 0) {
|
}
|
||||||
player.sendMessage("${ChatColor.AQUA}Teleporting to spawn...");
|
outt.writeShort(msgbytes.toByteArray().size)
|
||||||
try {
|
outt.write(msgbytes.toByteArray())
|
||||||
if (MainPlugin.ess != null)
|
player.sendPluginMessage(plugin, "BungeeCord", outt.toByteArray())
|
||||||
MainPlugin.ess.getUser(player).getTeleport()
|
})
|
||||||
.teleport(spawnloc, new Trade(BigDecimal.ZERO, MainPlugin.ess), PlayerTeleportEvent.TeleportCause.COMMAND);
|
}
|
||||||
else
|
}
|
||||||
player.teleport(spawnloc);
|
|
||||||
} catch (Exception e) {
|
|
||||||
player.sendMessage("${ChatColor.RED}Failed to teleport: " + e);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
|
||||||
out.writeUTF("Connect");
|
|
||||||
out.writeUTF(targetServer.get());
|
|
||||||
|
|
||||||
player.sendPluginMessage(getPlugin(), "BungeeCord", out.toByteArray());
|
|
||||||
|
|
||||||
Bukkit.getScheduler().runTask(getPlugin(), () -> { //Delay it a bit
|
|
||||||
ByteArrayDataOutput outt = ByteStreams.newDataOutput();
|
|
||||||
outt.writeUTF("ForwardToPlayer"); // So BungeeCord knows to forward it
|
|
||||||
outt.writeUTF(player.getName());
|
|
||||||
outt.writeUTF("ChromaCore-Spawn"); // The channel name to check if this your data
|
|
||||||
|
|
||||||
ByteArrayOutputStream msgbytes = new ByteArrayOutputStream();
|
|
||||||
DataOutputStream msgout = new DataOutputStream(msgbytes);
|
|
||||||
try {
|
|
||||||
msgout.writeUTF("SendToSpawn"); // You can do anything you want with msgout
|
|
||||||
} catch (IOException exception) {
|
|
||||||
exception.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
outt.writeShort(msgbytes.toByteArray().length);
|
|
||||||
outt.write(msgbytes.toByteArray());
|
|
||||||
|
|
||||||
player.sendPluginMessage(getPlugin(), "BungeeCord", outt.toByteArray());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ abstract class TBMCChatEventBase(
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: Errors are sent to the sender automatically<br></br>
|
* Note: Errors are sent to the sender automatically
|
||||||
*
|
*
|
||||||
* Null means don't send
|
* Null means don't send
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -83,7 +83,7 @@ abstract class ButtonPlugin : JavaPlugin() {
|
||||||
fun tryReloadConfig(): Boolean {
|
fun tryReloadConfig(): Boolean {
|
||||||
if (!justReload()) return false
|
if (!justReload()) return false
|
||||||
reloadIConfig()
|
reloadIConfig()
|
||||||
componentStack.forEach(Consumer { c -> c.updateComponentData() })
|
componentStack.forEach(Consumer { c -> c.updateConfig() })
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,18 +18,17 @@ import java.util.stream.Collectors
|
||||||
@HasConfig(global = false) //Used for obtaining javadoc
|
@HasConfig(global = false) //Used for obtaining javadoc
|
||||||
abstract class Component<TP : JavaPlugin> {
|
abstract class Component<TP : JavaPlugin> {
|
||||||
var isEnabled = false
|
var isEnabled = false
|
||||||
internal var componentData: ComponentData<TP>? = null
|
|
||||||
|
|
||||||
val config get() = componentData!!.config
|
lateinit var config: IHaveConfig
|
||||||
val plugin get() = componentData!!.plugin
|
private set
|
||||||
|
lateinit var plugin: TP
|
||||||
|
private set
|
||||||
|
|
||||||
private val data //TODO
|
private val data //TODO
|
||||||
: IHaveConfig? = null
|
: IHaveConfig? = null
|
||||||
|
|
||||||
@JvmField
|
val shouldBeEnabled: ConfigData<Boolean>
|
||||||
val shouldBeEnabled: ConfigData<Boolean> = config.getData("enabled",
|
get() = config.getData("enabled", javaClass.getAnnotation(ComponentMetadata::class.java)?.enabledByDefault ?: true)
|
||||||
Optional.ofNullable(javaClass.getAnnotation(ComponentMetadata::class.java)).map { it.enabledByDefault }
|
|
||||||
.orElse(true))
|
|
||||||
|
|
||||||
fun log(message: String) {
|
fun log(message: String) {
|
||||||
plugin.logger.info("[$className] $message")
|
plugin.logger.info("[$className] $message")
|
||||||
|
@ -58,7 +57,8 @@ abstract class Component<TP : JavaPlugin> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables the module, when called by the JavaPlugin class. Call
|
* Enables the module, when called by the JavaPlugin class. Call
|
||||||
* registerCommand() and registerListener() within this method.<br></br>
|
* registerCommand() and registerListener() within this method.
|
||||||
|
*
|
||||||
* To access the plugin, use [.getPlugin].
|
* To access the plugin, use [.getPlugin].
|
||||||
*/
|
*/
|
||||||
protected abstract fun enable()
|
protected abstract fun enable()
|
||||||
|
@ -121,8 +121,8 @@ abstract class Component<TP : JavaPlugin> {
|
||||||
|
|
||||||
private val className: String get() = javaClass.simpleName
|
private val className: String get() = javaClass.simpleName
|
||||||
|
|
||||||
internal fun updateComponentData(plugin: TP = this.plugin) {
|
internal fun updateConfig() {
|
||||||
componentData = ComponentData(plugin, { plugin.saveConfig() }, this.getConfigSection(plugin))
|
this.config = IHaveConfig(plugin::saveConfig, getConfigSection(plugin))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getConfigSection(plugin: JavaPlugin): ConfigurationSection {
|
private fun getConfigSection(plugin: JavaPlugin): ConfigurationSection {
|
||||||
|
@ -138,7 +138,7 @@ abstract class Component<TP : JavaPlugin> {
|
||||||
private val _components = HashMap<Class<out Component<*>>, Component<out JavaPlugin>>()
|
private val _components = HashMap<Class<out Component<*>>, Component<out JavaPlugin>>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the currently registered components<br></br>
|
* Returns the currently registered components
|
||||||
*
|
*
|
||||||
* @return The currently registered components
|
* @return The currently registered components
|
||||||
*/
|
*/
|
||||||
|
@ -149,9 +149,12 @@ abstract class Component<TP : JavaPlugin> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a component checking it's dependencies and calling [.register].<br></br>
|
* Registers a component checking it's dependencies and calling [.register].
|
||||||
* Make sure to register the dependencies first.<br></br>
|
*
|
||||||
* The component will be enabled automatically, regardless of when it was registered.<br></br>
|
* Make sure to register the dependencies first.
|
||||||
|
*
|
||||||
|
* The component will be enabled automatically, regardless of when it was registered.
|
||||||
|
*
|
||||||
* **If not using [ButtonPlugin], call [ComponentManager.unregComponents] on plugin disable.**
|
* **If not using [ButtonPlugin], call [ComponentManager.unregComponents] on plugin disable.**
|
||||||
*
|
*
|
||||||
* @param component The component to register
|
* @param component The component to register
|
||||||
|
@ -163,8 +166,10 @@ abstract class Component<TP : JavaPlugin> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregisters a component by calling [.unregister].<br></br>
|
* Unregisters a component by calling [.unregister].
|
||||||
* Make sure to unregister the dependencies last.<br></br>
|
*
|
||||||
|
* Make sure to unregister the dependencies last.
|
||||||
|
*
|
||||||
* **Components will be unregistered in opposite order of registering by default by [ButtonPlugin] or [ComponentManager.unregComponents].**
|
* **Components will be unregistered in opposite order of registering by default by [ButtonPlugin] or [ComponentManager.unregComponents].**
|
||||||
*
|
*
|
||||||
* @param component The component to unregister
|
* @param component The component to unregister
|
||||||
|
@ -186,7 +191,7 @@ abstract class Component<TP : JavaPlugin> {
|
||||||
val dependencies = metaAnn.depends
|
val dependencies = metaAnn.depends
|
||||||
for (dep in dependencies) { //TODO: Support dependencies at enable/disable as well
|
for (dep in dependencies) { //TODO: Support dependencies at enable/disable as well
|
||||||
if (!components.containsKey(dep.java)) {
|
if (!components.containsKey(dep.java)) {
|
||||||
plugin.logger.warning("Failed to " + (if (register) "" else "un") + "register component " + component.className + " as a required dependency is missing/disabled: " + dep.simpleName)
|
plugin.logger.warning("Failed to ${if (register) "" else "un"}register component ${component.className} as a required dependency is missing/disabled: ${dep.simpleName}")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,8 +206,8 @@ abstract class Component<TP : JavaPlugin> {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
component.register(plugin)
|
component.register(plugin)
|
||||||
// The plugin is saved with this call, so it must be specified
|
component.plugin = plugin
|
||||||
component.updateComponentData(plugin)
|
component.updateConfig()
|
||||||
_components[component.javaClass] = component
|
_components[component.javaClass] = component
|
||||||
if (plugin is ButtonPlugin) plugin.componentStack.push(component)
|
if (plugin is ButtonPlugin) plugin.componentStack.push(component)
|
||||||
if (ComponentManager.areComponentsEnabled() && component.shouldBeEnabled.get()) {
|
if (ComponentManager.areComponentsEnabled() && component.shouldBeEnabled.get()) {
|
||||||
|
@ -227,18 +232,10 @@ abstract class Component<TP : JavaPlugin> {
|
||||||
try {
|
try {
|
||||||
setComponentEnabled(component, false)
|
setComponentEnabled(component, false)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
TBMCCoreAPI.SendException(
|
TBMCCoreAPI.SendException("Failed to disable component ${component.className}!", e, component)
|
||||||
"Failed to disable component " + component.className + "!",
|
|
||||||
e,
|
|
||||||
component
|
|
||||||
)
|
|
||||||
return false //If failed to disable, won't unregister either
|
return false //If failed to disable, won't unregister either
|
||||||
} catch (e: NoClassDefFoundError) {
|
} catch (e: NoClassDefFoundError) {
|
||||||
TBMCCoreAPI.SendException(
|
TBMCCoreAPI.SendException("Failed to disable component ${component.className}!", e, component)
|
||||||
"Failed to disable component " + component.className + "!",
|
|
||||||
e,
|
|
||||||
component
|
|
||||||
)
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,7 +244,7 @@ abstract class Component<TP : JavaPlugin> {
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
TBMCCoreAPI.SendException("Failed to " + (if (register) "" else "un") + "register component " + component.className + "!", e, plugin)
|
TBMCCoreAPI.SendException("Failed to ${if (register) "" else "un"}register component ${component.className}!", e, plugin)
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
package buttondevteam.lib.architecture
|
|
||||||
|
|
||||||
import org.bukkit.configuration.ConfigurationSection
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper for plugin components. This is used internally.
|
|
||||||
*/
|
|
||||||
class ComponentData<TP : JavaPlugin>(
|
|
||||||
val plugin: TP,
|
|
||||||
saveAction: Runnable,
|
|
||||||
config: ConfigurationSection
|
|
||||||
) {
|
|
||||||
val config = IHaveConfig(saveAction, config) // TODO: Use lateinit instead of this class
|
|
||||||
}
|
|
|
@ -9,8 +9,11 @@ import org.bukkit.scheduler.BukkitTask
|
||||||
import java.util.function.Function
|
import java.util.function.Function
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use the getter/setter constructor if [T] isn't a primitive type or String.<br></br>
|
* Use the getter/setter constructor if [T] isn't a primitive type or String.
|
||||||
* Use [Component.config] or [ButtonPlugin.iConfig] then [IHaveConfig.getData] to get an instance.
|
*
|
||||||
|
* Use [Component.config] or [ButtonPlugin.iConfig] then [IHaveConfig.getData] to get an instance.
|
||||||
|
*
|
||||||
|
* **Note:** The instance can become outdated if the config is reloaded.
|
||||||
* @param config May be null for testing
|
* @param config May be null for testing
|
||||||
* @param getter The parameter is of a primitive type as returned by [Configuration.get]
|
* @param getter The parameter is of a primitive type as returned by [Configuration.get]
|
||||||
* @param setter The result should be a primitive type or string that can be retrieved correctly later
|
* @param setter The result should be a primitive type or string that can be retrieved correctly later
|
||||||
|
|
|
@ -26,7 +26,8 @@ class ChatMessage internal constructor(
|
||||||
*/
|
*/
|
||||||
val permCheck: CommandSender,
|
val permCheck: CommandSender,
|
||||||
/**
|
/**
|
||||||
* The origin of the message, "Minecraft" or "Discord" for example. May be displayed to the user.<br></br>
|
* The origin of the message, "Minecraft" or "Discord" for example. May be displayed to the user.
|
||||||
|
*
|
||||||
* **This is the user class capitalized folder name by default.**
|
* **This is the user class capitalized folder name by default.**
|
||||||
*/
|
*/
|
||||||
val origin: String
|
val origin: String
|
||||||
|
|
|
@ -39,7 +39,8 @@ abstract class ICommand2<TP : Command2Sender>(val manager: Command2<*, TP>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return null to not add any help text, return an empty array to only print subcommands.<br></br>
|
* Return null to not add any help text, return an empty array to only print subcommands.
|
||||||
|
*
|
||||||
* By default, returns null if the Subcommand annotation is not present and returns an empty array if no help text can be found.
|
* By default, returns null if the Subcommand annotation is not present and returns an empty array if no help text can be found.
|
||||||
*
|
*
|
||||||
* @param method The method of the subcommand
|
* @param method The method of the subcommand
|
||||||
|
@ -51,10 +52,13 @@ abstract class ICommand2<TP : Command2Sender>(val manager: Command2<*, TP>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The command's path, or name if top-level command.<br></br>
|
* The command's path, or name if top-level command.
|
||||||
* For example:<br></br>
|
*
|
||||||
* "u admin updateplugin" or "u" for the top level one<br></br>
|
* For example:
|
||||||
* <u>The path must be lowercase!</u><br></br>
|
*
|
||||||
|
* "u admin updateplugin" or "u" for the top level one
|
||||||
|
*
|
||||||
|
* __The path must be lowercase!__
|
||||||
*
|
*
|
||||||
* @return The command path, *which is the command class name by default* (removing any "command" from it) - Change via the [CommandClass] annotation
|
* @return The command path, *which is the command class name by default* (removing any "command" from it) - Change via the [CommandClass] annotation
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -17,7 +17,8 @@ import java.util.function.Supplier
|
||||||
|
|
||||||
object TBMCChatAPI {
|
object TBMCChatAPI {
|
||||||
/**
|
/**
|
||||||
* Sends a chat message to Minecraft. Make sure that the channel is registered with [.RegisterChatChannel].<br></br>
|
* Sends a chat message to Minecraft. Make sure that the channel is registered with [.RegisterChatChannel].
|
||||||
|
*
|
||||||
* This will also send the error message to the sender, if they can't send the message.
|
* This will also send the error message to the sender, if they can't send the message.
|
||||||
*
|
*
|
||||||
* @param cm The message to send
|
* @param cm The message to send
|
||||||
|
|
|
@ -21,12 +21,10 @@ abstract class ChromaGamerBase {
|
||||||
protected set
|
protected set
|
||||||
|
|
||||||
protected lateinit var commonUserData: CommonUserData<out ChromaGamerBase>
|
protected lateinit var commonUserData: CommonUserData<out ChromaGamerBase>
|
||||||
protected open fun init() {
|
protected open fun initConfig() {
|
||||||
config = IHaveConfig({ save() }, commonUserData.playerData)
|
config = IHaveConfig({ save() }, commonUserData.playerData)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun updateUserConfig() {} // TODO: Use this instead of reset()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the player. It'll handle all exceptions that may happen. Called automatically.
|
* Saves the player. It'll handle all exceptions that may happen. Called automatically.
|
||||||
*/
|
*/
|
||||||
|
@ -114,7 +112,8 @@ abstract class ChromaGamerBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a player instance of the given type that represents the same player. This will return a new instance unless the player is cached.<br></br>
|
* Returns a player instance of the given type that represents the same player. This will return a new instance unless the player is cached.
|
||||||
|
*
|
||||||
* If the class is a subclass of the current class then the same ID is used, otherwise, a connected ID is used, if found.
|
* If the class is a subclass of the current class then the same ID is used, otherwise, a connected ID is used, if found.
|
||||||
*
|
*
|
||||||
* @param cl The target player class
|
* @param cl The target player class
|
||||||
|
@ -130,7 +129,8 @@ abstract class ChromaGamerBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the filename for this player data. For example, for Minecraft-related data, MC UUIDs, for Discord data, Discord IDs, etc.<br></br>
|
* Returns the filename for this player data. For example, for Minecraft-related data, MC UUIDs, for Discord data, Discord IDs, etc.
|
||||||
|
*
|
||||||
* **Does not include .yml**
|
* **Does not include .yml**
|
||||||
*/
|
*/
|
||||||
val fileName: String by lazy {
|
val fileName: String by lazy {
|
||||||
|
@ -159,12 +159,12 @@ abstract class ChromaGamerBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
@JvmField
|
val channel: ConfigData<Channel>
|
||||||
val channel: ConfigData<Channel> = config.getData("channel", Channel.globalChat,
|
get() = config.getData("channel", Channel.globalChat,
|
||||||
{ id ->
|
{ id ->
|
||||||
getChannels().filter { ch: Channel -> ch.identifier.equals(id as String, ignoreCase = true) }
|
getChannels().filter { it.identifier.equals(id as String, ignoreCase = true) }
|
||||||
.findAny().orElseThrow { RuntimeException("Channel $id not found!") }
|
.findAny().orElseThrow { RuntimeException("Channel $id not found!") }
|
||||||
}, { ch -> ch.identifier })
|
}, { ch -> ch.identifier })
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TBMC_PLAYERS_DIR = "TBMC/players/"
|
private const val TBMC_PLAYERS_DIR = "TBMC/players/"
|
||||||
|
@ -258,10 +258,8 @@ abstract class ChromaGamerBase {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun <T : S, S : ChromaGamerBase> getUser(fname: String, cl: Class<T>): T {
|
fun <T : S, S : ChromaGamerBase> getUser(fname: String, cl: Class<T>): T {
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
val staticUserData: StaticUserData<S> = getStaticData(cl)
|
val staticUserData: StaticUserData<S> = getStaticData(cl)
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
val commonUserData: CommonUserData<S> = staticUserData.userDataMap[fname]
|
val commonUserData: CommonUserData<S> = staticUserData.userDataMap[fname]
|
||||||
?: run {
|
?: run {
|
||||||
val folder = staticUserData.folder
|
val folder = staticUserData.folder
|
||||||
|
@ -293,7 +291,7 @@ abstract class ChromaGamerBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
obj.commonUserData = commonUserData
|
obj.commonUserData = commonUserData
|
||||||
obj.init()
|
obj.initConfig()
|
||||||
obj.scheduleUncache()
|
obj.scheduleUncache()
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,8 @@ abstract class TBMCPlayerBase : ChromaGamerBase() {
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val playerName = super.config.getData("PlayerName", "")
|
val playerName = super.config.getData("PlayerName", "")
|
||||||
public override fun init() {
|
public override fun initConfig() {
|
||||||
super.init()
|
super.initConfig()
|
||||||
val pluginName = if (javaClass.isAnnotationPresent(PlayerClass::class.java))
|
val pluginName = if (javaClass.isAnnotationPresent(PlayerClass::class.java))
|
||||||
javaClass.getAnnotation(PlayerClass::class.java).pluginname
|
javaClass.getAnnotation(PlayerClass::class.java).pluginname
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue