Compare commits

..

30 commits

Author SHA1 Message Date
d1515c2ab2
Fix using delegated config properties from the Core 2023-07-01 20:11:19 +02:00
512a62d75c
Fix remaining test cases for formatting
- Fixed name mentioning test check
- Removed legacy tell raw stuff
- Fixed RPC sections getting combined because the settings weren't updated before checking if they are the same
- Fixed spoiler test assuming and expecting the hover text to be white
#130
2023-06-28 23:56:35 +02:00
b5fd834dc7
Fix chat tests with MockBukkit and fix Paper version
#130
2023-06-27 01:39:35 +02:00
e35e94e87c
Migrate chat formatting to Paper's text component API (#130)
- Also updated the configs to use the interfaces
- Also updated the fun component to use a list config
- The text component change adds Paper as a requirement for this plugin
2023-06-19 00:42:29 +02:00
51cf31713b
Start fixing errors related to player API changes
- The fancy chat API would be useful here, I don't want to update my old code
2023-06-09 01:25:09 +02:00
2242655c41
Merge branch 'hotfix/1.0.1'
# Conflicts:
#	src/main/java/buttondevteam/chat/components/towny/TownyComponent.java
2023-06-07 23:37:10 +02:00
522f29ba58
Update Chroma-Core to v2.0.0 2023-04-26 00:03:18 +02:00
10bf0e98df
Update Towny dependency and replace methods that were removed (#128) 2023-03-13 00:47:40 +01:00
6c1378f370
Update dependencies and fix tellRaw for 1.17+ 2021-12-30 21:19:22 +01:00
56b9296fbb
Merge pull request #126 from TBMCPlugins/dependabot/maven/org.apache.logging.log4j-log4j-core-2.17.0
Bump log4j-core from 2.13.2 to 2.17.0
2021-12-30 16:47:37 +01:00
dependabot[bot]
5c399a08ad
Bump log4j-core from 2.13.2 to 2.17.0
Bumps log4j-core from 2.13.2 to 2.17.0.

---
updated-dependencies:
- dependency-name: org.apache.logging.log4j:log4j-core
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-18 18:20:48 +00:00
724858ac70
Fix tellRaw for 1.16.4/1.16.5 2021-01-18 17:18:35 +01:00
9a10dcd1fc
Fix plugin.yml 2020-10-31 18:24:52 +01:00
dc6df53c96
Improve test coverage, preparations, fixes
Removed an unnnecessary bit of code from ChatFormatter
2020-10-29 20:31:38 +01:00
7646db4487
Fix player data plugin name, Spotbugs fixes
Also set the version
2020-10-28 00:28:15 +01:00
8e9989caee
Convert all configs 2020-10-26 19:56:22 +01:00
77b5a069c5
Merge pull request #123 from TBMCPlugins/dependabot/maven/junit-junit-4.13.1
Bump junit from 4.12 to 4.13.1
2020-10-25 02:00:58 +02:00
c52a6873fe
Exception stuff and player data stuff 2020-10-25 01:18:36 +02:00
c6ba0ec607
Create codeql-analysis.yml 2020-10-13 18:02:45 +02:00
dependabot[bot]
737016bf00
Bump junit from 4.12 to 4.13.1
Bumps [junit](https://github.com/junit-team/junit4) from 4.12 to 4.13.1.
- [Release notes](https://github.com/junit-team/junit4/releases)
- [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.12.md)
- [Commits](https://github.com/junit-team/junit4/compare/r4.12...r4.13.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-13 15:56:57 +00:00
a63f2bb256
Greentext formatter, doc and stuff 2020-09-06 22:46:24 +02:00
59dbc78b52
Fix #122
It will have to be fixed again at a later date
2020-09-04 03:56:25 +02:00
b483b7df0c
Fix /waitwhat and /me 2020-09-04 03:41:23 +02:00
4d4448fca1
Remove htmlcleaner and fix #117 2020-08-26 22:19:56 +02:00
02423153de
Merge pull request #119 from TBMCPlugins/dependabot/maven/org.apache.logging.log4j-log4j-core-2.13.2
Bump log4j-core from 2.8.1 to 2.13.2
2020-07-27 01:15:05 +02:00
ce4f40c2c4
Fix /u ncolor (#118) 2020-07-25 14:17:11 +02:00
dependabot[bot]
372b2f49b3
Bump log4j-core from 2.8.1 to 2.13.2
Bumps log4j-core from 2.8.1 to 2.13.2.

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-01 18:27:01 +00:00
7448eb7e3a
1.16 updates, fixes 2020-06-27 03:00:08 +02:00
c688ec9243
Finally fix Towny errors for 1.12 - use the intended API everywhere 2020-04-08 01:10:49 +02:00
e4b47efd3f
Fix case when the second section goes further when combining
And added a test for it
2020-04-07 23:08:48 +02:00
47 changed files with 788 additions and 939 deletions

View file

@ -7,17 +7,15 @@ before_install: | # Wget BuildTools and run if cached folder not found
# grep so that download counts don't appear in log files # grep so that download counts don't appear in log files
java -jar BuildTools.jar --rev 1.12.2 | grep -vE "[^/ ]*/[^/ ]*\s*KB\s*$" | grep -v "^\s*$" java -jar BuildTools.jar --rev 1.12.2 | grep -vE "[^/ ]*/[^/ ]*\s*KB\s*$" | grep -v "^\s*$"
fi fi
cp ci/settings.xml $HOME/.m2/
language: java language: java
jdk: jdk:
- oraclejdk8 - oraclejdk11
sudo: true sudo: true
dist: trusty # Needed for Java 8, although we might not need Java 8
deploy: deploy:
- provider: releases - provider: releases
api_key: api_key:
secure: "F5YiEuD6LyRENUDMCslcSl0O0dg4IDk+nNeb4X2VLYlmb8dW9beMuIgjH8efTMeaQ3D/ntIkN0Dtf2GKvpOduhwkSbAgw4WM028X60SY9f2hmpEO3LmM4T1tKoDlI1T3BmhYP4KeTKBYn+etV1mSPbT07vUybCm/vGzvr96yMZGNFEoKsWLaEu7dZfBFULj4tXOwrLh/KO6BsdAHvZcGKWNVupPq3YoUVT0dpGcUudf5cpn+aaqMwyd709zgMbyCuqf+c5Udps43q4EKvr9z7TWxFUkGTPVVAcUVygJsi2ytuyA8TLMPq/KhYe9htnkNUnizbqv/j49xww0gVaD7OJXENJ4hAUTV4sdn1DXG45JXW+dir3V7YzbRYn3M+eCuKB2O77SXRZBkxcGtTMtCmghP9/tcRAQlXDXnxu7oAnlUVp17g/+aFApvlzZEZVx2N+fkyEe7JrUFlRCixtHyrmTLWhyV0Px9p0FHJpvSSCL0S0UKVAT/sNHYHhD5gouK7owEomEbG58XCsRDH6Et7RuDksB98ekK8brZp6S7dNIS2CVuVx1vIkXC8PzUGcpJQoztvEYUE20Axahh5s8AkE9n/O9jzs9ajcfYaHhWzYeUZzHdHllOYF9l6VoCUitTk4Sl8eJifSq3GzI+T6wGMBepZHLpe230MvBIrqGZ+Vg=" secure: "F5YiEuD6LyRENUDMCslcSl0O0dg4IDk+nNeb4X2VLYlmb8dW9beMuIgjH8efTMeaQ3D/ntIkN0Dtf2GKvpOduhwkSbAgw4WM028X60SY9f2hmpEO3LmM4T1tKoDlI1T3BmhYP4KeTKBYn+etV1mSPbT07vUybCm/vGzvr96yMZGNFEoKsWLaEu7dZfBFULj4tXOwrLh/KO6BsdAHvZcGKWNVupPq3YoUVT0dpGcUudf5cpn+aaqMwyd709zgMbyCuqf+c5Udps43q4EKvr9z7TWxFUkGTPVVAcUVygJsi2ytuyA8TLMPq/KhYe9htnkNUnizbqv/j49xww0gVaD7OJXENJ4hAUTV4sdn1DXG45JXW+dir3V7YzbRYn3M+eCuKB2O77SXRZBkxcGtTMtCmghP9/tcRAQlXDXnxu7oAnlUVp17g/+aFApvlzZEZVx2N+fkyEe7JrUFlRCixtHyrmTLWhyV0Px9p0FHJpvSSCL0S0UKVAT/sNHYHhD5gouK7owEomEbG58XCsRDH6Et7RuDksB98ekK8brZp6S7dNIS2CVuVx1vIkXC8PzUGcpJQoztvEYUE20Axahh5s8AkE9n/O9jzs9ajcfYaHhWzYeUZzHdHllOYF9l6VoCUitTk4Sl8eJifSq3GzI+T6wGMBepZHLpe230MvBIrqGZ+Vg="
file: 'Chroma-Core/target/Chroma-Core.jar' file: 'target/Chroma-Chat.jar'
on: on:
tags: true tags: true
skip_cleanup: true skip_cleanup: true

View file

@ -1,36 +0,0 @@
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<activeProfiles>
<activeProfile>github</activeProfile>
</activeProfiles>
<profiles>
<profile>
<id>github</id>
<repositories>
<!-- <repository>
<id>central</id>
<url>https://repo1.maven.org/maven2</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
</repository> -->
<repository>
<id>github</id>
<name>GitHub Towny Apache Maven Packages</name>
<url>https://maven.pkg.github.com/TownyAdvanced/Towny</url>
</repository>
</repositories>
</profile>
</profiles>
<servers>
<server>
<id>github</id>
<username>NorbiPeti</username>
<password>${env.GHTOKEN}</password>
</server>
</servers>
</settings>

271
pom.xml
View file

@ -1,56 +1,30 @@
<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>
<parent> <parent>
<groupId>com.github.TBMCPlugins.ChromaCore</groupId> <groupId>com.github.TBMCPlugins.ChromaCore</groupId>
<artifactId>CorePOM</artifactId> <artifactId>CorePOM</artifactId>
<version>master-SNAPSHOT</version> <version>master-SNAPSHOT</version>
</parent> </parent>
<version>0.0.1-SNAPSHOT</version> <version>v${noprefix.version}-SNAPSHOT</version>
<name>Chroma-Chat Plugin</name> <name>Chroma-Chat Plugin</name>
<description>Chroma-Chat Plugin</description> <description>Chroma-Chat Plugin</description>
<build> <build>
<sourceDirectory>src/main/java</sourceDirectory> <sourceDirectory>src/main/java</sourceDirectory>
<resources> <resources>
<resource> <resource>
<directory>src</directory> <directory>src/main/resources</directory>
<excludes> <includes>
<exclude>**/*.java</exclude> <include>*.properties</include>
</excludes> <include>*.yml</include>
</resource> <include>*.csv</include>
<resource> <include>*.txt</include>
<directory>src/main/resources</directory> </includes>
<includes> <filtering>true</filtering>
<include>*.properties</include>
<include>*.yml</include>
<include>*.csv</include>
<include>*.txt</include>
</includes>
<filtering>true</filtering>
</resource> </resource>
</resources> </resources>
<finalName>Chroma-Chat</finalName> <finalName>Chroma-Chat</finalName>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>net.sourceforge.htmlcleaner:htmlcleaner</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</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>
@ -92,64 +66,6 @@
</useSystemClassLoader> <!-- https://stackoverflow.com/a/53012553/2703239 --> </useSystemClassLoader> <!-- https://stackoverflow.com/a/53012553/2703239 -->
</configuration> </configuration>
</plugin> </plugin>
<!-- <plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>2.2.5</version>
<executions>
<execution>
<id>get-the-git-infos</id>
<goals>
<goal>revision</goal>
</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
<phase>initialize</phase>
<configuration>
<injectAllReactorProjects>true</injectAllReactorProjects>
</configuration>
</execution>
<execution>
<id>validate-the-git-infos</id>
<goals>
<goal>validateRevision</goal>
</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
<phase>package</phase>
<configuration>
<validationProperties>
- <validationProperty>
<name>validating git dirty</name>
<value>${git.branch}</value>
<shouldMatchTo>dev</shouldMatchTo>
</validationProperty> -
</validationProperties>
</configuration>
</execution>
</executions>
<configuration>
<injectAllReactorProjects>true</injectAllReactorProjects>
<verbose>true</verbose>
<dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
</configuration>
</plugin> -->
<!-- <plugin> <groupId>org.basepom.maven</groupId> <artifactId>duplicate-finder-maven-plugin</artifactId>
<version>1.2.1</version> <executions> <execution> <goals> <goal>check</goal>
</goals> </execution> </executions> </plugin> -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-testCompile</id>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins> </plugins>
</build> </build>
<groupId>buttondevteam</groupId> <groupId>buttondevteam</groupId>
@ -164,115 +80,119 @@
</repository> </repository>
<repository> <repository>
<id>ess-repo</id> <id>ess-repo</id>
<url>https://ci.ender.zone/plugin/repository/everything/</url> <url>https://repo.essentialsx.net/releases/</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>https://projectlombok.org/mavenrepo</url>
</repository> </repository>
<repository>
<id>Dynmap</id>
<url>https://repo.mikeprimm.com</url>
</repository>
<repository>
<id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
</repositories> </repositories>
<dependencies> <dependencies>
<dependency> <dependency> <!-- TODO: Can't update MockBukkit because of a ByteBuddy exception and the old version relies on 1.19.1 -->
<groupId>org.spigotmc</groupId> <groupId>io.papermc.paper</groupId>
<artifactId>spigot-api</artifactId> <artifactId>paper-api</artifactId>
<version>1.12.2-R0.1-SNAPSHOT</version> <version>1.19.1-R0.1-SNAPSHOT</version>
</dependency> <scope>provided</scope>
<dependency> </dependency>
<groupId>com.github.TBMCPlugins.ChromaCore</groupId>
<artifactId>Chroma-Core</artifactId>
<version>${branch}-SNAPSHOT</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.sourceforge.htmlcleaner/htmlcleaner -->
<dependency>
<groupId>net.sourceforge.htmlcleaner</groupId>
<artifactId>htmlcleaner</artifactId>
<version>2.16</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.reflections/reflections -->
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.10</version>
</dependency>
<dependency> <dependency>
<groupId>net.ess3</groupId> <groupId>com.github.TBMCPlugins.ChromaCore</groupId>
<artifactId>Chroma-Core</artifactId>
<version>v2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>net.essentialsx</groupId>
<artifactId>EssentialsX</artifactId> <artifactId>EssentialsX</artifactId>
<version>2.17.1</version> <version>2.19.2</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.palmergames.bukkit.towny</groupId> <groupId>com.github.TownyAdvanced</groupId>
<artifactId>Towny</artifactId> <artifactId>Towny</artifactId>
<version>0.95.2.0</version> <!-- <version>8d3b6b6</version> ButtonCore repo -->
<version>0.98.6.0</version>
<scope>provided</scope>
</dependency>
<!-- <dependency> <groupId>au.com.mineauz</groupId> <artifactId>Minigames</artifactId>
<version>1.8.0</version> </dependency> -->
<dependency>
<groupId>com.github.MilkBowl</groupId>
<artifactId>VaultAPI</artifactId>
<version>1.7</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- <dependency> <groupId>au.com.mineauz</groupId> <artifactId>Minigames</artifactId>
<version>1.8.0</version> </dependency> -->
<dependency>
<groupId>com.github.milkbowl</groupId>
<artifactId>VaultAPI</artifactId>
<version>master-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.18.10</version> <version>1.18.22</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.12.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- <dependency> <!-- <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId> <artifactId>spigot</artifactId>
<version>1.14.4-R0.1-SNAPSHOT</version> <version>1.16.4-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency> --> </dependency> -->
<dependency> <dependency>
<groupId>com.github.webbukkit</groupId> <groupId>com.github.TownyAdvanced</groupId>
<artifactId>Dynmap-Towny</artifactId> <artifactId>Dynmap-Towny</artifactId>
<version>master-SNAPSHOT</version> <version>0.89</version>
</dependency>
<dependency>
<groupId>com.github.webbukkit</groupId>
<artifactId>Dynmap</artifactId>
<version>v2.5</version>
</dependency> </dependency>
<dependency>
<groupId>us.dynmap</groupId>
<artifactId>dynmap-api</artifactId>
<version>3.2-beta-1</version>
</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.13.2</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- Included in vanilla minecraft's JAR --> <!-- Included in vanilla minecraft's JAR -->
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId> <artifactId>log4j-core</artifactId>
<version>2.8.1</version> <version>2.17.0</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- TestPrepare also needs it (ChromaCore) so the versions should match --> <!-- TestPrepare also needs it (ChromaCore) so the versions should match -->
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId> <artifactId>mockito-core</artifactId>
<version>3.0.0</version> <version>4.2.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mojang/brigadier -->
<dependency>
<groupId>com.mojang</groupId>
<artifactId>brigadier</artifactId>
<version>1.0.500</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.seeseemelk</groupId>
<artifactId>MockBukkit-v1.19</artifactId>
<version>2.29.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
@ -285,23 +205,6 @@
<!-- 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>
<branch> <noprefix.version>1.0.0</noprefix.version>
master
</branch> <!-- Should be master if building ButtonCore locally - the CI will overwrite it (see below) -->
</properties> </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,50 +1,34 @@
package buttondevteam.chat; package buttondevteam.chat;
import buttondevteam.chat.components.flair.FlairStates; import buttondevteam.chat.components.flair.FlairStates;
import buttondevteam.lib.architecture.config.IConfigData;
import buttondevteam.lib.architecture.config.IListConfigData;
import buttondevteam.lib.chat.Color; import buttondevteam.lib.chat.Color;
import buttondevteam.lib.player.EnumPlayerData;
import buttondevteam.lib.player.PlayerClass; import buttondevteam.lib.player.PlayerClass;
import buttondevteam.lib.player.PlayerData;
import buttondevteam.lib.player.TBMCPlayerBase; import buttondevteam.lib.player.TBMCPlayerBase;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList; import java.util.Collections;
import java.util.List;
@PlayerClass(pluginname = "Button1Chat") @PlayerClass(pluginname = "Chroma-Chat")
public class ChatPlayer extends TBMCPlayerBase { public class ChatPlayer extends TBMCPlayerBase {
public PlayerData<String> UserName() { public final IConfigData<String> UserName = getConfig().getData("UserName", "");
return data(null);
}
public List<String> UserNames() { public final IListConfigData<String> UserNames = getConfig().getListData("UserNames", Collections.emptyList());
return data(new ArrayList<String>()).get();
}
public PlayerData<Integer> FlairTime() { public final IConfigData<Integer> FlairTime = getConfig().getData("FlairTime", FlairTimeNone);
return data(FlairTimeNone);
}
public EnumPlayerData<FlairStates> FlairState() { public final IConfigData<FlairStates> FlairState = getConfig().getData("FlairState", FlairStates.NoComment,
return dataEnum(FlairStates.class, FlairStates.NoComment); fs -> FlairStates.valueOf((String) fs), FlairStates::toString);
}
public PlayerData<Integer> FCount() { public final IConfigData<Integer> FCount = getConfig().getData("FCount", 0);
return data(0);
}
public PlayerData<Integer> FDeaths() { public final IConfigData<Integer> FDeaths = getConfig().getData("FDeaths", 0);
return data(0);
}
public PlayerData<Boolean> FlairCheater() { public final IConfigData<Boolean> FlairCheater = getConfig().getData("FlairCheater", false);
return data(false);
}
public PlayerData<ArrayList<Integer>> NameColorLocations() { // No byte[], no TIntArrayList public final IListConfigData<Integer> NameColorLocations = getConfig().getListData("NameColorLocations", Collections.emptyList()); // No byte[], no TIntArrayList
return data(null);
}
public boolean Working; public boolean Working;
// public int Tables = 10; // public int Tables = 10;
@ -64,7 +48,7 @@ public class ChatPlayer extends TBMCPlayerBase {
* @return The flair * @return The flair
*/ */
public String GetFormattedFlair(boolean noformats) { public String GetFormattedFlair(boolean noformats) {
int time = FlairTime().get(); int time = FlairTime.get();
if (time == FlairTimeCantPress) if (time == FlairTimeCantPress)
return noformats ? "(can't press)" : "§r(--s)§r"; return noformats ? "(can't press)" : "§r(--s)§r";
if (time == FlairTimeNonPresser) if (time == FlairTimeNonPresser)
@ -84,13 +68,13 @@ public class ChatPlayer extends TBMCPlayerBase {
} }
public void SetFlair(int time) { public void SetFlair(int time) {
FlairTime().set(time); FlairTime.set(time);
FlairUpdate(); FlairUpdate();
} }
public void SetFlair(int time, boolean cheater) { public void SetFlair(int time, boolean cheater) {
FlairTime().set(time); FlairTime.set(time);
FlairCheater().set(cheater); FlairCheater.set(cheater);
FlairUpdate(); FlairUpdate();
} }
@ -98,15 +82,15 @@ public class ChatPlayer extends TBMCPlayerBase {
// Flairs from Command Block The Button - Teams // Flairs from Command Block The Button - Teams
// PluginMain.Instance.getServer().getScoreboardManager().getMainScoreboard().getTeams().add() // PluginMain.Instance.getServer().getScoreboardManager().getMainScoreboard().getTeams().add()
Player p = Bukkit.getPlayer(uuid); Player p = Bukkit.getPlayer(getUniqueId());
if (p != null) if (p != null)
p.setPlayerListName(String.format("%s%s", p.getDisplayName(), GetFormattedFlair())); p.setPlayerListName(String.format("%s%s", p.getDisplayName(), GetFormattedFlair()));
} }
public short GetFlairColor() { public short GetFlairColor() {
if (FlairCheater().get()) if (FlairCheater.get())
return 0x5; return 0x5;
final int flairTime = FlairTime().get(); final int flairTime = FlairTime.get();
if (flairTime == FlairTimeNonPresser) if (flairTime == FlairTimeNonPresser)
return 0x7; return 0x7;
else if (flairTime == FlairTimeCantPress) else if (flairTime == FlairTimeCantPress)
@ -127,6 +111,6 @@ public class ChatPlayer extends TBMCPlayerBase {
} }
public double getF() { public double getF() {
return (double) FCount().get() / (double) FDeaths().get(); return (double) FCount.get() / (double) FDeaths.get();
} }
} }

View file

@ -1,12 +1,13 @@
package buttondevteam.chat; package buttondevteam.chat;
import buttondevteam.lib.ChromaUtils; import buttondevteam.core.component.channel.Channel;
import buttondevteam.lib.TBMCChatEvent; import buttondevteam.lib.TBMCChatEvent;
import buttondevteam.lib.player.ChromaGamerBase;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function;
public final class ChatUtils { public final class ChatUtils {
public 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
@ -44,16 +45,21 @@ public final class ChatUtils {
/** /**
* Sends a regular (non-Markdown) chat message. Used as a fallback if the chat processing fails. * Sends a regular (non-Markdown) chat message. Used as a fallback if the chat processing fails.
* *
* @param e The chat event * @param e The chat event
* @param modifier A function that alters the message to be displayed to the player
*/ */
public static void sendChatMessage(TBMCChatEvent e, Function<String, String> modifier) { public static void sendChatMessage(TBMCChatEvent e) {
var str = "[" + e.getChannel().DisplayName().get() + "] <" var str = getMessageString(e.getChannel(), e.getUser(), e.getMessage());
+ ChromaUtils.getDisplayName(e.getSender()) + "> " + e.getMessage();
str = modifier.apply(str);
for (Player p : Bukkit.getOnlinePlayers()) for (Player p : Bukkit.getOnlinePlayers())
if (e.shouldSendTo(p)) if (e.shouldSendTo(ChromaGamerBase.getFromSender(p)))
p.sendMessage(str); p.sendMessage(str);
Bukkit.getConsoleSender().sendMessage(str); Bukkit.getConsoleSender().sendMessage(str);
} }
public static String getMessageString(Channel channel, ChromaGamerBase sender, String message) {
return "§c!§r[" + channel.displayName.get() + "] <" + sender.getName() + "> " + message;
}
public static void sendChatMessage(Channel channel, ChromaGamerBase sender, String message, CommandSender to) {
to.sendMessage(getMessageString(channel, sender, message));
}
} }

View file

@ -21,19 +21,16 @@ import buttondevteam.core.component.channel.Channel;
import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.architecture.ButtonPlugin; import buttondevteam.lib.architecture.ButtonPlugin;
import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.architecture.ConfigData; import buttondevteam.lib.architecture.config.IConfigData;
import buttondevteam.lib.chat.Color; import buttondevteam.lib.chat.Color;
import buttondevteam.lib.chat.TBMCChatAPI; import buttondevteam.lib.chat.TBMCChatAPI;
import com.earth2me.essentials.Essentials; import com.earth2me.essentials.Essentials;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.permission.Permission; import net.milkbowl.vault.permission.Permission;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.ConsoleCommandSender; import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.RegisteredServiceProvider;
public class PluginMain extends ButtonPlugin { // Translated to Java: 2015.07.15. public class PluginMain extends ButtonPlugin { // Translated to Java: 2015.07.15.
// A user, which flair isn't obtainable:
// https://www.reddit.com/r/thebutton/comments/31c32v/i_pressed_the_button_without_really_thinking/
public static PluginMain Instance; public static PluginMain Instance;
public static ConsoleCommandSender Console; public static ConsoleCommandSender Console;
@ -41,9 +38,7 @@ public class PluginMain extends ButtonPlugin { // Translated to Java: 2015.07.15
* If enabled, stores and displays the last 10 messages the player can see (public, their town chat etc.) * If enabled, stores and displays the last 10 messages the player can see (public, their town chat etc.)
* Can be used with the Discord plugin so players can see some of the conversation they missed that's visible on Discord anyways. * Can be used with the Discord plugin so players can see some of the conversation they missed that's visible on Discord anyways.
*/ */
public ConfigData<Boolean> storeChatHistory() { public IConfigData<Boolean> storeChatHistory = getIConfig().getData("storeChatHistory", true);
return getIConfig().getData("storeChatHistory", true);
}
// Fired when plugin is first enabled // Fired when plugin is first enabled
@Override @Override
@ -58,10 +53,10 @@ public class PluginMain extends ButtonPlugin { // Translated to Java: 2015.07.15
if (Bukkit.getPluginManager().isPluginEnabled("Towny")) if (Bukkit.getPluginManager().isPluginEnabled("Towny"))
Component.registerComponent(this, new TownyComponent()); Component.registerComponent(this, new TownyComponent());
TBMCChatAPI.RegisterChatChannel(new Channel("§7RP§f", Color.Gray, "rp", null)); //Since it's null, it's recognised as global TBMCChatAPI.registerChatChannel(new Channel("§7RP§f", Color.Gray, "rp", null)); //Since it's null, it's recognised as global
if (!setupEconomy() || !setupPermissions()) if (!setupPermissions())
TBMCCoreAPI.SendException("We're in trouble", new Exception("Failed to set up economy or permissions!")); TBMCCoreAPI.SendException("We're in trouble", new Exception("Failed to set up permissions!"), this);
if (Bukkit.getPluginManager().isPluginEnabled("Towny")) if (Bukkit.getPluginManager().isPluginEnabled("Towny"))
Component.registerComponent(this, new TownColorComponent()); Component.registerComponent(this, new TownColorComponent());
@ -88,7 +83,6 @@ public class PluginMain extends ButtonPlugin { // Translated to Java: 2015.07.15
} }
public static Permission permission = null; public static Permission permission = null;
public static Economy economy = null;
private boolean setupPermissions() { private boolean setupPermissions() {
RegisteredServiceProvider<Permission> permissionProvider = getServer().getServicesManager() RegisteredServiceProvider<Permission> permissionProvider = getServer().getServicesManager()
@ -99,14 +93,4 @@ public class PluginMain extends ButtonPlugin { // Translated to Java: 2015.07.15
return (permission != null); return (permission != 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);
}
} }

View file

@ -2,10 +2,14 @@ package buttondevteam.chat;
import buttondevteam.core.MainPlugin; import buttondevteam.core.MainPlugin;
import buttondevteam.lib.TBMCChatEvent; import buttondevteam.lib.TBMCChatEvent;
import buttondevteam.lib.player.ChromaGamerBase;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import lombok.val; import lombok.val;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
import java.util.function.Predicate; import java.util.function.Predicate;
@ -13,14 +17,12 @@ import java.util.function.Predicate;
public class VanillaUtils { public class VanillaUtils {
public String getGroupIfChatOn(Player p, TBMCChatEvent e) { public String getGroupIfChatOn(Player p, TBMCChatEvent e) {
try { try {
if (isChatOn(p)) // Only send if client allows chat if (!isChatOn(p)) // Only send if client allows chat
return e.getGroupID(p);
else
return null; return null;
} catch (NoClassDefFoundError ex) { } catch (NoClassDefFoundError ex) {
MainPlugin.Instance.getLogger().warning("Compatibility error, can't check if the chat is hidden by the player."); MainPlugin.getInstance().getLogger().warning("Compatibility error, can't check if the chat is hidden by the player.");
return e.getGroupID(p);
} }
return e.getGroupID(ChromaGamerBase.getFromSender(p));
} }
private Predicate<Player> isChatOn; private Predicate<Player> isChatOn;
@ -79,9 +81,22 @@ public class VanillaUtils {
if (notCraftPlayer(pcl)) return false; if (notCraftPlayer(pcl)) return false;
val hm = pcl.getMethod("getHandle"); val hm = pcl.getMethod("getHandle");
val handle = hm.invoke(p); val handle = hm.invoke(p);
val nms = handle.getClass().getPackage().getName(); var nmsOrChat = handle.getClass().getPackage().getName();
val chatcompcl = Class.forName(nms + ".IChatBaseComponent"); if (!nmsOrChat.contains(".v1_"))
val sendmsg = handle.getClass().getMethod("sendMessage", chatcompcl); nmsOrChat = "net.minecraft.network.chat";
val chatcompcl = Class.forName(nmsOrChat + ".IChatBaseComponent");
//val chatcomarrcl = Class.forName("[L" + chatcompcl.getName() + ";");
val chatcomparr = Array.newInstance(chatcompcl, 1);
final Method sendmsg;
{
Method sendmsg1;
try {
sendmsg1 = handle.getClass().getMethod("sendMessage", UUID.class, chatcomparr.getClass());
} catch (NoSuchMethodException e) {
sendmsg1 = handle.getClass().getMethod("sendMessage", chatcomparr.getClass());
}
sendmsg = sendmsg1;
}
/*val ccucl = Class.forName(nms + ".ChatComponentUtils"); /*val ccucl = Class.forName(nms + ".ChatComponentUtils");
val iclcl = Class.forName(nms + ".ICommandListener"); val iclcl = Class.forName(nms + ".ICommandListener");
@ -97,7 +112,11 @@ public class VanillaUtils {
val hhandle = hm.invoke(pl); val hhandle = hm.invoke(pl);
val deserialized = am.invoke(null, jsonStr); val deserialized = am.invoke(null, jsonStr);
//val filtered = ffdm.invoke(null, hhandle, deserialized, hhandle); //val filtered = ffdm.invoke(null, hhandle, deserialized, hhandle);
sendmsg.invoke(hhandle, deserialized); Array.set(chatcomparr, 0, deserialized);
if (sendmsg.getParameterCount() == 2)
sendmsg.invoke(hhandle, null, chatcomparr); //
else
sendmsg.invoke(hhandle, chatcomparr);
return true; return true;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();

View file

@ -10,6 +10,6 @@ import buttondevteam.lib.chat.*;
public class MeCommand extends ICommand2MC { public class MeCommand extends ICommand2MC {
@Command2.Subcommand @Command2.Subcommand
public void def(Command2MCSender sender, @Command2.TextArg String message) { public void def(Command2MCSender sender, @Command2.TextArg String message) {
TBMCChatAPI.SendSystemMessage(sender.getChannel(), sender.getChannel().getRTR(sender.getPermCheck()), "§5* " + sender.getName() + " " + message, TBMCSystemChatEvent.BroadcastTarget.ALL); TBMCChatAPI.SendSystemMessage(sender.getChannel(), sender.getChannel().getRTR(sender.getPermCheck()), "§5* " + sender.getSender().getName() + " " + message, TBMCSystemChatEvent.BroadcastTarget.ALL);
} }
} }

View file

@ -10,7 +10,10 @@ import org.bukkit.command.CommandSender;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Random; import java.util.Random;
@CommandClass(modOnly = true) @CommandClass(modOnly = true, helpText = {
"Snap",
"Perfectly balanced as all things should be."
})
public class SnapCommand extends ICommand2MC { public class SnapCommand extends ICommand2MC {
@Command2.Subcommand @Command2.Subcommand
public void def(CommandSender sender) { public void def(CommandSender sender) {

View file

@ -49,8 +49,8 @@ public final class HelpCommand extends UCommandBase {
"§nunderline - &n§r | §oitalic - &o§r", // "§nunderline - &n§r | §oitalic - &o§r", //
"The format codes in tellraw should be used like \"italic\":\"true\""}); // "The format codes in tellraw should be used like \"italic\":\"true\""}); //
} else { } else {
String[] text = getManager().getHelpText(topicOrCommand); String[] text = getManager().getCommandNode(topicOrCommand).getData().getHelpText(sender); // TODO: This only works for the main command, not subcommands
if (text == null) if (text == null) // TODO: Null check for command node
sender.sendMessage( sender.sendMessage(
new String[]{"§cError: Command not found: " + topicOrCommand, new String[]{"§cError: Command not found: " + topicOrCommand,
"Usage example: /u accept --> /u help u accept"}); "Usage example: /u accept --> /u help u accept"});

View file

@ -6,9 +6,8 @@ import buttondevteam.lib.chat.ChatMessage;
import buttondevteam.lib.chat.Command2; import buttondevteam.lib.chat.Command2;
import buttondevteam.lib.chat.CommandClass; import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.chat.CustomTabCompleteMethod; import buttondevteam.lib.chat.CustomTabCompleteMethod;
import lombok.RequiredArgsConstructor; import buttondevteam.lib.player.ChromaGamerBase;
import lombok.val; import lombok.val;
import org.bukkit.command.CommandSender;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -26,22 +25,22 @@ public class HistoryCommand extends UCommandBase {
private static final HashMap<String, LinkedList<HistoryEntry>> messages = new HashMap<>(); private static final HashMap<String, LinkedList<HistoryEntry>> messages = new HashMap<>();
@Command2.Subcommand @Command2.Subcommand
public boolean def(CommandSender sender, @Command2.OptionalArg String channel) { public boolean def(ChromaGamerBase sender, @Command2.OptionalArg String channel) {
return showHistory(sender, channel); return showHistory(sender, channel);
} }
public static boolean showHistory(CommandSender sender, String channel) { public static boolean showHistory(ChromaGamerBase sender, String channel) {
if (!PluginMain.Instance.storeChatHistory().get()) { if (!PluginMain.Instance.storeChatHistory.get()) {
sender.sendMessage("§6Chat history is disabled"); sender.sendMessage("§6Chat history is disabled");
return true; return true;
} }
Function<Channel, LinkedList<HistoryEntry>> getThem = ch -> messages.get(ch.ID + "_" + ch.getGroupID(sender)); //If can't see, groupID is null, and that shouldn't be in the map Function<Channel, LinkedList<HistoryEntry>> getThem = ch -> messages.get(ch.getIdentifier() + "_" + ch.getGroupID(sender)); //If can't see, groupID is null, and that shouldn't be in the map
sender.sendMessage("§6---- Chat History ----"); sender.sendMessage("§6---- Chat History ----");
Stream<Channel> stream; Stream<Channel> stream;
if (channel == null) { if (channel == null) {
stream = Channel.getChannels(); stream = Channel.getChannels();
} else { } else {
Optional<Channel> och = Channel.getChannels().filter(chan -> chan.ID.equalsIgnoreCase(channel)).findAny(); Optional<Channel> och = Channel.getChannels().filter(chan -> chan.getIdentifier().equalsIgnoreCase(channel)).findAny();
if (!och.isPresent()) { if (!och.isPresent()) {
sender.sendMessage("§cChannel not found. Use the ID, for example: /u history g"); sender.sendMessage("§cChannel not found. Use the ID, for example: /u history g");
return true; return true;
@ -55,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().get() + "] " + cm.getSender().getName() + ": " + cm.getMessage()); sender.sendMessage("[" + e.channel.displayName.get() + "] " + cm.getUser().getName() + ": " + cm.getMessage());
sent.set(true); sent.set(true);
} }
} }
@ -66,25 +65,21 @@ public class HistoryCommand extends UCommandBase {
@CustomTabCompleteMethod(param = "channel") @CustomTabCompleteMethod(param = "channel")
public Iterable<String> def() { public Iterable<String> def() {
return Channel.getChannels().map(ch -> ch.ID)::iterator; return Channel.getChannels().map(Channel::getIdentifier)::iterator;
} }
@RequiredArgsConstructor /**
private static class HistoryEntry { * @param timestamp System.nanoTime()
/** */
* System.nanoTime() private record HistoryEntry(long timestamp, ChatMessage chatMessage, Channel channel) {
*/
private final long timestamp;
private final ChatMessage chatMessage;
private final Channel channel;
} }
public static void addChatMessage(ChatMessage chatMessage, Channel channel) { public static void addChatMessage(ChatMessage chatMessage, Channel channel) {
if (!PluginMain.Instance.storeChatHistory().get()) return; if (!PluginMain.Instance.storeChatHistory.get()) return;
val groupID = channel.getGroupID(chatMessage.getPermCheck()); val groupID = channel.getGroupID(chatMessage.getPermCheck());
if (groupID == null) return; //Just to be sure if (groupID == null) return; //Just to be sure
synchronized (messages) { synchronized (messages) {
var ll = messages.computeIfAbsent(channel.ID + "_" + groupID, k -> new LinkedList<>()); //<-- TIL var ll = messages.computeIfAbsent(channel.getIdentifier() + "_" + groupID, k -> new LinkedList<>()); //<-- TIL
ll.add(new HistoryEntry(System.nanoTime(), chatMessage, channel)); //Adds as last element ll.add(new HistoryEntry(System.nanoTime(), chatMessage, channel)); //Adds as last element
while (ll.size() > 10) while (ll.size() > 10)
ll.remove(); //Removes the first element ll.remove(); //Removes the first element

View file

@ -1,7 +1,6 @@
package buttondevteam.chat.commands.ucmds; package buttondevteam.chat.commands.ucmds;
import buttondevteam.chat.PluginMain; import buttondevteam.chat.PluginMain;
import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.chat.Command2; import buttondevteam.lib.chat.Command2;
import buttondevteam.lib.chat.CommandClass; import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.player.ChromaGamerBase.InfoTarget; import buttondevteam.lib.player.ChromaGamerBase.InfoTarget;
@ -19,16 +18,12 @@ public class InfoCommand extends UCommandBase {
@Command2.Subcommand @Command2.Subcommand
public boolean def(CommandSender sender, OfflinePlayer player) { public boolean def(CommandSender sender, OfflinePlayer player) {
Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> { Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
try (TBMCPlayer p = TBMCPlayerBase.getPlayer(player.getUniqueId(), TBMCPlayer.class)) { TBMCPlayer p = TBMCPlayerBase.getPlayer(player.getUniqueId(), TBMCPlayer.class);
if (p == null) { if (p == null) {
sender.sendMessage("§cThe specified player cannot be found"); sender.sendMessage("§cThe specified player cannot be found");
return; return;
}
sender.sendMessage(p.getInfo(InfoTarget.MCCommand));
} catch (Exception e) {
TBMCCoreAPI.SendException("Error while getting player information!", e);
sender.sendMessage("§cError while getting player information!");
} }
sender.sendMessage(p.getInfo(InfoTarget.MCCommand));
}); });
return true; return true;
} }

View file

@ -1,10 +1,7 @@
package buttondevteam.chat.components.announce; package buttondevteam.chat.components.announce;
import buttondevteam.chat.commands.ucmds.UCommandBase; import buttondevteam.chat.commands.ucmds.UCommandBase;
import buttondevteam.chat.components.formatter.ChatProcessing;
import buttondevteam.chat.components.formatter.FormatterComponent; import buttondevteam.chat.components.formatter.FormatterComponent;
import buttondevteam.chat.components.formatter.formatting.TellrawEvent;
import buttondevteam.chat.components.formatter.formatting.TellrawPart;
import buttondevteam.core.ComponentManager; import buttondevteam.core.ComponentManager;
import buttondevteam.lib.chat.Command2; import buttondevteam.lib.chat.Command2;
import buttondevteam.lib.chat.CommandClass; import buttondevteam.lib.chat.CommandClass;
@ -13,6 +10,12 @@ import lombok.val;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.event.ClickEvent.Action.SUGGEST_COMMAND;
import static net.kyori.adventure.text.event.ClickEvent.clickEvent;
import static net.kyori.adventure.text.event.HoverEvent.Action.SHOW_TEXT;
import static net.kyori.adventure.text.event.HoverEvent.hoverEvent;
@CommandClass(modOnly = true) @CommandClass(modOnly = true)
@RequiredArgsConstructor @RequiredArgsConstructor
public class AnnounceCommand extends UCommandBase { public class AnnounceCommand extends UCommandBase {
@ -24,7 +27,7 @@ public class AnnounceCommand extends UCommandBase {
}) })
public boolean add(CommandSender sender, @Command2.TextArg String text) { public boolean add(CommandSender sender, @Command2.TextArg String text) {
String finalmessage = text.replace('&', '§'); String finalmessage = text.replace('&', '§');
component.announceMessages().get().add(finalmessage); component.announceMessages.get().add(finalmessage);
sender.sendMessage("§bAnnouncement added.§r"); sender.sendMessage("§bAnnouncement added.§r");
return true; return true;
} }
@ -38,9 +41,9 @@ public class AnnounceCommand extends UCommandBase {
String finalmessage1 = text.replace('&', '§'); String finalmessage1 = text.replace('&', '§');
if (index > 100) if (index > 100)
return false; return false;
while (component.announceMessages().get().size() <= index) while (component.announceMessages.get().size() <= index)
component.announceMessages().get().add(""); component.announceMessages.get().add("");
component.announceMessages().get().set(index, finalmessage1); component.announceMessages.get().set(index, finalmessage1);
sender.sendMessage("Announcement edited."); sender.sendMessage("Announcement edited.");
return true; return true;
} }
@ -53,21 +56,19 @@ public class AnnounceCommand extends UCommandBase {
sender.sendMessage("§bList of announce messages:§r"); sender.sendMessage("§bList of announce messages:§r");
sender.sendMessage("§bFormat: [index] message§r"); sender.sendMessage("§bFormat: [index] message§r");
int i = 0; int i = 0;
for (String message : component.announceMessages().get()) { for (String message : component.announceMessages.get()) {
String msg = "[" + i++ + "] " + message; String msg = "[" + i++ + "] " + message;
//noinspection SuspiciousMethodCalls //noinspection SuspiciousMethodCalls
if (!ComponentManager.isEnabled(FormatterComponent.class) || !Bukkit.getOnlinePlayers().contains(sender)) { if (!ComponentManager.isEnabled(FormatterComponent.class) || !Bukkit.getOnlinePlayers().contains(sender)) {
sender.sendMessage(msg); sender.sendMessage(msg);
continue; continue;
} }
String json = ChatProcessing.toJson(new TellrawPart(msg) sender.sendMessage(text(msg)
.setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, "Click to edit")) .hoverEvent(hoverEvent(SHOW_TEXT, text("Click to edit")))
.setClickEvent(TellrawEvent.create(TellrawEvent.ClickAction.SUGGEST_COMMAND, .clickEvent(clickEvent(SUGGEST_COMMAND, "/" + getCommandPath() + " edit " + (i - 1) + " " + message.replace('§', '&'))));
"/" + getCommandPath() + " edit " + (i - 1) + " " + message.replace('§', '&'))));
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + sender.getName() + " " + json);
} }
sender.sendMessage("§bCurrent wait time between announcements: " sender.sendMessage("§bCurrent wait time between announcements: "
+ component.announceTime().get() / 60 / 1000 + " minute(s)§r"); + component.announceTime.get() / 60 / 1000 + " minute(s)§r");
return true; return true;
} }
@ -76,7 +77,7 @@ public class AnnounceCommand extends UCommandBase {
"This command removes an announcement" "This command removes an announcement"
}) })
public boolean remove(CommandSender sender, int index) { public boolean remove(CommandSender sender, int index) {
val msgs = component.announceMessages().get(); val msgs = component.announceMessages.get();
if (index < 0 || index > msgs.size()) return false; if (index < 0 || index > msgs.size()) return false;
msgs.remove(index); msgs.remove(index);
sender.sendMessage("Announcement removed."); sender.sendMessage("Announcement removed.");
@ -88,7 +89,7 @@ public class AnnounceCommand extends UCommandBase {
"This command sets the time between the announcements" "This command sets the time between the announcements"
}) })
public boolean settime(CommandSender sender, int minutes) { public boolean settime(CommandSender sender, int minutes) {
component.announceTime().set(minutes * 60 * 1000); component.announceTime.set(minutes * 60 * 1000);
sender.sendMessage("Time set between announce messages to " + minutes + " minutes"); sender.sendMessage("Time set between announce messages to " + minutes + " minutes");
return true; return true;
} }

View file

@ -4,28 +4,28 @@ import buttondevteam.chat.PluginMain;
import buttondevteam.core.component.channel.Channel; import buttondevteam.core.component.channel.Channel;
import buttondevteam.lib.TBMCSystemChatEvent; import buttondevteam.lib.TBMCSystemChatEvent;
import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.architecture.ConfigData; import buttondevteam.lib.architecture.ComponentMetadata;
import buttondevteam.lib.architecture.ListConfigData; import buttondevteam.lib.architecture.config.IConfigData;
import buttondevteam.lib.architecture.config.IListConfigData;
import buttondevteam.lib.chat.TBMCChatAPI; import buttondevteam.lib.chat.TBMCChatAPI;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import java.util.Collections;
/** /**
* Displays the configured messages at the set interval when someone is online. * Displays the configured messages at the set interval when someone is online.
*/ */
@ComponentMetadata(enabledByDefault = false)
public class AnnouncerComponent extends Component<PluginMain> implements Runnable { public class AnnouncerComponent extends Component<PluginMain> implements Runnable {
/** /**
* The messages to display to players. * The messages to display to players.
*/ */
public ListConfigData<String> announceMessages() { public IListConfigData<String> announceMessages = getConfig().getListData("announceMessages", Collections.emptyList());
return getConfig().getListData("announceMessages");
}
/** /**
* The time in milliseconds between the messages. Use /u announce settime to set minutes. * The time in milliseconds between the messages. Use /u announce settime to set minutes.
*/ */
public ConfigData<Integer> announceTime() { public IConfigData<Integer> announceTime = getConfig().getData("announceTime", 15 * 60 * 1000);
return getConfig().getData("announceTime", 15 * 60 * 1000);
}
private TBMCSystemChatEvent.BroadcastTarget target; private TBMCSystemChatEvent.BroadcastTarget target;
@ -35,15 +35,15 @@ public class AnnouncerComponent extends Component<PluginMain> implements Runnabl
public void run() { public void run() {
while (isEnabled()) { while (isEnabled()) {
try { try {
Thread.sleep(announceTime().get()); Thread.sleep(announceTime.get());
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }
if (Bukkit.getOnlinePlayers().size() == 0) continue; //Don't post to Discord if nobody is on if (Bukkit.getOnlinePlayers().size() == 0) continue; //Don't post to Discord if nobody is on
if (announceMessages().get().size() > AnnounceMessageIndex) { if (announceMessages.get().size() > AnnounceMessageIndex) {
TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, Channel.RecipientTestResult.ALL, announceMessages().get().get(AnnounceMessageIndex), target); TBMCChatAPI.SendSystemMessage(Channel.globalChat, Channel.RecipientTestResult.ALL, announceMessages.get().get(AnnounceMessageIndex), target);
AnnounceMessageIndex++; AnnounceMessageIndex++;
if (AnnounceMessageIndex == announceMessages().get().size()) if (AnnounceMessageIndex == announceMessages.get().size())
AnnounceMessageIndex = 0; AnnounceMessageIndex = 0;
} }
} }

View file

@ -2,10 +2,9 @@ package buttondevteam.chat.components.appendext;
import buttondevteam.chat.PluginMain; import buttondevteam.chat.PluginMain;
import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.architecture.ConfigData;
import buttondevteam.lib.architecture.IHaveConfig; import buttondevteam.lib.architecture.IHaveConfig;
import buttondevteam.lib.architecture.config.IConfigData;
import buttondevteam.lib.chat.*; import buttondevteam.lib.chat.*;
import buttondevteam.lib.player.ChromaGamerBase;
import lombok.val; import lombok.val;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -20,16 +19,16 @@ import java.util.function.Consumer;
public class AppendTextComponent extends Component<PluginMain> { public class AppendTextComponent extends Component<PluginMain> {
private Map<String, IHaveConfig> appendTexts; private Map<String, IHaveConfig> appendTexts;
private ConfigData<String[]> helpText(IHaveConfig config) { private IConfigData<String[]> helpText(IHaveConfig config) {
return config.getData("helpText", () -> new String[]{ return config.getData("helpText", new String[]{
"Tableflip", // "Tableflip", //
"This command appends a tableflip after your message", // "This command appends a tableflip after your message", //
"Or just makes you tableflip", // "Or just makes you tableflip", //
}); });
} }
private ConfigData<String> appendedText(IHaveConfig config) { private IConfigData<String> appendedText(IHaveConfig config) {
return config.getData("appendedText", () -> "tableflip"); return config.getData("appendedText", "tableflip");
} }
@Override @Override
@ -67,7 +66,7 @@ public class AppendTextComponent extends Component<PluginMain> {
}); });
appendedText(conf).set("( ͡° ͜ʖ ͡°)"); appendedText(conf).set("( ͡° ͜ʖ ͡°)");
}); });
map.put("ww", conf -> { map.put("waitwhat", conf -> {
helpText(conf).set(new String[]{ helpText(conf).set(new String[]{
"Wait what", // "Wait what", //
"Wait what" // "Wait what" //
@ -101,7 +100,7 @@ public class AppendTextComponent extends Component<PluginMain> {
@Command2.Subcommand @Command2.Subcommand
public void def(Command2MCSender sender, @Command2.OptionalArg @Command2.TextArg String message) { public void def(Command2MCSender sender, @Command2.OptionalArg @Command2.TextArg String message) {
TBMCChatAPI.SendChatMessage(ChatMessage.builder(sender.getSender(), ChromaGamerBase.getFromSender(sender.getSender()), TBMCChatAPI.sendChatMessage(ChatMessage.builder(sender.getSender(),
(message == null ? "" : message + " ") + appendedText).fromCommand(true).permCheck(sender.getPermCheck()).build()); (message == null ? "" : message + " ") + appendedText).fromCommand(true).permCheck(sender.getPermCheck()).build());
} }

View file

@ -2,21 +2,24 @@ package buttondevteam.chat.components.chatonly;
import buttondevteam.chat.ChatPlayer; import buttondevteam.chat.ChatPlayer;
import buttondevteam.chat.PluginMain; import buttondevteam.chat.PluginMain;
import buttondevteam.chat.components.formatter.formatting.TellrawEvent;
import buttondevteam.chat.components.formatter.formatting.TellrawPart;
import buttondevteam.core.ComponentManager; import buttondevteam.core.ComponentManager;
import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.architecture.ComponentMetadata; import buttondevteam.lib.architecture.ComponentMetadata;
import buttondevteam.lib.player.TBMCPlayer; import buttondevteam.lib.player.TBMCPlayer;
import buttondevteam.lib.player.TBMCPlayerJoinEvent;
import lombok.val; import lombok.val;
import net.kyori.adventure.text.TextComponent;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent;
import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.event.HoverEvent.Action.SHOW_TEXT;
import static net.kyori.adventure.text.event.HoverEvent.hoverEvent;
/** /**
* Allows players to enter chat-only mode which puts them into spectator mode and disallows moving. * Allows players to enter chat-only mode which puts them into spectator mode and disallows moving.
*/ */
@ -34,21 +37,20 @@ public class ChatOnlyComponent extends Component<PluginMain> implements Listener
} }
@EventHandler @EventHandler
public void playerJoin(TBMCPlayerJoinEvent event) { public void playerJoin(PlayerJoinEvent event) {
val p = event.getPlayer(); val p = event.getPlayer();
val cp = event.GetPlayer().asPluginPlayer(ChatPlayer.class); val cp = TBMCPlayer.getPlayer(p.getUniqueId(), ChatPlayer.class);
if (cp.ChatOnly || p.getGameMode().equals(GameMode.SPECTATOR)) { if (cp.ChatOnly || p.getGameMode().equals(GameMode.SPECTATOR)) {
cp.ChatOnly = false; cp.ChatOnly = false;
p.setGameMode(GameMode.SURVIVAL); p.setGameMode(GameMode.SURVIVAL);
} }
} }
public static void tellrawCreate(ChatPlayer mp, TellrawPart json) { public static void tellrawCreate(ChatPlayer mp, TextComponent.Builder json) {
if(!ComponentManager.isEnabled(ChatOnlyComponent.class)) if (!ComponentManager.isEnabled(ChatOnlyComponent.class))
return; return;
if (mp != null && mp.ChatOnly) { if (mp != null && mp.ChatOnly) {
json.addExtra(new TellrawPart("[C]") json.append(text("[C]").hoverEvent(hoverEvent(SHOW_TEXT, text("Chat only"))));
.setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, "Chat only")));
} }
} }

View file

@ -24,21 +24,21 @@ public class AcceptCommand extends UCommandBase {
@Command2.Subcommand @Command2.Subcommand
public boolean def(Player player, @Command2.OptionalArg String username) { public boolean def(Player player, @Command2.OptionalArg String username) {
ChatPlayer p = TBMCPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class); ChatPlayer p = TBMCPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class);
if (username == null && p.UserNames().size() > 1) { if (username == null && p.UserNames.get().size() > 1) {
player.sendMessage("§9Multiple users commented your name. §bPlease pick one using /u accept <username>"); player.sendMessage("§9Multiple users commented your name. §bPlease pick one using /u accept <username>");
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("§6Usernames:"); sb.append("§6Usernames:");
for (String name : p.UserNames()) for (String name : p.UserNames.get())
sb.append(" ").append(name); sb.append(" ").append(name);
player.sendMessage(sb.toString()); player.sendMessage(sb.toString());
return true; return true;
} }
if (p.FlairState().get().equals(FlairStates.NoComment) || p.UserNames().size() == 0) { if (p.FlairState.get().equals(FlairStates.NoComment) || p.UserNames.get().size() == 0) {
player.sendMessage("§cError: You need to write your username to the reddit thread§r"); player.sendMessage("§cError: You need to write your username to the reddit thread§r");
player.sendMessage(component.flairThreadURL().get()); player.sendMessage(component.flairThreadURL.get());
return true; return true;
} }
if (username != null && !p.UserNames().contains(username)) { if (username != null && !p.UserNames.get().contains(username)) {
player.sendMessage("§cError: Unknown name: " + username + "§r"); player.sendMessage("§cError: Unknown name: " + username + "§r");
return true; return true;
} }
@ -47,14 +47,14 @@ public class AcceptCommand extends UCommandBase {
return true; return true;
} }
if ((username != null ? username : p.UserNames().get(0)).equals(p.UserName().get())) { if ((username != null ? username : p.UserNames.get().get(0)).equals(p.UserName.get())) {
player.sendMessage("§cYou already have this user's flair.§r"); player.sendMessage("§cYou already have this user's flair.§r");
return true; return true;
} }
if (username != null) if (username != null)
p.UserName().set(username); p.UserName.set(username);
else else
p.UserName().set(p.UserNames().get(0)); p.UserName.set(p.UserNames.get().get(0));
player.sendMessage("§bObtaining flair..."); player.sendMessage("§bObtaining flair...");
p.Working = true; p.Working = true;
@ -65,22 +65,19 @@ public class AcceptCommand extends UCommandBase {
try { try {
component.DownloadFlair(mp); component.DownloadFlair(mp);
} catch (Exception e) { } catch (Exception e) {
TBMCCoreAPI.SendException( TBMCCoreAPI.SendException("An error occured while downloading flair for " + player.getCustomName() + "!", e, component);
"An error occured while downloading flair for " + player.getCustomName() + "!", e); player.sendMessage("Sorry, but an error occured while trying to get your flair. Please contact a mod.");
player.sendMessage(
"Sorry, but an error occured while trying to get your flair. Please contact a mod.");
mp.Working = false; mp.Working = false;
return; return;
} }
if (mp.FlairState().get().equals(FlairStates.Commented)) { if (mp.FlairState.get().equals(FlairStates.Commented)) {
player.sendMessage( player.sendMessage("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.");
"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.");
mp.Working = false; mp.Working = false;
return; return;
} }
String flair = mp.GetFormattedFlair(); String flair = mp.GetFormattedFlair();
mp.FlairState().set(FlairStates.Accepted); mp.FlairState.set(FlairStates.Accepted);
FlairComponent.ConfirmUserMessage(mp); FlairComponent.ConfirmUserMessage(mp);
player.sendMessage("§bYour flair has been set:§r " + flair); player.sendMessage("§bYour flair has been set:§r " + flair);
mp.Working = false; mp.Working = false;

View file

@ -5,23 +5,18 @@ import buttondevteam.chat.PluginMain;
import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.architecture.ComponentMetadata; import buttondevteam.lib.architecture.ComponentMetadata;
import buttondevteam.lib.architecture.ConfigData; import buttondevteam.lib.architecture.config.IConfigData;
import buttondevteam.lib.player.TBMCPlayerBase; import buttondevteam.lib.player.TBMCPlayerBase;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.text.SimpleDateFormat; import java.util.HashSet;
import java.util.*; import java.util.Set;
/** /**
* This component checks a specific Reddit thread every 10 seconds for comments such as "IGN: NorbiPeti" to link Reddit accounts and to determine their /r/thebutton flair. * This component checks a specific Reddit thread every 10 seconds for comments such as "IGN: NorbiPeti" to link Reddit accounts and to determine their /r/thebutton flair.
@ -32,9 +27,7 @@ public class FlairComponent extends Component<PluginMain> {
/** /**
* The Reddit thread to check for account connections. Re-enable the component if this was empty. * The Reddit thread to check for account connections. Re-enable the component if this was empty.
*/ */
ConfigData<String> flairThreadURL() { IConfigData<String> flairThreadURL = getConfig().getData("flairThreadURL", "");
return getConfig().getData("flairThreadURL", "");
}
/** /**
* <p> * <p>
@ -44,7 +37,7 @@ public class FlairComponent extends Component<PluginMain> {
* It's used because normally it has to load all associated player files every time to read the flair state * It's used because normally it has to load all associated player files every time to read the flair state
* </p> * </p>
*/ */
private Set<String> PlayersWithFlairs = new HashSet<>(); private final Set<String> PlayersWithFlairs = new HashSet<>();
@Override @Override
protected void enable() { protected void enable() {
@ -61,9 +54,9 @@ public class FlairComponent extends Component<PluginMain> {
private void FlairGetterThreadMethod() { private void FlairGetterThreadMethod() {
int errorcount = 0; int errorcount = 0;
while (isEnabled() && flairThreadURL().get().length() > 0) { while (isEnabled() && flairThreadURL.get().length() > 0) {
try { try {
String body = TBMCCoreAPI.DownloadString(flairThreadURL().get() + ".json?limit=1000"); String body = TBMCCoreAPI.DownloadString(flairThreadURL.get() + ".json?limit=1000");
JsonArray json = new JsonParser().parse(body).getAsJsonArray().get(1).getAsJsonObject().get("data") JsonArray json = new JsonParser().parse(body).getAsJsonArray().get(1).getAsJsonObject().get("data")
.getAsJsonObject().get("children").getAsJsonArray(); .getAsJsonObject().get("children").getAsJsonArray();
for (Object obj : json) { for (Object obj : json) {
@ -83,20 +76,19 @@ public class FlairComponent extends Component<PluginMain> {
ign = ign.trim(); ign = ign.trim();
if (PlayersWithFlairs.contains(ign)) if (PlayersWithFlairs.contains(ign))
continue; continue;
try (ChatPlayer mp = TBMCPlayerBase.getFromName(ign, ChatPlayer.class)) { // Loads player file ChatPlayer mp = TBMCPlayerBase.getFromName(ign, ChatPlayer.class); // Loads player file
if (mp == null) if (mp == null)
continue; continue;
/* /*
* if (!JoinedBefore(mp, 2015, 6, 5)) continue; * if (!JoinedBefore(mp, 2015, 6, 5)) continue;
*/ */
if (!mp.UserNames().contains(author)) if (!mp.UserNames.get().contains(author))
mp.UserNames().add(author); mp.UserNames.get().add(author);
if (mp.FlairState().get().equals(FlairStates.NoComment)) { if (mp.FlairState.get().equals(FlairStates.NoComment)) {
mp.FlairState().set(FlairStates.Commented); mp.FlairState.set(FlairStates.Commented);
ConfirmUserMessage(mp); ConfirmUserMessage(mp);
}
PlayersWithFlairs.add(ign); // Don't redownload even if flair isn't accepted
} }
PlayersWithFlairs.add(ign); // Don't redownload even if flair isn't accepted
} }
} catch (Exception e) { } catch (Exception e) {
errorcount++; errorcount++;
@ -104,7 +96,7 @@ public class FlairComponent extends Component<PluginMain> {
errorcount = 0; errorcount = 0;
if (!e.getMessage().contains("Server returned HTTP response code") if (!e.getMessage().contains("Server returned HTTP response code")
&& !(e instanceof UnknownHostException)) && !(e instanceof UnknownHostException))
TBMCCoreAPI.SendException("Error while getting flairs from Reddit!", e); TBMCCoreAPI.SendException("Error while getting flairs from Reddit!", e, this);
} }
} }
try { try {
@ -113,11 +105,12 @@ public class FlairComponent extends Component<PluginMain> {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }
} }
} }
void DownloadFlair(ChatPlayer mp) throws IOException { void DownloadFlair(ChatPlayer mp) throws IOException {
String[] flairdata = TBMCCoreAPI String[] flairdata = TBMCCoreAPI
.DownloadString("http://karmadecay.com/thebutton-data.php?users=" + mp.UserName().get()) .DownloadString("http://karmadecay.com/thebutton-data.php?users=" + mp.UserName.get())
.replace("\"", "").split(":"); .replace("\"", "").split(":");
String flair; String flair;
if (flairdata.length > 1) if (flairdata.length > 1)
@ -129,12 +122,12 @@ public class FlairComponent extends Component<PluginMain> {
flairclass = flairdata[2]; flairclass = flairdata[2];
else else
flairclass = "unknown"; flairclass = "unknown";
SetFlair(mp, flair, flairclass, mp.UserName().get()); SetFlair(mp, flair, flairclass, mp.UserName.get());
} }
private static void SetFlair(ChatPlayer p, String text, String flairclass, String username) { private void SetFlair(ChatPlayer p, String text, String flairclass, String username) {
p.UserName().set(username); p.UserName.set(username);
p.FlairState().set(FlairStates.Recognised); p.FlairState.set(FlairStates.Recognised);
switch (flairclass) { switch (flairclass) {
case "cheater": case "cheater":
p.SetFlair(Short.parseShort(text), true); p.SetFlair(Short.parseShort(text), true);
@ -150,9 +143,9 @@ public class FlairComponent extends Component<PluginMain> {
p.SetFlair(ChatPlayer.FlairTimeCantPress); p.SetFlair(ChatPlayer.FlairTimeCantPress);
} }
} catch (Exception e) { } catch (Exception e) {
p.FlairState().set(FlairStates.Commented); // Flair unknown p.FlairState.set(FlairStates.Commented); // Flair unknown
p.SetFlair(ChatPlayer.FlairTimeNone); p.SetFlair(ChatPlayer.FlairTimeNone);
TBMCCoreAPI.SendException("Error while checking join date for player " + p.PlayerName() + "!", e); TBMCCoreAPI.SendException("Error while checking join date for player " + p.getPlayerName() + "!", e, this);
} }
return; return;
default: default:
@ -166,7 +159,7 @@ public class FlairComponent extends Component<PluginMain> {
} }
private static boolean JoinedBefore(ChatPlayer mp, int year, int month, int day) throws Exception { 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()); /*URL url = new URL("https://www.reddit.com/u/" + mp.UserName());
URLConnection con = url.openConnection(); URLConnection con = url.openConnection();
con.setRequestProperty("User-Agent", "TheButtonAutoFlair"); con.setRequestProperty("User-Agent", "TheButtonAutoFlair");
InputStream in = con.getInputStream(); InputStream in = con.getInputStream();
@ -180,13 +173,14 @@ public class FlairComponent extends Component<PluginMain> {
joindate = joindate.split("T")[0]; joindate = joindate.split("T")[0];
Date date = parserSDF.parse(joindate); Date date = parserSDF.parse(joindate);
return date.before(new Calendar.Builder().setTimeZone(TimeZone.getTimeZone("UTC")).setDate(year, month, day) return date.before(new Calendar.Builder().setTimeZone(TimeZone.getTimeZone("UTC")).setDate(year, month, day)
.build().getTime()); .build().getTime());*/
return true;
} }
public static void ConfirmUserMessage(ChatPlayer mp) { public static void ConfirmUserMessage(ChatPlayer mp) {
Player p = Bukkit.getPlayer(mp.getUUID()); Player p = Bukkit.getPlayer(mp.getUniqueId());
if (mp.FlairState().get().equals(FlairStates.Commented) && p != null) if (mp.FlairState.get().equals(FlairStates.Commented) && p != null)
if (mp.UserNames().size() > 1) if (mp.UserNames.get().size() > 1)
p.sendMessage( p.sendMessage(
"§9Multiple Reddit users commented your name. You can select with /u accept.§r §6Type /u accept or /u ignore§r"); "§9Multiple Reddit users commented your name. You can select with /u accept.§r §6Type /u accept or /u ignore§r");
else else

View file

@ -15,18 +15,18 @@ public final class IgnoreCommand extends UCommandBase {
@Command2.Subcommand @Command2.Subcommand
public boolean def(Player player) { public boolean def(Player player) {
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");

View file

@ -35,22 +35,21 @@ public class SetFlairCommand extends AdminCommandBase {
ft = Short.parseShort(flairtime); ft = Short.parseShort(flairtime);
} 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;
} }
} }
ChatPlayer mp = TBMCPlayerBase.getPlayer(p.getUniqueId(), ChatPlayer.class); ChatPlayer mp = TBMCPlayerBase.getPlayer(p.getUniqueId(), ChatPlayer.class);
mp.SetFlair(ft, cheater); mp.SetFlair(ft, cheater);
mp.FlairState().set(FlairStates.Accepted); mp.FlairState.set(FlairStates.Accepted);
if (username == null) if (username == null)
mp.UserName().set(""); mp.UserName.set("");
else { else {
mp.UserName().set(username); mp.UserName.set(username);
if (!mp.UserNames().contains(username)) if (!mp.UserNames.get().contains(username))
mp.UserNames().add(username); mp.UserNames.get().add(username);
} }
sender.sendMessage( sender.sendMessage("§bThe flair has been set. Player: " + mp.getPlayerName() + " Flair: " + mp.GetFormattedFlair() + "§r");
"§bThe flair has been set. Player: " + mp.PlayerName() + " Flair: " + mp.GetFormattedFlair() + "§r");
return true; return true;
} }

View file

@ -12,20 +12,22 @@ import buttondevteam.chat.components.towny.TownyComponent;
import buttondevteam.chat.listener.PlayerListener; import buttondevteam.chat.listener.PlayerListener;
import buttondevteam.core.ComponentManager; import buttondevteam.core.ComponentManager;
import buttondevteam.core.component.channel.Channel; import buttondevteam.core.component.channel.Channel;
import buttondevteam.lib.ChromaUtils;
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.Color;
import buttondevteam.lib.chat.TellrawSerializableEnum;
import buttondevteam.lib.player.ChromaGamerBase; import buttondevteam.lib.player.ChromaGamerBase;
import buttondevteam.lib.player.TBMCPlayer; import buttondevteam.lib.player.TBMCPlayer;
import buttondevteam.lib.player.TBMCPlayerBase; import buttondevteam.lib.player.TBMCPlayerBase;
import com.earth2me.essentials.User; import com.earth2me.essentials.User;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.val; import lombok.val;
import net.ess3.api.events.AfkStatusChangeEvent;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@ -38,16 +40,23 @@ import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.event.ClickEvent.suggestCommand;
import static net.kyori.adventure.text.event.HoverEvent.Action.SHOW_TEXT;
import static net.kyori.adventure.text.event.HoverEvent.hoverEvent;
import static net.kyori.adventure.text.format.NamedTextColor.*;
public class ChatProcessing { public class ChatProcessing {
private static final Pattern HASHTAG_PATTERN = Pattern.compile("#(\\w+)"); private static final Pattern HASHTAG_PATTERN = Pattern.compile("#(\\w+)");
private static final Pattern URL_PATTERN = Pattern.compile("(http[\\w:/?=$\\-_.+!*'(),&]+(?:#[\\w]+)?)"); private static final Pattern URL_PATTERN = Pattern.compile("(http[\\w:/?=$\\-_.+!*'(),&]+(?:#[\\w]+)?)");
private static final Pattern MASKED_LINK_PATTERN = Pattern.compile("\\[([^\\[\\]]+)]\\(([^()]+)\\)"); private static final Pattern MASKED_LINK_PATTERN = Pattern.compile("\\[([^\\[\\]]+)]\\(([^()]+)\\)");
private static final Color[] RainbowPresserColors = new Color[]{Color.Red, Color.Gold, Color.Yellow, Color.Green, private static final NamedTextColor[] RainbowPresserColors = new NamedTextColor[]{RED, GOLD, YELLOW, GREEN,
Color.Blue, Color.DarkPurple}; BLUE, DARK_PURPLE};
private static final Pattern WORD_PATTERN = Pattern.compile("\\S+"); private static final Pattern WORD_PATTERN = Pattern.compile("\\S+");
private static final Pattern GREENTEXT_PATTERN = Pattern.compile("^>(?:.|\\s)*");
private static boolean pingedconsole = false; private static boolean pingedconsole = false;
private static ArrayList<MatchProviderBase> commonFormatters = Lists.newArrayList( private static final ArrayList<MatchProviderBase> commonFormatters = Lists.newArrayList(
new RangeMatchProvider("bold", "**", FormatSettings.builder().bold(true).build()), new RangeMatchProvider("bold", "**", FormatSettings.builder().bold(true).build()),
new RangeMatchProvider("italic", "*", FormatSettings.builder().italic(true).build()), new RangeMatchProvider("italic", "*", FormatSettings.builder().italic(true).build()),
new RangeMatchProvider("underlined", "__", FormatSettings.builder().underlined(true).build()), new RangeMatchProvider("underlined", "__", FormatSettings.builder().underlined(true).build()),
@ -58,8 +67,8 @@ public class ChatProcessing {
cf.setHoverText(match); cf.setHoverText(match);
return match; return match;
}).build()), }).build()),
new StringMatchProvider("nullMention", FormatSettings.builder().color(Color.DarkRed).build(), true, "null"), // Properly added a bug as a feature new StringMatchProvider("nullMention", FormatSettings.builder().color(DARK_RED).build(), true, "null"), // Properly added a bug as a feature
new StringMatchProvider("consolePing", FormatSettings.builder().color(Color.Aqua) new StringMatchProvider("consolePing", FormatSettings.builder().color(AQUA)
.onmatch((match, builder, section) -> { .onmatch((match, builder, section) -> {
if (!pingedconsole) { if (!pingedconsole) {
System.out.print("\007"); System.out.print("\007");
@ -68,19 +77,19 @@ public class ChatProcessing {
return "@console"; return "@console";
}).build(), true, "@console"), }).build(), true, "@console"),
new StringMatchProvider("cyan", FormatSettings.builder().color(Color.Aqua).build(), true, "cyan"), // #55 new StringMatchProvider("cyan", FormatSettings.builder().color(AQUA).build(), true, "cyan"), // #55
new RangeMatchProvider("code", "`", FormatSettings.builder().color(Color.DarkGray).build()), new RangeMatchProvider("code", "`", FormatSettings.builder().color(DARK_GRAY).build()),
new RegexMatchProvider("maskedLink", MASKED_LINK_PATTERN, FormatSettings.builder().underlined(true) new RegexMatchProvider("maskedLink", MASKED_LINK_PATTERN, FormatSettings.builder().underlined(true)
.onmatch((match, builder, section) -> { .onmatch((match, builder, section) -> {
String text, link; String text, link;
if (section.Matches.size() < 2 || (text = section.Matches.get(0)).length() == 0 || (link = section.Matches.get(1)).length() == 0) if (section.Matches.size() < 2 || (text = section.Matches.get(0)).length() == 0 || (link = section.Matches.get(1)).length() == 0)
return ""; return "[MISSING LINK]"; //Doesn't actually happen, because of the regex
builder.setOpenlink(link); builder.setOpenlink(link);
return text; return text;
}).build()), }).build()),
new RegexMatchProvider("url", URL_PATTERN, FormatSettings.builder().underlined(true).openlink("$1").build()), new RegexMatchProvider("url", URL_PATTERN, FormatSettings.builder().underlined(true).openlink("$1").build()),
new RegexMatchProvider("hashtag", HASHTAG_PATTERN, FormatSettings.builder().color(Color.Blue).openlink("https://twitter.com/hashtag/$1").build()), new RegexMatchProvider("hashtag", HASHTAG_PATTERN, FormatSettings.builder().color(BLUE).openlink("https://twitter.com/hashtag/$1").build()),
new StringMatchProvider("someone", FormatSettings.builder().color(Color.Aqua) new StringMatchProvider("someone", FormatSettings.builder().color(AQUA)
.onmatch((match, builder, section) -> { .onmatch((match, builder, section) -> {
if (Bukkit.getOnlinePlayers().size() == 0) return match; if (Bukkit.getOnlinePlayers().size() == 0) return match;
var players = ImmutableList.copyOf(Bukkit.getOnlinePlayers()); var players = ImmutableList.copyOf(Bukkit.getOnlinePlayers());
@ -88,12 +97,8 @@ public class ChatProcessing {
var player = players.get(playerC); var player = players.get(playerC);
playPingSound(player, ComponentManager.getIfEnabled(FormatterComponent.class)); playPingSound(player, ComponentManager.getIfEnabled(FormatterComponent.class));
return "@someone (" + player.getDisplayName() + "§r)"; return "@someone (" + player.getDisplayName() + "§r)";
}).build(), true, "@someone")); }).build(), true, "@someone"),
private static Gson gson = new GsonBuilder() new RegexMatchProvider("greentext", GREENTEXT_PATTERN, FormatSettings.builder().color(GREEN).build()));
.registerTypeHierarchyAdapter(TellrawSerializableEnum.class, new TellrawSerializer.TwEnum())
.registerTypeHierarchyAdapter(Collection.class, new TellrawSerializer.TwCollection())
.registerTypeAdapter(Boolean.class, new TellrawSerializer.TwBool())
.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"};
private ChatProcessing() { private ChatProcessing() {
@ -101,14 +106,14 @@ public class ChatProcessing {
public static boolean ProcessChat(TBMCChatEvent e, FormatterComponent component) { public static boolean ProcessChat(TBMCChatEvent e, FormatterComponent component) {
Channel channel = e.getChannel(); Channel channel = e.getChannel();
CommandSender sender = e.getSender(); ChromaGamerBase cuser = e.getUser();
String message = e.getMessage(); String message = e.getMessage();
long processstart = System.nanoTime(); long processstart = System.nanoTime();
Player player = (sender instanceof Player ? (Player) sender : null); Player player = (cuser instanceof TBMCPlayerBase ? ((TBMCPlayerBase) cuser).getPlayer() : null);
User user = PluginMain.essentials.getUser(player); User user = PluginMain.essentials.getUser(player);
if (player != null && PluginMain.essentials.getSettings().cancelAfkOnInteract()) { if (player != null && PluginMain.essentials.getSettings().cancelAfkOnInteract()) {
user.updateActivity(true); //Could talk in a private channel, so broadcast user.updateActivity(true, AfkStatusChangeEvent.Cause.CHAT); //Could talk in a private channel, so broadcast
if (user.isMuted()) if (user.isMuted())
return true; return true;
} }
@ -120,60 +125,61 @@ public class ChatProcessing {
mp = e.getUser().getAs(ChatPlayer.class); //May be null mp = e.getUser().getAs(ChatPlayer.class); //May be null
if (mp != null) { if (mp != null) {
if (System.nanoTime() - mp.LastMessageTime < 1000 * component.minTimeBetweenMessages().get()) { //0.1s by default if (System.nanoTime() - mp.LastMessageTime < 1000L * 1000L * component.minTimeBetweenMessages.get()) { //0.1s by default
sender.sendMessage("§cYou are sending messages too fast!"); cuser.sendMessage("§cYou are sending messages too quickly!");
return true; return true;
} }
mp.LastMessageTime = System.nanoTime(); mp.LastMessageTime = System.nanoTime();
} }
//DimensionManager.a()
//IRegistry.ae
//Bukkit.createWorld()
//MinecraftServer.reload()
//IRegistry
//CraftServer
doFunStuff(sender, e, message); doFunStuff(cuser, e, message);
final String channelidentifier = getChannelID(channel, e.getOrigin()); final String channelidentifier = getChannelID(channel, e.getOrigin());
PluginMain.Instance.getServer().getConsoleSender() PluginMain.Instance.getServer().getConsoleSender()
.sendMessage(String.format("%s <%s§r> %s", channelidentifier, getSenderName(sender, player), message)); .sendMessage(String.format("%s <%s§r> %s", channelidentifier, cuser.getName(), message));
if (Bukkit.getOnlinePlayers().size() == 0) return false; //Don't try to send to nobody (errors on 1.14) if (Bukkit.getOnlinePlayers().size() == 0) return false; //Don't try to send to nobody (errors on 1.14)
Color colormode = channel.Color().get(); TextColor colormode = NAMES.value(channel.color.get().getName());
if (mp != null && mp.OtherColorMode != null) boolean colorModeChanged = false;
colormode = mp.OtherColorMode; if (mp != null && mp.OtherColorMode != null) {
if (message.startsWith(">")) colormode = NAMES.value(mp.OtherColorMode.getName());
colormode = Color.Green; colorModeChanged = true;
// If greentext, ignore channel or player colors }
ArrayList<MatchProviderBase> formatters; ArrayList<MatchProviderBase> formatters;
if (component.allowFormatting().get()) { if (component.allowFormatting.get()) {
formatters = addFormatters(e::shouldSendTo, component); formatters = addFormatters(sender -> e.shouldSendTo(ChromaGamerBase.getFromSender(sender)), component);
if (colormode == channel.Color().get() && mp != null && mp.RainbowPresserColorMode) { // Only overwrite channel color if (colorModeChanged && mp.RainbowPresserColorMode) { // Only overwrite channel color
createRPC(colormode, formatters); createRPC(colormode, formatters);
} }
pingedconsole = false; // Will set it to true onmatch (static constructor) pingedconsole = false; // Will set it to true onmatch (static constructor)
} else } else
formatters = Lists.newArrayList(); formatters = Lists.newArrayList();
TellrawPart json = createTellraw(sender, message, player, mp, e.getUser(), channelidentifier, e.getOrigin()); TextComponent.Builder builder = createEmptyMessageLine(cuser, message, player, channelidentifier, e.getOrigin());
long combinetime = System.nanoTime(); long combinetime = System.nanoTime();
ChatFormatter.Combine(formatters, message, json, component.getConfig(), FormatSettings.builder().color(colormode).build()); ChatFormatter.Combine(formatters, message, builder, component.getConfig(), FormatSettings.builder().color(colormode).build());
combinetime = System.nanoTime() - combinetime; combinetime = System.nanoTime() - combinetime;
String jsonstr = toJson(json);
if (jsonstr.length() >= 32767) {
sender.sendMessage(
"§cError: Message too long. Try shortening it, or remove hashtags and other formatting.");
return true;
}
DebugCommand.SendDebugMessage(jsonstr);
try { try {
if (!channel.isGlobal()) { if (!channel.isGlobal()) {
String senderGroup = e.getGroupID(sender); String senderGroup = e.getGroupID(cuser);
if (senderGroup == null) { // Never send messages if the group is null if (senderGroup == null) { // Never send messages if the group is null
sender.sendMessage("§cYou don't have permission to send this message or something went wrong"); cuser.sendMessage("§cYou don't have permission to send this message or something went wrong");
return true; return true;
} }
val tc = ComponentManager.getIfEnabled(TownyComponent.class); val tc = ComponentManager.getIfEnabled(TownyComponent.class);
if (tc != null) tc.handleSpiesInit(channel, json, ChatProcessing::toJson); Consumer<Player> spyConsumer = null;
if (tc != null)
spyConsumer = tc.handleSpiesInit(channel, builder);
for (Player p : Bukkit.getOnlinePlayers()) { for (Player p : Bukkit.getOnlinePlayers()) {
final String group; final String group;
if (player != null if (player != null
@ -181,17 +187,18 @@ public class ChatProcessing {
group = null; // Don't send the message to them group = null; // Don't send the message to them
else else
group = VanillaUtils.getGroupIfChatOn(p, e); group = VanillaUtils.getGroupIfChatOn(p, e);
if (senderGroup.equals(group)) if (senderGroup.equals(group)) {
VanillaUtils.tellRaw(p, jsonstr); p.sendMessage(builder.build());
else if (tc != null) tc.handleSpies(channel, p); if (tc != null) spyConsumer.accept(p);
}
//Only sends if didn't send normally //Only sends if didn't send normally
} }
} else } else
for (Player p : Bukkit.getOnlinePlayers()) for (Player p : Bukkit.getOnlinePlayers())
VanillaUtils.tellRaw(p, jsonstr); p.sendMessage(builder.build());
} catch (Exception ex) { } catch (Exception ex) {
TBMCCoreAPI.SendException("An error occured while sending a chat message!", ex); TBMCCoreAPI.SendException("An error occured while sending a chat message!", ex, PluginMain.Instance);
sender.sendMessage("§cAn error occured while sending the message."); cuser.sendMessage("§cAn error occured while sending the message.");
return true; return true;
} }
DebugCommand.SendDebugMessage( DebugCommand.SendDebugMessage(
@ -200,7 +207,7 @@ public class ChatProcessing {
return false; return false;
} }
static void createRPC(Color colormode, ArrayList<MatchProviderBase> formatters) { static void createRPC(TextColor colormode, ArrayList<MatchProviderBase> formatters) {
final AtomicInteger rpc = new AtomicInteger(0); final AtomicInteger rpc = new AtomicInteger(0);
formatters.add(new RegexMatchProvider("rpc", WORD_PATTERN, FormatSettings.builder().color(colormode).onmatch((match, cf, s) -> { formatters.add(new RegexMatchProvider("rpc", WORD_PATTERN, FormatSettings.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)]);
@ -208,46 +215,29 @@ public class ChatProcessing {
}).build())); }).build()));
} }
public static String toJson(TellrawPart json) { static TextComponent.Builder createEmptyMessageLine(ChromaGamerBase user, String message, @Nullable Player player,
return gson.toJson(json); final String channelidentifier, String origin) {
} val json = text();
ChatOnlyComponent.tellrawCreate(user.getAs(ChatPlayer.class), json);
static TellrawPart createTellraw(CommandSender sender, String message, @Nullable Player player, val channelHover = (ChatUtils.MCORIGIN.equals(origin) ? "" : "From " + origin + "\n") + "Copy message";
@Nullable ChatPlayer mp, @Nullable ChromaGamerBase cg, final String channelidentifier, json.append(text(channelidentifier)
String origin) { .hoverEvent(hoverEvent(SHOW_TEXT, text(channelHover).color(BLUE))).clickEvent(suggestCommand(message)));
TellrawPart json = new TellrawPart(""); if (player != null) {
ChatOnlyComponent.tellrawCreate(mp, json); //TODO: Make nice API if (PluginMain.permission.has(player, "tbmc.badge.diamond")) // TODO: Cross-platform permissions
json.addExtra( json.append(text("[P]").color(AQUA).decorate(TextDecoration.BOLD)
new TellrawPart(channelidentifier) .hoverEvent(hoverEvent(SHOW_TEXT, text("Diamond Patreon supporter"))));
.setHoverEvent( else if (PluginMain.permission.has(player, "tbmc.badge.gold"))
TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, json.append(text("[P]").color(GOLD).decorate(TextDecoration.BOLD)
new TellrawPart((ChatUtils.MCORIGIN.equals(origin) ? "" : "From " + origin + "\n") .hoverEvent(hoverEvent(SHOW_TEXT, text("Gold Patreon supporter"))));
+ "Copy message").setColor(Color.Blue))) }
.setClickEvent(TellrawEvent.create(TellrawEvent.ClickAction.SUGGEST_COMMAND, message))); json.append(text(" <"));
if (PluginMain.permission.has(sender, "tbmc.badge.diamond")) json.append(text(user.getName()).hoverEvent(hoverEvent(SHOW_TEXT, text(user.getInfo(ChromaGamerBase.InfoTarget.MCHover)))));
json.addExtra(new TellrawPart("[P]").setColor(Color.Aqua).setBold(true) json.append(text("> "));
.setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, "Diamond Patreon supporter")));
else if (PluginMain.permission.has(sender, "tbmc.badge.gold"))
json.addExtra(new TellrawPart("[P]").setColor(Color.Gold).setBold(true)
.setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, "Gold Patreon supporter")));
json.addExtra(new TellrawPart(" <"));
TellrawPart hovertp = new TellrawPart("");
if (cg != null)
hovertp.addExtra(new TellrawPart(cg.getInfo(ChromaGamerBase.InfoTarget.MCHover)));
json.addExtra(new TellrawPart(getSenderName(sender, player))
.setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, hovertp)));
json.addExtra(new TellrawPart("> "));
return json; return json;
} }
private static String getSenderName(CommandSender sender, Player player) {
if (player == null)
return sender.getName();
return player.getDisplayName();
}
static String getChannelID(Channel channel, String origin) { static String getChannelID(Channel channel, String origin) {
return ("[" + (ChatUtils.MCORIGIN.equals(origin) ? "" : "§8" + origin.substring(0, 1) + "§r|") + channel.DisplayName().get()) return ("[" + (ChatUtils.MCORIGIN.equals(origin) ? "" : "§8" + origin.charAt(0) + "§r|") + channel.displayName.get())
+ "]"; + "]";
} }
@ -256,7 +246,7 @@ public class ChatProcessing {
ArrayList<MatchProviderBase> formatters = (ArrayList<MatchProviderBase>) commonFormatters.clone(); ArrayList<MatchProviderBase> formatters = (ArrayList<MatchProviderBase>) commonFormatters.clone();
boolean nottest; //Not assigning a default value, so that it can only be used in the if boolean nottest; //Not assigning a default value, so that it can only be used in the if
if ((nottest = Bukkit.getOnlinePlayers().size() > 0) || Bukkit.getVersion().equals("test")) { if ((nottest = Bukkit.getOnlinePlayers().size() > 0) || ChromaUtils.isTest()) {
String[] names; String[] names;
if (nottest) if (nottest)
names = Bukkit.getOnlinePlayers().stream().filter(canSee).map(CommandSender::getName).toArray(String[]::new); names = Bukkit.getOnlinePlayers().stream().filter(canSee).map(CommandSender::getName).toArray(String[]::new);
@ -275,12 +265,12 @@ public class ChatProcessing {
}; };
if (names.length > 0) //Add as first so it handles special characters (_) - though the order of the different types are defined if (names.length > 0) //Add as first so it handles special characters (_) - though the order of the different types are defined
formatters.add(0, new StringMatchProvider("name", FormatSettings.builder().color(Color.Aqua) formatters.add(0, new StringMatchProvider("name", FormatSettings.builder().color(AQUA)
.onmatch((match, builder, section) -> { .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();
if (nottest ? p == null : !pn.isPresent()) { if (nottest ? p == null : pn.isEmpty()) {
error.accept("Error: Can't find player " + match + " but was reported as online."); error.accept("Error: Can't find player " + match + " but was reported as online.");
return "§c" + match + "§r"; return "§c" + match + "§r";
} }
@ -293,7 +283,7 @@ public class ChatProcessing {
}).build(), true, names)); }).build(), true, names));
if (nicknames.length > 0) //Add as first so it handles special characters if (nicknames.length > 0) //Add as first so it handles special characters
formatters.add(0, new StringMatchProvider("nickname", FormatSettings.builder().color(Color.Aqua) formatters.add(0, new StringMatchProvider("nickname", FormatSettings.builder().color(AQUA)
.onmatch((match, builder, section) -> { .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()));
@ -314,15 +304,15 @@ public class ChatProcessing {
} }
private static void playPingSound(Player p, @Nullable FormatterComponent component) { private static void playPingSound(Player p, @Nullable FormatterComponent component) {
if (component == null || component.notificationSound().get().length() == 0) if (component == null || component.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(), component.notificationSound().get(), 1.0f, p.playSound(p.getLocation(), component.notificationSound.get(), 1.0f,
component.notificationPitch().get()); component.notificationPitch.get());
} }
static void doFunStuff(CommandSender sender, TBMCChatEventBase event, String message) { static void doFunStuff(ChromaGamerBase user, TBMCChatEventBase event, String message) {
val fc = ComponentManager.getIfEnabled(FunComponent.class); val fc = ComponentManager.getIfEnabled(FunComponent.class);
if (fc != null) fc.onChat(sender, event, message); if (fc != null) fc.onChat(user, event, message);
} }
} }

View file

@ -5,51 +5,42 @@ import buttondevteam.core.ComponentManager;
import buttondevteam.core.MainPlugin; import buttondevteam.core.MainPlugin;
import buttondevteam.lib.TBMCChatEvent; import buttondevteam.lib.TBMCChatEvent;
import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.architecture.ConfigData; import buttondevteam.lib.architecture.config.IConfigData;
/** /**
* This component handles the custom processing of chat messages. If this component is disabled channels won't be supported in Minecraft. * This component handles the custom processing of chat messages. If this component is disabled channels won't be supported in Minecraft.
* If you only want to disable the formatting features, set allowFormatting to false. * If you only want to disable the formatting features, set allowFormatting to false.
* If you're using another chat plugin, you should disable the whole component. * If you're using another chat plugin, you should disable the whole component but that will make it impossible to use channels.
*/ */
public class FormatterComponent extends Component<PluginMain> { public class FormatterComponent extends Component<PluginMain> {
/** /**
* Determines whether Markdown formatting, name mentioning and similar features are enabled. * Determines whether Markdown formatting, name mentioning and similar features are enabled.
*/ */
ConfigData<Boolean> allowFormatting() { IConfigData<Boolean> allowFormatting = getConfig().getData("allowFormatting", true);
return getConfig().getData("allowFormatting", true);
}
/** /**
* The sound to play when a player is mentioned. Leave empty to use default. * The sound to play when a player is mentioned. Leave empty to use default.
*/ */
public ConfigData<String> notificationSound() { public IConfigData<String> notificationSound = getConfig().getData("notificationSound", "");
return getConfig().getData("notificationSound", "");
}
/** /**
* The pitch of the notification sound. * The pitch of the notification sound.
*/ */
public ConfigData<Float> notificationPitch() { public IConfigData<Float> notificationPitch = getConfig().getData("notificationPitch", 1.0f);
return getConfig().getData("notificationPitch", 1.0f);
}
/** /**
* The minimum time between messages in milliseconds. * The minimum time between messages in milliseconds.
*/ */
public ConfigData<Integer> minTimeBetweenMessages() { public IConfigData<Integer> minTimeBetweenMessages = getConfig().getData("minTimeBetweenMessages", 100);
return getConfig().getData("minTimeBetweenMessages", 100);
}
@Override @Override
protected void enable() { protected void enable() {
MainPlugin.Instance.setChatHandlerEnabled(false); //Disable Core chat handler - if this component is disabled then let it do it's job MainPlugin.getInstance().setChatHandlerEnabled(false); //Disable Core chat handler - if this component is disabled then let it do its job
} }
@Override @Override
protected void disable() { protected void disable() {
MainPlugin.Instance.setChatHandlerEnabled(true); MainPlugin.getInstance().setChatHandlerEnabled(true);
} }
/** /**

View file

@ -2,15 +2,24 @@ package buttondevteam.chat.components.formatter.formatting;
import buttondevteam.chat.commands.ucmds.admin.DebugCommand; import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
import buttondevteam.lib.architecture.IHaveConfig; import buttondevteam.lib.architecture.IHaveConfig;
import buttondevteam.lib.chat.Color;
import lombok.val; import lombok.val;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.jetbrains.annotations.NotNull;
import java.util.*; import java.util.*;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.event.ClickEvent.Action.OPEN_URL;
import static net.kyori.adventure.text.event.ClickEvent.clickEvent;
import static net.kyori.adventure.text.event.HoverEvent.Action.SHOW_TEXT;
import static net.kyori.adventure.text.event.HoverEvent.hoverEvent;
/** /**
* A {@link MatchProvider} finds where the given {@link FormatSettings} need to be applied. {@link ChatFormatter#Combine(List, String, TellrawPart, IHaveConfig, FormatSettings)}} is used to turn it into a {@link TellrawPart}, combining * A {@link MatchProvider} finds where the given {@link FormatSettings} need to be applied. {@link ChatFormatter#Combine(List, String, TextComponent.Builder, IHaveConfig, FormatSettings)}} 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.
* *
@ -26,7 +35,7 @@ public final class ChatFormatter {
} }
//synchronized: Some of the formatters are reused, see createSections(...) //synchronized: Some of the formatters are reused, see createSections(...)
public static synchronized void Combine(List<MatchProviderBase> formatters, String str, TellrawPart tp, IHaveConfig config, FormatSettings defaults) { public static synchronized void Combine(List<MatchProviderBase> formatters, String str, TextComponent.Builder tp, IHaveConfig config, FormatSettings defaults) {
/* /*
* A global formatter is no longer needed * A global formatter is no longer needed
*/ */
@ -120,22 +129,25 @@ public final class ChatFormatter {
sortSections(sections); sortSections(sections);
continue; continue;
} else if (firstSection.End >= lastSection.Start && firstSection.Start <= lastSection.End) { } else if (firstSection.End >= lastSection.Start && firstSection.Start <= lastSection.End) {
int firstSectEnd = firstSection.End; int middleStart = lastSection.Start;
firstSection.End = lastSection.Start - 1; // |----|-- |------|
int lastSectEnd = lastSection.End; // --|----| -|----|-
FormattedSection section = new FormattedSection(firstSection.Settings, lastSection.Start, lastSectEnd, int middleEnd = Math.min(lastSection.End, firstSection.End);
int lastSectEnd = Math.max(lastSection.End, firstSection.End);
FormattedSection section = new FormattedSection(firstSection.Settings, middleStart, middleEnd,
firstSection.Matches); firstSection.Matches);
section.Settings.copyFrom(lastSection.Settings); section.Settings.copyFrom(lastSection.Settings);
section.Matches.addAll(lastSection.Matches); section.Matches.addAll(lastSection.Matches);
sections.add(i, section); sections.add(i, section);
if (firstSectEnd > lastSection.End) { //Copy first section info to last as the lastSection initially cuts the firstSection in half if (firstSection.End > lastSection.End) { //Copy first section info to last as the lastSection initially cuts the firstSection in half
lastSection.Settings = FormatSettings.builder().build(); lastSection.Settings = FormatSettings.builder().build();
lastSection.Settings.copyFrom(firstSection.Settings); lastSection.Settings.copyFrom(firstSection.Settings);
} }
lastSection.Start = lastSectEnd + 1; firstSection.End = middleStart - 1;
lastSection.End = firstSectEnd; lastSection.Start = middleEnd + 1;
lastSection.End = lastSectEnd;
Predicate<FormattedSection> removeIfNeeded = s -> { Predicate<FormattedSection> removeIfNeeded = s -> {
if (s.Start < 0 || s.End < 0 || s.Start > s.End) { if (s.Start < 0 || s.End < 0 || s.Start > s.End) {
@ -149,11 +161,11 @@ public final class ChatFormatter {
DebugCommand.SendDebugMessage("To sections"); DebugCommand.SendDebugMessage("To sections");
if (!removeIfNeeded.test(firstSection)) { if (!removeIfNeeded.test(firstSection)) {
DebugCommand.SendDebugMessage(" 1:" + firstSection + ""); DebugCommand.SendDebugMessage(" 1:" + firstSection);
ChatFormatUtils.sendMessageWithPointer(str, firstSection.Start, firstSection.End); ChatFormatUtils.sendMessageWithPointer(str, firstSection.Start, firstSection.End);
} }
if (!removeIfNeeded.test(section)) { if (!removeIfNeeded.test(section)) {
DebugCommand.SendDebugMessage(" 2:" + section + ""); DebugCommand.SendDebugMessage(" 2:" + section);
ChatFormatUtils.sendMessageWithPointer(str, section.Start, section.End); ChatFormatUtils.sendMessageWithPointer(str, section.Start, section.End);
} }
if (!removeIfNeeded.test(lastSection)) { if (!removeIfNeeded.test(lastSection)) {
@ -163,21 +175,11 @@ public final class ChatFormatter {
i = 0; i = 0;
} }
sortSections(sections); sortSections(sections);
if (i == 0) continue;
for (int j = i - 1; j <= i + 1; j++) {
if (j < sections.size() && sections.get(j).End < sections.get(j).Start) {
DebugCommand.SendDebugMessage("Removing section: " + sections.get(j));
ChatFormatUtils.sendMessageWithPointer(str, sections.get(j).Start, sections.get(j).End);
sections.remove(j);
j--;
i = 0;
}
}
} }
} }
private static void applySections(String str, TellrawPart tp, ArrayList<FormattedSection> sections, ArrayList<int[]> remchars) { private static void applySections(String str, TextComponent.Builder tp, ArrayList<FormattedSection> sections, ArrayList<int[]> remchars) {
TellrawPart lasttp = null; TextComponent lasttp = null;
String lastlink = null; String lastlink = null;
for (FormattedSection section : sections) { for (FormattedSection section : sections) {
DebugCommand.SendDebugMessage("Applying section: " + section); DebugCommand.SendDebugMessage("Applying section: " + section);
@ -185,21 +187,9 @@ public final class ChatFormatter {
int start = section.Start, end = section.End; int start = section.Start, end = section.End;
DebugCommand.SendDebugMessage("Start: " + start + " - End: " + end); DebugCommand.SendDebugMessage("Start: " + start + " - End: " + end);
ChatFormatUtils.sendMessageWithPointer(str, start, end); ChatFormatUtils.sendMessageWithPointer(str, start, end);
/*DebugCommand.SendDebugMessage("RCS: "+remchars.stream().filter(rc -> rc[0] <= start && start <= rc[1]).count());
DebugCommand.SendDebugMessage("RCE: "+remchars.stream().filter(rc -> rc[0] <= end && end <= rc[1]).count());
DebugCommand.SendDebugMessage("RCI: "+remchars.stream().filter(rc -> start < rc[0] || rc[1] < end).count());*/
val rci = remchars.stream().filter(rc -> (rc[0] <= start && rc[1] >= start) val rci = remchars.stream().filter(rc -> (rc[0] <= start && rc[1] >= start)
|| (rc[0] >= start && rc[1] <= end) || (rc[0] >= start && rc[1] <= end)
|| (rc[0] <= end && rc[1] >= end)).sorted(Comparator.comparingInt(rc -> rc[0] * 10000 + rc[1])).toArray(int[][]::new); || (rc[0] <= end && rc[1] >= end)).sorted(Comparator.comparingInt(rc -> rc[0] * 10000 + rc[1])).toArray(int[][]::new);
/*if (rcs.isPresent())
s = rcs.get()[1] + 1;
if (rce.isPresent())
e = rce.get()[0] - 1;
DebugCommand.SendDebugMessage("After RC - Start: " + s + " - End: " + e);
if (e - s < 0) { //e-s==0 means the end char is the same as start char, so one char message
DebugCommand.SendDebugMessage("Skipping section because of remchars (length would be " + (e - s + 1) + ")");
continue;
}*/
DebugCommand.SendDebugMessage("Applying RC: " + Arrays.stream(rci).map(Arrays::toString).collect(Collectors.joining(", ", "[", "]"))); DebugCommand.SendDebugMessage("Applying RC: " + Arrays.stream(rci).map(Arrays::toString).collect(Collectors.joining(", ", "[", "]")));
originaltext = str.substring(start, end + 1); originaltext = str.substring(start, end + 1);
val sb = new StringBuilder(originaltext); val sb = new StringBuilder(originaltext);
@ -212,50 +202,53 @@ public final class ChatFormatter {
} }
DebugCommand.SendDebugMessage("Section text: " + originaltext); DebugCommand.SendDebugMessage("Section text: " + originaltext);
String openlink = null; String openlink = null;
//section.Formatters.sort(Comparator.comparing(cf2 -> cf2.priority.GetValue())); //Apply the highest last, to overwrite previous ones
TellrawPart newtp = new TellrawPart("");
var settings = section.Settings; var settings = section.Settings;
DebugCommand.SendDebugMessage("Applying settings: " + settings); DebugCommand.SendDebugMessage("Applying settings: " + settings);
if (lasttp != null && hasSameDecorations(lasttp, settings) && Objects.equals(lastlink, settings.openlink)
&& settings.onmatch == null) { // The onmatch function can change the settings
DebugCommand.SendDebugMessage("This part has the same properties as the previous one, combining.");
lasttp = lasttp.content(lasttp.content() + originaltext);
continue; //Combine parts with the same properties
}
TextComponent.@NotNull Builder newtp = text();
if (settings.onmatch != null) if (settings.onmatch != null)
originaltext = settings.onmatch.apply(originaltext, settings, section); originaltext = settings.onmatch.apply(originaltext, settings, section);
if (settings.color != null) if (settings.color != null)
newtp.setColor(settings.color); newtp.color(settings.color);
if (settings.bold) if (settings.bold)
newtp.setBold(true); newtp.decorate(TextDecoration.BOLD);
if (settings.italic) if (settings.italic)
newtp.setItalic(true); newtp.decorate(TextDecoration.ITALIC);
if (settings.underlined) if (settings.underlined)
newtp.setUnderlined(true); newtp.decorate(TextDecoration.UNDERLINED);
if (settings.strikethrough) if (settings.strikethrough)
newtp.setStrikethrough(true); newtp.decorate(TextDecoration.STRIKETHROUGH);
if (settings.obfuscated) if (settings.obfuscated)
newtp.setObfuscated(true); newtp.decorate(TextDecoration.OBFUSCATED);
if (settings.openlink != null) if (settings.openlink != null)
openlink = settings.openlink; openlink = settings.openlink;
if (settings.hoverText != null) if (settings.hoverText != null)
newtp.setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, settings.hoverText)); newtp.hoverEvent(hoverEvent(SHOW_TEXT, text(settings.hoverText)));
if (lasttp != null && newtp.getColor() == lasttp.getColor() if (lasttp != null) tp.append(lasttp);
&& newtp.isBold() == lasttp.isBold()
&& newtp.isItalic() == lasttp.isItalic()
&& newtp.isUnderlined() == lasttp.isUnderlined()
&& newtp.isStrikethrough() == lasttp.isStrikethrough()
&& newtp.isObfuscated() == lasttp.isObfuscated()
&& Objects.equals(openlink, lastlink)) {
DebugCommand.SendDebugMessage("This part has the same properties as the previous one, combining.");
lasttp.setText(lasttp.getText() + originaltext);
continue; //Combine parts with the same properties
}
lastlink = openlink; lastlink = openlink;
newtp.setText(originaltext); newtp.content(originaltext);
if (openlink != null && openlink.length() > 0) { if (openlink != null && openlink.length() > 0) {
newtp.setClickEvent(TellrawEvent.create(TellrawEvent.ClickAction.OPEN_URL, if (section.Matches.size() > 0)
(section.Matches.size() > 0 ? openlink.replace("$1", section.Matches.get(0)) : openlink))) openlink = openlink.replace("$1", section.Matches.get(0));
.setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, newtp.clickEvent(clickEvent(OPEN_URL, openlink)).hoverEvent(hoverEvent(SHOW_TEXT, text("Click to open").color(NamedTextColor.BLUE)));
new TellrawPart("Click to open").setColor(Color.Blue)));
} }
tp.addExtra(newtp); lasttp = newtp.build();
lasttp = newtp;
} }
if (lasttp != null) tp.append(lasttp);
}
private static boolean hasSameDecorations(TextComponent c1, FormatSettings settings) {
return Objects.equals(c1.color(), settings.color)
&& c1.hasDecoration(TextDecoration.BOLD) == settings.bold
&& c1.hasDecoration(TextDecoration.ITALIC) == settings.italic
&& c1.hasDecoration(TextDecoration.UNDERLINED) == settings.underlined
&& c1.hasDecoration(TextDecoration.STRIKETHROUGH) == settings.strikethrough
&& c1.hasDecoration(TextDecoration.OBFUSCATED) == settings.obfuscated;
} }
private static void sortSections(ArrayList<FormattedSection> sections) { private static void sortSections(ArrayList<FormattedSection> sections) {

View file

@ -1,8 +1,8 @@
package buttondevteam.chat.components.formatter.formatting; package buttondevteam.chat.components.formatter.formatting;
import buttondevteam.lib.chat.Color;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import net.kyori.adventure.text.format.TextColor;
/** /**
* Describes how a matched section of the message should look. May be combined with other format settings. * Describes how a matched section of the message should look. May be combined with other format settings.
@ -15,7 +15,7 @@ public class FormatSettings {
boolean underlined; boolean underlined;
boolean strikethrough; boolean strikethrough;
boolean obfuscated; boolean obfuscated;
Color color; TextColor color;
ChatFormatter.TriFunc<String, FormatSettings, FormattedSection, String> onmatch; ChatFormatter.TriFunc<String, FormatSettings, FormattedSection, String> onmatch;
String openlink; String openlink;
String hoverText; String hoverText;
@ -27,7 +27,6 @@ public class FormatSettings {
if (field.getBoolean(settings)) if (field.getBoolean(settings))
field.setBoolean(this, true); //Set to true if either of them are true field.setBoolean(this, true); //Set to true if either of them are true
} else if (field.get(settings) != null) { } else if (field.get(settings) != null) {
//System.out.println("Setting " + field.getType() + " " + field.getName() + " from " + field.get(this) + " to " + field.get(settings));
field.set(this, field.get(settings)); field.set(this, field.get(settings));
} }
} }

View file

@ -1,7 +1,7 @@
package buttondevteam.chat.components.formatter.formatting; package buttondevteam.chat.components.formatter.formatting;
import buttondevteam.lib.architecture.ConfigData;
import buttondevteam.lib.architecture.IHaveConfig; import buttondevteam.lib.architecture.IHaveConfig;
import buttondevteam.lib.architecture.config.IConfigData;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -31,7 +31,7 @@ public abstract class MatchProviderBase implements MatchProvider {
resetSubclass(); resetSubclass();
} }
ConfigData<Boolean> enabled(IHaveConfig config) { IConfigData<Boolean> enabled(IHaveConfig config) {
return config.getData(name + ".enabled", true); return config.getData(name + ".enabled", true);
} }

View file

@ -12,7 +12,7 @@ public class StringMatchProvider extends MatchProviderBase {
@ToString.Exclude @ToString.Exclude
private final FormatSettings settings; private final FormatSettings settings;
private int nextIndex = 0; private int nextIndex = 0;
private boolean ignoreCase; private final boolean ignoreCase;
/** /**
* Matches the given strings in the order given * Matches the given strings in the order given

View file

@ -6,9 +6,9 @@ import java.io.Serializable;
public final class TellrawEvent<T extends TellrawEvent.Action> implements Serializable { public final class TellrawEvent<T extends TellrawEvent.Action> implements Serializable {
private static final long serialVersionUID = -1681364161210561505L; private static final long serialVersionUID = -1681364161210561505L;
private transient boolean hoverEvent; private final transient boolean hoverEvent;
private T action; private final T action;
private Object value; private final Object value;
private TellrawEvent(T action, String value) { private TellrawEvent(T action, String value) {
this.hoverEvent = action instanceof HoverAction; this.hoverEvent = action instanceof HoverAction;
@ -44,7 +44,7 @@ public final class TellrawEvent<T extends TellrawEvent.Action> implements Serial
public enum ClickAction implements Action { public enum ClickAction implements Action {
OPEN_URL("open_url"), RUN_COMMAND("run_command"), SUGGEST_COMMAND("suggest_command"); OPEN_URL("open_url"), RUN_COMMAND("run_command"), SUGGEST_COMMAND("suggest_command");
private String action; private final String action;
ClickAction(String action) { ClickAction(String action) {
this.action = action; this.action = action;
@ -58,8 +58,8 @@ public final class TellrawEvent<T extends TellrawEvent.Action> implements Serial
public enum HoverAction implements Action { public enum HoverAction implements Action {
SHOW_TEXT("show_text"), SHOW_ITEM("show_item"), SHOW_ACHIEVEMENT("show_achievement"), SHOW_ENTITY( SHOW_TEXT("show_text"), SHOW_ITEM("show_item"), SHOW_ACHIEVEMENT("show_achievement"), SHOW_ENTITY(
"show_entity"); "show_entity");
private String action; private final String action;
HoverAction(String action) { HoverAction(String action) {
this.action = action; this.action = action;

View file

@ -14,7 +14,7 @@ public final class TellrawPart implements Serializable {
private boolean underlined; private boolean underlined;
private boolean strikethrough; private boolean strikethrough;
private boolean obfuscated; private boolean obfuscated;
private List<TellrawPart> extra = new ArrayList<>(); private final List<TellrawPart> extra = new ArrayList<>();
private String text; private String text;
private TellrawEvent<TellrawEvent.HoverAction> hoverEvent; private TellrawEvent<TellrawEvent.HoverAction> hoverEvent;
private TellrawEvent<TellrawEvent.ClickAction> clickEvent; private TellrawEvent<TellrawEvent.ClickAction> clickEvent;

View file

@ -23,7 +23,7 @@ import java.util.stream.Collectors;
}) })
public class FTopCommand extends ICommand2MC { public class FTopCommand extends ICommand2MC {
private final File playerdir = new File(TBMCPlayerBase.TBMC_PLAYERS_DIR); private final File playerdir = new File("TBMC/players/");
private ChatPlayer[] cached; private ChatPlayer[] cached;
private long lastcache = 0; private long lastcache = 0;
@ -54,8 +54,8 @@ public class FTopCommand extends ICommand2MC {
} }
val ai = new AtomicInteger(); val ai = new AtomicInteger();
sender.sendMessage("§6---- Top Fs ----"); sender.sendMessage("§6---- Top Fs ----");
sender.sendMessage(Arrays.stream(cached).skip((i - 1) * 10).limit(i * 10) sender.sendMessage(Arrays.stream(cached).skip((i - 1) * 10L).limit(i * 10L)
.map(cp -> String.format("%d. %s - %f.2", ai.incrementAndGet(), cp.PlayerName().get(), cp.getF())) .map(cp -> String.format("%d. %s - %f.2", ai.incrementAndGet(), cp.getPlayerName(), cp.getF()))
.collect(Collectors.joining("\n"))); .collect(Collectors.joining("\n")));
}); });
return true; return true;

View file

@ -3,18 +3,19 @@ package buttondevteam.chat.components.fun;
import buttondevteam.chat.ChatPlayer; import buttondevteam.chat.ChatPlayer;
import buttondevteam.chat.PluginMain; import buttondevteam.chat.PluginMain;
import buttondevteam.core.component.channel.Channel; import buttondevteam.core.component.channel.Channel;
import buttondevteam.lib.ChromaUtils;
import buttondevteam.lib.TBMCChatEventBase; import buttondevteam.lib.TBMCChatEventBase;
import buttondevteam.lib.TBMCCommandPreprocessEvent; import buttondevteam.lib.TBMCCommandPreprocessEvent;
import buttondevteam.lib.TBMCSystemChatEvent; import buttondevteam.lib.TBMCSystemChatEvent;
import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.architecture.ConfigData; import buttondevteam.lib.architecture.config.IConfigData;
import buttondevteam.lib.architecture.config.IListConfigData;
import buttondevteam.lib.chat.TBMCChatAPI; import buttondevteam.lib.chat.TBMCChatAPI;
import buttondevteam.lib.player.ChromaGamerBase; import buttondevteam.lib.player.ChromaGamerBase;
import buttondevteam.lib.player.TBMCPlayer; import buttondevteam.lib.player.TBMCPlayer;
import buttondevteam.lib.player.TBMCPlayerBase;
import com.google.common.collect.Lists;
import lombok.val; import lombok.val;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
@ -36,34 +37,29 @@ public class FunComponent extends Component<PluginMain> implements Listener {
private boolean ActiveF = false; private boolean ActiveF = false;
private ChatPlayer FPlayer = null; private ChatPlayer FPlayer = null;
private BukkitTask Ftask = null; private BukkitTask Ftask = null;
private HashSet<CommandSender> Fs = new HashSet<>(); private final HashSet<ChromaGamerBase> Fs = new HashSet<>();
private UnlolCommand command; private UnlolCommand command;
private TBMCSystemChatEvent.BroadcastTarget unlolTarget; private TBMCSystemChatEvent.BroadcastTarget unlolTarget;
private TBMCSystemChatEvent.BroadcastTarget fTarget; private TBMCSystemChatEvent.BroadcastTarget fTarget;
private final Random random = new Random();
/** /**
* The strings that count as laughs, see unlol. * The strings that count as laughs, see unlol.
*/ */
private ConfigData<String[]> laughStrings() { private final IListConfigData<String> laughStrings = getConfig().getListData("laughStrings", Lists.newArrayList("xd", "lel", "lawl", "kek", "lmao", "hue", "hah", "rofl"));
return getConfig().getData("laughStrings", () -> new String[]{"xd", "lel", "lawl", "kek", "lmao", "hue", "hah", "rofl"});
}
/** /**
* The "Press F to pay respects" meme in Minecraft. It will randomly appear on player death and keep track of how many "F"s are said in chat. * The "Press F to pay respects" meme in Minecraft. It will randomly appear on player death and keep track of how many "F"s are said in chat.
* You can hover over a player's name to see their respect. * You can hover over a player's name to see their respect.
*/ */
private ConfigData<Boolean> respect() { private final IConfigData<Boolean> respect = getConfig().getData("respect", true);
return getConfig().getData("respect", true);
}
/** /**
* This is an inside joke on our server. * This is an inside joke on our server.
* It keeps track of laughs (lols and what's defined in laughStrings) and if someone does /unlol or /unlaugh it will unlaugh the last person who laughed. * It keeps track of laughs (lols and what's defined in laughStrings) and if someone does /unlol or /unlaugh it will unlaugh the last person who laughed.
* Which also blinds the laughing person for a few seconds. This action can only be performed once per laugh. * Which also blinds the laughing person for a few seconds. This action can only be performed once per laugh.
*/ */
private ConfigData<Boolean> unlol() { private final IConfigData<Boolean> unlol = getConfig().getData("unlol", true);
return getConfig().getData("unlol", true);
}
@Override @Override
protected void enable() { protected void enable() {
@ -72,7 +68,7 @@ public class FunComponent extends Component<PluginMain> implements Listener {
val pc = new PressCommand(); val pc = new PressCommand();
registerCommand(pc); registerCommand(pc);
registerListener(pc); registerListener(pc);
registerCommand(command=new UnlolCommand(unlolTarget)); registerCommand(command = new UnlolCommand(unlolTarget));
registerListener(this); registerListener(this);
registerCommand(new FTopCommand()); registerCommand(new FTopCommand());
registerCommand(new OpmeCommand()); registerCommand(new OpmeCommand());
@ -85,20 +81,21 @@ public class FunComponent extends Component<PluginMain> implements Listener {
} }
public void onChat(CommandSender sender, TBMCChatEventBase event, String message) { public void onChat(ChromaGamerBase sender, TBMCChatEventBase event, String message) {
if (ActiveF && !Fs.contains(sender) && message.equalsIgnoreCase("F")) if (ActiveF && !Fs.contains(sender) && message.equalsIgnoreCase("F"))
Fs.add(sender); Fs.add(sender);
if (unlol().get()) { if (unlol.get()) {
String msg = message.toLowerCase(); String msg = message.toLowerCase();
val lld = new UnlolCommand.LastlolData(sender, event, System.nanoTime()); val lld = new UnlolCommand.LastlolData(sender, event, System.nanoTime());
boolean add; boolean add = msg.contains("lol");
if (add = msg.contains("lol")) if (add)
lld.setLolornot(true); lld.setLolornot(true);
else { else {
String[] laughs = laughStrings().get(); val laughs = laughStrings.get();
for (String laugh : laughs) { for (String laugh : laughs) {
if (add = msg.contains(laugh)) { add = msg.contains(laugh);
if (add) {
lld.setLolornot(false); lld.setLolornot(false);
break; break;
} }
@ -112,13 +109,13 @@ public class FunComponent extends Component<PluginMain> implements Listener {
@EventHandler @EventHandler
public void onPlayerDeath(PlayerDeathEvent e) { public void onPlayerDeath(PlayerDeathEvent e) {
// MinigamePlayer mgp = Minigames.plugin.pdata.getMinigamePlayer(e.getEntity()); // MinigamePlayer mgp = Minigames.plugin.pdata.getMinigamePlayer(e.getEntity());
if (e.getDeathMessage().length() > 0 && respect().get() && new Random().nextBoolean()) { // Don't store Fs for NPCs if (e.getDeathMessage().length() > 0 && respect.get() && random.nextBoolean()) { // Don't store Fs for NPCs
Runnable tt = () -> { Runnable tt = () -> {
if (ActiveF) { if (ActiveF) {
ActiveF = false; ActiveF = false;
if (FPlayer != null && FPlayer.FCount().get() < Integer.MAX_VALUE - 1) if (FPlayer != null && FPlayer.FCount.get() < Integer.MAX_VALUE - 1)
FPlayer.FCount().set(FPlayer.FCount().get() + Fs.size()); FPlayer.FCount.set(FPlayer.FCount.get() + Fs.size());
TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, Channel.RecipientTestResult.ALL, TBMCChatAPI.SendSystemMessage(Channel.globalChat, Channel.RecipientTestResult.ALL,
"§b" + Fs.size() + " " + (Fs.size() == 1 ? "person" : "people") "§b" + Fs.size() + " " + (Fs.size() == 1 ? "person" : "people")
+ " paid their respects.§r", fTarget); + " paid their respects.§r", fTarget);
Fs.clear(); Fs.clear();
@ -131,8 +128,8 @@ public class FunComponent extends Component<PluginMain> implements Listener {
ActiveF = true; ActiveF = true;
Fs.clear(); Fs.clear();
FPlayer = TBMCPlayer.getPlayer(e.getEntity().getUniqueId(), ChatPlayer.class); FPlayer = TBMCPlayer.getPlayer(e.getEntity().getUniqueId(), ChatPlayer.class);
FPlayer.FDeaths().set(FPlayer.FDeaths().get() + 1); FPlayer.FDeaths.set(FPlayer.FDeaths.get() + 1);
TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, Channel.RecipientTestResult.ALL, TBMCChatAPI.SendSystemMessage(Channel.globalChat, Channel.RecipientTestResult.ALL,
"§bPress F to pay respects.§r", fTarget); "§bPress F to pay respects.§r", fTarget);
Ftask = Bukkit.getScheduler().runTaskLaterAsynchronously(PluginMain.Instance, tt, 15 * 20); Ftask = Bukkit.getScheduler().runTaskLaterAsynchronously(PluginMain.Instance, tt, 15 * 20);
} }
@ -140,14 +137,14 @@ public class FunComponent extends Component<PluginMain> implements Listener {
@EventHandler @EventHandler
public void onPlayerLeave(PlayerQuitEvent event) { public void onPlayerLeave(PlayerQuitEvent event) {
if (unlol().get()) if (unlol.get())
command.Lastlol.values().removeIf(lld -> lld.getLolowner().equals(event.getPlayer())); command.Lastlol.values().removeIf(lld -> lld.getLolowner().equals(ChromaGamerBase.getFromSender(event.getPlayer())));
} }
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)
public void onCommandPreprocess(TBMCCommandPreprocessEvent event) { public void onCommandPreprocess(TBMCCommandPreprocessEvent event) {
if (event.isCancelled()) return; if (event.isCancelled()) return;
if (!unlol().get()) return; if (!unlol.get()) return;
final String cmd = event.getMessage(); final String cmd = event.getMessage();
// We don't care if we have arguments // We don't care if we have arguments
if (cmd.toLowerCase().startsWith("/un")) { if (cmd.toLowerCase().startsWith("/un")) {
@ -155,7 +152,14 @@ public class FunComponent extends Component<PluginMain> implements Listener {
if (ht.getName().equalsIgnoreCase(cmd)) if (ht.getName().equalsIgnoreCase(cmd))
return; return;
} }
if (PluginMain.permission.has(event.getSender(), "chroma.unanything")) { val user = event.getSender();
if (!(user instanceof TBMCPlayerBase)) {
// TODO: Cross-platform permission check; console is not supported here
user.sendMessage("§cError: You must be a player to use this command.");
return;
}
val player = ((TBMCPlayerBase) user).getPlayer();
if (player != null && PluginMain.permission.has(player, "chroma.unanything")) {
event.setCancelled(true); event.setCancelled(true);
int index = cmd.lastIndexOf(' '); int index = cmd.lastIndexOf(' ');
if (index == -1) { if (index == -1) {
@ -168,10 +172,9 @@ public class FunComponent extends Component<PluginMain> implements Listener {
event.getSender().sendMessage("§cError: Player not found. (/un" + s + " <player>)"); event.getSender().sendMessage("§cError: Player not found. (/un" + s + " <player>)");
return; return;
} }
val user = ChromaGamerBase.getFromSender(event.getSender());
target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 10 * 20, 5, false, false)); target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 10 * 20, 5, false, false));
val chan = user.channel().get(); val chan = user.getChannel().get();
TBMCChatAPI.SendSystemMessage(chan, chan.getRTR(event.getSender()), ChromaUtils.getDisplayName(event.getSender()) + " un" + s TBMCChatAPI.SendSystemMessage(chan, chan.getRTR(event.getSender()), event.getSender().getName() + " un" + s
+ "'d " + target.getDisplayName(), unlolTarget); + "'d " + target.getDisplayName(), unlolTarget);
} }
} }

View file

@ -1,6 +1,7 @@
package buttondevteam.chat.components.fun; package buttondevteam.chat.components.fun;
import buttondevteam.core.component.channel.Channel; import buttondevteam.core.component.channel.Channel;
import buttondevteam.core.component.restart.RestartComponent;
import buttondevteam.core.component.restart.ScheduledRestartCommand; import buttondevteam.core.component.restart.ScheduledRestartCommand;
import buttondevteam.lib.ChromaUtils; import buttondevteam.lib.ChromaUtils;
import buttondevteam.lib.ScheduledServerRestartEvent; import buttondevteam.lib.ScheduledServerRestartEvent;
@ -8,6 +9,7 @@ import buttondevteam.lib.chat.Command2;
import buttondevteam.lib.chat.CommandClass; import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.chat.ICommand2MC; import buttondevteam.lib.chat.ICommand2MC;
import buttondevteam.lib.chat.TBMCChatAPI; import buttondevteam.lib.chat.TBMCChatAPI;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
@ -35,7 +37,7 @@ public class PressCommand extends ICommand2MC implements Listener {
return; return;
} }
pressers.add(sender); pressers.add(sender);
TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, Channel.RecipientTestResult.ALL, String.format("§b-- %s §bpressed at %.0fs", ChromaUtils.getDisplayName(sender), command.getRestartCounter() / 20f), command.getComponent().getRestartBroadcast()); TBMCChatAPI.SendSystemMessage(Channel.globalChat, Channel.RecipientTestResult.ALL, String.format("§b-- %s §bpressed at %.0fs", ChromaUtils.getDisplayName(sender), command.getRestartCounter() / 20f), ((RestartComponent) command.getComponent()).getRestartBroadcast());
command.setRestartCounter(startTicks); command.setRestartCounter(startTicks);
} }
@ -44,5 +46,7 @@ public class PressCommand extends ICommand2MC implements Listener {
command = event.getCommand(); command = event.getCommand();
pressers = new HashSet<>(); pressers = new HashSet<>();
startTicks = event.getRestartTicks(); startTicks = event.getRestartTicks();
if (Bukkit.getOnlinePlayers().size() > 0)
TBMCChatAPI.SendSystemMessage(Channel.globalChat, Channel.RecipientTestResult.ALL, "§b-- Do /press to reset the timer. You may only press once.", ((RestartComponent) command.getComponent()).getRestartBroadcast());
} }
} }

View file

@ -1,17 +1,16 @@
package buttondevteam.chat.components.fun; package buttondevteam.chat.components.fun;
import buttondevteam.core.component.channel.Channel; import buttondevteam.core.component.channel.Channel;
import buttondevteam.lib.ChromaUtils;
import buttondevteam.lib.TBMCChatEventBase; import buttondevteam.lib.TBMCChatEventBase;
import buttondevteam.lib.TBMCSystemChatEvent; import buttondevteam.lib.TBMCSystemChatEvent;
import buttondevteam.lib.chat.Command2; import buttondevteam.lib.chat.Command2;
import buttondevteam.lib.chat.CommandClass; import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.chat.ICommand2MC; import buttondevteam.lib.chat.ICommand2MC;
import buttondevteam.lib.chat.TBMCChatAPI; import buttondevteam.lib.chat.TBMCChatAPI;
import buttondevteam.lib.player.ChromaGamerBase;
import buttondevteam.lib.player.TBMCPlayerBase;
import lombok.Data; import lombok.Data;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.bukkit.command.CommandSender;
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;
@ -33,18 +32,18 @@ public final class UnlolCommand extends ICommand2MC {
private final TBMCSystemChatEvent.BroadcastTarget target; private final TBMCSystemChatEvent.BroadcastTarget target;
@Command2.Subcommand @Command2.Subcommand
public boolean def(CommandSender sender) { public boolean def(ChromaGamerBase sender) {
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 TBMCPlayerBase) {
((Player) lol.Lolowner) var player = ((TBMCPlayerBase) lol.Lolowner).getPlayer();
.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 2 * 20, 5, false, false)); if (player != null)
String msg = ChromaUtils.getDisplayName(sender) player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 2 * 20, 5, false, false));
+ (lol.Lolornot ? " unlolled " : " unlaughed ") }
+ ChromaUtils.getDisplayName(lol.Lolowner); String msg = sender.getName() + (lol.Lolornot ? " unlolled " : " unlaughed ") + lol.Lolowner.getName();
TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, Channel.RecipientTestResult.ALL, msg, target); TBMCChatAPI.SendSystemMessage(Channel.globalChat, Channel.RecipientTestResult.ALL, msg, target);
Lastlol.remove(lol.Chatevent.getChannel()); Lastlol.remove(lol.Chatevent.getChannel());
return true; return true;
} }
@ -52,7 +51,7 @@ public final class UnlolCommand extends ICommand2MC {
@Data @Data
public static class LastlolData { public static class LastlolData {
private boolean Lolornot; private boolean Lolornot;
private final CommandSender Lolowner; private final ChromaGamerBase Lolowner;
private final TBMCChatEventBase Chatevent; private final TBMCChatEventBase Chatevent;
private final long Loltime; private final long Loltime;
} }

View file

@ -11,7 +11,6 @@ import com.palmergames.bukkit.towny.object.Town;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -28,8 +27,8 @@ public class NColorCommand extends UCommandBase {
Resident res; Resident res;
Town town; Town town;
try { try {
if ((res = TownyComponent.TU.getResidentMap().get(player.getName().toLowerCase())) == null || !res.hasTown() if ((res = TownyComponent.dataSource.getResident(player.getName())) == 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;
} }
@ -41,7 +40,7 @@ public class NColorCommand extends UCommandBase {
//Don't add ~ for nicknames //Don't add ~ for nicknames
if (!nameWithLines.replace("|", "").replace(":", "").equalsIgnoreCase(name)) { if (!nameWithLines.replace("|", "").replace(":", "").equalsIgnoreCase(name)) {
player.sendMessage("§cThe name you gave doesn't match your name. Make sure to use " player.sendMessage("§cThe name you gave doesn't match your name. Make sure to use "
+ name + "§c with added vertical lines (|) or colons (:)."); + name + "§c with added vertical lines (|) or colons (:).");
return true; return true;
} }
String[] nameparts = nameWithLines.split("[|:]"); String[] nameparts = nameWithLines.split("[|:]");
@ -50,22 +49,31 @@ public class NColorCommand extends UCommandBase {
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;
} }
if (nameparts.length < towncolors.length + 1) { //+1: Nation color var component = TownColorComponent.getComponent();
byte nationColors = (byte) (component.useNationColors.get() ? 1 : 0);
if (nameparts.length < towncolors.length + nationColors) { //+1: Nation color
player.sendMessage("§cYou need more vertical lines (|) or colons (:) in your name. (Should have " + (towncolors.length - 1 + 1) + ")"); //Nation color player.sendMessage("§cYou need more vertical lines (|) or colons (:) in your name. (Should have " + (towncolors.length - 1 + 1) + ")"); //Nation color
return true; return true;
} }
if (nameparts.length > (towncolors.length + 1) * 2) { if (nameparts.length > (towncolors.length + nationColors) * 2) {
player.sendMessage("§cYou have waay too many vertical lines (|) or colons (:) in your name. (Should have " + (towncolors.length - 1 + 1) + ")"); player.sendMessage("§cYou have waay too many vertical lines (|) or colons (:) in your name. (Should have " + (towncolors.length - 1 + 1) + ")");
return true; return true;
} }
if (nameparts.length > towncolors.length + 1) { if (nameparts.length > towncolors.length + nationColors) {
player.sendMessage("§cYou have too many vertical lines (|) or colons (:) in your name. (Should have " + (towncolors.length - 1 + 1) + ")"); player.sendMessage("§cYou have too many vertical lines (|) or colons (:) in your name. (Should have " + (towncolors.length - 1 + 1) + ")");
return true; return true;
} }
ChatPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class).NameColorLocations() var cp = ChatPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class);
.set(new ArrayList<>(Arrays.stream(nameparts).map(String::length).collect(Collectors.toList()))); // No byte[], no TIntArrayList var list = Arrays.stream(nameparts).map(String::length).collect(Collectors.toList());
TownColorComponent.updatePlayerColors(player); if (list.contains(0)) {
player.sendMessage("§bName colors set: " + player.getDisplayName()); player.sendMessage("§cAll colors need to be represented in your name. (Use as Test|name|123 instead of |Testname123|)");
return true;
}
var clist = cp.NameColorLocations.get(); // No byte[], no TIntArrayList
clist.clear();
clist.addAll(list);
TownColorComponent.updatePlayerColors(player, cp);
player.sendMessage("§bName colors set: " + player.getDisplayName());
return true; return true;
} }
} }

View file

@ -3,7 +3,6 @@ package buttondevteam.chat.components.towncolors;
import buttondevteam.chat.commands.ucmds.UCommandBase; import buttondevteam.chat.commands.ucmds.UCommandBase;
import buttondevteam.chat.components.towncolors.admin.TownColorCommand; import buttondevteam.chat.components.towncolors.admin.TownColorCommand;
import buttondevteam.chat.components.towny.TownyComponent; import buttondevteam.chat.components.towny.TownyComponent;
import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.chat.Command2; import buttondevteam.lib.chat.Command2;
import buttondevteam.lib.chat.CommandClass; import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.chat.CustomTabCompleteMethod; import buttondevteam.lib.chat.CustomTabCompleteMethod;
@ -21,21 +20,19 @@ import org.bukkit.entity.Player;
public class NationColorCommand extends UCommandBase { public class NationColorCommand extends UCommandBase {
@Command2.Subcommand @Command2.Subcommand
public boolean def(Player player, String color) { public boolean def(Player player, String color) {
Resident res; String msg = "§cYou need to be the king of a nation to set it's colors.";
if (!(TownyComponent.TU.getResidentMap().containsKey(player.getName().toLowerCase())
&& (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.");
return true;
}
final Nation n;
try { try {
n = res.getTown().getNation(); Resident res = TownyComponent.dataSource.getResident(player.getName());
if (!res.isKing()) {
player.sendMessage(msg);
return true;
}
final Nation n = res.getTown().getNation();
return buttondevteam.chat.components.towncolors.admin.NationColorCommand.SetNationColor(player, n, color);
} catch (NotRegisteredException e) { } catch (NotRegisteredException e) {
TBMCCoreAPI.SendException("Failed to set nation color for player " + player + "!", e); player.sendMessage(msg);
player.sendMessage("§cCouldn't find your town/nation... Error reported.");
return true; return true;
} }
return buttondevteam.chat.components.towncolors.admin.NationColorCommand.SetNationColor(player, n, color);
} }
@CustomTabCompleteMethod(param = "color") @CustomTabCompleteMethod(param = "color")

View file

@ -2,7 +2,6 @@ package buttondevteam.chat.components.towncolors;
import buttondevteam.chat.commands.ucmds.UCommandBase; import buttondevteam.chat.commands.ucmds.UCommandBase;
import buttondevteam.chat.components.towny.TownyComponent; import buttondevteam.chat.components.towny.TownyComponent;
import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.chat.Command2; import buttondevteam.lib.chat.Command2;
import buttondevteam.lib.chat.CommandClass; import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.chat.CustomTabCompleteMethod; import buttondevteam.lib.chat.CustomTabCompleteMethod;
@ -18,33 +17,31 @@ import org.bukkit.entity.Player;
"This command allows setting a color for a town.", // "This command allows setting a color for a town.", //
"The town will be shown with this color on Dynmap and all players in the town will appear in chat with these colors.", // "The town will be shown with this color on Dynmap and all players in the town will appear in chat with these colors.", //
"The colors will split the name evenly but residents can override that with /u ncolor.", // "The colors will split the name evenly but residents can override that with /u ncolor.", //
}) // TODO: /u u when annotation not present })
@RequiredArgsConstructor @RequiredArgsConstructor
public class TownColorCommand extends UCommandBase { public class TownColorCommand extends UCommandBase {
private final TownColorComponent component; private final TownColorComponent component;
@Command2.Subcommand @Command2.Subcommand
public boolean def(Player player, String... colornames) { public boolean def(Player player, String... colornames) {
Resident res; String msg = "§cYou need to be the mayor of a town to set its colors.";
if (!(TownyComponent.TU.getResidentMap().containsKey(player.getName().toLowerCase())
&& (res = TownyComponent.TU.getResidentMap().get(player.getName().toLowerCase())).isMayor())) {
player.sendMessage("§cYou need to be the mayor of a town to set its colors.");
return true;
}
val cc = component.colorCount().get();
if (colornames.length > cc) {
player.sendMessage("You can only use " + cc + " color" + (cc > 1 ? "s" : "") + ".");
return true;
}
final Town t;
try { try {
t = res.getTown(); Resident res = TownyComponent.dataSource.getResident(player.getName());
if (!res.isMayor()) {
player.sendMessage(msg);
return true;
}
val cc = component.colorCount.get();
if (colornames.length > cc) {
player.sendMessage("You can only use " + cc + " color" + (cc > 1 ? "s" : "") + ".");
return true;
}
final Town t = res.getTown();
return buttondevteam.chat.components.towncolors.admin.TownColorCommand.SetTownColor(player, t, colornames);
} catch (NotRegisteredException e) { } catch (NotRegisteredException e) {
TBMCCoreAPI.SendException("Failed to set town color for player " + player + "!", e); player.sendMessage(msg);
player.sendMessage("§cCouldn't find your town... Error reported.");
return true; return true;
} }
return buttondevteam.chat.components.towncolors.admin.TownColorCommand.SetTownColor(player, t, colornames);
} }
@CustomTabCompleteMethod(param = "colornames") @CustomTabCompleteMethod(param = "colornames")

View file

@ -8,12 +8,13 @@ import buttondevteam.core.ComponentManager;
import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.architecture.ComponentMetadata; import buttondevteam.lib.architecture.ComponentMetadata;
import buttondevteam.lib.architecture.ConfigData; import buttondevteam.lib.architecture.config.IConfigData;
import buttondevteam.lib.chat.Color; import buttondevteam.lib.chat.Color;
import buttondevteam.lib.player.TBMCPlayerJoinEvent; import buttondevteam.lib.player.TBMCPlayer;
import com.earth2me.essentials.User; import com.earth2me.essentials.User;
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException; import com.palmergames.bukkit.towny.exceptions.NotRegisteredException;
import com.palmergames.bukkit.towny.object.Nation; import com.palmergames.bukkit.towny.object.Nation;
import com.palmergames.bukkit.towny.object.Resident;
import lombok.Getter; import lombok.Getter;
import lombok.val; import lombok.val;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -21,7 +22,9 @@ import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.dynmap.towny.DTBridge; import org.dynmap.towny.DTBridge;
@ -41,26 +44,22 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
/** /**
* Names lowercased * Names lowercased
*/ */
public static Map<String, Color[]> TownColors = new HashMap<>(); public static final Map<String, Color[]> TownColors = new HashMap<>();
/** /**
* Names lowercased - nation color gets added to town colors when needed * Names lowercased - nation color gets added to town colors when needed
*/ */
public static Map<String, Color> NationColor = new HashMap<>(); public static final Map<String, Color> NationColor = new HashMap<>();
/** /**
* The amount of town colors allowed. If more than one is used, players can change how many letters to be in a specific color using /u ncolor. * The amount of town colors allowed. If more than one is used (or nation colors are enabled), players can change how many letters to be in a specific color using /u ncolor.
*/ */
public ConfigData<Byte> colorCount() { public final IConfigData<Byte> colorCount = getConfig().getData("colorCount", (byte) 1, cc -> ((Integer) cc).byteValue(), Byte::intValue);
return getConfig().getData("colorCount", (byte) 1, cc -> ((Integer) cc).byteValue(), Byte::intValue);
}
/** /**
* If enabled, players will have a nation-defined color in addition to town colors, white by default. * If enabled, players will have a nation-defined color in addition to town colors, white by default.
* They can change how much of each color they want with this as well. * They can change how much of each color they want with this as well.
*/ */
public ConfigData<Boolean> useNationColors() { public final IConfigData<Boolean> useNationColors = getConfig().getData("useNationColors", true);
return getConfig().getData("useNationColors", true);
}
@Getter @Getter
private static TownColorComponent component; private static TownColorComponent component;
@ -72,7 +71,7 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
Consumer<ConfigurationSection> loadTC = cs -> TownColorComponent.TownColors.putAll(cs.getValues(true).entrySet().stream() Consumer<ConfigurationSection> loadTC = cs -> TownColorComponent.TownColors.putAll(cs.getValues(true).entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, v -> ((List<String>) v.getValue()).stream() .collect(Collectors.toMap(Map.Entry::getKey, v -> ((List<String>) v.getValue()).stream()
.map(Color::valueOf).toArray(Color[]::new)))); .map(Color::valueOf).toArray(Color[]::new))));
boolean usenc = useNationColors().get(); boolean usenc = useNationColors.get();
Consumer<ConfigurationSection> loadNC = ncs -> Consumer<ConfigurationSection> loadNC = ncs ->
TownColorComponent.NationColor.putAll(ncs.getValues(true).entrySet().stream() TownColorComponent.NationColor.putAll(ncs.getValues(true).entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, v -> Color.valueOf((String) v.getValue())))); .collect(Collectors.toMap(Map.Entry::getKey, v -> Color.valueOf((String) v.getValue()))));
@ -85,17 +84,17 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
loadNC.accept(ncs); loadNC.accept(ncs);
} }
TownColors.keySet().removeIf(t -> !TownyComponent.TU.getTownsMap().containsKey(t)); // Removes town colors for deleted/renamed towns TownColors.keySet().removeIf(t -> TownyComponent.dataSource.getTown(t) == null); // Removes town colors for deleted/renamed towns
if (usenc) if (usenc)
NationColor.keySet().removeIf(n -> !TownyComponent.TU.getNationsMap().containsKey(n)); // Removes nation colors for deleted/renamed nations NationColor.keySet().removeIf(n -> TownyComponent.dataSource.getNation(n) == null); // Removes nation colors for deleted/renamed nations
initDynmap(); initDynmap();
registerCommand(new TownColorCommand(this)); registerCommand(new TownColorCommand(this));
if (useNationColors().get()) if (useNationColors.get())
registerCommand(new NationColorCommand()); registerCommand(new NationColorCommand());
registerCommand(new buttondevteam.chat.components.towncolors.admin.TownColorCommand()); registerCommand(new buttondevteam.chat.components.towncolors.admin.TownColorCommand());
if (useNationColors().get()) if (useNationColors.get())
registerCommand(new buttondevteam.chat.components.towncolors.admin.NationColorCommand()); registerCommand(new buttondevteam.chat.components.towncolors.admin.NationColorCommand());
registerCommand(new TCCount()); registerCommand(new TCCount());
registerCommand(new NColorCommand()); registerCommand(new NColorCommand());
@ -107,9 +106,10 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
protected void disable() { protected void disable() {
getConfig().getConfig().createSection("towncolors", TownColors.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, getConfig().getConfig().createSection("towncolors", TownColors.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
v -> Arrays.stream(v.getValue()).map(Enum::toString).toArray(String[]::new)))); v -> Arrays.stream(v.getValue()).map(Enum::toString).toArray(String[]::new))));
if (useNationColors().get()) if (useNationColors.get())
getConfig().getConfig().createSection("nationcolors", NationColor.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, getConfig().getConfig().createSection("nationcolors", NationColor.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
v -> v.getValue().toString()))); v -> v.getValue().toString())));
getConfig().signalChange();
} }
private void initDynmap() { private void initDynmap() {
@ -119,16 +119,16 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
return; return;
for (val entry : TownColors.entrySet()) { for (val entry : TownColors.entrySet()) {
try { try {
val town = TownyComponent.TU.getTownsMap().get(entry.getKey()); val town = TownyComponent.dataSource.getTown(entry.getKey());
Nation nation; Nation nation;
Color nc; Color nc;
if (!useNationColors().get()) if (!useNationColors.get())
nc = null; nc = null;
else if (!town.hasNation() || (nation = town.getNation()) == null || (nc = NationColor.get(nation.getName().toLowerCase())) == null) else if (!town.hasNation() || (nation = town.getNation()) == null || (nc = NationColor.get(nation.getName().toLowerCase())) == null)
nc = Color.White; nc = Color.White;
setTownColor(dtp, buttondevteam.chat.components.towncolors.admin.TownColorCommand.getTownNameCased(entry.getKey()), entry.getValue(), nc); setTownColor(dtp, buttondevteam.chat.components.towncolors.admin.TownColorCommand.getTownNameCased(entry.getKey()), entry.getValue(), nc);
} catch (Exception e) { } catch (Exception e) {
TBMCCoreAPI.SendException("Error while setting town color for town " + entry.getKey() + "!", e); TBMCCoreAPI.SendException("Error while setting town color for town " + entry.getKey() + "!", e, this);
} }
} }
}); });
@ -147,7 +147,7 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
DTBridge.setTownColor(dtp, town, c2i.apply(nationcolor == null ? colors[0] : nationcolor), DTBridge.setTownColor(dtp, town, c2i.apply(nationcolor == null ? colors[0] : nationcolor),
c2i.apply(colors.length > 1 && nationcolor != null ? colors[1] : colors[0])); c2i.apply(colors.length > 1 && nationcolor != null ? colors[1] : colors[0]));
} catch (Exception e) { } catch (Exception e) {
TBMCCoreAPI.SendException("Failed to set town color for town " + town + "!", e); TBMCCoreAPI.SendException("Failed to set town color for town " + town + "!", e, component);
} }
} }
@ -156,7 +156,7 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
if (nickname.contains("~")) //StartsWith doesn't work because of color codes if (nickname.contains("~")) //StartsWith doesn't work because of color codes
nickname = nickname.replace("~", ""); //It gets stacked otherwise nickname = nickname.replace("~", ""); //It gets stacked otherwise
String name = ChatColor.stripColor(nickname); //Enforce "town colors" on non-members String name = ChatColor.stripColor(nickname); //Enforce "town colors" on non-members
val res = TownyComponent.TU.getResidentMap().get(player.getName().toLowerCase()); Resident res = TownyComponent.dataSource.getResident(player.getName());
if (res == null || !res.hasTown()) if (res == null || !res.hasTown())
return name; return name;
try { try {
@ -178,8 +178,8 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
len = name.length() / (clrs.length+1); len = name.length() / (clrs.length+1);
else else
len = name.length() / clrs.length;*/ len = name.length() / clrs.length;*/
boolean usenc = component.useNationColors().get(); boolean usenc = component.useNationColors.get();
val nclar = cp.NameColorLocations().get(); val nclar = cp.NameColorLocations.get();
int[] ncl = nclar == null ? null : nclar.stream().mapToInt(Integer::intValue).toArray(); int[] ncl = nclar == null ? null : nclar.stream().mapToInt(Integer::intValue).toArray();
if (ncl != null && (Arrays.stream(ncl).sum() != name.length() || ncl.length != clrs.length + (usenc ? 1 : 0))) //+1: Nation color if (ncl != null && (Arrays.stream(ncl).sum() != name.length() || ncl.length != clrs.length + (usenc ? 1 : 0))) //+1: Nation color
ncl = null; // Reset if name length changed ncl = null; // Reset if name length changed
@ -201,14 +201,14 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
/** /**
* Checks if the component is enabled * Checks if the component is enabled
*/ */
public static void updatePlayerColors(Player player) { //Probably while ingame (/u ncolor) public static void updatePlayerColors(Player player) { //Probably while ingame (/u ncolor - not anymore)
updatePlayerColors(player, ChatPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class)); updatePlayerColors(player, ChatPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class));
} }
/** /**
* Checks if the component is enabled * Checks if the component is enabled
*/ */
private static void updatePlayerColors(Player player, ChatPlayer cp) { //Probably at join - nop, nicknames public static void updatePlayerColors(Player player, ChatPlayer cp) { //Probably at join - nop, nicknames
if (!ComponentManager.isEnabled(TownColorComponent.class)) if (!ComponentManager.isEnabled(TownColorComponent.class))
return; return;
User user = PluginMain.essentials.getUser(player); User user = PluginMain.essentials.getUser(player);
@ -217,8 +217,8 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
cp.FlairUpdate(); //Update in list cp.FlairUpdate(); //Update in list
} }
@EventHandler @EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerJoin(TBMCPlayerJoinEvent event) { public void onPlayerJoin(PlayerJoinEvent event) {
updatePlayerColors(event.getPlayer(), event.GetPlayer().asPluginPlayer(ChatPlayer.class)); updatePlayerColors(event.getPlayer(), TBMCPlayer.getPlayer(event.getPlayer().getUniqueId(), ChatPlayer.class));
} }
} }

