Merge pull request #96 from TBMCPlugins/dev

Towny event broadcasting to Discord and masked links
This commit is contained in:
Norbi Peti 2019-01-20 22:39:53 +01:00 committed by GitHub
commit d0e4447126
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 2462 additions and 2394 deletions

542
pom.xml
View file

@ -1,263 +1,281 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
<name>The Button Minecraft Chat Plugin</name> <name>The Button Minecraft Chat Plugin</name>
<description>The Button Minecraft Chat Plugin</description> <description>The Button Minecraft Chat Plugin</description>
<build> <build>
<sourceDirectory>src/main/java</sourceDirectory> <sourceDirectory>src/main/java</sourceDirectory>
<resources> <resources>
<resource> <resource>
<directory>src</directory> <directory>src</directory>
<excludes> <excludes>
<exclude>**/*.java</exclude> <exclude>**/*.java</exclude>
</excludes> </excludes>
</resource> </resource>
<resource> <resource>
<directory>src/main/resources</directory> <directory>src/main/resources</directory>
<includes> <includes>
<include>*.properties</include> <include>*.properties</include>
<include>*.yml</include> <include>*.yml</include>
<include>*.csv</include> <include>*.csv</include>
<include>*.txt</include> <include>*.txt</include>
</includes> </includes>
<filtering>true</filtering> <filtering>true</filtering>
</resource> </resource>
</resources> </resources>
<finalName>ButtonChat</finalName> <finalName>ButtonChat</finalName>
<plugins> <plugins>
<plugin> <plugin>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version> <version>3.3</version>
<configuration> <configuration>
<source>1.8</source> <source>1.8</source>
<target>1.8</target> <target>1.8</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>2.4.2</version> <version>2.4.2</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
<goals> <goals>
<goal>shade</goal> <goal>shade</goal>
</goals> </goals>
<configuration> <configuration>
<artifactSet> <artifactSet>
<includes> <includes>
<include>net.sourceforge.htmlcleaner:htmlcleaner</include> <include>net.sourceforge.htmlcleaner:htmlcleaner</include>
<include>org.javassist:javassist</include> <include>org.javassist:javassist</include>
</includes> </includes>
</artifactSet> </artifactSet>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId> <artifactId>maven-resources-plugin</artifactId>
<version>3.0.1</version> <version>3.0.1</version>
<executions> <executions>
<execution> <execution>
<id>copy</id> <id>copy</id>
<phase>compile</phase> <phase>compile</phase>
<goals> <goals>
<goal>copy-resources</goal> <goal>copy-resources</goal>
</goals> </goals>
<configuration> <configuration>
<outputDirectory>target</outputDirectory> <outputDirectory>target</outputDirectory>
<resources> <resources>
<resource> <resource>
<directory>resources</directory> <directory>resources</directory>
</resource> </resource>
</resources> </resources>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId> <artifactId>maven-failsafe-plugin</artifactId>
<version>2.12.4</version> <version>2.12.4</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
<goal>integration-test</goal> <goal>integration-test</goal>
<goal>verify</goal> <goal>verify</goal>
</goals> </goals>
<phase>test</phase> <phase>test</phase>
</execution> </execution>
</executions> </executions>
<configuration> <configuration>
<testFailureIgnore>true</testFailureIgnore> <testFailureIgnore>true</testFailureIgnore>
<useSystemClassLoader>false <useSystemClassLoader>false
</useSystemClassLoader> <!-- https://stackoverflow.com/a/53012553/2703239 --> </useSystemClassLoader> <!-- https://stackoverflow.com/a/53012553/2703239 -->
</configuration> </configuration>
</plugin> </plugin>
<!-- <plugin> <!-- <plugin>
<groupId>pl.project13.maven</groupId> <groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId> <artifactId>git-commit-id-plugin</artifactId>
<version>2.2.5</version> <version>2.2.5</version>
<executions> <executions>
<execution> <execution>
<id>get-the-git-infos</id> <id>get-the-git-infos</id>
<goals> <goals>
<goal>revision</goal> <goal>revision</goal>
</goals> </goals>
*NOTE*: The default phase of revision is initialize, but in case you want to change it, you can do so by adding the phase here *NOTE*: The default phase of revision is initialize, but in case you want to change it, you can do so by adding the phase here
<phase>initialize</phase> <phase>initialize</phase>
<configuration> <configuration>
<injectAllReactorProjects>true</injectAllReactorProjects> <injectAllReactorProjects>true</injectAllReactorProjects>
</configuration> </configuration>
</execution> </execution>
<execution> <execution>
<id>validate-the-git-infos</id> <id>validate-the-git-infos</id>
<goals> <goals>
<goal>validateRevision</goal> <goal>validateRevision</goal>
</goals> </goals>
*NOTE*: The default phase of validateRevision is verify, but in case you want to change it, you can do so by adding the phase here *NOTE*: The default phase of validateRevision is verify, but in case you want to change it, you can do so by adding the phase here
<phase>package</phase> <phase>package</phase>
<configuration> <configuration>
<validationProperties> <validationProperties>
- <validationProperty> - <validationProperty>
<name>validating git dirty</name> <name>validating git dirty</name>
<value>${git.branch}</value> <value>${git.branch}</value>
<shouldMatchTo>dev</shouldMatchTo> <shouldMatchTo>dev</shouldMatchTo>
</validationProperty> - </validationProperty> -
</validationProperties> </validationProperties>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
<configuration> <configuration>
<injectAllReactorProjects>true</injectAllReactorProjects> <injectAllReactorProjects>true</injectAllReactorProjects>
<verbose>true</verbose> <verbose>true</verbose>
<dotGitDirectory>${project.basedir}/.git</dotGitDirectory> <dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
</configuration> </configuration>
</plugin> --> </plugin> -->
<!-- <plugin> <groupId>org.basepom.maven</groupId> <artifactId>duplicate-finder-maven-plugin</artifactId> <!-- <plugin> <groupId>org.basepom.maven</groupId> <artifactId>duplicate-finder-maven-plugin</artifactId>
<version>1.2.1</version> <executions> <execution> <goals> <goal>check</goal> <version>1.2.1</version> <executions> <execution> <goals> <goal>check</goal>
</goals> </execution> </executions> </plugin> --> </goals> </execution> </executions> </plugin> -->
</plugins> </plugins>
</build> </build>
<groupId>buttondevteam</groupId> <groupId>buttondevteam</groupId>
<repositories> <repositories>
<repository> <repository>
<id>spigot-repo</id> <id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url> <url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository> </repository>
<repository> <repository>
<id>jitpack</id> <id>jitpack</id>
<url>https://jitpack.io/</url> <url>https://jitpack.io/</url>
</repository> </repository>
<repository> <repository>
<id>Essentials</id> <id>Essentials</id>
<url>http://repo.ess3.net/content/repositories/essrel/</url> <url>http://repo.ess3.net/content/repositories/essrel/</url>
</repository> </repository>
<repository> <repository>
<id>Votifier</id> <id>Votifier</id>
<url>https://dl.bintray.com/nuvotifier/maven/</url> <url>https://dl.bintray.com/nuvotifier/maven/</url>
</repository> </repository>
<repository> <repository>
<id>Minigames</id> <id>Minigames</id>
<url>http://maven.addstar.com.au/artifactory/release</url> <url>http://maven.addstar.com.au/artifactory/release</url>
</repository> </repository>
<repository> <repository>
<id>vault-repo</id> <id>vault-repo</id>
<url>http://nexus.hc.to/content/repositories/pub_releases</url> <url>http://nexus.hc.to/content/repositories/pub_releases</url>
</repository> </repository>
<!-- <repository> <id>WorldEdit</id> <url>http://maven.sk89q.com/artifactory/repo</url> <!-- <repository> <id>WorldEdit</id> <url>http://maven.sk89q.com/artifactory/repo</url>
</repository> --> </repository> -->
<repository> <repository>
<id>projectlombok.org</id> <id>projectlombok.org</id>
<url>http://projectlombok.org/mavenrepo</url> <url>http://projectlombok.org/mavenrepo</url>
</repository> </repository>
</repositories> </repositories>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId> <artifactId>spigot-api</artifactId>
<version>1.12.2-R0.1-SNAPSHOT</version> <version>1.12.2-R0.1-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.TBMCPlugins.ButtonCore</groupId> <groupId>com.github.TBMCPlugins.ButtonCore</groupId>
<artifactId>ButtonCore</artifactId> <artifactId>ButtonCore</artifactId>
<version>${env.TRAVIS_BRANCH}-SNAPSHOT</version> <version>${branch}-SNAPSHOT</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/net.sourceforge.htmlcleaner/htmlcleaner --> <!-- https://mvnrepository.com/artifact/net.sourceforge.htmlcleaner/htmlcleaner -->
<dependency> <dependency>
<groupId>net.sourceforge.htmlcleaner</groupId> <groupId>net.sourceforge.htmlcleaner</groupId>
<artifactId>htmlcleaner</artifactId> <artifactId>htmlcleaner</artifactId>
<version>2.16</version> <version>2.16</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.reflections/reflections --> <!-- https://mvnrepository.com/artifact/org.reflections/reflections -->
<dependency> <dependency>
<groupId>org.reflections</groupId> <groupId>org.reflections</groupId>
<artifactId>reflections</artifactId> <artifactId>reflections</artifactId>
<version>0.9.10</version> <version>0.9.10</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.ess3</groupId> <groupId>net.ess3</groupId>
<artifactId>Essentials</artifactId> <artifactId>Essentials</artifactId>
<version>2.13.1</version> <version>2.13.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.TBMCPlugins.ButtonCore</groupId> <groupId>com.github.TBMCPlugins.ButtonCore</groupId>
<artifactId>Towny</artifactId> <artifactId>Towny</artifactId>
<version>8d3b6b6</version> <version>8d3b6b6</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.vexsoftware</groupId> <groupId>com.vexsoftware</groupId>
<artifactId>nuvotifier-universal</artifactId> <artifactId>nuvotifier-universal</artifactId>
<version>2.3.4</version> <version>2.3.4</version>
</dependency> </dependency>
<!-- <dependency> <groupId>au.com.mineauz</groupId> <artifactId>Minigames</artifactId> <!-- <dependency> <groupId>au.com.mineauz</groupId> <artifactId>Minigames</artifactId>
<version>1.8.0</version> </dependency> --> <version>1.8.0</version> </dependency> -->
<dependency> <dependency>
<groupId>net.milkbowl.vault</groupId> <groupId>net.milkbowl.vault</groupId>
<artifactId>VaultAPI</artifactId> <artifactId>VaultAPI</artifactId>
<version>1.6</version> <version>1.6</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.16.16</version> <version>1.16.16</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId> <artifactId>spigot</artifactId>
<version>1.12.2-R0.1-SNAPSHOT</version> <version>1.12.2-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.webbukkit</groupId> <groupId>com.github.webbukkit</groupId>
<artifactId>Dynmap-Towny</artifactId> <artifactId>Dynmap-Towny</artifactId>
<version>master-SNAPSHOT</version> <version>master-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.webbukkit</groupId> <groupId>com.github.webbukkit</groupId>
<artifactId>Dynmap</artifactId> <artifactId>Dynmap</artifactId>
<version>v2.5</version> <version>v2.5</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/junit/junit --> <!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.12</version> <version>4.12</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<artifactId>ButtonChat</artifactId> <artifactId>ButtonChat</artifactId>
<organization> <organization>
<name>TBMCPlugins</name> <name>TBMCPlugins</name>
<url>https://github.com/TBMCPlugins</url> <url>https://github.com/TBMCPlugins</url>
</organization> </organization>
<properties> <properties>
<!-- github server corresponds to entry in ~/.m2/settings.xml --> <!-- github server corresponds to entry in ~/.m2/settings.xml -->
<github.global.server>githubo</github.global.server> <github.global.server>githubo</github.global.server>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> <branch>
master
</branch> <!-- Should be master if building ButtonCore locally - the CI will overwrite it (see below) -->
</properties>
<profiles>
<profile>
<id>ci</id>
<activation>
<property>
<name>env.TRAVIS_BRANCH</name>
</property>
</activation>
<properties>
<!-- Override only if necessary -->
<branch>${env.TRAVIS_BRANCH}</branch>
</properties>
</profile>
</profiles>
</project> </project>

View file

@ -1,25 +0,0 @@
package buttondevteam.chat;
import org.bukkit.Bukkit;
public class AnnouncerThread implements Runnable {
private static int AnnounceMessageIndex = 0;
@Override
public void run() {
while (!PluginMain.Instance.stop) {
try {
Thread.sleep(PluginMain.AnnounceTime);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
if (Bukkit.getOnlinePlayers().size() == 0) continue; //Don't post to Discord if nobody is on
if (PluginMain.AnnounceMessages.size() > AnnounceMessageIndex) {
Bukkit.broadcastMessage(PluginMain.AnnounceMessages.get(AnnounceMessageIndex));
AnnounceMessageIndex++;
if (AnnounceMessageIndex == PluginMain.AnnounceMessages.size())
AnnounceMessageIndex = 0;
}
}
}
}

View file

@ -1,135 +1,132 @@
package buttondevteam.chat; package buttondevteam.chat;
import buttondevteam.lib.chat.Color; import buttondevteam.chat.components.flair.FlairStates;
import buttondevteam.lib.player.EnumPlayerData; import buttondevteam.lib.chat.Color;
import buttondevteam.lib.player.PlayerClass; import buttondevteam.lib.player.EnumPlayerData;
import buttondevteam.lib.player.PlayerData; import buttondevteam.lib.player.PlayerClass;
import buttondevteam.lib.player.TBMCPlayerBase; import buttondevteam.lib.player.PlayerData;
import org.bukkit.Bukkit; import buttondevteam.lib.player.TBMCPlayerBase;
import org.bukkit.Location; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@PlayerClass(pluginname = "Button1Chat") @PlayerClass(pluginname = "Button1Chat")
public class ChatPlayer extends TBMCPlayerBase { public class ChatPlayer extends TBMCPlayerBase {
public PlayerData<String> UserName() { public PlayerData<String> UserName() {
return data(null); return data(null);
} }
public List<String> UserNames() { public List<String> UserNames() {
return data(new ArrayList<String>()).get(); return data(new ArrayList<String>()).get();
} }
public PlayerData<Integer> FlairTime() { public PlayerData<Integer> FlairTime() {
return data(FlairTimeNone); return data(FlairTimeNone);
} }
public EnumPlayerData<FlairStates> FlairState() { public EnumPlayerData<FlairStates> FlairState() {
return dataEnum(FlairStates.class, FlairStates.NoComment); return dataEnum(FlairStates.class, FlairStates.NoComment);
} }
public PlayerData<Integer> FCount() { public PlayerData<Integer> FCount() {
return data(0); return data(0);
} }
public PlayerData<Integer> FDeaths() { public PlayerData<Integer> FDeaths() {
return data(0); return data(0);
} }
public PlayerData<Boolean> FlairCheater() { public PlayerData<Boolean> FlairCheater() {
return data(false); return data(false);
} }
public PlayerData<ArrayList<Integer>> NameColorLocations() { // No byte[], no TIntArrayList public PlayerData<ArrayList<Integer>> NameColorLocations() { // No byte[], no TIntArrayList
return data(null); return data(null);
} }
public Location SavedLocation; public boolean Working;
public boolean Working; // public int Tables = 10;
// public int Tables = 10; public boolean RainbowPresserColorMode = false;
public boolean SendingLink = false; public Color OtherColorMode = null;
public boolean RainbowPresserColorMode = false; public boolean ChatOnly = false;
public Color OtherColorMode = null;
public boolean ChatOnly = false; public static final int FlairTimeNonPresser = -1;
public int LoginWarningCount = 0; public static final int FlairTimeCantPress = -2;
public static final int FlairTimeNone = -3;
public static final int FlairTimeNonPresser = -1;
public static final int FlairTimeCantPress = -2; /**
public static final int FlairTimeNone = -3; * Gets the player's flair, optionally formatting for Minecraft.
*
/** * @param noformats
* Gets the player's flair, optionally formatting for Minecraft. * The MC formatting codes will be only applied if false
* * @return The flair
* @param noformats */
* The MC formatting codes will be only applied if false public String GetFormattedFlair(boolean noformats) {
* @return The flair int time = FlairTime().get();
*/ if (time == FlairTimeCantPress)
public String GetFormattedFlair(boolean noformats) { return noformats ? "(can't press)" : "§r(--s)§r";
int time = FlairTime().get(); if (time == FlairTimeNonPresser)
if (time == FlairTimeCantPress) return noformats ? "(non-presser)" : "§7(--s)§r";
return noformats ? "(can't press)" : "§r(--s)§r"; if (time == FlairTimeNone)
if (time == FlairTimeNonPresser) return "";
return noformats ? "(non-presser)" : "§7(--s)§r"; return noformats ? String.format("(%ds)", time) : String.format("§%x(%ds)§r", GetFlairColor(), time);
if (time == FlairTimeNone) }
return "";
return noformats ? String.format("(%ds)", time) : String.format("§%x(%ds)§r", GetFlairColor(), time); /**
} * Gets the player's flair, formatted for Minecraft.
*
/** * @return The flair
* Gets the player's flair, formatted for Minecraft. */
* public String GetFormattedFlair() {
* @return The flair return GetFormattedFlair(false);
*/ }
public String GetFormattedFlair() {
return GetFormattedFlair(false); public void SetFlair(int time) {
} FlairTime().set(time);
FlairUpdate();
public void SetFlair(int time) { }
FlairTime().set(time);
FlairUpdate(); public void SetFlair(int time, boolean cheater) {
} FlairTime().set(time);
FlairCheater().set(cheater);
public void SetFlair(int time, boolean cheater) { FlairUpdate();
FlairTime().set(time); }
FlairCheater().set(cheater);
FlairUpdate(); public void FlairUpdate() {
}
// Flairs from Command Block The Button - Teams
public void FlairUpdate() { // PluginMain.Instance.getServer().getScoreboardManager().getMainScoreboard().getTeams().add()
Player p = Bukkit.getPlayer(uuid);
// Flairs from Command Block The Button - Teams if (p != null)
// PluginMain.Instance.getServer().getScoreboardManager().getMainScoreboard().getTeams().add() p.setPlayerListName(String.format("%s%s", p.getDisplayName(), GetFormattedFlair()));
Player p = Bukkit.getPlayer(uuid); }
if (p != null)
p.setPlayerListName(String.format("%s%s", p.getDisplayName(), GetFormattedFlair())); public short GetFlairColor() {
} if (FlairCheater().get())
return 0x5;
public short GetFlairColor() { final int flairTime = FlairTime().get();
if (FlairCheater().get()) if (flairTime == FlairTimeNonPresser)
return 0x5; return 0x7;
final int flairTime = FlairTime().get(); else if (flairTime == FlairTimeCantPress)
if (flairTime == FlairTimeNonPresser) return 0xf;
return 0x7; else if (flairTime <= 60 && flairTime >= 52)
else if (flairTime == FlairTimeCantPress) return 0x5;
return 0xf; else if (flairTime <= 51 && flairTime >= 42)
else if (flairTime <= 60 && flairTime >= 52) return 0x9;
return 0x5; else if (flairTime <= 41 && flairTime >= 32)
else if (flairTime <= 51 && flairTime >= 42) return 0xa;
return 0x9; else if (flairTime <= 31 && flairTime >= 22)
else if (flairTime <= 41 && flairTime >= 32) return 0xe;
return 0xa; else if (flairTime <= 21 && flairTime >= 11)
else if (flairTime <= 31 && flairTime >= 22) return 0x6;
return 0xe; else if (flairTime <= 11 && flairTime >= 0)
else if (flairTime <= 21 && flairTime >= 11) return 0xc;
return 0x6; return 0x00; //Return 0 if none or too high, so names will get aqua default color, not white
else if (flairTime <= 11 && flairTime >= 0) }
return 0xc;
return 0x00; //Return 0 if none or too high, so names will get aqua default color, not white public double getF() {
} return (double) FCount().get() / (double) FDeaths().get();
}
public double getF() { }
return (double) FCount().get() / (double) FDeaths().get();
}
}

View file

