" //
+ };
+ }
+}
diff --git a/ButtonCore/src/main/java/buttondevteam/core/ScheduledRestartCommand.java b/ButtonCore/src/main/java/buttondevteam/core/ScheduledRestartCommand.java
index d7ade35..6044c40 100755
--- a/ButtonCore/src/main/java/buttondevteam/core/ScheduledRestartCommand.java
+++ b/ButtonCore/src/main/java/buttondevteam/core/ScheduledRestartCommand.java
@@ -32,7 +32,7 @@ public class ScheduledRestartCommand extends TBMCCommandBase {
return false;
}
final int restarttime = restartcounter = ticks;
- restartbar = Bukkit.createBossBar("Server restart in " + ticks / 20f, BarColor.RED, BarStyle.SOLID,
+ restartbar = Bukkit.createBossBar("Server restart in " + ticks / 20f + "s", BarColor.RED, BarStyle.SOLID,
BarFlag.DARKEN_SKY);
restartbar.setProgress(1);
Bukkit.getOnlinePlayers().forEach(p -> restartbar.addPlayer(p));
diff --git a/ButtonCore/src/main/java/buttondevteam/lib/TBMCChannelConnectFakeEvent.java b/ButtonCore/src/main/java/buttondevteam/lib/TBMCChannelConnectFakeEvent.java
deleted file mode 100644
index afc12cd..0000000
--- a/ButtonCore/src/main/java/buttondevteam/lib/TBMCChannelConnectFakeEvent.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package buttondevteam.lib;
-
-import buttondevteam.lib.chat.Channel;
-import lombok.Getter;
-import org.bukkit.command.CommandSender;
-import org.bukkit.event.Cancellable;
-import org.bukkit.event.HandlerList;
-
-import javax.annotation.Nullable;
-
-/**
- * The purpose of this event is to determine which group the given channel belongs to
- * or to validate that they have access to the given group chat.
- * It's not meant to be called from any plugin - it should be only created to use the helper methods
- */
-@Getter
-public class TBMCChannelConnectFakeEvent extends TBMCChatEventBase implements Cancellable {
- private static final HandlerList handlers = new HandlerList();
-
- @Nullable
- private final CommandSender sender;
-
- /**
- * Using this the group will be determined based on the sender.
- *
- * @param sender The sender to get the group from
- * @param channel The channel to use
- */
- public TBMCChannelConnectFakeEvent(CommandSender sender, Channel channel) {
- super(channel, "Channel connecting message. One of the things users should never see in action.", -1, null);
- this.sender = sender;
- }
-
- /**
- * Using this the given group will be validated and used.
- *
- * @param groupid The group to use, for example the name of a town or nation
- * @param channel The channel to use
- */
- public TBMCChannelConnectFakeEvent(String groupid, Channel channel) {
- super(channel, "Channel connecting message. One of the things users should never see in action.", -1, groupid);
- this.sender = null;
- }
-
- @Override
- public HandlerList getHandlers() {
- return handlers;
- }
-
- public static HandlerList getHandlerList() {
- return handlers;
- }
-}
diff --git a/ButtonCore/src/main/java/buttondevteam/lib/TBMCChatEventBase.java b/ButtonCore/src/main/java/buttondevteam/lib/TBMCChatEventBase.java
index 77dd9fd..14c7de9 100755
--- a/ButtonCore/src/main/java/buttondevteam/lib/TBMCChatEventBase.java
+++ b/ButtonCore/src/main/java/buttondevteam/lib/TBMCChatEventBase.java
@@ -1,7 +1,6 @@
package buttondevteam.lib;
import buttondevteam.lib.chat.Channel;
-import buttondevteam.lib.chat.Channel.RecipientTestResult;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
@@ -31,20 +30,14 @@ public abstract class TBMCChatEventBase extends Event implements Cancellable {
* Note: Errors are sent to the sender automatically
*/
public boolean shouldSendTo(CommandSender sender) {
- if (channel.filteranderrormsg == null)
- return true;
- RecipientTestResult result = channel.filteranderrormsg.apply(sender);
- return result.errormessage == null && score == result.score;
+ return channel.shouldSendTo(sender, score);
}
/**
* Note: Errors are sent to the sender automatically
*/
public int getMCScore(CommandSender sender) {
- if (channel.filteranderrormsg == null)
- return 0;
- RecipientTestResult result = channel.filteranderrormsg.apply(sender);
- return result.errormessage == null ? result.score : -1;
+ return channel.getMCScore(sender);
}
/**
@@ -54,9 +47,6 @@ public abstract class TBMCChatEventBase extends Event implements Cancellable {
*/
@Nullable
public String getGroupID(CommandSender sender) {
- if (channel.filteranderrormsg == null)
- return "everyone";
- RecipientTestResult result = channel.filteranderrormsg.apply(sender);
- return result.errormessage == null ? result.groupID : null;
+ return channel.getGroupID(sender); //TODO: Performance-wise it'd be much better to use serialization for player data - it's only converted once
}
}
diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/Channel.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/Channel.java
index a9d4d20..c18c557 100755
--- a/ButtonCore/src/main/java/buttondevteam/lib/chat/Channel.java
+++ b/ButtonCore/src/main/java/buttondevteam/lib/chat/Channel.java
@@ -14,6 +14,18 @@ import java.util.function.Function;
import java.util.function.Predicate;
public class Channel {
+ /**
+ * Specifies a score that means it's OK to send - but it does not define any groups, only send or not send. See {@link #GROUP_EVERYONE}
+ */
+ public static final int SCORE_SEND_OK = 0;
+ /**
+ * Specifies a score that means the user doesn't have permission to see or send the message. Any negative value has the same effect.
+ */
+ public static final int SCORE_SEND_NOPE = -1;
+ /**
+ * Send the message to everyone who has access to the channel - this does not necessarily mean all players
+ */
+ public static final String GROUP_EVERYONE = "everyone";
public final String DisplayName;
public final Color color;
public final String ID;
@@ -57,6 +69,43 @@ public class Channel {
this.filteranderrormsg = s -> filteranderrormsg.apply((T) this, s);
}
+ public boolean isGlobal() {
+ return filteranderrormsg == null;
+ }
+
+ /**
+ * Note: Errors are sent to the sender automatically
+ *
+ * @param sender The user we're sending to
+ * @param score The (source) score to compare with the user's
+ */
+ public boolean shouldSendTo(CommandSender sender, int score) {
+ return score == getMCScore(sender); //If there's any error, the score won't be equal
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Note: Errors are sent to the sender automatically
+ *
+ * Null means don't send
+ */
+ @Nullable
+ public String getGroupID(CommandSender sender) {
+ if (filteranderrormsg == null)
+ return GROUP_EVERYONE;
+ RecipientTestResult result = filteranderrormsg.apply(sender);
+ return result.errormessage == null ? result.groupID : null;
+ }
+
public static List getChannels() {
return channels;
}
@@ -76,12 +125,12 @@ public class Channel {
public static Function noScoreResult(Predicate filter,
String errormsg) {
- return s -> filter.test(s) ? new RecipientTestResult(0, "everyone") : new RecipientTestResult(errormsg);
+ return s -> filter.test(s) ? new RecipientTestResult(SCORE_SEND_OK, GROUP_EVERYONE) : new RecipientTestResult(errormsg);
}
public static BiFunction noScoreResult(
BiPredicate filter, String errormsg) {
- return (this_, s) -> filter.test(this_, s) ? new RecipientTestResult(0, "everyone") : new RecipientTestResult(errormsg);
+ return (this_, s) -> filter.test(this_, s) ? new RecipientTestResult(SCORE_SEND_OK, GROUP_EVERYONE) : new RecipientTestResult(errormsg);
}
public static Channel GlobalChat;
@@ -95,7 +144,7 @@ public class Channel {
public static class RecipientTestResult {
public String errormessage = null;
- public int score = -1; // Anything below 0 is "never send"
+ public int score = SCORE_SEND_NOPE; // Anything below 0 is "never send"
public String groupID = null;
/**
@@ -110,7 +159,7 @@ public class Channel {
/**
* Creates a result that indicates a success
*
- * @param score The score that identifies the target group. For example, the index of the town or nation to send to.
+ * @param score The score that identifies the target group. Must be non-negative. For example, the index of the town or nation to send to.
* @param groupID The ID of the target group.
*/
public RecipientTestResult(int score, String groupID) {
diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/ChatMessage.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/ChatMessage.java
index 056674a..ff5528b 100644
--- a/ButtonCore/src/main/java/buttondevteam/lib/chat/ChatMessage.java
+++ b/ButtonCore/src/main/java/buttondevteam/lib/chat/ChatMessage.java
@@ -9,10 +9,6 @@ import org.bukkit.command.CommandSender;
@Builder
@Getter
public class ChatMessage {
- /**
- * The MC channel to send the message to.
- */
- private final Channel channel;
/**
* The sender which sends the message.
*/
@@ -44,6 +40,6 @@ public class ChatMessage {
@NonNull
public static ChatMessageBuilder builder(Channel channel, CommandSender sender, ChromaGamerBase user, String message) {
- return builder().channel(channel).sender(sender).user(user).message(message);
+ return builder().sender(sender).user(user).message(message);
}
}
diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java
index 18b0487..995d48e 100755
--- a/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java
+++ b/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java
@@ -214,19 +214,31 @@ public class TBMCChatAPI {
* @return The event cancelled state
*/
public static boolean SendChatMessage(ChatMessage cm) {
- if (!Channel.getChannels().contains(cm.getChannel()))
- throw new RuntimeException("Channel " + cm.getChannel().DisplayName + " not registered!");
+ return SendChatMessage(cm, cm.getUser().channel().get());
+ }
+
+ /**
+ * Sends a chat message to Minecraft. Make sure that the channel is registered with {@link #RegisterChatChannel(Channel)}.
+ * This will also send the error message to the sender, if they can't send the message.
+ *
+ * @param cm The message to send
+ * @param channel The MC channel to send in
+ * @return The event cancelled state
+ */
+ 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();
- RecipientTestResult rtr = getScoreOrSendError(cm.getChannel(), permcheck);
+ RecipientTestResult rtr = getScoreOrSendError(channel, permcheck);
int score = rtr.score;
if (score == -1 || rtr.groupID == null)
return true;
- TBMCChatPreprocessEvent eventPre = new TBMCChatPreprocessEvent(cm.getSender(), cm.getChannel(), cm.getMessage());
+ TBMCChatPreprocessEvent eventPre = new TBMCChatPreprocessEvent(cm.getSender(), channel, cm.getMessage());
Bukkit.getPluginManager().callEvent(eventPre);
if (eventPre.isCancelled())
return true;
TBMCChatEvent event;
- event = new TBMCChatEvent(cm.getSender(), cm.getUser(), cm.getChannel(), eventPre.getMessage(), score, cm.isFromCommand(), rtr.groupID, permcheck != cm.getSender());
+ event = new TBMCChatEvent(cm.getSender(), cm.getUser(), channel, eventPre.getMessage(), score, cm.isFromCommand(), rtr.groupID, permcheck != cm.getSender());
Bukkit.getPluginManager().callEvent(event);
return event.isCancelled();
}
diff --git a/ButtonCore/src/main/java/buttondevteam/lib/player/ChannelPlayerData.java b/ButtonCore/src/main/java/buttondevteam/lib/player/ChannelPlayerData.java
new file mode 100644
index 0000000..583a5c9
--- /dev/null
+++ b/ButtonCore/src/main/java/buttondevteam/lib/player/ChannelPlayerData.java
@@ -0,0 +1,25 @@
+package buttondevteam.lib.player;
+
+import buttondevteam.lib.chat.Channel;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+public class ChannelPlayerData { //I just want this to work
+ private final PlayerData data;
+ private final Channel def;
+
+ public ChannelPlayerData(String name, YamlConfiguration yaml, Channel def) {
+ data = new PlayerData<>(name, yaml, "");
+ this.def = def;
+ }
+
+ public Channel get() {
+ String str = data.get();
+ if (str.isEmpty())
+ return def;
+ return Channel.getChannels().stream().filter(c -> str.equals(c.ID)).findAny().orElse(def);
+ }
+
+ public void set(Channel value) {
+ data.set(value.ID);
+ }
+}
diff --git a/ButtonCore/src/main/java/buttondevteam/lib/player/ChromaGamerBase.java b/ButtonCore/src/main/java/buttondevteam/lib/player/ChromaGamerBase.java
index 2d7ef8b..3ab07b6 100755
--- a/ButtonCore/src/main/java/buttondevteam/lib/player/ChromaGamerBase.java
+++ b/ButtonCore/src/main/java/buttondevteam/lib/player/ChromaGamerBase.java
@@ -1,14 +1,19 @@
package buttondevteam.lib.player;
import buttondevteam.lib.TBMCCoreAPI;
+import buttondevteam.lib.chat.Channel;
import com.google.common.collect.HashBiMap;
import lombok.val;
import org.bukkit.Bukkit;
+import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Optional;
import java.util.function.Consumer;
+import java.util.function.Function;
@ChromaGamerEnforcer
public abstract class ChromaGamerBase implements AutoCloseable {
@@ -92,6 +97,32 @@ public abstract class ChromaGamerBase implements AutoCloseable {
return null;
}
+ private static ArrayList>> senderConverters = new ArrayList<>();
+
+ /**
+ * Adds a converter to the start of the list.
+ *
+ * @param converter The converter that returns an object corresponding to the sender or null, if it's not the right type.
+ */
+ public static void addConverter(Function> converter) {
+ senderConverters.add(0, converter);
+ }
+
+ /**
+ * Get from the given sender. the object's type will depend on the sender's type. May be null, but shouldn't be.
+ *
+ * @param sender The sender to use
+ * @return A user as returned by a converter or null if none can supply it
+ */
+ public static ChromaGamerBase getFromSender(CommandSender sender) {
+ for (val converter : senderConverters) {
+ val ocg = converter.apply(sender);
+ if (ocg.isPresent())
+ return ocg.get();
+ }
+ return null;
+ }
+
/**
* Saves the player. It'll pass all exceptions to the caller. To automatically handle the exception, use {@link #save()} instead.
*/
@@ -123,8 +154,10 @@ public abstract class ChromaGamerBase implements AutoCloseable {
if (!playerTypes.containsKey(getClass()))
throw new RuntimeException("Class not registered as a user class! Use TBMCCoreAPI.RegisterUserClass");
final String ownFolder = getFolder();
- user.plugindata.set(ownFolder + "_id", plugindata.getString(ownFolder + "_id"));
final String userFolder = user.getFolder();
+ if (ownFolder.equalsIgnoreCase(userFolder))
+ throw new RuntimeException("Do not connect two accounts of the same type! Type: "+ownFolder);
+ user.plugindata.set(ownFolder + "_id", plugindata.getString(ownFolder + "_id"));
plugindata.set(userFolder + "_id", user.plugindata.getString(userFolder + "_id"));
Consumer sync = sourcedata -> {
final String sourcefolder = sourcedata == plugindata ? ownFolder : userFolder;
@@ -225,7 +258,8 @@ public abstract class ChromaGamerBase implements AutoCloseable {
}
@SuppressWarnings("rawtypes")
- private final HashMap dataenummap = new HashMap<>();
+ private final HashMap dataenummap = new HashMap<>();
+ private ChannelPlayerData datachannel;
/**
* Use from a data() method, which is in a method with the name of the key. For example, use flair() for the enclosing method of the outer data() to save to and load from "flair"
@@ -243,7 +277,7 @@ public abstract class ChromaGamerBase implements AutoCloseable {
/**
* Use from a method with the name of the key. For example, use flair() for the enclosing method to save to and load from "flair"
- *
+ *
* @return A data object with methods to get and set
*/
@SuppressWarnings("unchecked")
@@ -255,6 +289,19 @@ public abstract class ChromaGamerBase implements AutoCloseable {
return dataenummap.get(mname);
}
+ /**
+ * Channel
+ *
+ * @return A data object with methods to get and set
+ */
+ @SuppressWarnings("unchecked")
+ protected ChannelPlayerData dataChannel(Channel def) { //TODO: Make interface with fromString() method and require use of that for player data types
+ ThrowIfNoUser();
+ if (datachannel == null)
+ datachannel = new ChannelPlayerData("channel", plugindata, def);
+ return datachannel;
+ }
+
/**
* Get player information. This method calls the {@link TBMCPlayerGetInfoEvent} to get all the player information across the TBMC plugins.
*
@@ -271,4 +318,10 @@ public abstract class ChromaGamerBase implements AutoCloseable {
public enum InfoTarget {
MCHover, MCCommand, Discord
}
+
+ //-----------------------------------------------------------------
+
+ public ChannelPlayerData channel() {
+ return dataChannel(Channel.GlobalChat);
+ }
}
diff --git a/ButtonCore/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.java b/ButtonCore/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.java
index cc5ff5c..cef358d 100755
--- a/ButtonCore/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.java
+++ b/ButtonCore/src/main/java/buttondevteam/lib/player/TBMCPlayerBase.java
@@ -206,119 +206,4 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
if (keys.size() > 1) // PlayerName is always saved, but we don't need a file for just that
super.close();
}
-
- /*private static void renameInTowny(TBMCPlayerBase player, Resident resident, String newName, TownyDatabaseHandler tdh) throws Exception {
- val field=TownyDataSource.class.getDeclaredField("lock"); //TODO: Remove
- field.setAccessible(true);
- Lock lock=(Lock)field.get(tdh);
- lock.lock(); //From Towny, removed the economy part, as that works by UUIDs
- String oldName = resident.getName();
-
- try {
- String filteredName;
- try {
- filteredName = NameValidation.checkAndFilterName(newName);
- } catch (InvalidNameException var39) {
- throw new NotRegisteredException(var39.getMessage());
- }
-
- double balance = 0.0D;
- Town town = null;
- long registered = 0L;
- long lastOnline = 0L;
- boolean isMayor = false;
- boolean isJailed = false;
- int JailSpawn = 0;
- //Don't do anything with economy balance as that works based on UUIDs
- List friends = resident.getFriends();
- List nationRanks = resident.getNationRanks();
- TownyPermission permissions = resident.getPermissions();
- String surname = resident.getSurname();
- String title = resident.getTitle();
- if (resident.hasTown()) {
- town = resident.getTown();
- }
-
- List townBlocks = resident.getTownBlocks();
- List townRanks = resident.getTownRanks();
- registered = resident.getRegistered();
- lastOnline = resident.getLastOnline();
- isMayor = resident.isMayor();
- isJailed = resident.isJailed();
- int JailSpawn = resident.getJailSpawn();
- this.deleteResident(resident);
- this.universe.getResidentMap().remove(oldName.toLowerCase());
- resident.setName(filteredName);
- this.universe.getResidentMap().put(filteredName.toLowerCase(), resident);
- if (transferBalance && TownySettings.isUsingEconomy()) {
- try {
- resident.setBalance(balance, "Rename Player - Transfer to new account");
- } catch (EconomyException var37) {
- var37.printStackTrace();
- }
- }
-
- resident.setFriends(friends);
- resident.setNationRanks(nationRanks);
- resident.setPermissions(permissions.toString());
- resident.setSurname(surname);
- resident.setTitle(title);
- resident.setTown(town);
- resident.setTownblocks(townBlocks);
- resident.setTownRanks(townRanks);
- resident.setRegistered(registered);
- resident.setLastOnline(lastOnline);
- if (isMayor) {
- try {
- town.setMayor(resident);
- } catch (TownyException var36) {
- ;
- }
- }
-
- resident.setJailed(isJailed);
- resident.setJailSpawn(JailSpawn);
- this.saveResidentList();
- this.saveResident(resident);
- if (town != null) {
- this.saveTown(town);
- }
-
- Iterator i$ = townBlocks.iterator();
-
- while(i$.hasNext()) {
- TownBlock tb = (TownBlock)i$.next();
- this.saveTownBlock(tb);
- }
-
- Resident oldResident = new Resident(oldName);
- List toSaveResident = new ArrayList(this.getResidents());
- Iterator i$ = toSaveResident.iterator();
-
- Resident toCheck;
- while(i$.hasNext()) {
- toCheck = (Resident)i$.next();
- if (toCheck.hasFriend(oldResident)) {
- try {
- toCheck.removeFriend(oldResident);
- toCheck.addFriend(resident);
- } catch (NotRegisteredException var35) {
- var35.printStackTrace();
- }
- }
- }
-
- i$ = toSaveResident.iterator();
-
- while(i$.hasNext()) {
- toCheck = (Resident)i$.next();
- this.saveResident(toCheck);
- }
- } finally {
- this.lock.unlock();
- }
-
- BukkitTools.getPluginManager().callEvent(new RenameResidentEvent(oldName, resident));
- this.universe.setChangedNotify(TownyObservableType.RENAME_RESIDENT);
- }*/
}
diff --git a/ButtonCore/src/main/resources/plugin.yml b/ButtonCore/src/main/resources/plugin.yml
index c638c1c..4e53d6c 100755
--- a/ButtonCore/src/main/resources/plugin.yml
+++ b/ButtonCore/src/main/resources/plugin.yml
@@ -10,4 +10,6 @@ commands:
primerestart:
description: Restarts the server as soon as nobody is online.
randomtp:
- description: teleport player to random location within world border. Every five players teleport to the same general area, and then a new general area is randomly selected for the next five players.
\ No newline at end of file
+ description: teleport player to random location within world border. Every five players teleport to the same general area, and then a new general area is randomly selected for the next five players.
+ member:
+ description: Add or remove a member
\ No newline at end of file
diff --git a/ButtonProcessor/pom.xml b/ButtonProcessor/pom.xml
index a4ce7fa..54981ad 100755
--- a/ButtonProcessor/pom.xml
+++ b/ButtonProcessor/pom.xml
@@ -37,13 +37,4 @@
UTF-8
-
-
-
- junit
- junit
- 3.8.1
- test
-
-
diff --git a/pom.xml b/pom.xml
index 1da127a..9529df4 100755
--- a/pom.xml
+++ b/pom.xml
@@ -28,6 +28,12 @@
1.8
+
+ maven-surefire-plugin
+
+ false
+
+