View file

@ -61,7 +61,7 @@ public class TownyListener implements Listener {
@EventHandler @EventHandler
public void onNationRename(RenameNationEvent event) { public void onNationRename(RenameNationEvent event) {
if (!TownColorComponent.getComponent().useNationColors().get()) return; if (!TownColorComponent.getComponent().useNationColors.get()) return;
val clrs = TownColorComponent.NationColor.remove(event.getOldName().toLowerCase()); val clrs = TownColorComponent.NationColor.remove(event.getOldName().toLowerCase());
if (clrs != null) if (clrs != null)
TownColorComponent.NationColor.put(event.getNation().getName().toLowerCase(), clrs); TownColorComponent.NationColor.put(event.getNation().getName().toLowerCase(), clrs);
@ -69,25 +69,25 @@ public class TownyListener implements Listener {
@EventHandler //Gets called on town load as well @EventHandler //Gets called on town load as well
public void onNationJoin(NationAddTownEvent event) { public void onNationJoin(NationAddTownEvent event) {
if (!TownColorComponent.getComponent().useNationColors().get()) return; if (!TownColorComponent.getComponent().useNationColors.get()) return;
updateTownMembers(event.getTown()); updateTownMembers(event.getTown());
} }
@EventHandler @EventHandler
public void onNationLeave(NationRemoveTownEvent event) { public void onNationLeave(NationRemoveTownEvent event) {
if (!TownColorComponent.getComponent().useNationColors().get()) return; if (!TownColorComponent.getComponent().useNationColors.get()) return;
updateTownMembers(event.getTown()); //The town still has it's colours updateTownMembers(event.getTown()); //The town still has it's colours
} }
@EventHandler @EventHandler
public void onNationDelete(DeleteNationEvent event) { public void onNationDelete(DeleteNationEvent event) {
if (!TownColorComponent.getComponent().useNationColors().get()) return; if (!TownColorComponent.getComponent().useNationColors.get()) return;
TownColorComponent.NationColor.remove(event.getNationName().toLowerCase()); TownColorComponent.NationColor.remove(event.getNationName().toLowerCase());
} }
@EventHandler @EventHandler
public void onNationCreate(NewNationEvent event) { public void onNationCreate(NewNationEvent event) {
if (!TownColorComponent.getComponent().useNationColors().get()) return; if (!TownColorComponent.getComponent().useNationColors.get()) return;
Player p = Bukkit.getPlayer(event.getNation().getCapital().getMayor().getName()); Player p = Bukkit.getPlayer(event.getNation().getCapital().getMayor().getName());
if (p != null) if (p != null)
p.sendMessage("§6Use /u nationcolor to set a color for the nation."); p.sendMessage("§6Use /u nationcolor to set a color for the nation.");

View file

@ -23,7 +23,7 @@ import org.bukkit.command.CommandSender;
public class NationColorCommand extends AdminCommandBase { public class NationColorCommand extends AdminCommandBase {
@Command2.Subcommand @Command2.Subcommand
public boolean def(CommandSender sender, String nation, String color) { public boolean def(CommandSender sender, String nation, String color) {
final Nation n = TownyComponent.TU.getNationsMap().get(nation.toLowerCase()); final Nation n = TownyComponent.dataSource.getNation(nation);
if (n == null) { if (n == null) {
sender.sendMessage("§cThe nation '" + nation + "' cannot be found."); sender.sendMessage("§cThe nation '" + nation + "' cannot be found.");
return true; return true;
@ -38,7 +38,7 @@ public class NationColorCommand extends AdminCommandBase {
@CustomTabCompleteMethod(param = "nation") @CustomTabCompleteMethod(param = "nation")
public Iterable<String> def() { public Iterable<String> def() {
return TownyComponent.TU.getDataSource().getNations().stream().map(TownyObject::getName)::iterator; return TownyComponent.dataSource.getNations().stream().map(TownyObject::getName)::iterator;
} }
public static boolean SetNationColor(CommandSender sender, Nation nation, String color) { public static boolean SetNationColor(CommandSender sender, Nation nation, String color) {

View file

@ -15,7 +15,7 @@ public class TCCount extends AdminCommandBase {
@Command2.Subcommand @Command2.Subcommand
public boolean def(CommandSender sender, byte count) { public boolean def(CommandSender sender, byte count) {
val comp = TownColorComponent.getComponent(); val comp = TownColorComponent.getComponent();
comp.colorCount().set(count); comp.colorCount.set(count);
sender.sendMessage("Color count set to " + count); sender.sendMessage("Color count set to " + count);
return true; return true;
} }

View file

@ -25,14 +25,18 @@ import java.util.stream.Collectors;
"The town will be shown with this color on Dynmap and all players in the town will appear in chat with these colors.", // "The town will be shown with this color on Dynmap and all players in the town will appear in chat with these colors.", //
"The colors will split the name evenly.", // "The colors will split the name evenly.", //
}) })
public class TownColorCommand extends AdminCommandBase { //TODO: Command path aliases public class TownColorCommand extends AdminCommandBase {
@Command2.Subcommand @Command2.Subcommand
public boolean def(CommandSender sender, String town, String... colornames) { public boolean def(CommandSender sender, String town, String... colornames) {
if (!TownyComponent.TU.getTownsMap().containsKey(town.toLowerCase())) { if (TownyComponent.dataSource.getTown(town) == null) {
sender.sendMessage("§cThe town '" + town + "' cannot be found.");
return true;
}
Town targetTown = TownyComponent.dataSource.getTown(town);
if (targetTown == null) {
sender.sendMessage("§cThe town '" + town + "' cannot be found."); sender.sendMessage("§cThe town '" + town + "' cannot be found.");
return true; return true;
} }
Town targetTown = TownyComponent.TU.getTownsMap().get(town.toLowerCase());
return SetTownColor(sender, targetTown, colornames); return SetTownColor(sender, targetTown, colornames);
} }
@ -43,7 +47,7 @@ public class TownColorCommand extends AdminCommandBase { //TODO: Command path al
@CustomTabCompleteMethod(param = "town") @CustomTabCompleteMethod(param = "town")
public Iterable<String> def() { public Iterable<String> def() {
return TownyComponent.TU.getDataSource().getTowns().stream().map(TownyObject::getName)::iterator; return TownyComponent.dataSource.getTowns().stream().map(TownyObject::getName)::iterator;
} }
public static boolean SetTownColor(CommandSender sender, Town town, String[] colors) { public static boolean SetTownColor(CommandSender sender, Town town, String[] colors) {
@ -55,7 +59,7 @@ public class TownColorCommand extends AdminCommandBase { //TODO: Command path al
clrs[i] = c.get(); clrs[i] = c.get();
} }
Color tnc; Color tnc;
boolean usenc = TownColorComponent.getComponent().useNationColors().get(); boolean usenc = TownColorComponent.getComponent().useNationColors.get();
if (usenc) { if (usenc) {
try { try {
tnc = TownColorComponent.NationColor.get(town.getNation().getName().toLowerCase()); tnc = TownColorComponent.NationColor.get(town.getNation().getName().toLowerCase());
@ -68,7 +72,7 @@ public class TownColorCommand extends AdminCommandBase { //TODO: Command path al
Color nc; Color nc;
if (usenc) { if (usenc) {
try { try {
nc = TownColorComponent.NationColor.get(TownyComponent.TU.getTownsMap().get(other.getKey()).getNation().getName().toLowerCase()); nc = TownColorComponent.NationColor.get(TownyComponent.dataSource.getTown(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;
} }
@ -112,7 +116,11 @@ public class TownColorCommand extends AdminCommandBase { //TODO: Command path al
} }
public static String getTownNameCased(String name) { public static String getTownNameCased(String name) {
return TownyComponent.TU.getTownsMap().get(name.toLowerCase()).getName(); val town = TownyComponent.dataSource.getTown(name);
if (town == null) {
return null;
}
return town.getName();
} }
public static Iterable<String> tabcompleteColor() { public static Iterable<String> tabcompleteColor() {

View file

@ -44,7 +44,7 @@ public class TownyAnnouncer {
message, target, ChatUtils.MCORIGIN); message, target, ChatUtils.MCORIGIN);
break; break;
case "Global": case "Global":
TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, TBMCChatAPI.SendSystemMessage(Channel.globalChat,
Channel.RecipientTestResult.ALL, Channel.RecipientTestResult.ALL,
message, target, ChatUtils.MCORIGIN); message, target, ChatUtils.MCORIGIN);
break; break;

View file

@ -1,33 +1,33 @@
package buttondevteam.chat.components.towny; package buttondevteam.chat.components.towny;
import buttondevteam.chat.PluginMain; import buttondevteam.chat.PluginMain;
import buttondevteam.chat.VanillaUtils;
import buttondevteam.chat.components.formatter.formatting.TellrawPart;
import buttondevteam.core.component.channel.Channel; import buttondevteam.core.component.channel.Channel;
import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.chat.Color; import buttondevteam.lib.chat.Color;
import buttondevteam.lib.chat.TBMCChatAPI; import buttondevteam.lib.chat.TBMCChatAPI;
import buttondevteam.lib.player.ChromaGamerBase;
import buttondevteam.lib.player.TBMCPlayerBase;
import com.palmergames.bukkit.towny.TownyAPI;
import com.palmergames.bukkit.towny.TownyUniverse; import com.palmergames.bukkit.towny.TownyUniverse;
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException; import com.palmergames.bukkit.towny.exceptions.NotRegisteredException;
import com.palmergames.bukkit.towny.object.Nation; import com.palmergames.bukkit.towny.object.Nation;
import com.palmergames.bukkit.towny.object.Resident; import com.palmergames.bukkit.towny.object.Resident;
import com.palmergames.bukkit.towny.object.Town; import com.palmergames.bukkit.towny.object.Town;
import lombok.val; import lombok.val;
import org.bukkit.command.CommandSender; import net.kyori.adventure.text.TextComponent;
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.function.Consumer;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
* This component manages the town and nation chat. It's also needed for the TownColorComponent. * This component manages the town and nation chat. It's also needed for the TownColorComponent.
* It provides the TC and NC channels, and posts Towny messages (global, town, nation) to the correct channels for other platforms like Discord. * It provides the TC and NC channels, and posts Towny messages (global, town, nation) to the correct channels for other platforms like Discord.
* You can disable /tc and /nc in Chroma-Core's config if you only want to use the TownColorComponent.
*/ */
public class TownyComponent extends Component<PluginMain> { public class TownyComponent extends Component<PluginMain> {
public static TownyUniverse TU; public static TownyAPI dataSource;
private static ArrayList<String> Towns; private static ArrayList<String> Towns;
private static ArrayList<String> Nations; private static ArrayList<String> Nations;
@ -36,12 +36,12 @@ public class TownyComponent extends Component<PluginMain> {
@Override @Override
protected void enable() { protected void enable() {
TU = TownyUniverse.getInstance(); dataSource = TownyAPI.getInstance();
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 Towns = TownyUniverse.getInstance().getTowns().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 Nations = TownyUniverse.getInstance().getNations().stream().map(Nation::getName).collect(Collectors.toCollection(ArrayList::new)); // Same here but with nations
TBMCChatAPI.RegisterChatChannel( TBMCChatAPI.registerChatChannel(
TownChat = new Channel("§3TC§f", Color.DarkAqua, "tc", s -> checkTownNationChat(s, false))); TownChat = new Channel("§3TC§f", Color.DarkAqua, "tc", s -> checkTownNationChat(s, false)));
TBMCChatAPI.RegisterChatChannel( TBMCChatAPI.registerChatChannel(
NationChat = new Channel("§6NC§f", Color.Gold, "nc", s -> checkTownNationChat(s, true))); NationChat = new Channel("§6NC§f", Color.Gold, "nc", s -> checkTownNationChat(s, true)));
TownyAnnouncer.setup(TownChat, NationChat); TownyAnnouncer.setup(TownChat, NationChat);
} }
@ -51,30 +51,34 @@ public class TownyComponent extends Component<PluginMain> {
TownyAnnouncer.setdown(); TownyAnnouncer.setdown();
} }
public void handleSpiesInit(Channel channel, TellrawPart json, Function<TellrawPart, String> toJson) { public Consumer<Player> handleSpiesInit(Channel channel, TextComponent.Builder json) {
if (channel.ID.equals(TownChat.ID) || channel.ID.equals(NationChat.ID)) { if (channel.getIdentifier().equals(TownChat.getIdentifier()) || channel.getIdentifier().equals(NationChat.getIdentifier())) {
((List<TellrawPart>) json.getExtra()).add(0, new TellrawPart("[SPY]")); // TODO: Cannot prepend to json, so we need to run this ealier
jsonstr = toJson.apply(json); //((List<TellrawPart>) json.getExtra()).add(0, new TellrawPart("[SPY]"));
return p -> handleSpies(channel, p, json);
} }
return p -> {};
} }
private String jsonstr; private void handleSpies(Channel channel, Player p, TextComponent.Builder jsonstr) {
if (channel.getIdentifier().equals(TownChat.getIdentifier()) || channel.getIdentifier().equals(NationChat.getIdentifier())) {
public void handleSpies(Channel channel, Player p) { val res = dataSource.getResident(p.getName());
if (channel.ID.equals(TownChat.ID) || channel.ID.equals(NationChat.ID)) { if (res == null) {
if (Optional.ofNullable(TU.getResidentMap().get(p.getName().toLowerCase())) return;
.filter(r -> r.hasMode("spy")).isPresent()) }
VanillaUtils.tellRaw(p, jsonstr); if (res.hasMode("spy"))
p.sendMessage(jsonstr.build());
} }
} }
/** /**
* Return the error message for the message sender if they can't send it and the score * 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) { private static Channel.RecipientTestResult checkTownNationChat(ChromaGamerBase user, boolean nationchat) {
if (!(sender instanceof Player)) if (!(user instanceof TBMCPlayerBase))
return new Channel.RecipientTestResult("§cYou are not a player!"); return new Channel.RecipientTestResult("§cYou are not a player!");
Resident resident = TU.getResidentMap().get(sender.getName().toLowerCase()); val sender = ((TBMCPlayerBase) user).getOfflinePlayer();
Resident resident = dataSource.getResident(sender.getName());
Channel.RecipientTestResult result = checkTownNationChatInternal(nationchat, resident); Channel.RecipientTestResult result = checkTownNationChatInternal(nationchat, resident);
if (result.errormessage != null && resident != null && resident.getModes().contains("spy")) // Only use spy if they wouldn't see it 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 result = new Channel.RecipientTestResult(1000, "allspies"); // There won't be more than a thousand towns/nations probably

View file

@ -7,31 +7,27 @@ import buttondevteam.chat.commands.ucmds.HistoryCommand;
import buttondevteam.chat.components.flair.FlairComponent; import buttondevteam.chat.components.flair.FlairComponent;
import buttondevteam.chat.components.flair.FlairStates; import buttondevteam.chat.components.flair.FlairStates;
import buttondevteam.core.ComponentManager; import buttondevteam.core.ComponentManager;
import buttondevteam.lib.player.TBMCPlayerJoinEvent; import buttondevteam.lib.player.ChromaGamerBase;
import buttondevteam.lib.player.TBMCPlayerLoadEvent; import buttondevteam.lib.player.TBMCPlayerBase;
import buttondevteam.lib.player.TBMCPlayerSaveEvent;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import java.util.Timer; import java.util.Timer;
public class PlayerJoinLeaveListener implements Listener { public class PlayerJoinLeaveListener implements Listener {
@EventHandler @EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerLoad(TBMCPlayerLoadEvent e) { public void onPlayerJoin(PlayerJoinEvent e) {
ChatPlayer cp = e.GetPlayer().asPluginPlayer(ChatPlayer.class);
cp.FlairUpdate();
}
@EventHandler
public void onPlayerTBMCJoin(TBMCPlayerJoinEvent e) {
ChatPlayer cp = e.GetPlayer().asPluginPlayer(ChatPlayer.class);
Player p = e.getPlayer(); Player p = e.getPlayer();
ChatPlayer cp = TBMCPlayerBase.getPlayer(p.getUniqueId(), ChatPlayer.class);
cp.FlairUpdate();
if (ComponentManager.isEnabled(FlairComponent.class)) { if (ComponentManager.isEnabled(FlairComponent.class)) {
if (!cp.FlairState().get().equals(FlairStates.NoComment)) { if (!cp.FlairState.get().equals(FlairStates.NoComment)) {
FlairComponent.ConfirmUserMessage(cp); FlairComponent.ConfirmUserMessage(cp);
Timer timer = new Timer(); Timer timer = new Timer();
PlayerJoinTimerTask tt = new PlayerJoinTimerTask() { PlayerJoinTimerTask tt = new PlayerJoinTimerTask() {
@ -55,14 +51,10 @@ public class PlayerJoinLeaveListener implements Listener {
nwithoutformatting = nwithoutformatting.replace("§" + nwithoutformatting.charAt(index + 1), ""); nwithoutformatting = nwithoutformatting.replace("§" + nwithoutformatting.charAt(index + 1), "");
} else } else
nwithoutformatting = p.getName(); nwithoutformatting = p.getName();
PlayerListener.nicknames.forcePut(nwithoutformatting.toLowerCase(), p.getUniqueId()); //TODO: FormatterComponent PlayerListener.nicknames.forcePut(nwithoutformatting.toLowerCase(), p.getUniqueId());
if (PluginMain.Instance.storeChatHistory().get()) if (PluginMain.Instance.storeChatHistory.get())
HistoryCommand.showHistory(e.getPlayer(), null); HistoryCommand.showHistory(ChromaGamerBase.getFromSender(e.getPlayer()), null);
}
@EventHandler
public void onPlayerSave(TBMCPlayerSaveEvent e) {
} }
@EventHandler @EventHandler

View file

@ -10,6 +10,7 @@ import buttondevteam.chat.components.towncolors.TownColorComponent;
import buttondevteam.core.ComponentManager; import buttondevteam.core.ComponentManager;
import buttondevteam.lib.TBMCChatEvent; import buttondevteam.lib.TBMCChatEvent;
import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.player.ChromaGamerBase;
import buttondevteam.lib.player.ChromaGamerBase.InfoTarget; import buttondevteam.lib.player.ChromaGamerBase.InfoTarget;
import buttondevteam.lib.player.TBMCPlayerGetInfoEvent; import buttondevteam.lib.player.TBMCPlayerGetInfoEvent;
import com.google.common.collect.BiMap; import com.google.common.collect.BiMap;
@ -31,7 +32,7 @@ public class PlayerListener implements Listener {
/** /**
* Does not contain format codes, lowercased * Does not contain format codes, lowercased
*/ */
public static BiMap<String, UUID> nicknames = HashBiMap.create(); public static final BiMap<String, UUID> nicknames = HashBiMap.create();
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerChat(AsyncPlayerChatEvent event) { public void onPlayerChat(AsyncPlayerChatEvent event) {
@ -53,21 +54,18 @@ public class PlayerListener implements Listener {
@EventHandler @EventHandler
public void onGetInfo(TBMCPlayerGetInfoEvent e) { public void onGetInfo(TBMCPlayerGetInfoEvent e) {
try (ChatPlayer cp = e.getPlayer().getAs(ChatPlayer.class)) { ChatPlayer cp = e.getPlayer().getAs(ChatPlayer.class);
if (cp == null) if (cp == null)
return; return;
e.addInfo("Minecraft name: " + cp.PlayerName().get()); e.addInfo("Minecraft name: " + cp.getPlayerName());
if (cp.UserName().get() != null && cp.UserName().get().length() > 0) if (cp.UserName.get() != null && cp.UserName.get().length() > 0)
e.addInfo("Reddit name: " + cp.UserName().get()); e.addInfo("Reddit name: " + cp.UserName.get());
if (ComponentManager.isEnabled(FlairComponent.class)) { if (ComponentManager.isEnabled(FlairComponent.class)) {
final String flair = cp.GetFormattedFlair(e.getTarget() != InfoTarget.MCCommand); final String flair = cp.GetFormattedFlair(e.getTarget() != InfoTarget.MCCommand);
if (flair.length() > 0) if (flair.length() > 0)
e.addInfo("/r/TheButton flair: " + flair); e.addInfo("/r/TheButton flair: " + flair);
}
e.addInfo(String.format("Respect: %.2f", cp.getF()));
} catch (Exception ex) {
TBMCCoreAPI.SendException("Error while providing chat info for player " + e.getPlayer().getFileName(), ex);
} }
e.addInfo(String.format("Respect: %.2f", cp.getF()));
} }
private long lastError = 0; private long lastError = 0;
@ -77,18 +75,18 @@ public class PlayerListener implements Listener {
try { try {
if (e.isCancelled()) if (e.isCancelled())
return; return;
HistoryCommand.addChatMessage(e.getCm(), e.getChannel()); HistoryCommand.addChatMessage(e.getChatMessage(), e.getChannel());
e.setCancelled(FormatterComponent.handleChat(e)); e.setCancelled(FormatterComponent.handleChat(e));
} catch (NoClassDefFoundError | Exception ex) { // Weird things can happen } catch (NoClassDefFoundError | Exception ex) { // Weird things can happen
if (lastError < System.nanoTime() - 1000L * 1000L * 1000L * 60 * 60 //60 mins if (lastError < System.nanoTime() - 1000L * 1000L * 1000L * 60 * 60 //60 mins
&& Bukkit.getOnlinePlayers().size() > 0) { //If there are no players on, display to the first person && Bukkit.getOnlinePlayers().size() > 0) { //If there are no players on, display to the first person
lastError = System.nanoTime(); //I put the whole thing in the if to protect against race conditions lastError = System.nanoTime(); //I put the whole thing in the if to protect against race conditions
for (Player p : Bukkit.getOnlinePlayers()) for (Player p : Bukkit.getOnlinePlayers())
if (e.shouldSendTo(p)) if (e.shouldSendTo(ChromaGamerBase.getFromSender(p)))
p.sendMessage("[" + e.getChannel().DisplayName().get() + "] §cSome features in the message below might be unavailable due to an error."); p.sendMessage("[" + e.getChannel().displayName.get() + "] §cSome features in the message below might be unavailable due to an error.");
} }
ChatUtils.sendChatMessage(e, s -> "§c!§r" + s); ChatUtils.sendChatMessage(e);
TBMCCoreAPI.SendException("An error occured while processing a chat message!", ex); TBMCCoreAPI.SendException("An error occured while processing a chat message!", ex, PluginMain.Instance);
} }
} }
@ -96,9 +94,9 @@ public class PlayerListener implements Listener {
public void onNickChange(NickChangeEvent e) { public void onNickChange(NickChangeEvent e) {
String nick = e.getValue(); String nick = e.getValue();
if (nick == null) if (nick == null)
nicknames.inverse().remove(e.getAffected().getBase().getUniqueId()); nicknames.inverse().remove(e.getController().getBase().getUniqueId()); //EssentialsX has it swapped
else else
nicknames.inverse().forcePut(e.getAffected().getBase().getUniqueId(), ChatColor.stripColor(nick).toLowerCase()); nicknames.inverse().forcePut(e.getController().getBase().getUniqueId(), ChatColor.stripColor(nick).toLowerCase());
Bukkit.getScheduler().runTaskLater(PluginMain.Instance, () -> { Bukkit.getScheduler().runTaskLater(PluginMain.Instance, () -> {
TownColorComponent.updatePlayerColors(e.getAffected().getBase()); //Won't fire this event again TownColorComponent.updatePlayerColors(e.getAffected().getBase()); //Won't fire this event again

View file

@ -4,7 +4,7 @@ import lombok.val;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.dynmap.bukkit.DynmapPlugin; import org.dynmap.DynmapCommonAPI;
import org.dynmap.markers.MarkerAPI; import org.dynmap.markers.MarkerAPI;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
@ -35,7 +35,7 @@ public class DTBridge {
Constructor<?> c = cl.getDeclaredConstructor(FileConfiguration.class, String.class, MarkerAPI.class); Constructor<?> c = cl.getDeclaredConstructor(FileConfiguration.class, String.class, MarkerAPI.class);
c.setAccessible(true); c.setAccessible(true);
style = c.newInstance(dtp.getConfig(), "custstyle." + townname, style = c.newInstance(dtp.getConfig(), "custstyle." + townname,
((DynmapPlugin) Bukkit.getPluginManager().getPlugin("dynmap")).getMarkerAPI()); ((DynmapCommonAPI) Bukkit.getPluginManager().getPlugin("dynmap")).getMarkerAPI());
map.put(townname, style); map.put(townname, style);
} }
set(cl, style, "fillcolor", fillcolor); set(cl, style, "fillcolor", fillcolor);

View file

@ -1,18 +1,14 @@
name: Chroma-Chat name: Chroma-Chat
main: buttondevteam.chat.PluginMain main: buttondevteam.chat.PluginMain
version: '4.0' version: '${noprefix.version}'
commands: commands:
u: u:
description: Auto-flair system. Accept or ignore flair. description: The main command for Chroma-Chat.
ooc:
description: Send message Out-of-Character.
alias: nrp
unlol: unlol:
description: Unlaugh the last laugh. description: Unlaugh the last laugh.
alias: unlaugh alias: unlaugh
mwiki: mwiki:
description: Search the wiki. description: Search the wiki.
dontrunthiscmd: null
tableflip: tableflip:
description: Flip a table. description: Flip a table.
unflip: unflip:
@ -30,15 +26,17 @@ commands:
description: Lenny face. description: Lenny face.
ftop: ftop:
description: Top respect. description: Top respect.
me:
description: Me command with Chroma support.
author: NorbiPeti author: NorbiPeti
depend: depend:
- Essentials - Essentials
- Vault - Vault
- ChromaCore - Chroma-Core
soft-depend: softdepend:
- Minigames - Dynmap-Towny
- Dynmap-Towny - Towny
- Towny - dynmap
permissions: permissions:
tbmc.badge.gold: tbmc.badge.gold:
description: Gives a patron badge. description: Gives a patron badge.
@ -46,3 +44,4 @@ permissions:
tbmc.badge.diamond: tbmc.badge.diamond:
description: Gives a cool patron badge. description: Gives a cool patron badge.
default: false default: false
api-version: '1.13'

View file

@ -1,103 +1,129 @@
package buttondevteam.chat.components.formatter; package buttondevteam.chat.components.formatter;
import buttondevteam.chat.ChatPlayer;
import buttondevteam.chat.ChatUtils; import buttondevteam.chat.ChatUtils;
import buttondevteam.chat.ObjectTestRunner; import buttondevteam.chat.ObjectTestRunner;
import buttondevteam.chat.ObjectTestRunner.Objects; import buttondevteam.chat.ObjectTestRunner.Objects;
import buttondevteam.chat.PluginMain; import buttondevteam.chat.PluginMain;
import buttondevteam.chat.commands.ucmds.admin.DebugCommand; import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
import buttondevteam.chat.components.formatter.formatting.*; import buttondevteam.chat.components.formatter.formatting.ChatFormatter;
import buttondevteam.chat.components.formatter.formatting.TellrawEvent.ClickAction; import buttondevteam.chat.components.formatter.formatting.FormatSettings;
import buttondevteam.chat.components.formatter.formatting.TellrawEvent.HoverAction; import buttondevteam.chat.components.formatter.formatting.MatchProviderBase;
import buttondevteam.core.TestPrepare; import buttondevteam.core.MainPlugin;
import buttondevteam.core.component.channel.Channel; import buttondevteam.core.component.channel.Channel;
import buttondevteam.lib.chat.Color; import buttondevteam.lib.player.ChromaGamerBase;
import net.milkbowl.vault.permission.Permission; import buttondevteam.lib.test.TestPermissions;
import org.bukkit.command.CommandSender; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mockito;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
import java.util.function.Function;
import static be.seeseemelk.mockbukkit.MockBukkit.load;
import static be.seeseemelk.mockbukkit.MockBukkit.mock;
import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.event.ClickEvent.Action.OPEN_URL;
import static net.kyori.adventure.text.event.ClickEvent.clickEvent;
import static net.kyori.adventure.text.event.HoverEvent.Action.SHOW_TEXT;
import static net.kyori.adventure.text.event.HoverEvent.hoverEvent;
import static net.kyori.adventure.text.format.NamedTextColor.*;
import static net.kyori.adventure.text.format.TextDecoration.*;
@RunWith(ObjectTestRunner.class) @RunWith(ObjectTestRunner.class)
public class ChatFormatIT { public class ChatFormatIT {
@Objects @Objects
public static List<Object> data() { public static List<Object> data() {
TestPrepare.PrepareServer(); mock();
final CommandSender sender = Mockito.mock(CommandSender.class); load(MainPlugin.class, true);
var sender = ChromaGamerBase.getUser(UUID.randomUUID().toString(), ChatPlayer.class);
DebugCommand.DebugMode = true; DebugCommand.DebugMode = true;
PluginMain.permission = Mockito.mock(Permission.class); PluginMain.permission = new TestPermissions();
List<Object> list = new ArrayList<>(); List<Object> list = new ArrayList<>();
list.add(new ChatFormatIT(sender, "*test*", new TellrawPart("test").setItalic(true).setColor(Color.White))); list.add(new ChatFormatIT(sender, "*test*", text("test").decorate(ITALIC).color(WHITE)));
list.add(new ChatFormatIT(sender, "**test**", new TellrawPart("test").setBold(true).setColor(Color.White))); list.add(new ChatFormatIT(sender, "**test**", text("test").decorate(BOLD).color(WHITE)));
list.add(new ChatFormatIT(sender, "***test***", list.add(new ChatFormatIT(sender, "***test***", text("test").decorate(BOLD, ITALIC).color(WHITE)));
new TellrawPart("test").setBold(true).setItalic(true).setColor(Color.White))); list.add(new ChatFormatIT(sender, "***__test__***", text("test").decorate(BOLD, ITALIC, UNDERLINED).color(WHITE)));
list.add(new ChatFormatIT(sender, "***__test__***", list.add(new ChatFormatIT(sender, "***__~~test~~__***", text("test").decorate(BOLD, ITALIC, UNDERLINED, STRIKETHROUGH).color(WHITE)));
new TellrawPart("test").setBold(true).setItalic(true).setUnderlined(true).setColor(Color.White))); list.add(new ChatFormatIT(sender, "¯\\\\\\_(ツ)\\_/¯", text("¯\\_(ツ)_/¯").color(WHITE)));
list.add(new ChatFormatIT(sender, "***__~~test~~__***", new TellrawPart("test").setBold(true).setItalic(true)
.setUnderlined(true).setStrikethrough(true).setColor(Color.White)));
list.add(new ChatFormatIT(sender, "¯\\\\\\_(ツ)\\_/¯", new TellrawPart("¯\\_(ツ)_/¯").setColor(Color.White)));
list.add(new ChatFormatIT(sender, "https://google.hu/", list.add(new ChatFormatIT(sender, "https://google.hu/",
new TellrawPart("https://google.hu/").setColor(Color.White).setUnderlined(true) text("https://google.hu/").color(WHITE).decorate(UNDERLINED)
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT, .hoverEvent(hoverEvent(SHOW_TEXT, text("Click to open").color(BLUE)))
new TellrawPart("Click to open").setColor(Color.Blue))) .clickEvent(clickEvent(OPEN_URL, "https://google.hu/"))));
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://google.hu/")))); list.add(new ChatFormatIT(sender, "*test", text("*test").color(WHITE)));
list.add(new ChatFormatIT(sender, "*test", new TellrawPart("*test").setColor(Color.White))); list.add(new ChatFormatIT(sender, "**test*", text("**test*").color(WHITE)));
list.add(new ChatFormatIT(sender, "**test*", new TellrawPart("**test*").setColor(Color.White))); list.add(new ChatFormatIT(sender, "***test", text("***test").color(WHITE)));
list.add(new ChatFormatIT(sender, "***test", new TellrawPart("***test").setColor(Color.White))); list.add(new ChatFormatIT(sender, "Koiiev", text("§bKoiiev§r").color(AQUA)));
list.add(new ChatFormatIT(sender, "Koiiev", new TellrawPart("§bKoiiev§r").setColor(Color.Aqua))); list.add(new ChatFormatIT(sender, "norbipeti", text("§bNorbiPeti§r").color(AQUA)));
list.add(new ChatFormatIT(sender, "norbipeti", new TellrawPart("§bNorbiPeti§r").setColor(Color.Aqua))); list.add(new ChatFormatIT(sender, "Arsen_Derby_FTW", text("§bArsen_Derby_FTW§r").color(AQUA)));
list.add(new ChatFormatIT(sender, "Arsen_Derby_FTW", new TellrawPart("§bArsen_Derby_FTW§r").setColor(Color.Aqua))); list.add(new ChatFormatIT(sender, "carrot_lynx", text("§bcarrot_lynx§r").color(AQUA)));
list.add(new ChatFormatIT(sender, "carrot_lynx", new TellrawPart("§bcarrot_lynx§r").setColor(Color.Aqua))); list.add(new ChatFormatIT(sender, "*carrot_lynx*", text("§bcarrot_lynx§r").decorate(ITALIC).color(AQUA)));
list.add(new ChatFormatIT(sender, "*carrot_lynx*", new TellrawPart("§bcarrot_lynx§r").setItalic(true).setColor(Color.Aqua))); list.add(new ChatFormatIT(sender, "https://norbipeti.github.io/", text("https://norbipeti.github.io/")
list.add(new ChatFormatIT(sender, "https://norbipeti.github.io/", new TellrawPart("https://norbipeti.github.io/") .color(WHITE).decorate(UNDERLINED)
.setColor(Color.White).setUnderlined(true) .hoverEvent(hoverEvent(SHOW_TEXT, text("Click to open").color(BLUE)))
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT, .clickEvent(clickEvent(OPEN_URL, "https://norbipeti.github.io/"))));
new TellrawPart("Click to open").setColor(Color.Blue))) list.add(new ChatFormatIT(sender, "*https://norbipeti.github.io/ heh*", text("https://norbipeti.github.io/").decorate(ITALIC).decorate(UNDERLINED)
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/")))); .hoverEvent(hoverEvent(SHOW_TEXT, text("Click to open").color(BLUE)))
list.add(new ChatFormatIT(sender, "*https://norbipeti.github.io/ heh*", new TellrawPart("https://norbipeti.github.io/").setItalic(true).setUnderlined(true) .clickEvent(clickEvent(OPEN_URL, "https://norbipeti.github.io/")).color(WHITE), text(" heh").decorate(ITALIC).color(WHITE)));
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT, list.add(new ChatFormatIT(sender, "*test _test_ test*", text("test test test").decorate(ITALIC).color(WHITE)));
new TellrawPart("Click to open").setColor(Color.Blue))) list.add(new ChatFormatIT(sender, "*test __test__ test*", text("test ").decorate(ITALIC).color(WHITE),
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/")).setColor(Color.White), new TellrawPart(" heh").setItalic(true).setColor(Color.White))); text("test").decorate(ITALIC).decorate(UNDERLINED).color(WHITE), text(" test").decorate(ITALIC).color(WHITE)));
list.add(new ChatFormatIT(sender, "*test _test_ test*", new TellrawPart("test test test").setItalic(true).setColor(Color.White))); list.add(new ChatFormatIT(sender, "**test __test__ test**", text("test ").decorate(BOLD).color(WHITE),
list.add(new ChatFormatIT(sender, "*test __test__ test*", new TellrawPart("test ").setItalic(true).setColor(Color.White), text("test").decorate(BOLD).decorate(UNDERLINED).color(WHITE), text(" test").decorate(BOLD).color(WHITE)));
new TellrawPart("test").setItalic(true).setUnderlined(true).setColor(Color.White), new TellrawPart(" test").setItalic(true).setColor(Color.White))); list.add(new ChatFormatIT(sender, "**test _test_ test**", text("test ").decorate(BOLD).color(WHITE),
list.add(new ChatFormatIT(sender, "**test __test__ test**", new TellrawPart("test ").setBold(true).setColor(Color.White), text("test").decorate(ITALIC).decorate(BOLD).color(WHITE), text(" test").decorate(BOLD).color(WHITE)));
new TellrawPart("test").setBold(true).setUnderlined(true).setColor(Color.White), new TellrawPart(" test").setBold(true).setColor(Color.White))); list.add(new ChatFormatIT(sender, "https://norbipeti.github.io/test?test&test#test", text("https://norbipeti.github.io/test?test&test#test")
list.add(new ChatFormatIT(sender, "**test _test_ test**", new TellrawPart("test ").setBold(true).setColor(Color.White), .color(WHITE).decorate(UNDERLINED)
new TellrawPart("test").setItalic(true).setBold(true).setColor(Color.White), new TellrawPart(" test").setBold(true).setColor(Color.White))); .hoverEvent(hoverEvent(SHOW_TEXT, text("Click to open").color(BLUE)))
list.add(new ChatFormatIT(sender, "https://norbipeti.github.io/test?test&test#test", new TellrawPart("https://norbipeti.github.io/test?test&test#test") .clickEvent(clickEvent(OPEN_URL, "https://norbipeti.github.io/test?test&test#test"))));
.setColor(Color.White).setUnderlined(true) list.add(new ChatFormatIT(sender, "[hmm](https://norbipeti.github.io/test)", text("hmm")
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT, .color(WHITE).decorate(UNDERLINED)
new TellrawPart("Click to open").setColor(Color.Blue))) .hoverEvent(hoverEvent(SHOW_TEXT, text("Click to open").color(BLUE)))
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/test?test&test#test")))); .clickEvent(clickEvent(OPEN_URL, "https://norbipeti.github.io/test"))));
list.add(new ChatFormatIT(sender, "[hmm](https://norbipeti.github.io/test)", new TellrawPart("hmm") var space = text(" ").color(WHITE);
.setColor(Color.White).setUnderlined(true) list.add(new ChatFormatIT(sender, "A rainbow text for testing. O", text("A").color(RED),
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT, space, text("rainbow").color(GOLD), space, text("text").color(YELLOW),
new TellrawPart("Click to open").setColor(Color.Blue))) space, text("for").color(GREEN), space, text("testing.").color(BLUE),
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/test")))); space, text("O").color(DARK_PURPLE)).setRainbowMode());
TellrawPart space = new TellrawPart(" ").setColor(Color.White); list.add(new ChatFormatIT(sender, "***test*** test", text("test").color(WHITE)
list.add(new ChatFormatIT(sender, "A rainbow text for testing. O", new TellrawPart("A").setColor(Color.Red), .decorate(ITALIC).decorate(BOLD), text(" test").color(WHITE)));
space, new TellrawPart("rainbow").setColor(Color.Gold), space, new TellrawPart("text").setColor(Color.Yellow), list.add(new ChatFormatIT(sender, ">test message\nheh", text(">test message\nheh").color(GREEN)));
space, new TellrawPart("for").setColor(Color.Green), space, new TellrawPart("testing.").setColor(Color.Blue), list.add(new ChatFormatIT(sender, "[here's a link]()", text("[here's a link]()").color(WHITE)));
space, new TellrawPart("O").setColor(Color.DarkPurple)).setRainbowMode()); list.add(new ChatFormatIT(sender, "[](fakelink)", text("[](fakelink)").color(WHITE)));
list.add(new ChatFormatIT(sender, "||this is a spoiler||", text("this is a spoiler").color(WHITE)
.decorate(OBFUSCATED).hoverEvent(hoverEvent(SHOW_TEXT, text("this is a spoiler")))));
Function<String, TextComponent> whiteBoldItalic = text -> text(text).color(WHITE).decorate(BOLD).decorate(ITALIC);
list.add(new ChatFormatIT(sender, "***some complicated ||test message|| with [links](https://chromagaming.figytuna.com) and other __greatness__ by NorbiPeti***",
whiteBoldItalic.apply("some complicated "),
whiteBoldItalic.apply("test message").decorate(OBFUSCATED).hoverEvent(hoverEvent(SHOW_TEXT, text("test message"))),
whiteBoldItalic.apply(" with "),
whiteBoldItalic.apply("links").clickEvent(clickEvent(OPEN_URL, "https://chromagaming.figytuna.com"))
.decorate(UNDERLINED).hoverEvent(hoverEvent(SHOW_TEXT, text("Click to open").color(BLUE))),
whiteBoldItalic.apply(" and other "),
whiteBoldItalic.apply("greatness").decorate(UNDERLINED),
whiteBoldItalic.apply(" by "),
whiteBoldItalic.apply("§bNorbiPeti§r").color(AQUA))); //§b: flair color
list.add(new ChatFormatIT(sender, "hey @console", text("hey ").color(WHITE),
text("@console").color(AQUA)));
return list; return list;
} }
private final CommandSender sender; private final ChromaGamerBase sender;
private final String message; private final String message;
private final TellrawPart[] extras; private final Component[] extras;
private boolean rainbowMode; private boolean rainbowMode;
public ChatFormatIT(CommandSender sender, String message, TellrawPart... expectedextras) { public ChatFormatIT(ChromaGamerBase sender, String message, Component... expectedExtras) {
this.sender = sender; this.sender = sender;
this.message = message; this.message = message;
this.extras = expectedextras; this.extras = expectedExtras;
} }
private ChatFormatIT setRainbowMode() { private ChatFormatIT setRainbowMode() {
@ -107,18 +133,16 @@ public class ChatFormatIT {
@Test @Test
public void testMessage() { public void testMessage() {
ArrayList<MatchProviderBase> cfs = ChatProcessing.addFormatters(p -> true, null);
final String chid = ChatProcessing.getChannelID(Channel.GlobalChat, ChatUtils.MCORIGIN);
if (rainbowMode)
ChatProcessing.createRPC(Color.White, cfs);
final TellrawPart tp = ChatProcessing.createTellraw(sender, message, null, null, null, chid, ChatUtils.MCORIGIN);
ChatFormatter.Combine(cfs, message, tp, null, FormatSettings.builder().color(Color.White).build());
System.out.println("Testing: " + message); System.out.println("Testing: " + message);
// System.out.println(ChatProcessing.toJson(tp)); ArrayList<MatchProviderBase> cfs = ChatProcessing.addFormatters(p -> true, null);
final TellrawPart expectedtp = ChatProcessing.createTellraw(sender, message, null, null, null, chid, ChatUtils.MCORIGIN); final String chid = ChatProcessing.getChannelID(Channel.globalChat, ChatUtils.MCORIGIN);
// System.out.println("Raw: " + ChatProcessing.toJson(expectedtp)); if (rainbowMode)
for (TellrawPart extra : extras) ChatProcessing.createRPC(WHITE, cfs);
expectedtp.addExtra(extra); final TextComponent.Builder tp = ChatProcessing.createEmptyMessageLine(sender, message, null, chid, ChatUtils.MCORIGIN);
Assert.assertEquals(ChatProcessing.toJson(expectedtp), ChatProcessing.toJson(tp)); ChatFormatter.Combine(cfs, message, tp, null, FormatSettings.builder().color(WHITE).build());
final TextComponent.Builder expectedtp = ChatProcessing.createEmptyMessageLine(sender, message, null, chid, ChatUtils.MCORIGIN);
for (Component extra : extras)
expectedtp.append(extra);
Assert.assertEquals(expectedtp.build(), tp.build());
} }
} }