@ -7,10 +7,10 @@ import buttondevteam.chat.formatting.TellrawEvent;
import buttondevteam.chat.formatting.TellrawPart; import buttondevteam.chat.formatting.TellrawPart;
import buttondevteam.chat.formatting.TellrawSerializer; import buttondevteam.chat.formatting.TellrawSerializer;
import buttondevteam.chat.listener.PlayerListener; import buttondevteam.chat.listener.PlayerListener;
import buttondevteam.component.channel.Channel;
import buttondevteam.lib.TBMCChatEvent; import buttondevteam.lib.TBMCChatEvent;
import buttondevteam.lib.TBMCChatEventBase; import buttondevteam.lib.TBMCChatEventBase;
import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.chat.Channel;
import buttondevteam.lib.chat.Color; import buttondevteam.lib.chat.Color;
import buttondevteam.lib.chat.Priority; import buttondevteam.lib.chat.Priority;
import buttondevteam.lib.chat.TellrawSerializableEnum; import buttondevteam.lib.chat.TellrawSerializableEnum;
@ -46,7 +46,7 @@ public class ChatProcessing {
private static final Pattern ITALIC_PATTERN = Pattern.compile("\\*"); private static final Pattern ITALIC_PATTERN = Pattern.compile("\\*");
private static final Pattern BOLD_PATTERN = Pattern.compile("\\*\\*"); private static final Pattern BOLD_PATTERN = Pattern.compile("\\*\\*");
private static final Pattern CODE_PATTERN = Pattern.compile("`"); private static final Pattern CODE_PATTERN = Pattern.compile("`");
private static final Pattern MASKED_LINK_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"); //TODO
private static final Pattern STRIKETHROUGH_PATTERN = Pattern.compile("~~"); private static final Pattern STRIKETHROUGH_PATTERN = Pattern.compile("~~");
private static final Color[] RainbowPresserColors = new Color[]{Color.Red, Color.Gold, Color.Yellow, Color.Green, private static final Color[] RainbowPresserColors = new Color[]{Color.Red, Color.Gold, Color.Yellow, Color.Green,
@ -63,9 +63,8 @@ public class ChatProcessing {
.build(), .build(),
ChatFormatter.builder().regex(STRIKETHROUGH_PATTERN).strikethrough(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range) ChatFormatter.builder().regex(STRIKETHROUGH_PATTERN).strikethrough(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range)
.build(), .build(),
ESCAPE_FORMATTER, ChatFormatter.builder().regex(URL_PATTERN).underlined(true).openlink("$1").type(ChatFormatter.Type.Excluder).build(), ESCAPE_FORMATTER, ChatFormatter.builder().regex(NULL_MENTION_PATTERN).color(Color.DarkRed).build(), // Properly added a bug as a feature
ChatFormatter.builder().regex(NULL_MENTION_PATTERN).color(Color.DarkRed).build(), // Properly added a bug as a feature ChatFormatter.builder().regex(CONSOLE_PING_PATTERN).color(Color.Aqua).onmatch((match, builder, section) -> {
ChatFormatter.builder().regex(CONSOLE_PING_PATTERN).color(Color.Aqua).onmatch((match, builder) -> {
if (!pingedconsole) { if (!pingedconsole) {
System.out.print("\007"); System.out.print("\007");
pingedconsole = true; // Will set it to false in ProcessChat pingedconsole = true; // Will set it to false in ProcessChat
@ -78,16 +77,21 @@ public class ChatProcessing {
ChatFormatter.builder().regex(CYAN_PATTERN).color(Color.Aqua).build(), // #55 ChatFormatter.builder().regex(CYAN_PATTERN).color(Color.Aqua).build(), // #55
ChatFormatter.builder().regex(CODE_PATTERN).color(Color.DarkGray).removeCharCount((short) 1).type(ChatFormatter.Type.Range) ChatFormatter.builder().regex(CODE_PATTERN).color(Color.DarkGray).removeCharCount((short) 1).type(ChatFormatter.Type.Range)
.build(), .build(),
ChatFormatter.builder().regex(MASKED_LINK_PATTERN).underlined(true).onmatch((match, builder) -> { ChatFormatter.builder().regex(MASKED_LINK_PATTERN).underlined(true).onmatch((match, builder, section) -> {
return match; // TODO! String text, link;
}).build()); if (section.Matches.size() < 2 || (text = section.Matches.get(0)).length() == 0 || (link = section.Matches.get(1)).length() == 0)
return "";
builder.setOpenlink(link);
return text;
}).type(ChatFormatter.Type.Excluder).build(),
ChatFormatter.builder().regex(URL_PATTERN).underlined(true).openlink("$1").type(ChatFormatter.Type.Excluder).build());
private static Gson gson = new GsonBuilder() private static Gson gson = new GsonBuilder()
.registerTypeHierarchyAdapter(TellrawSerializableEnum.class, new TellrawSerializer.TwEnum()) .registerTypeHierarchyAdapter(TellrawSerializableEnum.class, new TellrawSerializer.TwEnum())
.registerTypeHierarchyAdapter(Collection.class, new TellrawSerializer.TwCollection()) .registerTypeHierarchyAdapter(Collection.class, new TellrawSerializer.TwCollection())
.registerTypeAdapter(Boolean.class, new TellrawSerializer.TwBool()) .registerTypeAdapter(Boolean.class, new TellrawSerializer.TwBool())
.registerTypeAdapter(boolean.class, new TellrawSerializer.TwBool()).disableHtmlEscaping().create(); .registerTypeAdapter(boolean.class, new TellrawSerializer.TwBool()).disableHtmlEscaping().create();
private static final String[] testPlayers = {"Koiiev", "iie", "Alisolarflare", "NorbiPeti", "Arsen_Derby_FTW", "carrot_lynx"}; private static final String[] testPlayers = {"Koiiev", "iie", "Alisolarflare", "NorbiPeti", "Arsen_Derby_FTW", "carrot_lynx"};
static final String MCORIGIN = "Minecraft"; //Shouldn't change, like ever - TBMCPlayer.getFolderForType(TBMCPlayer.class) capitalized public static final String MCORIGIN = "Minecraft"; //Shouldn't change, like ever - TBMCPlayer.getFolderForType(TBMCPlayer.class) capitalized
private ChatProcessing() { private ChatProcessing() {
} }
@ -114,7 +118,7 @@ public class ChatProcessing {
else //Due to the online player map, getPlayer() can be more efficient than getAs() else //Due to the online player map, getPlayer() can be more efficient than getAs()
mp = e.getUser().getAs(ChatPlayer.class); //May be null mp = e.getUser().getAs(ChatPlayer.class); //May be null
Color colormode = channel.color; Color colormode = channel.Color().get();
if (mp != null && mp.OtherColorMode != null) if (mp != null && mp.OtherColorMode != null)
colormode = mp.OtherColorMode; colormode = mp.OtherColorMode;
if (message.startsWith(">")) if (message.startsWith(">"))
@ -122,9 +126,9 @@ public class ChatProcessing {
// If greentext, ignore channel or player colors // If greentext, ignore channel or player colors
ArrayList<ChatFormatter> formatters = addFormatters(colormode); ArrayList<ChatFormatter> formatters = addFormatters(colormode);
if (colormode == channel.color && mp != null && mp.RainbowPresserColorMode) { // Only overwrite channel color if (colormode == channel.Color().get() && mp != null && mp.RainbowPresserColorMode) { // Only overwrite channel color
final AtomicInteger rpc = new AtomicInteger(0); final AtomicInteger rpc = new AtomicInteger(0);
formatters.add(ChatFormatter.builder().color(colormode).onmatch((match, cf) -> { formatters.add(ChatFormatter.builder().color(colormode).onmatch((match, cf, s) -> {
cf.setColor(RainbowPresserColors[rpc.getAndUpdate(i -> ++i < RainbowPresserColors.length ? i : 0)]); cf.setColor(RainbowPresserColors[rpc.getAndUpdate(i -> ++i < RainbowPresserColors.length ? i : 0)]);
return match; return match;
}).build()); }).build());
@ -233,7 +237,7 @@ public class ChatProcessing {
} }
static String getChannelID(Channel channel, CommandSender sender, String origin) { static String getChannelID(Channel channel, CommandSender sender, String origin) {
return ("[" + (MCORIGIN.equals(origin) ? "" : "§8" + origin.substring(0, 1) + "§r|") + channel.DisplayName) return ("[" + (MCORIGIN.equals(origin) ? "" : "§8" + origin.substring(0, 1) + "§r|") + channel.DisplayName().get())
+ "]"; + "]";
} }
@ -257,14 +261,12 @@ public class ChatProcessing {
namesb.append(")"); namesb.append(")");
StringBuilder nicksb = new StringBuilder("(?i)("); StringBuilder nicksb = new StringBuilder("(?i)(");
boolean addNickFormatter = false; boolean addNickFormatter = false;
int index = 0;
for (Player p : Bukkit.getOnlinePlayers()) { for (Player p : Bukkit.getOnlinePlayers()) {
final String nick = PlayerListener.nicknames.inverse().get(p.getUniqueId()); final String nick = PlayerListener.nicknames.inverse().get(p.getUniqueId());
if (nick != null) { if (nick != null) {
nicksb.append(nick).append("|"); nicksb.append(nick).append("|");
addNickFormatter = true; //Add it even if there's only 1 player online (it was in the if) addNickFormatter = true; //Add it even if there's only 1 player online (it was in the if)
} }
index++;
} }
nicksb.deleteCharAt(nicksb.length() - 1); nicksb.deleteCharAt(nicksb.length() - 1);
nicksb.append(")"); nicksb.append(")");
@ -277,7 +279,7 @@ public class ChatProcessing {
}; };
formatters.add(ChatFormatter.builder().regex(Pattern.compile(namesb.toString())).color(Color.Aqua) formatters.add(ChatFormatter.builder().regex(Pattern.compile(namesb.toString())).color(Color.Aqua)
.onmatch((match, builder) -> { .onmatch((match, builder, section) -> {
Player p = Bukkit.getPlayer(match); Player p = Bukkit.getPlayer(match);
Optional<String> pn = nottest ? Optional.empty() Optional<String> pn = nottest ? Optional.empty()
: Arrays.stream(testPlayers).filter(tp -> tp.equalsIgnoreCase(match)).findAny(); : Arrays.stream(testPlayers).filter(tp -> tp.equalsIgnoreCase(match)).findAny();
@ -287,11 +289,11 @@ public class ChatProcessing {
} }
ChatPlayer mpp = TBMCPlayer.getPlayer(nottest ? p.getUniqueId() : new UUID(0, 0), ChatPlayer.class); ChatPlayer mpp = TBMCPlayer.getPlayer(nottest ? p.getUniqueId() : new UUID(0, 0), ChatPlayer.class);
if (nottest) { if (nottest) {
if (PlayerListener.NotificationSound == null) if (PluginMain.Instance.notificationSound().get().length() == 0)
p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 0.5f); // TODO: Airhorn p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 0.5f); // TODO: Airhorn
else else
p.playSound(p.getLocation(), PlayerListener.NotificationSound, 1.0f, p.playSound(p.getLocation(), PluginMain.Instance.notificationSound().get(), 1.0f,
(float) PlayerListener.NotificationPitch); PluginMain.Instance.notificationPitch().get());
} }
String color = String.format("§%x", (mpp.GetFlairColor() == 0x00 ? 0xb : mpp.GetFlairColor())); 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 return color + (nottest ? p.getName() : pn.get()) + "§r"; //Fix name casing, except when testing
@ -299,7 +301,7 @@ public class ChatProcessing {
if (addNickFormatter) if (addNickFormatter)
formatters.add(ChatFormatter.builder().regex((Pattern.compile(nicksb.toString()))).color(Color.Aqua) formatters.add(ChatFormatter.builder().regex((Pattern.compile(nicksb.toString()))).color(Color.Aqua)
.onmatch((match, builder) -> { .onmatch((match, builder, section) -> {
if (PlayerListener.nicknames.containsKey(match.toLowerCase())) { //Made a stream and all that but I can actually store it lowercased if (PlayerListener.nicknames.containsKey(match.toLowerCase())) { //Made a stream and all that but I can actually store it lowercased
Player p = Bukkit.getPlayer(PlayerListener.nicknames.get(match.toLowerCase())); Player p = Bukkit.getPlayer(PlayerListener.nicknames.get(match.toLowerCase()));
if (p == null) { if (p == null) {
@ -307,11 +309,11 @@ public class ChatProcessing {
+ match.toLowerCase() + " but was reported as online."); + match.toLowerCase() + " but was reported as online.");
return "§c" + match + "§r"; return "§c" + match + "§r";
} }
if (PlayerListener.NotificationSound == null) if (PluginMain.Instance.notificationSound().get().length() == 0)
p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 0.5f); p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 0.5f); // TODO: Airhorn
else else
p.playSound(p.getLocation(), PlayerListener.NotificationSound, 1.0f, p.playSound(p.getLocation(), PluginMain.Instance.notificationSound().get(), 1.0f,
(float) PlayerListener.NotificationPitch); PluginMain.Instance.notificationPitch().get());
return PluginMain.essentials.getUser(p).getNickname(); return PluginMain.essentials.getUser(p).getNickname();
} }
error.accept("Player nicknamed " + match.toLowerCase() error.accept("Player nicknamed " + match.toLowerCase()

View file

@ -1,90 +0,0 @@
package buttondevteam.chat;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class JarUtils {
public static boolean extractFromJar(final String fileName,
final String dest) throws IOException {
if (getRunningJar() == null) {
return false;
}
final File file = new File(dest);
if (file.isDirectory()) {
file.mkdir();
return false;
}
if (!file.exists()) {
file.getParentFile().mkdirs();
}
final JarFile jar = getRunningJar();
final Enumeration<JarEntry> e = jar.entries();
while (e.hasMoreElements()) {
final JarEntry je = e.nextElement();
if (!je.getName().contains(fileName)) {
continue;
}
final InputStream in = new BufferedInputStream(
jar.getInputStream(je));
final OutputStream out = new BufferedOutputStream(
new FileOutputStream(file));
copyInputStream(in, out);
jar.close();
return true;
}
jar.close();
return false;
}
private final static void copyInputStream(final InputStream in,
final OutputStream out) throws IOException {
try {
final byte[] buff = new byte[4096];
int n;
while ((n = in.read(buff)) > 0) {
out.write(buff, 0, n);
}
} finally {
out.flush();
out.close();
in.close();
}
}
public static URL getJarUrl(final File file) throws IOException {
return new URL("jar:" + file.toURI().toURL().toExternalForm() + "!/");
}
public static JarFile getRunningJar() throws IOException {
if (!RUNNING_FROM_JAR) {
return null; // null if not running from jar
}
String path = new File(JarUtils.class.getProtectionDomain()
.getCodeSource().getLocation().getPath()).getAbsolutePath();
path = URLDecoder.decode(path, "UTF-8");
return new JarFile(path);
}
private static boolean RUNNING_FROM_JAR = false;
static {
final URL resource = JarUtils.class.getClassLoader().getResource(
"plugin.yml");
if (resource != null) {
RUNNING_FROM_JAR = true;
}
}
}

View file

@ -1,426 +1,102 @@
package buttondevteam.chat; package buttondevteam.chat;
import buttondevteam.chat.commands.YeehawCommand; import buttondevteam.chat.commands.YeehawCommand;
import buttondevteam.chat.commands.ucmds.TownColorCommand; import buttondevteam.chat.components.announce.AnnouncerComponent;
import buttondevteam.chat.listener.PlayerJoinLeaveListener; import buttondevteam.chat.components.flair.FlairComponent;
import buttondevteam.chat.listener.PlayerListener; import buttondevteam.chat.components.towncolors.TownColorComponent;
import buttondevteam.chat.listener.TownyListener; import buttondevteam.chat.components.towncolors.TownyListener;
import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.chat.components.towny.TownyComponent;
import buttondevteam.lib.chat.Channel; import buttondevteam.chat.listener.PlayerJoinLeaveListener;
import buttondevteam.lib.chat.Channel.RecipientTestResult; import buttondevteam.chat.listener.PlayerListener;
import buttondevteam.lib.chat.Color; import buttondevteam.component.channel.Channel;
import buttondevteam.lib.chat.TBMCChatAPI; import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.player.TBMCPlayerBase; import buttondevteam.lib.architecture.ButtonPlugin;
import com.earth2me.essentials.Essentials; import buttondevteam.lib.architecture.Component;
import com.google.gson.JsonArray; import buttondevteam.lib.architecture.ConfigData;
import com.google.gson.JsonObject; import buttondevteam.lib.chat.Color;
import com.google.gson.JsonParser; import buttondevteam.lib.chat.TBMCChatAPI;
import com.palmergames.bukkit.towny.Towny; import com.earth2me.essentials.Essentials;
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException; import net.milkbowl.vault.chat.Chat;
import com.palmergames.bukkit.towny.object.Nation; import net.milkbowl.vault.economy.Economy;
import com.palmergames.bukkit.towny.object.Resident; import net.milkbowl.vault.permission.Permission;
import com.palmergames.bukkit.towny.object.Town; import org.bukkit.Bukkit;
import com.palmergames.bukkit.towny.object.TownyUniverse; import org.bukkit.command.ConsoleCommandSender;
import lombok.val; import org.bukkit.plugin.RegisteredServiceProvider;
import net.milkbowl.vault.chat.Chat; import org.bukkit.scoreboard.Scoreboard;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.permission.Permission; public class PluginMain extends ButtonPlugin { // Translated to Java: 2015.07.15.
import org.bukkit.Bukkit; // A user, which flair isn't obtainable:
import org.bukkit.command.CommandSender; // https://www.reddit.com/r/thebutton/comments/31c32v/i_pressed_the_button_without_really_thinking/
import org.bukkit.command.ConsoleCommandSender; public static PluginMain Instance;
import org.bukkit.configuration.file.YamlConfiguration; public static ConsoleCommandSender Console;
import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider; public static Scoreboard SB;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scoreboard.Scoreboard; public static Channel TownChat;
import org.dynmap.towny.DTBridge; public static Channel NationChat;
import org.dynmap.towny.DynmapTownyPlugin;
import org.htmlcleaner.HtmlCleaner; public ConfigData<String> notificationSound() {
import org.htmlcleaner.TagNode; return getIConfig().getData("notificationSound", "");
}
import java.io.File;
import java.io.IOException; public ConfigData<Float> notificationPitch() {
import java.io.InputStream; return getIConfig().getData("notificationPitch", 1.0f);
import java.net.URL; }
import java.net.URLConnection;
import java.net.UnknownHostException; // Fired when plugin is first enabled
import java.text.SimpleDateFormat; @Override
import java.util.*; public void pluginEnable() {
import java.util.function.Function; Instance = this;
import java.util.stream.Collectors; PluginMain.essentials = (Essentials) (Bukkit.getPluginManager().getPlugin("Essentials"));
public class PluginMain extends JavaPlugin { // Translated to Java: 2015.07.15. TBMCCoreAPI.RegisterEventsForExceptions(new PlayerListener(), this);
// A user, which flair isn't obtainable: TBMCCoreAPI.RegisterEventsForExceptions(new PlayerJoinLeaveListener(), this);
// https://www.reddit.com/r/thebutton/comments/31c32v/i_pressed_the_button_without_really_thinking/ TBMCCoreAPI.RegisterEventsForExceptions(new TownyListener(), this);
public static PluginMain Instance; TBMCChatAPI.AddCommands(this, YeehawCommand.class);
public static ConsoleCommandSender Console; Console = this.getServer().getConsoleSender();
private final static String FlairThreadURL = "https://www.reddit.com/r/Chromagamers/comments/51ys94/flair_thread_for_the_mc_server/";
SB = getServer().getScoreboardManager().getMainScoreboard(); // Main can be detected with @a[score_...]
public static Scoreboard SB;
public static TownyUniverse TU; Component.registerComponent(this, new TownyComponent());
private static ArrayList<Town> Towns;
private static ArrayList<Nation> Nations; TBMCChatAPI.RegisterChatChannel(new Channel("§7RP§f", Color.Gray, "rp", null)); //Since it's null, it's recognised as global
public static Channel TownChat; if (!setupEconomy() || !setupPermissions())
public static Channel NationChat; TBMCCoreAPI.SendException("We're in trouble", new Exception("Failed to set up economy or permissions!"));
private static Channel RPChannel;
Component.registerComponent(this, new TownColorComponent());
/** Component.registerComponent(this, new FlairComponent()); //The original purpose of this plugin
* <p> Component.registerComponent(this, new AnnouncerComponent());
* This variable is used as a cache for flair state checking when reading the flair thread. }
* </p>
* <p> public static Essentials essentials = null;
* It's used because normally it has to load all associated player files every time to read the flair state
* </p> // Fired when plugin is disabled
*/ @Override
private Set<String> PlayersWithFlairs = new HashSet<>(); public void pluginDisable() {
}
// Fired when plugin is first enabled
@Override public static Permission permission = null;
public void onEnable() { public static Economy economy = null;
Instance = this; public static Chat chat = null;
PluginMain.essentials = (Essentials) (Bukkit.getPluginManager().getPlugin("Essentials"));
private boolean setupPermissions() {
TBMCCoreAPI.RegisterEventsForExceptions(new PlayerListener(), this); RegisteredServiceProvider<Permission> permissionProvider = getServer().getServicesManager()
TBMCCoreAPI.RegisterEventsForExceptions(new PlayerJoinLeaveListener(), this); .getRegistration(net.milkbowl.vault.permission.Permission.class);
TBMCCoreAPI.RegisterEventsForExceptions(new TownyListener(), this); if (permissionProvider != null) {
TBMCChatAPI.AddCommands(this, YeehawCommand.class); permission = permissionProvider.getProvider();
Console = this.getServer().getConsoleSender(); }
LoadFiles(); return (permission != null);
}
SB = getServer().getScoreboardManager().getMainScoreboard(); // Main can be detected with @a[score_...]
TU = ((Towny) Bukkit.getPluginManager().getPlugin("Towny")).getTownyUniverse(); private boolean setupEconomy() {
Towns = new ArrayList<>(TU.getTownsMap().values()); // Creates a snapshot of towns, new towns will be added when needed RegisteredServiceProvider<Economy> economyProvider = getServer().getServicesManager()
Nations = new ArrayList<>(TU.getNationsMap().values()); // Same here but with nations .getRegistration(net.milkbowl.vault.economy.Economy.class);
if (economyProvider != null) {
TownColors.keySet().removeIf(t -> !TU.getTownsMap().containsKey(t)); // Removes town colors for deleted/renamed towns economy = economyProvider.getProvider();
NationColor.keySet().removeIf(n -> !TU.getNationsMap().containsKey(n)); // Removes nation colors for deleted/renamed nations }
TBMCChatAPI.RegisterChatChannel( return (economy != null);
TownChat = new Channel("§3TC§f", Color.DarkAqua, "tc", s -> checkTownNationChat(s, false))); }
TBMCChatAPI.RegisterChatChannel(
NationChat = new Channel("§6NC§f", Color.Gold, "nc", s -> checkTownNationChat(s, true))); }
TBMCChatAPI.RegisterChatChannel(RPChannel = new Channel("§7RP§f", Color.Gray, "rp", null)); //Since it's null, it's recognised as global
Bukkit.getScheduler().runTask(this, () -> {
val dtp = (DynmapTownyPlugin) Bukkit.getPluginManager().getPlugin("Dynmap-Towny");
if (dtp == null)
return;
for (val entry : TownColors.entrySet())
setTownColor(dtp, buttondevteam.chat.commands.ucmds.admin.TownColorCommand.getTownNameCased(entry.getKey()), entry.getValue());
});
if (!setupEconomy() || !setupPermissions())
TBMCCoreAPI.SendException("We're in trouble", new Exception("Failed to set up economy or permissions!"));
new Thread(this::FlairGetterThreadMethod).start();
new Thread(new AnnouncerThread()).start();
}
/**
* Sets a town's color on Dynmap.
*
* @param dtp A reference for the Dynmap-Towny plugin
* @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) {
Function<Color, Integer> c2i = c -> c.getRed() << 16 | c.getGreen() << 8 | c.getBlue();
try {
DTBridge.setTownColor(dtp, town, c2i.apply(colors[0]),
c2i.apply(colors.length > 1 ? colors[1] : colors[0]));
} catch (Exception e) {
TBMCCoreAPI.SendException("Failed to set town color for town " + town + "!", e);
}
}
public Boolean stop = false;
public static Essentials essentials = null;
// Fired when plugin is disabled
@Override
public void onDisable() {
SaveFiles();
stop = true;
}
private void FlairGetterThreadMethod() {
int errorcount = 0;
while (!stop) {
try {
String body = TBMCCoreAPI.DownloadString(FlairThreadURL + ".json?limit=1000");
JsonArray json = new JsonParser().parse(body).getAsJsonArray().get(1).getAsJsonObject().get("data")
.getAsJsonObject().get("children").getAsJsonArray();
for (Object obj : json) {
JsonObject item = (JsonObject) obj;
String author = item.get("data").getAsJsonObject().get("author").getAsString();
String ign = item.get("data").getAsJsonObject().get("body").getAsString();
int start = ign.indexOf("IGN:") + "IGN:".length();
if (start == -1 + "IGN:".length())
continue;
int end = ign.indexOf(' ', start);
if (end == -1 || end == start)
end = ign.indexOf('\n', start);
if (end == -1 || end == start)
ign = ign.substring(start);
else
ign = ign.substring(start, end);
ign = ign.trim();
if (PlayersWithFlairs.contains(ign))
continue;
try (ChatPlayer mp = TBMCPlayerBase.getFromName(ign, ChatPlayer.class)) { // Loads player file
if (mp == null)
continue;
/*
* if (!JoinedBefore(mp, 2015, 6, 5)) continue;
*/
if (!mp.UserNames().contains(author))
mp.UserNames().add(author);
if (mp.FlairState().get().equals(FlairStates.NoComment)) {
mp.FlairState().set(FlairStates.Commented);
ConfirmUserMessage(mp);
}
PlayersWithFlairs.add(ign); // Don't redownload even if flair isn't accepted
}
}
} catch (Exception e) {
errorcount++;
if (errorcount >= 10) {
errorcount = 0;
if (!e.getMessage().contains("Server returned HTTP response code")
&& !(e instanceof UnknownHostException))
TBMCCoreAPI.SendException("Error while getting flairs from Reddit!", e);
}
}
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
public void DownloadFlair(ChatPlayer mp) throws IOException {
String[] flairdata = TBMCCoreAPI
.DownloadString("http://karmadecay.com/thebutton-data.php?users=" + mp.UserName().get())
.replace("\"", "").split(":");
String flair;
if (flairdata.length > 1)
flair = flairdata[1];
else
flair = "";
String flairclass;
if (flairdata.length > 2)
flairclass = flairdata[2];
else
flairclass = "unknown";
SetFlair(mp, flair, flairclass, mp.UserName().get());
}
private void SetFlair(ChatPlayer p, String text, String flairclass, String username) {
p.UserName().set(username);
p.FlairState().set(FlairStates.Recognised);
switch (flairclass) {
case "cheater":
p.SetFlair(Short.parseShort(text), true);
return;
case "unknown":
try {
if (CheckForJoinDate(p)) {
if (text.equals("-1")) // If true, only non-presser/can't press; if false, any flair (but we can still detect can't press)
p.SetFlair(ChatPlayer.FlairTimeNonPresser);
else
p.SetFlair(ChatPlayer.FlairTimeNone); // Flair unknown
} else {
p.SetFlair(ChatPlayer.FlairTimeCantPress);
}
} catch (Exception e) {
p.FlairState().set(FlairStates.Commented); // Flair unknown
p.SetFlair(ChatPlayer.FlairTimeNone);
TBMCCoreAPI.SendException("Error while checking join date for player " + p.PlayerName() + "!", e);
}
return;
default:
break;
}
p.SetFlair(Short.parseShort(text));
}
private static boolean CheckForJoinDate(ChatPlayer mp) throws Exception {
return JoinedBefore(mp, 2015, 4, 1);
}
private static boolean JoinedBefore(ChatPlayer mp, int year, int month, int day) throws Exception {
URL url = new URL("https://www.reddit.com/u/" + mp.UserName());
URLConnection con = url.openConnection();
con.setRequestProperty("User-Agent", "TheButtonAutoFlair");
InputStream in = con.getInputStream();
HtmlCleaner cleaner = new HtmlCleaner();
TagNode node = cleaner.clean(in);
node = node.getElementsByAttValue("class", "age", true, true)[0];
node = node.getElementsByName("time", false)[0];
String joindate = node.getAttributeByName("datetime");
SimpleDateFormat parserSDF = new SimpleDateFormat("yyyy-MM-dd");
joindate = joindate.split("T")[0];
Date date = parserSDF.parse(joindate);
return date.before(new Calendar.Builder().setTimeZone(TimeZone.getTimeZone("UTC")).setDate(year, month, day)
.build().getTime());
}
public static void ConfirmUserMessage(ChatPlayer mp) {
Player p = Bukkit.getPlayer(mp.getUUID());
if (mp.FlairState().get().equals(FlairStates.Commented) && p != null)
if (mp.UserNames().size() > 1)
p.sendMessage(
"§9Multiple Reddit users commented your name. You can select with /u accept.§r §6Type /u accept or /u ignore§r");
else
p.sendMessage("§9A Reddit user commented your name. Is that you?§r §6Type /u accept or /u ignore§r");
}
public static ArrayList<String> AnnounceMessages = new ArrayList<>();
public static int AnnounceTime = 15 * 60 * 1000;
/**
* Names lowercased
*/
public static Map<String, Color[]> TownColors = new HashMap<>();
/**
* Names lowercased - nation color gets added to town colors when needed
*/
public static Map<String, Color> NationColor = new HashMap<>();
@SuppressWarnings("unchecked")
private static void LoadFiles() {
PluginMain.Instance.getLogger().info("Loading files...");
try {
File file = new File("TBMC/chatsettings.yml");
if (file.exists()) {
YamlConfiguration yc = new YamlConfiguration();
yc.load(file);
PlayerListener.NotificationSound = yc.getString("notificationsound");
PlayerListener.NotificationPitch = yc.getDouble("notificationpitch");
AnnounceTime = yc.getInt("announcetime", 15 * 60 * 1000);
AnnounceMessages.addAll(yc.getStringList("announcements"));
PlayerListener.AlphaDeaths = yc.getInt("alphadeaths");
val cs = yc.getConfigurationSection("towncolors");
if (cs != null)
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))));
TownColorCommand.ColorCount = (byte) yc.getInt("towncolorcount", 1);
val ncs = yc.getConfigurationSection("nationcolors");
if (ncs != null)
NationColor.putAll(ncs.getValues(true).entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, v -> Color.valueOf((String) v.getValue()))));
PluginMain.Instance.getLogger().info("Loaded files!");
} else
PluginMain.Instance.getLogger().info("No files to load, first run probably.");
} catch (Exception e) {
TBMCCoreAPI.SendException("Error while loading chat files!", e);
}
}
public static void SaveFiles() {
PluginMain.Instance.getLogger().info("Saving files...");
try {
File file = new File("TBMC/chatsettings.yml");
YamlConfiguration yc = new YamlConfiguration();
yc.set("notificationsound", PlayerListener.NotificationSound);
yc.set("notificationpitch", PlayerListener.NotificationPitch);
yc.set("announcetime", AnnounceTime);
yc.set("announcements", AnnounceMessages);
yc.set("alphadeaths", PlayerListener.AlphaDeaths);
yc.createSection("towncolors", TownColors.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
v -> Arrays.stream(v.getValue()).map(Enum::toString).toArray(String[]::new))));
yc.set("towncolorcount", TownColorCommand.ColorCount);
yc.createSection("nationcolors", NationColor.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
v -> v.getValue().toString())));
yc.save(file);
PluginMain.Instance.getLogger().info("Saved files!");
} catch (Exception e) {
TBMCCoreAPI.SendException("Error while loading chat files!", e);
}
}
public static Permission permission = null;
public static Economy economy = null;
public static Chat chat = null;
private boolean setupPermissions() {
RegisteredServiceProvider<Permission> permissionProvider = getServer().getServicesManager()
.getRegistration(net.milkbowl.vault.permission.Permission.class);
if (permissionProvider != null) {
permission = permissionProvider.getProvider();
}
return (permission != null);
}
private boolean setupChat() {
RegisteredServiceProvider<Chat> chatProvider = getServer().getServicesManager()
.getRegistration(net.milkbowl.vault.chat.Chat.class);
if (chatProvider != null) {
chat = chatProvider.getProvider();
}
return (chat != null);
}
private boolean setupEconomy() {
RegisteredServiceProvider<Economy> economyProvider = getServer().getServicesManager()
.getRegistration(net.milkbowl.vault.economy.Economy.class);
if (economyProvider != null) {
economy = economyProvider.getProvider();
}
return (economy != null);
}
/**
* Return the error message for the message sender if they can't send it and the score
*/
private static RecipientTestResult checkTownNationChat(CommandSender sender, boolean nationchat) {
if (!(sender instanceof Player))
return new RecipientTestResult("§cYou are not a player!");
Resident resident = PluginMain.TU.getResidentMap().get(sender.getName().toLowerCase());
RecipientTestResult result = checkTownNationChatInternal(sender, nationchat, resident);
if (result.errormessage != null && resident != null && resident.getModes().contains("spy")) // Only use spy if they wouldn't see it
result = new RecipientTestResult(1000, "allspies"); // There won't be more than a thousand towns/nations probably
return result;
}
private static RecipientTestResult checkTownNationChatInternal(CommandSender sender, boolean nationchat,
Resident resident) {
try {
/*
* p.sendMessage(String.format("[SPY-%s] - %s: %s", channel.DisplayName, ((Player) sender).getDisplayName(), message));
*/
Town town = null;
if (resident != null && resident.hasTown())
town = resident.getTown();
if (town == null)
return new RecipientTestResult("You aren't in a town.");
Nation nation = null;
int index;
if (nationchat) {
if (town.hasNation())
nation = town.getNation();
if (nation == null)
return new RecipientTestResult("Your town isn't in a nation.");
index = PluginMain.Nations.indexOf(nation);
if (index < 0) {
PluginMain.Nations.add(nation);
index = PluginMain.Nations.size() - 1;
}
} else {
index = PluginMain.Towns.indexOf(town);
if (index < 0) {
PluginMain.Towns.add(town);
index = PluginMain.Towns.size() - 1;
}
}
return new RecipientTestResult(index, nationchat ? nation.getName() : town.getName());
} catch (NotRegisteredException e) {
return new RecipientTestResult("You (probably) aren't knwon by Towny! (Not in a town)");
}
}
}

View file

@ -1,55 +1,55 @@
package buttondevteam.chat.commands; package buttondevteam.chat.commands;
import buttondevteam.lib.TBMCChatEventBase; import buttondevteam.component.channel.Channel;
import buttondevteam.lib.chat.Channel; import buttondevteam.lib.TBMCChatEventBase;
import buttondevteam.lib.chat.CommandClass; import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.chat.TBMCCommandBase; import buttondevteam.lib.chat.TBMCCommandBase;
import lombok.Data; import lombok.Data;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@CommandClass(modOnly = false) @CommandClass(modOnly = false)
public final class UnlolCommand extends TBMCCommandBase { public final class UnlolCommand extends TBMCCommandBase {
public static Map<Channel, LastlolData> Lastlol = new HashMap<>(); public static Map<Channel, LastlolData> Lastlol = new HashMap<>();
@Override @Override
public String[] GetHelpText(String alias) { public String[] GetHelpText(String alias) {
return new String[] { "§6---- Unlol/unlaugh ----", return new String[] { "§6---- Unlol/unlaugh ----",
"This command is based on a joke between NorbiPeti and Ghostise", "This command is based on a joke between NorbiPeti and Ghostise",
"It will make the last person saying one of the recognized laugh strings blind for a few seconds", "It will make the last person saying one of the recognized laugh strings blind for a few seconds",
"Note that you can only unlaugh laughs that weren't unlaughed before" }; "Note that you can only unlaugh laughs that weren't unlaughed before" };
} }
@Override @Override
public boolean OnCommand(CommandSender sender, String alias, String[] args) { public boolean OnCommand(CommandSender sender, String alias, String[] args) {
LastlolData lol = Lastlol.values().stream().filter(lld -> lld.Chatevent.shouldSendTo(sender)) LastlolData lol = Lastlol.values().stream().filter(lld -> lld.Chatevent.shouldSendTo(sender))
.max(Comparator.comparingLong(lld -> lld.Loltime)).orElse(null); .max(Comparator.comparingLong(lld -> lld.Loltime)).orElse(null);
if (lol == null) if (lol == null)
return true; return true;
if (lol.Lolowner instanceof Player) if (lol.Lolowner instanceof Player)
((Player) lol.Lolowner) ((Player) lol.Lolowner)
.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 2 * 20, 5, false, false)); .addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 2 * 20, 5, false, false));
String msg = (sender instanceof Player ? ((Player) sender).getDisplayName() : sender.getName()) String msg = (sender instanceof Player ? ((Player) sender).getDisplayName() : sender.getName())
+ (lol.Lolornot ? " unlolled " : " unlaughed ") + (lol.Lolornot ? " unlolled " : " unlaughed ")
+ (lol.Lolowner instanceof Player ? ((Player) lol.Lolowner).getDisplayName() : lol.Lolowner.getName()); + (lol.Lolowner instanceof Player ? ((Player) lol.Lolowner).getDisplayName() : lol.Lolowner.getName());
Bukkit.broadcastMessage(msg); Bukkit.broadcastMessage(msg);
Lastlol.remove(lol.Chatevent.getChannel()); Lastlol.remove(lol.Chatevent.getChannel());
return true; return true;
} }
@Data @Data
public static class LastlolData { public static class LastlolData {
private boolean Lolornot; private boolean Lolornot;
private final CommandSender Lolowner; private final CommandSender Lolowner;
private final TBMCChatEventBase Chatevent; private final TBMCChatEventBase Chatevent;
private final long Loltime; private final long Loltime;
} }
} }

View file

@ -1,6 +1,6 @@
package buttondevteam.chat.commands.ucmds; package buttondevteam.chat.commands.ucmds;
import buttondevteam.lib.chat.Channel; import buttondevteam.component.channel.Channel;
import buttondevteam.lib.chat.ChatMessage; import buttondevteam.lib.chat.ChatMessage;
import buttondevteam.lib.chat.CommandClass; import buttondevteam.lib.chat.CommandClass;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -39,9 +39,9 @@ public class HistoryCommand extends UCommandBase {
sender.sendMessage("§6---- Chat History ----"); sender.sendMessage("§6---- Chat History ----");
Stream<Channel> stream; Stream<Channel> stream;
if (args.length == 0) { if (args.length == 0) {
stream = Channel.getChannels().stream(); stream = Channel.getChannels();
} else { } else {
Optional<Channel> och = Channel.getChannels().stream().filter(chan -> chan.ID.equalsIgnoreCase(args[0])).findAny(); Optional<Channel> och = Channel.getChannels().filter(chan -> chan.ID.equalsIgnoreCase(args[0])).findAny();
if (!och.isPresent()) { if (!och.isPresent()) {
sender.sendMessage("§cChannel not found. Use the ID, for example: /" + (hc == null ? "u history" : hc.GetCommandPath()) + " ooc"); sender.sendMessage("§cChannel not found. Use the ID, for example: /" + (hc == null ? "u history" : hc.GetCommandPath()) + " ooc");
return true; return true;
@ -54,7 +54,7 @@ public class HistoryCommand extends UCommandBase {
for (int i = Math.max(0, arr.length - 10); i < arr.length; i++) { for (int i = Math.max(0, arr.length - 10); i < arr.length; i++) {
HistoryEntry e = arr[i]; HistoryEntry e = arr[i];
val cm = e.chatMessage; val cm = e.chatMessage;
sender.sendMessage("[" + e.channel.DisplayName + "] " + cm.getSender().getName() + ": " + cm.getMessage()); sender.sendMessage("[" + e.channel.DisplayName().get() + "] " + cm.getSender().getName() + ": " + cm.getMessage());
sent.set(true); sent.set(true);
} }
if (!sent.get()) if (!sent.get())

View file

@ -1,23 +0,0 @@
package buttondevteam.chat.commands.ucmds.admin;
import org.bukkit.command.CommandSender;
import buttondevteam.chat.PluginMain;
public class SaveCommand extends AdminCommandBase {
@Override
public String[] GetHelpText(String alias) {
return new String[] { "§6---- Save config ----",
"This command saves the config file(s)" };
}
@Override
public boolean OnCommand(CommandSender sender, String alias,
String[] args) {
PluginMain.SaveFiles(); // 2015.08.09.
sender.sendMessage("§bSaved files. Now you can edit them and reload if you want.§r");
return true;
}
}

View file

@ -1,24 +0,0 @@
package buttondevteam.chat.components;
import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.architecture.ConfigData;
public class TownColorComponent extends Component {
public ConfigData<Byte> colorCount() { //TODO
return getData("colorCount", (byte) 1, cc -> (byte) cc, cc -> (int) cc);
}
public ConfigData<Boolean> useNationColors() { //TODO
return getData("useNationColors", true);
}
@Override
protected void enable() {
//TODO: Don't register all commands automatically (welp)
}
@Override
protected void disable() {
}
}

View file

@ -1,37 +1,36 @@
package buttondevteam.chat.commands.ucmds.announce; package buttondevteam.chat.components.announce;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import buttondevteam.chat.PluginMain; public class AddCommand extends AnnounceCommandBase {
public class AddCommand extends AnnounceCommandBase { @Override
public String[] GetHelpText(String alias) {
@Override return new String[] {
public String[] GetHelpText(String alias) { "§6---- Add announcement ----",
return new String[] { "This command adds a new announcement",
"§6---- Add announcement ----", "Note: Please avoid using this command, if possible",
"This command adds a new announcement", "Instead, use the command blocks in flatworld to set announcements",
"Note: Please avoid using this command, if possible", "This makes editing announcements easier" };
"Instead, use the command blocks in flatworld to set announcements", }
"This makes editing announcements easier" };
} @Override
public boolean OnCommand(CommandSender sender, String alias,
@Override String[] args) {
public boolean OnCommand(CommandSender sender, String alias, if (args.length < 1) {
String[] args) { return false;
if (args.length < 1) { }
return false; StringBuilder sb = new StringBuilder();
} for (int i = 0; i < args.length; i++) {
StringBuilder sb = new StringBuilder(); sb.append(args[i]);
for (int i = 0; i < args.length; i++) { if (i != args.length - 1)
sb.append(args[i]); sb.append(" ");
if (i != args.length - 1) }
sb.append(" "); String finalmessage = sb.toString().replace('&', '§');
} AnnouncerComponent component = (AnnouncerComponent) getComponent();
String finalmessage = sb.toString().replace('&', '§'); component.AnnounceMessages().get().add(finalmessage);
PluginMain.AnnounceMessages.add(finalmessage); sender.sendMessage("§bAnnouncement added. - Plase avoid using this command if possible, see /u announce add without args.§r");
sender.sendMessage("§bAnnouncement added. - Plase avoid using this command if possible, see /u announce add without args.§r"); return true;
return true; }
}
}
}

View file

@ -1,13 +1,13 @@
package buttondevteam.chat.commands.ucmds.announce; package buttondevteam.chat.components.announce;
import buttondevteam.chat.commands.ucmds.UCommandBase; import buttondevteam.chat.commands.ucmds.UCommandBase;
import buttondevteam.lib.chat.CommandClass; import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.chat.OptionallyPlayerCommandClass; import buttondevteam.lib.chat.OptionallyPlayerCommandClass;
@CommandClass(modOnly = true) @CommandClass(modOnly = true)
@OptionallyPlayerCommandClass(playerOnly = false) @OptionallyPlayerCommandClass(playerOnly = false)
public abstract class AnnounceCommandBase extends UCommandBase { public abstract class AnnounceCommandBase extends UCommandBase {
public abstract String[] GetHelpText(String alias); public abstract String[] GetHelpText(String alias);
} }

View file

@ -0,0 +1,50 @@
package buttondevteam.chat.components.announce;
import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.architecture.ConfigData;
import org.bukkit.Bukkit;
import java.util.ArrayList;
public class AnnouncerComponent extends Component implements Runnable {
public ConfigData<ArrayList<String>> AnnounceMessages() {
return getConfig().getData("announceMessages", new ArrayList<>(0));
}
public ConfigData<Integer> AnnounceTime() {
return getConfig().getData("announceTime", 15 * 60 * 1000);
}
private static int AnnounceMessageIndex = 0;
@Override
public void run() {
while (isEnabled()) {
try {
Thread.sleep(AnnounceTime().get());
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
if (Bukkit.getOnlinePlayers().size() == 0) continue; //Don't post to Discord if nobody is on
if (AnnounceMessages().get().size() > AnnounceMessageIndex) {
Bukkit.broadcastMessage(AnnounceMessages().get().get(AnnounceMessageIndex));
AnnounceMessageIndex++;
if (AnnounceMessageIndex == AnnounceMessages().get().size())
AnnounceMessageIndex = 0;
}
}
}
@Override
protected void enable() {
registerCommand(new AddCommand());
registerCommand(new EditCommand());
registerCommand(new ListCommand());
registerCommand(new RemoveCommand());
registerCommand(new SetTimeCommand());
new Thread(this).start();
}
@Override
protected void disable() {
}
}

View file

@ -1,45 +1,44 @@
package buttondevteam.chat.commands.ucmds.announce; package buttondevteam.chat.components.announce;
import org.bukkit.command.BlockCommandSender; import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import buttondevteam.chat.PluginMain; public class EditCommand extends AnnounceCommandBase {
public class EditCommand extends AnnounceCommandBase { @Override
public String[] GetHelpText(String alias) {
@Override return new String[] { "§6---- Edit announcement ----",
public String[] GetHelpText(String alias) { "This command can only be used in a command block.",
return new String[] { "§6---- Edit announcement ----", "Usage: /u annonunce edit <index> <text>" };
"This command can only be used in a command block.", }
"Usage: /u annonunce edit <index> <text>" };
} @Override
public boolean OnCommand(CommandSender sender, String alias,
@Override String[] args) {
public boolean OnCommand(CommandSender sender, String alias, if (!(sender instanceof BlockCommandSender)) {
String[] args) { sender.sendMessage("§cError: This command can only be used from a command block. You can use add and remove, though it's not recommended.");
if (!(sender instanceof BlockCommandSender)) { return true;
sender.sendMessage("§cError: This command can only be used from a command block. You can use add and remove, though it's not recommended."); }
return true; if (args.length < 1) {
} return false;
if (args.length < 1) { }
return false; StringBuilder sb1 = new StringBuilder();
} for (int i1 = 1; i1 < args.length; i1++) {
StringBuilder sb1 = new StringBuilder(); sb1.append(args[i1]);
for (int i1 = 1; i1 < args.length; i1++) { if (i1 != args.length - 1)
sb1.append(args[i1]); sb1.append(" ");
if (i1 != args.length - 1) }
sb1.append(" "); String finalmessage1 = sb1.toString().replace('&', '§');
} int index = Integer.parseInt(args[0]);
String finalmessage1 = sb1.toString().replace('&', '§'); if (index > 100)
int index = Integer.parseInt(args[0]); return false;
if (index > 100) AnnouncerComponent component = (AnnouncerComponent) getComponent();
return false; while (component.AnnounceMessages().get().size() <= index)
while (PluginMain.AnnounceMessages.size() <= index) component.AnnounceMessages().get().add("");
PluginMain.AnnounceMessages.add(""); component.AnnounceMessages().get().set(Integer.parseInt(args[0]),
PluginMain.AnnounceMessages.set(Integer.parseInt(args[0]), finalmessage1);
finalmessage1); sender.sendMessage("Announcement edited.");
sender.sendMessage("Announcement edited."); return true;
return true; }
}
}
}

View file

@ -1,28 +1,27 @@
package buttondevteam.chat.commands.ucmds.announce; package buttondevteam.chat.components.announce;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import buttondevteam.chat.PluginMain; public class ListCommand extends AnnounceCommandBase {
public class ListCommand extends AnnounceCommandBase { @Override
public String[] GetHelpText(String alias) {
@Override return new String[] { "§6---- List announcements ----",
public String[] GetHelpText(String alias) { "This command lists the announcements and the time between them" };
return new String[] { "§6---- List announcements ----", }
"This command lists the announcements and the time between them" };
} @Override
public boolean OnCommand(CommandSender sender, String alias,
@Override String[] args) {
public boolean OnCommand(CommandSender sender, String alias, sender.sendMessage("§bList of announce messages:§r");
String[] args) { sender.sendMessage("§bFormat: [index] message§r");
sender.sendMessage("§bList of announce messages:§r"); int i = 0;
sender.sendMessage("§bFormat: [index] message§r"); AnnouncerComponent component = (AnnouncerComponent) getComponent();
int i = 0; for (String message : component.AnnounceMessages().get())
for (String message : PluginMain.AnnounceMessages) sender.sendMessage("[" + i++ + "] " + message);
sender.sendMessage("[" + i++ + "] " + message); sender.sendMessage("§bCurrent wait time between announcements: "
sender.sendMessage("§bCurrent wait time between announcements: " + component.AnnounceTime().get() / 60 / 1000 + " minute(s)§r");
+ PluginMain.AnnounceTime / 60 / 1000 + " minute(s)§r"); return true;
return true; }
}
}
}

View file

@ -1,30 +1,28 @@
package buttondevteam.chat.commands.ucmds.announce; package buttondevteam.chat.components.announce;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import buttondevteam.chat.PluginMain; public class RemoveCommand extends AnnounceCommandBase {
public class RemoveCommand extends AnnounceCommandBase { @Override
public String[] GetHelpText(String alias) {
@Override return new String[] {
public String[] GetHelpText(String alias) { "§6---- Remove announcement ----",
return new String[] { "This command removes an announcement",
"§6---- Remove announcement ----", "Note: Please avoid using this command, if possible",
"This command removes an announcement", "Instead, use the command blocks in flatworld to set announcements",
"Note: Please avoid using this command, if possible", "This makes editing announcements easier" };
"Instead, use the command blocks in flatworld to set announcements", }
"This makes editing announcements easier" };
} @Override
public boolean OnCommand(CommandSender sender, String alias,
@Override String[] args) {
public boolean OnCommand(CommandSender sender, String alias, if (args.length < 1) {
String[] args) { sender.sendMessage("§cUsage: /u announce remove <index>");
if (args.length < 1) { return true;
sender.sendMessage("§cUsage: /u announce remove <index>"); }
return true; ((AnnouncerComponent) getComponent()).AnnounceMessages().get().remove(Integer.parseInt(args[0]));
} return true;
PluginMain.AnnounceMessages.remove(Integer.parseInt(args[0])); }
return true;
} }
}

View file

@ -1,33 +1,31 @@
package buttondevteam.chat.commands.ucmds.announce; package buttondevteam.chat.components.announce;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import buttondevteam.chat.PluginMain; public class SetTimeCommand extends AnnounceCommandBase {
public class SetTimeCommand extends AnnounceCommandBase { @Override
public String[] GetHelpText(String alias) {
@Override return new String[] { "§6---- Set time ----",
public String[] GetHelpText(String alias) { "This command sets the time between the announcements",
return new String[] { "§6---- Set time ----", "Usage: /u anonunce settime <minutes>", "Default: 15" };
"This command sets the time between the announcements", }
"Usage: /u anonunce settime <minutes>", "Default: 15" };
} @Override
public boolean OnCommand(CommandSender sender, String alias,
@Override String[] args) {
public boolean OnCommand(CommandSender sender, String alias, if (args.length < 1) {
String[] args) { return false;
if (args.length < 1) { }
return false; try {
} ((AnnouncerComponent) getComponent()).AnnounceTime().set(Integer.parseInt(args[0]) * 60 * 1000);
try { } catch (Exception e) {
PluginMain.AnnounceTime = Integer.parseInt(args[0]) * 60 * 1000; sender.sendMessage("§cMinutes argument must be a number. Got: "
} catch (Exception e) { + args[0]);
sender.sendMessage("§cMinutes argument must be a number. Got: " return true;
+ args[0]); }
return true; sender.sendMessage("Time set between announce messages");
} return true;
sender.sendMessage("Time set between announce messages"); }
return true;
} }
}

View file

@ -1,99 +1,97 @@
package buttondevteam.chat.commands.ucmds; package buttondevteam.chat.components.flair;
import java.util.Timer; import buttondevteam.chat.ChatPlayer;
import buttondevteam.chat.PlayerJoinTimerTask;
import org.bukkit.command.CommandSender; import buttondevteam.chat.commands.ucmds.UCommandBase;
import org.bukkit.entity.Player; import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.chat.CommandClass;
import buttondevteam.chat.ChatPlayer; import buttondevteam.lib.chat.OptionallyPlayerCommandClass;
import buttondevteam.chat.FlairStates; import buttondevteam.lib.player.TBMCPlayer;
import buttondevteam.chat.PlayerJoinTimerTask; import org.bukkit.command.CommandSender;
import buttondevteam.chat.PluginMain; import org.bukkit.entity.Player;
import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.chat.CommandClass; import java.util.Timer;
import buttondevteam.lib.chat.OptionallyPlayerCommandClass;
import buttondevteam.lib.player.TBMCPlayer; @CommandClass(modOnly = false)
@OptionallyPlayerCommandClass(playerOnly = true)
@CommandClass(modOnly = false) public class AcceptCommand extends UCommandBase {
@OptionallyPlayerCommandClass(playerOnly = true)
public class AcceptCommand extends UCommandBase { @Override
public String[] GetHelpText(String alias) {
@Override return new String[] { "§6---- Accept flair ----", //
public String[] GetHelpText(String alias) { "Accepts a flair from Reddit", //
return new String[] { "§6---- Accept flair ----", // "Use /u accept <username> if you commented from multiple accounts" //
"Accepts a flair from Reddit", // };
"Use /u accept <username> if you commented from multiple accounts" // }
};
} @Override
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
@Override final Player player = (Player) sender;
public boolean OnCommand(CommandSender sender, String alias, String[] args) { ChatPlayer p = TBMCPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class);
final Player player = (Player) sender; if (args.length < 1 && p.UserNames().size() > 1) {
ChatPlayer p = TBMCPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class); player.sendMessage("§9Multiple users commented your name. §bPlease pick one using /u accept <username>");
if (args.length < 1 && p.UserNames().size() > 1) { StringBuilder sb = new StringBuilder();
player.sendMessage("§9Multiple users commented your name. §bPlease pick one using /u accept <username>"); sb.append("§6Usernames:");
StringBuilder sb = new StringBuilder(); for (String username : p.UserNames())
sb.append("§6Usernames:"); sb.append(" ").append(username);
for (String username : p.UserNames()) player.sendMessage(sb.toString());
sb.append(" ").append(username); return true;
player.sendMessage(sb.toString()); }
return true; if (p.FlairState().get().equals(FlairStates.NoComment) || p.UserNames().size() == 0) {
} player.sendMessage("§cError: You need to write your username to the reddit thread at /r/ChromaGamers§r");
if (p.FlairState().get().equals(FlairStates.NoComment) || p.UserNames().size() == 0) { return true;
player.sendMessage("§cError: You need to write your username to the reddit thread at /r/ChromaGamers§r"); }
return true; if (args.length > 0 && !p.UserNames().contains(args[0])) {
} player.sendMessage("§cError: Unknown name: " + args[0] + "§r");
if (args.length > 0 && !p.UserNames().contains(args[0])) { return true;
player.sendMessage("§cError: Unknown name: " + args[0] + "§r"); }
return true; if (p.Working) {
} player.sendMessage("§cError: Something is already in progress.§r");
if (p.Working) { return true;
player.sendMessage("§cError: Something is already in progress.§r"); }
return true;
} if ((args.length > 0 ? args[0] : p.UserNames().get(0)).equals(p.UserName().get())) {
player.sendMessage("§cYou already have this user's flair.§r");
if ((args.length > 0 ? args[0] : p.UserNames().get(0)).equals(p.UserName().get())) { return true;
player.sendMessage("§cYou already have this user's flair.§r"); }
return true; if (args.length > 0)
} p.UserName().set(args[0]);
if (args.length > 0) else
p.UserName().set(args[0]); p.UserName().set(p.UserNames().get(0));
else
p.UserName().set(p.UserNames().get(0)); player.sendMessage("§bObtaining flair...");
p.Working = true;
player.sendMessage("§bObtaining flair..."); Timer timer = new Timer();
p.Working = true; PlayerJoinTimerTask tt = new PlayerJoinTimerTask() {
Timer timer = new Timer(); @Override
PlayerJoinTimerTask tt = new PlayerJoinTimerTask() { public void run() {
@Override try {
public void run() { FlairComponent.DownloadFlair(mp);
try { } catch (Exception e) {
PluginMain.Instance.DownloadFlair(mp); TBMCCoreAPI.SendException(
} catch (Exception e) { "An error occured while downloading flair for " + player.getCustomName() + "!", e);
TBMCCoreAPI.SendException( player.sendMessage(
"An error occured while downloading flair for " + player.getCustomName() + "!", e); "Sorry, but an error occured while trying to get your flair. Please contact a mod.");
player.sendMessage( mp.Working = false;
"Sorry, but an error occured while trying to get your flair. Please contact a mod."); return;
mp.Working = false; }
return;
} if (mp.FlairState().get().equals(FlairStates.Commented)) {
player.sendMessage(
if (mp.FlairState().get().equals(FlairStates.Commented)) { "Sorry, but your flair isn't recorded. Please ask an admin to set it for you. Also, prepare a comment on /r/thebutton, if possible.");
player.sendMessage( mp.Working = false;
"Sorry, but your flair isn't recorded. Please ask an admin to set it for you. Also, prepare a comment on /r/thebutton, if possible."); return;
mp.Working = false; }
return; String flair = mp.GetFormattedFlair();
} mp.FlairState().set(FlairStates.Accepted);
String flair = mp.GetFormattedFlair(); FlairComponent.ConfirmUserMessage(mp);
mp.FlairState().set(FlairStates.Accepted); player.sendMessage("§bYour flair has been set:§r " + flair);
PluginMain.ConfirmUserMessage(mp); mp.Working = false;
player.sendMessage("§bYour flair has been set:§r " + flair); }
mp.Working = false; };
} tt.mp = p;
}; timer.schedule(tt, 20);
tt.mp = p; return true;
timer.schedule(tt, 20); }
return true;
} }
}

View file

@ -0,0 +1,185 @@
package buttondevteam.chat.components.flair;
import buttondevteam.chat.ChatPlayer;
import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.architecture.ConfigData;
import buttondevteam.lib.player.TBMCPlayerBase;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.*;
public class FlairComponent extends Component {
private ConfigData<String> FlairThreadURL() {
return getConfig().getData("flairThreadURL", "https://www.reddit.com/r/Chromagamers/comments/51ys94/flair_thread_for_the_mc_server/");
}
/**
* <p>
* This variable is used as a cache for flair state checking when reading the flair thread.
* </p>
* <p>
* It's used because normally it has to load all associated player files every time to read the flair state
* </p>
*/
private Set<String> PlayersWithFlairs = new HashSet<>();
@Override
protected void enable() {
registerCommand(new AcceptCommand());
registerCommand(new IgnoreCommand());
registerCommand(new SetFlairCommand());
new Thread(this::FlairGetterThreadMethod).start();
}
@Override
protected void disable() {
}
private void FlairGetterThreadMethod() {
int errorcount = 0;
while (isEnabled()) {
try {
String body = TBMCCoreAPI.DownloadString(FlairThreadURL().get() + ".json?limit=1000");
JsonArray json = new JsonParser().parse(body).getAsJsonArray().get(1).getAsJsonObject().get("data")
.getAsJsonObject().get("children").getAsJsonArray();
for (Object obj : json) {
JsonObject item = (JsonObject) obj;
String author = item.get("data").getAsJsonObject().get("author").getAsString();
String ign = item.get("data").getAsJsonObject().get("body").getAsString();
int start = ign.indexOf("IGN:") + "IGN:".length();
if (start == -1 + "IGN:".length())
continue;
int end = ign.indexOf(' ', start);
if (end == -1 || end == start)
end = ign.indexOf('\n', start);
if (end == -1 || end == start)
ign = ign.substring(start);
else
ign = ign.substring(start, end);
ign = ign.trim();
if (PlayersWithFlairs.contains(ign))
continue;
try (ChatPlayer mp = TBMCPlayerBase.getFromName(ign, ChatPlayer.class)) { // Loads player file
if (mp == null)
continue;
/*
* if (!JoinedBefore(mp, 2015, 6, 5)) continue;
*/
if (!mp.UserNames().contains(author))
mp.UserNames().add(author);
if (mp.FlairState().get().equals(FlairStates.NoComment)) {
mp.FlairState().set(FlairStates.Commented);
ConfirmUserMessage(mp);
}
PlayersWithFlairs.add(ign); // Don't redownload even if flair isn't accepted
}
}
} catch (Exception e) {
errorcount++;
if (errorcount >= 10) {
errorcount = 0;
if (!e.getMessage().contains("Server returned HTTP response code")
&& !(e instanceof UnknownHostException))
TBMCCoreAPI.SendException("Error while getting flairs from Reddit!", e);
}
}
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
public static void DownloadFlair(ChatPlayer mp) throws IOException {
String[] flairdata = TBMCCoreAPI
.DownloadString("http://karmadecay.com/thebutton-data.php?users=" + mp.UserName().get())
.replace("\"", "").split(":");
String flair;
if (flairdata.length > 1)
flair = flairdata[1];
else
flair = "";
String flairclass;
if (flairdata.length > 2)
flairclass = flairdata[2];
else
flairclass = "unknown";
SetFlair(mp, flair, flairclass, mp.UserName().get());
}
private static void SetFlair(ChatPlayer p, String text, String flairclass, String username) {
p.UserName().set(username);
p.FlairState().set(FlairStates.Recognised);
switch (flairclass) {
case "cheater":
p.SetFlair(Short.parseShort(text), true);
return;
case "unknown":
try {
if (CheckForJoinDate(p)) {
if (text.equals("-1")) // If true, only non-presser/can't press; if false, any flair (but we can still detect can't press)
p.SetFlair(ChatPlayer.FlairTimeNonPresser);
else
p.SetFlair(ChatPlayer.FlairTimeNone); // Flair unknown
} else {
p.SetFlair(ChatPlayer.FlairTimeCantPress);
}
} catch (Exception e) {
p.FlairState().set(FlairStates.Commented); // Flair unknown
p.SetFlair(ChatPlayer.FlairTimeNone);
TBMCCoreAPI.SendException("Error while checking join date for player " + p.PlayerName() + "!", e);
}
return;
default:
break;
}
p.SetFlair(Short.parseShort(text));
}
private static boolean CheckForJoinDate(ChatPlayer mp) throws Exception {
return JoinedBefore(mp, 2015, 4, 1);
}
private static boolean JoinedBefore(ChatPlayer mp, int year, int month, int day) throws Exception {
URL url = new URL("https://www.reddit.com/u/" + mp.UserName());
URLConnection con = url.openConnection();
con.setRequestProperty("User-Agent", "TheButtonAutoFlair");
InputStream in = con.getInputStream();
HtmlCleaner cleaner = new HtmlCleaner();
TagNode node = cleaner.clean(in);
node = node.getElementsByAttValue("class", "age", true, true)[0];
node = node.getElementsByName("time", false)[0];
String joindate = node.getAttributeByName("datetime");
SimpleDateFormat parserSDF = new SimpleDateFormat("yyyy-MM-dd");
joindate = joindate.split("T")[0];
Date date = parserSDF.parse(joindate);
return date.before(new Calendar.Builder().setTimeZone(TimeZone.getTimeZone("UTC")).setDate(year, month, day)
.build().getTime());
}
public static void ConfirmUserMessage(ChatPlayer mp) {
Player p = Bukkit.getPlayer(mp.getUUID());
if (mp.FlairState().get().equals(FlairStates.Commented) && p != null)
if (mp.UserNames().size() > 1)
p.sendMessage(
"§9Multiple Reddit users commented your name. You can select with /u accept.§r §6Type /u accept or /u ignore§r");
else
p.sendMessage("§9A Reddit user commented your name. Is that you?§r §6Type /u accept or /u ignore§r");
}
}

View file

@ -1,5 +1,5 @@
package buttondevteam.chat; package buttondevteam.chat.components.flair;
public enum FlairStates { public enum FlairStates {
Accepted, Ignored, Recognised, Commented, NoComment Accepted, Ignored, Recognised, Commented, NoComment
} }

View file

@ -1,44 +1,43 @@
package buttondevteam.chat.commands.ucmds; package buttondevteam.chat.components.flair;
import org.bukkit.command.CommandSender; import buttondevteam.chat.ChatPlayer;
import org.bukkit.entity.Player; import buttondevteam.chat.commands.ucmds.UCommandBase;
import buttondevteam.lib.chat.CommandClass;
import buttondevteam.chat.ChatPlayer; import buttondevteam.lib.chat.OptionallyPlayerCommandClass;
import buttondevteam.chat.FlairStates; import buttondevteam.lib.player.TBMCPlayer;
import buttondevteam.lib.chat.CommandClass; import org.bukkit.command.CommandSender;
import buttondevteam.lib.chat.OptionallyPlayerCommandClass; import org.bukkit.entity.Player;
import buttondevteam.lib.player.TBMCPlayer;
@CommandClass(modOnly = false)
@CommandClass(modOnly = false) @OptionallyPlayerCommandClass(playerOnly = true)
@OptionallyPlayerCommandClass(playerOnly = true) public final class IgnoreCommand extends UCommandBase {
public final class IgnoreCommand extends UCommandBase {
@Override
@Override public String[] GetHelpText(String alias) {
public String[] GetHelpText(String alias) { return new String[] { "§6---- Ignore flair ----",
return new String[] { "§6---- Ignore flair ----", "Stop the \"write your name in the thread\" message from showing up" };
"Stop the \"write your name in the thread\" message from showing up" }; }
}
@Override
@Override public boolean OnCommand(CommandSender sender, String alias, String[] args) {
public boolean OnCommand(CommandSender sender, String alias, String[] args) { final Player player = (Player) sender;
final Player player = (Player) sender; ChatPlayer p = TBMCPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class);
ChatPlayer p = TBMCPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class); if (p.FlairState().get().equals(FlairStates.Accepted)) {
if (p.FlairState().get().equals(FlairStates.Accepted)) { player.sendMessage("§cYou can only ignore the \"write your name in the thread\" message.");
player.sendMessage("§cYou can only ignore the \"write your name in the thread\" message."); return true;
return true; }
} if (p.FlairState().get().equals(FlairStates.Commented)) {
if (p.FlairState().get().equals(FlairStates.Commented)) { player.sendMessage("Sorry, but your flair isn't recorded. Please ask a mod to set it for you.");
player.sendMessage("Sorry, but your flair isn't recorded. Please ask a mod to set it for you."); return true;
return true; }
} if (!p.FlairState().get().equals(FlairStates.Ignored)) {
if (!p.FlairState().get().equals(FlairStates.Ignored)) { p.FlairState().set(FlairStates.Ignored);
p.FlairState().set(FlairStates.Ignored); p.SetFlair(ChatPlayer.FlairTimeNone);
p.SetFlair(ChatPlayer.FlairTimeNone); p.UserName().set("");
p.UserName().set(""); player.sendMessage("§bYou have ignored the message.§r");
player.sendMessage("§bYou have ignored the message.§r"); } else
} else player.sendMessage("§cYou already ignored the message.§r");
player.sendMessage("§cYou already ignored the message.§r"); return true;
return true; }
}
}
}

View file

@ -1,71 +1,70 @@
package buttondevteam.chat.commands.ucmds.admin; package buttondevteam.chat.components.flair;
import org.bukkit.Bukkit; import buttondevteam.chat.ChatPlayer;
import org.bukkit.command.CommandSender; import buttondevteam.chat.commands.ucmds.admin.AdminCommandBase;
import org.bukkit.entity.Player; import buttondevteam.lib.player.TBMCPlayerBase;
import org.bukkit.Bukkit;
import buttondevteam.chat.ChatPlayer; import org.bukkit.command.CommandSender;
import buttondevteam.chat.FlairStates; import org.bukkit.entity.Player;
import buttondevteam.lib.player.TBMCPlayerBase;
public class SetFlairCommand extends AdminCommandBase {
public class SetFlairCommand extends AdminCommandBase {
@Override
@Override public String[] GetHelpText(String alias) {
public String[] GetHelpText(String alias) { return new String[] { "§6---- Set flair -----", "Set a flair for a player",
return new String[] { "§6---- Set flair -----", "Set a flair for a player", "Usage: /u admin setflair <player> <flairtime (or non-presser, cant-press, none)> <cheater(true/false)> [username]",
"Usage: /u admin setflair <player> <flairtime (or non-presser, cant-press, none)> <cheater(true/false)> [username]", "Example 1: /u admin setflair NorbiPeti 19 false NorbiPeti --> orange (19s)",
"Example 1: /u admin setflair NorbiPeti 19 false NorbiPeti --> orange (19s)", "Example 2: /u admin setflair iie 0 true asde --> purple (0s)" };
"Example 2: /u admin setflair iie 0 true asde --> purple (0s)" }; }
}
@Override
@Override public boolean OnCommand(CommandSender sender, String alias, String[] args) {
public boolean OnCommand(CommandSender sender, String alias, String[] args) { if (args.length < 3) {
if (args.length < 3) { return false;
return false; }
} Player p = Bukkit.getPlayer(args[0]);
Player p = Bukkit.getPlayer(args[0]); if (p == null) {
if (p == null) { sender.sendMessage("§cPlayer not found.&r");
sender.sendMessage("§cPlayer not found.&r"); return true;
return true; }
} short flairtime = 0x00;
short flairtime = 0x00; if (args[1].equalsIgnoreCase("non-presser"))
if (args[1].equalsIgnoreCase("non-presser")) flairtime = ChatPlayer.FlairTimeNonPresser;
flairtime = ChatPlayer.FlairTimeNonPresser; else if (args[1].equalsIgnoreCase("cant-press"))
else if (args[1].equalsIgnoreCase("cant-press")) flairtime = ChatPlayer.FlairTimeCantPress;
flairtime = ChatPlayer.FlairTimeCantPress; else if (args[1].equalsIgnoreCase("none"))
else if (args[1].equalsIgnoreCase("none")) flairtime = ChatPlayer.FlairTimeNone;
flairtime = ChatPlayer.FlairTimeNone; else {
else { try {
try { flairtime = Short.parseShort(args[1]);
flairtime = Short.parseShort(args[1]); } catch (Exception e) {
} catch (Exception e) { sender.sendMessage(
sender.sendMessage( "§cFlairtime must be a number, \"non-presser\", \"cant-press\" or \"none\". Run without args to see usage.");
"§cFlairtime must be a number, \"non-presser\", \"cant-press\" or \"none\". Run without args to see usage."); return true;
return true; }
} }
} boolean cheater;
boolean cheater = false; if (args[2].equalsIgnoreCase("true"))
if (args[2].equalsIgnoreCase("true")) cheater = true;
cheater = true; else if (args[2].equalsIgnoreCase("false"))
else if (args[2].equalsIgnoreCase("false")) cheater = false;
cheater = false; else {
else { sender.sendMessage("§cUnknown value for cheater parameter.");
sender.sendMessage("§cUnknown value for cheater parameter. Run without args to see usage."); return false;
return true; }
} ChatPlayer mp = TBMCPlayerBase.getPlayer(p.getUniqueId(), ChatPlayer.class);
ChatPlayer mp = TBMCPlayerBase.getPlayer(p.getUniqueId(), ChatPlayer.class); mp.SetFlair(flairtime, cheater);
mp.SetFlair(flairtime, cheater); mp.FlairState().set(FlairStates.Accepted);
mp.FlairState().set(FlairStates.Accepted); if (args.length < 4)
if (args.length < 4) mp.UserName().set("");
mp.UserName().set(""); else {
else { mp.UserName().set(args[3]);
mp.UserName().set(args[3]); if (!mp.UserNames().contains(args[3]))
if (!mp.UserNames().contains(args[3])) mp.UserNames().add(args[3]);
mp.UserNames().add(args[3]); }
} sender.sendMessage(
sender.sendMessage( "§bThe flair has been set. Player: " + mp.PlayerName() + " Flair: " + mp.GetFormattedFlair() + "§r");
"§bThe flair has been set. Player: " + mp.PlayerName() + " Flair: " + mp.GetFormattedFlair() + "§r"); return true;
return true; }
}
}
}

View file

@ -1,8 +1,8 @@
package buttondevteam.chat.commands.ucmds; package buttondevteam.chat.components.towncolors;
import buttondevteam.chat.ChatPlayer; import buttondevteam.chat.ChatPlayer;
import buttondevteam.chat.PluginMain; import buttondevteam.chat.commands.ucmds.UCommandBase;
import buttondevteam.chat.listener.PlayerJoinLeaveListener; import buttondevteam.chat.components.towny.TownyComponent;
import buttondevteam.lib.chat.Color; import buttondevteam.lib.chat.Color;
import buttondevteam.lib.chat.CommandClass; import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.chat.OptionallyPlayerCommandClass; import buttondevteam.lib.chat.OptionallyPlayerCommandClass;
@ -34,7 +34,7 @@ public class NColorCommand extends UCommandBase {
Resident res; Resident res;
Town town; Town town;
try { try {
if ((res = PluginMain.TU.getResidentMap().get(player.getName().toLowerCase())) == null || !res.hasTown() if ((res = TownyComponent.TU.getResidentMap().get(player.getName().toLowerCase())) == null || !res.hasTown()
|| (town = res.getTown()) == null) { || (town = res.getTown()) == null) {
player.sendMessage("§cYou need to be in a town."); player.sendMessage("§cYou need to be in a town.");
return true; return true;
@ -53,7 +53,7 @@ public class NColorCommand extends UCommandBase {
return true; return true;
} }
String[] nameparts = arg.split("[|:]"); String[] nameparts = arg.split("[|:]");
Color[] towncolors = PluginMain.TownColors.get(town.getName().toLowerCase()); Color[] towncolors = TownColorComponent.TownColors.get(town.getName().toLowerCase());
if (towncolors == null) { if (towncolors == null) {
player.sendMessage("§cYour town doesn't have a color set. The town mayor can set it using /u towncolor."); player.sendMessage("§cYour town doesn't have a color set. The town mayor can set it using /u towncolor.");
return true; return true;
@ -71,8 +71,8 @@ public class NColorCommand extends UCommandBase {
return true; return true;
} }
ChatPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class).NameColorLocations() ChatPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class).NameColorLocations()
.set(new ArrayList<>(Arrays.stream(nameparts).map(np -> np.length()).collect(Collectors.toList()))); // No byte[], no TIntArrayList .set(new ArrayList<>(Arrays.stream(nameparts).map(String::length).collect(Collectors.toList()))); // No byte[], no TIntArrayList
PlayerJoinLeaveListener.updatePlayerColors(player); TownColorComponent.updatePlayerColors(player);
player.sendMessage("§bName colors set: " + player.getDisplayName()); player.sendMessage("§bName colors set: " + player.getDisplayName());
return true; return true;
} }

View file

@ -1,6 +1,7 @@
package buttondevteam.chat.commands.ucmds; package buttondevteam.chat.components.towncolors;
import buttondevteam.chat.PluginMain; import buttondevteam.chat.commands.ucmds.UCommandBase;
import buttondevteam.chat.components.towny.TownyComponent;
import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.chat.CommandClass; import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.chat.OptionallyPlayerCommandClass; import buttondevteam.lib.chat.OptionallyPlayerCommandClass;
@ -26,8 +27,8 @@ public class NationColorCommand extends UCommandBase {
@Override @Override
public boolean OnCommand(Player player, String alias, String[] args) { public boolean OnCommand(Player player, String alias, String[] args) {
Resident res; Resident res;
if (!(PluginMain.TU.getResidentMap().containsKey(player.getName().toLowerCase()) if (!(TownyComponent.TU.getResidentMap().containsKey(player.getName().toLowerCase())
&& (res = PluginMain.TU.getResidentMap().get(player.getName().toLowerCase())).isKing())) { && (res = TownyComponent.TU.getResidentMap().get(player.getName().toLowerCase())).isKing())) {
player.sendMessage("§cYou need to be the king of a nation to set it's colors."); player.sendMessage("§cYou need to be the king of a nation to set it's colors.");
return true; return true;
} }
@ -44,6 +45,6 @@ public class NationColorCommand extends UCommandBase {
player.sendMessage("§cCouldn't find your town/nation... Error reported."); player.sendMessage("§cCouldn't find your town/nation... Error reported.");
return true; return true;
} }
return buttondevteam.chat.commands.ucmds.admin.NationColorCommand.SetNationColor(player, alias, a); return buttondevteam.chat.components.towncolors.admin.NationColorCommand.SetNationColor(player, alias, a);
} }
} }

View file

@ -1,11 +1,13 @@
package buttondevteam.chat.commands.ucmds; package buttondevteam.chat.components.towncolors;
import buttondevteam.chat.PluginMain; import buttondevteam.chat.commands.ucmds.UCommandBase;
import buttondevteam.chat.components.towny.TownyComponent;
import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.chat.CommandClass; import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.chat.OptionallyPlayerCommandClass; import buttondevteam.lib.chat.OptionallyPlayerCommandClass;
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException; import com.palmergames.bukkit.towny.exceptions.NotRegisteredException;
import com.palmergames.bukkit.towny.object.Resident; import com.palmergames.bukkit.towny.object.Resident;
import lombok.val;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@CommandClass // TODO: /u u when annotation not present @CommandClass // TODO: /u u when annotation not present
@ -14,7 +16,8 @@ public class TownColorCommand extends UCommandBase {
@Override @Override
public String GetHelpText(String alias)[] { public String GetHelpText(String alias)[] {
StringBuilder cns = new StringBuilder(" <colorname1>"); StringBuilder cns = new StringBuilder(" <colorname1>");
for (int i = 2; i <= ColorCount; i++) val comp = (TownColorComponent) getComponent();
for (int i = 2; i <= comp.colorCount().get(); i++)
cns.append(" [colorname").append(i).append("]"); cns.append(" [colorname").append(i).append("]");
return new String[] { // return new String[] { //
"§6---- Town Color ----", // "§6---- Town Color ----", //
@ -26,18 +29,17 @@ public class TownColorCommand extends UCommandBase {
}; };
} }
public static byte ColorCount;
@Override @Override
public boolean OnCommand(Player player, String alias, String[] args) { public boolean OnCommand(Player player, String alias, String[] args) {
Resident res; Resident res;
if (!(PluginMain.TU.getResidentMap().containsKey(player.getName().toLowerCase()) if (!(TownyComponent.TU.getResidentMap().containsKey(player.getName().toLowerCase())
&& (res = PluginMain.TU.getResidentMap().get(player.getName().toLowerCase())).isMayor())) { && (res = TownyComponent.TU.getResidentMap().get(player.getName().toLowerCase())).isMayor())) {
player.sendMessage("§cYou need to be the mayor of a town to set it's colors."); player.sendMessage("§cYou need to be the mayor of a town to set it's colors.");
return true; return true;
} }
if (args.length > ColorCount) { val comp = (TownColorComponent) getComponent();
player.sendMessage("You can only use " + ColorCount + " color" + (ColorCount > 1 ? "s" : "") + "."); if (args.length > comp.colorCount().get()) {
player.sendMessage("You can only use " + comp.colorCount().get() + " color" + (comp.colorCount().get() > 1 ? "s" : "") + ".");
return true; return true;
} }
String[] a = new String[args.length + 1]; String[] a = new String[args.length + 1];
@ -49,6 +51,6 @@ public class TownColorCommand extends UCommandBase {
player.sendMessage("§cCouldn't find your town... Error reported."); player.sendMessage("§cCouldn't find your town... Error reported.");
return true; return true;
} }
return buttondevteam.chat.commands.ucmds.admin.TownColorCommand.SetTownColor(player, alias, a); return buttondevteam.chat.components.towncolors.admin.TownColorCommand.SetTownColor(player, alias, a);
} }
} }

View file

@ -0,0 +1,201 @@
package buttondevteam.chat.components.towncolors;
import buttondevteam.chat.ChatPlayer;
import buttondevteam.chat.PluginMain;
import buttondevteam.chat.components.towncolors.admin.TCCount;
import buttondevteam.chat.components.towny.TownyComponent;
import buttondevteam.core.ComponentManager;
import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.architecture.ComponentMetadata;
import buttondevteam.lib.architecture.ConfigData;
import buttondevteam.lib.chat.Color;
import com.earth2me.essentials.User;
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException;
import lombok.experimental.var;
import lombok.val;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.dynmap.towny.DTBridge;
import org.dynmap.towny.DynmapTownyPlugin;
import java.io.File;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
@ComponentMetadata(depends = TownyComponent.class)
public class TownColorComponent extends Component {
/**
* Names lowercased
*/
public static Map<String, Color[]> TownColors = new HashMap<>();
/**
* Names lowercased - nation color gets added to town colors when needed
*/
public static Map<String, Color> NationColor = new HashMap<>();
public ConfigData<Byte> colorCount() {
return getConfig().getData("colorCount", (byte) 1, cc -> ((Integer) cc).byteValue(), Byte::intValue);
}
public ConfigData<Boolean> useNationColors() { //TODO
return getConfig().getData("useNationColors", true);
}
@SuppressWarnings("unchecked")
@Override
protected void enable() {
//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))));
Consumer<ConfigurationSection> loadNC = ncs ->
TownColorComponent.NationColor.putAll(ncs.getValues(true).entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, v -> Color.valueOf((String) v.getValue()))));
var cs = getConfig().getConfig().getConfigurationSection("towncolors");
if (cs != null)
loadTC.accept(cs);
else
load_old(loadTC, null); //Load old data
var ncs = getConfig().getConfig().getConfigurationSection("nationcolors");
if (ncs != null)
loadNC.accept(ncs);
else
load_old(null, loadNC); //Why not choose by making different args null
TownColors.keySet().removeIf(t -> !TownyComponent.TU.getTownsMap().containsKey(t)); // Removes town colors for deleted/renamed towns
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())
setTownColor(dtp, buttondevteam.chat.components.towncolors.admin.TownColorCommand.getTownNameCased(entry.getKey()), entry.getValue());
});
registerCommand(new TownColorCommand());
registerCommand(new NationColorCommand());
registerCommand(new buttondevteam.chat.components.towncolors.admin.TownColorCommand());
registerCommand(new buttondevteam.chat.components.towncolors.admin.NationColorCommand());
registerCommand(new TCCount());
}
@Override
protected void disable() {
getConfig().getConfig().createSection("towncolors", TownColors.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
v -> Arrays.stream(v.getValue()).map(Enum::toString).toArray(String[]::new))));
getConfig().getConfig().createSection("nationcolors", NationColor.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
v -> v.getValue().toString())));
}
/**
* Sets a town's color on Dynmap.
*
* @param dtp A reference for the Dynmap-Towny plugin
* @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) {
Function<Color, Integer> c2i = c -> c.getRed() << 16 | c.getGreen() << 8 | c.getBlue();
try {
DTBridge.setTownColor(dtp, town, c2i.apply(colors[0]),
c2i.apply(colors.length > 1 ? colors[1] : colors[0]));
} catch (Exception e) {
TBMCCoreAPI.SendException("Failed to set town color for town " + town + "!", e);
}
}
private static String getPlayerNickname(Player player, User user, ChatPlayer cp) {
String nickname = user.getNick(true);
if (nickname.contains("~")) //StartsWith doesn't work because of color codes
nickname = nickname.replace("~", ""); //It gets stacked otherwise
String name = ChatColor.stripColor(nickname); //Enforce "town colors" on non-members
val res = TownyComponent.TU.getResidentMap().get(player.getName().toLowerCase());
if (res == null || !res.hasTown())
return name;
try {
Color[] clrs = Optional.ofNullable(
TownColors.get(res.getTown().getName().toLowerCase())
).orElse(new Color[]{Color.White}); //Use white as default town color
StringBuilder ret = new StringBuilder();
AtomicInteger prevlen = new AtomicInteger();
BiFunction<Color, Integer, String> anyColoredNamePart = (c, len) -> "§" //Len==0 if last part
+ Integer.toHexString(c.ordinal()) // 'Odds' are the last character is chopped off so we make sure to include all chars at the end
+ (len == 0 ? name.substring(prevlen.get())
: name.substring(prevlen.get(), prevlen.addAndGet(len)));
BiFunction<Integer, Integer, String> coloredNamePart = (len, i)
-> anyColoredNamePart.apply(clrs[i], i + 1 == clrs.length ? 0 : len);
final int len = name.length() / (clrs.length + 1); //The above param is needed because this isn't always passed
Color nc;
/*if(res.getTown().hasNation()
&&(nc=PluginMain.NationColor.get(res.getTown().getNation().getName().toLowerCase()))!=null)
len = name.length() / (clrs.length+1);
else
len = name.length() / clrs.length;*/
val nclar = cp.NameColorLocations().get();
int[] ncl = nclar == null ? null : nclar.stream().mapToInt(Integer::intValue).toArray();
if (ncl != null && (Arrays.stream(ncl).sum() != name.length() || ncl.length != clrs.length + 1)) //+1: Nation color
ncl = null; // Reset if name length changed
//System.out.println("ncl: "+Arrays.toString(ncl)+" - sum: "+Arrays.stream(ncl).sum()+" - name len: "+name.length());
if (!res.getTown().hasNation()
|| (nc = NationColor.get(res.getTown().getNation().getName().toLowerCase())) == null)
nc = Color.White;
ret.append(anyColoredNamePart.apply(nc, ncl == null ? len : ncl[0])); //Make first color the nation color
for (int i = 0; i < clrs.length; i++)
//ret.append(coloredNamePart.apply(ncl == null ? len : (nc==null?ncl[i]:ncl[i+1]), i));
ret.append(coloredNamePart.apply(ncl == null ? len : ncl[i + 1], i));
return ret.toString();
} catch (NotRegisteredException e) {
return nickname;
}
}
/**
* Checks if the component is enabled
*/
public static void updatePlayerColors(Player player) { //Probably while ingame (/u ncolor)
updatePlayerColors(player, ChatPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class));
}
/**
* Checks if the component is enabled
*/
public static void updatePlayerColors(Player player, ChatPlayer cp) { //Probably at join - nop, nicknames
if (!ComponentManager.isEnabled(TownColorComponent.class))
return;
User user = PluginMain.essentials.getUser(player);
user.setNickname(getPlayerNickname(player, user, cp));
user.setDisplayNick(); //These won't fire the nick change event
cp.FlairUpdate(); //Update in list
}
private static void load_old(Consumer<ConfigurationSection> loadTC,
Consumer<ConfigurationSection> loadNC) {
PluginMain.Instance.getLogger().info("Loading files...");
try {
File file = new File("TBMC/chatsettings.yml");
if (file.exists()) {
YamlConfiguration yc = new YamlConfiguration();
yc.load(file);
ConfigurationSection cs;
if (loadTC != null && (cs = yc.getConfigurationSection("towncolors")) != null)
loadTC.accept(cs);
if (loadNC != null && (cs = yc.getConfigurationSection("nationcolors")) != null)
loadNC.accept(cs);
PluginMain.Instance.getLogger().info("Loaded files!");
} else
PluginMain.Instance.getLogger().info("No files to load, first run probably.");
} catch (Exception e) {
TBMCCoreAPI.SendException("Error while loading chat files!", e);
}
}
}

