Merge pull request #114 from TBMCPlugins/dev
Misc. fixes, chat history config, clickable announcements
This commit is contained in:
commit
c66b212b0c
33 changed files with 439 additions and 272 deletions
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_13_PREVIEW">
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_11">
|
||||
<output url="file://$MODULE_DIR$/target/classes" />
|
||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
|
@ -34,14 +34,14 @@
|
|||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.ess3:LegacyProvider:2.17.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.ess3:ReflectionProvider:2.17.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.ess3:FlattenedProvider:2.17.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.palmergames.bukkit.towny:Towny:0.95.0.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.github.milkbowl:VaultAPI:master-4c248aad62-1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.bukkit:bukkit:1.13.1-R0.1-SNAPSHOT" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.palmergames.bukkit.towny:Towny:0.95.2.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.github.milkbowl:VaultAPI:master-89c00e1cb8-1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.projectlombok:lombok:1.18.10" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.spigotmc:spigot:1.12.2-R0.1-SNAPSHOT" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.github.webbukkit:Dynmap-Towny:master-0.60-g924051d-7" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.github.webbukkit:Dynmap:v2.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.nijikokun.bukkit:Permissions:3.1.6" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.bukkit:bukkit:1.7.10-R0.1-SNAPSHOT" level="project" />
|
||||
<orderEntry type="library" name="Maven: ru.tehkode:PermissionsEx:1.19.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: de.bananaco:bPermissions:2.9.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.platymuus.bukkit.permissions:PermissionsBukkit:1.6" level="project" />
|
||||
|
|
17
pom.xml
17
pom.xml
|
@ -135,6 +135,21 @@
|
|||
<!-- <plugin> <groupId>org.basepom.maven</groupId> <artifactId>duplicate-finder-maven-plugin</artifactId>
|
||||
<version>1.2.1</version> <executions> <execution> <goals> <goal>check</goal>
|
||||
</goals> </execution> </executions> </plugin> -->
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-testCompile</id>
|
||||
<goals>
|
||||
<goal>testCompile</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<groupId>buttondevteam</groupId>
|
||||
|
@ -198,7 +213,7 @@
|
|||
<dependency>
|
||||
<groupId>com.palmergames.bukkit.towny</groupId>
|
||||
<artifactId>Towny</artifactId>
|
||||
<version>0.95.0.0</version>
|
||||
<version>0.95.2.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- <dependency> <groupId>au.com.mineauz</groupId> <artifactId>Minigames</artifactId>
|
||||
|
|
|
@ -16,7 +16,6 @@ import buttondevteam.chat.components.towncolors.TownColorComponent;
|
|||
import buttondevteam.chat.components.towny.TownyComponent;
|
||||
import buttondevteam.chat.listener.PlayerJoinLeaveListener;
|
||||
import buttondevteam.chat.listener.PlayerListener;
|
||||
import buttondevteam.core.MainPlugin;
|
||||
import buttondevteam.core.component.channel.Channel;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.architecture.ButtonPlugin;
|
||||
|
@ -37,12 +36,12 @@ public class PluginMain extends ButtonPlugin { // Translated to Java: 2015.07.15
|
|||
public static PluginMain Instance;
|
||||
public static ConsoleCommandSender Console;
|
||||
|
||||
public ConfigData<String> notificationSound() {
|
||||
return getIConfig().getData("notificationSound", "");
|
||||
}
|
||||
|
||||
public ConfigData<Float> notificationPitch() {
|
||||
return getIConfig().getData("notificationPitch", 1.0f);
|
||||
/**
|
||||
* If enabled, stores and displays the last 10 messages the player can see (public, their town chat etc.)
|
||||
* Can be used with the Discord plugin so players can see some of the conversation they missed that's visible on Discord anyways.
|
||||
*/
|
||||
public ConfigData<Boolean> storeChatHistory() {
|
||||
return getIConfig().getData("storeChatHistory", true);
|
||||
}
|
||||
|
||||
// Fired when plugin is first enabled
|
||||
|
|
|
@ -16,14 +16,14 @@ import java.net.URLEncoder;
|
|||
})
|
||||
public class MWikiCommand extends ICommand2MC {
|
||||
@Command2.Subcommand
|
||||
public boolean def(CommandSender sender, @Command2.OptionalArg String query) {
|
||||
public boolean def(CommandSender sender, @Command2.OptionalArg @Command2.TextArg String query) {
|
||||
try {
|
||||
if (query == null)
|
||||
sender.sendMessage(new String[] { "§bMinecraft Wiki link: http://minecraft.gamepedia.com/",
|
||||
"You can also search on it using /mwiki <query>" });
|
||||
sender.sendMessage(new String[]{"§bMinecraft Wiki link: http://minecraft.gamepedia.com/",
|
||||
"You can also search on it using /mwiki <query>"});
|
||||
else
|
||||
sender.sendMessage("§bMinecraft Wiki link: http://minecraft.gamepedia.com/index.php?search="
|
||||
+ URLEncoder.encode(query, "UTF-8") + "&title=Special%3ASearch&go=Go");
|
||||
+ URLEncoder.encode(query, "UTF-8") + "&title=Special%3ASearch&go=Go");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
package buttondevteam.chat.commands.ucmds;
|
||||
|
||||
import buttondevteam.chat.PluginMain;
|
||||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@CommandClass(modOnly = false, helpText = {
|
||||
"Help",
|
||||
|
@ -36,19 +30,7 @@ public final class HelpCommand extends UCommandBase {
|
|||
"- Playernames: Hover over them to get some player info",
|
||||
"-- Respect: This is the number of paid respects divided by eliglble deaths. This is a reference to CoD:AW's \"Press F to pay respects\""});
|
||||
else if (topicOrCommand.equalsIgnoreCase("commands")) {
|
||||
ArrayList<String> text = new ArrayList<String>();
|
||||
text.add("§6---- Command list ----");
|
||||
for (TBMCCommandBase cmd : TBMCChatAPI.GetCommands().values())
|
||||
if (!cmd.getClass().getAnnotation(CommandClass.class).modOnly() || PluginMain.permission.has(sender, "tbmc.admin"))
|
||||
if (!cmd.isPlayerOnly() || sender instanceof Player)
|
||||
if (!cmd.GetCommandPath().contains(" "))
|
||||
text.add("/" + cmd.GetCommandPath());
|
||||
else {
|
||||
final String topcmd = cmd.GetCommandPath().substring(0, cmd.GetCommandPath().indexOf(' '));
|
||||
if (!text.contains("/" + topcmd))
|
||||
text.add("/" + topcmd);
|
||||
}
|
||||
sender.sendMessage(text.toArray(new String[0]));
|
||||
sender.sendMessage(getManager().getCommandsText());
|
||||
} else if (topicOrCommand.equalsIgnoreCase("colors")) {
|
||||
sender.sendMessage(new String[]{"§6---- Chat colors/formats ----", //
|
||||
"Tellraw name - Code | Tellraw name - Code", //
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package buttondevteam.chat.commands.ucmds;
|
||||
|
||||
import buttondevteam.chat.PluginMain;
|
||||
import buttondevteam.core.component.channel.Channel;
|
||||
import buttondevteam.lib.chat.ChatMessage;
|
||||
import buttondevteam.lib.chat.Command2;
|
||||
|
@ -21,7 +22,7 @@ public class HistoryCommand extends UCommandBase {
|
|||
/**
|
||||
* Key: ChannelID_groupID
|
||||
*/
|
||||
private static HashMap<String, LinkedList<HistoryEntry>> messages = new HashMap<>();
|
||||
private static final HashMap<String, LinkedList<HistoryEntry>> messages = new HashMap<>();
|
||||
|
||||
@Command2.Subcommand
|
||||
public boolean def(CommandSender sender, @Command2.OptionalArg String channel) {
|
||||
|
@ -29,6 +30,10 @@ public class HistoryCommand extends UCommandBase {
|
|||
}
|
||||
|
||||
public static boolean showHistory(CommandSender sender, String channel) {
|
||||
if (!PluginMain.Instance.storeChatHistory().get()) {
|
||||
sender.sendMessage("§6Chat history is disabled");
|
||||
return true;
|
||||
}
|
||||
Function<Channel, LinkedList<HistoryEntry>> getThem = ch -> messages.get(ch.ID + "_" + ch.getGroupID(sender)); //If can't see, groupID is null, and that shouldn't be in the map
|
||||
sender.sendMessage("§6---- Chat History ----");
|
||||
Stream<Channel> stream;
|
||||
|
@ -43,13 +48,15 @@ public class HistoryCommand extends UCommandBase {
|
|||
stream = Stream.of(och.get());
|
||||
}
|
||||
AtomicBoolean sent = new AtomicBoolean();
|
||||
val arr = stream.map(getThem).filter(Objects::nonNull).flatMap(Collection::stream)
|
||||
synchronized (messages) {
|
||||
val arr = stream.map(getThem).filter(Objects::nonNull).flatMap(Collection::stream)
|
||||
.sorted(Comparator.comparingLong(he -> he.timestamp)).toArray(HistoryEntry[]::new);
|
||||
for (int i = Math.max(0, arr.length - 10); i < arr.length; i++) {
|
||||
HistoryEntry e = arr[i];
|
||||
val cm = e.chatMessage;
|
||||
sender.sendMessage("[" + e.channel.DisplayName().get() + "] " + cm.getSender().getName() + ": " + cm.getMessage());
|
||||
sent.set(true);
|
||||
for (int i = Math.max(0, arr.length - 10); i < arr.length; i++) {
|
||||
HistoryEntry e = arr[i];
|
||||
val cm = e.chatMessage;
|
||||
sender.sendMessage("[" + e.channel.DisplayName().get() + "] " + cm.getSender().getName() + ": " + cm.getMessage());
|
||||
sent.set(true);
|
||||
}
|
||||
}
|
||||
if (!sent.get())
|
||||
sender.sendMessage("No messages can be found.");
|
||||
|
@ -67,11 +74,14 @@ public class HistoryCommand extends UCommandBase {
|
|||
}
|
||||
|
||||
public static void addChatMessage(ChatMessage chatMessage, Channel channel) {
|
||||
if (!PluginMain.Instance.storeChatHistory().get()) return;
|
||||
val groupID = channel.getGroupID(chatMessage.getPermCheck());
|
||||
if (groupID == null) return; //Just to be sure
|
||||
var ll = messages.computeIfAbsent(channel.ID + "_" + groupID, k -> new LinkedList<>()); //<-- TIL
|
||||
ll.add(new HistoryEntry(System.nanoTime(), chatMessage, channel)); //Adds as last element
|
||||
while (ll.size() > 10)
|
||||
ll.remove(); //Removes the first element
|
||||
synchronized (messages) {
|
||||
var ll = messages.computeIfAbsent(channel.ID + "_" + groupID, k -> new LinkedList<>()); //<-- TIL
|
||||
ll.add(new HistoryEntry(System.nanoTime(), chatMessage, channel)); //Adds as last element
|
||||
while (ll.size() > 10)
|
||||
ll.remove(); //Removes the first element
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package buttondevteam.chat.commands.ucmds;
|
||||
|
||||
import buttondevteam.chat.PluginMain;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.player.ChromaGamerBase.InfoTarget;
|
||||
import buttondevteam.lib.player.TBMCPlayer;
|
||||
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
@CommandClass(modOnly = false, helpText = {
|
||||
|
@ -20,16 +22,18 @@ public class InfoCommand extends UCommandBase {
|
|||
sender.sendMessage("The server console.");
|
||||
return true;
|
||||
}
|
||||
try (TBMCPlayer p = TBMCPlayerBase.getFromName(player, TBMCPlayer.class)) {
|
||||
if (p == null) {
|
||||
sender.sendMessage("§cThe specified player cannot be found");
|
||||
return true;
|
||||
Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
|
||||
try (TBMCPlayer p = TBMCPlayerBase.getFromName(player, TBMCPlayer.class)) {
|
||||
if (p == null) {
|
||||
sender.sendMessage("§cThe specified player cannot be found");
|
||||
return;
|
||||
}
|
||||
sender.sendMessage(p.getInfo(InfoTarget.MCCommand));
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Error while getting player information!", e);
|
||||
sender.sendMessage("§cError while getting player information!");
|
||||
}
|
||||
sender.sendMessage(p.getInfo(InfoTarget.MCCommand));
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Error while getting player information!", e);
|
||||
sender.sendMessage("§cError while getting player information!");
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,7 @@ package buttondevteam.chat.commands.ucmds;
|
|||
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.ICommand2MC;
|
||||
import buttondevteam.lib.chat.OptionallyPlayerCommandClass;
|
||||
|
||||
@CommandClass(modOnly = false, path = "u")
|
||||
@OptionallyPlayerCommandClass(playerOnly = false)
|
||||
public abstract class UCommandBase extends ICommand2MC {
|
||||
}
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
package buttondevteam.chat.components.announce;
|
||||
|
||||
import buttondevteam.chat.commands.ucmds.UCommandBase;
|
||||
import buttondevteam.chat.components.formatter.ChatProcessing;
|
||||
import buttondevteam.chat.components.formatter.FormatterComponent;
|
||||
import buttondevteam.chat.components.formatter.formatting.TellrawEvent;
|
||||
import buttondevteam.chat.components.formatter.formatting.TellrawPart;
|
||||
import buttondevteam.core.ComponentManager;
|
||||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.OptionallyPlayerCommandClass;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.val;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
@CommandClass(modOnly = true)
|
||||
@OptionallyPlayerCommandClass(playerOnly = false)
|
||||
@RequiredArgsConstructor
|
||||
public class AnnounceCommand extends UCommandBase {
|
||||
private final AnnouncerComponent component;
|
||||
|
@ -28,7 +32,7 @@ public class AnnounceCommand extends UCommandBase {
|
|||
@Command2.Subcommand(helpText = {
|
||||
"Edit announcement",
|
||||
"This command lets you edit an announcement by its index.",
|
||||
"Shouldn't be used directly, use either command blocks or click on an announcement in /u announce list (WIP) instead." //TODO: <--
|
||||
"Shouldn't be used directly, use either command blocks or click on an announcement in /u announce list instead."
|
||||
})
|
||||
public boolean edit(CommandSender sender, byte index, @Command2.TextArg String text) {
|
||||
String finalmessage1 = text.replace('&', '§');
|
||||
|
@ -49,8 +53,19 @@ public class AnnounceCommand extends UCommandBase {
|
|||
sender.sendMessage("§bList of announce messages:§r");
|
||||
sender.sendMessage("§bFormat: [index] message§r");
|
||||
int i = 0;
|
||||
for (String message : component.announceMessages().get())
|
||||
sender.sendMessage("[" + i++ + "] " + message);
|
||||
for (String message : component.announceMessages().get()) {
|
||||
String msg = "[" + i++ + "] " + message;
|
||||
//noinspection SuspiciousMethodCalls
|
||||
if (!ComponentManager.isEnabled(FormatterComponent.class) || !Bukkit.getOnlinePlayers().contains(sender)) {
|
||||
sender.sendMessage(msg);
|
||||
continue;
|
||||
}
|
||||
String json = ChatProcessing.toJson(new TellrawPart(msg)
|
||||
.setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, "Click to edit"))
|
||||
.setClickEvent(TellrawEvent.create(TellrawEvent.ClickAction.SUGGEST_COMMAND,
|
||||
"/" + getCommandPath() + " edit " + (i - 1) + " " + message.replace('§', '&'))));
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + sender.getName() + " " + json);
|
||||
}
|
||||
sender.sendMessage("§bCurrent wait time between announcements: "
|
||||
+ component.announceTime().get() / 60 / 1000 + " minute(s)§r");
|
||||
return true;
|
||||
|
|
|
@ -5,23 +5,31 @@ import buttondevteam.core.component.channel.Channel;
|
|||
import buttondevteam.lib.TBMCSystemChatEvent;
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.architecture.ConfigData;
|
||||
import buttondevteam.lib.architecture.ListConfigData;
|
||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Displays the configured messages at the set interval when someone is online.
|
||||
*/
|
||||
public class AnnouncerComponent extends Component<PluginMain> implements Runnable {
|
||||
public ConfigData<ArrayList<String>> announceMessages() {
|
||||
return getConfig().getData("announceMessages", new ArrayList<>(0));
|
||||
/**
|
||||
* The messages to display to players.
|
||||
*/
|
||||
public ListConfigData<String> announceMessages() {
|
||||
return getConfig().getListData("announceMessages");
|
||||
}
|
||||
|
||||
/**
|
||||
* The time in milliseconds between the messages. Use /u announce settime to set minutes.
|
||||
*/
|
||||
public ConfigData<Integer> announceTime() {
|
||||
return getConfig().getData("announceTime", 15 * 60 * 1000);
|
||||
}
|
||||
|
||||
private TBMCSystemChatEvent.BroadcastTarget target;
|
||||
|
||||
private static int AnnounceMessageIndex = 0;
|
||||
private int AnnounceMessageIndex = 0;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -43,7 +51,7 @@ public class AnnouncerComponent extends Component<PluginMain> implements Runnabl
|
|||
|
||||
@Override
|
||||
protected void enable() {
|
||||
target= TBMCSystemChatEvent.BroadcastTarget.add("announcements");
|
||||
target = TBMCSystemChatEvent.BroadcastTarget.add("announcements");
|
||||
registerCommand(new AnnounceCommand(this));
|
||||
new Thread(this).start();
|
||||
}
|
||||
|
|
|
@ -15,8 +15,12 @@ import java.util.Map;
|
|||
import java.util.NoSuchElementException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Allows players to append tableflips and other things to their messages. Everything is configurable here.
|
||||
*/
|
||||
public class AppendTextComponent extends Component<PluginMain> {
|
||||
private Map<String, IHaveConfig> appendTexts;
|
||||
|
||||
private ConfigData<String[]> helpText(IHaveConfig config) {
|
||||
return config.getData("helpText", () -> new String[]{
|
||||
"Tableflip", //
|
||||
|
|
|
@ -5,6 +5,7 @@ import buttondevteam.chat.components.formatter.formatting.TellrawEvent;
|
|||
import buttondevteam.chat.components.formatter.formatting.TellrawPart;
|
||||
import buttondevteam.core.ComponentManager;
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.architecture.ComponentMetadata;
|
||||
import buttondevteam.lib.player.TBMCPlayer;
|
||||
import buttondevteam.lib.player.TBMCPlayerJoinEvent;
|
||||
import lombok.val;
|
||||
|
@ -15,6 +16,10 @@ import org.bukkit.event.Listener;
|
|||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
|
||||
/**
|
||||
* Allows players to enter chat-only mode which puts them into spectator mode and disallows everything besides chatting.
|
||||
*/
|
||||
@ComponentMetadata(enabledByDefault = false)
|
||||
public class ChatOnlyComponent extends Component implements Listener {
|
||||
@Override
|
||||
protected void enable() {
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package buttondevteam.chat.components.chatonly;
|
||||
|
||||
import buttondevteam.lib.chat.ICommand2MC;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import buttondevteam.chat.ChatPlayer;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.PlayerCommandBase;
|
||||
import buttondevteam.lib.chat.ICommand2MC;
|
||||
import buttondevteam.lib.player.TBMCPlayer;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@CommandClass(modOnly = false, helpText = {
|
||||
"§6---- Chat-only mode ----", //
|
||||
|
|
|
@ -6,10 +6,8 @@ import buttondevteam.chat.commands.ucmds.UCommandBase;
|
|||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.OptionallyPlayerCommandClass;
|
||||
import buttondevteam.lib.player.TBMCPlayer;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Timer;
|
||||
|
@ -19,14 +17,12 @@ import java.util.Timer;
|
|||
"Accepts a flair from Reddit", //
|
||||
"Use /u accept <username> if you commented from multiple accounts"
|
||||
})
|
||||
@OptionallyPlayerCommandClass(playerOnly = true)
|
||||
@RequiredArgsConstructor
|
||||
public class AcceptCommand extends UCommandBase {
|
||||
private final FlairComponent component;
|
||||
|
||||
@Command2.Subcommand
|
||||
public boolean def(CommandSender sender, @Command2.OptionalArg String username) {
|
||||
final Player player = (Player) sender;
|
||||
public boolean def(Player player, @Command2.OptionalArg String username) {
|
||||
ChatPlayer p = TBMCPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class);
|
||||
if (username == null && p.UserNames().size() > 1) {
|
||||
player.sendMessage("§9Multiple users commented your name. §bPlease pick one using /u accept <username>");
|
||||
|
|
|
@ -4,6 +4,7 @@ import buttondevteam.chat.ChatPlayer;
|
|||
import buttondevteam.chat.PluginMain;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.architecture.ComponentMetadata;
|
||||
import buttondevteam.lib.architecture.ConfigData;
|
||||
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||
import com.google.gson.JsonArray;
|
||||
|
@ -22,9 +23,17 @@ import java.net.UnknownHostException;
|
|||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This component checks a specific Reddit thread every 10 seconds for comments such as "IGN: NorbiPeti" to link Reddit accounts and to determine their /r/thebutton flair.
|
||||
* This was the original goal of this plugin when it was made.
|
||||
*/
|
||||
@ComponentMetadata(enabledByDefault = false)
|
||||
public class FlairComponent extends Component<PluginMain> {
|
||||
/**
|
||||
* The Reddit thread to check for account connections. Re-enable the component if this was empty.
|
||||
*/
|
||||
ConfigData<String> flairThreadURL() {
|
||||
return getConfig().getData("flairThreadURL", "https://www.reddit.com/r/Chromagamers/comments/51ys94/flair_thread_for_the_mc_server/");
|
||||
return getConfig().getData("flairThreadURL", "");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,7 +61,7 @@ public class FlairComponent extends Component<PluginMain> {
|
|||
|
||||
private void FlairGetterThreadMethod() {
|
||||
int errorcount = 0;
|
||||
while (isEnabled()) {
|
||||
while (isEnabled() && flairThreadURL().get().length() > 0) {
|
||||
try {
|
||||
String body = TBMCCoreAPI.DownloadString(flairThreadURL().get() + ".json?limit=1000");
|
||||
JsonArray json = new JsonParser().parse(body).getAsJsonArray().get(1).getAsJsonObject().get("data")
|
||||
|
|
|
@ -4,20 +4,16 @@ import buttondevteam.chat.ChatPlayer;
|
|||
import buttondevteam.chat.commands.ucmds.UCommandBase;
|
||||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.OptionallyPlayerCommandClass;
|
||||
import buttondevteam.lib.player.TBMCPlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@CommandClass(modOnly = false, helpText = {
|
||||
"Ignore flair",
|
||||
"Stop the \"write your name in the thread\" message from showing up"
|
||||
})
|
||||
@OptionallyPlayerCommandClass(playerOnly = true)
|
||||
public final class IgnoreCommand extends UCommandBase {
|
||||
@Command2.Subcommand
|
||||
public boolean def(CommandSender sender) {
|
||||
final Player player = (Player) sender;
|
||||
public boolean def(Player player) {
|
||||
ChatPlayer p = TBMCPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class);
|
||||
if (p.FlairState().get().equals(FlairStates.Accepted)) {
|
||||
player.sendMessage("§cYou can only ignore the \"write your name in the thread\" message.");
|
||||
|
|
|
@ -25,6 +25,7 @@ import buttondevteam.lib.player.ChromaGamerBase;
|
|||
import buttondevteam.lib.player.TBMCPlayer;
|
||||
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
@ -49,12 +50,13 @@ public class ChatProcessing {
|
|||
private static final Pattern HASHTAG_PATTERN = Pattern.compile("#(\\w+)");
|
||||
private static final Pattern URL_PATTERN = Pattern.compile("(http[\\w:/?=$\\-_.+!*'(),&]+(?:#[\\w]+)?)");
|
||||
public static final Pattern ENTIRE_MESSAGE_PATTERN = Pattern.compile(".+");
|
||||
private static final Pattern UNDERLINED_PATTERN = Pattern.compile("_");
|
||||
private static final Pattern UNDERLINED_PATTERN = Pattern.compile("__");
|
||||
private static final Pattern ITALIC_PATTERN = Pattern.compile("\\*");
|
||||
private static final Pattern ITALIC_PATTERN_2 = Pattern.compile("_");
|
||||
private static final Pattern BOLD_PATTERN = Pattern.compile("\\*\\*");
|
||||
private static final Pattern CODE_PATTERN = Pattern.compile("`");
|
||||
private static final Pattern MASKED_LINK_PATTERN = Pattern.compile("\\[([^\\[\\]]+)]\\(([^()]+)\\)");
|
||||
private static final Pattern SOMEONE_PATTERN = Pattern.compile("@someone"); //TODO
|
||||
private static final Pattern SOMEONE_PATTERN = Pattern.compile("@someone");
|
||||
private static final Pattern STRIKETHROUGH_PATTERN = Pattern.compile("~~");
|
||||
private static final Pattern SPOILER_PATTERN = Pattern.compile("\\|\\|");
|
||||
private static final Color[] RainbowPresserColors = new Color[]{Color.Red, Color.Gold, Color.Yellow, Color.Green,
|
||||
|
@ -68,7 +70,8 @@ public class ChatProcessing {
|
|||
ChatFormatter.builder("bold", BOLD_PATTERN).bold(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range)
|
||||
.priority(Priority.High).build(),
|
||||
ChatFormatter.builder("italic", ITALIC_PATTERN).italic(true).removeCharCount((short) 1).type(ChatFormatter.Type.Range).build(),
|
||||
ChatFormatter.builder("underlined", UNDERLINED_PATTERN).underlined(true).removeCharCount((short) 1).type(ChatFormatter.Type.Range)
|
||||
ChatFormatter.builder("italic2", ITALIC_PATTERN_2).italic(true).removeCharCount((short) 1).type(ChatFormatter.Type.Range).build(),
|
||||
ChatFormatter.builder("underlined", UNDERLINED_PATTERN).underlined(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range)
|
||||
.build(),
|
||||
ChatFormatter.builder("strikethrough", STRIKETHROUGH_PATTERN).strikethrough(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range)
|
||||
.build(),
|
||||
|
@ -98,7 +101,15 @@ public class ChatProcessing {
|
|||
builder.setOpenlink(link);
|
||||
return text;
|
||||
}).type(ChatFormatter.Type.Excluder).build(),
|
||||
ChatFormatter.builder("url", URL_PATTERN).underlined(true).openlink("$1").type(ChatFormatter.Type.Excluder).build());
|
||||
ChatFormatter.builder("url", URL_PATTERN).underlined(true).openlink("$1").type(ChatFormatter.Type.Excluder).build(),
|
||||
ChatFormatter.builder("someone", SOMEONE_PATTERN).color(Color.Aqua).onmatch((match, builder, section) -> {
|
||||
if (Bukkit.getOnlinePlayers().size() == 0) return match;
|
||||
var players = ImmutableList.copyOf(Bukkit.getOnlinePlayers());
|
||||
var playerC = new Random().nextInt(players.size());
|
||||
var player = players.get(playerC);
|
||||
playPingSound(player, ComponentManager.getIfEnabled(FormatterComponent.class));
|
||||
return "@someone (" + player.getDisplayName() + "§r)";
|
||||
}).build());
|
||||
private static Gson gson = new GsonBuilder()
|
||||
.registerTypeHierarchyAdapter(TellrawSerializableEnum.class, new TellrawSerializer.TwEnum())
|
||||
.registerTypeHierarchyAdapter(Collection.class, new TellrawSerializer.TwCollection())
|
||||
|
@ -146,13 +157,9 @@ public class ChatProcessing {
|
|||
|
||||
ArrayList<ChatFormatter> formatters;
|
||||
if (component.allowFormatting().get()) {
|
||||
formatters = addFormatters(colormode, e::shouldSendTo);
|
||||
formatters = addFormatters(colormode, e::shouldSendTo, component);
|
||||
if (colormode == channel.Color().get() && mp != null && mp.RainbowPresserColorMode) { // Only overwrite channel color
|
||||
final AtomicInteger rpc = new AtomicInteger(0);
|
||||
formatters.add(ChatFormatter.builder("word", WORD_PATTERN).color(colormode).onmatch((match, cf, s) -> {
|
||||
cf.setColor(RainbowPresserColors[rpc.getAndUpdate(i -> ++i < RainbowPresserColors.length ? i : 0)]);
|
||||
return match;
|
||||
}).build());
|
||||
createRPC(colormode, formatters);
|
||||
}
|
||||
pingedconsole = false; // Will set it to true onmatch (static constructor)
|
||||
} else
|
||||
|
@ -206,13 +213,21 @@ public class ChatProcessing {
|
|||
return false;
|
||||
}
|
||||
|
||||
static String toJson(TellrawPart json) {
|
||||
static void createRPC(Color colormode, ArrayList<ChatFormatter> formatters) {
|
||||
final AtomicInteger rpc = new AtomicInteger(0);
|
||||
formatters.add(ChatFormatter.builder("rpc", WORD_PATTERN).color(colormode).onmatch((match, cf, s) -> {
|
||||
cf.setColor(RainbowPresserColors[rpc.getAndUpdate(i -> ++i < RainbowPresserColors.length ? i : 0)]);
|
||||
return match;
|
||||
}).build());
|
||||
}
|
||||
|
||||
public static String toJson(TellrawPart json) {
|
||||
return gson.toJson(json);
|
||||
}
|
||||
|
||||
static TellrawPart createTellraw(CommandSender sender, String message, @Nullable Player player,
|
||||
@Nullable ChatPlayer mp, @Nullable ChromaGamerBase cg, final String channelidentifier,
|
||||
String origin) {
|
||||
@Nullable ChatPlayer mp, @Nullable ChromaGamerBase cg, final String channelidentifier,
|
||||
String origin) {
|
||||
TellrawPart json = new TellrawPart("");
|
||||
ChatOnlyComponent.tellrawCreate(mp, json); //TODO: Make nice API
|
||||
json.addExtra(
|
||||
|
@ -249,7 +264,7 @@ public class ChatProcessing {
|
|||
+ "]";
|
||||
}
|
||||
|
||||
static ArrayList<ChatFormatter> addFormatters(Color colormode, Predicate<Player> canSee) {
|
||||
static ArrayList<ChatFormatter> addFormatters(Color colormode, Predicate<Player> canSee, @Nullable FormatterComponent component) {
|
||||
@SuppressWarnings("unchecked")
|
||||
ArrayList<ChatFormatter> formatters = (ArrayList<ChatFormatter>) commonFormatters.clone();
|
||||
|
||||
|
@ -306,7 +321,7 @@ public class ChatProcessing {
|
|||
}
|
||||
ChatPlayer mpp = TBMCPlayer.getPlayer(nottest ? p.getUniqueId() : new UUID(0, 0), ChatPlayer.class);
|
||||
if (nottest) {
|
||||
playPingSound(p);
|
||||
playPingSound(p, component);
|
||||
}
|
||||
String color = String.format("§%x", (mpp.GetFlairColor() == 0x00 ? 0xb : mpp.GetFlairColor()));
|
||||
return color + (nottest ? p.getName() : pn.get()) + "§r"; //Fix name casing, except when testing
|
||||
|
@ -322,7 +337,7 @@ public class ChatProcessing {
|
|||
+ match.toLowerCase() + " but was reported as online.");
|
||||
return "§c" + match + "§r";
|
||||
}
|
||||
playPingSound(p);
|
||||
playPingSound(p, component);
|
||||
return PluginMain.essentials.getUser(p).getNickname();
|
||||
}
|
||||
error.accept("Player nicknamed " + match.toLowerCase()
|
||||
|
@ -333,12 +348,12 @@ public class ChatProcessing {
|
|||
return formatters;
|
||||
}
|
||||
|
||||
private static void playPingSound(Player p) {
|
||||
if (PluginMain.Instance.notificationSound().get().length() == 0)
|
||||
private static void playPingSound(Player p, @Nullable FormatterComponent component) {
|
||||
if (component == null || component.notificationSound().get().length() == 0)
|
||||
p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 0.5f); // TODO: Airhorn
|
||||
else
|
||||
p.playSound(p.getLocation(), PluginMain.Instance.notificationSound().get(), 1.0f,
|
||||
PluginMain.Instance.notificationPitch().get());
|
||||
p.playSound(p.getLocation(), component.notificationSound().get(), 1.0f,
|
||||
component.notificationPitch().get());
|
||||
}
|
||||
|
||||
static void doFunStuff(CommandSender sender, TBMCChatEventBase event, String message) {
|
||||
|
|
|
@ -8,14 +8,33 @@ import buttondevteam.lib.architecture.Component;
|
|||
import buttondevteam.lib.architecture.ConfigData;
|
||||
|
||||
/**
|
||||
* This component handles the custom processing of chat messages. If this component is disabled channels won't be supported either in Minecraft.
|
||||
* This component handles the custom processing of chat messages. If this component is disabled channels won't be supported in Minecraft.
|
||||
* If you only want to disable the formatting features, set allowFormatting to false.
|
||||
* If you're using another chat plugin, you should disable the whole component.
|
||||
*/
|
||||
public class FormatterComponent extends Component<PluginMain> {
|
||||
/**
|
||||
* Determines whether Markdown formatting, name mentioning and similar features are enabled.
|
||||
*/
|
||||
ConfigData<Boolean> allowFormatting() {
|
||||
return getConfig().getData("allowFormatting", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* The sound to play when a player is mentioned. Leave empty to use default.
|
||||
*/
|
||||
public ConfigData<String> notificationSound() {
|
||||
return getConfig().getData("notificationSound", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* The pitch of the notification sound.
|
||||
*/
|
||||
public ConfigData<Float> notificationPitch() {
|
||||
return getConfig().getData("notificationPitch", 1.0f);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void enable() {
|
||||
MainPlugin.Instance.setChatHandlerEnabled(false); //Disable Core chat handler - if this component is disabled then let it do it's job
|
||||
|
|
|
@ -45,6 +45,13 @@ public final class ChatFormatter {
|
|||
String hoverText;
|
||||
String name;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ChatFormatter{" +
|
||||
"name='" + name + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
public static ChatFormatterBuilder builder(String name, Pattern regex) {
|
||||
return builder().regex(regex).name(name);
|
||||
}
|
||||
|
@ -98,7 +105,7 @@ public final class ChatFormatter {
|
|||
sections = convertRangeSections(str, sections, remchars);
|
||||
|
||||
header("Adding remove chars (RC)"); // Important to add after the range section conversion
|
||||
addRemChars(sections, remchars);
|
||||
addRemChars(sections, remchars, str);
|
||||
|
||||
header("Section combining");
|
||||
combineSections(str, sections);
|
||||
|
@ -134,12 +141,26 @@ public final class ChatFormatter {
|
|||
}
|
||||
}
|
||||
|
||||
private static void newCombine(String str, ArrayList<FormattedSection> sections, ArrayList<int[]> remchars) {
|
||||
var stack = new Stack<FormattedSection>();
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
for (Iterator<FormattedSection> iterator = sections.iterator(); iterator.hasNext(); ) {
|
||||
FormattedSection section = iterator.next();
|
||||
if (section.Start <= i) {
|
||||
stack.push(section);
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ArrayList<FormattedSection> convertRangeSections(String str, ArrayList<FormattedSection> sections, ArrayList<int[]> remchars) {
|
||||
ArrayList<FormattedSection> combined = new ArrayList<>();
|
||||
Map<ChatFormatter, FormattedSection> nextSection = new HashMap<>();
|
||||
boolean escaped = false;
|
||||
int takenStart = -1, takenEnd = -1;
|
||||
ChatFormatter takenFormatter = null;
|
||||
boolean takenByBigGuy = false; //Can't win against him (finished sections take precedence)
|
||||
for (final FormattedSection section : sections) {
|
||||
// Set ending to -1 until closed with another 1 long "section" - only do this if IsRange is true
|
||||
if (section.type != Type.Range) {
|
||||
|
@ -155,11 +176,12 @@ public final class ChatFormatter {
|
|||
continue;
|
||||
}
|
||||
if (!escaped) {
|
||||
ChatFormatter formatter = section.Formatters.get(0);
|
||||
if (section.Start == takenStart || (section.Start > takenStart && section.Start < takenEnd)) {
|
||||
/*
|
||||
* if (nextSection.containsKey(section.Formatters.get(0)) ? section.RemCharFromStart <= takenEnd - takenStart : section.RemCharFromStart > takenEnd - takenStart) {
|
||||
*/
|
||||
if (section.Formatters.get(0).removeCharCount < takenEnd - takenStart) {
|
||||
if (takenByBigGuy || formatter.removeCharCount < takenEnd - takenStart) {
|
||||
DebugCommand.SendDebugMessage("Lose: " + section);
|
||||
sendMessageWithPointer(str, section.Start, section.End);
|
||||
DebugCommand.SendDebugMessage("And win: " + takenFormatter);
|
||||
|
@ -170,21 +192,38 @@ public final class ChatFormatter {
|
|||
sendMessageWithPointer(str, section.Start, section.End);
|
||||
DebugCommand.SendDebugMessage("And lose: " + takenFormatter);
|
||||
}
|
||||
boolean hasFormatter = nextSection.containsKey(formatter);
|
||||
if (!hasFormatter) {
|
||||
val ff = formatter;
|
||||
val cfo = nextSection.keySet().stream().filter(f -> f.removeCharCount > ff.removeCharCount).findAny();
|
||||
if (cfo.isPresent()) {
|
||||
//formatter = cfo.get();
|
||||
val s = nextSection.get(cfo.get());
|
||||
int takenS = section.Start, takenE = section.Start + formatter.removeCharCount;
|
||||
if (s.Start == takenS || (s.Start > takenS && s.Start < takenE)) { //Peek()
|
||||
hasFormatter = true;
|
||||
continue; //Not the formatter we're looking for - TODO: It doesn't fix the problem of italics at the end
|
||||
}
|
||||
}
|
||||
}
|
||||
takenStart = section.Start;
|
||||
takenEnd = section.Start + section.Formatters.get(0).removeCharCount;
|
||||
takenFormatter = section.Formatters.get(0);
|
||||
if (nextSection.containsKey(section.Formatters.get(0))) {
|
||||
FormattedSection s = nextSection.remove(section.Formatters.get(0));
|
||||
takenEnd = section.Start + formatter.removeCharCount;
|
||||
takenFormatter = formatter;
|
||||
if (hasFormatter) {
|
||||
FormattedSection s = nextSection.remove(formatter);
|
||||
//HACK? If we can find another section that removes more characters, finish that instead
|
||||
// section: the ending marker section - s: the to-be full section
|
||||
s.End = takenEnd - 1; //Take the remCharCount into account as well
|
||||
// s.IsRange = false; // IsRange means it's a 1 long section indicating a start or an end
|
||||
combined.add(s);
|
||||
takenByBigGuy = true;
|
||||
DebugCommand.SendDebugMessage("Finished section: " + s);
|
||||
sendMessageWithPointer(str, s.Start, s.End);
|
||||
} else {
|
||||
DebugCommand.SendDebugMessage("Adding next section: " + section);
|
||||
sendMessageWithPointer(str, section.Start, section.End);
|
||||
nextSection.put(section.Formatters.get(0), section);
|
||||
nextSection.put(formatter, section);
|
||||
takenByBigGuy = false;
|
||||
}
|
||||
DebugCommand
|
||||
.SendDebugMessage("New area taken: (" + takenStart + "-" + takenEnd + ") " + takenFormatter);
|
||||
|
@ -200,7 +239,7 @@ public final class ChatFormatter {
|
|||
return sections;
|
||||
}
|
||||
|
||||
private static void addRemChars(ArrayList<FormattedSection> sections, ArrayList<int[]> remchars) {
|
||||
private static void addRemChars(ArrayList<FormattedSection> sections, ArrayList<int[]> remchars, String str) {
|
||||
sections.stream()
|
||||
.flatMap(fs -> fs.Formatters.stream().filter(cf -> cf.removeCharCount > 0)
|
||||
.mapToInt(cf -> cf.removeCharCount).mapToObj(rcc -> new int[]{fs.Start, fs.Start + rcc - 1}))
|
||||
|
@ -210,31 +249,41 @@ public final class ChatFormatter {
|
|||
.mapToInt(cf -> cf.removeCharCount).mapToObj(rcc -> new int[]{fs.End - rcc + 1, fs.End}))
|
||||
.forEach(remchars::add);
|
||||
DebugCommand.SendDebugMessage("Added remchars:");
|
||||
DebugCommand
|
||||
.SendDebugMessage(remchars.stream().map(Arrays::toString).collect(Collectors.joining("; ")));
|
||||
DebugCommand.SendDebugMessage(remchars.stream().map(Arrays::toString).collect(Collectors.joining("; ")));
|
||||
sendMessageWithPointer(str,
|
||||
remchars.stream().flatMapToInt(Arrays::stream).toArray());
|
||||
}
|
||||
|
||||
private static void combineSections(String str, ArrayList<FormattedSection> sections) {
|
||||
boolean cont = true;
|
||||
boolean found = false;
|
||||
for (int i = 1; cont; ) {
|
||||
int nextindex = i + 1;
|
||||
if (sections.size() < 2)
|
||||
break;
|
||||
for (int i = 1; i < sections.size(); i++) {
|
||||
DebugCommand.SendDebugMessage("i: " + i);
|
||||
FormattedSection firstSection = sections.get(i - 1);
|
||||
final FormattedSection firstSection;
|
||||
final FormattedSection lastSection;
|
||||
{
|
||||
FormattedSection firstSect = sections.get(i - 1);
|
||||
FormattedSection lastSect = sections.get(i);
|
||||
if (firstSect.Start > lastSect.Start) { //The first can't start later
|
||||
var section = firstSect;
|
||||
firstSect = lastSect;
|
||||
lastSect = section;
|
||||
}
|
||||
firstSection = firstSect;
|
||||
lastSection = lastSect;
|
||||
}
|
||||
DebugCommand.SendDebugMessage("Combining sections " + firstSection);
|
||||
sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
||||
final FormattedSection lastSection = sections.get(i);
|
||||
DebugCommand.SendDebugMessage(" and " + lastSection);
|
||||
sendMessageWithPointer(str, lastSection.Start, lastSection.End);
|
||||
if (firstSection.Start == lastSection.Start && firstSection.End == lastSection.End) {
|
||||
firstSection.Formatters.addAll(lastSection.Formatters);
|
||||
firstSection.Matches.addAll(lastSection.Matches);
|
||||
firstSection.type = lastSection.type;
|
||||
DebugCommand.SendDebugMessage("To section " + firstSection);
|
||||
sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
||||
sections.remove(i);
|
||||
found = true;
|
||||
i = 0;
|
||||
sortSections(sections);
|
||||
continue;
|
||||
} else if (firstSection.End > lastSection.Start && firstSection.Start < lastSection.End) {
|
||||
int origend2 = firstSection.End;
|
||||
firstSection.End = lastSection.Start - 1;
|
||||
|
@ -244,7 +293,6 @@ public final class ChatFormatter {
|
|||
section.Formatters.addAll(lastSection.Formatters);
|
||||
section.Matches.addAll(lastSection.Matches); // TODO: Clean
|
||||
sections.add(i, section);
|
||||
nextindex++;
|
||||
// Use the properties of the first section not the second one
|
||||
lastSection.Formatters.clear();
|
||||
lastSection.Formatters.addAll(firstSection.Formatters);
|
||||
|
@ -256,7 +304,7 @@ public final class ChatFormatter {
|
|||
|
||||
Predicate<FormattedSection> removeIfNeeded = s -> {
|
||||
if (s.Start < 0 || s.End < 0 || s.Start > s.End) {
|
||||
DebugCommand.SendDebugMessage("Removing section: " + s);
|
||||
DebugCommand.SendDebugMessage(" Removed: " + s);
|
||||
sendMessageWithPointer(str, s.Start, s.End);
|
||||
sections.remove(s);
|
||||
return true;
|
||||
|
@ -277,27 +325,19 @@ public final class ChatFormatter {
|
|||
DebugCommand.SendDebugMessage(" 3:" + lastSection);
|
||||
sendMessageWithPointer(str, lastSection.Start, lastSection.End);
|
||||
}
|
||||
found = true;
|
||||
i = 0;
|
||||
}
|
||||
sortSections(sections);
|
||||
if (i == 0) continue;
|
||||
for (int j = i - 1; j <= i + 1; j++) {
|
||||
if (j < sections.size() && sections.get(j).End < sections.get(j).Start) {
|
||||
DebugCommand.SendDebugMessage("Removing section: " + sections.get(j));
|
||||
sendMessageWithPointer(str, sections.get(j).Start, sections.get(j).End);
|
||||
sections.remove(j);
|
||||
j--;
|
||||
found = true;
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
i = nextindex - 1;
|
||||
i++;
|
||||
if (i >= sections.size()) {
|
||||
if (found) {
|
||||
i = 1;
|
||||
found = false;
|
||||
sortSections(sections);
|
||||
} else
|
||||
cont = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,11 +350,13 @@ public final class ChatFormatter {
|
|||
int start = section.Start, end = section.End;
|
||||
DebugCommand.SendDebugMessage("Start: " + start + " - End: " + end);
|
||||
sendMessageWithPointer(str, start, end);
|
||||
val rcs = remchars.stream().filter(rc -> rc[0] <= start && start <= rc[1]).findAny();
|
||||
val rce = remchars.stream().filter(rc -> rc[0] <= end && end <= rc[1]).findAny();
|
||||
val rci = remchars.stream().filter(rc -> start < rc[0] && rc[1] < end).toArray(int[][]::new);
|
||||
int s = start, e = end;
|
||||
if (rcs.isPresent())
|
||||
/*DebugCommand.SendDebugMessage("RCS: "+remchars.stream().filter(rc -> rc[0] <= start && start <= rc[1]).count());
|
||||
DebugCommand.SendDebugMessage("RCE: "+remchars.stream().filter(rc -> rc[0] <= end && end <= rc[1]).count());
|
||||
DebugCommand.SendDebugMessage("RCI: "+remchars.stream().filter(rc -> start < rc[0] || rc[1] < end).count());*/
|
||||
val rci = remchars.stream().filter(rc -> (rc[0] <= start && rc[1] >= start)
|
||||
|| (rc[0] >= start && rc[1] <= end)
|
||||
|| (rc[0] <= end && rc[1] >= end)).sorted(Comparator.comparingInt(rc -> rc[0] * 10000 + rc[1])).toArray(int[][]::new);
|
||||
/*if (rcs.isPresent())
|
||||
s = rcs.get()[1] + 1;
|
||||
if (rce.isPresent())
|
||||
e = rce.get()[0] - 1;
|
||||
|
@ -322,12 +364,17 @@ public final class ChatFormatter {
|
|||
if (e - s < 0) { //e-s==0 means the end char is the same as start char, so one char message
|
||||
DebugCommand.SendDebugMessage("Skipping section because of remchars (length would be " + (e - s + 1) + ")");
|
||||
continue;
|
||||
}
|
||||
originaltext = str.substring(s, e + 1);
|
||||
}*/
|
||||
DebugCommand.SendDebugMessage("Applying RC: " + Arrays.stream(rci).map(Arrays::toString).collect(Collectors.joining(", ", "[", "]")));
|
||||
originaltext = str.substring(start, end + 1);
|
||||
val sb = new StringBuilder(originaltext);
|
||||
for (int x = rci.length - 1; x >= 0; x--)
|
||||
sb.delete(rci[x][0] - start - 1, rci[x][1] - start); //Delete going backwards
|
||||
sb.delete(Math.max(rci[x][0] - start, 0), Math.min(rci[x][1] - start, end) + 1); //Delete going backwards
|
||||
originaltext = sb.toString();
|
||||
if (originaltext.length() == 0) {
|
||||
DebugCommand.SendDebugMessage("Skipping section because of remchars");
|
||||
continue;
|
||||
}
|
||||
DebugCommand.SendDebugMessage("Section text: " + originaltext);
|
||||
String openlink = null;
|
||||
section.Formatters.sort(Comparator.comparing(cf2 -> cf2.priority.GetValue())); //Apply the highest last, to overwrite previous ones
|
||||
|
@ -381,7 +428,7 @@ public final class ChatFormatter {
|
|||
sections.sort(
|
||||
(s1, s2) -> s1.Start == s2.Start
|
||||
? s1.End == s2.End ? Integer.compare(s2.Formatters.get(0).priority.GetValue(),
|
||||
s1.Formatters.get(0).priority.GetValue()) : Integer.compare(s2.End, s1.End)
|
||||
s1.Formatters.get(0).priority.GetValue()) : Integer.compare(s1.End, s2.End)
|
||||
: Integer.compare(s1.Start, s2.Start));
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,10 @@ package buttondevteam.chat.components.fun;
|
|||
|
||||
import buttondevteam.chat.ChatPlayer;
|
||||
import buttondevteam.chat.PluginMain;
|
||||
import buttondevteam.lib.chat.*;
|
||||
import buttondevteam.lib.chat.Color;
|
||||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.ICommand2MC;
|
||||
import buttondevteam.lib.player.TBMCPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
|
@ -13,7 +16,6 @@ import java.util.Optional;
|
|||
"Rainbow mode",
|
||||
"This command allows you to talk in rainbow colors"
|
||||
})
|
||||
@OptionallyPlayerCommandClass(playerOnly = true)
|
||||
public class CCommand extends ICommand2MC {
|
||||
@Command2.Subcommand
|
||||
public boolean def(Player player, @Command2.OptionalArg String color) {
|
||||
|
|
|
@ -5,7 +5,6 @@ import buttondevteam.chat.PluginMain;
|
|||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.ICommand2MC;
|
||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
||||
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||
import lombok.val;
|
||||
import org.bukkit.Bukkit;
|
||||
|
|
|
@ -26,26 +26,41 @@ import org.bukkit.potion.PotionEffect;
|
|||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Random things I added over the years.
|
||||
*/
|
||||
public class FunComponent extends Component<PluginMain> implements Listener {
|
||||
private boolean ActiveF = false;
|
||||
private ChatPlayer FPlayer = null;
|
||||
private BukkitTask Ftask = null;
|
||||
private ArrayList<CommandSender> Fs = new ArrayList<>();
|
||||
private HashSet<CommandSender> Fs = new HashSet<>();
|
||||
private UnlolCommand command;
|
||||
private TBMCSystemChatEvent.BroadcastTarget unlolTarget;
|
||||
private TBMCSystemChatEvent.BroadcastTarget fTarget;
|
||||
|
||||
/**
|
||||
* The strings that count as laughs, see unlol.
|
||||
*/
|
||||
private ConfigData<String[]> laughStrings() {
|
||||
return getConfig().getData("laughStrings", () -> new String[]{"xd", "lel", "lawl", "kek", "lmao", "hue", "hah", "rofl"});
|
||||
}
|
||||
|
||||
/**
|
||||
* The "Press F to pay respects" meme in Minecraft. It will randomly appear on player death and keep track of how many "F"s are said in chat.
|
||||
* You can hover over a player's name to see their respect.
|
||||
*/
|
||||
private ConfigData<Boolean> respect() {
|
||||
return getConfig().getData("respect", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an inside joke on our server.
|
||||
* It keeps track of laughs (lols and what's defined in laughStrings) and if someone does /unlol or /unlaugh it will unlaugh the last person who laughed.
|
||||
* Which also blinds the laughing person for a few seconds. This action can only be performed once per laugh.
|
||||
*/
|
||||
private ConfigData<Boolean> unlol() {
|
||||
return getConfig().getData("unlol", true);
|
||||
}
|
||||
|
@ -105,7 +120,7 @@ public class FunComponent extends Component<PluginMain> implements Listener {
|
|||
FPlayer.FCount().set(FPlayer.FCount().get() + Fs.size());
|
||||
TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, Channel.RecipientTestResult.ALL,
|
||||
"§b" + Fs.size() + " " + (Fs.size() == 1 ? "person" : "people")
|
||||
+ " paid their respects.§r", fTarget);
|
||||
+ " paid their respects.§r", fTarget);
|
||||
Fs.clear();
|
||||
}
|
||||
};
|
||||
|
@ -119,9 +134,10 @@ public class FunComponent extends Component<PluginMain> implements Listener {
|
|||
FPlayer.FDeaths().set(FPlayer.FDeaths().get() + 1);
|
||||
TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, Channel.RecipientTestResult.ALL,
|
||||
"§bPress F to pay respects.§r", fTarget);
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(PluginMain.Instance, tt, 15 * 20);
|
||||
Ftask = Bukkit.getScheduler().runTaskLaterAsynchronously(PluginMain.Instance, tt, 15 * 20);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerLeave(PlayerQuitEvent event) {
|
||||
if (unlol().get())
|
||||
|
|
|
@ -6,7 +6,6 @@ import buttondevteam.chat.components.towny.TownyComponent;
|
|||
import buttondevteam.lib.chat.Color;
|
||||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.OptionallyPlayerCommandClass;
|
||||
import com.palmergames.bukkit.towny.object.Resident;
|
||||
import com.palmergames.bukkit.towny.object.Town;
|
||||
import org.bukkit.ChatColor;
|
||||
|
@ -16,7 +15,6 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@OptionallyPlayerCommandClass(playerOnly = true)
|
||||
@CommandClass(helpText = {
|
||||
"Name color", //
|
||||
"This command allows you to set how the town colors look on your name.", //
|
||||
|
|
|
@ -5,7 +5,6 @@ import buttondevteam.chat.components.towny.TownyComponent;
|
|||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.OptionallyPlayerCommandClass;
|
||||
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException;
|
||||
import com.palmergames.bukkit.towny.object.Nation;
|
||||
import com.palmergames.bukkit.towny.object.Resident;
|
||||
|
@ -17,7 +16,6 @@ import org.bukkit.entity.Player;
|
|||
"Each town in the nation will have it's first color (border) set to this color.", //
|
||||
"See the help text for /u towncolor for more details.", //
|
||||
})
|
||||
@OptionallyPlayerCommandClass(playerOnly = true)
|
||||
public class NationColorCommand extends UCommandBase {
|
||||
@Command2.Subcommand
|
||||
public boolean def(Player player, String color) {
|
||||
|
|
|
@ -5,7 +5,6 @@ import buttondevteam.chat.components.towny.TownyComponent;
|
|||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.OptionallyPlayerCommandClass;
|
||||
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException;
|
||||
import com.palmergames.bukkit.towny.object.Resident;
|
||||
import com.palmergames.bukkit.towny.object.Town;
|
||||
|
@ -21,7 +20,6 @@ import java.lang.reflect.Method;
|
|||
"The town will be shown with this color on Dynmap and all players in the town will appear in chat with these colors.", //
|
||||
"The colors will split the name evenly but residents can override that with /u ncolor.", //
|
||||
}) // TODO: /u u when annotation not present
|
||||
@OptionallyPlayerCommandClass(playerOnly = true)
|
||||
@RequiredArgsConstructor
|
||||
public class TownColorCommand extends UCommandBase {
|
||||
private final TownColorComponent component;
|
||||
|
|
|
@ -23,8 +23,8 @@ import org.bukkit.configuration.file.YamlConfiguration;
|
|||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.dynmap.towny.DTBridge;
|
||||
import org.dynmap.towny.DynmapTownyPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
@ -34,6 +34,10 @@ import java.util.function.Consumer;
|
|||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Town colors for Towny. It allows mayors and kings to set a color for their town/nation (nation can be disabled).
|
||||
* This color is applied to the player names in chat and on Dynmap, if used.
|
||||
*/
|
||||
@ComponentMetadata(depends = TownyComponent.class)
|
||||
public class TownColorComponent extends Component<PluginMain> implements Listener {
|
||||
/**
|
||||
|
@ -45,10 +49,17 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
|
|||
*/
|
||||
public static Map<String, Color> NationColor = new HashMap<>();
|
||||
|
||||
/**
|
||||
* The amount of town colors allowed. If more than one is used, players can change how many letters to be in a specific color using /u ncolor.
|
||||
*/
|
||||
public ConfigData<Byte> colorCount() {
|
||||
return getConfig().getData("colorCount", (byte) 1, cc -> ((Integer) cc).byteValue(), Byte::intValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* If enabled, players will have a nation-defined color in addition to town colors, white by default.
|
||||
* They can change how much of each color they want with this as well.
|
||||
*/
|
||||
public ConfigData<Boolean> useNationColors() {
|
||||
return getConfig().getData("useNationColors", true);
|
||||
}
|
||||
|
@ -60,7 +71,6 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
|
|||
@Override
|
||||
protected void enable() {
|
||||
component = this;
|
||||
//TODO: Don't register all commands automatically (welp)
|
||||
Consumer<ConfigurationSection> loadTC = cs -> TownColorComponent.TownColors.putAll(cs.getValues(true).entrySet().stream()
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, v -> ((List<String>) v.getValue()).stream()
|
||||
.map(Color::valueOf).toArray(Color[]::new))));
|
||||
|
@ -85,25 +95,7 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
|
|||
if (usenc)
|
||||
NationColor.keySet().removeIf(n -> !TownyComponent.TU.getNationsMap().containsKey(n)); // Removes nation colors for deleted/renamed nations
|
||||
|
||||
Bukkit.getScheduler().runTask(getPlugin(), () -> {
|
||||
val dtp = (DynmapTownyPlugin) Bukkit.getPluginManager().getPlugin("Dynmap-Towny");
|
||||
if (dtp == null)
|
||||
return;
|
||||
for (val entry : TownColors.entrySet()) {
|
||||
try {
|
||||
val town = TownyComponent.TU.getTownsMap().get(entry.getKey());
|
||||
Nation nation;
|
||||
Color nc;
|
||||
if (!useNationColors().get())
|
||||
nc = null;
|
||||
else if (!town.hasNation() || (nation = town.getNation()) == null || (nc = NationColor.get(nation.getName().toLowerCase())) == null)
|
||||
nc = Color.White;
|
||||
setTownColor(dtp, buttondevteam.chat.components.towncolors.admin.TownColorCommand.getTownNameCased(entry.getKey()), entry.getValue(), nc);
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Error while setting town color for town " + entry.getKey() + "!", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
initDynmap();
|
||||
|
||||
registerCommand(new TownColorCommand(this));
|
||||
if (useNationColors().get())
|
||||
|
@ -126,6 +118,28 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
|
|||
v -> v.getValue().toString())));
|
||||
}
|
||||
|
||||
private void initDynmap() {
|
||||
Bukkit.getScheduler().runTask(getPlugin(), () -> {
|
||||
val dtp = Bukkit.getPluginManager().getPlugin("Dynmap-Towny");
|
||||
if (dtp == null)
|
||||
return;
|
||||
for (val entry : TownColors.entrySet()) {
|
||||
try {
|
||||
val town = TownyComponent.TU.getTownsMap().get(entry.getKey());
|
||||
Nation nation;
|
||||
Color nc;
|
||||
if (!useNationColors().get())
|
||||
nc = null;
|
||||
else if (!town.hasNation() || (nation = town.getNation()) == null || (nc = NationColor.get(nation.getName().toLowerCase())) == null)
|
||||
nc = Color.White;
|
||||
setTownColor(dtp, buttondevteam.chat.components.towncolors.admin.TownColorCommand.getTownNameCased(entry.getKey()), entry.getValue(), nc);
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Error while setting town color for town " + entry.getKey() + "!", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a town's color on Dynmap.
|
||||
*
|
||||
|
@ -133,8 +147,7 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
|
|||
* @param town The town's name using the correct casing
|
||||
* @param colors The town's colors
|
||||
*/
|
||||
|
||||
public static void setTownColor(DynmapTownyPlugin dtp, String town, Color[] colors, Color nationcolor) {
|
||||
public static void setTownColor(Plugin dtp, String town, Color[] colors, Color nationcolor) {
|
||||
Function<Color, Integer> c2i = c -> c.getRed() << 16 | c.getGreen() << 8 | c.getBlue();
|
||||
try {
|
||||
DTBridge.setTownColor(dtp, town, c2i.apply(nationcolor == null ? colors[0] : nationcolor),
|
||||
|
|
|
@ -11,7 +11,6 @@ import com.palmergames.bukkit.towny.object.Town;
|
|||
import lombok.val;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.dynmap.towny.DynmapTownyPlugin;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
@ -39,52 +38,52 @@ public class TownColorCommand extends AdminCommandBase { //TODO: Command path al
|
|||
Color[] clrs = new Color[colors.length];
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
val c = getColorOrSendError(colors[i], sender);
|
||||
if (!c.isPresent())
|
||||
return true;
|
||||
if (!c.isPresent())
|
||||
return true;
|
||||
clrs[i] = c.get();
|
||||
}
|
||||
Color tnc;
|
||||
boolean usenc = TownColorComponent.getComponent().useNationColors().get();
|
||||
if (usenc) {
|
||||
try {
|
||||
tnc = TownColorComponent.NationColor.get(town.getNation().getName().toLowerCase());
|
||||
} catch (Exception e) {
|
||||
tnc = null;
|
||||
}
|
||||
if (tnc == null) tnc = Color.White; //Default nation color - TODO: Make configurable
|
||||
} else tnc = null;
|
||||
for (Map.Entry<String, Color[]> other : TownColorComponent.TownColors.entrySet()) {
|
||||
Color nc;
|
||||
if (usenc) {
|
||||
try {
|
||||
nc = TownColorComponent.NationColor.get(TownyComponent.TU.getTownsMap().get(other.getKey()).getNation().getName().toLowerCase());
|
||||
} catch (Exception e) { //Too lazy for lots of null-checks and it may throw exceptions anyways
|
||||
nc = null;
|
||||
}
|
||||
if (nc == null) nc = Color.White; //Default nation color
|
||||
} else nc = null;
|
||||
if (!usenc || nc.getName().equals(tnc.getName())) {
|
||||
int C = 0;
|
||||
if (clrs.length == other.getValue().length)
|
||||
for (int i = 0; i < clrs.length; i++)
|
||||
if (clrs[i].getName().equals(other.getValue()[i].getName()))
|
||||
C++;
|
||||
else break;
|
||||
if (C == clrs.length) {
|
||||
sender.sendMessage("§cThis town color combination is already used!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Color tnc;
|
||||
boolean usenc = TownColorComponent.getComponent().useNationColors().get();
|
||||
if (usenc) {
|
||||
try {
|
||||
tnc = TownColorComponent.NationColor.get(town.getNation().getName().toLowerCase());
|
||||
} catch (Exception e) {
|
||||
tnc = null;
|
||||
}
|
||||
if (tnc == null) tnc = Color.White; //Default nation color - TODO: Make configurable
|
||||
} else tnc = null;
|
||||
for (Map.Entry<String, Color[]> other : TownColorComponent.TownColors.entrySet()) {
|
||||
Color nc;
|
||||
if (usenc) {
|
||||
try {
|
||||
nc = TownColorComponent.NationColor.get(TownyComponent.TU.getTownsMap().get(other.getKey()).getNation().getName().toLowerCase());
|
||||
} catch (Exception e) { //Too lazy for lots of null-checks and it may throw exceptions anyways
|
||||
nc = null;
|
||||
}
|
||||
if (nc == null) nc = Color.White; //Default nation color
|
||||
} else nc = null;
|
||||
if (!usenc || nc.getName().equals(tnc.getName())) {
|
||||
int C = 0;
|
||||
if (clrs.length == other.getValue().length)
|
||||
for (int i = 0; i < clrs.length; i++)
|
||||
if (clrs[i].getName().equals(other.getValue()[i].getName()))
|
||||
C++;
|
||||
else break;
|
||||
if (C == clrs.length) {
|
||||
sender.sendMessage("§cThis town color combination is already used!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
TownColorComponent.TownColors.put(town.getName().toLowerCase(), clrs);
|
||||
TownyListener.updateTownMembers(town);
|
||||
|
||||
val dtp = (DynmapTownyPlugin) Bukkit.getPluginManager().getPlugin("Dynmap-Towny");
|
||||
val dtp = Bukkit.getPluginManager().getPlugin("Dynmap-Towny");
|
||||
if (dtp != null) //If it's not found then it's not loaded, it'll be noticed by the admins if needed
|
||||
TownColorComponent.setTownColor(dtp, town.getName(), clrs, tnc);
|
||||
sender.sendMessage("§bColor(s) set.");
|
||||
return true;
|
||||
}
|
||||
sender.sendMessage("§bColor(s) set.");
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Optional<Color> getColorOrSendError(String name, CommandSender sender) {
|
||||
val c = Arrays.stream(Color.values()).skip(1).filter(cc -> cc.getName().equalsIgnoreCase(name)).findAny();
|
||||
|
@ -102,5 +101,5 @@ public class TownColorCommand extends AdminCommandBase { //TODO: Command path al
|
|||
|
||||
public static String getTownNameCased(String name) {
|
||||
return TownyComponent.TU.getTownsMap().get(name.toLowerCase()).getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,10 @@ import java.util.Optional;
|
|||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* This component manages the town and nation chat. It's also needed for the TownColorComponent.
|
||||
* It provides the TC and NC channels, and posts Towny messages (global, town, nation) to the correct channels for other platforms like Discord.
|
||||
*/
|
||||
public class TownyComponent extends Component<PluginMain> {
|
||||
public static TownyUniverse TU;
|
||||
private static ArrayList<String> Towns;
|
||||
|
|
|
@ -57,7 +57,8 @@ public class PlayerJoinLeaveListener implements Listener {
|
|||
nwithoutformatting = p.getName();
|
||||
PlayerListener.nicknames.forcePut(nwithoutformatting.toLowerCase(), p.getUniqueId()); //TODO: FormatterComponent
|
||||
|
||||
HistoryCommand.showHistory(e.getPlayer(), null);
|
||||
if (PluginMain.Instance.storeChatHistory().get())
|
||||
HistoryCommand.showHistory(e.getPlayer(), null);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
|
|
@ -161,6 +161,8 @@ public class PlayerListener implements Listener {
|
|||
}
|
||||
}
|
||||
|
||||
private long lastError = 0;
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerTBMCChat(TBMCChatEvent e) {
|
||||
try {
|
||||
|
@ -169,6 +171,13 @@ public class PlayerListener implements Listener {
|
|||
HistoryCommand.addChatMessage(e.getCm(), e.getChannel());
|
||||
e.setCancelled(FormatterComponent.handleChat(e));
|
||||
} catch (NoClassDefFoundError | Exception ex) { // Weird things can happen
|
||||
if (lastError < System.nanoTime() - 1000L * 1000L * 1000L * 60 * 60 //60 mins
|
||||
&& Bukkit.getOnlinePlayers().size() > 0) { //If there are no players on, display to the first person
|
||||
lastError = System.nanoTime(); //I put the whole thing in the if to protect against race conditions
|
||||
for (Player p : Bukkit.getOnlinePlayers())
|
||||
if (e.shouldSendTo(p))
|
||||
p.sendMessage("[" + e.getChannel().DisplayName().get() + "] §cSome features in the message below might be unavailable due to an error.");
|
||||
}
|
||||
ChatUtils.sendChatMessage(e, s -> "§c!§r" + s);
|
||||
TBMCCoreAPI.SendException("An error occured while processing a chat message!", ex);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.dynmap.towny;
|
|||
import lombok.val;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.dynmap.bukkit.DynmapPlugin;
|
||||
import org.dynmap.markers.MarkerAPI;
|
||||
|
||||
|
@ -14,32 +15,27 @@ import java.util.Map;
|
|||
public class DTBridge {
|
||||
/**
|
||||
* Sets the town color on Dynmap.
|
||||
*
|
||||
* @param dtp
|
||||
* The Dynmap-Towny plugin
|
||||
* @param townname
|
||||
* The name of the town, using correct casing
|
||||
* @param strokecolor
|
||||
* The stroke color in RGB format
|
||||
* @param fillcolor
|
||||
* The fill color in RGB format
|
||||
* @throws Exception
|
||||
* When couldn't set the town color
|
||||
*
|
||||
* @param dtp The Dynmap-Towny plugin
|
||||
* @param townname The name of the town, using correct casing
|
||||
* @param strokecolor The stroke color in RGB format
|
||||
* @param fillcolor The fill color in RGB format
|
||||
* @throws Exception When couldn't set the town color
|
||||
*/
|
||||
public static void setTownColor(DynmapTownyPlugin dtp, String townname, int strokecolor, int fillcolor)
|
||||
throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, // Keeping these because why not
|
||||
IllegalAccessException, NoSuchMethodException, InstantiationException, InvocationTargetException {
|
||||
public static void setTownColor(Plugin dtp, String townname, int strokecolor, int fillcolor)
|
||||
throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, // Keeping these because why not
|
||||
IllegalAccessException, NoSuchMethodException, InstantiationException, InvocationTargetException {
|
||||
Class<?> cl = Class.forName(DynmapTownyPlugin.class.getName() + "$AreaStyle");
|
||||
Field field = DynmapTownyPlugin.class.getDeclaredField("cusstyle");
|
||||
field.setAccessible(true); // Doesn't allow accessing it from the same package, if it's from a different plugin
|
||||
field.setAccessible(true); // Doesn't allow accessing it from the same package, if it's from a different plugin
|
||||
@SuppressWarnings("unchecked")
|
||||
val map = (Map<String, Object>) field.get(dtp);
|
||||
Object style = map.get(townname);
|
||||
if (style == null) {
|
||||
Constructor<?> c = cl.getDeclaredConstructor(FileConfiguration.class, String.class, MarkerAPI.class);
|
||||
c.setAccessible(true);
|
||||
style = c.newInstance(dtp.getConfig(), "custstyle." + townname,
|
||||
((DynmapPlugin) Bukkit.getPluginManager().getPlugin("dynmap")).getMarkerAPI());
|
||||
style = c.newInstance(dtp.getConfig(), "custstyle." + townname,
|
||||
((DynmapPlugin) Bukkit.getPluginManager().getPlugin("dynmap")).getMarkerAPI());
|
||||
map.put(townname, style);
|
||||
}
|
||||
set(cl, style, "fillcolor", fillcolor);
|
||||
|
@ -47,7 +43,7 @@ public class DTBridge {
|
|||
}
|
||||
|
||||
private static <T> void set(Class<?> cl, Object style, String fieldname, T value)
|
||||
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||
Field field = cl.getDeclaredField(fieldname);
|
||||
field.setAccessible(true);
|
||||
field.set(style, value);
|
||||
|
|
|
@ -40,10 +40,6 @@ soft-depend:
|
|||
- Dynmap-Towny
|
||||
- Towny
|
||||
permissions:
|
||||
tbmc.admin:
|
||||
description: Gives access to /un- commands and /u admin commands
|
||||
tbmc.rainbow:
|
||||
description: Gives access to rainbow colors (/u c).
|
||||
tbmc.badge.gold:
|
||||
description: Gives a patron badge.
|
||||
default: false
|
||||
|
|
|
@ -37,36 +37,41 @@ public class ChatFormatIT {
|
|||
list.add(new ChatFormatIT(sender, "*test*", new TellrawPart("test").setItalic(true).setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "**test**", new TellrawPart("test").setBold(true).setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "***test***",
|
||||
new TellrawPart("test").setBold(true).setItalic(true).setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "***_test_***",
|
||||
new TellrawPart("test").setBold(true).setItalic(true).setUnderlined(true).setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "***_~~test~~_***", new TellrawPart("test").setBold(true).setItalic(true)
|
||||
.setUnderlined(true).setStrikethrough(true).setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "¯\\\\\\_(ツ)\\_/¯", new TellrawPart("¯\\_(ツ)_/¯").setColor(Color.White)));
|
||||
new TellrawPart("test").setBold(true).setItalic(true).setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "***__test__***",
|
||||
new TellrawPart("test").setBold(true).setItalic(true).setUnderlined(true).setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "***__~~test~~__***", new TellrawPart("test").setBold(true).setItalic(true)
|
||||
.setUnderlined(true).setStrikethrough(true).setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "¯\\\\\\_(ツ)\\_/¯", new TellrawPart("¯\\_(ツ)_/¯").setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "https://google.hu/",
|
||||
new TellrawPart("https://google.hu/").setColor(Color.White).setUnderlined(true)
|
||||
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT,
|
||||
new TellrawPart("Click to open").setColor(Color.Blue)))
|
||||
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://google.hu/"))));
|
||||
list.add(new ChatFormatIT(sender, "*test", new TellrawPart("*test").setColor(Color.White)));
|
||||
new TellrawPart("https://google.hu/").setColor(Color.White).setUnderlined(true)
|
||||
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT,
|
||||
new TellrawPart("Click to open").setColor(Color.Blue)))
|
||||
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://google.hu/"))));
|
||||
list.add(new ChatFormatIT(sender, "*test", new TellrawPart("*test").setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "**test*", new TellrawPart("**test*").setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "***test", new TellrawPart("***test").setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "Koiiev", new TellrawPart("§bKoiiev§r").setColor(Color.Aqua)));
|
||||
list.add(new ChatFormatIT(sender, "Koiiev", new TellrawPart("§bKoiiev§r").setColor(Color.Aqua)));
|
||||
list.add(new ChatFormatIT(sender, "norbipeti", new TellrawPart("§bNorbiPeti§r").setColor(Color.Aqua)));
|
||||
list.add(new ChatFormatIT(sender, "Arsen_Derby_FTW", new TellrawPart("§bArsen_Derby_FTW§r").setColor(Color.Aqua)));
|
||||
list.add(new ChatFormatIT(sender, "Arsen_Derby_FTW", new TellrawPart("§bArsen_Derby_FTW§r").setColor(Color.Aqua)));
|
||||
list.add(new ChatFormatIT(sender, "carrot_lynx", new TellrawPart("§bcarrot_lynx§r").setColor(Color.Aqua)));
|
||||
list.add(new ChatFormatIT(sender, "*carrot_lynx*", new TellrawPart("§bcarrot_lynx§r").setItalic(true).setColor(Color.Aqua)));
|
||||
list.add(new ChatFormatIT(sender, "https://norbipeti.github.io/", new TellrawPart("https://norbipeti.github.io/")
|
||||
.setColor(Color.White).setUnderlined(true)
|
||||
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT,
|
||||
new TellrawPart("Click to open").setColor(Color.Blue)))
|
||||
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/"))));
|
||||
.setColor(Color.White).setUnderlined(true)
|
||||
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT,
|
||||
new TellrawPart("Click to open").setColor(Color.Blue)))
|
||||
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/"))));
|
||||
list.add(new ChatFormatIT(sender, "*https://norbipeti.github.io/ heh*", new TellrawPart("https://norbipeti.github.io/").setItalic(true).setUnderlined(true)
|
||||
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT,
|
||||
new TellrawPart("Click to open").setColor(Color.Blue)))
|
||||
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/")), new TellrawPart(" heh").setItalic(true)));
|
||||
list.add(new ChatFormatIT(sender, "*test _test_ test*", new TellrawPart("test ").setItalic(true).setColor(Color.White),
|
||||
new TellrawPart("test").setItalic(true).setUnderlined(true).setColor(Color.White), new TellrawPart(" test").setItalic(true).setColor(Color.White)));
|
||||
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT,
|
||||
new TellrawPart("Click to open").setColor(Color.Blue)))
|
||||
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/")), new TellrawPart(" heh").setItalic(true)));
|
||||
list.add(new ChatFormatIT(sender, "*test _test_ test*", new TellrawPart("test test test").setItalic(true).setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "*test __test__ test*", new TellrawPart("test ").setItalic(true).setColor(Color.White),
|
||||
new TellrawPart("test").setItalic(true).setUnderlined(true).setColor(Color.White), new TellrawPart(" test").setItalic(true).setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "**test __test__ test**", new TellrawPart("test ").setBold(true).setColor(Color.White),
|
||||
new TellrawPart("test").setBold(true).setUnderlined(true).setColor(Color.White), new TellrawPart(" test").setBold(true).setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "**test _test_ test**", new TellrawPart("test ").setBold(true).setColor(Color.White),
|
||||
new TellrawPart("test").setItalic(true).setBold(true).setColor(Color.White), new TellrawPart(" test").setBold(true).setColor(Color.White)));
|
||||
list.add(new ChatFormatIT(sender, "https://norbipeti.github.io/test?test&test#test", new TellrawPart("https://norbipeti.github.io/test?test&test#test")
|
||||
.setColor(Color.White).setUnderlined(true)
|
||||
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT,
|
||||
|
@ -77,6 +82,11 @@ public class ChatFormatIT {
|
|||
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT,
|
||||
new TellrawPart("Click to open").setColor(Color.Blue)))
|
||||
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/test"))));
|
||||
TellrawPart space = new TellrawPart(" ").setColor(Color.White);
|
||||
list.add(new ChatFormatIT(sender, "A rainbow text for testing. O", new TellrawPart("A").setColor(Color.Red),
|
||||
space, new TellrawPart("rainbow").setColor(Color.Gold), space, new TellrawPart("text").setColor(Color.Yellow),
|
||||
space, new TellrawPart("for").setColor(Color.Green), space, new TellrawPart("testing.").setColor(Color.Blue),
|
||||
space, new TellrawPart("O").setColor(Color.DarkPurple)).setRainbowMode());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
@ -84,6 +94,7 @@ public class ChatFormatIT {
|
|||
private final CommandSender sender;
|
||||
private final String message;
|
||||
private final TellrawPart[] extras;
|
||||
private boolean rainbowMode;
|
||||
|
||||
public ChatFormatIT(CommandSender sender, String message, TellrawPart... expectedextras) {
|
||||
this.sender = sender;
|
||||
|
@ -91,10 +102,17 @@ public class ChatFormatIT {
|
|||
this.extras = expectedextras;
|
||||
}
|
||||
|
||||
private ChatFormatIT setRainbowMode() {
|
||||
rainbowMode = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessage() {
|
||||
ArrayList<ChatFormatter> cfs = ChatProcessing.addFormatters(Color.White, p -> true);
|
||||
ArrayList<ChatFormatter> cfs = ChatProcessing.addFormatters(Color.White, p -> true, null);
|
||||
final String chid = ChatProcessing.getChannelID(Channel.GlobalChat, ChatUtils.MCORIGIN);
|
||||
if (rainbowMode)
|
||||
ChatProcessing.createRPC(Color.White, cfs);
|
||||
final TellrawPart tp = ChatProcessing.createTellraw(sender, message, null, null, null, chid, ChatUtils.MCORIGIN);
|
||||
ChatFormatter.Combine(cfs, message, tp, null);
|
||||
System.out.println("Testing: " + message);
|
||||
|
|
Loading…
Reference in a new issue