Merge branch 'dev'
# Conflicts: # .idea/ButtonChat.iml
This commit is contained in:
commit
f3ec9e7870
26 changed files with 751 additions and 763 deletions
445
.gitignore
vendored
445
.gitignore
vendored
|
@ -1,224 +1,221 @@
|
||||||
#################
|
#################
|
||||||
## Eclipse
|
## Eclipse
|
||||||
#################
|
#################
|
||||||
|
|
||||||
*.pydevproject
|
*.pydevproject
|
||||||
.metadata/
|
.metadata/
|
||||||
bin/
|
bin/
|
||||||
tmp/
|
tmp/
|
||||||
*.tmp
|
*.tmp
|
||||||
*.bak
|
*.bak
|
||||||
*.swp
|
*.swp
|
||||||
*~.nib
|
*~.nib
|
||||||
local.properties
|
local.properties
|
||||||
.classpath
|
.classpath
|
||||||
.settings/
|
.settings/
|
||||||
.loadpath
|
.loadpath
|
||||||
target/
|
target/
|
||||||
.project
|
.project
|
||||||
|
|
||||||
# External tool builders
|
# External tool builders
|
||||||
.externalToolBuilders/
|
.externalToolBuilders/
|
||||||
|
|
||||||
# Locally stored "Eclipse launch configurations"
|
# Locally stored "Eclipse launch configurations"
|
||||||
*.launch
|
*.launch
|
||||||
|
|
||||||
# CDT-specific
|
# CDT-specific
|
||||||
.cproject
|
.cproject
|
||||||
|
|
||||||
# PDT-specific
|
# PDT-specific
|
||||||
.buildpath
|
.buildpath
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
## Visual Studio
|
## Visual Studio
|
||||||
#################
|
#################
|
||||||
|
|
||||||
## Ignore Visual Studio temporary files, build results, and
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
## files generated by popular Visual Studio add-ons.
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
# User-specific files
|
# User-specific files
|
||||||
*.suo
|
*.suo
|
||||||
*.user
|
*.user
|
||||||
*.sln.docstates
|
*.sln.docstates
|
||||||
|
|
||||||
# Build results
|
# Build results
|
||||||
|
|
||||||
[Dd]ebug/
|
[Dd]ebug/
|
||||||
[Rr]elease/
|
[Rr]elease/
|
||||||
x64/
|
x64/
|
||||||
build/
|
build/
|
||||||
[Bb]in/
|
[Bb]in/
|
||||||
[Oo]bj/
|
[Oo]bj/
|
||||||
|
|
||||||
# MSTest test Results
|
# MSTest test Results
|
||||||
[Tt]est[Rr]esult*/
|
[Tt]est[Rr]esult*/
|
||||||
[Bb]uild[Ll]og.*
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
*_i.c
|
*_i.c
|
||||||
*_p.c
|
*_p.c
|
||||||
*.ilk
|
*.ilk
|
||||||
*.meta
|
*.meta
|
||||||
*.obj
|
*.obj
|
||||||
*.pch
|
*.pch
|
||||||
*.pdb
|
*.pdb
|
||||||
*.pgc
|
*.pgc
|
||||||
*.pgd
|
*.pgd
|
||||||
*.rsp
|
*.rsp
|
||||||
*.sbr
|
*.sbr
|
||||||
*.tlb
|
*.tlb
|
||||||
*.tli
|
*.tli
|
||||||
*.tlh
|
*.tlh
|
||||||
*.tmp
|
*.tmp_proj
|
||||||
*.tmp_proj
|
*.log
|
||||||
*.log
|
*.vspscc
|
||||||
*.vspscc
|
*.vssscc
|
||||||
*.vssscc
|
.builds
|
||||||
.builds
|
*.pidb
|
||||||
*.pidb
|
*.scc
|
||||||
*.log
|
|
||||||
*.scc
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
# Visual C++ cache files
|
*.aps
|
||||||
ipch/
|
*.ncb
|
||||||
*.aps
|
*.opensdf
|
||||||
*.ncb
|
*.sdf
|
||||||
*.opensdf
|
*.cachefile
|
||||||
*.sdf
|
|
||||||
*.cachefile
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
# Visual Studio profiler
|
*.vsp
|
||||||
*.psess
|
*.vspx
|
||||||
*.vsp
|
|
||||||
*.vspx
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
# Guidance Automation Toolkit
|
|
||||||
*.gpState
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
# ReSharper is a .NET coding add-in
|
*.[Rr]e[Ss]harper
|
||||||
_ReSharper*/
|
|
||||||
*.[Rr]e[Ss]harper
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
# TeamCity is a build add-in
|
|
||||||
_TeamCity*
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
# DotCover is a Code Coverage Tool
|
|
||||||
*.dotCover
|
# NCrunch
|
||||||
|
*.ncrunch*
|
||||||
# NCrunch
|
.*crunch*.local.xml
|
||||||
*.ncrunch*
|
|
||||||
.*crunch*.local.xml
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
# Installshield output folder
|
|
||||||
[Ee]xpress/
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
# DocProject is a documentation generator add-in
|
DocProject/Help/*.HxT
|
||||||
DocProject/buildhelp/
|
DocProject/Help/*.HxC
|
||||||
DocProject/Help/*.HxT
|
DocProject/Help/*.hhc
|
||||||
DocProject/Help/*.HxC
|
DocProject/Help/*.hhk
|
||||||
DocProject/Help/*.hhc
|
DocProject/Help/*.hhp
|
||||||
DocProject/Help/*.hhk
|
DocProject/Help/Html2
|
||||||
DocProject/Help/*.hhp
|
DocProject/Help/html
|
||||||
DocProject/Help/Html2
|
|
||||||
DocProject/Help/html
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
# Click-Once directory
|
|
||||||
publish/
|
# Publish Web Output
|
||||||
|
*.Publish.xml
|
||||||
# Publish Web Output
|
*.pubxml
|
||||||
*.Publish.xml
|
*.publishproj
|
||||||
*.pubxml
|
|
||||||
*.publishproj
|
# NuGet Packages Directory
|
||||||
|
## TO!DO: If you have NuGet Package Restore enabled, uncomment the next line
|
||||||
# NuGet Packages Directory
|
#packages/
|
||||||
## TO!DO: If you have NuGet Package Restore enabled, uncomment the next line
|
|
||||||
#packages/
|
# Windows Azure Build Output
|
||||||
|
csx
|
||||||
# Windows Azure Build Output
|
*.build.csdef
|
||||||
csx
|
|
||||||
*.build.csdef
|
# Windows Store app package directory
|
||||||
|
AppPackages/
|
||||||
# Windows Store app package directory
|
|
||||||
AppPackages/
|
# Others
|
||||||
|
sql/
|
||||||
# Others
|
*.Cache
|
||||||
sql/
|
ClientBin/
|
||||||
*.Cache
|
[Ss]tyle[Cc]op.*
|
||||||
ClientBin/
|
~$*
|
||||||
[Ss]tyle[Cc]op.*
|
*~
|
||||||
~$*
|
*.dbmdl
|
||||||
*~
|
*.[Pp]ublish.xml
|
||||||
*.dbmdl
|
*.pfx
|
||||||
*.[Pp]ublish.xml
|
*.publishsettings
|
||||||
*.pfx
|
|
||||||
*.publishsettings
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
# RIA/Silverlight projects
|
|
||||||
Generated_Code/
|
# Backup & report files from converting an old project file to a newer
|
||||||
|
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||||
# Backup & report files from converting an old project file to a newer
|
_UpgradeReport_Files/
|
||||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
Backup*/
|
||||||
_UpgradeReport_Files/
|
UpgradeLog*.XML
|
||||||
Backup*/
|
UpgradeLog*.htm
|
||||||
UpgradeLog*.XML
|
|
||||||
UpgradeLog*.htm
|
# SQL Server files
|
||||||
|
App_Data/*.mdf
|
||||||
# SQL Server files
|
App_Data/*.ldf
|
||||||
App_Data/*.mdf
|
|
||||||
App_Data/*.ldf
|
#############
|
||||||
|
## Windows detritus
|
||||||
#############
|
#############
|
||||||
## Windows detritus
|
|
||||||
#############
|
# Windows image file caches
|
||||||
|
Thumbs.db
|
||||||
# Windows image file caches
|
ehthumbs.db
|
||||||
Thumbs.db
|
|
||||||
ehthumbs.db
|
# Folder config file
|
||||||
|
Desktop.ini
|
||||||
# Folder config file
|
|
||||||
Desktop.ini
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
# Recycle Bin used on file shares
|
|
||||||
$RECYCLE.BIN/
|
# Mac crap
|
||||||
|
.DS_Store
|
||||||
# Mac crap
|
|
||||||
.DS_Store
|
|
||||||
|
#############
|
||||||
|
## Python
|
||||||
#############
|
#############
|
||||||
## Python
|
|
||||||
#############
|
*.py[cod]
|
||||||
|
|
||||||
*.py[cod]
|
# Packages
|
||||||
|
*.egg
|
||||||
# Packages
|
*.egg-info
|
||||||
*.egg
|
dist/
|
||||||
*.egg-info
|
eggs/
|
||||||
dist/
|
parts/
|
||||||
build/
|
var/
|
||||||
eggs/
|
sdist/
|
||||||
parts/
|
develop-eggs/
|
||||||
var/
|
.installed.cfg
|
||||||
sdist/
|
|
||||||
develop-eggs/
|
# Installer logs
|
||||||
.installed.cfg
|
pip-log.txt
|
||||||
|
|
||||||
# Installer logs
|
# Unit test / coverage reports
|
||||||
pip-log.txt
|
.coverage
|
||||||
|
.tox
|
||||||
# Unit test / coverage reports
|
|
||||||
.coverage
|
#Translations
|
||||||
.tox
|
*.mo
|
||||||
|
|
||||||
#Translations
|
#Mr Developer
|
||||||
*.mo
|
.mr.developer.cfg
|
||||||
|
.metadata/*
|
||||||
#Mr Developer
|
TheButtonAutoFlair/out/artifacts/Autoflair/Autoflair.jar
|
||||||
.mr.developer.cfg
|
*.iml
|
||||||
.metadata/*
|
*.name
|
||||||
TheButtonAutoFlair/out/artifacts/Autoflair/Autoflair.jar
|
.idea/compiler.xml
|
||||||
#*.iml
|
*.xml
|
||||||
*.name
|
/.apt_generated/
|
||||||
.idea/compiler.xml
|
|
||||||
*.xml
|
|
||||||
/.apt_generated/
|
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_11">
|
|
||||||
<output url="file://$MODULE_DIR$/target/classes" />
|
|
||||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/target/generated-sources/annotations" isTestSource="false" generated="true" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
<orderEntry type="library" name="Maven: org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.6" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.google.guava:guava:21.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.19" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: net.md-5:bungeecord-chat:1.12-SNAPSHOT" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.github.TBMCPlugins.ChromaCore:Chroma-Core:master-59aa13cd74-1" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: net.sourceforge.htmlcleaner:htmlcleaner:2.16" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.jdom:jdom2:2.0.5" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.reflections:reflections:0.9.10" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.javassist:javassist:3.19.0-GA" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.google.code.findbugs:annotations:2.0.1" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.ess3:EssentialsX:2.17.1" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: io.papermc:paperlib:1.0.2" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.ess3:NMSProvider:2.17.1" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.ess3:UpdatedMetaProvider:2.17.1" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.ess3:1_8_R1Provider:2.17.1" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.ess3:1_8_R2Provider:2.17.1" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.ess3:LegacyProvider:2.17.1" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.ess3:ReflectionProvider:2.17.1" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.ess3:FlattenedProvider:2.17.1" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.palmergames.bukkit.towny:Towny:0.95.2.0" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.github.milkbowl:VaultAPI:master-89c00e1cb8-1" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.projectlombok:lombok:1.18.10" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.spigotmc:spigot:1.12.2-R0.1-SNAPSHOT" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.github.webbukkit:Dynmap-Towny:master-0.60-g924051d-7" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.github.webbukkit:Dynmap:v2.5" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.nijikokun.bukkit:Permissions:3.1.6" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.bukkit:bukkit:1.7.10-R0.1-SNAPSHOT" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: ru.tehkode:PermissionsEx:1.19.1" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: de.bananaco:bPermissions:2.9.1" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.platymuus.bukkit.permissions:PermissionsBukkit:1.6" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.anjocaido:EssentialsGroupManager:2.10.1" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.apache.logging.log4j:log4j-core:2.8.1" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.apache.logging.log4j:log4j-api:2.8.1" level="project" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
16
.travis.yml
16
.travis.yml
|
@ -7,21 +7,17 @@ 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
|
- oraclejdk8
|
||||||
sudo: true
|
sudo: true
|
||||||
dist: trusty # Needed for Java 8, although we might not need Java 8
|
dist: trusty # Needed for Java 8, although we might not need Java 8
|
||||||
deploy:
|
deploy:
|
||||||
# deploy develop to the staging environment
|
- provider: releases
|
||||||
- provider: script
|
api_key:
|
||||||
script: chmod +x deploy.sh && sh deploy.sh staging
|
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'
|
||||||
on:
|
on:
|
||||||
branch: dev
|
tags: true
|
||||||
skip_cleanup: true
|
|
||||||
# deploy master to production
|
|
||||||
- provider: script
|
|
||||||
script: chmod +x deploy.sh && sh deploy.sh production
|
|
||||||
on:
|
|
||||||
branch: master
|
|
||||||
skip_cleanup: true
|
skip_cleanup: true
|
||||||
|
|
1
Mvn.txt
1
Mvn.txt
|
@ -1 +0,0 @@
|
||||||
apache-maven-3.2.5/bin/mvn install:install-file -Dfile=Towny.jar -DgroupId=com.palmergames -DartifactId=Towny -Dversion=0.90.0.0 -Dpackaging=jar
|
|
36
ci/settings.xml
Normal file
36
ci/settings.xml
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<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>
|
10
deploy.sh
10
deploy.sh
|
@ -1,10 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
FILENAME=$(find target/ -maxdepth 1 ! -name '*original*' -name '*.jar')
|
|
||||||
echo Found file: $FILENAME
|
|
||||||
|
|
||||||
if [ $1 = 'production' ]; then
|
|
||||||
echo Production mode
|
|
||||||
echo $UPLOAD_KEY > upload_key
|
|
||||||
chmod 400 upload_key
|
|
||||||
yes | scp -B -i upload_key -o StrictHostKeyChecking=no $FILENAME travis@server.figytuna.com:/minecraft/main/TBMC/pluginupdates
|
|
||||||
fi
|
|
|
@ -69,13 +69,13 @@ public class PluginMain extends ButtonPlugin { // Translated to Java: 2015.07.15
|
||||||
Component.registerComponent(this, new FunComponent());
|
Component.registerComponent(this, new FunComponent());
|
||||||
Component.registerComponent(this, new AppendTextComponent());
|
Component.registerComponent(this, new AppendTextComponent());
|
||||||
Component.registerComponent(this, new FormatterComponent());
|
Component.registerComponent(this, new FormatterComponent());
|
||||||
getCommand2MC().registerCommand(new DebugCommand());
|
registerCommand(new DebugCommand());
|
||||||
getCommand2MC().registerCommand(new HelpCommand());
|
registerCommand(new HelpCommand());
|
||||||
getCommand2MC().registerCommand(new HistoryCommand());
|
registerCommand(new HistoryCommand());
|
||||||
getCommand2MC().registerCommand(new InfoCommand());
|
registerCommand(new InfoCommand());
|
||||||
getCommand2MC().registerCommand(new MWikiCommand());
|
registerCommand(new MWikiCommand());
|
||||||
getCommand2MC().registerCommand(new ReloadCommand());
|
registerCommand(new ReloadCommand());
|
||||||
getCommand2MC().registerCommand(new SnapCommand());
|
registerCommand(new SnapCommand());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Essentials essentials = null;
|
public static Essentials essentials = null;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package buttondevteam.chat.components.chatonly;
|
package buttondevteam.chat.components.chatonly;
|
||||||
|
|
||||||
import buttondevteam.chat.ChatPlayer;
|
import buttondevteam.chat.ChatPlayer;
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
import buttondevteam.chat.components.formatter.formatting.TellrawEvent;
|
import buttondevteam.chat.components.formatter.formatting.TellrawEvent;
|
||||||
import buttondevteam.chat.components.formatter.formatting.TellrawPart;
|
import buttondevteam.chat.components.formatter.formatting.TellrawPart;
|
||||||
import buttondevteam.core.ComponentManager;
|
import buttondevteam.core.ComponentManager;
|
||||||
|
@ -20,7 +21,7 @@ import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
@ComponentMetadata(enabledByDefault = false)
|
@ComponentMetadata(enabledByDefault = false)
|
||||||
public class ChatOnlyComponent extends Component implements Listener {
|
public class ChatOnlyComponent extends Component<PluginMain> implements Listener {
|
||||||
@Override
|
@Override
|
||||||
protected void enable() {
|
protected void enable() {
|
||||||
registerListener(this);
|
registerListener(this);
|
||||||
|
|
|
@ -23,7 +23,7 @@ public class SetFlairCommand extends AdminCommandBase {
|
||||||
sender.sendMessage("§cPlayer not found.&r");
|
sender.sendMessage("§cPlayer not found.&r");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
short ft = 0x00;
|
short ft;
|
||||||
if (flairtime.equalsIgnoreCase("non-presser"))
|
if (flairtime.equalsIgnoreCase("non-presser"))
|
||||||
ft = ChatPlayer.FlairTimeNonPresser;
|
ft = ChatPlayer.FlairTimeNonPresser;
|
||||||
else if (flairtime.equalsIgnoreCase("cant-press"))
|
else if (flairtime.equalsIgnoreCase("cant-press"))
|
||||||
|
|
|
@ -6,10 +6,7 @@ import buttondevteam.chat.PluginMain;
|
||||||
import buttondevteam.chat.VanillaUtils;
|
import buttondevteam.chat.VanillaUtils;
|
||||||
import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
|
import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
|
||||||
import buttondevteam.chat.components.chatonly.ChatOnlyComponent;
|
import buttondevteam.chat.components.chatonly.ChatOnlyComponent;
|
||||||
import buttondevteam.chat.components.formatter.formatting.ChatFormatter;
|
import buttondevteam.chat.components.formatter.formatting.*;
|
||||||
import buttondevteam.chat.components.formatter.formatting.TellrawEvent;
|
|
||||||
import buttondevteam.chat.components.formatter.formatting.TellrawPart;
|
|
||||||
import buttondevteam.chat.components.formatter.formatting.TellrawSerializer;
|
|
||||||
import buttondevteam.chat.components.fun.FunComponent;
|
import buttondevteam.chat.components.fun.FunComponent;
|
||||||
import buttondevteam.chat.components.towny.TownyComponent;
|
import buttondevteam.chat.components.towny.TownyComponent;
|
||||||
import buttondevteam.chat.listener.PlayerListener;
|
import buttondevteam.chat.listener.PlayerListener;
|
||||||
|
@ -19,7 +16,6 @@ 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.Color;
|
||||||
import buttondevteam.lib.chat.Priority;
|
|
||||||
import buttondevteam.lib.chat.TellrawSerializableEnum;
|
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;
|
||||||
|
@ -43,73 +39,56 @@ import java.util.function.Predicate;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class ChatProcessing {
|
public class ChatProcessing {
|
||||||
private static final Pattern NULL_MENTION_PATTERN = Pattern.compile("null");
|
|
||||||
private static final Pattern CYAN_PATTERN = Pattern.compile("cyan");
|
|
||||||
private static final Pattern ESCAPE_PATTERN = Pattern.compile("\\\\");
|
|
||||||
private static final Pattern CONSOLE_PING_PATTERN = Pattern.compile("(?i)" + Pattern.quote("@console"));
|
|
||||||
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]+)?)");
|
||||||
public static final Pattern ENTIRE_MESSAGE_PATTERN = Pattern.compile(".+");
|
|
||||||
private static final Pattern UNDERLINED_PATTERN = Pattern.compile("__");
|
|
||||||
private static final Pattern ITALIC_PATTERN = Pattern.compile("\\*");
|
|
||||||
private static final Pattern ITALIC_PATTERN_2 = Pattern.compile("_");
|
|
||||||
private static final Pattern BOLD_PATTERN = Pattern.compile("\\*\\*");
|
|
||||||
private static final Pattern CODE_PATTERN = Pattern.compile("`");
|
|
||||||
private static final Pattern MASKED_LINK_PATTERN = Pattern.compile("\\[([^\\[\\]]+)]\\(([^()]+)\\)");
|
private static final Pattern MASKED_LINK_PATTERN = Pattern.compile("\\[([^\\[\\]]+)]\\(([^()]+)\\)");
|
||||||
private static final Pattern SOMEONE_PATTERN = Pattern.compile("@someone");
|
|
||||||
private static final Pattern STRIKETHROUGH_PATTERN = Pattern.compile("~~");
|
|
||||||
private static final Pattern SPOILER_PATTERN = Pattern.compile("\\|\\|");
|
|
||||||
private static final Color[] RainbowPresserColors = new Color[]{Color.Red, Color.Gold, Color.Yellow, Color.Green,
|
private static final Color[] RainbowPresserColors = new Color[]{Color.Red, Color.Gold, Color.Yellow, Color.Green,
|
||||||
Color.Blue, Color.DarkPurple};
|
Color.Blue, Color.DarkPurple};
|
||||||
private static final Pattern WORD_PATTERN = Pattern.compile("\\S+");
|
private static final Pattern WORD_PATTERN = Pattern.compile("\\S+");
|
||||||
private static boolean pingedconsole = false;
|
private static boolean pingedconsole = false;
|
||||||
|
|
||||||
public static final ChatFormatter ESCAPE_FORMATTER = ChatFormatter.builder("escape", ESCAPE_PATTERN).build();
|
private static ArrayList<MatchProviderBase> commonFormatters = Lists.newArrayList(
|
||||||
|
new RangeMatchProvider("bold", "**", FormatSettings.builder().bold(true).build()),
|
||||||
private static ArrayList<ChatFormatter> commonFormatters = Lists.newArrayList(
|
new RangeMatchProvider("italic", "*", FormatSettings.builder().italic(true).build()),
|
||||||
ChatFormatter.builder("bold", BOLD_PATTERN).bold(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range)
|
new RangeMatchProvider("underlined", "__", FormatSettings.builder().underlined(true).build()),
|
||||||
.priority(Priority.High).build(),
|
new RangeMatchProvider("italic2", "_", FormatSettings.builder().italic(true).build()),
|
||||||
ChatFormatter.builder("italic", ITALIC_PATTERN).italic(true).removeCharCount((short) 1).type(ChatFormatter.Type.Range).build(),
|
new RangeMatchProvider("strikethrough", "~~", FormatSettings.builder().strikethrough(true).build()),
|
||||||
ChatFormatter.builder("italic2", ITALIC_PATTERN_2).italic(true).removeCharCount((short) 1).type(ChatFormatter.Type.Range).build(),
|
new RangeMatchProvider("spoiler", "||", FormatSettings.builder().obfuscated(true)
|
||||||
ChatFormatter.builder("underlined", UNDERLINED_PATTERN).underlined(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range)
|
|
||||||
.build(),
|
|
||||||
ChatFormatter.builder("strikethrough", STRIKETHROUGH_PATTERN).strikethrough(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range)
|
|
||||||
.build(),
|
|
||||||
ChatFormatter.builder("spoiler", SPOILER_PATTERN).obfuscated(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range)
|
|
||||||
.onmatch((match, cf, fs) -> {
|
.onmatch((match, cf, fs) -> {
|
||||||
cf.setHoverText(match);
|
cf.setHoverText(match);
|
||||||
return match;
|
return match;
|
||||||
}).build(),
|
}).build()),
|
||||||
ESCAPE_FORMATTER, ChatFormatter.builder("nullMention", NULL_MENTION_PATTERN).color(Color.DarkRed).build(), // Properly added a bug as a feature
|
new StringMatchProvider("nullMention", FormatSettings.builder().color(Color.DarkRed).build(), true, "null"), // Properly added a bug as a feature
|
||||||
ChatFormatter.builder("consolePing", CONSOLE_PING_PATTERN).color(Color.Aqua).onmatch((match, builder, section) -> {
|
new StringMatchProvider("consolePing", FormatSettings.builder().color(Color.Aqua)
|
||||||
if (!pingedconsole) {
|
.onmatch((match, builder, section) -> {
|
||||||
System.out.print("\007");
|
if (!pingedconsole) {
|
||||||
pingedconsole = true; // Will set it to false in ProcessChat
|
System.out.print("\007");
|
||||||
}
|
pingedconsole = true; // Will set it to false in ProcessChat
|
||||||
return match;
|
}
|
||||||
}).priority(Priority.High).build(),
|
return "@console";
|
||||||
|
}).build(), true, "@console"),
|
||||||
|
|
||||||
ChatFormatter.builder("hashtag", HASHTAG_PATTERN).color(Color.Blue).openlink("https://twitter.com/hashtag/$1")
|
new StringMatchProvider("cyan", FormatSettings.builder().color(Color.Aqua).build(), true, "cyan"), // #55
|
||||||
.priority(Priority.High).build(),
|
new RangeMatchProvider("code", "`", FormatSettings.builder().color(Color.DarkGray).build()),
|
||||||
ChatFormatter.builder("cyan", CYAN_PATTERN).color(Color.Aqua).build(), // #55
|
new RegexMatchProvider("maskedLink", MASKED_LINK_PATTERN, FormatSettings.builder().underlined(true)
|
||||||
ChatFormatter.builder("code", CODE_PATTERN).color(Color.DarkGray).removeCharCount((short) 1).type(ChatFormatter.Type.Range)
|
.onmatch((match, builder, section) -> {
|
||||||
.build(),
|
String text, link;
|
||||||
ChatFormatter.builder("maskedLink", MASKED_LINK_PATTERN).underlined(true).onmatch((match, builder, section) -> {
|
if (section.Matches.size() < 2 || (text = section.Matches.get(0)).length() == 0 || (link = section.Matches.get(1)).length() == 0)
|
||||||
String text, link;
|
return "";
|
||||||
if (section.Matches.size() < 2 || (text = section.Matches.get(0)).length() == 0 || (link = section.Matches.get(1)).length() == 0)
|
builder.setOpenlink(link);
|
||||||
return "";
|
return text;
|
||||||
builder.setOpenlink(link);
|
}).build()),
|
||||||
return text;
|
new RegexMatchProvider("url", URL_PATTERN, FormatSettings.builder().underlined(true).openlink("$1").build()),
|
||||||
}).type(ChatFormatter.Type.Excluder).build(),
|
new RegexMatchProvider("hashtag", HASHTAG_PATTERN, FormatSettings.builder().color(Color.Blue).openlink("https://twitter.com/hashtag/$1").build()),
|
||||||
ChatFormatter.builder("url", URL_PATTERN).underlined(true).openlink("$1").type(ChatFormatter.Type.Excluder).build(),
|
new StringMatchProvider("someone", FormatSettings.builder().color(Color.Aqua)
|
||||||
ChatFormatter.builder("someone", SOMEONE_PATTERN).color(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());
|
||||||
var playerC = new Random().nextInt(players.size());
|
var playerC = new Random().nextInt(players.size());
|
||||||
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());
|
}).build(), true, "@someone"));
|
||||||
private static Gson gson = new GsonBuilder()
|
private static Gson gson = new GsonBuilder()
|
||||||
.registerTypeHierarchyAdapter(TellrawSerializableEnum.class, new TellrawSerializer.TwEnum())
|
.registerTypeHierarchyAdapter(TellrawSerializableEnum.class, new TellrawSerializer.TwEnum())
|
||||||
.registerTypeHierarchyAdapter(Collection.class, new TellrawSerializer.TwCollection())
|
.registerTypeHierarchyAdapter(Collection.class, new TellrawSerializer.TwCollection())
|
||||||
|
@ -164,20 +143,19 @@ public class ChatProcessing {
|
||||||
colormode = Color.Green;
|
colormode = Color.Green;
|
||||||
// If greentext, ignore channel or player colors
|
// If greentext, ignore channel or player colors
|
||||||
|
|
||||||
ArrayList<ChatFormatter> formatters;
|
ArrayList<MatchProviderBase> formatters;
|
||||||
if (component.allowFormatting().get()) {
|
if (component.allowFormatting().get()) {
|
||||||
formatters = addFormatters(colormode, e::shouldSendTo, component);
|
formatters = addFormatters(e::shouldSendTo, component);
|
||||||
if (colormode == channel.Color().get() && mp != null && mp.RainbowPresserColorMode) { // Only overwrite channel color
|
if (colormode == channel.Color().get() && mp != null && 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(ChatFormatter.builder("entireMessage", ENTIRE_MESSAGE_PATTERN)
|
formatters = Lists.newArrayList();
|
||||||
.color(Color.White).priority(Priority.Low).build()); //This formatter is necessary
|
|
||||||
|
|
||||||
TellrawPart json = createTellraw(sender, message, player, mp, e.getUser(), channelidentifier, e.getOrigin());
|
TellrawPart json = createTellraw(sender, message, player, mp, e.getUser(), channelidentifier, e.getOrigin());
|
||||||
long combinetime = System.nanoTime();
|
long combinetime = System.nanoTime();
|
||||||
ChatFormatter.Combine(formatters, message, json, component.getConfig());
|
ChatFormatter.Combine(formatters, message, json, component.getConfig(), FormatSettings.builder().color(colormode).build());
|
||||||
combinetime = System.nanoTime() - combinetime;
|
combinetime = System.nanoTime() - combinetime;
|
||||||
String jsonstr = toJson(json);
|
String jsonstr = toJson(json);
|
||||||
if (jsonstr.length() >= 32767) {
|
if (jsonstr.length() >= 32767) {
|
||||||
|
@ -222,12 +200,12 @@ public class ChatProcessing {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void createRPC(Color colormode, ArrayList<ChatFormatter> formatters) {
|
static void createRPC(Color colormode, ArrayList<MatchProviderBase> formatters) {
|
||||||
final AtomicInteger rpc = new AtomicInteger(0);
|
final AtomicInteger rpc = new AtomicInteger(0);
|
||||||
formatters.add(ChatFormatter.builder("rpc", WORD_PATTERN).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)]);
|
||||||
return match;
|
return match;
|
||||||
}).build());
|
}).build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toJson(TellrawPart json) {
|
public static String toJson(TellrawPart json) {
|
||||||
|
@ -273,43 +251,21 @@ public class ChatProcessing {
|
||||||
+ "]";
|
+ "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
static ArrayList<ChatFormatter> addFormatters(Color colormode, Predicate<Player> canSee, @Nullable FormatterComponent component) {
|
static ArrayList<MatchProviderBase> addFormatters(Predicate<Player> canSee, @Nullable FormatterComponent component) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
ArrayList<ChatFormatter> formatters = (ArrayList<ChatFormatter>) commonFormatters.clone();
|
ArrayList<MatchProviderBase> formatters = (ArrayList<MatchProviderBase>) commonFormatters.clone();
|
||||||
|
|
||||||
formatters.add(
|
|
||||||
ChatFormatter.builder("entireMessage", ENTIRE_MESSAGE_PATTERN).color(colormode).priority(Priority.Low).build());
|
|
||||||
|
|
||||||
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) || Bukkit.getVersion().equals("test")) {
|
||||||
StringBuilder namesb = new StringBuilder("(?i)(");
|
String[] names;
|
||||||
boolean addNameFormatter = false; //Needed because some names may be filtered out if they can't see the channel
|
|
||||||
if (nottest)
|
if (nottest)
|
||||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
names = Bukkit.getOnlinePlayers().stream().filter(canSee).map(CommandSender::getName).toArray(String[]::new);
|
||||||
if (canSee.test(p)) {
|
|
||||||
namesb.append(p.getName()).append("|");
|
|
||||||
addNameFormatter = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
for (String testPlayer : testPlayers)
|
names = new String[testPlayers.length];
|
||||||
namesb.append(testPlayer).append("|");
|
System.arraycopy(testPlayers, 0, names, 0, testPlayers.length);
|
||||||
addNameFormatter = true;
|
|
||||||
}
|
}
|
||||||
namesb.deleteCharAt(namesb.length() - 1);
|
String[] nicknames = Bukkit.getOnlinePlayers().stream().filter(canSee).map(Player::getUniqueId).map(PlayerListener.nicknames.inverse()::get)
|
||||||
namesb.append(")");
|
.filter(Objects::nonNull).toArray(String[]::new);
|
||||||
StringBuilder nicksb = new StringBuilder("(?i)(");
|
|
||||||
boolean addNickFormatter = false;
|
|
||||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
|
||||||
if (!canSee.test(p)) continue;
|
|
||||||
final String nick = PlayerListener.nicknames.inverse().get(p.getUniqueId());
|
|
||||||
if (nick != null) {
|
|
||||||
nicksb.append(nick).append("|");
|
|
||||||
addNickFormatter = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nicksb.deleteCharAt(nicksb.length() - 1);
|
|
||||||
nicksb.append(")");
|
|
||||||
|
|
||||||
Consumer<String> error = message -> {
|
Consumer<String> error = message -> {
|
||||||
if (PluginMain.Instance != null)
|
if (PluginMain.Instance != null)
|
||||||
|
@ -318,8 +274,8 @@ public class ChatProcessing {
|
||||||
System.out.println(message);
|
System.out.println(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (addNameFormatter)
|
if (names.length > 0) //Add as first so it handles special characters (_) - though the order of the different types are defined
|
||||||
formatters.add(ChatFormatter.builder("name", Pattern.compile(namesb.toString())).color(Color.Aqua)
|
formatters.add(0, new StringMatchProvider("name", FormatSettings.builder().color(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()
|
||||||
|
@ -334,10 +290,10 @@ public class ChatProcessing {
|
||||||
}
|
}
|
||||||
String color = String.format("§%x", (mpp.GetFlairColor() == 0x00 ? 0xb : mpp.GetFlairColor()));
|
String color = String.format("§%x", (mpp.GetFlairColor() == 0x00 ? 0xb : mpp.GetFlairColor()));
|
||||||
return color + (nottest ? p.getName() : pn.get()) + "§r"; //Fix name casing, except when testing
|
return color + (nottest ? p.getName() : pn.get()) + "§r"; //Fix name casing, except when testing
|
||||||
}).priority(Priority.High).type(ChatFormatter.Type.Excluder).build());
|
}).build(), true, names));
|
||||||
|
|
||||||
if (addNickFormatter)
|
if (nicknames.length > 0) //Add as first so it handles special characters
|
||||||
formatters.add(ChatFormatter.builder("nickname", Pattern.compile(nicksb.toString())).color(Color.Aqua)
|
formatters.add(0, new StringMatchProvider("nickname", FormatSettings.builder().color(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()));
|
||||||
|
@ -352,7 +308,7 @@ public class ChatProcessing {
|
||||||
error.accept("Player nicknamed " + match.toLowerCase()
|
error.accept("Player nicknamed " + match.toLowerCase()
|
||||||
+ " not found in nickname map but was reported as online.");
|
+ " not found in nickname map but was reported as online.");
|
||||||
return "§c" + match + "§r";
|
return "§c" + match + "§r";
|
||||||
}).priority(Priority.High).type(ChatFormatter.Type.Excluder).build());
|
}).build(), true, nicknames));
|
||||||
}
|
}
|
||||||
return formatters;
|
return formatters;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package buttondevteam.chat.components.formatter.formatting;
|
||||||
|
|
||||||
|
import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public final class ChatFormatUtils {
|
||||||
|
private ChatFormatUtils() {}
|
||||||
|
|
||||||
|
static void sendMessageWithPointer(String str, int... pointer) {
|
||||||
|
DebugCommand.SendDebugMessage(str);
|
||||||
|
StringBuilder sb = new StringBuilder(str.length());
|
||||||
|
Arrays.sort(pointer);
|
||||||
|
for (int i = 0; i < pointer.length; i++) {
|
||||||
|
for (int j = 0; j < pointer[i] - (i > 0 ? pointer[i - 1] + 1 : 0); j++)
|
||||||
|
sb.append(' ');
|
||||||
|
if (pointer[i] == (i > 0 ? pointer[i - 1] : -1))
|
||||||
|
continue;
|
||||||
|
sb.append('^');
|
||||||
|
}
|
||||||
|
DebugCommand.SendDebugMessage(sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given start and end position is inside any of the ranges
|
||||||
|
*/
|
||||||
|
static boolean isInRange(int start, int end, ArrayList<int[]> ranges) {
|
||||||
|
return ranges.stream().anyMatch(range -> range[1] >= start && range[0] <= end);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,79 +1,23 @@
|
||||||
package buttondevteam.chat.components.formatter.formatting;
|
package buttondevteam.chat.components.formatter.formatting;
|
||||||
|
|
||||||
import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
|
import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
|
||||||
import buttondevteam.chat.components.formatter.ChatProcessing;
|
|
||||||
import buttondevteam.lib.architecture.ConfigData;
|
|
||||||
import buttondevteam.lib.architecture.IHaveConfig;
|
import buttondevteam.lib.architecture.IHaveConfig;
|
||||||
import buttondevteam.lib.chat.Color;
|
import buttondevteam.lib.chat.Color;
|
||||||
import buttondevteam.lib.chat.Priority;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link ChatFormatter} shows what formatting to use based on regular expressions. {@link ChatFormatter#Combine(List, String, TellrawPart, IHaveConfig)} 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, TellrawPart, 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.
|
||||||
*
|
*
|
||||||
* @author NorbiPeti
|
* @author NorbiPeti
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("UnusedAssignment")
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public final class ChatFormatter {
|
public final class ChatFormatter {
|
||||||
Pattern regex;
|
private ChatFormatter() {
|
||||||
boolean italic;
|
|
||||||
boolean bold;
|
|
||||||
boolean underlined;
|
|
||||||
boolean strikethrough;
|
|
||||||
boolean obfuscated;
|
|
||||||
Color color;
|
|
||||||
TriFunc<String, ChatFormatter, FormattedSection, String> onmatch;
|
|
||||||
String openlink;
|
|
||||||
@Builder.Default
|
|
||||||
Priority priority = Priority.Normal;
|
|
||||||
@Builder.Default
|
|
||||||
short removeCharCount = 0;
|
|
||||||
@Builder.Default
|
|
||||||
Type type = Type.Normal;
|
|
||||||
String hoverText;
|
|
||||||
String name;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ChatFormatter{" +
|
|
||||||
"name='" + name + '\'' +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ChatFormatterBuilder builder(String name, Pattern regex) {
|
|
||||||
return builder().regex(regex).name(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ChatFormatterBuilder builder() {
|
|
||||||
return new ChatFormatterBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ConfigData<Boolean> enabled(IHaveConfig config) {
|
|
||||||
return config.getData(name + ".enabled", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Type {
|
|
||||||
Normal,
|
|
||||||
/**
|
|
||||||
* Matches a start and an end section which gets converted to one section (for example see italics)
|
|
||||||
*/
|
|
||||||
Range,
|
|
||||||
/**
|
|
||||||
* Exclude matching area from further processing (besides this formatter)
|
|
||||||
*/
|
|
||||||
Excluder
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
|
@ -81,31 +25,32 @@ public final class ChatFormatter {
|
||||||
R apply(T1 x1, T2 x2, T3 x3);
|
R apply(T1 x1, T2 x2, T3 x3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Combine(List<ChatFormatter> formatters, String str, TellrawPart tp, IHaveConfig config) {
|
//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) {
|
||||||
/*
|
/*
|
||||||
* This method assumes that there is always a global formatter
|
* A global formatter is no longer needed
|
||||||
*/
|
*/
|
||||||
header("ChatFormatter.Combine begin");
|
header("ChatFormatter.Combine begin");
|
||||||
ArrayList<FormattedSection> sections = new ArrayList<>();
|
ArrayList<FormattedSection> sections = new ArrayList<>();
|
||||||
|
|
||||||
if (config != null) //null if testing
|
if (config != null) //null if testing
|
||||||
formatters.removeIf(cf -> !cf.enabled(config).get()); //Remove disabled formatters
|
formatters.removeIf(cf -> !cf.enabled(config).get()); //Remove disabled formatters
|
||||||
createSections(formatters, str, sections, true);
|
var excluded = new ArrayList<int[]>();
|
||||||
|
|
||||||
header("Section creation (excluders done)");
|
|
||||||
createSections(formatters, str, sections, false);
|
|
||||||
sortSections(sections);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 0: Start - 1: End index
|
* 0: Start - 1: End index
|
||||||
*/
|
*/
|
||||||
val remchars = new ArrayList<int[]>();
|
val remchars = new ArrayList<int[]>();
|
||||||
|
|
||||||
header("Range section conversion");
|
escapeThings(str, excluded, remchars);
|
||||||
sections = convertRangeSections(str, sections, remchars);
|
|
||||||
|
|
||||||
header("Adding remove chars (RC)"); // Important to add after the range section conversion
|
sections.add(new FormattedSection(defaults, 0, str.length() - 1, Collections.emptyList())); //Add entire message
|
||||||
addRemChars(sections, remchars, str);
|
var providers = formatters.stream().filter(mp -> mp instanceof RegexMatchProvider).collect(Collectors.toList());
|
||||||
|
createSections(providers, str, sections, excluded, remchars);
|
||||||
|
providers = formatters.stream().filter(mp -> mp instanceof StringMatchProvider).collect(Collectors.toList());
|
||||||
|
createSections(providers, str, sections, excluded, remchars);
|
||||||
|
providers = formatters.stream().filter(mp -> mp instanceof RangeMatchProvider).collect(Collectors.toList());
|
||||||
|
createSections(providers, str, sections, excluded, remchars);
|
||||||
|
sortSections(sections);
|
||||||
|
|
||||||
header("Section combining");
|
header("Section combining");
|
||||||
combineSections(str, sections);
|
combineSections(str, sections);
|
||||||
|
@ -115,145 +60,35 @@ public final class ChatFormatter {
|
||||||
header("ChatFormatter.Combine done");
|
header("ChatFormatter.Combine done");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void createSections(List<ChatFormatter> formatters, String str, ArrayList<FormattedSection> sections,
|
private static void escapeThings(String str, ArrayList<int[]> ignoredAreas, ArrayList<int[]> remchars) {
|
||||||
boolean excluders) {
|
boolean escaped = false;
|
||||||
for (ChatFormatter formatter : formatters) {
|
for (int i = 0; i < str.length(); i++) {
|
||||||
if (excluders == (formatter.type != Type.Excluder))
|
if (str.charAt(i) == '\\') {
|
||||||
continue; //If we're looking at excluders and this isn't one, skip - or vica-versa
|
remchars.add(new int[]{i, i});
|
||||||
Matcher matcher = formatter.regex.matcher(str);
|
ignoredAreas.add(new int[]{i + 1, i + 1});
|
||||||
while (matcher.find()) {
|
i++; //Ignore a potential second slash
|
||||||
DebugCommand.SendDebugMessage("Found match from " + matcher.start() + " to " + (matcher.end() - 1));
|
|
||||||
DebugCommand.SendDebugMessage("With " + (excluders ? "excluder " : "") + "formatter: " + formatter);
|
|
||||||
sendMessageWithPointer(str, matcher.start(), matcher.end() - 1);
|
|
||||||
if (formatter.regex != ChatProcessing.ENTIRE_MESSAGE_PATTERN && sections.stream().anyMatch(fs -> fs.type == Type.Excluder && (fs.End >= matcher.start() && fs.Start <= matcher.end() - 1))) {
|
|
||||||
DebugCommand.SendDebugMessage("Ignoring formatter because of an excluder");
|
|
||||||
continue; //Exclude areas matched by excluders - Range sections are correctly handled afterwards
|
|
||||||
}
|
|
||||||
ArrayList<String> groups = new ArrayList<>();
|
|
||||||
for (int i = 0; i < matcher.groupCount(); i++)
|
|
||||||
groups.add(matcher.group(i + 1));
|
|
||||||
if (groups.size() > 0)
|
|
||||||
DebugCommand.SendDebugMessage("First group: " + groups.get(0));
|
|
||||||
FormattedSection section = new FormattedSection(formatter, matcher.start(), matcher.end() - 1, groups,
|
|
||||||
formatter.type);
|
|
||||||
sections.add(section);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void newCombine(String str, ArrayList<FormattedSection> sections, ArrayList<int[]> remchars) {
|
private static void createSections(List<MatchProviderBase> formatters, String str, ArrayList<FormattedSection> sections,
|
||||||
var stack = new Stack<FormattedSection>();
|
ArrayList<int[]> excludedAreas, ArrayList<int[]> removedCharacters) {
|
||||||
for (int i = 0; i < str.length(); i++) {
|
formatters.forEach(MatchProviderBase::reset); //Reset state information, as we aren't doing deep cloning
|
||||||
for (Iterator<FormattedSection> iterator = sections.iterator(); iterator.hasNext(); ) {
|
while (formatters.size() > 0) {
|
||||||
FormattedSection section = iterator.next();
|
for (var iterator = formatters.iterator(); iterator.hasNext(); ) {
|
||||||
if (section.Start <= i) {
|
MatchProviderBase formatter = iterator.next();
|
||||||
stack.push(section);
|
DebugCommand.SendDebugMessage("Checking provider: " + formatter);
|
||||||
|
var sect = formatter.getNextSection(str, excludedAreas, removedCharacters);
|
||||||
|
if (sect != null) //Not excluding the area here because the range matcher shouldn't take it all
|
||||||
|
sections.add(sect);
|
||||||
|
if (formatter.isFinished()) {
|
||||||
|
DebugCommand.SendDebugMessage("Provider finished");
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ArrayList<FormattedSection> convertRangeSections(String str, ArrayList<FormattedSection> sections, ArrayList<int[]> remchars) {
|
|
||||||
ArrayList<FormattedSection> combined = new ArrayList<>();
|
|
||||||
Map<ChatFormatter, FormattedSection> nextSection = new HashMap<>();
|
|
||||||
boolean escaped = false;
|
|
||||||
int takenStart = -1, takenEnd = -1;
|
|
||||||
ChatFormatter takenFormatter = null;
|
|
||||||
boolean takenByBigGuy = false; //Can't win against him (finished sections take precedence)
|
|
||||||
for (final FormattedSection section : sections) {
|
|
||||||
// Set ending to -1 until closed with another 1 long "section" - only do this if IsRange is true
|
|
||||||
if (section.type != Type.Range) {
|
|
||||||
escaped = section.Formatters.contains(ChatProcessing.ESCAPE_FORMATTER) && !escaped; // Enable escaping on first \, disable on second
|
|
||||||
if (escaped) {// Don't add the escape character
|
|
||||||
remchars.add(new int[]{section.Start, section.Start});
|
|
||||||
DebugCommand.SendDebugMessage("Found escaper section: " + section);
|
|
||||||
} else {
|
|
||||||
combined.add(section); // The above will delete the \
|
|
||||||
DebugCommand.SendDebugMessage("Added section: " + section);
|
|
||||||
}
|
|
||||||
sendMessageWithPointer(str, section.Start, section.End);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!escaped) {
|
|
||||||
ChatFormatter formatter = section.Formatters.get(0);
|
|
||||||
if (section.Start == takenStart || (section.Start > takenStart && section.Start < takenEnd)) {
|
|
||||||
/*
|
|
||||||
* if (nextSection.containsKey(section.Formatters.get(0)) ? section.RemCharFromStart <= takenEnd - takenStart : section.RemCharFromStart > takenEnd - takenStart) {
|
|
||||||
*/
|
|
||||||
if (takenByBigGuy || formatter.removeCharCount < takenEnd - takenStart) {
|
|
||||||
DebugCommand.SendDebugMessage("Lose: " + section);
|
|
||||||
sendMessageWithPointer(str, section.Start, section.End);
|
|
||||||
DebugCommand.SendDebugMessage("And win: " + takenFormatter);
|
|
||||||
continue; // The current section loses
|
|
||||||
}
|
|
||||||
nextSection.remove(takenFormatter); // The current section wins
|
|
||||||
DebugCommand.SendDebugMessage("Win: " + section);
|
|
||||||
sendMessageWithPointer(str, section.Start, section.End);
|
|
||||||
DebugCommand.SendDebugMessage("And lose: " + takenFormatter);
|
|
||||||
}
|
|
||||||
boolean hasFormatter = nextSection.containsKey(formatter);
|
|
||||||
if (!hasFormatter) {
|
|
||||||
val ff = formatter;
|
|
||||||
val cfo = nextSection.keySet().stream().filter(f -> f.removeCharCount > ff.removeCharCount).findAny();
|
|
||||||
if (cfo.isPresent()) {
|
|
||||||
//formatter = cfo.get();
|
|
||||||
val s = nextSection.get(cfo.get());
|
|
||||||
int takenS = section.Start, takenE = section.Start + formatter.removeCharCount;
|
|
||||||
if (s.Start == takenS || (s.Start > takenS && s.Start < takenE)) { //Peek()
|
|
||||||
hasFormatter = true;
|
|
||||||
continue; //Not the formatter we're looking for - TODO: It doesn't fix the problem of italics at the end
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
takenStart = section.Start;
|
|
||||||
takenEnd = section.Start + formatter.removeCharCount;
|
|
||||||
takenFormatter = formatter;
|
|
||||||
if (hasFormatter) {
|
|
||||||
FormattedSection s = nextSection.remove(formatter);
|
|
||||||
//HACK? If we can find another section that removes more characters, finish that instead
|
|
||||||
// section: the ending marker section - s: the to-be full section
|
|
||||||
s.End = takenEnd - 1; //Take the remCharCount into account as well
|
|
||||||
// s.IsRange = false; // IsRange means it's a 1 long section indicating a start or an end
|
|
||||||
combined.add(s);
|
|
||||||
takenByBigGuy = true;
|
|
||||||
DebugCommand.SendDebugMessage("Finished section: " + s);
|
|
||||||
sendMessageWithPointer(str, s.Start, s.End);
|
|
||||||
} else {
|
|
||||||
DebugCommand.SendDebugMessage("Adding next section: " + section);
|
|
||||||
sendMessageWithPointer(str, section.Start, section.End);
|
|
||||||
nextSection.put(formatter, section);
|
|
||||||
takenByBigGuy = false;
|
|
||||||
}
|
|
||||||
DebugCommand
|
|
||||||
.SendDebugMessage("New area taken: (" + takenStart + "-" + takenEnd + ") " + takenFormatter);
|
|
||||||
sendMessageWithPointer(str, takenStart, takenEnd);
|
|
||||||
} else {
|
|
||||||
DebugCommand.SendDebugMessage("Skipping section: " + section); // This will keep the text (character)
|
|
||||||
sendMessageWithPointer(str, section.Start, section.End);
|
|
||||||
escaped = false; // Reset escaping if applied, like if we're at the '*' in '\*'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Do not finish unfinished sections, ignore them
|
|
||||||
sections = combined;
|
|
||||||
return sections;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addRemChars(ArrayList<FormattedSection> sections, ArrayList<int[]> remchars, String str) {
|
|
||||||
sections.stream()
|
|
||||||
.flatMap(fs -> fs.Formatters.stream().filter(cf -> cf.removeCharCount > 0)
|
|
||||||
.mapToInt(cf -> cf.removeCharCount).mapToObj(rcc -> new int[]{fs.Start, fs.Start + rcc - 1}))
|
|
||||||
.forEach(remchars::add);
|
|
||||||
sections.stream()
|
|
||||||
.flatMap(fs -> fs.Formatters.stream().filter(cf -> cf.removeCharCount > 0)
|
|
||||||
.mapToInt(cf -> cf.removeCharCount).mapToObj(rcc -> new int[]{fs.End - rcc + 1, fs.End}))
|
|
||||||
.forEach(remchars::add);
|
|
||||||
DebugCommand.SendDebugMessage("Added remchars:");
|
|
||||||
DebugCommand.SendDebugMessage(remchars.stream().map(Arrays::toString).collect(Collectors.joining("; ")));
|
|
||||||
sendMessageWithPointer(str,
|
|
||||||
remchars.stream().flatMapToInt(Arrays::stream).toArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void combineSections(String str, ArrayList<FormattedSection> sections) {
|
private static void combineSections(String str, ArrayList<FormattedSection> sections) {
|
||||||
for (int i = 1; i < sections.size(); i++) {
|
for (int i = 1; i < sections.size(); i++) {
|
||||||
DebugCommand.SendDebugMessage("i: " + i);
|
DebugCommand.SendDebugMessage("i: " + i);
|
||||||
|
@ -262,7 +97,8 @@ public final class ChatFormatter {
|
||||||
{
|
{
|
||||||
FormattedSection firstSect = sections.get(i - 1);
|
FormattedSection firstSect = sections.get(i - 1);
|
||||||
FormattedSection lastSect = sections.get(i);
|
FormattedSection lastSect = sections.get(i);
|
||||||
if (firstSect.Start > lastSect.Start) { //The first can't start later
|
if (firstSect.Start > lastSect.Start //The first can't start later
|
||||||
|
|| (firstSect.Start == lastSect.Start && firstSect.End < lastSect.End)) {
|
||||||
var section = firstSect;
|
var section = firstSect;
|
||||||
firstSect = lastSect;
|
firstSect = lastSect;
|
||||||
lastSect = section;
|
lastSect = section;
|
||||||
|
@ -271,41 +107,40 @@ public final class ChatFormatter {
|
||||||
lastSection = lastSect;
|
lastSection = lastSect;
|
||||||
}
|
}
|
||||||
DebugCommand.SendDebugMessage("Combining sections " + firstSection);
|
DebugCommand.SendDebugMessage("Combining sections " + firstSection);
|
||||||
sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
ChatFormatUtils.sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
||||||
DebugCommand.SendDebugMessage(" and " + lastSection);
|
DebugCommand.SendDebugMessage(" and " + lastSection);
|
||||||
sendMessageWithPointer(str, lastSection.Start, lastSection.End);
|
ChatFormatUtils.sendMessageWithPointer(str, lastSection.Start, lastSection.End);
|
||||||
if (firstSection.Start == lastSection.Start && firstSection.End == lastSection.End) {
|
if (firstSection.Start == lastSection.Start && firstSection.End == lastSection.End) {
|
||||||
firstSection.Formatters.addAll(lastSection.Formatters);
|
firstSection.Settings.copyFrom(lastSection.Settings);
|
||||||
firstSection.Matches.addAll(lastSection.Matches);
|
firstSection.Matches.addAll(lastSection.Matches);
|
||||||
firstSection.type = lastSection.type;
|
|
||||||
DebugCommand.SendDebugMessage("To section " + firstSection);
|
DebugCommand.SendDebugMessage("To section " + firstSection);
|
||||||
sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
ChatFormatUtils.sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
||||||
sections.remove(i);
|
sections.remove(i);
|
||||||
i = 0;
|
i = 0;
|
||||||
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 origend2 = firstSection.End;
|
int firstSectEnd = firstSection.End;
|
||||||
firstSection.End = lastSection.Start - 1;
|
firstSection.End = lastSection.Start - 1;
|
||||||
int origend = lastSection.End;
|
int lastSectEnd = lastSection.End;
|
||||||
FormattedSection section = new FormattedSection(firstSection.Formatters, lastSection.Start, origend,
|
FormattedSection section = new FormattedSection(firstSection.Settings, lastSection.Start, lastSectEnd,
|
||||||
firstSection.Matches, Type.Normal);
|
firstSection.Matches);
|
||||||
section.Formatters.addAll(lastSection.Formatters);
|
section.Settings.copyFrom(lastSection.Settings);
|
||||||
section.Matches.addAll(lastSection.Matches); // TODO: Clean
|
section.Matches.addAll(lastSection.Matches);
|
||||||
sections.add(i, section);
|
sections.add(i, section);
|
||||||
// Use the properties of the first section not the second one
|
|
||||||
lastSection.Formatters.clear();
|
|
||||||
lastSection.Formatters.addAll(firstSection.Formatters);
|
|
||||||
lastSection.Matches.clear();
|
|
||||||
lastSection.Matches.addAll(firstSection.Matches);
|
|
||||||
|
|
||||||
lastSection.Start = origend + 1;
|
if (firstSectEnd > lastSection.End) { //Copy first section info to last as the lastSection initially cuts the firstSection in half
|
||||||
lastSection.End = origend2;
|
lastSection.Settings = FormatSettings.builder().build();
|
||||||
|
lastSection.Settings.copyFrom(firstSection.Settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastSection.Start = lastSectEnd + 1;
|
||||||
|
lastSection.End = firstSectEnd;
|
||||||
|
|
||||||
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) {
|
||||||
DebugCommand.SendDebugMessage(" Removed: " + s);
|
DebugCommand.SendDebugMessage(" Removed: " + s);
|
||||||
sendMessageWithPointer(str, s.Start, s.End);
|
ChatFormatUtils.sendMessageWithPointer(str, s.Start, s.End);
|
||||||
sections.remove(s);
|
sections.remove(s);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -315,15 +150,15 @@ 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 + "");
|
||||||
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 + "");
|
||||||
sendMessageWithPointer(str, section.Start, section.End);
|
ChatFormatUtils.sendMessageWithPointer(str, section.Start, section.End);
|
||||||
}
|
}
|
||||||
if (!removeIfNeeded.test(lastSection)) {
|
if (!removeIfNeeded.test(lastSection)) {
|
||||||
DebugCommand.SendDebugMessage(" 3:" + lastSection);
|
DebugCommand.SendDebugMessage(" 3:" + lastSection);
|
||||||
sendMessageWithPointer(str, lastSection.Start, lastSection.End);
|
ChatFormatUtils.sendMessageWithPointer(str, lastSection.Start, lastSection.End);
|
||||||
}
|
}
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
|
@ -332,7 +167,7 @@ public final class ChatFormatter {
|
||||||
for (int j = i - 1; j <= i + 1; j++) {
|
for (int j = i - 1; j <= i + 1; j++) {
|
||||||
if (j < sections.size() && sections.get(j).End < sections.get(j).Start) {
|
if (j < sections.size() && sections.get(j).End < sections.get(j).Start) {
|
||||||
DebugCommand.SendDebugMessage("Removing section: " + sections.get(j));
|
DebugCommand.SendDebugMessage("Removing section: " + sections.get(j));
|
||||||
sendMessageWithPointer(str, sections.get(j).Start, sections.get(j).End);
|
ChatFormatUtils.sendMessageWithPointer(str, sections.get(j).Start, sections.get(j).End);
|
||||||
sections.remove(j);
|
sections.remove(j);
|
||||||
j--;
|
j--;
|
||||||
i = 0;
|
i = 0;
|
||||||
|
@ -349,7 +184,7 @@ public final class ChatFormatter {
|
||||||
String originaltext;
|
String originaltext;
|
||||||
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);
|
||||||
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("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("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());*/
|
DebugCommand.SendDebugMessage("RCI: "+remchars.stream().filter(rc -> start < rc[0] || rc[1] < end).count());*/
|
||||||
|
@ -377,29 +212,28 @@ 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
|
//section.Formatters.sort(Comparator.comparing(cf2 -> cf2.priority.GetValue())); //Apply the highest last, to overwrite previous ones
|
||||||
TellrawPart newtp = new TellrawPart("");
|
TellrawPart newtp = new TellrawPart("");
|
||||||
for (ChatFormatter formatter : section.Formatters) {
|
var settings = section.Settings;
|
||||||
DebugCommand.SendDebugMessage("Applying formatter: " + formatter);
|
DebugCommand.SendDebugMessage("Applying settings: " + settings);
|
||||||
if (formatter.onmatch != null)
|
if (settings.onmatch != null)
|
||||||
originaltext = formatter.onmatch.apply(originaltext, formatter, section);
|
originaltext = settings.onmatch.apply(originaltext, settings, section);
|
||||||
if (formatter.color != null)
|
if (settings.color != null)
|
||||||
newtp.setColor(formatter.color);
|
newtp.setColor(settings.color);
|
||||||
if (formatter.bold)
|
if (settings.bold)
|
||||||
newtp.setBold(true);
|
newtp.setBold(true);
|
||||||
if (formatter.italic)
|
if (settings.italic)
|
||||||
newtp.setItalic(true);
|
newtp.setItalic(true);
|
||||||
if (formatter.underlined)
|
if (settings.underlined)
|
||||||
newtp.setUnderlined(true);
|
newtp.setUnderlined(true);
|
||||||
if (formatter.strikethrough)
|
if (settings.strikethrough)
|
||||||
newtp.setStrikethrough(true);
|
newtp.setStrikethrough(true);
|
||||||
if (formatter.obfuscated)
|
if (settings.obfuscated)
|
||||||
newtp.setObfuscated(true);
|
newtp.setObfuscated(true);
|
||||||
if (formatter.openlink != null)
|
if (settings.openlink != null)
|
||||||
openlink = formatter.openlink;
|
openlink = settings.openlink;
|
||||||
if (formatter.hoverText != null)
|
if (settings.hoverText != null)
|
||||||
newtp.setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, formatter.hoverText));
|
newtp.setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAction.SHOW_TEXT, settings.hoverText));
|
||||||
}
|
|
||||||
if (lasttp != null && newtp.getColor() == lasttp.getColor()
|
if (lasttp != null && newtp.getColor() == lasttp.getColor()
|
||||||
&& newtp.isBold() == lasttp.isBold()
|
&& newtp.isBold() == lasttp.isBold()
|
||||||
&& newtp.isItalic() == lasttp.isItalic()
|
&& newtp.isItalic() == lasttp.isItalic()
|
||||||
|
@ -427,25 +261,10 @@ public final class ChatFormatter {
|
||||||
private static void sortSections(ArrayList<FormattedSection> sections) {
|
private static void sortSections(ArrayList<FormattedSection> sections) {
|
||||||
sections.sort(
|
sections.sort(
|
||||||
(s1, s2) -> s1.Start == s2.Start
|
(s1, s2) -> s1.Start == s2.Start
|
||||||
? s1.End == s2.End ? Integer.compare(s2.Formatters.get(0).priority.GetValue(),
|
? s1.End == s2.End ? 0 : Integer.compare(s1.End, s2.End)
|
||||||
s1.Formatters.get(0).priority.GetValue()) : Integer.compare(s1.End, s2.End)
|
|
||||||
: Integer.compare(s1.Start, s2.Start));
|
: Integer.compare(s1.Start, s2.Start));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void sendMessageWithPointer(String str, int... pointer) {
|
|
||||||
DebugCommand.SendDebugMessage(str);
|
|
||||||
StringBuilder sb = new StringBuilder(str.length());
|
|
||||||
Arrays.sort(pointer);
|
|
||||||
for (int i = 0; i < pointer.length; i++) {
|
|
||||||
for (int j = 0; j < pointer[i] - (i > 0 ? pointer[i - 1] + 1 : 0); j++)
|
|
||||||
sb.append(' ');
|
|
||||||
if (pointer[i] == (i > 0 ? pointer[i - 1] : -1))
|
|
||||||
continue;
|
|
||||||
sb.append('^');
|
|
||||||
}
|
|
||||||
DebugCommand.SendDebugMessage(sb.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void header(String message) {
|
private static void header(String message) {
|
||||||
DebugCommand.SendDebugMessage("\n--------\n" + message + "\n--------\n");
|
DebugCommand.SendDebugMessage("\n--------\n" + message + "\n--------\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package buttondevteam.chat.components.formatter.formatting;
|
||||||
|
|
||||||
|
import buttondevteam.lib.chat.Color;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes how a matched section of the message should look. May be combined with other format settings.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class FormatSettings {
|
||||||
|
boolean italic;
|
||||||
|
boolean bold;
|
||||||
|
boolean underlined;
|
||||||
|
boolean strikethrough;
|
||||||
|
boolean obfuscated;
|
||||||
|
Color color;
|
||||||
|
ChatFormatter.TriFunc<String, FormatSettings, FormattedSection, String> onmatch;
|
||||||
|
String openlink;
|
||||||
|
String hoverText;
|
||||||
|
|
||||||
|
public void copyFrom(FormatSettings settings) {
|
||||||
|
try {
|
||||||
|
for (var field : FormatSettings.class.getDeclaredFields()) {
|
||||||
|
if (field.getType() == boolean.class) {
|
||||||
|
if (field.getBoolean(settings))
|
||||||
|
field.setBoolean(this, true); //Set to true if either of them are true
|
||||||
|
} 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,36 +1,22 @@
|
||||||
package buttondevteam.chat.components.formatter.formatting;
|
package buttondevteam.chat.components.formatter.formatting;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import lombok.ToString;
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ToString
|
||||||
public class FormattedSection {
|
public class FormattedSection {
|
||||||
public int Start;
|
public int Start;
|
||||||
public int End;
|
public int End;
|
||||||
public ArrayList<ChatFormatter> Formatters = new ArrayList<ChatFormatter>();
|
public FormatSettings Settings;
|
||||||
public ArrayList<String> Matches = new ArrayList<String>();
|
public List<String> Matches = new ArrayList<>();
|
||||||
public ChatFormatter.Type type;
|
|
||||||
|
|
||||||
FormattedSection(ChatFormatter formatter, int start, int end, ArrayList<String> matches, ChatFormatter.Type type) {
|
FormattedSection(FormatSettings settings, int start, int end, List<String> matches) {
|
||||||
Start = start;
|
Start = start;
|
||||||
End = end;
|
End = end;
|
||||||
Formatters.add(formatter);
|
Settings = FormatSettings.builder().build();
|
||||||
|
Settings.copyFrom(settings);
|
||||||
Matches.addAll(matches);
|
Matches.addAll(matches);
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
FormattedSection(Collection<ChatFormatter> formatters, int start, int end, ArrayList<String> matches,
|
|
||||||
ChatFormatter.Type type) {
|
|
||||||
Start = start;
|
|
||||||
End = end;
|
|
||||||
Formatters.addAll(formatters);
|
|
||||||
Matches.addAll(matches);
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Section(" + Start + ", " + End + ", formatters: " +
|
|
||||||
Formatters.toString() + ", matches: " + Matches.toString() + ", " +
|
|
||||||
type + ")";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package buttondevteam.chat.components.formatter.formatting;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to find a match for the provided message, returning null if none was found.
|
||||||
|
*/
|
||||||
|
public interface MatchProvider {
|
||||||
|
@Nullable
|
||||||
|
FormattedSection getNextSection(String message, ArrayList<int[]> ignoredAreas, ArrayList<int[]> removedCharacters);
|
||||||
|
|
||||||
|
boolean isFinished();
|
||||||
|
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String toString();
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package buttondevteam.chat.components.formatter.formatting;
|
||||||
|
|
||||||
|
import buttondevteam.lib.architecture.ConfigData;
|
||||||
|
import buttondevteam.lib.architecture.IHaveConfig;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public abstract class MatchProviderBase implements MatchProvider {
|
||||||
|
@Getter
|
||||||
|
protected boolean finished;
|
||||||
|
@Getter
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public abstract FormattedSection getNextSection(String message, ArrayList<int[]> ignoredAreas, ArrayList<int[]> removedCharacters);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void resetSubclass();
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
finished = false;
|
||||||
|
resetSubclass();
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigData<Boolean> enabled(IHaveConfig config) {
|
||||||
|
return config.getData(name + ".enabled", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package buttondevteam.chat.components.formatter.formatting;
|
||||||
|
|
||||||
|
import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
public class RangeMatchProvider extends MatchProviderBase {
|
||||||
|
private final String pattern;
|
||||||
|
@ToString.Exclude
|
||||||
|
private final FormatSettings settings;
|
||||||
|
private int nextIndex = 0;
|
||||||
|
private FormattedSection startedSection;
|
||||||
|
|
||||||
|
public RangeMatchProvider(String name, String pattern, FormatSettings settings) {
|
||||||
|
super(name);
|
||||||
|
this.pattern = pattern;
|
||||||
|
this.settings = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FormattedSection getNextSection(String message, ArrayList<int[]> ignoredAreas, ArrayList<int[]> removedCharacters) {
|
||||||
|
int i, len;
|
||||||
|
i = message.indexOf(pattern, nextIndex);
|
||||||
|
len = pattern.length();
|
||||||
|
nextIndex = i + len; //Set for the next method call
|
||||||
|
if (i == -1) {
|
||||||
|
finished = true; //Won't find any more - unfinished sections will be garbage collected
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (ChatFormatUtils.isInRange(i, i + len - 1, ignoredAreas)) {
|
||||||
|
DebugCommand.SendDebugMessage("Range start is in ignored area, skipping");
|
||||||
|
return null; //Not setting finished to true, so it will go to the next match
|
||||||
|
}
|
||||||
|
ignoredAreas.add(new int[]{i, i + len - 1});
|
||||||
|
if (startedSection == null) {
|
||||||
|
DebugCommand.SendDebugMessage("Started range match from " + i + " to " + (i + len - 1));
|
||||||
|
DebugCommand.SendDebugMessage("With settings: " + settings);
|
||||||
|
ChatFormatUtils.sendMessageWithPointer(message, i, i + len - 1);
|
||||||
|
startedSection = new FormattedSection(settings, i, i + len - 1, Collections.emptyList());
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
var section = startedSection;
|
||||||
|
DebugCommand.SendDebugMessage("Finished range match from " + section.Start + " to " + (i + len - 1));
|
||||||
|
DebugCommand.SendDebugMessage("With settings: " + settings);
|
||||||
|
ChatFormatUtils.sendMessageWithPointer(message, section.Start, i + len - 1);
|
||||||
|
section.End = i + len - 1;
|
||||||
|
removedCharacters.add(new int[]{section.Start, section.Start + len - 1});
|
||||||
|
removedCharacters.add(new int[]{i, i + len - 1});
|
||||||
|
startedSection = null; //Reset so next find creates a new one
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetSubclass() {
|
||||||
|
nextIndex = 0;
|
||||||
|
startedSection = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package buttondevteam.chat.components.formatter.formatting;
|
||||||
|
|
||||||
|
import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class RegexMatchProvider extends MatchProviderBase {
|
||||||
|
private final Pattern pattern;
|
||||||
|
@ToString.Exclude
|
||||||
|
private final FormatSettings settings;
|
||||||
|
private Matcher matcher;
|
||||||
|
|
||||||
|
public RegexMatchProvider(String name, Pattern pattern, FormatSettings settings) {
|
||||||
|
super(name);
|
||||||
|
this.pattern = pattern;
|
||||||
|
this.settings = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public FormattedSection getNextSection(String message, ArrayList<int[]> ignoredAreas, ArrayList<int[]> removedCharacters) {
|
||||||
|
if (matcher == null)
|
||||||
|
matcher = pattern.matcher(message);
|
||||||
|
if (!matcher.find()) {
|
||||||
|
finished = true;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int start = matcher.start(), end = matcher.end() - 1;
|
||||||
|
DebugCommand.SendDebugMessage("Found regex match from " + start + " to " + end);
|
||||||
|
DebugCommand.SendDebugMessage("With settings: " + settings);
|
||||||
|
ChatFormatUtils.sendMessageWithPointer(message, start, end);
|
||||||
|
if (ChatFormatUtils.isInRange(start, end, ignoredAreas)) {
|
||||||
|
DebugCommand.SendDebugMessage("Match is in ignored area, skipping");
|
||||||
|
return null; //Not setting finished to true, so it will go to the next match
|
||||||
|
}
|
||||||
|
ArrayList<String> groups = new ArrayList<>();
|
||||||
|
for (int i = 0; i < matcher.groupCount(); i++)
|
||||||
|
groups.add(matcher.group(i + 1));
|
||||||
|
if (groups.size() > 0)
|
||||||
|
DebugCommand.SendDebugMessage("First group: " + groups.get(0));
|
||||||
|
ignoredAreas.add(new int[]{start, end});
|
||||||
|
return new FormattedSection(settings, matcher.start(), matcher.end() - 1, groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetSubclass() {
|
||||||
|
matcher = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package buttondevteam.chat.components.formatter.formatting;
|
||||||
|
|
||||||
|
import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
public class StringMatchProvider extends MatchProviderBase {
|
||||||
|
private final String[] strings;
|
||||||
|
@ToString.Exclude
|
||||||
|
private final FormatSettings settings;
|
||||||
|
private int nextIndex = 0;
|
||||||
|
private boolean ignoreCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches the given strings in the order given
|
||||||
|
*
|
||||||
|
* @param settings The format settings
|
||||||
|
* @param strings The strings to match in the correct order
|
||||||
|
*/
|
||||||
|
public StringMatchProvider(String name, FormatSettings settings, boolean ignoreCase, String... strings) {
|
||||||
|
super(name);
|
||||||
|
this.settings = settings;
|
||||||
|
this.strings = strings;
|
||||||
|
this.ignoreCase = ignoreCase;
|
||||||
|
if (ignoreCase) {
|
||||||
|
for (int i = 0; i < strings.length; i++) {
|
||||||
|
strings[i] = strings[i].toLowerCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public FormattedSection getNextSection(String message, ArrayList<int[]> ignoredAreas, ArrayList<int[]> removedCharacters) {
|
||||||
|
if (ignoreCase)
|
||||||
|
message = message.toLowerCase();
|
||||||
|
int i = -1, len = 0;
|
||||||
|
for (String string : strings) {
|
||||||
|
i = message.indexOf(string, nextIndex);
|
||||||
|
len = string.length();
|
||||||
|
if (i != -1) break;
|
||||||
|
}
|
||||||
|
if (i == -1) {
|
||||||
|
finished = true; //Won't find any more
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
nextIndex = i + len;
|
||||||
|
if (ChatFormatUtils.isInRange(i, i + len - 1, ignoredAreas)) {
|
||||||
|
DebugCommand.SendDebugMessage("String is in ignored area, skipping");
|
||||||
|
return null; //Not setting finished to true, so it will go to the next match
|
||||||
|
}
|
||||||
|
DebugCommand.SendDebugMessage("Found string match from " + i + " to " + (i + len - 1));
|
||||||
|
DebugCommand.SendDebugMessage("With settings: " + settings);
|
||||||
|
ChatFormatUtils.sendMessageWithPointer(message, i, i + len - 1);
|
||||||
|
ignoredAreas.add(new int[]{i, i + len - 1});
|
||||||
|
return new FormattedSection(settings, i, i + len - 1, Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetSubclass() {
|
||||||
|
nextIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -71,6 +71,6 @@ public final class TellrawEvent<T extends TellrawEvent.Action> implements Serial
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static interface Action extends TellrawSerializableEnum {
|
public interface Action extends TellrawSerializableEnum {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ public abstract class TellrawSerializer {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
@Override
|
@Override
|
||||||
public void write(JsonWriter writer, Boolean val) throws IOException {
|
public void write(JsonWriter writer, Boolean val) throws IOException {
|
||||||
if (val)
|
if (val)
|
||||||
|
|
|
@ -12,8 +12,6 @@ import lombok.RequiredArgsConstructor;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
@CommandClass(helpText = {
|
@CommandClass(helpText = {
|
||||||
"Town Color", //
|
"Town Color", //
|
||||||
"This command allows setting a color for a town.", //
|
"This command allows setting a color for a town.", //
|
||||||
|
@ -23,18 +21,6 @@ import java.lang.reflect.Method;
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class TownColorCommand extends UCommandBase {
|
public class TownColorCommand extends UCommandBase {
|
||||||
private final TownColorComponent component;
|
private final TownColorComponent component;
|
||||||
@Override
|
|
||||||
public String[] getHelpText(Method method, Command2.Subcommand ann) {
|
|
||||||
StringBuilder cns = new StringBuilder(" <colorname1>");
|
|
||||||
for (int i = 2; i <= component.colorCount().get(); i++)
|
|
||||||
cns.append(" [colorname").append(i).append("]");
|
|
||||||
return new String[] { //
|
|
||||||
"§6---- Town Color ----", //
|
|
||||||
"This command allows setting color(s) 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 colors will split the name evenly.", //
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Command2.Subcommand
|
@Command2.Subcommand
|
||||||
public boolean def(Player player, String... colornames) {
|
public boolean def(Player player, String... colornames) {
|
||||||
|
|
|
@ -19,14 +19,12 @@ import lombok.val;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.dynmap.towny.DTBridge;
|
import org.dynmap.towny.DTBridge;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
@ -81,14 +79,10 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
|
||||||
var cs = getConfig().getConfig().getConfigurationSection("towncolors");
|
var cs = getConfig().getConfig().getConfigurationSection("towncolors");
|
||||||
if (cs != null)
|
if (cs != null)
|
||||||
loadTC.accept(cs);
|
loadTC.accept(cs);
|
||||||
else
|
|
||||||
load_old(loadTC, null); //Load old data
|
|
||||||
if (usenc) {
|
if (usenc) {
|
||||||
var ncs = getConfig().getConfig().getConfigurationSection("nationcolors");
|
var ncs = getConfig().getConfig().getConfigurationSection("nationcolors");
|
||||||
if (ncs != null)
|
if (ncs != null)
|
||||||
loadNC.accept(ncs);
|
loadNC.accept(ncs);
|
||||||
else
|
|
||||||
load_old(null, loadNC); //Why not choose by making different args null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TownColors.keySet().removeIf(t -> !TownyComponent.TU.getTownsMap().containsKey(t)); // Removes town colors for deleted/renamed towns
|
TownColors.keySet().removeIf(t -> !TownyComponent.TU.getTownsMap().containsKey(t)); // Removes town colors for deleted/renamed towns
|
||||||
|
@ -227,25 +221,4 @@ public class TownColorComponent extends Component<PluginMain> implements Listene
|
||||||
public void onPlayerJoin(TBMCPlayerJoinEvent event) {
|
public void onPlayerJoin(TBMCPlayerJoinEvent event) {
|
||||||
updatePlayerColors(event.getPlayer(), event.GetPlayer().asPluginPlayer(ChatPlayer.class));
|
updatePlayerColors(event.getPlayer(), event.GetPlayer().asPluginPlayer(ChatPlayer.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void load_old(Consumer<ConfigurationSection> loadTC,
|
|
||||||
Consumer<ConfigurationSection> loadNC) {
|
|
||||||
PluginMain.Instance.getLogger().info("Loading files...");
|
|
||||||
try {
|
|
||||||
File file = new File("TBMC/chatsettings.yml");
|
|
||||||
if (file.exists()) {
|
|
||||||
YamlConfiguration yc = new YamlConfiguration();
|
|
||||||
yc.load(file);
|
|
||||||
ConfigurationSection cs;
|
|
||||||
if (loadTC != null && (cs = yc.getConfigurationSection("towncolors")) != null)
|
|
||||||
loadTC.accept(cs);
|
|
||||||
if (loadNC != null && (cs = yc.getConfigurationSection("nationcolors")) != null)
|
|
||||||
loadNC.accept(cs);
|
|
||||||
PluginMain.Instance.getLogger().info("Loaded files!");
|
|
||||||
} else
|
|
||||||
PluginMain.Instance.getLogger().info("No files to load, first run probably.");
|
|
||||||
} catch (Exception e) {
|
|
||||||
TBMCCoreAPI.SendException("Error while loading chat files!", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
name: Chroma-Chat
|
name: Chroma-Chat
|
||||||
main: buttondevteam.chat.PluginMain
|
main: buttondevteam.chat.PluginMain
|
||||||
version: 4.0
|
version: '4.0'
|
||||||
commands:
|
commands:
|
||||||
u:
|
u:
|
||||||
description: Auto-flair system. Accept or ignore flair.
|
description: Auto-flair system. Accept or ignore flair.
|
||||||
|
|
|
@ -1,15 +1,5 @@
|
||||||
package buttondevteam.chat;
|
package buttondevteam.chat;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.junit.runner.Runner;
|
import org.junit.runner.Runner;
|
||||||
import org.junit.runner.notification.RunNotifier;
|
import org.junit.runner.notification.RunNotifier;
|
||||||
import org.junit.runners.BlockJUnit4ClassRunner;
|
import org.junit.runners.BlockJUnit4ClassRunner;
|
||||||
|
@ -20,6 +10,12 @@ import org.junit.runners.model.InitializationError;
|
||||||
import org.junit.runners.model.Statement;
|
import org.junit.runners.model.Statement;
|
||||||
import org.junit.runners.model.TestClass;
|
import org.junit.runners.model.TestClass;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Based on {@link Parameterized}
|
* Based on {@link Parameterized}
|
||||||
*
|
*
|
||||||
|
@ -32,10 +28,10 @@ public class ObjectTestRunner extends Suite {
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
public static @interface Objects {
|
public @interface Objects {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestClassRunnerForObjects extends BlockJUnit4ClassRunner {
|
private static class TestClassRunnerForObjects extends BlockJUnit4ClassRunner {
|
||||||
|
|
||||||
private List<Object> objectList;
|
private List<Object> objectList;
|
||||||
private int fParameterSetNumber;
|
private int fParameterSetNumber;
|
||||||
|
@ -77,13 +73,13 @@ public class ObjectTestRunner extends Suite {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ArrayList<Runner> runners = new ArrayList<Runner>();
|
private final ArrayList<Runner> runners = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only called reflectively. Do not use programmatically.
|
* Only called reflectively. Do not use programmatically.
|
||||||
*/
|
*/
|
||||||
public ObjectTestRunner(Class<?> klass) throws Throwable {
|
public ObjectTestRunner(Class<?> klass) throws Throwable {
|
||||||
super(klass, Collections.<Runner>emptyList());
|
super(klass, Collections.emptyList());
|
||||||
List<Object> objectsList = getObjectsList(getTestClass());
|
List<Object> objectsList = getObjectsList(getTestClass());
|
||||||
for (int i = 0; i < objectsList.size(); i++)
|
for (int i = 0; i < objectsList.size(); i++)
|
||||||
runners.add(new TestClassRunnerForObjects(getTestClass().getJavaClass(), objectsList, i));
|
runners.add(new TestClassRunnerForObjects(getTestClass().getJavaClass(), objectsList, i));
|
||||||
|
|
|
@ -5,11 +5,9 @@ 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.ChatFormatter;
|
import buttondevteam.chat.components.formatter.formatting.*;
|
||||||
import buttondevteam.chat.components.formatter.formatting.TellrawEvent;
|
|
||||||
import buttondevteam.chat.components.formatter.formatting.TellrawEvent.ClickAction;
|
import buttondevteam.chat.components.formatter.formatting.TellrawEvent.ClickAction;
|
||||||
import buttondevteam.chat.components.formatter.formatting.TellrawEvent.HoverAction;
|
import buttondevteam.chat.components.formatter.formatting.TellrawEvent.HoverAction;
|
||||||
import buttondevteam.chat.components.formatter.formatting.TellrawPart;
|
|
||||||
import buttondevteam.core.TestPrepare;
|
import buttondevteam.core.TestPrepare;
|
||||||
import buttondevteam.core.component.channel.Channel;
|
import buttondevteam.core.component.channel.Channel;
|
||||||
import buttondevteam.lib.chat.Color;
|
import buttondevteam.lib.chat.Color;
|
||||||
|
@ -32,7 +30,7 @@ public class ChatFormatIT {
|
||||||
DebugCommand.DebugMode = true;
|
DebugCommand.DebugMode = true;
|
||||||
PluginMain.permission = Mockito.mock(Permission.class);
|
PluginMain.permission = Mockito.mock(Permission.class);
|
||||||
|
|
||||||
List<Object> list = new ArrayList<Object>();
|
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*", new TellrawPart("test").setItalic(true).setColor(Color.White)));
|
||||||
list.add(new ChatFormatIT(sender, "**test**", new TellrawPart("test").setBold(true).setColor(Color.White)));
|
list.add(new ChatFormatIT(sender, "**test**", new TellrawPart("test").setBold(true).setColor(Color.White)));
|
||||||
|
@ -64,7 +62,7 @@ public class ChatFormatIT {
|
||||||
list.add(new ChatFormatIT(sender, "*https://norbipeti.github.io/ heh*", new TellrawPart("https://norbipeti.github.io/").setItalic(true).setUnderlined(true)
|
list.add(new ChatFormatIT(sender, "*https://norbipeti.github.io/ heh*", new TellrawPart("https://norbipeti.github.io/").setItalic(true).setUnderlined(true)
|
||||||
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT,
|
.setHoverEvent(TellrawEvent.create(HoverAction.SHOW_TEXT,
|
||||||
new TellrawPart("Click to open").setColor(Color.Blue)))
|
new TellrawPart("Click to open").setColor(Color.Blue)))
|
||||||
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/")), new TellrawPart(" heh").setItalic(true)));
|
.setClickEvent(TellrawEvent.create(ClickAction.OPEN_URL, "https://norbipeti.github.io/")).setColor(Color.White), new TellrawPart(" heh").setItalic(true).setColor(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*", new TellrawPart("test test test").setItalic(true).setColor(Color.White)));
|
||||||
list.add(new ChatFormatIT(sender, "*test __test__ test*", new TellrawPart("test ").setItalic(true).setColor(Color.White),
|
list.add(new ChatFormatIT(sender, "*test __test__ test*", new TellrawPart("test ").setItalic(true).setColor(Color.White),
|
||||||
new TellrawPart("test").setItalic(true).setUnderlined(true).setColor(Color.White), new TellrawPart(" test").setItalic(true).setColor(Color.White)));
|
new TellrawPart("test").setItalic(true).setUnderlined(true).setColor(Color.White), new TellrawPart(" test").setItalic(true).setColor(Color.White)));
|
||||||
|
@ -109,12 +107,12 @@ public class ChatFormatIT {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMessage() {
|
public void testMessage() {
|
||||||
ArrayList<ChatFormatter> cfs = ChatProcessing.addFormatters(Color.White, p -> true, null);
|
ArrayList<MatchProviderBase> cfs = ChatProcessing.addFormatters(p -> true, null);
|
||||||
final String chid = ChatProcessing.getChannelID(Channel.GlobalChat, ChatUtils.MCORIGIN);
|
final String chid = ChatProcessing.getChannelID(Channel.GlobalChat, ChatUtils.MCORIGIN);
|
||||||
if (rainbowMode)
|
if (rainbowMode)
|
||||||
ChatProcessing.createRPC(Color.White, cfs);
|
ChatProcessing.createRPC(Color.White, cfs);
|
||||||
final TellrawPart tp = ChatProcessing.createTellraw(sender, message, null, null, null, chid, ChatUtils.MCORIGIN);
|
final TellrawPart tp = ChatProcessing.createTellraw(sender, message, null, null, null, chid, ChatUtils.MCORIGIN);
|
||||||
ChatFormatter.Combine(cfs, message, tp, null);
|
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));
|
// System.out.println(ChatProcessing.toJson(tp));
|
||||||
final TellrawPart expectedtp = ChatProcessing.createTellraw(sender, message, null, null, null, chid, ChatUtils.MCORIGIN);
|
final TellrawPart expectedtp = ChatProcessing.createTellraw(sender, message, null, null, null, chid, ChatUtils.MCORIGIN);
|
||||||
|
|
Loading…
Reference in a new issue