View file

@ -1,4 +1,4 @@
package buttondevteam.chat.listener; package buttondevteam.chat.components.towncolors;
import buttondevteam.chat.PluginMain; import buttondevteam.chat.PluginMain;
import com.earth2me.essentials.User; import com.earth2me.essentials.User;
@ -16,21 +16,21 @@ import java.util.Objects;
public class TownyListener implements Listener { public class TownyListener implements Listener {
@EventHandler @EventHandler
public void onTownRename(RenameTownEvent event) { public void onTownRename(RenameTownEvent event) {
val clrs = PluginMain.TownColors.remove(event.getOldName().toLowerCase()); val clrs = TownColorComponent.TownColors.remove(event.getOldName().toLowerCase());
if (clrs != null) if (clrs != null)
PluginMain.TownColors.put(event.getTown().getName().toLowerCase(), clrs); TownColorComponent.TownColors.put(event.getTown().getName().toLowerCase(), clrs);
} }
@EventHandler //Gets called on town load as well @EventHandler //Gets called on town load as well
public void onTownJoin(TownAddResidentEvent event) { public void onTownJoin(TownAddResidentEvent event) {
Player p = Bukkit.getPlayer(event.getResident().getName()); Player p = Bukkit.getPlayer(event.getResident().getName());
if (p != null) if (p != null)
PlayerJoinLeaveListener.updatePlayerColors(p); TownColorComponent.updatePlayerColors(p);
} }
public static void updateTownMembers(Town town) { public static void updateTownMembers(Town town) {
town.getResidents().stream().map(r -> Bukkit.getPlayer(r.getName())) town.getResidents().stream().map(r -> Bukkit.getPlayer(r.getName()))
.filter(Objects::nonNull).forEach(PlayerJoinLeaveListener::updatePlayerColors); .filter(Objects::nonNull).forEach(TownColorComponent::updatePlayerColors);
} }
@EventHandler @EventHandler
@ -47,7 +47,7 @@ public class TownyListener implements Listener {
@EventHandler @EventHandler
public void onTownDelete(DeleteTownEvent event) { public void onTownDelete(DeleteTownEvent event) {
PluginMain.TownColors.remove(event.getTownName().toLowerCase()); TownColorComponent.TownColors.remove(event.getTownName().toLowerCase());
} }
@EventHandler @EventHandler
@ -61,9 +61,9 @@ public class TownyListener implements Listener {
@EventHandler @EventHandler
public void onNationRename(RenameNationEvent event) { public void onNationRename(RenameNationEvent event) {
val clrs = PluginMain.NationColor.remove(event.getOldName().toLowerCase()); val clrs = TownColorComponent.NationColor.remove(event.getOldName().toLowerCase());
if (clrs != null) if (clrs != null)
PluginMain.NationColor.put(event.getNation().getName().toLowerCase(), clrs); TownColorComponent.NationColor.put(event.getNation().getName().toLowerCase(), clrs);
} }
@EventHandler //Gets called on town load as well @EventHandler //Gets called on town load as well
@ -78,7 +78,7 @@ public class TownyListener implements Listener {
@EventHandler @EventHandler
public void onNationDelete(DeleteNationEvent event) { public void onNationDelete(DeleteNationEvent event) {
PluginMain.NationColor.remove(event.getNationName().toLowerCase()); TownColorComponent.NationColor.remove(event.getNationName().toLowerCase());
} }
@EventHandler @EventHandler

View file

@ -1,7 +1,10 @@
package buttondevteam.chat.commands.ucmds.admin; package buttondevteam.chat.components.towncolors.admin;
import buttondevteam.chat.PluginMain; import buttondevteam.chat.PluginMain;
import buttondevteam.chat.listener.TownyListener; import buttondevteam.chat.commands.ucmds.admin.AdminCommandBase;
import buttondevteam.chat.components.towncolors.TownColorComponent;
import buttondevteam.chat.components.towncolors.TownyListener;
import buttondevteam.chat.components.towny.TownyComponent;
import buttondevteam.lib.chat.Color; import buttondevteam.lib.chat.Color;
import com.palmergames.bukkit.towny.object.Nation; import com.palmergames.bukkit.towny.object.Nation;
import com.palmergames.bukkit.towny.object.Town; import com.palmergames.bukkit.towny.object.Town;
@ -31,7 +34,7 @@ public class NationColorCommand extends AdminCommandBase {
sender.sendMessage("§cYou can only use one color as a nation color."); sender.sendMessage("§cYou can only use one color as a nation color.");
return true; return true;
} }
final Nation nation = PluginMain.TU.getNationsMap().get(args[0].toLowerCase()); final Nation nation = TownyComponent.TU.getNationsMap().get(args[0].toLowerCase());
if (nation == null) { if (nation == null) {
sender.sendMessage("§cThe nation '" + args[0] + "' cannot be found."); sender.sendMessage("§cThe nation '" + args[0] + "' cannot be found.");
return true; return true;
@ -39,14 +42,14 @@ public class NationColorCommand extends AdminCommandBase {
val c = TownColorCommand.getColorOrSendError(args[1], sender); val c = TownColorCommand.getColorOrSendError(args[1], sender);
if (!c.isPresent()) return true; if (!c.isPresent()) return true;
if (!c.get().getName().equals(Color.White.getName())) { //Default nation color if (!c.get().getName().equals(Color.White.getName())) { //Default nation color
for (val nc : PluginMain.NationColor.values()) { for (val nc : TownColorComponent.NationColor.values()) {
if (nc.getName().equals(c.get().getName())) { if (nc.getName().equals(c.get().getName())) {
sender.sendMessage("§cAnother nation already uses this color!"); sender.sendMessage("§cAnother nation already uses this color!");
return true; return true;
} }
} }
} }
PluginMain.NationColor.put(args[0].toLowerCase(), c.get()); TownColorComponent.NationColor.put(args[0].toLowerCase(), c.get());
Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> { Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
for (Town t : nation.getTowns()) for (Town t : nation.getTowns())
TownyListener.updateTownMembers(t); TownyListener.updateTownMembers(t);

View file

@ -1,5 +1,8 @@
package buttondevteam.chat.commands.ucmds.admin; package buttondevteam.chat.components.towncolors.admin;
import buttondevteam.chat.commands.ucmds.admin.AdminCommandBase;
import buttondevteam.chat.components.towncolors.TownColorComponent;
import lombok.val;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
public class TCCount extends AdminCommandBase { public class TCCount extends AdminCommandBase {
@ -20,7 +23,8 @@ public class TCCount extends AdminCommandBase {
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
return false; return false;
} }
buttondevteam.chat.commands.ucmds.TownColorCommand.ColorCount = count; val comp = (TownColorComponent) getComponent();
comp.colorCount().set(count);
sender.sendMessage("Color count set to " + count); sender.sendMessage("Color count set to " + count);
return true; return true;
} }

View file

@ -1,7 +1,10 @@
package buttondevteam.chat.commands.ucmds.admin; package buttondevteam.chat.components.towncolors.admin;
import buttondevteam.chat.PluginMain; import buttondevteam.chat.PluginMain;
import buttondevteam.chat.listener.TownyListener; import buttondevteam.chat.commands.ucmds.admin.AdminCommandBase;
import buttondevteam.chat.components.towncolors.TownColorComponent;
import buttondevteam.chat.components.towncolors.TownyListener;
import buttondevteam.chat.components.towny.TownyComponent;
import buttondevteam.lib.chat.Color; import buttondevteam.lib.chat.Color;
import com.palmergames.bukkit.towny.object.Town; import com.palmergames.bukkit.towny.object.Town;
import lombok.val; import lombok.val;
@ -35,28 +38,28 @@ public class TownColorCommand extends AdminCommandBase {
public static boolean SetTownColor(CommandSender sender, String alias, String[] args) { public static boolean SetTownColor(CommandSender sender, String alias, String[] args) {
if (args.length < 2) if (args.length < 2)
return false; return false;
if (!PluginMain.TU.getTownsMap().containsKey(args[0].toLowerCase())) { if (!TownyComponent.TU.getTownsMap().containsKey(args[0].toLowerCase())) {
sender.sendMessage("§cThe town '" + args[0] + "' cannot be found."); sender.sendMessage("§cThe town '" + args[0] + "' cannot be found.");
return true; return true;
} }
Color[] clrs = new Color[args.length - 1]; Color[] clrs = new Color[args.length - 1];
Town targetTown = PluginMain.TU.getTownsMap().get(args[0].toLowerCase()); Town targetTown = TownyComponent.TU.getTownsMap().get(args[0].toLowerCase());
for (int i = 1; i < args.length; i++) { for (int i = 1; i < args.length; i++) {
val c = getColorOrSendError(args[i], sender); val c = getColorOrSendError(args[i], sender);
if (!c.isPresent()) if (!c.isPresent())
return true; return true;
clrs[i - 1] = c.get(); clrs[i - 1] = c.get();
} }
for (Map.Entry<String, Color[]> other : PluginMain.TownColors.entrySet()) { for (Map.Entry<String, Color[]> other : TownColorComponent.TownColors.entrySet()) {
Color nc, tnc; Color nc, tnc;
try { try {
nc = PluginMain.NationColor.get(PluginMain.TU.getTownsMap().get(other.getKey()).getNation().getName().toLowerCase()); 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 } catch (Exception e) { //Too lazy for lots of null-checks and it may throw exceptions anyways
nc = null; nc = null;
} }
if (nc == null) nc = Color.White; //Default nation color if (nc == null) nc = Color.White; //Default nation color
try { try {
tnc = PluginMain.NationColor.get(targetTown.getNation().getName().toLowerCase()); tnc = TownColorComponent.NationColor.get(targetTown.getNation().getName().toLowerCase());
} catch (Exception e) { } catch (Exception e) {
tnc = null; tnc = null;
} }
@ -74,7 +77,7 @@ public class TownColorCommand extends AdminCommandBase {
} }
} }
} }
PluginMain.TownColors.put(args[0].toLowerCase(), clrs); TownColorComponent.TownColors.put(args[0].toLowerCase(), clrs);
TownyListener.updateTownMembers(targetTown); TownyListener.updateTownMembers(targetTown);
val dtp = (DynmapTownyPlugin) Bukkit.getPluginManager().getPlugin("Dynmap-Towny"); val dtp = (DynmapTownyPlugin) Bukkit.getPluginManager().getPlugin("Dynmap-Towny");
@ -83,7 +86,7 @@ public class TownColorCommand extends AdminCommandBase {
PluginMain.Instance.getLogger().warning("Dynmap-Towny not found for setting town color!"); PluginMain.Instance.getLogger().warning("Dynmap-Towny not found for setting town color!");
return true; return true;
} }
PluginMain.setTownColor(dtp, targetTown.getName(), clrs); TownColorComponent.setTownColor(dtp, targetTown.getName(), clrs);
sender.sendMessage("§bColor(s) set."); sender.sendMessage("§bColor(s) set.");
return true; return true;
} }
@ -103,6 +106,6 @@ public class TownColorCommand extends AdminCommandBase {
} }
public static String getTownNameCased(String name) { public static String getTownNameCased(String name) {
return PluginMain.TU.getTownsMap().get(name.toLowerCase()).getName(); return TownyComponent.TU.getTownsMap().get(name.toLowerCase()).getName();
} }
} }

View file

@ -0,0 +1,60 @@
package buttondevteam.chat.components.towny;
import buttondevteam.chat.ChatProcessing;
import buttondevteam.chat.PluginMain;
import buttondevteam.component.channel.Channel;
import buttondevteam.lib.chat.TBMCChatAPI;
import com.palmergames.bukkit.towny.TownyLogger;
import lombok.val;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.regex.Pattern;
public class TownyAnnouncer {
private static final Pattern LOG_TYPE_PATTERN = Pattern.compile("\\[(\\w+) (?:Msg|Message)](?: (\\w+):)?");
private static final Handler HANDLER = new Handler() {
@Override
public void publish(LogRecord logRecord) {
if (logRecord.getMessage() == null) return;
val m = LOG_TYPE_PATTERN.matcher(logRecord.getMessage());
if (!m.find()) return;
String groupID = m.group(2); //The group ID is correctly cased
switch (String.valueOf(m.group(1))) { //valueOf: Handles null
case "Town":
TBMCChatAPI.SendSystemMessage(PluginMain.TownChat,
new Channel.RecipientTestResult(TownyComponent.getTownNationIndex(groupID, false), groupID),
logRecord.getMessage(), ChatProcessing.MCORIGIN);
break;
case "Nation":
TBMCChatAPI.SendSystemMessage(PluginMain.NationChat,
new Channel.RecipientTestResult(TownyComponent.getTownNationIndex(groupID, true), groupID),
logRecord.getMessage(), ChatProcessing.MCORIGIN);
break;
case "Global":
TBMCChatAPI.SendSystemMessage(Channel.GlobalChat,
Channel.RecipientTestResult.ALL,
logRecord.getMessage(), ChatProcessing.MCORIGIN);
break;
}
}
@Override
public void flush() {
}
@Override
public void close() throws SecurityException {
}
};
public static void setup() {
TownyLogger.log.addHandler(HANDLER);
}
public static void setdown() {
TownyLogger.log.removeHandler(HANDLER);
}
}

View file

@ -0,0 +1,94 @@
package buttondevteam.chat.components.towny;
import buttondevteam.chat.PluginMain;
import buttondevteam.component.channel.Channel;
import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.chat.Color;
import buttondevteam.lib.chat.TBMCChatAPI;
import com.palmergames.bukkit.towny.Towny;
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException;
import com.palmergames.bukkit.towny.object.Nation;
import com.palmergames.bukkit.towny.object.Resident;
import com.palmergames.bukkit.towny.object.Town;
import com.palmergames.bukkit.towny.object.TownyUniverse;
import lombok.val;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.stream.Collectors;
public class TownyComponent extends Component {
public static TownyUniverse TU;
private static ArrayList<String> Towns;
private static ArrayList<String> Nations;
@Override
protected void enable() {
TU = ((Towny) Bukkit.getPluginManager().getPlugin("Towny")).getTownyUniverse();
Towns = TU.getTownsMap().values().stream().map(Town::getName).collect(Collectors.toCollection(ArrayList::new)); // Creates a snapshot of towns, new towns will be added when needed
Nations = TU.getNationsMap().values().stream().map(Nation::getName).collect(Collectors.toCollection(ArrayList::new)); // Same here but with nations
TBMCChatAPI.RegisterChatChannel(
PluginMain.TownChat = new Channel("§3TC§f", Color.DarkAqua, "tc", s -> checkTownNationChat(s, false)));
TBMCChatAPI.RegisterChatChannel(
PluginMain.NationChat = new Channel("§6NC§f", Color.Gold, "nc", s -> checkTownNationChat(s, true)));
TownyAnnouncer.setup();
}
@Override
protected void disable() {
TownyAnnouncer.setdown();
}
/**
* Return the error message for the message sender if they can't send it and the score
*/
private static Channel.RecipientTestResult checkTownNationChat(CommandSender sender, boolean nationchat) {
if (!(sender instanceof Player))
return new Channel.RecipientTestResult("§cYou are not a player!");
Resident resident = TU.getResidentMap().get(sender.getName().toLowerCase());
Channel.RecipientTestResult result = checkTownNationChatInternal(sender, nationchat, resident);
if (result.errormessage != null && resident != null && resident.getModes().contains("spy")) // Only use spy if they wouldn't see it
result = new Channel.RecipientTestResult(1000, "allspies"); // There won't be more than a thousand towns/nations probably
return result;
}
private static Channel.RecipientTestResult checkTownNationChatInternal(CommandSender sender, boolean nationchat,
Resident resident) {
try {
/*
* p.sendMessage(String.format("[SPY-%s] - %s: %s", channel.DisplayName, ((Player) sender).getDisplayName(), message));
*/
Town town = null;
if (resident != null && resident.hasTown())
town = resident.getTown();
if (town == null)
return new Channel.RecipientTestResult("You aren't in a town.");
Nation nation = null;
int index;
if (nationchat) {
if (town.hasNation())
nation = town.getNation();
if (nation == null)
return new Channel.RecipientTestResult("Your town isn't in a nation.");
index = getTownNationIndex(nation.getName(), true);
} else
index = getTownNationIndex(town.getName(), false);
return new Channel.RecipientTestResult(index, nationchat ? nation.getName() : town.getName());
} catch (NotRegisteredException e) {
return new Channel.RecipientTestResult("You (probably) aren't knwon by Towny! (Not in a town)");
}
}
public static int getTownNationIndex(String name, boolean nation) {
val list = nation ? Nations : Towns;
int index = list.indexOf(name);
if (index < 0) {
list.add(name);
index = list.size() - 1;
}
return index;
}
}

View file

@ -1,394 +1,398 @@
package buttondevteam.chat.formatting; package buttondevteam.chat.formatting;
import buttondevteam.chat.ChatProcessing; import buttondevteam.chat.ChatProcessing;
import buttondevteam.chat.commands.ucmds.admin.DebugCommand; import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
import buttondevteam.lib.chat.Color; import buttondevteam.lib.chat.Color;
import buttondevteam.lib.chat.Priority; import buttondevteam.lib.chat.Priority;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.val; import lombok.val;
import java.util.*; import java.util.*;
import java.util.function.BiFunction; import java.util.function.Predicate;
import java.util.function.Predicate; import java.util.regex.Matcher;
import java.util.regex.Matcher; import java.util.regex.Pattern;
import java.util.regex.Pattern; import java.util.stream.Collectors;
import java.util.stream.Collectors;
/**
/** * A {@link ChatFormatter} shows what formatting to use based on regular expressions. {@link ChatFormatter#Combine(List, String, TellrawPart)} is used to turn it into a {@link TellrawPart}, combining
* A {@link ChatFormatter} shows what formatting to use based on regular expressions. {@link ChatFormatter#Combine(List, String, TellrawPart)} is used to turn it into a {@link TellrawPart}, combining * intersecting parts found, for example when {@code _abc*def*ghi_} is said in chat, it'll turn it into an underlined part, then an underlined <i>and italics</i> part, finally an underlined part
* intersecting parts found, for example when {@code _abc*def*ghi_} is said in chat, it'll turn it into an underlined part, then an underlined <i>and italics</i> part, finally an underlined part * again.
* again. *
* * @author NorbiPeti
* @author NorbiPeti *
* */
*/ @Data
@Data @Builder
@Builder public final class ChatFormatter {
public final class ChatFormatter { Pattern regex;
Pattern regex; boolean italic;
boolean italic; boolean bold;
boolean bold; boolean underlined;
boolean underlined; boolean strikethrough;
boolean strikethrough; boolean obfuscated;
boolean obfuscated; Color color;
Color color; TriFunc<String, ChatFormatter, FormattedSection, String> onmatch;
BiFunction<String, ChatFormatter, String> onmatch; String openlink;
String openlink; @Builder.Default
@Builder.Default Priority priority = Priority.Normal;
Priority priority = Priority.Normal; @Builder.Default
@Builder.Default short removeCharCount = 0;
short removeCharCount = 0; @Builder.Default
@Builder.Default Type type = Type.Normal;
Type type = Type.Normal;
public enum Type {
public enum Type { Normal,
Normal, /**
/** * Matches a start and an end section which gets converted to one section (for example see italics)
* Matches a start and an end section which gets converted to one section (for example see italics) */
*/ Range,
Range, /**
/** * Exclude matching area from further processing (besides this formatter)
* Exclude matching area from further processing (besides this formatter) */
*/ Excluder
Excluder }
}
@FunctionalInterface
public static void Combine(List<ChatFormatter> formatters, String str, TellrawPart tp) { public interface TriFunc<T1, T2, T3, R> {
/* R apply(T1 x1, T2 x2, T3 x3);
* This method assumes that there is always a global formatter }
*/
header("ChatFormatter.Combine begin"); public static void Combine(List<ChatFormatter> formatters, String str, TellrawPart tp) {
ArrayList<FormattedSection> sections = new ArrayList<FormattedSection>(); /*
* This method assumes that there is always a global formatter
for (ChatFormatter formatter : formatters) { */
if (formatter.type != Type.Excluder) header("ChatFormatter.Combine begin");
continue; ArrayList<FormattedSection> sections = new ArrayList<FormattedSection>();
Matcher matcher = formatter.regex.matcher(str);
while (matcher.find()) { for (ChatFormatter formatter : formatters) {
DebugCommand.SendDebugMessage("Found match from " + matcher.start() + " to " + (matcher.end() - 1)); if (formatter.type != Type.Excluder)
DebugCommand.SendDebugMessage("With excluder formatter:" + formatter); continue;
sendMessageWithPointer(str, matcher.start(), matcher.end() - 1); Matcher matcher = formatter.regex.matcher(str);
if (formatter.regex != ChatProcessing.ENTIRE_MESSAGE_PATTERN && sections.stream().anyMatch(fs -> fs.type == Type.Excluder && (fs.End >= matcher.start() && fs.Start <= matcher.end() - 1))) { while (matcher.find()) {
DebugCommand.SendDebugMessage("Ignoring formatter because of an excluder"); DebugCommand.SendDebugMessage("Found match from " + matcher.start() + " to " + (matcher.end() - 1));
continue; //Exclude areas matched by excluders - Range sections are correctly handled afterwards DebugCommand.SendDebugMessage("With excluder formatter:" + formatter);
} sendMessageWithPointer(str, matcher.start(), matcher.end() - 1);
ArrayList<String> groups = new ArrayList<String>(); if (formatter.regex != ChatProcessing.ENTIRE_MESSAGE_PATTERN && sections.stream().anyMatch(fs -> fs.type == Type.Excluder && (fs.End >= matcher.start() && fs.Start <= matcher.end() - 1))) {
for (int i = 0; i < matcher.groupCount(); i++) DebugCommand.SendDebugMessage("Ignoring formatter because of an excluder");
groups.add(matcher.group(i + 1)); continue; //Exclude areas matched by excluders - Range sections are correctly handled afterwards
if (groups.size() > 0) }
DebugCommand.SendDebugMessage("First group: " + groups.get(0)); ArrayList<String> groups = new ArrayList<String>();
FormattedSection section = new FormattedSection(formatter, matcher.start(), matcher.end() - 1, groups, for (int i = 0; i < matcher.groupCount(); i++)
formatter.type); groups.add(matcher.group(i + 1));
sections.add(section); if (groups.size() > 0)
} DebugCommand.SendDebugMessage("First group: " + groups.get(0));
} FormattedSection section = new FormattedSection(formatter, matcher.start(), matcher.end() - 1, groups,
formatter.type);
header("Section creation (excluders done)"); sections.add(section);
for (ChatFormatter formatter : formatters) { }
if (formatter.type == Type.Excluder) }
continue;
Matcher matcher = formatter.regex.matcher(str); header("Section creation (excluders done)");
while (matcher.find()) { for (ChatFormatter formatter : formatters) {
DebugCommand.SendDebugMessage("Found match from " + matcher.start() + " to " + (matcher.end() - 1)); if (formatter.type == Type.Excluder)
DebugCommand.SendDebugMessage("With formatter:" + formatter); continue;
sendMessageWithPointer(str, matcher.start(), matcher.end() - 1); Matcher matcher = formatter.regex.matcher(str);
if (formatter.regex != ChatProcessing.ENTIRE_MESSAGE_PATTERN && sections.stream().anyMatch(fs -> fs.type == Type.Excluder && (fs.End >= matcher.start() && fs.Start <= matcher.end() - 1))) { while (matcher.find()) {
DebugCommand.SendDebugMessage("Ignoring formatter because of an excluder"); DebugCommand.SendDebugMessage("Found match from " + matcher.start() + " to " + (matcher.end() - 1));
continue; //Exclude areas matched by excluders - Range sections are correctly handled afterwards DebugCommand.SendDebugMessage("With formatter:" + formatter);
} sendMessageWithPointer(str, matcher.start(), matcher.end() - 1);
ArrayList<String> groups = new ArrayList<String>(); if (formatter.regex != ChatProcessing.ENTIRE_MESSAGE_PATTERN && sections.stream().anyMatch(fs -> fs.type == Type.Excluder && (fs.End >= matcher.start() && fs.Start <= matcher.end() - 1))) {
for (int i = 0; i < matcher.groupCount(); i++) DebugCommand.SendDebugMessage("Ignoring formatter because of an excluder");
groups.add(matcher.group(i + 1)); continue; //Exclude areas matched by excluders - Range sections are correctly handled afterwards
if (groups.size() > 0) }
DebugCommand.SendDebugMessage("First group: " + groups.get(0)); ArrayList<String> groups = new ArrayList<String>();
FormattedSection section = new FormattedSection(formatter, matcher.start(), matcher.end() - 1, groups, for (int i = 0; i < matcher.groupCount(); i++)
formatter.type); groups.add(matcher.group(i + 1));
sections.add(section); if (groups.size() > 0)
} DebugCommand.SendDebugMessage("First group: " + groups.get(0));
} FormattedSection section = new FormattedSection(formatter, matcher.start(), matcher.end() - 1, groups,
sections.sort( formatter.type);
(s1, s2) -> s1.Start == s2.Start sections.add(section);
? s1.End == s2.End ? Integer.compare(s2.Formatters.get(0).priority.GetValue(), }
s1.Formatters.get(0).priority.GetValue()) : Integer.compare(s2.End, s1.End) }
: Integer.compare(s1.Start, s2.Start)); sections.sort(
(s1, s2) -> s1.Start == s2.Start
/** ? s1.End == s2.End ? Integer.compare(s2.Formatters.get(0).priority.GetValue(),
* 0: Start - 1: End index s1.Formatters.get(0).priority.GetValue()) : Integer.compare(s2.End, s1.End)
*/ : Integer.compare(s1.Start, s2.Start));
val remchars = new ArrayList<int[]>();
/**
header("Range section conversion"); * 0: Start - 1: End index
ArrayList<FormattedSection> combined = new ArrayList<>(); */
Map<ChatFormatter, FormattedSection> nextSection = new HashMap<>(); val remchars = new ArrayList<int[]>();
boolean escaped = false;
int takenStart = -1, takenEnd = -1; header("Range section conversion");
ChatFormatter takenFormatter = null; ArrayList<FormattedSection> combined = new ArrayList<>();
for (int i = 0; i < sections.size(); i++) { Map<ChatFormatter, FormattedSection> nextSection = new HashMap<>();
// Set ending to -1 until closed with another 1 long "section" - only do this if IsRange is true boolean escaped = false;
final FormattedSection section = sections.get(i); int takenStart = -1, takenEnd = -1;
if (section.type!=Type.Range) { ChatFormatter takenFormatter = null;
escaped = section.Formatters.contains(ChatProcessing.ESCAPE_FORMATTER) && !escaped; // Enable escaping on first \, disable on second for (int i = 0; i < sections.size(); i++) {
if (escaped) {// Don't add the escape character // Set ending to -1 until closed with another 1 long "section" - only do this if IsRange is true
remchars.add(new int[]{section.Start, section.Start}); final FormattedSection section = sections.get(i);
DebugCommand.SendDebugMessage("Found escaper section: " + section); if (section.type!=Type.Range) {
} else { escaped = section.Formatters.contains(ChatProcessing.ESCAPE_FORMATTER) && !escaped; // Enable escaping on first \, disable on second
combined.add(section); // The above will delete the \ if (escaped) {// Don't add the escape character
DebugCommand.SendDebugMessage("Added section: " + section); remchars.add(new int[]{section.Start, section.Start});
} DebugCommand.SendDebugMessage("Found escaper section: " + section);
sendMessageWithPointer(str, section.Start, section.End); } else {
continue; combined.add(section); // The above will delete the \
} DebugCommand.SendDebugMessage("Added section: " + section);
if (!escaped) { }
if (combined.stream().anyMatch(s -> section.type != Type.Range && (s.Start == section.Start sendMessageWithPointer(str, section.Start, section.End);
|| (s.Start < section.Start ? s.End >= section.Start : s.Start <= section.End)))) { continue;
DebugCommand.SendDebugMessage("Range " + section + " overlaps with a combined section, ignoring."); }
sendMessageWithPointer(str, section.Start, section.End); if (!escaped) {
continue; if (combined.stream().anyMatch(s -> section.type != Type.Range && (s.Start == section.Start
} || (s.Start < section.Start ? s.End >= section.Start : s.Start <= section.End)))) {
if (section.Start == takenStart || (section.Start > takenStart && section.Start < takenEnd)) { DebugCommand.SendDebugMessage("Range " + section + " overlaps with a combined section, ignoring.");
/* sendMessageWithPointer(str, section.Start, section.End);
* if (nextSection.containsKey(section.Formatters.get(0)) ? section.RemCharFromStart <= takenEnd - takenStart : section.RemCharFromStart > takenEnd - takenStart) { continue;
*/ }
if (section.Formatters.get(0).removeCharCount < takenEnd - takenStart) { if (section.Start == takenStart || (section.Start > takenStart && section.Start < takenEnd)) {
DebugCommand.SendDebugMessage("Lose: " + section); /*
sendMessageWithPointer(str, section.Start, section.End); * if (nextSection.containsKey(section.Formatters.get(0)) ? section.RemCharFromStart <= takenEnd - takenStart : section.RemCharFromStart > takenEnd - takenStart) {
DebugCommand.SendDebugMessage("And win: " + takenFormatter); */
continue; // The current section loses if (section.Formatters.get(0).removeCharCount < takenEnd - takenStart) {
} DebugCommand.SendDebugMessage("Lose: " + section);
nextSection.remove(takenFormatter); // The current section wins sendMessageWithPointer(str, section.Start, section.End);
DebugCommand.SendDebugMessage("Win: " + section); DebugCommand.SendDebugMessage("And win: " + takenFormatter);
sendMessageWithPointer(str, section.Start, section.End); continue; // The current section loses
DebugCommand.SendDebugMessage("And lose: " + takenFormatter); }
} nextSection.remove(takenFormatter); // The current section wins
takenStart = section.Start; DebugCommand.SendDebugMessage("Win: " + section);
takenEnd = section.Start + section.Formatters.get(0).removeCharCount; sendMessageWithPointer(str, section.Start, section.End);
takenFormatter = section.Formatters.get(0); DebugCommand.SendDebugMessage("And lose: " + takenFormatter);
if (nextSection.containsKey(section.Formatters.get(0))) { }
FormattedSection s = nextSection.remove(section.Formatters.get(0)); takenStart = section.Start;
// section: the ending marker section - s: the to-be full section takenEnd = section.Start + section.Formatters.get(0).removeCharCount;
s.End = takenEnd - 1; //Take the remCharCount into account as well takenFormatter = section.Formatters.get(0);
// s.IsRange = false; // IsRange means it's a 1 long section indicating a start or an end if (nextSection.containsKey(section.Formatters.get(0))) {
combined.add(s); FormattedSection s = nextSection.remove(section.Formatters.get(0));
DebugCommand.SendDebugMessage("Finished section: " + s); // section: the ending marker section - s: the to-be full section
sendMessageWithPointer(str, s.Start, s.End); s.End = takenEnd - 1; //Take the remCharCount into account as well
} else { // s.IsRange = false; // IsRange means it's a 1 long section indicating a start or an end
DebugCommand.SendDebugMessage("Adding next section: " + section); combined.add(s);
sendMessageWithPointer(str, section.Start, section.End); DebugCommand.SendDebugMessage("Finished section: " + s);
nextSection.put(section.Formatters.get(0), section); sendMessageWithPointer(str, s.Start, s.End);
} } else {
DebugCommand DebugCommand.SendDebugMessage("Adding next section: " + section);
.SendDebugMessage("New area taken: (" + takenStart + "-" + takenEnd + ") " + takenFormatter); sendMessageWithPointer(str, section.Start, section.End);
sendMessageWithPointer(str, takenStart, takenEnd); nextSection.put(section.Formatters.get(0), section);
} else { }
DebugCommand.SendDebugMessage("Skipping section: " + section); // This will keep the text (character) DebugCommand
sendMessageWithPointer(str, section.Start, section.End); .SendDebugMessage("New area taken: (" + takenStart + "-" + takenEnd + ") " + takenFormatter);
escaped = false; // Reset escaping if applied, like if we're at the '*' in '\*' sendMessageWithPointer(str, takenStart, takenEnd);
} } else {
} DebugCommand.SendDebugMessage("Skipping section: " + section); // This will keep the text (character)
//Do not finish unfinished sections, ignore them sendMessageWithPointer(str, section.Start, section.End);
sections = combined; escaped = false; // Reset escaping if applied, like if we're at the '*' in '\*'
}
header("Adding remove chars (RC)"); // Important to add after the range section conversion }
sections.stream() //Do not finish unfinished sections, ignore them
.flatMap(fs -> fs.Formatters.stream().filter(cf -> cf.removeCharCount > 0) sections = combined;
.mapToInt(cf -> cf.removeCharCount).mapToObj(rcc -> new int[]{fs.Start, fs.Start + rcc - 1}))
.forEach(rc -> remchars.add(rc)); header("Adding remove chars (RC)"); // Important to add after the range section conversion
sections.stream() sections.stream()
.flatMap(fs -> fs.Formatters.stream().filter(cf -> cf.removeCharCount > 0) .flatMap(fs -> fs.Formatters.stream().filter(cf -> cf.removeCharCount > 0)
.mapToInt(cf -> cf.removeCharCount).mapToObj(rcc -> new int[]{fs.End - rcc + 1, fs.End})) .mapToInt(cf -> cf.removeCharCount).mapToObj(rcc -> new int[]{fs.Start, fs.Start + rcc - 1}))
.forEach(rc -> remchars.add(rc)); .forEach(rc -> remchars.add(rc));
DebugCommand.SendDebugMessage("Added remchars:"); sections.stream()
DebugCommand .flatMap(fs -> fs.Formatters.stream().filter(cf -> cf.removeCharCount > 0)
.SendDebugMessage(remchars.stream().map(rc -> Arrays.toString(rc)).collect(Collectors.joining("; "))); .mapToInt(cf -> cf.removeCharCount).mapToObj(rcc -> new int[]{fs.End - rcc + 1, fs.End}))
.forEach(rc -> remchars.add(rc));
header("Section combining"); DebugCommand.SendDebugMessage("Added remchars:");
boolean cont = true; DebugCommand
boolean found = false; .SendDebugMessage(remchars.stream().map(rc -> Arrays.toString(rc)).collect(Collectors.joining("; ")));
for (int i = 1; cont;) {
int nextindex = i + 1; header("Section combining");
if (sections.size() < 2) boolean cont = true;
break; boolean found = false;
DebugCommand.SendDebugMessage("i: " + i); for (int i = 1; cont;) {
FormattedSection firstSection = sections.get(i - 1); int nextindex = i + 1;
DebugCommand.SendDebugMessage("Combining sections " + firstSection); if (sections.size() < 2)
sendMessageWithPointer(str, firstSection.Start, firstSection.End); break;
DebugCommand.SendDebugMessage(" and " + sections.get(i)); DebugCommand.SendDebugMessage("i: " + i);
sendMessageWithPointer(str, sections.get(i).Start, sections.get(i).End); FormattedSection firstSection = sections.get(i - 1);
if (firstSection.Start == sections.get(i).Start && firstSection.End == sections.get(i).End) { DebugCommand.SendDebugMessage("Combining sections " + firstSection);
firstSection.Formatters.addAll(sections.get(i).Formatters); sendMessageWithPointer(str, firstSection.Start, firstSection.End);
firstSection.Matches.addAll(sections.get(i).Matches); DebugCommand.SendDebugMessage(" and " + sections.get(i));
DebugCommand.SendDebugMessage("To section " + firstSection); sendMessageWithPointer(str, sections.get(i).Start, sections.get(i).End);
sendMessageWithPointer(str, firstSection.Start, firstSection.End); if (firstSection.Start == sections.get(i).Start && firstSection.End == sections.get(i).End) {
sections.remove(i); firstSection.Formatters.addAll(sections.get(i).Formatters);
found = true; firstSection.Matches.addAll(sections.get(i).Matches);
} else if (firstSection.End > sections.get(i).Start && firstSection.Start < sections.get(i).End) { DebugCommand.SendDebugMessage("To section " + firstSection);
int origend = firstSection.End; sendMessageWithPointer(str, firstSection.Start, firstSection.End);
firstSection.End = sections.get(i).Start - 1; sections.remove(i);
int origend2 = sections.get(i).End; found = true;
boolean switchends; } else if (firstSection.End > sections.get(i).Start && firstSection.Start < sections.get(i).End) {
if (switchends = origend2 < origend) { int origend = firstSection.End;
int tmp = origend; firstSection.End = sections.get(i).Start - 1;
origend = origend2; int origend2 = sections.get(i).End;
origend2 = tmp; boolean switchends;
} if (switchends = origend2 < origend) {
FormattedSection section = new FormattedSection(firstSection.Formatters, sections.get(i).Start, origend, int tmp = origend;
firstSection.Matches, Type.Normal); origend = origend2;
section.Formatters.addAll(sections.get(i).Formatters); origend2 = tmp;
section.Matches.addAll(sections.get(i).Matches); // TODO: Clean }
sections.add(i, section); FormattedSection section = new FormattedSection(firstSection.Formatters, sections.get(i).Start, origend,
nextindex++; firstSection.Matches, Type.Normal);
FormattedSection thirdFormattedSection = sections.get(i + 1); section.Formatters.addAll(sections.get(i).Formatters);
if (switchends) { // Use the properties of the first section not the second one section.Matches.addAll(sections.get(i).Matches); // TODO: Clean
thirdFormattedSection.Formatters.clear(); sections.add(i, section);
thirdFormattedSection.Formatters.addAll(firstSection.Formatters); nextindex++;
thirdFormattedSection.Matches.clear(); FormattedSection thirdFormattedSection = sections.get(i + 1);
thirdFormattedSection.Matches.addAll(firstSection.Matches); if (switchends) { // Use the properties of the first section not the second one
} thirdFormattedSection.Formatters.clear();
thirdFormattedSection.Start = origend + 1; thirdFormattedSection.Formatters.addAll(firstSection.Formatters);
thirdFormattedSection.End = origend2; thirdFormattedSection.Matches.clear();
thirdFormattedSection.Matches.addAll(firstSection.Matches);
ArrayList<FormattedSection> sts = sections; }
Predicate<FormattedSection> removeIfNeeded = s -> { thirdFormattedSection.Start = origend + 1;
if (s.Start < 0 || s.End < 0 || s.Start > s.End) { thirdFormattedSection.End = origend2;
DebugCommand.SendDebugMessage("Removing section: " + s);
sendMessageWithPointer(str, s.Start, s.End); ArrayList<FormattedSection> sts = sections;
sts.remove(s); Predicate<FormattedSection> removeIfNeeded = s -> {
return true; if (s.Start < 0 || s.End < 0 || s.Start > s.End) {
} DebugCommand.SendDebugMessage("Removing section: " + s);
return false; sendMessageWithPointer(str, s.Start, s.End);
}; sts.remove(s);
return true;
DebugCommand.SendDebugMessage("To sections"); }
if (!removeIfNeeded.test(firstSection)) { return false;
DebugCommand.SendDebugMessage(" 1:" + firstSection + ""); };
sendMessageWithPointer(str, firstSection.Start, firstSection.End);
} DebugCommand.SendDebugMessage("To sections");
if (!removeIfNeeded.test(section)) { if (!removeIfNeeded.test(firstSection)) {
DebugCommand.SendDebugMessage(" 2:" + section + ""); DebugCommand.SendDebugMessage(" 1:" + firstSection + "");
sendMessageWithPointer(str, section.Start, section.End); sendMessageWithPointer(str, firstSection.Start, firstSection.End);
} }
if (!removeIfNeeded.test(thirdFormattedSection)) { if (!removeIfNeeded.test(section)) {
DebugCommand.SendDebugMessage(" 3:" + thirdFormattedSection); DebugCommand.SendDebugMessage(" 2:" + section + "");
sendMessageWithPointer(str, thirdFormattedSection.Start, thirdFormattedSection.End); sendMessageWithPointer(str, section.Start, section.End);
} }
found = true; if (!removeIfNeeded.test(thirdFormattedSection)) {
} DebugCommand.SendDebugMessage(" 3:" + thirdFormattedSection);
for (int j = i - 1; j <= i + 1; j++) { sendMessageWithPointer(str, thirdFormattedSection.Start, thirdFormattedSection.End);
if (j < sections.size() && sections.get(j).End < sections.get(j).Start) { }
DebugCommand.SendDebugMessage("Removing section: " + sections.get(j)); found = true;
sendMessageWithPointer(str, sections.get(j).Start, sections.get(j).End); }
sections.remove(j); for (int j = i - 1; j <= i + 1; j++) {
j--; if (j < sections.size() && sections.get(j).End < sections.get(j).Start) {
found = true; DebugCommand.SendDebugMessage("Removing section: " + sections.get(j));
} sendMessageWithPointer(str, sections.get(j).Start, sections.get(j).End);
} sections.remove(j);
i = nextindex - 1; j--;
i++; found = true;
if (i >= sections.size()) { }
if (found) { }
i = 1; i = nextindex - 1;
found = false; i++;
sections.sort( if (i >= sections.size()) {
(s1, s2) -> s1.Start == s2.Start if (found) {
? s1.End == s2.End i = 1;
? Integer.compare(s2.Formatters.get(0).priority.GetValue(), found = false;
s1.Formatters.get(0).priority.GetValue()) sections.sort(
: Integer.compare(s2.End, s1.End) (s1, s2) -> s1.Start == s2.Start
: Integer.compare(s1.Start, s2.Start)); ? s1.End == s2.End
} else ? Integer.compare(s2.Formatters.get(0).priority.GetValue(),
cont = false; s1.Formatters.get(0).priority.GetValue())
} : Integer.compare(s2.End, s1.End)
} : Integer.compare(s1.Start, s2.Start));
} else
header("Section applying"); cont = false;
TellrawPart lasttp = null; String lastlink = null; }
for (FormattedSection section : sections) { }
DebugCommand.SendDebugMessage("Applying section: " + section);
String originaltext; header("Section applying");
int start = section.Start, end = section.End; TellrawPart lasttp = null; String lastlink = null;
DebugCommand.SendDebugMessage("Start: " + start + " - End: " + end); for (FormattedSection section : sections) {
sendMessageWithPointer(str, start, end); DebugCommand.SendDebugMessage("Applying section: " + section);
val rcs = remchars.stream().filter(rc -> rc[0] <= start && start <= rc[1]).findAny(); String originaltext;
val rce = remchars.stream().filter(rc -> rc[0] <= end && end <= rc[1]).findAny(); int start = section.Start, end = section.End;
val rci = remchars.stream().filter(rc -> start < rc[0] && rc[1] < end).toArray(int[][]::new); DebugCommand.SendDebugMessage("Start: " + start + " - End: " + end);
int s = start, e = end; sendMessageWithPointer(str, start, end);
if (rcs.isPresent()) val rcs = remchars.stream().filter(rc -> rc[0] <= start && start <= rc[1]).findAny();
s = rcs.get()[1] + 1; val rce = remchars.stream().filter(rc -> rc[0] <= end && end <= rc[1]).findAny();
if (rce.isPresent()) val rci = remchars.stream().filter(rc -> start < rc[0] && rc[1] < end).toArray(int[][]::new);
e = rce.get()[0] - 1; int s = start, e = end;
DebugCommand.SendDebugMessage("After RC - Start: " + s + " - End: " + e); if (rcs.isPresent())
if (e - s < 0) { //e-s==0 means the end char is the same as start char, so one char message s = rcs.get()[1] + 1;
DebugCommand.SendDebugMessage("Skipping section because of remchars (length would be " + (e - s + 1) + ")"); if (rce.isPresent())
continue; e = rce.get()[0] - 1;
} DebugCommand.SendDebugMessage("After RC - Start: " + s + " - End: " + e);
originaltext = str.substring(s, e + 1); if (e - s < 0) { //e-s==0 means the end char is the same as start char, so one char message
val sb = new StringBuilder(originaltext); DebugCommand.SendDebugMessage("Skipping section because of remchars (length would be " + (e - s + 1) + ")");
for (int x = rci.length - 1; x >= 0; x--) continue;
sb.delete(rci[x][0] - start - 1, rci[x][1] - start); //Delete going backwards }
originaltext = sb.toString(); originaltext = str.substring(s, e + 1);
DebugCommand.SendDebugMessage("Section text: " + originaltext); val sb = new StringBuilder(originaltext);
String openlink = null; for (int x = rci.length - 1; x >= 0; x--)
section.Formatters.sort(Comparator.comparing(cf2 -> cf2.priority.GetValue())); //Apply the highest last, to overwrite previous ones sb.delete(rci[x][0] - start - 1, rci[x][1] - start); //Delete going backwards
TellrawPart newtp = new TellrawPart(""); originaltext = sb.toString();
for (ChatFormatter formatter : section.Formatters) { DebugCommand.SendDebugMessage("Section text: " + originaltext);
DebugCommand.SendDebugMessage("Applying formatter: " + formatter); String openlink = null;
if (formatter.onmatch != null) section.Formatters.sort(Comparator.comparing(cf2 -> cf2.priority.GetValue())); //Apply the highest last, to overwrite previous ones
originaltext = formatter.onmatch.apply(originaltext, formatter); TellrawPart newtp = new TellrawPart("");
if (formatter.color != null) for (ChatFormatter formatter : section.Formatters) {
newtp.setColor(formatter.color); DebugCommand.SendDebugMessage("Applying formatter: " + formatter);
if (formatter.bold) if (formatter.onmatch != null)
newtp.setBold(formatter.bold); originaltext = formatter.onmatch.apply(originaltext, formatter, section);
if (formatter.italic) if (formatter.color != null)
newtp.setItalic(formatter.italic); newtp.setColor(formatter.color);
if (formatter.underlined) if (formatter.bold)
newtp.setUnderlined(formatter.underlined); newtp.setBold(formatter.bold);
if (formatter.strikethrough) if (formatter.italic)
newtp.setStrikethrough(formatter.strikethrough); newtp.setItalic(formatter.italic);
if (formatter.obfuscated) if (formatter.underlined)
newtp.setObfuscated(formatter.obfuscated); newtp.setUnderlined(formatter.underlined);
if (formatter.openlink != null) if (formatter.strikethrough)
openlink = formatter.openlink; newtp.setStrikethrough(formatter.strikethrough);
} if (formatter.obfuscated)
if (lasttp != null && newtp.getColor() == lasttp.getColor() newtp.setObfuscated(formatter.obfuscated);
&& newtp.isBold() == lasttp.isBold() if (formatter.openlink != null)
&& newtp.isItalic() == lasttp.isItalic() openlink = formatter.openlink;
&& newtp.isUnderlined() == lasttp.isUnderlined() }
&& newtp.isStrikethrough() == lasttp.isStrikethrough() if (lasttp != null && newtp.getColor() == lasttp.getColor()
&& newtp.isObfuscated() == lasttp.isObfuscated() && newtp.isBold() == lasttp.isBold()
&& (openlink == null ? lastlink == null : openlink.equals(lastlink))) { && newtp.isItalic() == lasttp.isItalic()
DebugCommand.SendDebugMessage("This part has the same properties as the previous one, combining."); && newtp.isUnderlined() == lasttp.isUnderlined()
lasttp.setText(lasttp.getText() + originaltext); && newtp.isStrikethrough() == lasttp.isStrikethrough()
continue; //Combine parts with the same properties && newtp.isObfuscated() == lasttp.isObfuscated()
} && Objects.equals(openlink, lastlink)) {
newtp.setText(originaltext); DebugCommand.SendDebugMessage("This part has the same properties as the previous one, combining.");
if (openlink != null && openlink.length() > 0) { lasttp.setText(lasttp.getText() + originaltext);
newtp.setClickEvent(TellrawEvent.create(TellrawEvent.ClickAction.OPEN_URL, continue; //Combine parts with the same properties
(section.Matches.size() > 0 ? openlink.replace("$1", section.Matches.get(0)) : openlink))) }
.setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, newtp.setText(originaltext);
new TellrawPart("Click to open").setColor(Color.Blue))); if (openlink != null && openlink.length() > 0) {
} newtp.setClickEvent(TellrawEvent.create(TellrawEvent.ClickAction.OPEN_URL,
tp.addExtra(newtp); (section.Matches.size() > 0 ? openlink.replace("$1", section.Matches.get(0)) : openlink)))
lasttp = newtp; .setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT,
} new TellrawPart("Click to open").setColor(Color.Blue)));
header("ChatFormatter.Combine done"); }
} tp.addExtra(newtp);
lasttp = newtp;
private static void sendMessageWithPointer(String str, int... pointer) { }
DebugCommand.SendDebugMessage(str); header("ChatFormatter.Combine done");
StringBuilder sb = new StringBuilder(str.length()); }
Arrays.sort(pointer);
for (int i = 0; i < pointer.length; i++) { private static void sendMessageWithPointer(String str, int... pointer) {
for (int j = 0; j < pointer[i] - (i > 0 ? pointer[i - 1] + 1 : 0); j++) DebugCommand.SendDebugMessage(str);
sb.append(' '); StringBuilder sb = new StringBuilder(str.length());
if (pointer[i] == (i > 0 ? pointer[i - 1] : -1)) Arrays.sort(pointer);
continue; for (int i = 0; i < pointer.length; i++) {
sb.append('^'); for (int j = 0; j < pointer[i] - (i > 0 ? pointer[i - 1] + 1 : 0); j++)
} sb.append(' ');
DebugCommand.SendDebugMessage(sb.toString()); if (pointer[i] == (i > 0 ? pointer[i - 1] : -1))
} continue;
sb.append('^');
private static void header(String message) { }
DebugCommand.SendDebugMessage("\n--------\n" + message + "\n--------\n"); DebugCommand.SendDebugMessage(sb.toString());
} }
}
private static void header(String message) {
DebugCommand.SendDebugMessage("\n--------\n" + message + "\n--------\n");
}
}

View file

@ -1,36 +1,36 @@
package buttondevteam.chat.formatting; package buttondevteam.chat.formatting;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
class FormattedSection { public class FormattedSection {
int Start; public int Start;
int End; public int End;
ArrayList<ChatFormatter> Formatters = new ArrayList<ChatFormatter>(); public ArrayList<ChatFormatter> Formatters = new ArrayList<ChatFormatter>();
ArrayList<String> Matches = new ArrayList<String>(); public ArrayList<String> Matches = new ArrayList<String>();
ChatFormatter.Type type; public ChatFormatter.Type type;
FormattedSection(ChatFormatter formatter, int start, int end, ArrayList<String> matches, ChatFormatter.Type type) { FormattedSection(ChatFormatter formatter, int start, int end, ArrayList<String> matches, ChatFormatter.Type type) {
Start = start; Start = start;
End = end; End = end;
Formatters.add(formatter); Formatters.add(formatter);
Matches.addAll(matches); Matches.addAll(matches);
this.type = type; this.type = type;
} }
FormattedSection(Collection<ChatFormatter> formatters, int start, int end, ArrayList<String> matches, FormattedSection(Collection<ChatFormatter> formatters, int start, int end, ArrayList<String> matches,
ChatFormatter.Type type) { ChatFormatter.Type type) {
Start = start; Start = start;
End = end; End = end;
Formatters.addAll(formatters); Formatters.addAll(formatters);
Matches.addAll(matches); Matches.addAll(matches);
this.type = type; this.type = type;
} }
@Override @Override
public String toString() { public String toString() {
return "Section(" + Start + ", " + End + ", formatters: " + return "Section(" + Start + ", " + End + ", formatters: " +
Formatters.toString() + ", matches: " + Matches.toString() + ", " + Formatters.toString() + ", matches: " + Matches.toString() + ", " +
type + ")"; type + ")";
} }
} }

View file

@ -1,144 +1,83 @@
package buttondevteam.chat.listener; package buttondevteam.chat.listener;
import buttondevteam.chat.ChatPlayer; import buttondevteam.chat.ChatPlayer;
import buttondevteam.chat.FlairStates; import buttondevteam.chat.PlayerJoinTimerTask;
import buttondevteam.chat.PlayerJoinTimerTask; import buttondevteam.chat.PluginMain;
import buttondevteam.chat.PluginMain; import buttondevteam.chat.commands.UnlolCommand;
import buttondevteam.chat.commands.UnlolCommand; import buttondevteam.chat.commands.ucmds.HistoryCommand;
import buttondevteam.chat.commands.ucmds.HistoryCommand; import buttondevteam.chat.components.flair.FlairComponent;
import buttondevteam.lib.chat.Color; import buttondevteam.chat.components.flair.FlairStates;
import buttondevteam.lib.player.TBMCPlayerJoinEvent; import buttondevteam.chat.components.towncolors.TownColorComponent;
import buttondevteam.lib.player.TBMCPlayerLoadEvent; import buttondevteam.core.ComponentManager;
import buttondevteam.lib.player.TBMCPlayerSaveEvent; import buttondevteam.lib.player.TBMCPlayerJoinEvent;
import com.earth2me.essentials.User; import buttondevteam.lib.player.TBMCPlayerLoadEvent;
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException; import buttondevteam.lib.player.TBMCPlayerSaveEvent;
import lombok.val; import org.bukkit.GameMode;
import org.bukkit.Bukkit; import org.bukkit.entity.Player;
import org.bukkit.ChatColor; import org.bukkit.event.EventHandler;
import org.bukkit.GameMode; import org.bukkit.event.Listener;
import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import java.util.Timer;
import org.bukkit.event.player.PlayerQuitEvent;
public class PlayerJoinLeaveListener implements Listener {
import java.util.Arrays;
import java.util.Optional; @EventHandler
import java.util.Timer; public void onPlayerLoad(TBMCPlayerLoadEvent e) {
import java.util.concurrent.atomic.AtomicInteger; ChatPlayer cp = e.GetPlayer().asPluginPlayer(ChatPlayer.class);
import java.util.function.BiFunction; cp.FlairUpdate();
}
public class PlayerJoinLeaveListener implements Listener {
@EventHandler
@EventHandler public void onPlayerTBMCJoin(TBMCPlayerJoinEvent e) {
public void onPlayerLoad(TBMCPlayerLoadEvent e) { ChatPlayer cp = e.GetPlayer().asPluginPlayer(ChatPlayer.class);
ChatPlayer cp = e.GetPlayer().asPluginPlayer(ChatPlayer.class); Player p = e.getPlayer();
cp.FlairUpdate();
} if (ComponentManager.isEnabled(FlairComponent.class)) {
if (!cp.FlairState().get().equals(FlairStates.NoComment)) {
@EventHandler FlairComponent.ConfirmUserMessage(cp);
public void onPlayerTBMCJoin(TBMCPlayerJoinEvent e) { Timer timer = new Timer();
ChatPlayer cp = e.GetPlayer().asPluginPlayer(ChatPlayer.class); PlayerJoinTimerTask tt = new PlayerJoinTimerTask() {
Player p = Bukkit.getPlayer(cp.getUUID()); @Override
public void run() {
if (!cp.FlairState().get().equals(FlairStates.NoComment)) { mp.FlairUpdate();
PluginMain.ConfirmUserMessage(cp); }
Timer timer = new Timer(); };
PlayerJoinTimerTask tt = new PlayerJoinTimerTask() { tt.mp = cp;
@Override timer.schedule(tt, 1000);
public void run() { } //TODO: Better Reddit integration (OAuth)
mp.FlairUpdate(); }
}
}; String nwithoutformatting = PluginMain.essentials.getUser(p).getNickname();
tt.mp = cp;
timer.schedule(tt, 1000); int index;
} //TODO: Better Reddit integration (OAuth) if (nwithoutformatting != null) {
while ((index = nwithoutformatting.indexOf("§k")) != -1)
String nwithoutformatting = PluginMain.essentials.getUser(p).getNickname(); nwithoutformatting = nwithoutformatting.replace("§k" + nwithoutformatting.charAt(index + 2), ""); // Support for one random char
while ((index = nwithoutformatting.indexOf('§')) != -1)
int index; nwithoutformatting = nwithoutformatting.replace("§" + nwithoutformatting.charAt(index + 1), "");
if (nwithoutformatting != null) { } else
while ((index = nwithoutformatting.indexOf("§k")) != -1) nwithoutformatting = p.getName();
nwithoutformatting = nwithoutformatting.replace("§k" + nwithoutformatting.charAt(index + 2), ""); // Support for one random char PlayerListener.nicknames.forcePut(nwithoutformatting.toLowerCase(), p.getUniqueId());
while ((index = nwithoutformatting.indexOf('§')) != -1)
nwithoutformatting = nwithoutformatting.replace("§" + nwithoutformatting.charAt(index + 1), ""); TownColorComponent.updatePlayerColors(p, cp); //TO!DO: Doesn't have effect - It can help to register the listener
} else
nwithoutformatting = p.getName(); if (cp.ChatOnly || p.getGameMode().equals(GameMode.SPECTATOR)) {
PlayerListener.nicknames.forcePut(nwithoutformatting.toLowerCase(), p.getUniqueId()); cp.ChatOnly = false;
p.setGameMode(GameMode.SURVIVAL);
updatePlayerColors(p, cp); //TO!DO: Doesn't have effect - It can help to register the listener }
if (cp.ChatOnly || p.getGameMode().equals(GameMode.SPECTATOR)) { HistoryCommand.showHistory(e.getPlayer(), "u history", new String[0], null);
cp.ChatOnly = false; }
p.setGameMode(GameMode.SURVIVAL);
} @EventHandler
public void onPlayerSave(TBMCPlayerSaveEvent e) {
HistoryCommand.showHistory(e.getPlayer(), "u history", new String[0], null); }
}
@EventHandler
@EventHandler public void onPlayerLeave(PlayerQuitEvent event) {
public void onPlayerSave(TBMCPlayerSaveEvent e) { PlayerListener.nicknames.inverse().remove(event.getPlayer().getUniqueId());
} UnlolCommand.Lastlol.values().removeIf(lld -> lld.getLolowner().equals(event.getPlayer()));
}
@EventHandler
public void onPlayerLeave(PlayerQuitEvent event) { }
PlayerListener.nicknames.inverse().remove(event.getPlayer().getUniqueId());
UnlolCommand.Lastlol.values().removeIf(lld -> lld.getLolowner().equals(event.getPlayer()));
}
private static String getPlayerNickname(Player player, User user, ChatPlayer cp) {
String nickname = user.getNick(true);
if (nickname.contains("~")) //StartsWith doesn't work because of color codes
nickname = nickname.replace("~", ""); //It gets stacked otherwise
String name = ChatColor.stripColor(nickname); //Enforce "town colors" on non-members
val res = PluginMain.TU.getResidentMap().get(player.getName().toLowerCase());
if (res == null || !res.hasTown())
return name;
try {
Color[] clrs = Optional.ofNullable(
PluginMain.TownColors.get(res.getTown().getName().toLowerCase())
).orElse(new Color[]{Color.White}); //Use white as default town color
StringBuilder ret = new StringBuilder();
AtomicInteger prevlen = new AtomicInteger();
BiFunction<Color, Integer, String> anyColoredNamePart = (c, len) -> "§" //Len==0 if last part
+ Integer.toHexString(c.ordinal()) // 'Odds' are the last character is chopped off so we make sure to include all chars at the end
+ (len == 0 ? name.substring(prevlen.get())
: name.substring(prevlen.get(), prevlen.addAndGet(len)));
BiFunction<Integer, Integer, String> coloredNamePart = (len, i)
-> anyColoredNamePart.apply(clrs[i], i + 1 == clrs.length ? 0 : len);
final int len = name.length() / (clrs.length + 1); //The above param is needed because this isn't always passed
Color nc;
/*if(res.getTown().hasNation()
&&(nc=PluginMain.NationColor.get(res.getTown().getNation().getName().toLowerCase()))!=null)
len = name.length() / (clrs.length+1);
else
len = name.length() / clrs.length;*/
val nclar = cp.NameColorLocations().get();
int[] ncl = nclar == null ? null : nclar.stream().mapToInt(Integer::intValue).toArray();
if (ncl != null && (Arrays.stream(ncl).sum() != name.length() || ncl.length != clrs.length + 1)) //+1: Nation color
ncl = null; // Reset if name length changed
//System.out.println("ncl: "+Arrays.toString(ncl)+" - sum: "+Arrays.stream(ncl).sum()+" - name len: "+name.length());
if (!res.getTown().hasNation()
|| (nc = PluginMain.NationColor.get(res.getTown().getNation().getName().toLowerCase())) == null)
nc = Color.White;
ret.append(anyColoredNamePart.apply(nc, ncl == null ? len : ncl[0])); //Make first color the nation color
for (int i = 0; i < clrs.length; i++)
//ret.append(coloredNamePart.apply(ncl == null ? len : (nc==null?ncl[i]:ncl[i+1]), i));
ret.append(coloredNamePart.apply(ncl == null ? len : ncl[i + 1], i));
return ret.toString();
} catch (NotRegisteredException e) {
return nickname;
}
}
public static void updatePlayerColors(Player player) { //Probably while ingame (/u ncolor)
updatePlayerColors(player, ChatPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class));
}
@SuppressWarnings("WeakerAccess")
public static void updatePlayerColors(Player player, ChatPlayer cp) { //Probably at join - nop, nicknames
User user = PluginMain.essentials.getUser(player);
user.setNickname(getPlayerNickname(player, user, cp));
user.setDisplayNick(); //These won't fire the nick change event
cp.FlairUpdate(); //Update in list
}
}

View file

@ -1,293 +1,290 @@
package buttondevteam.chat.listener; package buttondevteam.chat.listener;
import buttondevteam.chat.ChatPlayer; import buttondevteam.chat.ChatPlayer;
import buttondevteam.chat.ChatProcessing; import buttondevteam.chat.ChatProcessing;
import buttondevteam.chat.PluginMain; import buttondevteam.chat.PluginMain;
import buttondevteam.chat.commands.ucmds.HistoryCommand; import buttondevteam.chat.commands.ucmds.HistoryCommand;
import buttondevteam.lib.TBMCChatEvent; import buttondevteam.chat.components.flair.FlairComponent;
import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.chat.components.towncolors.TownColorComponent;
import buttondevteam.lib.chat.*; import buttondevteam.component.channel.Channel;
import buttondevteam.lib.player.ChromaGamerBase; import buttondevteam.component.channel.ChatChannelRegisterEvent;
import buttondevteam.lib.player.ChromaGamerBase.InfoTarget; import buttondevteam.component.channel.ChatRoom;
import buttondevteam.lib.player.TBMCPlayer; import buttondevteam.core.ComponentManager;
import buttondevteam.lib.player.TBMCPlayerGetInfoEvent; import buttondevteam.lib.TBMCChatEvent;
import com.google.common.collect.BiMap; import buttondevteam.lib.TBMCCoreAPI;
import com.google.common.collect.HashBiMap; import buttondevteam.lib.chat.ChatMessage;
import com.vexsoftware.votifier.model.Vote; import buttondevteam.lib.chat.TBMCChatAPI;
import com.vexsoftware.votifier.model.VotifierEvent; import buttondevteam.lib.player.ChromaGamerBase;
import lombok.val; import buttondevteam.lib.player.ChromaGamerBase.InfoTarget;
import net.ess3.api.events.NickChangeEvent; import buttondevteam.lib.player.TBMCPlayer;
import org.bukkit.Bukkit; import buttondevteam.lib.player.TBMCPlayerGetInfoEvent;
import org.bukkit.ChatColor; import com.google.common.collect.BiMap;
import org.bukkit.command.CommandSender; import com.google.common.collect.HashBiMap;
import org.bukkit.command.ConsoleCommandSender; import com.vexsoftware.votifier.model.Vote;
import org.bukkit.entity.Player; import com.vexsoftware.votifier.model.VotifierEvent;
import org.bukkit.event.EventHandler; import lombok.val;
import org.bukkit.event.EventPriority; import net.ess3.api.events.NickChangeEvent;
import org.bukkit.event.Listener; import org.bukkit.Bukkit;
import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.ChatColor;
import org.bukkit.event.player.*; import org.bukkit.command.CommandSender;
import org.bukkit.event.server.ServerCommandEvent; import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.help.HelpTopic; import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect; import org.bukkit.event.EventHandler;
import org.bukkit.potion.PotionEffectType; import org.bukkit.event.EventPriority;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import java.util.ArrayList; import org.bukkit.event.player.*;
import java.util.Arrays; import org.bukkit.event.server.ServerCommandEvent;
import java.util.Map.Entry; import org.bukkit.help.HelpTopic;
import java.util.Random; import org.bukkit.potion.PotionEffect;
import java.util.UUID; import org.bukkit.potion.PotionEffectType;
import java.util.function.BiPredicate; import org.bukkit.scheduler.BukkitTask;
public class PlayerListener implements Listener { import java.util.ArrayList;
/** import java.util.Arrays;
* Does not contain format codes, lowercased import java.util.Map.Entry;
*/ import java.util.Random;
public static BiMap<String, UUID> nicknames = HashBiMap.create(); import java.util.UUID;
import java.util.function.BiPredicate;
public static boolean Enable = false;
public class PlayerListener implements Listener {
public static int LoginWarningCountTotal = 5; /**
* Does not contain format codes, lowercased
public static String NotificationSound; */
public static double NotificationPitch; public static BiMap<String, UUID> nicknames = HashBiMap.create();
public static boolean ShowRPTag = false; public final static String[] LaughStrings = new String[]{"xd", "lel", "lawl", "kek", "lmao", "hue", "hah", "rofl"};
public final static String[] LaughStrings = new String[]{"xd", "lel", "lawl", "kek", "lmao", "hue", "hah", "rofl"}; @EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerChat(AsyncPlayerChatEvent event) {
@EventHandler(priority = EventPriority.HIGHEST) if (event.isCancelled())
public void onPlayerChat(AsyncPlayerChatEvent event) { return;
if (event.isCancelled()) ChatPlayer cp = TBMCPlayer.getPlayer(event.getPlayer().getUniqueId(), ChatPlayer.class);
return; TBMCChatAPI.SendChatMessage(ChatMessage.builder(event.getPlayer(), cp, event.getMessage()).build());
ChatPlayer cp = TBMCPlayer.getPlayer(event.getPlayer().getUniqueId(), ChatPlayer.class); event.setCancelled(true); // The custom event should only be cancelled when muted or similar
TBMCChatAPI.SendChatMessage(ChatMessage.builder(event.getPlayer(), cp, event.getMessage()).build()); }
event.setCancelled(true); // The custom event should only be cancelled when muted or similar
} @EventHandler(priority = EventPriority.HIGHEST)
public void PlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
@EventHandler(priority = EventPriority.HIGHEST) if (!event.isCancelled())
public void PlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { event.setCancelled(onCommandPreprocess(event.getPlayer(), event.getMessage()));
if (!event.isCancelled()) }
event.setCancelled(onCommandPreprocess(event.getPlayer(), event.getMessage()));
} private boolean onCommandPreprocess(CommandSender sender, String message) {
if (message.length() < 2)
private boolean onCommandPreprocess(CommandSender sender, String message) { return false;
if (message.length() < 2) int index = message.indexOf(" ");
return false; val mp = ChromaGamerBase.getFromSender(sender);
int index = message.indexOf(" "); String cmd;
val mp = ChromaGamerBase.getFromSender(sender); final BiPredicate<Channel, String> checkchid = (chan, cmd1) -> cmd1.equalsIgnoreCase(chan.ID) || (Arrays.stream(chan.IDs().get()).anyMatch(cmd1::equalsIgnoreCase));
String cmd; if (index == -1) { // Only the command is run
final BiPredicate<Channel, String> checkchid = (chan, cmd1) -> cmd1.equalsIgnoreCase(chan.ID) || (chan.IDs != null && Arrays.stream(chan.IDs).anyMatch(cmd1::equalsIgnoreCase)); if (!(sender instanceof Player || sender instanceof ConsoleCommandSender))
if (index == -1) { // Only the command is run return false;
if (!(sender instanceof Player || sender instanceof ConsoleCommandSender)) // ^^ We can only store player or console channels - Directly sending to channels would still work if they had an event
return false; cmd = sender instanceof ConsoleCommandSender ? message : message.substring(1);
// ^^ We can only store player or console channels - Directly sending to channels would still work if they had an event for (Channel channel : ((Iterable<Channel>) Channel.getChannels()::iterator)) { //Using Stream.forEach would be too easy
cmd = sender instanceof ConsoleCommandSender ? message : message.substring(1); if (checkchid.test(channel, cmd)) {
for (Channel channel : Channel.getChannels()) { Channel oldch = mp.channel().get();
if (checkchid.test(channel, cmd)) { if (oldch instanceof ChatRoom)
Channel oldch = mp.channel().get(); ((ChatRoom) oldch).leaveRoom(sender);
if (oldch instanceof ChatRoom) if (oldch.equals(channel))
((ChatRoom) oldch).leaveRoom(sender); mp.channel().set(Channel.GlobalChat);
if (oldch.equals(channel)) else {
mp.channel().set(Channel.GlobalChat); mp.channel().set(channel);
else { if (channel instanceof ChatRoom)
mp.channel().set(channel); ((ChatRoom) channel).joinRoom(sender);
if (channel instanceof ChatRoom) }
((ChatRoom) channel).joinRoom(sender); sender.sendMessage("§6You are now talking in: §b" + mp.channel().get().DisplayName().get());
} return true;
sender.sendMessage("§6You are now talking in: §b" + mp.channel().get().DisplayName); }
return true; }
} } else { // We have arguments
} cmd = sender instanceof ConsoleCommandSender ? message.substring(0, index) : message.substring(1, index);
} else { // We have arguments if (cmd.equalsIgnoreCase("tpahere")) {
cmd = sender instanceof ConsoleCommandSender ? message.substring(0, index) : message.substring(1, index); Player player = Bukkit.getPlayer(message.substring(index + 1));
if (cmd.equalsIgnoreCase("tpahere")) { if (player != null && sender instanceof Player)
Player player = Bukkit.getPlayer(message.substring(index + 1)); player.sendMessage("§b" + ((Player) sender).getDisplayName() + " §bis in this world: "
if (player != null && sender instanceof Player) + ((Player) sender).getWorld().getName());
player.sendMessage("§b" + ((Player) sender).getDisplayName() + " §bis in this world: " } else if (cmd.equalsIgnoreCase("minecraft:me")) {
+ ((Player) sender).getWorld().getName()); if (!(sender instanceof Player) || !PluginMain.essentials.getUser((Player) sender).isMuted()) {
} else if (cmd.equalsIgnoreCase("minecraft:me")) { String msg = message.substring(index + 1);
if (!(sender instanceof Player) || !PluginMain.essentials.getUser((Player) sender).isMuted()) { Bukkit.broadcastMessage(String.format("* %s %s", sender instanceof Player ? ((Player) sender).getDisplayName() : sender.getName(), msg));
String msg = message.substring(index + 1); return true;
Bukkit.broadcastMessage(String.format("* %s %s", sender instanceof Player ? ((Player) sender).getDisplayName() : sender.getName(), msg)); } else {
return true; sender.sendMessage("§cCan't use /minecraft:me while muted.");
} else { return true;
sender.sendMessage("§cCan't use /minecraft:me while muted."); }
return true; } else if (cmd.equalsIgnoreCase("me")) { //Take over for Discord broadcast
} if (!(sender instanceof Player) || !PluginMain.essentials.getUser((Player) sender).isMuted()) {
} else if (cmd.equalsIgnoreCase("me")) { //Take over for Discord broadcast String msg = message.substring(index + 1);
if (!(sender instanceof Player) || !PluginMain.essentials.getUser((Player) sender).isMuted()) { Bukkit.broadcastMessage(String.format("§5* %s %s", sender instanceof Player ? ((Player) sender).getDisplayName() : sender.getName(), msg));
String msg = message.substring(index + 1); return true;
Bukkit.broadcastMessage(String.format("§5* %s %s", sender instanceof Player ? ((Player) sender).getDisplayName() : sender.getName(), msg)); } else {
return true; sender.sendMessage("§cCan't use /me while muted.");
} else { return true;
sender.sendMessage("§cCan't use /me while muted."); }
return true; } else
} for (Channel channel : (Iterable<Channel>) Channel.getChannels()::iterator) {
} else if (checkchid.test(channel, cmd)) { //Apparently method references don't require final variables
for (Channel channel : Channel.getChannels()) { TBMCChatAPI.SendChatMessage(ChatMessage.builder(sender, mp, message.substring(index + 1)).build(), channel);
if (checkchid.test(channel, cmd)) { //Apparently method references don't require final variables return true;
TBMCChatAPI.SendChatMessage(ChatMessage.builder(sender, mp, message.substring(index + 1)).build(), channel); }
return true; }
} // TODO: Target selectors
} }
// TODO: Target selectors // We don't care if we have arguments
} if (cmd.toLowerCase().startsWith("un")) {
// We don't care if we have arguments for (HelpTopic ht : PluginMain.Instance.getServer().getHelpMap().getHelpTopics()) {
if (cmd.toLowerCase().startsWith("un")) { if (ht.getName().equalsIgnoreCase("/" + cmd))
for (HelpTopic ht : PluginMain.Instance.getServer().getHelpMap().getHelpTopics()) { return false;
if (ht.getName().equalsIgnoreCase("/" + cmd)) }
return false; if (PluginMain.permission.has(sender, "tbmc.admin")) {
} String s = cmd.substring(2);
if (PluginMain.permission.has(sender, "tbmc.admin")) { Player target = Bukkit.getPlayer(message.substring(index + 1));
String s = cmd.substring(2); if (target == null) {
Player target = Bukkit.getPlayer(message.substring(index + 1)); sender.sendMessage("§cError: Player not found. (/un" + s + " <player>)");
if (target == null) { return true;
sender.sendMessage("§cError: Player not found. (/un" + s + " <player>)"); }
return true; target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 10 * 20, 5, false, false));
} Bukkit.broadcastMessage(
target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 10 * 20, 5, false, false)); (sender instanceof Player ? ((Player) sender).getDisplayName() : sender.getName()) + " un" + s
Bukkit.broadcastMessage( + "'d " + target.getDisplayName());
(sender instanceof Player ? ((Player) sender).getDisplayName() : sender.getName()) + " un" + s return true;
+ "'d " + target.getDisplayName()); }
return true; }
} return false;
} }
return false;
} @EventHandler
public void onTabComplete(PlayerChatTabCompleteEvent e) {
@EventHandler String name = e.getLastToken();
public void onTabComplete(PlayerChatTabCompleteEvent e) { for (Entry<String, UUID> nicknamekv : nicknames.entrySet()) {
String name = e.getLastToken(); if (nicknamekv.getKey().startsWith(name.toLowerCase()))
for (Entry<String, UUID> nicknamekv : nicknames.entrySet()) { e.getTabCompletions().add(PluginMain.essentials.getUser(Bukkit.getPlayer(nicknamekv.getValue())).getNick(true)); //Tabcomplete with the correct case
if (nicknamekv.getKey().startsWith(name.toLowerCase())) }
e.getTabCompletions().add(PluginMain.essentials.getUser(Bukkit.getPlayer(nicknamekv.getValue())).getNick(true)); //Tabcomplete with the correct case }
}
} public static boolean ActiveF = false;
public static ChatPlayer FPlayer = null;
public static boolean ActiveF = false; public static BukkitTask Ftask = null;
public static ChatPlayer FPlayer = null; public static ArrayList<CommandSender> Fs = new ArrayList<>();
public static BukkitTask Ftask = null;
public static int AlphaDeaths; @EventHandler
public static ArrayList<CommandSender> Fs = new ArrayList<>(); public void onPlayerDeath(PlayerDeathEvent e) {
// MinigamePlayer mgp = Minigames.plugin.pdata.getMinigamePlayer(e.getEntity());
@EventHandler if (/* (mgp != null && !mgp.isInMinigame()) && */ new Random().nextBoolean()) { // Don't store Fs for NPCs
public void onPlayerDeath(PlayerDeathEvent e) { Runnable tt = () -> {
if (e.getEntity().getName().equals("Alpha_Bacca44")) if (ActiveF) {
AlphaDeaths++; ActiveF = false;
// MinigamePlayer mgp = Minigames.plugin.pdata.getMinigamePlayer(e.getEntity()); if (FPlayer != null && FPlayer.FCount().get() < Integer.MAX_VALUE - 1)
if (/* (mgp != null && !mgp.isInMinigame()) && */ new Random().nextBoolean()) { // Don't store Fs for NPCs FPlayer.FCount().set(FPlayer.FCount().get() + Fs.size());
Runnable tt = () -> { Bukkit.broadcastMessage("§b" + Fs.size() + " " + (Fs.size() == 1 ? "person" : "people")
if (ActiveF) { + " paid their respects.§r");
ActiveF = false; Fs.clear();
if (FPlayer != null && FPlayer.FCount().get() < Integer.MAX_VALUE - 1) }
FPlayer.FCount().set(FPlayer.FCount().get() + Fs.size()); };
Bukkit.broadcastMessage("§b" + Fs.size() + " " + (Fs.size() == 1 ? "person" : "people") if (Ftask != null) {
+ " paid their respects.§r"); Ftask.cancel();
Fs.clear(); tt.run(); //Finish previous one
} }
}; ActiveF = true;
if (Ftask != null) { Fs.clear();
Ftask.cancel(); FPlayer = TBMCPlayer.getPlayer(e.getEntity().getUniqueId(), ChatPlayer.class);
tt.run(); //Finish previous one FPlayer.FDeaths().set(FPlayer.FDeaths().get() + 1);
} Bukkit.broadcastMessage("§bPress F to pay respects.§r");
ActiveF = true; Bukkit.getScheduler().runTaskLaterAsynchronously(PluginMain.Instance, tt, 15 * 20);
Fs.clear(); }
FPlayer = TBMCPlayer.getPlayer(e.getEntity().getUniqueId(), ChatPlayer.class); }
FPlayer.FDeaths().set(FPlayer.FDeaths().get() + 1);
Bukkit.broadcastMessage("§bPress F to pay respects.§r"); @EventHandler
Bukkit.getScheduler().runTaskLaterAsynchronously(PluginMain.Instance, tt, 15 * 20); @SuppressWarnings("deprecation")
} public void onVotifierEvent(VotifierEvent event) { //TODO: Move to teh Core eh
} Vote vote = event.getVote();
PluginMain.Instance.getLogger().info("Vote: " + vote);
@EventHandler org.bukkit.OfflinePlayer op = Bukkit.getOfflinePlayer(vote.getUsername());
@SuppressWarnings("deprecation") Player p = Bukkit.getPlayer(vote.getUsername());
public void onVotifierEvent(VotifierEvent event) { //TODO: Move to teh Core eh if (op != null) {
Vote vote = event.getVote(); PluginMain.economy.depositPlayer(op, 50.0);
PluginMain.Instance.getLogger().info("Vote: " + vote); }
org.bukkit.OfflinePlayer op = Bukkit.getOfflinePlayer(vote.getUsername()); if (p != null) {
Player p = Bukkit.getPlayer(vote.getUsername()); p.sendMessage("§bThanks for voting! $50 was added to your account.");
if (op != null) { }
PluginMain.economy.depositPlayer(op, 50.0); }
}
if (p != null) { @EventHandler
p.sendMessage("§bThanks for voting! $50 was added to your account."); public void onPlayerMove(PlayerMoveEvent e) {
} ChatPlayer mp = TBMCPlayer.getPlayer(e.getPlayer().getUniqueId(), ChatPlayer.class);
} if (mp.ChatOnly)
e.setCancelled(true);
@EventHandler }
public void onPlayerMove(PlayerMoveEvent e) {
ChatPlayer mp = TBMCPlayer.getPlayer(e.getPlayer().getUniqueId(), ChatPlayer.class); @EventHandler(priority = EventPriority.LOWEST)
if (mp.ChatOnly) public void onPlayerTeleport(PlayerTeleportEvent e) {
e.setCancelled(true); if (TBMCPlayer.getPlayer(e.getPlayer().getUniqueId(), ChatPlayer.class).ChatOnly) {
} e.setCancelled(true);
e.getPlayer().sendMessage("§cYou are not allowed to teleport while in chat-only mode.");
@EventHandler(priority = EventPriority.LOWEST) }
public void onPlayerTeleport(PlayerTeleportEvent e) { }
if (TBMCPlayer.getPlayer(e.getPlayer().getUniqueId(), ChatPlayer.class).ChatOnly) {
e.setCancelled(true); @EventHandler(priority = EventPriority.HIGHEST)
e.getPlayer().sendMessage("§cYou are not allowed to teleport while in chat-only mode."); public void onConsoleCommand(ServerCommandEvent event) {
} if (onCommandPreprocess(event.getSender(), event.getCommand()))
} event.setCommand("dontrunthiscmd");
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onConsoleCommand(ServerCommandEvent event) { @EventHandler
if (onCommandPreprocess(event.getSender(), event.getCommand())) public void onGetInfo(TBMCPlayerGetInfoEvent e) {
event.setCommand("dontrunthiscmd"); try (ChatPlayer cp = e.getPlayer().getAs(ChatPlayer.class)) {
} if (cp == null)
return;
@EventHandler e.addInfo("Minecraft name: " + cp.PlayerName().get());
public void onGetInfo(TBMCPlayerGetInfoEvent e) { if (cp.UserName().get() != null && cp.UserName().get().length() > 0)
try (ChatPlayer cp = e.getPlayer().getAs(ChatPlayer.class)) { e.addInfo("Reddit name: " + cp.UserName().get());
if (cp == null) if (ComponentManager.isEnabled(FlairComponent.class)) {
return; final String flair = cp.GetFormattedFlair(e.getTarget() != InfoTarget.MCCommand);
e.addInfo("Minecraft name: " + cp.PlayerName().get()); if (flair.length() > 0)
if (cp.UserName().get() != null && cp.UserName().get().length() > 0) e.addInfo("/r/TheButton flair: " + flair);
e.addInfo("Reddit name: " + cp.UserName().get()); }
final String flair = cp.GetFormattedFlair(e.getTarget() != InfoTarget.MCCommand); e.addInfo(String.format("Respect: %.2f", cp.getF()));
if (flair.length() > 0) } catch (Exception ex) {
e.addInfo("/r/TheButton flair: " + flair); TBMCCoreAPI.SendException("Error while providing chat info for player " + e.getPlayer().getFileName(), ex);
e.addInfo(String.format("Respect: %.2f", cp.getF())); }
} catch (Exception ex) { }
TBMCCoreAPI.SendException("Error while providing chat info for player " + e.getPlayer().getFileName(), ex);
} @EventHandler
} public void onPlayerTBMCChat(TBMCChatEvent e) {
try {
@EventHandler if (e.isCancelled())
public void onPlayerTBMCChat(TBMCChatEvent e) { return;
try { HistoryCommand.addChatMessage(e.getCm(), e.getChannel());
if (e.isCancelled()) e.setCancelled(ChatProcessing.ProcessChat(e));
return; } catch (NoClassDefFoundError | Exception ex) { // Weird things can happen
HistoryCommand.addChatMessage(e.getCm(), e.getChannel()); for (Player p : Bukkit.getOnlinePlayers())
e.setCancelled(ChatProcessing.ProcessChat(e)); if (e.shouldSendTo(p))
} catch (NoClassDefFoundError | Exception ex) { // Weird things can happen p.sendMessage("§c!§r["
for (Player p : Bukkit.getOnlinePlayers()) + e.getChannel().DisplayName().get() + "] <" + (e.getSender() instanceof Player
if (e.shouldSendTo(p)) ? ((Player) e.getSender()).getDisplayName() : e.getSender().getName())
p.sendMessage("§c!§r[" + "> " + e.getMessage());
+ e.getChannel().DisplayName + "] <" + (e.getSender() instanceof Player TBMCCoreAPI.SendException("An error occured while processing a chat message!", ex);
? ((Player) e.getSender()).getDisplayName() : e.getSender().getName()) }
+ "> " + e.getMessage()); }
TBMCCoreAPI.SendException("An error occured while processing a chat message!", ex);
} @EventHandler
} public void onChannelRegistered(ChatChannelRegisterEvent e) {
if (!e.getChannel().isGlobal() && PluginMain.SB.getObjective(e.getChannel().ID) == null) // Not global chat and doesn't exist yet
@EventHandler PluginMain.SB.registerNewObjective(e.getChannel().ID, "dummy");
public void onChannelRegistered(ChatChannelRegisterEvent e) { }
if (!e.getChannel().isGlobal() && PluginMain.SB.getObjective(e.getChannel().ID) == null) // Not global chat and doesn't exist yet
PluginMain.SB.registerNewObjective(e.getChannel().ID, "dummy"); @EventHandler
} public void onNickChange(NickChangeEvent e) {
String nick = e.getValue();
@EventHandler if (nick == null)
public void onNickChange(NickChangeEvent e) { nicknames.inverse().remove(e.getAffected().getBase().getUniqueId());
String nick = e.getValue(); else
if (nick == null) nicknames.inverse().forcePut(e.getAffected().getBase().getUniqueId(), ChatColor.stripColor(nick).toLowerCase());
nicknames.inverse().remove(e.getAffected().getBase().getUniqueId());
else Bukkit.getScheduler().runTaskLater(PluginMain.Instance, () -> {
nicknames.inverse().forcePut(e.getAffected().getBase().getUniqueId(), ChatColor.stripColor(nick).toLowerCase()); TownColorComponent.updatePlayerColors(e.getAffected().getBase()); //Won't fire this event again
}, 1);
Bukkit.getScheduler().runTaskLater(PluginMain.Instance, () -> { }
PlayerJoinLeaveListener.updatePlayerColors(e.getAffected().getBase()); //Won't fire this event again }
}, 1);
}
}

View file

@ -37,9 +37,9 @@ depend:
- Votifier - Votifier
- Vault - Vault
- ButtonCore - ButtonCore
- Dynmap-Towny
soft-depend: soft-depend:
- Minigames - Minigames
- Dynmap-Towny
permissions: permissions:
tbmc.admin: tbmc.admin:
description: Gives access to /un- commands and /u admin commands description: Gives access to /un- commands and /u admin commands

View file

@ -7,8 +7,8 @@ import buttondevteam.chat.formatting.TellrawEvent;
import buttondevteam.chat.formatting.TellrawEvent.ClickAction; import buttondevteam.chat.formatting.TellrawEvent.ClickAction;
import buttondevteam.chat.formatting.TellrawEvent.HoverAction; import buttondevteam.chat.formatting.TellrawEvent.HoverAction;
import buttondevteam.chat.formatting.TellrawPart; import buttondevteam.chat.formatting.TellrawPart;
import buttondevteam.component.channel.Channel;
import buttondevteam.core.TestPrepare; import buttondevteam.core.TestPrepare;
import buttondevteam.lib.chat.Channel;
import buttondevteam.lib.chat.Color; import buttondevteam.lib.chat.Color;
import net.milkbowl.vault.permission.Permission; import net.milkbowl.vault.permission.Permission;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@ -66,10 +66,15 @@ public class ChatFormatIT {
list.add(new ChatFormatIT(sender, "*test _test_ test*", new TellrawPart("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))); new TellrawPart("test").setItalic(true).setUnderlined(true).setColor(Color.White), new TellrawPart(" test").setItalic(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") 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) .setColor(Color.White).setUnderlined(true)
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT, .setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT,
new TellrawPart("Click to open").setColor(Color.Blue))) new TellrawPart("Click to open").setColor(Color.Blue)))
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/test?test&test#test")))); .setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/test?test&test#test"))));
list.add(new ChatFormatIT(sender, "[hmm](https://norbipeti.github.io/test)", new TellrawPart("hmm")
.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/test"))));
return list; return list;
} }