Compare commits
246 commits
Author | SHA1 | Date | |
---|---|---|---|
d1515c2ab2 | |||
512a62d75c | |||
b5fd834dc7 | |||
e35e94e87c | |||
51cf31713b | |||
2242655c41 | |||
522f29ba58 | |||
10bf0e98df | |||
6c1378f370 | |||
56b9296fbb | |||
|
5c399a08ad | ||
724858ac70 | |||
9a10dcd1fc | |||
dc6df53c96 | |||
7646db4487 | |||
8e9989caee | |||
77b5a069c5 | |||
c52a6873fe | |||
c6ba0ec607 | |||
|
737016bf00 | ||
a63f2bb256 | |||
59dbc78b52 | |||
b483b7df0c | |||
4d4448fca1 | |||
02423153de | |||
ce4f40c2c4 | |||
|
372b2f49b3 | ||
7448eb7e3a | |||
c688ec9243 | |||
e4b47efd3f | |||
43525bd93c | |||
052149bcb7 | |||
5d8ae7fbd0 | |||
f3ec9e7870 | |||
0421cc6d16 | |||
aad65e0222 | |||
03b91d2fdb | |||
661534b92d | |||
6af2ad79a7 | |||
f19aa41205 | |||
4952923f9b | |||
4d0c7c170e | |||
0dbfaa65a5 | |||
30ee99d495 | |||
1dc801575a | |||
0a4cdd01ce | |||
b452170ff7 | |||
c66b212b0c | |||
2d874d7bc9 | |||
cda2a36da1 | |||
d5f500aece | |||
2a9bc58157 | |||
22c7fed75d | |||
825e327903 | |||
fd3d3df108 | |||
c0128831a7 | |||
013287cb47 | |||
cc6c477add | |||
a91ee1b842 | |||
aa455e373d | |||
6a16a3a1d5 | |||
750b71de65 | |||
bd656015bf | |||
fa375c4912 | |||
a964ce6595 | |||
4a456d9b1e | |||
a4b7f689c0 | |||
b3939f3c92 | |||
1275cdafd0 | |||
f3904a8448 | |||
415e61a401 | |||
7b2ecdbf7b | |||
4956837e5d | |||
3ad2346990 | |||
8907d5308f | |||
bbe9a8c146 | |||
80e45aa1a9 | |||
c25097b525 | |||
049ad55168 | |||
c7f04b8731 | |||
073346eb7f | |||
5b5252382e | |||
e510667215 | |||
ae49777007 | |||
8ff45ad676 | |||
4744f2edf9 | |||
f7c1106d1c | |||
40a1739951 | |||
c5e33a93ba | |||
26b44fbfe1 | |||
36655dfd84 | |||
df7f8bca5e | |||
e2a6afd16a | |||
21bf41db2b | |||
185b0df8e0 | |||
f12912c735 | |||
d0e4447126 | |||
3a29010042 | |||
0802de4b6f | |||
3f387a9775 | |||
25ce2a4c9f | |||
8ccf3ee9d7 | |||
bfe7d48760 | |||
be29caa904 | |||
2b621adefb | |||
aed7864a15 | |||
720740dea3 | |||
99a8c1b020 | |||
12072f3106 | |||
1081f3cf9d | |||
f8539a0392 | |||
cf8af73ed0 | |||
fd72e2de91 | |||
dedfbacda6 | |||
6da19877b8 | |||
71aeafadda | |||
304f5c562d | |||
df6e76086b | |||
241992571e | |||
58d8d1276f | |||
3124d41f54 | |||
e6ada0b2d0 | |||
775789a451 | |||
0ac78c9cb2 | |||
83c99df895 | |||
c080a857fd | |||
45b273e036 | |||
c5cae54aea | |||
7006f178b9 | |||
24c9e2d494 | |||
62caf31727 | |||
44488a78ad | |||
4f2abe41b8 | |||
e6ac18e0c7 | |||
01562bf769 | |||
050fd88560 | |||
f2a7a10ef7 | |||
ab5c9e3ea6 | |||
bf1a5562a0 | |||
79d0d06044 | |||
b174b8969e | |||
68de2f36cf | |||
ef2328e126 | |||
71242cc0ac | |||
6d3d24ecbf | |||
0c768b95e8 | |||
4a7d7379b0 | |||
6202e30522 | |||
991ca23918 | |||
2de3f1f6e7 | |||
e5053a0483 | |||
4006cdad58 | |||
1c0c29ae96 | |||
4340a50789 | |||
91e44c20c2 | |||
f671b6e9d6 | |||
029a7f1deb | |||
35ccf22a55 | |||
840b522a98 | |||
5a217fcb70 | |||
c129e5b18b | |||
b4de61adf8 | |||
ae3c05c14a | |||
9057ab9f15 | |||
cee69dc55b | |||
06ea519987 | |||
b5e8e0f93c | |||
9abcde610e | |||
e0459fa36f | |||
ee1430036c | |||
7174a97728 | |||
2ab6a5f4eb | |||
91c22e650b | |||
d0a990e0f1 | |||
1d1b3453b3 | |||
2f83a90553 | |||
9ab875f73b | |||
16acba643f | |||
51c3e1dec6 | |||
0de469e514 | |||
437d9e8f98 | |||
1c32dbd949 | |||
107a60eb2e | |||
5e7da1e89a | |||
bae49352ef | |||
2aa0443286 | |||
55053d635e | |||
39ef366c20 | |||
2b48aba75e | |||
4b55c76fd5 | |||
3e0a49659d | |||
2c631b28bc | |||
ad3d3ecaf9 | |||
6ee8ca0f4c | |||
9d7b244a74 | |||
c078a292ec | |||
12b1a45558 | |||
bcd6d3f194 | |||
d4c016b495 | |||
3e1df267cf | |||
28aeb35573 | |||
07fccda8d3 | |||
9e1bd49cd0 | |||
8f69e40d8b | |||
db37482134 | |||
7751defc9f | |||
5da1083067 | |||
a7a677d85a | |||
ec5c90ecc8 | |||
758332faf6 | |||
441e9a4eaf | |||
0da4a543e5 | |||
fa95891a6a | |||
a36c6b564b | |||
d13dfc3eb2 | |||
c6031a6f11 | |||
3cd1707182 | |||
d0e038cdd3 | |||
e8fa82d10d | |||
7de0ecc87d | |||
2594721152 | |||
0f74ad4cb1 | |||
eba73d6db4 | |||
81b188f338 | |||
94252e446d | |||
dc9bcd2cfd | |||
1fe200cf3f | |||
5e20689dc1 | |||
3ab97276f6 | |||
4311a567c5 | |||
1bb3ddb0ee | |||
f39ed23699 | |||
15ece1a3dc | |||
888086f427 | |||
|
596a4e422e | ||
|
e2b33f5342 | ||
|
63f7106000 | ||
da3eacc2e1 | |||
08640f404d | |||
a3b3af859a | |||
845f3e1f16 | |||
a09a30d460 | |||
6d75e9bd9e | |||
0a4ab5a46e | |||
a058990075 | |||
a2ad97faec |
100 changed files with 4893 additions and 3618 deletions
19
.editorconfig
Normal file
19
.editorconfig
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = false
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.json]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.java]
|
||||||
|
indent_style = tab
|
||||||
|
tab_width = 4
|
||||||
|
|
||||||
|
[{*.yml, *.yaml}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -69,14 +69,12 @@ build/
|
||||||
*.tlb
|
*.tlb
|
||||||
*.tli
|
*.tli
|
||||||
*.tlh
|
*.tlh
|
||||||
*.tmp
|
|
||||||
*.tmp_proj
|
*.tmp_proj
|
||||||
*.log
|
*.log
|
||||||
*.vspscc
|
*.vspscc
|
||||||
*.vssscc
|
*.vssscc
|
||||||
.builds
|
.builds
|
||||||
*.pidb
|
*.pidb
|
||||||
*.log
|
|
||||||
*.scc
|
*.scc
|
||||||
|
|
||||||
# Visual C++ cache files
|
# Visual C++ cache files
|
||||||
|
@ -131,7 +129,7 @@ publish/
|
||||||
*.publishproj
|
*.publishproj
|
||||||
|
|
||||||
# NuGet Packages Directory
|
# NuGet Packages Directory
|
||||||
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
|
## TO!DO: If you have NuGet Package Restore enabled, uncomment the next line
|
||||||
#packages/
|
#packages/
|
||||||
|
|
||||||
# Windows Azure Build Output
|
# Windows Azure Build Output
|
||||||
|
@ -195,7 +193,6 @@ $RECYCLE.BIN/
|
||||||
*.egg
|
*.egg
|
||||||
*.egg-info
|
*.egg-info
|
||||||
dist/
|
dist/
|
||||||
build/
|
|
||||||
eggs/
|
eggs/
|
||||||
parts/
|
parts/
|
||||||
var/
|
var/
|
||||||
|
@ -221,3 +218,4 @@ TheButtonAutoFlair/out/artifacts/Autoflair/Autoflair.jar
|
||||||
*.name
|
*.name
|
||||||
.idea/compiler.xml
|
.idea/compiler.xml
|
||||||
*.xml
|
*.xml
|
||||||
|
/.apt_generated/
|
||||||
|
|
0
.idea/ButtonChat.iml
Normal file
0
.idea/ButtonChat.iml
Normal file
2
.project
2
.project
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<projectDescription>
|
<projectDescription>
|
||||||
<name>ButtonChat</name>
|
<name>Chroma-Chat</name>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
<projects>
|
<projects>
|
||||||
</projects>
|
</projects>
|
||||||
|
|
20
.travis.yml
20
.travis.yml
|
@ -1 +1,21 @@
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/.m2/repository/org/
|
||||||
|
before_install: | # Wget BuildTools and run if cached folder not found
|
||||||
|
if [ ! -d "$HOME/.m2/repository/org/spigotmc/spigot/1.12.2-R0.1-SNAPSHOT" ]; then
|
||||||
|
wget -O BuildTools.jar https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar
|
||||||
|
# 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*$"
|
||||||
|
fi
|
||||||
language: java
|
language: java
|
||||||
|
jdk:
|
||||||
|
- oraclejdk11
|
||||||
|
sudo: true
|
||||||
|
deploy:
|
||||||
|
- provider: releases
|
||||||
|
api_key:
|
||||||
|
secure: "F5YiEuD6LyRENUDMCslcSl0O0dg4IDk+nNeb4X2VLYlmb8dW9beMuIgjH8efTMeaQ3D/ntIkN0Dtf2GKvpOduhwkSbAgw4WM028X60SY9f2hmpEO3LmM4T1tKoDlI1T3BmhYP4KeTKBYn+etV1mSPbT07vUybCm/vGzvr96yMZGNFEoKsWLaEu7dZfBFULj4tXOwrLh/KO6BsdAHvZcGKWNVupPq3YoUVT0dpGcUudf5cpn+aaqMwyd709zgMbyCuqf+c5Udps43q4EKvr9z7TWxFUkGTPVVAcUVygJsi2ytuyA8TLMPq/KhYe9htnkNUnizbqv/j49xww0gVaD7OJXENJ4hAUTV4sdn1DXG45JXW+dir3V7YzbRYn3M+eCuKB2O77SXRZBkxcGtTMtCmghP9/tcRAQlXDXnxu7oAnlUVp17g/+aFApvlzZEZVx2N+fkyEe7JrUFlRCixtHyrmTLWhyV0Px9p0FHJpvSSCL0S0UKVAT/sNHYHhD5gouK7owEomEbG58XCsRDH6Et7RuDksB98ekK8brZp6S7dNIS2CVuVx1vIkXC8PzUGcpJQoztvEYUE20Axahh5s8AkE9n/O9jzs9ajcfYaHhWzYeUZzHdHllOYF9l6VoCUitTk4Sl8eJifSq3GzI+T6wGMBepZHLpe230MvBIrqGZ+Vg="
|
||||||
|
file: 'target/Chroma-Chat.jar'
|
||||||
|
on:
|
||||||
|
tags: 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
|
|
143
README.md
143
README.md
|
@ -1,133 +1,28 @@
|
||||||
# The Button Minecraft server chat plugin
|
# Chroma-Chat plugin
|
||||||
|
A plugin that provides markdown formatting, name mentioning and other chat features.
|
||||||
|
|
||||||
## How to use
|
## Components
|
||||||
### Players
|
|
||||||
#### Obtaining the flair (/u accept)
|
|
||||||
At first, you need to connect your Reddit account with your Minecraft account. This is done by writing your Minecraft name to [this thread](https://www.reddit.com/r/Chromagamers/comments/51ys94/flair_thread_for_the_mc_server/), following the instructions in the post.
|
|
||||||
|
|
||||||
When you're done, connect to the server, if you aren't already on. You should see a message after a while (max. 10 seconds) asking if you're the correct Reddit user. Type /u accept to confirm it and accept your flair.
|
### Announcer
|
||||||
|
This component simply sends messages globally based on a configurable list in a given interval.
|
||||||
|
|
||||||
__Note__: You can comment your ingame name from multiple Reddit accounts. In this case, you'll need to specify the exact username you want to pair with your Minecraft account. For example:
|
### Append text
|
||||||
|
This component allows the players to put tableflips and other texts after their messages using /tableflip and other commands.
|
||||||
|
|
||||||
/u accept NorbiPeti
|
### Chat-only
|
||||||
|
This component lets a player become invincible at the cost of not being able to move. It was made for chat clients.
|
||||||
|
|
||||||
#### Hiding the message (/u ignore)
|
### Flair
|
||||||
You can use this command to hide the notice showing up after you log in if you don't have a flair accepted.
|
This component downloads /r/TheButton flairs from Reddit for users who comment in a specific thread. This was the original function of the plugin.
|
||||||
|
|
||||||
#### Flair not showing up
|
### Formatter
|
||||||
Please note that in some cases your flair cannot be obtained (specifically, if it's not stored by karmadecay.com, in which case possibly Karmancer can't show it as well). In this case, there are two possibilities.
|
This component provides the Markdown and other formatting and name mentioning.
|
||||||
|
|
||||||
If you're a non-presser or a can't press and only your time is recorded, it will automatically decide based on your account creation date.
|
### Fun
|
||||||
|
This component has some random things I added for fun, including "Press F to pay respects" and rainbow chat.
|
||||||
|
|
||||||
If nothing is known about your flair, you need to ask an admin to set the flair for you. Please prepare a link to a comment you made on /r/thebutton, if possible.
|
### Town colors
|
||||||
|
This component allows mayors and kings to set a color for their town/nation, which sets each resident's name colors and also shows on Dynmap.
|
||||||
|
|
||||||
#### Getting someone's Reddit username (/u name)
|
### Towny
|
||||||
You can see a player's username if they have a flair shown.
|
This component is needed by the town colors component. Besides, it reads Towny events to be broadcasted to Discord, if that plugin is used.
|
||||||
|
|
||||||
#### Name mentioning
|
|
||||||
If you simply say any online player's full playername or nickname, it'll highlight it and play a sound for the target player.
|
|
||||||
|
|
||||||
If you say a nickname, it'll show it's original colors, if you say a username, then it will choose based on flair color if known, otherwise it'll use the aqua color.
|
|
||||||
|
|
||||||
You can also use @console to ping the console. If someone is there, they'll receive an audible bell signal.
|
|
||||||
|
|
||||||
#### RP/OOC mode (/nrp or /ooc)
|
|
||||||
You can use /ooc <message> to say something Out-of-Character. Otherwise everything you speak should be treated as said in RP, except when it is obvious it's not in RP (like talking about the server).
|
|
||||||
|
|
||||||
#### Greentext support (>message)
|
|
||||||
Start your message with '>' to make it green.
|
|
||||||
|
|
||||||
#### Hashtags (#hashtag)
|
|
||||||
If you say a hashtag in global chat, it'll highlight it and makes it clickable, linking to the hashtag page on Twitter.
|
|
||||||
|
|
||||||
#### Paying respects (F)
|
|
||||||
If a player dies, sometimes the plugin will tell everyone "Press F to pay respects.". After a few seconds, a message will tell everyone how many people paid their respects.
|
|
||||||
|
|
||||||
If you hover over a player's name in chat, you can see how much respect they gained this way, divided by the number of eligible deaths.
|
|
||||||
|
|
||||||
#### Copy messages
|
|
||||||
To copy a message from chat, click the channel identifier (for example: [g] or [TC]) at the beginning of the message.
|
|
||||||
|
|
||||||
#### Tableflipping (/tableflip and /unflip) and shrug (/shrug)
|
|
||||||
The idea of this command came from Discord.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
/tableflip - (╯°□°)╯︵ ┻━┻
|
|
||||||
/tableflip test - test(╯°□°)╯︵ ┻━┻
|
|
||||||
/unflip - ┬─┬ ノ( ゜-゜ノ)
|
|
||||||
/unflip test - test┬─┬ ノ( ゜-゜ノ)
|
|
||||||
|
|
||||||
#### Chat only (/chatonly)
|
|
||||||
You can use this mode to protect yourself if you connect from a chat-only client. This will make you invincible, but unable to move, teleport or interact with the world in any way.
|
|
||||||
|
|
||||||
#### Rainbow chat (/u c)
|
|
||||||
Chat in rainbow/Presser colors.
|
|
||||||
|
|
||||||
### Admins
|
|
||||||
Type /u admin for a list of the commands.
|
|
||||||
#### Seeing player information (/u admin playerinfo)
|
|
||||||
You can check someone's flair status and other infos in case something goes wrong.
|
|
||||||
|
|
||||||
It outputs the player name (useful if something goes *really* wrong), the player's current ingame flair, the Reddit username, and their flair status:
|
|
||||||
|
|
||||||
* Accepted: The user has a flair shown after their name.
|
|
||||||
* Ignored: The user chose to hide their flair, but they have one.
|
|
||||||
* Recognised: The user has recognised flair(s) but haven't accepted any.
|
|
||||||
* Commented: The user commented, but their flair isn't known.
|
|
||||||
* NoComment: The user haven't commented in the thread.
|
|
||||||
|
|
||||||
#### Reloading the plugin (/u admin reload)
|
|
||||||
This is useful if you want to change a file related to the plugin.
|
|
||||||
|
|
||||||
Be careful and make sure you do /u admin save before you reload the plugin. You need to confirm your action (/u admin confirm) to make sure no setting is lost.
|
|
||||||
|
|
||||||
If you want to edit a file, you need to do /u admin save, then edit the file you want, then do /u admin reload.
|
|
||||||
|
|
||||||
#### Setting the flair by hand (/u admin setflair)
|
|
||||||
This allows you to set any flair you want to any player. This will override the automatic flairs, though it's not recommended to do so. However, the player can reset the automatic flair at any time (see /u accept).
|
|
||||||
|
|
||||||
* To remove a user's flair:
|
|
||||||
|
|
||||||
/u admin setflair <playername> none false
|
|
||||||
|
|
||||||
* To set a non-presser or can't press flair:
|
|
||||||
|
|
||||||
/u admin setflair <playername> non-presser/cant-press false
|
|
||||||
|
|
||||||
* To set a cheater flair:
|
|
||||||
|
|
||||||
/u admin setflair <playername> <time> true
|
|
||||||
|
|
||||||
* To also set the username for the flair:
|
|
||||||
|
|
||||||
/u admin setflair <playername> <time> <cheater> <username>
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
|
|
||||||
/u admin setflair <playername> <time (without s) or non-presser, can't press, none> <cheater (true/false)>> [username]
|
|
||||||
|
|
||||||
#### Updating the plugin (/u admin updateplugin)
|
|
||||||
I've made a simple command to allow updating the plugin easily. After running this command, the server needs to get restarted for the changes to take effect.
|
|
||||||
|
|
||||||
This command will not do any other thing than downloading the JAR file from here to the plugins directory. Do not spam it, because it will then generate unnecessary network traffic on the server.
|
|
||||||
|
|
||||||
#### Toggle settings
|
|
||||||
|
|
||||||
/u admin togglerpshow - Toggles [RP] tag shown at each message except /ooc or /nrp.
|
|
||||||
/u admin debug - Toggles debug mode. Currently it outputs a lot of info about the chat formatting.
|
|
||||||
|
|
||||||
#### Setting the sound played on name mentioning
|
|
||||||
You can set the sound played by editing "notificationsound" and "notificationpitch" in the config file (thebuttonmc.yml).
|
|
||||||
|
|
||||||
#### Announcements (/u announce)
|
|
||||||
You can make announcements broadcasted every n minutes where you can set n and it defaults to 15.
|
|
||||||
|
|
||||||
/u announce add <message> - Adds a new announcement. It supports formatting codes with &.
|
|
||||||
/u announce remove <index> - Remove announcement by index (see below).
|
|
||||||
/u announce list - List announcements with indexes.
|
|
||||||
/u announce settime <minutes> - Set the time between announcements in minutes.
|
|
||||||
/u announce edit <index> <message> - Directly edits the announcement at the specified index. If there are less announcements than index, it'll create enough announcements.
|
|
||||||
|
|
||||||
#### Color modes (/u c)
|
|
||||||
Use /u c \<colorname\> to set the color of your messages.
|
|
||||||
|
|
Binary file not shown.
1
lombok.config
Normal file
1
lombok.config
Normal file
|
@ -0,0 +1 @@
|
||||||
|
lombok.var.flagUsage = ALLOW
|
213
pom.xml
213
pom.xml
|
@ -1,18 +1,17 @@
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<parent>
|
||||||
<name>The Button Minecraft Chat Plugin</name>
|
<groupId>com.github.TBMCPlugins.ChromaCore</groupId>
|
||||||
<description>The Button Minecraft Chat Plugin</description>
|
<artifactId>CorePOM</artifactId>
|
||||||
|
<version>master-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<version>v${noprefix.version}-SNAPSHOT</version>
|
||||||
|
<name>Chroma-Chat Plugin</name>
|
||||||
|
<description>Chroma-Chat Plugin</description>
|
||||||
<build>
|
<build>
|
||||||
<sourceDirectory>src/main/java</sourceDirectory>
|
<sourceDirectory>src/main/java</sourceDirectory>
|
||||||
<resources>
|
<resources>
|
||||||
<resource>
|
|
||||||
<directory>src</directory>
|
|
||||||
<excludes>
|
|
||||||
<exclude>**/*.java</exclude>
|
|
||||||
</excludes>
|
|
||||||
</resource>
|
|
||||||
<resource>
|
<resource>
|
||||||
<directory>src/main/resources</directory>
|
<directory>src/main/resources</directory>
|
||||||
<includes>
|
<includes>
|
||||||
|
@ -24,42 +23,8 @@
|
||||||
<filtering>true</filtering>
|
<filtering>true</filtering>
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
<finalName>ButtonChat</finalName>
|
<finalName>Chroma-Chat</finalName>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<version>3.3</version>
|
|
||||||
<configuration>
|
|
||||||
<source>1.8</source>
|
|
||||||
<target>1.8</target>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
|
||||||
<version>2.4.2</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>shade</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<artifactSet>
|
|
||||||
<includes>
|
|
||||||
<include>net.sourceforge.htmlcleaner:htmlcleaner</include>
|
|
||||||
<include>org.javassist:javassist</include>
|
|
||||||
</includes>
|
|
||||||
</artifactSet>
|
|
||||||
<pluginExecution>
|
|
||||||
<action>
|
|
||||||
<execute />
|
|
||||||
</action>
|
|
||||||
</pluginExecution>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-resources-plugin</artifactId>
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
@ -82,6 +47,25 @@
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-failsafe-plugin</artifactId>
|
||||||
|
<version>2.12.4</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>integration-test</goal>
|
||||||
|
<goal>verify</goal>
|
||||||
|
</goals>
|
||||||
|
<phase>test</phase>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<testFailureIgnore>true</testFailureIgnore>
|
||||||
|
<useSystemClassLoader>false
|
||||||
|
</useSystemClassLoader> <!-- https://stackoverflow.com/a/53012553/2703239 -->
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
<groupId>buttondevteam</groupId>
|
<groupId>buttondevteam</groupId>
|
||||||
|
@ -91,82 +75,128 @@
|
||||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||||
</repository>
|
</repository>
|
||||||
<repository>
|
<repository>
|
||||||
<id>jitpack.io</id>
|
<id>jitpack</id>
|
||||||
<url>https://jitpack.io/</url>
|
<url>https://jitpack.io/</url>
|
||||||
</repository>
|
</repository>
|
||||||
<repository>
|
<repository>
|
||||||
<id>Essentials</id>
|
<id>ess-repo</id>
|
||||||
<url>http://repo.ess3.net/</url>
|
<url>https://repo.essentialsx.net/releases/</url>
|
||||||
</repository>
|
</repository>
|
||||||
<repository>
|
<!-- <repository>
|
||||||
<id>Votifier</id>
|
|
||||||
<url>http://repo.howaner.de/</url>
|
|
||||||
</repository>
|
|
||||||
<repository>
|
|
||||||
<id>Minigames</id>
|
<id>Minigames</id>
|
||||||
<url>http://maven.addstar.com.au/artifactory/release</url>
|
<url>http://maven.addstar.com.au/artifactory/release</url>
|
||||||
</repository>
|
</repository> -->
|
||||||
<repository>
|
<!-- <repository>
|
||||||
<id>vault-repo</id>
|
<id>vault-repo</id>
|
||||||
<url>http://nexus.hc.to/content/repositories/pub_releases</url>
|
<url>http://nexus.hc.to/content/repositories/pub_releases</url>
|
||||||
</repository>
|
</repository> -->
|
||||||
<!-- <repository> <id>WorldEdit</id> <url>http://maven.sk89q.com/artifactory/repo</url>
|
<!-- <repository> <id>WorldEdit</id> <url>http://maven.sk89q.com/artifactory/repo</url>
|
||||||
</repository> -->
|
</repository> -->
|
||||||
|
<repository>
|
||||||
|
<id>projectlombok.org</id>
|
||||||
|
<url>https://projectlombok.org/mavenrepo</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>Dynmap</id>
|
||||||
|
<url>https://repo.mikeprimm.com</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>papermc</id>
|
||||||
|
<url>https://repo.papermc.io/repository/maven-public/</url>
|
||||||
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency> <!-- TODO: Can't update MockBukkit because of a ByteBuddy exception and the old version relies on 1.19.1 -->
|
||||||
<groupId>org.spigotmc</groupId>
|
<groupId>io.papermc.paper</groupId>
|
||||||
<artifactId>spigot-api</artifactId>
|
<artifactId>paper-api</artifactId>
|
||||||
<version>1.9.2-R0.1-SNAPSHOT</version>
|
<version>1.19.1-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.TBMCPlugins.ButtonCore</groupId>
|
<groupId>com.github.TBMCPlugins.ChromaCore</groupId>
|
||||||
<artifactId>ButtonCore</artifactId>
|
<artifactId>Chroma-Core</artifactId>
|
||||||
<version>master-SNAPSHOT</version>
|
<version>v2.0.0-SNAPSHOT</version>
|
||||||
</dependency>
|
|
||||||
<!-- https://mvnrepository.com/artifact/net.sourceforge.htmlcleaner/htmlcleaner -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.sourceforge.htmlcleaner</groupId>
|
|
||||||
<artifactId>htmlcleaner</artifactId>
|
|
||||||
<version>2.16</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- https://mvnrepository.com/artifact/org.reflections/reflections -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.reflections</groupId>
|
|
||||||
<artifactId>reflections</artifactId>
|
|
||||||
<version>0.9.10</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.ess3</groupId>
|
<groupId>net.essentialsx</groupId>
|
||||||
<artifactId>Essentials</artifactId>
|
<artifactId>EssentialsX</artifactId>
|
||||||
<version>2.13.1</version>
|
<version>2.19.2</version>
|
||||||
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.TBMCPlugins.ButtonCore</groupId>
|
<groupId>com.github.TownyAdvanced</groupId>
|
||||||
<artifactId>Towny</artifactId>
|
<artifactId>Towny</artifactId>
|
||||||
<version>master-SNAPSHOT</version>
|
<!-- <version>8d3b6b6</version> ButtonCore repo -->
|
||||||
</dependency>
|
<version>0.98.6.0</version>
|
||||||
<dependency>
|
<scope>provided</scope>
|
||||||
<groupId>com.vexsoftware</groupId>
|
|
||||||
<artifactId>votifier</artifactId>
|
|
||||||
<version>1.9</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- <dependency> <groupId>au.com.mineauz</groupId> <artifactId>Minigames</artifactId>
|
<!-- <dependency> <groupId>au.com.mineauz</groupId> <artifactId>Minigames</artifactId>
|
||||||
<version>1.8.0</version> </dependency> -->
|
<version>1.8.0</version> </dependency> -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.milkbowl.vault</groupId>
|
<groupId>com.github.MilkBowl</groupId>
|
||||||
<artifactId>VaultAPI</artifactId>
|
<artifactId>VaultAPI</artifactId>
|
||||||
<version>1.6</version>
|
<version>1.7</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
|
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.javassist</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>javassist</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>3.20.0-GA</version>
|
<version>1.18.22</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- <dependency>
|
||||||
|
<groupId>org.spigotmc</groupId>
|
||||||
|
<artifactId>spigot</artifactId>
|
||||||
|
<version>1.16.4-R0.1-SNAPSHOT</version>
|
||||||
|
</dependency> -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.TownyAdvanced</groupId>
|
||||||
|
<artifactId>Dynmap-Towny</artifactId>
|
||||||
|
<version>0.89</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>us.dynmap</groupId>
|
||||||
|
<artifactId>dynmap-api</artifactId>
|
||||||
|
<version>3.2-beta-1</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/junit/junit -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.13.2</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- Included in vanilla minecraft's JAR -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-core</artifactId>
|
||||||
|
<version>2.17.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- TestPrepare also needs it (ChromaCore) so the versions should match -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
<version>4.2.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/com.mojang/brigadier -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.mojang</groupId>
|
||||||
|
<artifactId>brigadier</artifactId>
|
||||||
|
<version>1.0.500</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.seeseemelk</groupId>
|
||||||
|
<artifactId>MockBukkit-v1.19</artifactId>
|
||||||
|
<version>2.29.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<artifactId>ButtonChat</artifactId>
|
<artifactId>Chroma-Chat</artifactId>
|
||||||
<organization>
|
<organization>
|
||||||
<name>TBMCPlugins</name>
|
<name>TBMCPlugins</name>
|
||||||
<url>https://github.com/TBMCPlugins</url>
|
<url>https://github.com/TBMCPlugins</url>
|
||||||
|
@ -175,5 +205,6 @@
|
||||||
<!-- github server corresponds to entry in ~/.m2/settings.xml -->
|
<!-- github server corresponds to entry in ~/.m2/settings.xml -->
|
||||||
<github.global.server>githubo</github.global.server>
|
<github.global.server>githubo</github.global.server>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<noprefix.version>1.0.0</noprefix.version>
|
||||||
</properties>
|
</properties>
|
||||||
</project>
|
</project>
|
|
@ -1,25 +0,0 @@
|
||||||
package buttondevteam.chat;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public class AnnouncerThread {
|
|
||||||
private static int AnnounceMessageIndex = 0;
|
|
||||||
|
|
||||||
public static void Run() {
|
|
||||||
while (!PluginMain.Instance.stop) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(PluginMain.AnnounceTime);
|
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
if (PluginMain.AnnounceMessages.size() > AnnounceMessageIndex) {
|
|
||||||
for (Player player : PluginMain.GetPlayers())
|
|
||||||
player.sendMessage(PluginMain.AnnounceMessages
|
|
||||||
.get(AnnounceMessageIndex));
|
|
||||||
AnnounceMessageIndex++;
|
|
||||||
if (AnnounceMessageIndex == PluginMain.AnnounceMessages.size())
|
|
||||||
AnnounceMessageIndex = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,105 +1,61 @@
|
||||||
package buttondevteam.chat;
|
package buttondevteam.chat;
|
||||||
|
|
||||||
import java.util.List;
|
import buttondevteam.chat.components.flair.FlairStates;
|
||||||
import java.util.Optional;
|
import buttondevteam.lib.architecture.config.IConfigData;
|
||||||
|
import buttondevteam.lib.architecture.config.IListConfigData;
|
||||||
|
import buttondevteam.lib.chat.Color;
|
||||||
|
import buttondevteam.lib.player.PlayerClass;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import buttondevteam.chat.formatting.ChatFormatter;
|
import java.util.Collections;
|
||||||
import buttondevteam.lib.TBMCPlayer;
|
|
||||||
import buttondevteam.lib.chat.*;
|
|
||||||
|
|
||||||
public class ChatPlayer extends TBMCPlayer {
|
@PlayerClass(pluginname = "Chroma-Chat")
|
||||||
public String getUserName() {
|
public class ChatPlayer extends TBMCPlayerBase {
|
||||||
return getData();
|
public final IConfigData<String> UserName = getConfig().getData("UserName", "");
|
||||||
}
|
|
||||||
|
|
||||||
public void setUserName(String name) {
|
public final IListConfigData<String> UserNames = getConfig().getListData("UserNames", Collections.emptyList());
|
||||||
setData(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getUserNames() {
|
public final IConfigData<Integer> FlairTime = getConfig().getData("FlairTime", FlairTimeNone);
|
||||||
return getData();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUserNames(List<String> names) {
|
public final IConfigData<FlairStates> FlairState = getConfig().getData("FlairState", FlairStates.NoComment,
|
||||||
setData(names);
|
fs -> FlairStates.valueOf((String) fs), FlairStates::toString);
|
||||||
}
|
|
||||||
|
|
||||||
public short getFlairTime() {
|
public final IConfigData<Integer> FCount = getConfig().getData("FCount", 0);
|
||||||
return getIntData(Short.class).orElse(FlairTimeNone);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setFlairTime(short time) {
|
public final IConfigData<Integer> FDeaths = getConfig().getData("FDeaths", 0);
|
||||||
setIntData(time);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FlairStates getFlairState() {
|
public final IConfigData<Boolean> FlairCheater = getConfig().getData("FlairCheater", false);
|
||||||
return getEnumData(FlairStates.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFlairState(FlairStates state) {
|
public final IListConfigData<Integer> NameColorLocations = getConfig().getListData("NameColorLocations", Collections.emptyList()); // No byte[], no TIntArrayList
|
||||||
setEnumData(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getFCount() {
|
|
||||||
return getIntData(Integer.class).orElse(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFCount(int count) {
|
|
||||||
setIntData(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getFDeaths() {
|
|
||||||
return getIntData(Integer.class).orElse(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFDeaths(int count) {
|
|
||||||
setIntData(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getFlairCheater() {
|
|
||||||
return getData();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setFlairCheater(boolean cheater) {
|
|
||||||
setData(cheater);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean RPMode = true;
|
|
||||||
public boolean PressedF;
|
|
||||||
public Location SavedLocation;
|
|
||||||
public boolean Working;
|
public boolean Working;
|
||||||
// public int Tables = 10;
|
// public int Tables = 10;
|
||||||
public Channel CurrentChannel = Channel.GlobalChat;
|
|
||||||
public boolean SendingLink = false;
|
|
||||||
public boolean RainbowPresserColorMode = false;
|
public boolean RainbowPresserColorMode = false;
|
||||||
public Color OtherColorMode = null;
|
public Color OtherColorMode = null;
|
||||||
public boolean ChatOnly = false;
|
public boolean ChatOnly = false;
|
||||||
public int LoginWarningCount = 0;
|
public long LastMessageTime = 0L;
|
||||||
|
|
||||||
public static final short FlairTimeNonPresser = -1;
|
public static final int FlairTimeNonPresser = -1;
|
||||||
public static final short FlairTimeCantPress = -2;
|
public static final int FlairTimeCantPress = -2;
|
||||||
public static final short FlairTimeNone = -3;
|
public static final int FlairTimeNone = -3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the player's flair, optionally formatting for Minecraft.
|
* Gets the player's flair, optionally formatting for Minecraft.
|
||||||
*
|
*
|
||||||
* @param noformats
|
* @param noformats The MC formatting codes will be only applied if false
|
||||||
* The MC formatting codes will be only applied if false
|
|
||||||
* @return The flair
|
* @return The flair
|
||||||
*/
|
*/
|
||||||
public String GetFormattedFlair(boolean noformats) {
|
public String GetFormattedFlair(boolean noformats) {
|
||||||
if (getFlairTime() == FlairTimeCantPress)
|
int time = FlairTime.get();
|
||||||
return String.format(noformats ? "(can't press)" : "§r(--s)§r");
|
if (time == FlairTimeCantPress)
|
||||||
if (getFlairTime() == FlairTimeNonPresser)
|
return noformats ? "(can't press)" : "§r(--s)§r";
|
||||||
return String.format(noformats ? "(non-presser)" : "§7(--s)§r");
|
if (time == FlairTimeNonPresser)
|
||||||
if (getFlairTime() == FlairTimeNone)
|
return noformats ? "(non-presser)" : "§7(--s)§r";
|
||||||
|
if (time == FlairTimeNone)
|
||||||
return "";
|
return "";
|
||||||
return noformats ? String.format("(%ss)", getFlairTime())
|
return noformats ? String.format("(%ds)", time) : String.format("§%x(%ds)§r", GetFlairColor(), time);
|
||||||
: String.format("§%x(%ss)§r", GetFlairColor(), getFlairTime());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -111,14 +67,14 @@ public class ChatPlayer extends TBMCPlayer {
|
||||||
return GetFormattedFlair(false);
|
return GetFormattedFlair(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetFlair(short time) {
|
public void SetFlair(int time) {
|
||||||
setFlairTime(time);
|
FlairTime.set(time);
|
||||||
FlairUpdate();
|
FlairUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetFlair(short time, boolean cheater) {
|
public void SetFlair(int time, boolean cheater) {
|
||||||
setFlairTime(time);
|
FlairTime.set(time);
|
||||||
setFlairCheater(cheater);
|
FlairCheater.set(cheater);
|
||||||
FlairUpdate();
|
FlairUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,30 +82,35 @@ public class ChatPlayer extends TBMCPlayer {
|
||||||
|
|
||||||
// Flairs from Command Block The Button - Teams
|
// Flairs from Command Block The Button - Teams
|
||||||
// PluginMain.Instance.getServer().getScoreboardManager().getMainScoreboard().getTeams().add()
|
// PluginMain.Instance.getServer().getScoreboardManager().getMainScoreboard().getTeams().add()
|
||||||
Player p = Bukkit.getPlayer(getUuid());
|
Player p = Bukkit.getPlayer(getUniqueId());
|
||||||
if (p != null)
|
if (p != null)
|
||||||
p.setPlayerListName(String.format("%s%s", p.getName(), GetFormattedFlair()));
|
p.setPlayerListName(String.format("%s%s", p.getDisplayName(), GetFormattedFlair()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public short GetFlairColor() {
|
public short GetFlairColor() {
|
||||||
if (getFlairCheater())
|
if (FlairCheater.get())
|
||||||
return 0x5;
|
return 0x5;
|
||||||
if (getFlairTime() == -1)
|
final int flairTime = FlairTime.get();
|
||||||
|
if (flairTime == FlairTimeNonPresser)
|
||||||
return 0x7;
|
return 0x7;
|
||||||
else if (getFlairTime() == -2)
|
else if (flairTime == FlairTimeCantPress)
|
||||||
return 0xf;
|
return 0xf;
|
||||||
else if (getFlairTime() <= 60 && getFlairTime() >= 52)
|
else if (flairTime <= 60 && flairTime >= 52)
|
||||||
return 0x5;
|
return 0x5;
|
||||||
else if (getFlairTime() <= 51 && getFlairTime() >= 42)
|
else if (flairTime <= 51 && flairTime >= 42)
|
||||||
return 0x9;
|
return 0x9;
|
||||||
else if (getFlairTime() <= 41 && getFlairTime() >= 32)
|
else if (flairTime <= 41 && flairTime >= 32)
|
||||||
return 0xa;
|
return 0xa;
|
||||||
else if (getFlairTime() <= 31 && getFlairTime() >= 22)
|
else if (flairTime <= 31 && flairTime >= 22)
|
||||||
return 0xe;
|
return 0xe;
|
||||||
else if (getFlairTime() <= 21 && getFlairTime() >= 11)
|
else if (flairTime <= 21 && flairTime >= 11)
|
||||||
return 0x6;
|
return 0x6;
|
||||||
else if (getFlairTime() <= 11 && getFlairTime() >= 0)
|
else if (flairTime <= 11 && flairTime >= 0)
|
||||||
return 0xc;
|
return 0xc;
|
||||||
return 0xf;
|
return 0x00; //Return 0 if none or too high, so names will get aqua default color, not white
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getF() {
|
||||||
|
return (double) FCount.get() / (double) FDeaths.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,385 +0,0 @@
|
||||||
package buttondevteam.chat;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Sound;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.scoreboard.Objective;
|
|
||||||
|
|
||||||
import com.earth2me.essentials.Essentials;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException;
|
|
||||||
import com.palmergames.bukkit.towny.object.Nation;
|
|
||||||
import com.palmergames.bukkit.towny.object.Resident;
|
|
||||||
import com.palmergames.bukkit.towny.object.Town;
|
|
||||||
|
|
||||||
import buttondevteam.chat.commands.UnlolCommand;
|
|
||||||
import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
|
|
||||||
import buttondevteam.chat.formatting.ChatFormatter;
|
|
||||||
import buttondevteam.chat.formatting.ChatFormatterBuilder;
|
|
||||||
import buttondevteam.chat.formatting.TellrawEvent;
|
|
||||||
import buttondevteam.chat.formatting.TellrawPart;
|
|
||||||
import buttondevteam.chat.formatting.TellrawSerializer;
|
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
|
||||||
import buttondevteam.lib.TBMCPlayer;
|
|
||||||
import buttondevteam.lib.chat.Channel;
|
|
||||||
import buttondevteam.lib.chat.TellrawSerializableEnum;
|
|
||||||
import buttondevteam.chat.listener.PlayerListener;
|
|
||||||
import buttondevteam.lib.chat.*;
|
|
||||||
|
|
||||||
public class ChatProcessing {
|
|
||||||
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 URL_PATTERN = Pattern.compile("(http[\\w:/?=$\\-_.+!*'(),]+)");
|
|
||||||
private 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 BOLD_PATTERN = Pattern.compile("(?<!\\\\)\\*\\*((?:\\\\\\*|[^\\*])+[^\\*\\\\])\\*\\*");
|
|
||||||
private static final String[] RainbowPresserColors = new String[] { "red", "gold", "yellow", "green", "blue",
|
|
||||||
"dark_purple" }; // TODO
|
|
||||||
private static boolean pingedconsole = false;
|
|
||||||
|
|
||||||
// Returns e.setCancelled
|
|
||||||
public static boolean ProcessChat(Channel channel, CommandSender sender, String message) {
|
|
||||||
long processstart = System.nanoTime();
|
|
||||||
if (PluginMain.essentials == null)
|
|
||||||
PluginMain.essentials = (Essentials) (Bukkit.getPluginManager().getPlugin("Essentials"));
|
|
||||||
Player player = (sender instanceof Player ? (Player) sender : null);
|
|
||||||
|
|
||||||
if (player != null && PluginMain.essentials.getUser(player).isMuted())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
ChatPlayer mp = null;
|
|
||||||
if (player != null) {
|
|
||||||
mp = TBMCPlayer.getPlayer(player).asPluginPlayer(ChatPlayer.class);
|
|
||||||
if (message.equalsIgnoreCase("F")) {
|
|
||||||
if (!mp.PressedF && PlayerListener.ActiveF) {
|
|
||||||
PlayerListener.FCount++;
|
|
||||||
mp.PressedF = true;
|
|
||||||
if (PlayerListener.FPlayer != null && PlayerListener.FPlayer.getFCount() < Integer.MAX_VALUE - 1)
|
|
||||||
PlayerListener.FPlayer.setFCount(PlayerListener.FPlayer.getFCount() + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String msg = message.toLowerCase();
|
|
||||||
if (msg.contains("lol")) {
|
|
||||||
UnlolCommand.Lastlolornot = true;
|
|
||||||
UnlolCommand.Lastlol = sender;
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < PlayerListener.LaughStrings.length; i++) {
|
|
||||||
if (msg.contains(PlayerListener.LaughStrings[i])) {
|
|
||||||
UnlolCommand.Lastlol = sender;
|
|
||||||
UnlolCommand.Lastlolornot = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Channel currentchannel = channel;
|
|
||||||
|
|
||||||
ArrayList<ChatFormatter> formatters = new ArrayList<ChatFormatter>();
|
|
||||||
|
|
||||||
Color colormode = currentchannel.color;
|
|
||||||
if (mp != null && mp.OtherColorMode != null)
|
|
||||||
colormode = mp.OtherColorMode;
|
|
||||||
if (mp != null && mp.RainbowPresserColorMode)
|
|
||||||
colormode = Color.RPC;
|
|
||||||
if (message.startsWith(">"))
|
|
||||||
colormode = Color.Green;
|
|
||||||
// If greentext, ignore channel or player colors
|
|
||||||
|
|
||||||
formatters.add(new ChatFormatterBuilder().setRegex(ENTIRE_MESSAGE_PATTERN).setColor(colormode)
|
|
||||||
.setPriority(Priority.Low).build());
|
|
||||||
|
|
||||||
String formattedmessage = message;
|
|
||||||
|
|
||||||
String suggestmsg = formattedmessage;
|
|
||||||
|
|
||||||
formatters.add(new ChatFormatterBuilder().setRegex(BOLD_PATTERN).setFormat(Format.Bold)
|
|
||||||
.setRemoveCharCount((short) 2).build());
|
|
||||||
formatters.add(new ChatFormatterBuilder().setRegex(ITALIC_PATTERN).setFormat(Format.Italic)
|
|
||||||
.setRemoveCharCount((short) 1).build());
|
|
||||||
formatters.add(new ChatFormatterBuilder().setRegex(UNDERLINED_PATTERN).setFormat(Format.Underlined)
|
|
||||||
.setRemoveCharCount((short) 1).build());
|
|
||||||
formatters.add(new ChatFormatterBuilder().setRegex(ESCAPE_PATTERN).setRemoveCharPos((short) 0).build());
|
|
||||||
|
|
||||||
// URLs + Rainbow text
|
|
||||||
formatters.add(new ChatFormatterBuilder().setRegex(URL_PATTERN).setFormat(Format.Underlined).setOpenlink("$1")
|
|
||||||
.build());
|
|
||||||
if (PluginMain.GetPlayers().size() > 0) {
|
|
||||||
StringBuilder namesb = new StringBuilder();
|
|
||||||
namesb.append("(?i)(");
|
|
||||||
for (Player p : PluginMain.GetPlayers())
|
|
||||||
namesb.append(p.getName()).append("|");
|
|
||||||
namesb.deleteCharAt(namesb.length() - 1);
|
|
||||||
namesb.append(")");
|
|
||||||
StringBuilder nicksb = new StringBuilder();
|
|
||||||
nicksb.append("(?i)(");
|
|
||||||
for (Player p : PluginMain.GetPlayers())
|
|
||||||
nicksb.append(PlayerListener.nicknames.inverse().get(p.getUniqueId())).append("|");
|
|
||||||
nicksb.deleteCharAt(nicksb.length() - 1);
|
|
||||||
nicksb.append(")");
|
|
||||||
|
|
||||||
formatters.add(new ChatFormatterBuilder().setRegex(Pattern.compile(namesb.toString())).setColor(Color.Aqua)
|
|
||||||
.setOnmatch((String match) -> {
|
|
||||||
Player p = Bukkit.getPlayer(match);
|
|
||||||
if (p == null) {
|
|
||||||
PluginMain.Instance.getLogger()
|
|
||||||
.warning("Error: Can't find player " + match + " but was reported as online.");
|
|
||||||
return "§c" + match + "§r";
|
|
||||||
}
|
|
||||||
ChatPlayer mpp = TBMCPlayer.getPlayer(p).asPluginPlayer(ChatPlayer.class);
|
|
||||||
if (PlayerListener.NotificationSound == null)
|
|
||||||
p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 0.5f); // TODO: Airhorn
|
|
||||||
else
|
|
||||||
p.playSound(p.getLocation(), PlayerListener.NotificationSound, 1.0f,
|
|
||||||
(float) PlayerListener.NotificationPitch);
|
|
||||||
String color = String.format("§%x", (mpp.GetFlairColor() == 0x00 ? 0xb : mpp.GetFlairColor()));
|
|
||||||
return color + p.getName() + "§r";
|
|
||||||
}).setPriority(Priority.High).build());
|
|
||||||
|
|
||||||
formatters.add(new ChatFormatterBuilder().setRegex(Pattern.compile(nicksb.toString())).setColor(Color.Aqua)
|
|
||||||
.setOnmatch((String match) -> {
|
|
||||||
if (PlayerListener.nicknames.containsKey(match)) {
|
|
||||||
Player p = Bukkit.getPlayer(PlayerListener.nicknames.get(match));
|
|
||||||
if (p == null) {
|
|
||||||
PluginMain.Instance.getLogger().warning(
|
|
||||||
"Error: Can't find player nicknamed " + match + " but was reported as online.");
|
|
||||||
return "§c" + match + "§r";
|
|
||||||
}
|
|
||||||
if (PlayerListener.NotificationSound == null)
|
|
||||||
p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 0.5f);
|
|
||||||
else
|
|
||||||
p.playSound(p.getLocation(), PlayerListener.NotificationSound, 1.0f,
|
|
||||||
(float) PlayerListener.NotificationPitch);
|
|
||||||
return PluginMain.essentials.getUser(p).getNickname();
|
|
||||||
}
|
|
||||||
Bukkit.getServer().getLogger().warning(
|
|
||||||
"Player nicknamed " + match + " not found in nickname map but was reported as online.");
|
|
||||||
return "§c" + match + "§r";
|
|
||||||
}).setPriority(Priority.High).build());
|
|
||||||
}
|
|
||||||
|
|
||||||
pingedconsole = false;
|
|
||||||
formatters.add(new ChatFormatterBuilder().setRegex(CONSOLE_PING_PATTERN).setColor(Color.Aqua)
|
|
||||||
.setOnmatch((String match) -> {
|
|
||||||
if (!pingedconsole) {
|
|
||||||
System.out.print("\007");
|
|
||||||
pingedconsole = true;
|
|
||||||
}
|
|
||||||
return match;
|
|
||||||
}).setPriority(Priority.High).build());
|
|
||||||
|
|
||||||
formatters.add(new ChatFormatterBuilder().setRegex(HASHTAG_PATTERN).setColor(Color.Blue)
|
|
||||||
.setOpenlink("https://twitter.com/hashtag/$1").setPriority(Priority.High).build());
|
|
||||||
|
|
||||||
/*
|
|
||||||
* if (!hadurls) { if (formattedmessage.matches("(?i).*" + Pattern.quote("@console") + ".*")) { formattedmessage = formattedmessage.replaceAll( "(?i)" + Pattern.quote("@console"),
|
|
||||||
* "§b@console§r"); formattedmessage = formattedmessage .replaceAll( "(?i)" + Pattern.quote("@console"), String.format(
|
|
||||||
* "\",\"color\":\"%s\"},{\"text\":\"§b@console§r\",\"color\":\"blue\"},{\"text\":\"" , colormode)); System.out.println("\007"); } }
|
|
||||||
*/
|
|
||||||
|
|
||||||
TellrawPart json = new TellrawPart("");
|
|
||||||
if (mp != null && mp.ChatOnly) {
|
|
||||||
json.addExtra(new TellrawPart("[C]").setHoverEvent(
|
|
||||||
TellrawEvent.create(TellrawEvent.HoverAC, TellrawEvent.HoverAction.SHOW_TEXT, "Chat only")));
|
|
||||||
}
|
|
||||||
json.addExtra(
|
|
||||||
new TellrawPart(("[" + (sender instanceof IDiscordSender ? "d|" : "") + currentchannel.DisplayName)
|
|
||||||
+ "]" + (mp != null && !mp.RPMode ? "[OOC]" : "")).setHoverEvent(
|
|
||||||
TellrawEvent.create(TellrawEvent.HoverAC, TellrawEvent.HoverAction.SHOW_TEXT,
|
|
||||||
new TellrawPart((sender instanceof IDiscordSender ? "From Discord\n" : "")
|
|
||||||
+ "Copy message").setColor(Color.Blue)))
|
|
||||||
.setClickEvent(TellrawEvent.create(TellrawEvent.ClickAC,
|
|
||||||
TellrawEvent.ClickAction.SUGGEST_COMMAND, suggestmsg)));
|
|
||||||
json.addExtra(new TellrawPart(" <"));
|
|
||||||
json.addExtra(
|
|
||||||
new TellrawPart(
|
|
||||||
(player != null ? player.getDisplayName() : sender.getName()))
|
|
||||||
.setHoverEvent(
|
|
||||||
TellrawEvent
|
|
||||||
.create(TellrawEvent.HoverAC, TellrawEvent.HoverAction.SHOW_TEXT,
|
|
||||||
new TellrawPart("")
|
|
||||||
.addExtra(new TellrawPart(String.format("Flair: %s",
|
|
||||||
(mp != null ? mp.GetFormattedFlair() : "-"))))
|
|
||||||
.addExtra(new TellrawPart(
|
|
||||||
String.format("\nPlayername: %s\n",
|
|
||||||
(player != null ? player.getName()
|
|
||||||
: sender.getName())))
|
|
||||||
.setColor(Color.Aqua))
|
|
||||||
.addExtra(new TellrawPart(String.format("World: %s\n",
|
|
||||||
(player != null ? player.getWorld().getName()
|
|
||||||
: "-"))))
|
|
||||||
.addExtra(
|
|
||||||
new TellrawPart(String.format("Respect: %s%s%s",
|
|
||||||
(mp != null ? (mp.getFCount()
|
|
||||||
/ (double) mp.getFDeaths())
|
|
||||||
: "Infinite"),
|
|
||||||
(mp != null && mp.getUserName() != null
|
|
||||||
&& !mp.getUserName().isEmpty()
|
|
||||||
? "\nUserName: "
|
|
||||||
+ mp.getUserName()
|
|
||||||
: ""),
|
|
||||||
(mp != null && mp.getPlayerName()
|
|
||||||
.equals("\nAlpha_Bacca44")
|
|
||||||
? "\nDeaths: "
|
|
||||||
+ PlayerListener.AlphaDeaths
|
|
||||||
: ""))))
|
|
||||||
.addExtra(new TellrawPart("\nFor more, do /u info "
|
|
||||||
+ sender.getName())))));
|
|
||||||
json.addExtra(new TellrawPart("> "));
|
|
||||||
long combinetime = System.nanoTime();
|
|
||||||
ChatFormatter.Combine(formatters, formattedmessage, json);
|
|
||||||
combinetime = System.nanoTime() - combinetime;
|
|
||||||
Gson gson = new GsonBuilder()
|
|
||||||
.registerTypeHierarchyAdapter(TellrawSerializableEnum.class, new TellrawSerializer.TwEnum())
|
|
||||||
.registerTypeHierarchyAdapter(Collection.class, new TellrawSerializer.TwCollection())
|
|
||||||
.registerTypeAdapter(Boolean.class, new TellrawSerializer.TwBool())
|
|
||||||
.registerTypeAdapter(boolean.class, new TellrawSerializer.TwBool()).disableHtmlEscaping().create();
|
|
||||||
String jsonstr = gson.toJson(json);
|
|
||||||
if (jsonstr.length() >= 32767) {
|
|
||||||
sender.sendMessage(
|
|
||||||
"§cError: Message too long. Try shortening it, or remove hashtags and other formatting.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
DebugCommand.SendDebugMessage(jsonstr);
|
|
||||||
if (currentchannel.equals(Channel.TownChat) || currentchannel.equals(Channel.NationChat)) {
|
|
||||||
if (player == null) {
|
|
||||||
sender.sendMessage("§cYou are not a player!");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
for (Player p : PluginMain.GetPlayers()) {
|
|
||||||
try {
|
|
||||||
Resident resident = PluginMain.Instance.TU.getResidentMap().get(p.getName().toLowerCase());
|
|
||||||
if (resident != null && !resident.getName().equals(player.getName())
|
|
||||||
&& resident.getModes().contains("spy"))
|
|
||||||
Bukkit.getPlayer(resident.getName()).sendMessage(String.format("[SPY-%s] - %s: %s",
|
|
||||||
currentchannel.DisplayName, player.getDisplayName(), message));
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (currentchannel.equals(Channel.TownChat)) {
|
|
||||||
Town town = null;
|
|
||||||
try {
|
|
||||||
final Resident resident = PluginMain.Instance.TU.getResidentMap()
|
|
||||||
.get(player.getName().toLowerCase());
|
|
||||||
if (resident != null && resident.hasTown())
|
|
||||||
town = resident.getTown();
|
|
||||||
} catch (NotRegisteredException e) {
|
|
||||||
}
|
|
||||||
if (town == null) {
|
|
||||||
player.sendMessage("§cYou aren't in a town or an error occured.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
int index = PluginMain.Instance.Towns.indexOf(town);
|
|
||||||
if (index < 0) {
|
|
||||||
PluginMain.Instance.Towns.add(town);
|
|
||||||
index = PluginMain.Instance.Towns.size() - 1;
|
|
||||||
}
|
|
||||||
Objective obj = PluginMain.SB.getObjective("town");
|
|
||||||
for (Player p : PluginMain.GetPlayers()) {
|
|
||||||
try {
|
|
||||||
if (town.getResidents().stream().anyMatch(r -> r.getName().equalsIgnoreCase(p.getName())))
|
|
||||||
obj.getScore(p.getName()).setScore(index);
|
|
||||||
else
|
|
||||||
obj.getScore(p.getName()).setScore(-1);
|
|
||||||
} catch (Exception e) {
|
|
||||||
obj.getScore(p.getName()).setScore(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PluginMain.Instance.getServer().dispatchCommand(PluginMain.Console,
|
|
||||||
String.format("tellraw @a[score_town=%d,score_town_min=%d] %s", index, index, jsonstr));
|
|
||||||
} else if (currentchannel.equals(Channel.NationChat)) {
|
|
||||||
Town town = null;
|
|
||||||
try {
|
|
||||||
final Resident resident = PluginMain.Instance.TU.getResidentMap()
|
|
||||||
.get(player.getName().toLowerCase());
|
|
||||||
if (resident != null && resident.hasTown())
|
|
||||||
town = resident.getTown();
|
|
||||||
} catch (NotRegisteredException e) {
|
|
||||||
}
|
|
||||||
if (town == null) {
|
|
||||||
player.sendMessage("§cYou aren't in a town or an error occured.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Nation nation = null;
|
|
||||||
try {
|
|
||||||
nation = town.getNation();
|
|
||||||
} catch (NotRegisteredException e) {
|
|
||||||
}
|
|
||||||
if (nation == null) {
|
|
||||||
player.sendMessage("§cYour town isn't in a nation or an error occured.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
int index = PluginMain.Instance.Nations.indexOf(nation);
|
|
||||||
if (index < 0) {
|
|
||||||
PluginMain.Instance.Nations.add(nation);
|
|
||||||
index = PluginMain.Instance.Nations.size() - 1;
|
|
||||||
}
|
|
||||||
Objective obj = PluginMain.SB.getObjective("nation");
|
|
||||||
for (Player p : PluginMain.GetPlayers()) {
|
|
||||||
try {
|
|
||||||
if (nation.getResidents().stream().anyMatch(r -> r.getName().equalsIgnoreCase(p.getName())))
|
|
||||||
obj.getScore(p.getName()).setScore(index);
|
|
||||||
else
|
|
||||||
obj.getScore(p.getName()).setScore(-1);
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PluginMain.Instance.getServer().dispatchCommand(PluginMain.Console,
|
|
||||||
String.format("tellraw @a[score_nation=%d,score_nation_min=%d] %s", index, index, jsonstr));
|
|
||||||
} else if (currentchannel.equals(Channel.AdminChat)) {
|
|
||||||
if (player != null && !player.isOp()) {
|
|
||||||
player.sendMessage("§cYou need to be an OP to use this channel.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Objective obj = PluginMain.SB.getObjective("admin");
|
|
||||||
for (Player p : PluginMain.GetPlayers()) {
|
|
||||||
if (p.isOp())
|
|
||||||
obj.getScore(p.getName()).setScore(1);
|
|
||||||
else
|
|
||||||
obj.getScore(p.getName()).setScore(0);
|
|
||||||
}
|
|
||||||
PluginMain.Instance.getServer().dispatchCommand(PluginMain.Console,
|
|
||||||
String.format("tellraw @a[score_admin=%d,score_admin_min=%d] %s", 1, 1, jsonstr));
|
|
||||||
} else if (currentchannel.equals(Channel.ModChat)) {
|
|
||||||
if (player != null && !PluginMain.permission.playerInGroup(player, "mod")) {
|
|
||||||
player.sendMessage("§cYou need to be a mod to use this channel.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Objective obj = PluginMain.SB.getObjective("mod");
|
|
||||||
for (Player p : PluginMain.GetPlayers()) {
|
|
||||||
if (PluginMain.permission.playerInGroup(p, "mod"))
|
|
||||||
obj.getScore(p.getName()).setScore(1);
|
|
||||||
else
|
|
||||||
obj.getScore(p.getName()).setScore(0);
|
|
||||||
}
|
|
||||||
PluginMain.Instance.getServer().dispatchCommand(PluginMain.Console,
|
|
||||||
String.format("tellraw @a[score_mod=%d,score_mod_min=%d] %s", 1, 1, jsonstr));
|
|
||||||
} else
|
|
||||||
PluginMain.Instance.getServer().dispatchCommand(PluginMain.Console,
|
|
||||||
String.format("tellraw @a %s", jsonstr));
|
|
||||||
} catch (Exception e) {
|
|
||||||
TBMCCoreAPI.SendException("An error occured while sending a chat message!", e);
|
|
||||||
player.sendMessage("§cAn error occured while sending the message.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
PluginMain.Instance.getServer().getConsoleSender()
|
|
||||||
.sendMessage(String.format("[%s] <%s%s> %s", currentchannel.DisplayName,
|
|
||||||
(player != null ? player.getDisplayName() : sender.getName()),
|
|
||||||
(mp != null ? mp.GetFormattedFlair() : ""), message));
|
|
||||||
DebugCommand.SendDebugMessage(
|
|
||||||
"-- Full ChatProcessing time: " + (System.nanoTime() - processstart) / 1000000f + " ms");
|
|
||||||
DebugCommand.SendDebugMessage("-- ChatFormatter.Combine time: " + combinetime / 1000000f + " ms");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
65
src/main/java/buttondevteam/chat/ChatUtils.java
Normal file
65
src/main/java/buttondevteam/chat/ChatUtils.java
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
package buttondevteam.chat;
|
||||||
|
|
||||||
|
import buttondevteam.core.component.channel.Channel;
|
||||||
|
import buttondevteam.lib.TBMCChatEvent;
|
||||||
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public final class ChatUtils {
|
||||||
|
public static final String MCORIGIN = "Minecraft"; //Shouldn't change, like ever - TBMCPlayer.getFolderForType(TBMCPlayer.class) capitalized
|
||||||
|
|
||||||
|
private ChatUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch a console command.
|
||||||
|
*
|
||||||
|
* @param command The command
|
||||||
|
* @param async Whether the caller is async
|
||||||
|
*/
|
||||||
|
public static void dispatchConsoleCommand(String command, boolean async) {
|
||||||
|
if (async)
|
||||||
|
Bukkit.getScheduler().runTask(PluginMain.Instance, () -> Bukkit.dispatchCommand(PluginMain.Console, command));
|
||||||
|
else
|
||||||
|
Bukkit.dispatchCommand(PluginMain.Console, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string between the start and end strings (exclusive).
|
||||||
|
*
|
||||||
|
* @param str The original string
|
||||||
|
* @param start The start string
|
||||||
|
* @param end The end string
|
||||||
|
* @return The result string
|
||||||
|
*/
|
||||||
|
public static Optional<String> coolSubstring(String str, String start, String end) {
|
||||||
|
int a = str.indexOf(start) + start.length();
|
||||||
|
int b = str.indexOf(end, a);
|
||||||
|
return a != -1 && b != -1 ? Optional.of(str.substring(a, b)) : Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a regular (non-Markdown) chat message. Used as a fallback if the chat processing fails.
|
||||||
|
*
|
||||||
|
* @param e The chat event
|
||||||
|
*/
|
||||||
|
public static void sendChatMessage(TBMCChatEvent e) {
|
||||||
|
var str = getMessageString(e.getChannel(), e.getUser(), e.getMessage());
|
||||||
|
for (Player p : Bukkit.getOnlinePlayers())
|
||||||
|
if (e.shouldSendTo(ChromaGamerBase.getFromSender(p)))
|
||||||
|
p.sendMessage(str);
|
||||||
|
Bukkit.getConsoleSender().sendMessage(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getMessageString(Channel channel, ChromaGamerBase sender, String message) {
|
||||||
|
return "§c!§r[" + channel.displayName.get() + "] <" + sender.getName() + "> " + message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendChatMessage(Channel channel, ChromaGamerBase sender, String message, CommandSender to) {
|
||||||
|
to.sendMessage(getMessageString(channel, sender, message));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,90 +0,0 @@
|
||||||
package buttondevteam.chat;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLDecoder;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.jar.JarEntry;
|
|
||||||
import java.util.jar.JarFile;
|
|
||||||
|
|
||||||
public class JarUtils {
|
|
||||||
|
|
||||||
public static boolean extractFromJar(final String fileName,
|
|
||||||
final String dest) throws IOException {
|
|
||||||
if (getRunningJar() == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final File file = new File(dest);
|
|
||||||
if (file.isDirectory()) {
|
|
||||||
file.mkdir();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!file.exists()) {
|
|
||||||
file.getParentFile().mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
final JarFile jar = getRunningJar();
|
|
||||||
final Enumeration<JarEntry> e = jar.entries();
|
|
||||||
while (e.hasMoreElements()) {
|
|
||||||
final JarEntry je = e.nextElement();
|
|
||||||
if (!je.getName().contains(fileName)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final InputStream in = new BufferedInputStream(
|
|
||||||
jar.getInputStream(je));
|
|
||||||
final OutputStream out = new BufferedOutputStream(
|
|
||||||
new FileOutputStream(file));
|
|
||||||
copyInputStream(in, out);
|
|
||||||
jar.close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
jar.close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final static void copyInputStream(final InputStream in,
|
|
||||||
final OutputStream out) throws IOException {
|
|
||||||
try {
|
|
||||||
final byte[] buff = new byte[4096];
|
|
||||||
int n;
|
|
||||||
while ((n = in.read(buff)) > 0) {
|
|
||||||
out.write(buff, 0, n);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
out.flush();
|
|
||||||
out.close();
|
|
||||||
in.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static URL getJarUrl(final File file) throws IOException {
|
|
||||||
return new URL("jar:" + file.toURI().toURL().toExternalForm() + "!/");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JarFile getRunningJar() throws IOException {
|
|
||||||
if (!RUNNING_FROM_JAR) {
|
|
||||||
return null; // null if not running from jar
|
|
||||||
}
|
|
||||||
String path = new File(JarUtils.class.getProtectionDomain()
|
|
||||||
.getCodeSource().getLocation().getPath()).getAbsolutePath();
|
|
||||||
path = URLDecoder.decode(path, "UTF-8");
|
|
||||||
return new JarFile(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean RUNNING_FROM_JAR = false;
|
|
||||||
|
|
||||||
static {
|
|
||||||
final URL resource = JarUtils.class.getClassLoader().getResource(
|
|
||||||
"plugin.yml");
|
|
||||||
if (resource != null) {
|
|
||||||
RUNNING_FROM_JAR = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,304 +1,88 @@
|
||||||
package buttondevteam.chat;
|
package buttondevteam.chat;
|
||||||
|
|
||||||
import net.milkbowl.vault.chat.Chat;
|
import buttondevteam.chat.commands.MWikiCommand;
|
||||||
import net.milkbowl.vault.economy.Economy;
|
import buttondevteam.chat.commands.MeCommand;
|
||||||
|
import buttondevteam.chat.commands.SnapCommand;
|
||||||
|
import buttondevteam.chat.commands.ucmds.HelpCommand;
|
||||||
|
import buttondevteam.chat.commands.ucmds.HistoryCommand;
|
||||||
|
import buttondevteam.chat.commands.ucmds.InfoCommand;
|
||||||
|
import buttondevteam.chat.commands.ucmds.ReloadCommand;
|
||||||
|
import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
|
||||||
|
import buttondevteam.chat.components.announce.AnnouncerComponent;
|
||||||
|
import buttondevteam.chat.components.appendext.AppendTextComponent;
|
||||||
|
import buttondevteam.chat.components.flair.FlairComponent;
|
||||||
|
import buttondevteam.chat.components.formatter.FormatterComponent;
|
||||||
|
import buttondevteam.chat.components.fun.FunComponent;
|
||||||
|
import buttondevteam.chat.components.towncolors.TownColorComponent;
|
||||||
|
import buttondevteam.chat.components.towny.TownyComponent;
|
||||||
|
import buttondevteam.chat.listener.PlayerJoinLeaveListener;
|
||||||
|
import buttondevteam.chat.listener.PlayerListener;
|
||||||
|
import buttondevteam.core.component.channel.Channel;
|
||||||
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
|
import buttondevteam.lib.architecture.ButtonPlugin;
|
||||||
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import buttondevteam.lib.architecture.config.IConfigData;
|
||||||
|
import buttondevteam.lib.chat.Color;
|
||||||
|
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||||
|
import com.earth2me.essentials.Essentials;
|
||||||
import net.milkbowl.vault.permission.Permission;
|
import net.milkbowl.vault.permission.Permission;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.ConsoleCommandSender;
|
import org.bukkit.command.ConsoleCommandSender;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
import org.bukkit.scoreboard.Scoreboard;
|
|
||||||
import org.htmlcleaner.HtmlCleaner;
|
|
||||||
import org.htmlcleaner.TagNode;
|
|
||||||
|
|
||||||
import buttondevteam.chat.commands.YeehawCommand;
|
public class PluginMain extends ButtonPlugin { // Translated to Java: 2015.07.15.
|
||||||
import buttondevteam.chat.listener.PlayerListener;
|
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
|
||||||
import buttondevteam.lib.TBMCPlayer;
|
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
|
||||||
|
|
||||||
import com.earth2me.essentials.Essentials;
|
|
||||||
import com.google.gson.JsonArray;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonParser;
|
|
||||||
import com.palmergames.bukkit.towny.Towny;
|
|
||||||
import com.palmergames.bukkit.towny.object.Nation;
|
|
||||||
import com.palmergames.bukkit.towny.object.Town;
|
|
||||||
import com.palmergames.bukkit.towny.object.TownyUniverse;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.lang.String;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLConnection;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
|
|
||||||
public class PluginMain extends JavaPlugin { // Translated to Java: 2015.07.15.
|
|
||||||
// A user, which flair isn't obtainable:
|
|
||||||
// https://www.reddit.com/r/thebutton/comments/31c32v/i_pressed_the_button_without_really_thinking/
|
|
||||||
public static PluginMain Instance;
|
public static PluginMain Instance;
|
||||||
public static ConsoleCommandSender Console;
|
public static ConsoleCommandSender Console;
|
||||||
public static Scoreboard SB;
|
|
||||||
public final static String FlairThreadURL = "https://www.reddit.com/r/Chromagamers/comments/51ys94/flair_thread_for_the_mc_server/";
|
|
||||||
public TownyUniverse TU;
|
|
||||||
public ArrayList<Town> Towns;
|
|
||||||
public ArrayList<Nation> Nations;
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* If enabled, stores and displays the last 10 messages the player can see (public, their town chat etc.)
|
||||||
* This variable is used as a cache for flair state checking when reading the flair thread.
|
* Can be used with the Discord plugin so players can see some of the conversation they missed that's visible on Discord anyways.
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* It's used because normally it has to load all associated player files every time to read the filename
|
|
||||||
* </p>
|
|
||||||
*/
|
*/
|
||||||
private Set<String> PlayersWithFlairs = new HashSet<>();
|
public IConfigData<Boolean> storeChatHistory = getIConfig().getData("storeChatHistory", true);
|
||||||
|
|
||||||
// Fired when plugin is first enabled
|
// Fired when plugin is first enabled
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void pluginEnable() {
|
||||||
Instance = this;
|
Instance = this;
|
||||||
|
PluginMain.essentials = (Essentials) (Bukkit.getPluginManager().getPlugin("Essentials"));
|
||||||
|
|
||||||
TBMCCoreAPI.RegisterEventsForExceptions(new PlayerListener(), this);
|
TBMCCoreAPI.RegisterEventsForExceptions(new PlayerListener(), this);
|
||||||
TBMCChatAPI.AddCommands(this, YeehawCommand.class);
|
TBMCCoreAPI.RegisterEventsForExceptions(new PlayerJoinLeaveListener(), this);
|
||||||
Console = this.getServer().getConsoleSender();
|
Console = this.getServer().getConsoleSender();
|
||||||
LoadFiles();
|
|
||||||
|
|
||||||
SB = PluginMain.Instance.getServer().getScoreboardManager().getMainScoreboard(); // Main can be detected with @a[score_...]
|
if (Bukkit.getPluginManager().isPluginEnabled("Towny"))
|
||||||
if (SB.getObjective("town") == null)
|
Component.registerComponent(this, new TownyComponent());
|
||||||
SB.registerNewObjective("town", "dummy");
|
|
||||||
if (SB.getObjective("nation") == null)
|
|
||||||
SB.registerNewObjective("nation", "dummy");
|
|
||||||
if (SB.getObjective("admin") == null)
|
|
||||||
SB.registerNewObjective("admin", "dummy");
|
|
||||||
if (SB.getObjective("mod") == null)
|
|
||||||
SB.registerNewObjective("mod", "dummy");
|
|
||||||
TU = ((Towny) Bukkit.getPluginManager().getPlugin("Towny")).getTownyUniverse();
|
|
||||||
Towns = new ArrayList<Town>(TU.getTownsMap().values());
|
|
||||||
Nations = new ArrayList<Nation>(TU.getNationsMap().values());
|
|
||||||
|
|
||||||
setupChat();
|
TBMCChatAPI.registerChatChannel(new Channel("§7RP§f", Color.Gray, "rp", null)); //Since it's null, it's recognised as global
|
||||||
setupEconomy();
|
|
||||||
setupPermissions();
|
|
||||||
|
|
||||||
Runnable r = new Runnable() {
|
if (!setupPermissions())
|
||||||
public void run() {
|
TBMCCoreAPI.SendException("We're in trouble", new Exception("Failed to set up permissions!"), this);
|
||||||
FlairGetterThreadMethod();
|
|
||||||
}
|
if (Bukkit.getPluginManager().isPluginEnabled("Towny"))
|
||||||
};
|
Component.registerComponent(this, new TownColorComponent());
|
||||||
Thread t = new Thread(r);
|
Component.registerComponent(this, new FlairComponent()); //The original purpose of this plugin
|
||||||
t.start();
|
Component.registerComponent(this, new AnnouncerComponent());
|
||||||
r = new Runnable() {
|
Component.registerComponent(this, new FunComponent());
|
||||||
public void run() {
|
Component.registerComponent(this, new AppendTextComponent());
|
||||||
AnnouncerThread.Run();
|
Component.registerComponent(this, new FormatterComponent());
|
||||||
}
|
registerCommand(new DebugCommand());
|
||||||
};
|
registerCommand(new HelpCommand());
|
||||||
t = new Thread(r);
|
registerCommand(new HistoryCommand());
|
||||||
t.start();
|
registerCommand(new InfoCommand());
|
||||||
|
registerCommand(new MWikiCommand());
|
||||||
|
registerCommand(new ReloadCommand());
|
||||||
|
registerCommand(new SnapCommand());
|
||||||
|
registerCommand(new MeCommand());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean stop = false;
|
|
||||||
public static Essentials essentials = null;
|
public static Essentials essentials = null;
|
||||||
|
|
||||||
// Fired when plugin is disabled
|
// Fired when plugin is disabled
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void pluginDisable() {
|
||||||
SaveFiles();
|
|
||||||
stop = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FlairGetterThreadMethod() {
|
|
||||||
int errorcount = 0;
|
|
||||||
while (!stop) {
|
|
||||||
try {
|
|
||||||
String body = TBMCCoreAPI.DownloadString(FlairThreadURL + ".json?limit=1000");
|
|
||||||
JsonArray json = new JsonParser().parse(body).getAsJsonArray().get(1).getAsJsonObject().get("data")
|
|
||||||
.getAsJsonObject().get("children").getAsJsonArray();
|
|
||||||
for (Object obj : json) {
|
|
||||||
JsonObject item = (JsonObject) obj;
|
|
||||||
String author = item.get("data").getAsJsonObject().get("author").getAsString();
|
|
||||||
String ign = item.get("data").getAsJsonObject().get("body").getAsString();
|
|
||||||
int start = ign.indexOf("IGN:") + "IGN:".length();
|
|
||||||
if (start == -1 + "IGN:".length())
|
|
||||||
continue;
|
|
||||||
int end = ign.indexOf(' ', start);
|
|
||||||
if (end == -1 || end == start)
|
|
||||||
end = ign.indexOf('\n', start);
|
|
||||||
if (end == -1 || end == start)
|
|
||||||
ign = ign.substring(start);
|
|
||||||
else
|
|
||||||
ign = ign.substring(start, end);
|
|
||||||
ign = ign.trim();
|
|
||||||
if (PlayersWithFlairs.contains(ign))
|
|
||||||
continue;
|
|
||||||
try (ChatPlayer mp = TBMCPlayer.getFromName(ign).asPluginPlayer(ChatPlayer.class)) { // Loads player file
|
|
||||||
if (mp == null || mp.getUserNames() == null || author == null)
|
|
||||||
continue;
|
|
||||||
/*
|
|
||||||
* if (!JoinedBefore(mp, 2015, 6, 5)) continue;
|
|
||||||
*/
|
|
||||||
if (!mp.getUserNames().contains(author))
|
|
||||||
mp.getUserNames().add(author);
|
|
||||||
if (mp.getFlairState().equals(FlairStates.NoComment)) {
|
|
||||||
mp.setFlairState(FlairStates.Commented);
|
|
||||||
ConfirmUserMessage(mp);
|
|
||||||
}
|
|
||||||
PlayersWithFlairs.add(ign); // Don't redownload even if flair isn't accepted
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Thread.sleep(10);
|
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Thread.sleep(10000);
|
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
errorcount++;
|
|
||||||
if (errorcount >= 10) {
|
|
||||||
errorcount = 0;
|
|
||||||
TBMCCoreAPI.SendException("Error while getting flairs from Reddit!", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DownloadFlair(ChatPlayer mp) throws MalformedURLException, IOException {
|
|
||||||
String[] flairdata = TBMCCoreAPI
|
|
||||||
.DownloadString("http://karmadecay.com/thebutton-data.php?users=" + mp.getUserName()).replace("\"", "")
|
|
||||||
.split(":");
|
|
||||||
String flair;
|
|
||||||
if (flairdata.length > 1)
|
|
||||||
flair = flairdata[1];
|
|
||||||
else
|
|
||||||
flair = "";
|
|
||||||
String flairclass;
|
|
||||||
if (flairdata.length > 2)
|
|
||||||
flairclass = flairdata[2];
|
|
||||||
else
|
|
||||||
flairclass = "unknown";
|
|
||||||
SetFlair(mp, flair, flairclass, mp.getUserName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetFlair(ChatPlayer p, String text, String flairclass, String username) {
|
|
||||||
p.setUserName(username);
|
|
||||||
p.setFlairState(FlairStates.Recognised);
|
|
||||||
switch (flairclass) {
|
|
||||||
case "cheater":
|
|
||||||
p.SetFlair(Short.parseShort(text), true);
|
|
||||||
return;
|
|
||||||
case "unknown":
|
|
||||||
try {
|
|
||||||
if (CheckForJoinDate(p)) {
|
|
||||||
if (text.equals("-1")) // If true, only non-presser/can't press; if false, any flair (but we can still detect can't press)
|
|
||||||
p.SetFlair(ChatPlayer.FlairTimeNonPresser);
|
|
||||||
else
|
|
||||||
p.SetFlair(ChatPlayer.FlairTimeNone); // Flair unknown
|
|
||||||
} else {
|
|
||||||
p.SetFlair(ChatPlayer.FlairTimeCantPress);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
p.setFlairState(FlairStates.Commented); // Flair unknown
|
|
||||||
p.SetFlair(ChatPlayer.FlairTimeNone);
|
|
||||||
TBMCCoreAPI.SendException("Error while checking join date for player " + p.getPlayerName() + "!", e);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p.SetFlair(Short.parseShort(text));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean CheckForJoinDate(ChatPlayer mp) throws Exception {
|
|
||||||
return JoinedBefore(mp, 2015, 4, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean JoinedBefore(ChatPlayer mp, int year, int month, int day) throws Exception {
|
|
||||||
URL url = new URL("https://www.reddit.com/u/" + mp.getUserName());
|
|
||||||
URLConnection con = url.openConnection();
|
|
||||||
con.setRequestProperty("User-Agent", "TheButtonAutoFlair");
|
|
||||||
InputStream in = con.getInputStream();
|
|
||||||
HtmlCleaner cleaner = new HtmlCleaner();
|
|
||||||
TagNode node = cleaner.clean(in);
|
|
||||||
|
|
||||||
node = node.getElementsByAttValue("class", "age", true, true)[0];
|
|
||||||
node = node.getElementsByName("time", false)[0];
|
|
||||||
String joindate = node.getAttributeByName("datetime");
|
|
||||||
SimpleDateFormat parserSDF = new SimpleDateFormat("yyyy-MM-dd");
|
|
||||||
joindate = joindate.split("T")[0];
|
|
||||||
Date date = parserSDF.parse(joindate);
|
|
||||||
return date.before(new Calendar.Builder().setTimeZone(TimeZone.getTimeZone("UTC")).setDate(year, month, day)
|
|
||||||
.build().getTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ConfirmUserMessage(ChatPlayer mp) {
|
|
||||||
Player p = Bukkit.getPlayer(mp.getUuid());
|
|
||||||
if (mp.getFlairState().equals(FlairStates.Commented) && p != null)
|
|
||||||
if (mp.getUserNames().size() > 1)
|
|
||||||
p.sendMessage(
|
|
||||||
"§9Multiple Reddit users commented your name. You can select with /u accept.§r §6Type /u accept or /u ignore§r");
|
|
||||||
else
|
|
||||||
p.sendMessage("§9A Reddit user commented your name. Is that you?§r §6Type /u accept or /u ignore§r");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Collection<? extends Player> GetPlayers() {
|
|
||||||
return Instance.getServer().getOnlinePlayers();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ArrayList<String> AnnounceMessages = new ArrayList<>();
|
|
||||||
public static int AnnounceTime = 15 * 60 * 1000;
|
|
||||||
|
|
||||||
public static void LoadFiles() {
|
|
||||||
PluginMain.Instance.getLogger().info("Loading files...");
|
|
||||||
try {
|
|
||||||
File file = new File("TBMC/chatsettings.yml");
|
|
||||||
if (file.exists()) {
|
|
||||||
YamlConfiguration yc = new YamlConfiguration();
|
|
||||||
yc.load(file);
|
|
||||||
PlayerListener.NotificationSound = yc.getString("notificationsound");
|
|
||||||
PlayerListener.NotificationPitch = yc.getDouble("notificationpitch");
|
|
||||||
AnnounceTime = yc.getInt("announcetime");
|
|
||||||
AnnounceMessages.addAll(yc.getStringList("announcements"));
|
|
||||||
PlayerListener.AlphaDeaths = yc.getInt("alphadeaths");
|
|
||||||
}
|
|
||||||
PluginMain.Instance.getLogger().info("Loaded files!");
|
|
||||||
} catch (Exception e) {
|
|
||||||
TBMCCoreAPI.SendException("Error while loading chat files!", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SaveFiles() {
|
|
||||||
PluginMain.Instance.getLogger().info("Saving files...");
|
|
||||||
try {
|
|
||||||
File file = new File("TBMC/chatsettings.yml");
|
|
||||||
YamlConfiguration yc = new YamlConfiguration();
|
|
||||||
yc.set("notificationsound", PlayerListener.NotificationSound);
|
|
||||||
yc.set("notificationpitch", PlayerListener.NotificationPitch);
|
|
||||||
yc.set("announcetime", AnnounceTime);
|
|
||||||
yc.set("announcements", AnnounceMessages);
|
|
||||||
yc.set("alphadeaths", PlayerListener.AlphaDeaths);
|
|
||||||
yc.save(file);
|
|
||||||
PluginMain.Instance.getLogger().info("Saved files!");
|
|
||||||
} catch (Exception e) {
|
|
||||||
TBMCCoreAPI.SendException("Error while loading chat files!", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Permission permission = null;
|
public static Permission permission = null;
|
||||||
public static Economy economy = null;
|
|
||||||
public static Chat chat = null;
|
|
||||||
|
|
||||||
private boolean setupPermissions() {
|
private boolean setupPermissions() {
|
||||||
RegisteredServiceProvider<Permission> permissionProvider = getServer().getServicesManager()
|
RegisteredServiceProvider<Permission> permissionProvider = getServer().getServicesManager()
|
||||||
|
@ -309,23 +93,4 @@ public class PluginMain extends JavaPlugin { // Translated to Java: 2015.07.15.
|
||||||
return (permission != null);
|
return (permission != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean setupChat() {
|
|
||||||
RegisteredServiceProvider<Chat> chatProvider = getServer().getServicesManager()
|
|
||||||
.getRegistration(net.milkbowl.vault.chat.Chat.class);
|
|
||||||
if (chatProvider != null) {
|
|
||||||
chat = chatProvider.getProvider();
|
|
||||||
}
|
|
||||||
|
|
||||||
return (chat != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean setupEconomy() {
|
|
||||||
RegisteredServiceProvider<Economy> economyProvider = getServer().getServicesManager()
|
|
||||||
.getRegistration(net.milkbowl.vault.economy.Economy.class);
|
|
||||||
if (economyProvider != null) {
|
|
||||||
economy = economyProvider.getProvider();
|
|
||||||
}
|
|
||||||
|
|
||||||
return (economy != null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
141
src/main/java/buttondevteam/chat/VanillaUtils.java
Normal file
141
src/main/java/buttondevteam/chat/VanillaUtils.java
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
package buttondevteam.chat;
|
||||||
|
|
||||||
|
import buttondevteam.core.MainPlugin;
|
||||||
|
import buttondevteam.lib.TBMCChatEvent;
|
||||||
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
import lombok.val;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.BiPredicate;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
|
public class VanillaUtils {
|
||||||
|
public String getGroupIfChatOn(Player p, TBMCChatEvent e) {
|
||||||
|
try {
|
||||||
|
if (!isChatOn(p)) // Only send if client allows chat
|
||||||
|
return null;
|
||||||
|
} catch (NoClassDefFoundError ex) {
|
||||||
|
MainPlugin.getInstance().getLogger().warning("Compatibility error, can't check if the chat is hidden by the player.");
|
||||||
|
}
|
||||||
|
return e.getGroupID(ChromaGamerBase.getFromSender(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Predicate<Player> isChatOn;
|
||||||
|
|
||||||
|
private boolean isChatOn(Player p) {
|
||||||
|
try {
|
||||||
|
if (isChatOn == null) {
|
||||||
|
val cl = p.getClass();
|
||||||
|
if (notCraftPlayer(cl)) return true; // p instanceof CraftPlayer
|
||||||
|
val hm = cl.getMethod("getHandle");
|
||||||
|
val handle = hm.invoke(p); //p.getHandle()
|
||||||
|
val vpcl = handle.getClass();
|
||||||
|
val gcfm = vpcl.getMethod("getChatFlags");
|
||||||
|
Class<?> encl;
|
||||||
|
try {
|
||||||
|
encl = Class.forName(handle.getClass().getPackage().getName() + ".EnumChatVisibility");
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
encl = Class.forName(handle.getClass().getPackage().getName() + ".EntityHuman$EnumChatVisibility");
|
||||||
|
}
|
||||||
|
val ff = encl.getField("FULL");
|
||||||
|
val full = ff.get(null); // EnumChatVisibility.FULL
|
||||||
|
isChatOn = pl -> {
|
||||||
|
try {
|
||||||
|
if (notCraftPlayer(pl.getClass())) return true; //Need to check each time
|
||||||
|
val ph = hm.invoke(pl); //pl.getHandle()
|
||||||
|
val flags = gcfm.invoke(ph); //handle.getChatFlags()
|
||||||
|
return flags == full;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return isChatOn.test(p);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*private String version;
|
||||||
|
|
||||||
|
public short getMCVersion() {
|
||||||
|
if (version != null) return version;
|
||||||
|
val v = ChatUtils.coolSubstring(Bukkit.getServer().getVersion().getClass().getPackage().getName(),
|
||||||
|
"org.bukkit.craftbukkit.v", "_R1").orElse("1_8").replace("_", "");
|
||||||
|
return Short.parseShort(v);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
private BiPredicate<Player, String> tellRaw;
|
||||||
|
|
||||||
|
public boolean tellRaw(Player p, String json) {
|
||||||
|
try {
|
||||||
|
if (tellRaw == null) {
|
||||||
|
val pcl = p.getClass();
|
||||||
|
if (notCraftPlayer(pcl)) return false;
|
||||||
|
val hm = pcl.getMethod("getHandle");
|
||||||
|
val handle = hm.invoke(p);
|
||||||
|
var nmsOrChat = handle.getClass().getPackage().getName();
|
||||||
|
if (!nmsOrChat.contains(".v1_"))
|
||||||
|
nmsOrChat = "net.minecraft.network.chat";
|
||||||
|
val chatcompcl = Class.forName(nmsOrChat + ".IChatBaseComponent");
|
||||||
|
//val chatcomarrcl = Class.forName("[L" + chatcompcl.getName() + ";");
|
||||||
|
val chatcomparr = Array.newInstance(chatcompcl, 1);
|
||||||
|
final Method sendmsg;
|
||||||
|
{
|
||||||
|
Method sendmsg1;
|
||||||
|
try {
|
||||||
|
sendmsg1 = handle.getClass().getMethod("sendMessage", UUID.class, chatcomparr.getClass());
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
sendmsg1 = handle.getClass().getMethod("sendMessage", chatcomparr.getClass());
|
||||||
|
}
|
||||||
|
sendmsg = sendmsg1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*val ccucl = Class.forName(nms + ".ChatComponentUtils");
|
||||||
|
val iclcl = Class.forName(nms + ".ICommandListener");
|
||||||
|
val encl = Class.forName(nms + ".Entity");
|
||||||
|
val ffdm = ccucl.getMethod("filterForDisplay", iclcl, chatcompcl, encl);*/
|
||||||
|
|
||||||
|
val cscl = Class.forName(chatcompcl.getName() + "$ChatSerializer");
|
||||||
|
val am = cscl.getMethod("a", String.class);
|
||||||
|
|
||||||
|
tellRaw = (pl, jsonStr) -> {
|
||||||
|
if (notCraftPlayer(pl.getClass())) return false;
|
||||||
|
try {
|
||||||
|
val hhandle = hm.invoke(pl);
|
||||||
|
val deserialized = am.invoke(null, jsonStr);
|
||||||
|
//val filtered = ffdm.invoke(null, hhandle, deserialized, hhandle);
|
||||||
|
Array.set(chatcomparr, 0, deserialized);
|
||||||
|
if (sendmsg.getParameterCount() == 2)
|
||||||
|
sendmsg.invoke(hhandle, null, chatcomparr); //
|
||||||
|
else
|
||||||
|
sendmsg.invoke(hhandle, chatcomparr);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*((CraftPlayer) p).getHandle().sendMessage(ChatComponentUtils
|
||||||
|
.filterForDisplay(((CraftPlayer) p).getHandle(),
|
||||||
|
IChatBaseComponent.ChatSerializer.a(json), ((CraftPlayer) p).getHandle()));*/
|
||||||
|
return tellRaw.test(p, json);
|
||||||
|
} catch (Exception e) {
|
||||||
|
PluginMain.Instance.getLogger().warning("Could not use tellRaw: " + e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean notCraftPlayer(Class<?> cl) {
|
||||||
|
return !cl.getSimpleName().contains("CraftPlayer");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,47 +0,0 @@
|
||||||
package buttondevteam.chat.commands;
|
|
||||||
|
|
||||||
import org.bukkit.GameMode;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import buttondevteam.chat.ChatPlayer;
|
|
||||||
import buttondevteam.lib.TBMCPlayer;
|
|
||||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
|
||||||
|
|
||||||
public final class ChatonlyCommand extends TBMCCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- Chat-only mode ----", //
|
|
||||||
"This mode makes you invincible but unable to move, teleport or interact with the world in any way", //
|
|
||||||
"It was designed for chat clients", //
|
|
||||||
"Once enabled, the only way of disabling it is by relogging to the server" //
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
Player player = (Player) sender;
|
|
||||||
ChatPlayer p = TBMCPlayer.getPlayerAs(player, ChatPlayer.class);
|
|
||||||
p.ChatOnly = true;
|
|
||||||
player.setGameMode(GameMode.SPECTATOR);
|
|
||||||
player.sendMessage("§bChat-only mode enabled. You are now invincible.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetCommandPath() {
|
|
||||||
return "chatonly";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetPlayerOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetModOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,31 +1,24 @@
|
||||||
package buttondevteam.chat.commands;
|
package buttondevteam.chat.commands;
|
||||||
|
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
@CommandClass(modOnly = false, helpText = {
|
||||||
|
"Minecraft Wiki linker", //
|
||||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
|
||||||
|
|
||||||
public class MWikiCommand extends TBMCCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- Minecraft Wiki linker ----", //
|
|
||||||
"Use without parameters to get a link to the wiki", //
|
"Use without parameters to get a link to the wiki", //
|
||||||
"You can also search the wiki, for example:", //
|
"You can also search the wiki, for example:", //
|
||||||
" /" + alias + " beacon - Provides a link that redirects to the beacon's wiki page" //
|
" /mwiki beacon - Provides a link that redirects to the beacon's wiki page" //
|
||||||
};
|
})
|
||||||
}
|
public class MWikiCommand extends ICommand2MC {
|
||||||
|
@Command2.Subcommand
|
||||||
@Override
|
public boolean def(CommandSender sender, @Command2.OptionalArg @Command2.TextArg String query) {
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
String query = "";
|
|
||||||
for (int i = 0; i < args.length; i++)
|
|
||||||
query += args[i] + " ";
|
|
||||||
query = query.trim();
|
|
||||||
try {
|
try {
|
||||||
if (query.length() == 0)
|
if (query == null)
|
||||||
sender.sendMessage(new String[]{"§bMinecraft Wiki link: http://minecraft.gamepedia.com/",
|
sender.sendMessage(new String[]{"§bMinecraft Wiki link: http://minecraft.gamepedia.com/",
|
||||||
"You can also search on it using /mwiki <query>"});
|
"You can also search on it using /mwiki <query>"});
|
||||||
else
|
else
|
||||||
|
@ -37,19 +30,4 @@ public class MWikiCommand extends TBMCCommandBase {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetCommandPath() {
|
|
||||||
return "mwiki";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetPlayerOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetModOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
15
src/main/java/buttondevteam/chat/commands/MeCommand.java
Normal file
15
src/main/java/buttondevteam/chat/commands/MeCommand.java
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package buttondevteam.chat.commands;
|
||||||
|
|
||||||
|
import buttondevteam.lib.TBMCSystemChatEvent;
|
||||||
|
import buttondevteam.lib.chat.*;
|
||||||
|
|
||||||
|
@CommandClass(helpText = {
|
||||||
|
"Me",
|
||||||
|
"Displays a message starting with your name in your current channel."
|
||||||
|
})
|
||||||
|
public class MeCommand extends ICommand2MC {
|
||||||
|
@Command2.Subcommand
|
||||||
|
public void def(Command2MCSender sender, @Command2.TextArg String message) {
|
||||||
|
TBMCChatAPI.SendSystemMessage(sender.getChannel(), sender.getChannel().getRTR(sender.getPermCheck()), "§5* " + sender.getSender().getName() + " " + message, TBMCSystemChatEvent.BroadcastTarget.ALL);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,51 +0,0 @@
|
||||||
package buttondevteam.chat.commands;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import buttondevteam.chat.ChatPlayer;
|
|
||||||
import buttondevteam.lib.TBMCPlayer;
|
|
||||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
|
||||||
|
|
||||||
public final class OOCCommand extends TBMCCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- Out-of-character message ----",
|
|
||||||
"This command will put a [OCC] tag before your message indicating that you are talking out of character",
|
|
||||||
"Usage: /" + alias + " <message>" };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
Player player = (Player) sender;
|
|
||||||
if (args.length == 0) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
final ChatPlayer cp = TBMCPlayer.getPlayerAs(player, ChatPlayer.class);
|
|
||||||
cp.RPMode = false;
|
|
||||||
String message = "";
|
|
||||||
for (String arg : args)
|
|
||||||
message += arg + " ";
|
|
||||||
player.chat(message.substring(0, message.length() - 1));
|
|
||||||
cp.RPMode = true;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetCommandPath() {
|
|
||||||
return "ooc";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetPlayerOnly() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetModOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
30
src/main/java/buttondevteam/chat/commands/SnapCommand.java
Normal file
30
src/main/java/buttondevteam/chat/commands/SnapCommand.java
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package buttondevteam.chat.commands;
|
||||||
|
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
|
import lombok.val;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
@CommandClass(modOnly = true, helpText = {
|
||||||
|
"Snap",
|
||||||
|
"Perfectly balanced as all things should be."
|
||||||
|
})
|
||||||
|
public class SnapCommand extends ICommand2MC {
|
||||||
|
@Command2.Subcommand
|
||||||
|
public void def(CommandSender sender) {
|
||||||
|
val pls = new ArrayList<>(Bukkit.getOnlinePlayers());
|
||||||
|
int target = pls.size() / 2;
|
||||||
|
Random rand = new Random();
|
||||||
|
//noinspection SuspiciousMethodCalls
|
||||||
|
if (pls.remove(sender) && target > 0)
|
||||||
|
target--; //The sender isn't kicked, so kick someone else
|
||||||
|
while (pls.size() > target)
|
||||||
|
pls.remove(rand.nextInt(pls.size())).kickPlayer("You were saved by Thanos.");
|
||||||
|
sender.sendMessage(target + " grateful players remain.");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,56 +0,0 @@
|
||||||
package buttondevteam.chat.commands;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.potion.PotionEffect;
|
|
||||||
import org.bukkit.potion.PotionEffectType;
|
|
||||||
|
|
||||||
import buttondevteam.chat.PluginMain;
|
|
||||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
|
||||||
|
|
||||||
public final class UnlolCommand extends TBMCCommandBase {
|
|
||||||
|
|
||||||
public static CommandSender Lastlol = null;
|
|
||||||
public static boolean Lastlolornot;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- Unlol/unlaugh ----",
|
|
||||||
"This command is based on a joke between NorbiPeti and Ghostise",
|
|
||||||
"It will make anyone saying one of the recognized laugh strings blind for a few seconds",
|
|
||||||
"Note that you can only unlaugh laughs that weren't unlaughed before" };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
if (Lastlol != null) {
|
|
||||||
if (Lastlol instanceof Player)
|
|
||||||
((Player) Lastlol)
|
|
||||||
.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 10 * 20, 5, false, false));
|
|
||||||
String msg = (sender instanceof Player ? ((Player) sender).getDisplayName() : sender.getName())
|
|
||||||
+ (Lastlolornot ? " unlolled " : " unlaughed ")
|
|
||||||
+ (Lastlol instanceof Player ? ((Player) Lastlol).getDisplayName() : Lastlol.getName());
|
|
||||||
for (Player pl : PluginMain.GetPlayers())
|
|
||||||
pl.sendMessage(msg);
|
|
||||||
Bukkit.getServer().getConsoleSender().sendMessage(msg);
|
|
||||||
Lastlol = null;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetCommandPath() {
|
|
||||||
return "unlol";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetPlayerOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetModOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
package buttondevteam.chat.commands;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import buttondevteam.chat.PluginMain;
|
|
||||||
import buttondevteam.lib.TBMCYEEHAWEvent;
|
|
||||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
|
||||||
|
|
||||||
public class YeehawCommand extends TBMCCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- YEEHAW command ----", "This command makes you YEEHAW." };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
final String message = "§b* "
|
|
||||||
+ (sender instanceof Player ? ((Player) sender).getDisplayName() : sender.getName()) + " §bYEEHAWs.";
|
|
||||||
for (Player p : PluginMain.GetPlayers()) {
|
|
||||||
p.playSound(p.getLocation(), "tbmc.yeehaw", 1f, 1f);
|
|
||||||
p.sendMessage(message);
|
|
||||||
} // Even a cmdblock could yeehaw in theory
|
|
||||||
// Or anyone from Discord
|
|
||||||
Bukkit.getConsoleSender().sendMessage(message);
|
|
||||||
Bukkit.getPluginManager().callEvent(new TBMCYEEHAWEvent(sender));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetCommandPath() {
|
|
||||||
return "yeehaw";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetPlayerOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetModOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
package buttondevteam.chat.commands.appendtext;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import buttondevteam.chat.ChatPlayer;
|
|
||||||
import buttondevteam.chat.listener.PlayerListener;
|
|
||||||
import buttondevteam.lib.TBMCPlayer;
|
|
||||||
import buttondevteam.lib.chat.Channel;
|
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
|
||||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
|
||||||
|
|
||||||
public abstract class AppendTextCommandBase extends TBMCCommandBase {
|
|
||||||
|
|
||||||
public abstract String[] GetHelpText(String alias);
|
|
||||||
|
|
||||||
public abstract String GetAppendedText();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
String msg = GetAppendedText();
|
|
||||||
for (int i = args.length - 1; i >= 0; i--)
|
|
||||||
msg = args[i] + " " + msg;
|
|
||||||
if (sender instanceof Player)
|
|
||||||
TBMCChatAPI.SendChatMessage(
|
|
||||||
TBMCPlayer.getPlayer((Player) sender).asPluginPlayer(ChatPlayer.class).CurrentChannel, sender, msg);
|
|
||||||
else if (sender.isOp())
|
|
||||||
TBMCChatAPI.SendChatMessage(PlayerListener.ConsoleChannel, sender, msg);
|
|
||||||
else
|
|
||||||
TBMCChatAPI.SendChatMessage(Channel.GlobalChat, sender, msg);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetPlayerOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetModOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
package buttondevteam.chat.commands.appendtext;
|
|
||||||
|
|
||||||
public final class ShrugCommand extends AppendTextCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- Shrug ----",
|
|
||||||
"This command appends a shrug after your message",
|
|
||||||
"Or just makes you shrug",
|
|
||||||
"Use either /" + alias + " <message> or just /" + alias };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetAppendedText() {
|
|
||||||
return "¯\\\\\\_(ツ)\\_/¯";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetCommandPath() {
|
|
||||||
return "shrug";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package buttondevteam.chat.commands.appendtext;
|
|
||||||
|
|
||||||
public final class TableflipCommand extends AppendTextCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- Tableflip ----",
|
|
||||||
"This command appends a tableflip after your message",
|
|
||||||
"Or just makes you tableflip",
|
|
||||||
"Use either /" + alias + " <message> or just /" + alias };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetAppendedText() {
|
|
||||||
return "(╯°□°)╯︵ ┻━┻";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetCommandPath() {
|
|
||||||
return "tableflip";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
package buttondevteam.chat.commands.appendtext;
|
|
||||||
|
|
||||||
public final class UnflipCommand extends AppendTextCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- Unflip ----",
|
|
||||||
"This command appends an unflip after your message",
|
|
||||||
"Or just unflips as you",
|
|
||||||
"Use either /" + alias + " <message> or just /" + alias };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetAppendedText() {
|
|
||||||
return "┬─┬ ノ( ゜-゜ノ)";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetCommandPath() {
|
|
||||||
return "unflip";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,100 +0,0 @@
|
||||||
package buttondevteam.chat.commands.ucmds;
|
|
||||||
|
|
||||||
import java.util.Timer;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import buttondevteam.chat.ChatPlayer;
|
|
||||||
import buttondevteam.chat.FlairStates;
|
|
||||||
import buttondevteam.chat.PlayerJoinTimerTask;
|
|
||||||
import buttondevteam.chat.PluginMain;
|
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
|
||||||
import buttondevteam.lib.TBMCPlayer;
|
|
||||||
|
|
||||||
public class AcceptCommand extends UCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- Accept flair ----", //
|
|
||||||
"Accepts a flair from Reddit", //
|
|
||||||
"Use /u accept <username> if you commented from multiple accounts" //
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
final Player player = (Player) sender;
|
|
||||||
ChatPlayer p = TBMCPlayer.getPlayerAs(player, ChatPlayer.class);
|
|
||||||
if (args.length < 1 && p.getUserNames().size() > 1) {
|
|
||||||
player.sendMessage("§9Multiple users commented your name. §bPlease pick one using /u accept <username>");
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("§6Usernames:");
|
|
||||||
for (String username : p.getUserNames())
|
|
||||||
sb.append(" ").append(username);
|
|
||||||
player.sendMessage(sb.toString());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (p.getFlairState().equals(FlairStates.NoComment) || p.getUserNames().size() == 0) {
|
|
||||||
player.sendMessage("§cError: You need to write your username to the reddit thread at /r/ChromaGamers§r");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (args.length > 0 && !p.getUserNames().contains(args[0])) {
|
|
||||||
player.sendMessage("§cError: Unknown name: " + args[0] + "§r");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (p.Working) {
|
|
||||||
player.sendMessage("§cError: Something is already in progress.§r");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((args.length > 0 ? args[0] : p.getUserNames().get(0)).equals(p.getUserName())) {
|
|
||||||
player.sendMessage("§cYou already have this user's flair.§r");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (args.length > 0)
|
|
||||||
p.setUserName(args[0]);
|
|
||||||
else
|
|
||||||
p.setUserName(p.getUserNames().get(0));
|
|
||||||
|
|
||||||
player.sendMessage("§bObtaining flair...");
|
|
||||||
p.Working = true;
|
|
||||||
Timer timer = new Timer();
|
|
||||||
PlayerJoinTimerTask tt = new PlayerJoinTimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
PluginMain.Instance.DownloadFlair(mp);
|
|
||||||
} catch (Exception e) {
|
|
||||||
TBMCCoreAPI.SendException(
|
|
||||||
"An error occured while downloading flair for " + player.getCustomName() + "!", e);
|
|
||||||
player.sendMessage(
|
|
||||||
"Sorry, but an error occured while trying to get your flair. Please contact a mod.");
|
|
||||||
mp.Working = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mp.getFlairState().equals(FlairStates.Commented)) {
|
|
||||||
player.sendMessage(
|
|
||||||
"Sorry, but your flair isn't recorded. Please ask an admin to set it for you. Also, prepare a comment on /r/thebutton, if possible.");
|
|
||||||
mp.Working = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String flair = mp.GetFormattedFlair();
|
|
||||||
mp.setFlairState(FlairStates.Accepted);
|
|
||||||
PluginMain.ConfirmUserMessage(mp);
|
|
||||||
player.sendMessage("§bYour flair has been set:§r " + flair);
|
|
||||||
mp.Working = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
tt.mp = p;
|
|
||||||
timer.schedule(tt, 20);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetUCommandPath() {
|
|
||||||
return "accept";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
package buttondevteam.chat.commands.ucmds;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import buttondevteam.chat.ChatPlayer;
|
|
||||||
import buttondevteam.chat.PluginMain;
|
|
||||||
import buttondevteam.lib.TBMCPlayer;
|
|
||||||
import buttondevteam.lib.chat.*;
|
|
||||||
|
|
||||||
public class CCommand extends UCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- Rainbow mode ----", "This command allows you to talk in rainbow colors",
|
|
||||||
"You need to be a donator or a mod to use this command" };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
Player player = (Player) sender;
|
|
||||||
ChatPlayer p = TBMCPlayer.getPlayerAs(player, ChatPlayer.class);
|
|
||||||
if (args.length < 1) {
|
|
||||||
if (PluginMain.permission.has(player, "tbmc.rainbow")) {
|
|
||||||
p.RainbowPresserColorMode = !p.RainbowPresserColorMode;
|
|
||||||
p.OtherColorMode = null;
|
|
||||||
if (p.RainbowPresserColorMode)
|
|
||||||
player.sendMessage("§eRainbow colors §aenabled.");
|
|
||||||
else
|
|
||||||
player.sendMessage("§eRainbow colors §cdisabled.");
|
|
||||||
} else {
|
|
||||||
player.sendMessage("§cYou don't have permission for this command. Donate to get it!");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (PluginMain.permission.has(player, "tbmc.admin")) {
|
|
||||||
p.RainbowPresserColorMode = false;
|
|
||||||
p.OtherColorMode = null;
|
|
||||||
try {
|
|
||||||
p.OtherColorMode = Color.valueOf(args[0].toLowerCase());
|
|
||||||
} catch (Exception e) {
|
|
||||||
player.sendMessage("§cUnknown message color: " + args[0]);
|
|
||||||
player.sendMessage("§cUse color names, like blue, or dark_aqua");
|
|
||||||
}
|
|
||||||
if (p.OtherColorMode != null)
|
|
||||||
player.sendMessage(String.format("§eMessage color set to %s", p.OtherColorMode));
|
|
||||||
else
|
|
||||||
player.sendMessage("§eMessage color reset.");
|
|
||||||
} else {
|
|
||||||
player.sendMessage("§cYou don't have permission for this command.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetUCommandPath() {
|
|
||||||
return "c";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,86 +1,63 @@
|
||||||
package buttondevteam.chat.commands.ucmds;
|
package buttondevteam.chat.commands.ucmds;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.CustomTabComplete;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import buttondevteam.chat.PluginMain;
|
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
|
||||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
|
||||||
|
|
||||||
|
@CommandClass(modOnly = false, helpText = {
|
||||||
|
"Help",
|
||||||
|
"Prints out help messages for the TBMC plugins"
|
||||||
|
})
|
||||||
public final class HelpCommand extends UCommandBase {
|
public final class HelpCommand extends UCommandBase {
|
||||||
|
@Command2.Subcommand
|
||||||
@Override
|
public boolean def(CommandSender sender, @Command2.TextArg @Command2.OptionalArg
|
||||||
public String[] GetHelpText(String alias) {
|
@CustomTabComplete({"commands", "chat", "colors"}) String topicOrCommand) {
|
||||||
return new String[] { "§6---- Help ----", "Prints out help messages for the TBMC plugins" };
|
if (topicOrCommand == null) {
|
||||||
}
|
sender.sendMessage(new String[]{
|
||||||
|
"§6---- Chroma Help ----",
|
||||||
@Override
|
"Do /u help <topic> for more info",
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
"Do /u help <commandname> [subcommands] for more info about a command",
|
||||||
if (args.length == 0) {
|
"Topics:",
|
||||||
sender.sendMessage(new String[] { "§6---- TBMC Help ----", "Do /u help <topic> for more info",
|
|
||||||
"Do /u help <commandname> [subcommands] for more info about a command", "Topics:",
|
|
||||||
"commands: See all the commands from this plugin",
|
"commands: See all the commands from this plugin",
|
||||||
"chat: Shows some info about custom chat features", "colors: Shows Minecraft color codes" });
|
"chat: Shows some info about custom chat features",
|
||||||
|
"colors: Shows Minecraft color codes"
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (args[0].equalsIgnoreCase("chat"))
|
if (topicOrCommand.equalsIgnoreCase("chat"))
|
||||||
sender.sendMessage(new String[]{"§6---- Chat features ----",
|
sender.sendMessage(new String[]{"§6---- Chat features ----",
|
||||||
"- [g] Channel identifier: Click it to copy message", "-- [g]: Global chat (/g)",
|
"- [g] Channel identifier: Click it to copy message", "-- [g] Global chat (/g)",
|
||||||
"-- [TC] Town chat (/tc)", "-- [NC] Nation chat (/nc)",
|
"-- [TC] Town chat (/tc)", "-- [NC] Nation chat (/nc)",
|
||||||
"- Playernames: Hover over them to get some player info",
|
"- Playernames: Hover over them to get some player info",
|
||||||
"-- Respect: This is the number of paid respects divided by eliglble deaths. This is a reference to CoD:AW's \"Press F to pay respects\"" });
|
"-- Respect: This is the number of paid respects divided by eligible deaths. This is a reference to CoD:AW's \"Press F to pay respects\""});
|
||||||
else if (args[0].equalsIgnoreCase("commands")) {
|
else if (topicOrCommand.equalsIgnoreCase("commands")) {
|
||||||
ArrayList<String> text = new ArrayList<String>();
|
sender.sendMessage(getManager().getCommandsText());
|
||||||
text.add("§6---- Command list ----");
|
} else if (topicOrCommand.equalsIgnoreCase("colors")) {
|
||||||
for (TBMCCommandBase cmd : TBMCChatAPI.GetCommands().values())
|
|
||||||
if (!cmd.GetCommandPath().contains(" "))
|
|
||||||
if (!cmd.GetModOnly() || PluginMain.permission.has(sender, "tbmc.admin"))
|
|
||||||
if (!cmd.GetPlayerOnly() || sender instanceof Player)
|
|
||||||
text.add("/" + cmd.GetCommandPath());
|
|
||||||
sender.sendMessage(text.toArray(new String[text.size()]));
|
|
||||||
} else if (args[0].equalsIgnoreCase("colors")) {
|
|
||||||
sender.sendMessage(new String[]{"§6---- Chat colors/formats ----", //
|
sender.sendMessage(new String[]{"§6---- Chat colors/formats ----", //
|
||||||
"Tellraw name - Code | Tellraw name - Code", //
|
"Tellraw name - Code | Tellraw name - Code", //
|
||||||
"§0black - &0 | §1dark_blue - &1", //
|
"§0black - &0§r | §1dark_blue - &1§r", //
|
||||||
"§2dark_green - &2 | §3dark_aqua - &3", //
|
"§2dark_green - &2§r | §3dark_aqua - &3§r", //
|
||||||
"§4dark_red - &4 | §5dark_purple - &5", //
|
"§4dark_red - &4§r | §5dark_purple - &5§r", //
|
||||||
"§6gold - &6 | §7gray - &7", //
|
"§6gold - &6§r | §7gray - &7§r", //
|
||||||
"§8dark_gray - &8 | §9blue - &9", //
|
"§8dark_gray - &8§r | §9blue - &9§r", //
|
||||||
"§agreen - &a | §baqua - &b", //
|
"§agreen - &a§r | §baqua - &b§r", //
|
||||||
"§cred - &c | §dlight_purple - &d", //
|
"§cred - &c§r | §dlight_purple - &d§r", //
|
||||||
"§eyellow - &e | §fwhite - &f", //
|
"§eyellow - &e§r | §fwhite - &f§r", //
|
||||||
"§rreset - &r | §kk§robfuscated - &k", //
|
"§rreset - &r§r | §kk§robfuscated - &k§r", //
|
||||||
"§lbold - &l | §mstrikethrough - &m", //
|
"§lbold - &l§r | §mstrikethrough - &m§r", //
|
||||||
"§nunderline - &n | §oitalic - &o", //
|
"§nunderline - &n§r | §oitalic - &o§r", //
|
||||||
"The format codes in tellraw should be used like \"italic\":\"true\""}); //
|
"The format codes in tellraw should be used like \"italic\":\"true\""}); //
|
||||||
} else {
|
} else {
|
||||||
String path = args[0];
|
String[] text = getManager().getCommandNode(topicOrCommand).getData().getHelpText(sender); // TODO: This only works for the main command, not subcommands
|
||||||
for (int i = 1; i < args.length; i++)
|
if (text == null) // TODO: Null check for command node
|
||||||
path += " " + args[i];
|
sender.sendMessage(
|
||||||
TBMCCommandBase cmd = TBMCChatAPI.GetCommands().get(path);
|
new String[]{"§cError: Command not found: " + topicOrCommand,
|
||||||
if (cmd == null) {
|
|
||||||
String[] subcmds = TBMCChatAPI.GetSubCommands(path, sender);
|
|
||||||
if (subcmds.length > 0)
|
|
||||||
sender.sendMessage(subcmds);
|
|
||||||
else
|
|
||||||
sender.sendMessage(new String[] { "§cError: Command not found or you don't have permission for it: " + path,
|
|
||||||
"Usage example: /u accept --> /u help u accept"});
|
"Usage example: /u accept --> /u help u accept"});
|
||||||
} else
|
else
|
||||||
sender.sendMessage(cmd.GetHelpText(args[0]));
|
sender.sendMessage(text);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetUCommandPath() {
|
|
||||||
return "help";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetPlayerOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
package buttondevteam.chat.commands.ucmds;
|
||||||
|
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.core.component.channel.Channel;
|
||||||
|
import buttondevteam.lib.chat.ChatMessage;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.CustomTabCompleteMethod;
|
||||||
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
|
import lombok.val;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@CommandClass(helpText = {
|
||||||
|
"Chat History", //
|
||||||
|
"Returns the last 10 messages the player can see." //
|
||||||
|
})
|
||||||
|
public class HistoryCommand extends UCommandBase {
|
||||||
|
/**
|
||||||
|
* Key: ChannelID_groupID
|
||||||
|
*/
|
||||||
|
private static final HashMap<String, LinkedList<HistoryEntry>> messages = new HashMap<>();
|
||||||
|
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean def(ChromaGamerBase sender, @Command2.OptionalArg String channel) {
|
||||||
|
return showHistory(sender, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean showHistory(ChromaGamerBase sender, String channel) {
|
||||||
|
if (!PluginMain.Instance.storeChatHistory.get()) {
|
||||||
|
sender.sendMessage("§6Chat history is disabled");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Function<Channel, LinkedList<HistoryEntry>> getThem = ch -> messages.get(ch.getIdentifier() + "_" + ch.getGroupID(sender)); //If can't see, groupID is null, and that shouldn't be in the map
|
||||||
|
sender.sendMessage("§6---- Chat History ----");
|
||||||
|
Stream<Channel> stream;
|
||||||
|
if (channel == null) {
|
||||||
|
stream = Channel.getChannels();
|
||||||
|
} else {
|
||||||
|
Optional<Channel> och = Channel.getChannels().filter(chan -> chan.getIdentifier().equalsIgnoreCase(channel)).findAny();
|
||||||
|
if (!och.isPresent()) {
|
||||||
|
sender.sendMessage("§cChannel not found. Use the ID, for example: /u history g");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
stream = Stream.of(och.get());
|
||||||
|
}
|
||||||
|
AtomicBoolean sent = new AtomicBoolean();
|
||||||
|
synchronized (messages) {
|
||||||
|
val arr = stream.map(getThem).filter(Objects::nonNull).flatMap(Collection::stream)
|
||||||
|
.sorted(Comparator.comparingLong(he -> he.timestamp)).toArray(HistoryEntry[]::new);
|
||||||
|
for (int i = Math.max(0, arr.length - 10); i < arr.length; i++) {
|
||||||
|
HistoryEntry e = arr[i];
|
||||||
|
val cm = e.chatMessage;
|
||||||
|
sender.sendMessage("[" + e.channel.displayName.get() + "] " + cm.getUser().getName() + ": " + cm.getMessage());
|
||||||
|
sent.set(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!sent.get())
|
||||||
|
sender.sendMessage("No messages can be found.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@CustomTabCompleteMethod(param = "channel")
|
||||||
|
public Iterable<String> def() {
|
||||||
|
return Channel.getChannels().map(Channel::getIdentifier)::iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param timestamp System.nanoTime()
|
||||||
|
*/
|
||||||
|
private record HistoryEntry(long timestamp, ChatMessage chatMessage, Channel channel) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addChatMessage(ChatMessage chatMessage, Channel channel) {
|
||||||
|
if (!PluginMain.Instance.storeChatHistory.get()) return;
|
||||||
|
val groupID = channel.getGroupID(chatMessage.getPermCheck());
|
||||||
|
if (groupID == null) return; //Just to be sure
|
||||||
|
synchronized (messages) {
|
||||||
|
var ll = messages.computeIfAbsent(channel.getIdentifier() + "_" + groupID, k -> new LinkedList<>()); //<-- TIL
|
||||||
|
ll.add(new HistoryEntry(System.nanoTime(), chatMessage, channel)); //Adds as last element
|
||||||
|
while (ll.size() > 10)
|
||||||
|
ll.remove(); //Removes the first element
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,46 +0,0 @@
|
||||||
package buttondevteam.chat.commands.ucmds;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import buttondevteam.chat.ChatPlayer;
|
|
||||||
import buttondevteam.chat.FlairStates;
|
|
||||||
import buttondevteam.lib.TBMCPlayer;
|
|
||||||
|
|
||||||
public final class IgnoreCommand extends UCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- Ignore flair ----",
|
|
||||||
"Stop the \"write your name in the thread\" message from showing up",
|
|
||||||
"Use /u ignore <username> if you commented from multiple accounts" };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
final Player player = (Player) sender;
|
|
||||||
ChatPlayer p = TBMCPlayer.getPlayerAs(player, ChatPlayer.class);
|
|
||||||
if (p.getFlairState().equals(FlairStates.Accepted)) {
|
|
||||||
player.sendMessage("§cYou can only ignore the \"write your name in the thread\" message.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (p.getFlairState().equals(FlairStates.Commented)) {
|
|
||||||
player.sendMessage("Sorry, but your flair isn't recorded. Please ask a mod to set it for you.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!p.getFlairState().equals(FlairStates.Ignored)) {
|
|
||||||
p.setFlairState(FlairStates.Ignored);
|
|
||||||
p.SetFlair(ChatPlayer.FlairTimeNone);
|
|
||||||
p.setUserName("");
|
|
||||||
player.sendMessage("§bYou have ignored the message.§r");
|
|
||||||
} else
|
|
||||||
player.sendMessage("§cYou already ignored the message.§r");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetUCommandPath() {
|
|
||||||
return "ignore";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,47 +1,30 @@
|
||||||
package buttondevteam.chat.commands.ucmds;
|
package buttondevteam.chat.commands.ucmds;
|
||||||
|
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.player.ChromaGamerBase.InfoTarget;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayer;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import buttondevteam.lib.TBMCPlayer;
|
@CommandClass(modOnly = false, helpText = {
|
||||||
import buttondevteam.lib.TBMCPlayer.InfoTarget;
|
"User information", //
|
||||||
|
|
||||||
public class InfoCommand extends UCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { //
|
|
||||||
"§6---- User information ----", //
|
|
||||||
"Get some information known about the user.", //
|
"Get some information known about the user.", //
|
||||||
"Usage: /u " + alias + " <playername>" //
|
})
|
||||||
};
|
public class InfoCommand extends UCommandBase {
|
||||||
}
|
@Command2.Subcommand
|
||||||
|
public boolean def(CommandSender sender, OfflinePlayer player) {
|
||||||
@Override
|
Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
|
||||||
public String GetUCommandPath() {
|
TBMCPlayer p = TBMCPlayerBase.getPlayer(player.getUniqueId(), TBMCPlayer.class);
|
||||||
return "info";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
if (args.length == 0)
|
|
||||||
return false;
|
|
||||||
if (args[0].equalsIgnoreCase("console") || args[0].equalsIgnoreCase("server")
|
|
||||||
|| args[0].equalsIgnoreCase("@console")) {
|
|
||||||
sender.sendMessage("The server console."); // TODO: Console login? The Discord thing might replace it
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
try (TBMCPlayer p = TBMCPlayer.getFromName(args[0])) {
|
|
||||||
if (p == null) {
|
if (p == null) {
|
||||||
sender.sendMessage("§cThe specified player cannot be found");
|
sender.sendMessage("§cThe specified player cannot be found");
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
sender.sendMessage(p.getInfo(InfoTarget.MCCommand));
|
sender.sendMessage(p.getInfo(InfoTarget.MCCommand));
|
||||||
}
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetPlayerOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
package buttondevteam.chat.commands.ucmds;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
public class OpmeCommand extends UCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- OP me ----", "Totally makes you OP" };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
sender.sendMessage("It would be nice, wouldn't it?");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetUCommandPath() {
|
|
||||||
return "opme";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package buttondevteam.chat.commands.ucmds;
|
||||||
|
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
@CommandClass(helpText = {
|
||||||
|
"Reload",
|
||||||
|
"Reloads the config"
|
||||||
|
}, modOnly = true)
|
||||||
|
public class ReloadCommand extends UCommandBase {
|
||||||
|
@Command2.Subcommand
|
||||||
|
public void def(CommandSender sender) {
|
||||||
|
if (PluginMain.Instance.tryReloadConfig())
|
||||||
|
sender.sendMessage("§bReloaded config");
|
||||||
|
else
|
||||||
|
sender.sendMessage("§cFailed to reload config.");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,25 +1,8 @@
|
||||||
package buttondevteam.chat.commands.ucmds;
|
package buttondevteam.chat.commands.ucmds;
|
||||||
|
|
||||||
import buttondevteam.lib.chat.TBMCCommandBase;
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
|
|
||||||
public abstract class UCommandBase extends TBMCCommandBase {
|
@CommandClass(modOnly = false, path = "u")
|
||||||
|
public abstract class UCommandBase extends ICommand2MC {
|
||||||
public abstract String[] GetHelpText(String alias);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetCommandPath() {
|
|
||||||
return "u " + GetUCommandPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract String GetUCommandPath();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetPlayerOnly() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetModOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,9 @@
|
||||||
package buttondevteam.chat.commands.ucmds.admin;
|
package buttondevteam.chat.commands.ucmds.admin;
|
||||||
|
|
||||||
import buttondevteam.chat.commands.ucmds.UCommandBase;
|
import buttondevteam.chat.commands.ucmds.UCommandBase;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
|
||||||
|
@CommandClass(modOnly = true)
|
||||||
public abstract class AdminCommandBase extends UCommandBase {
|
public abstract class AdminCommandBase extends UCommandBase {
|
||||||
|
|
||||||
public abstract String[] GetHelpText(String alias);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetUCommandPath() {
|
|
||||||
return "admin " + GetAdminCommandPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetPlayerOnly() {
|
|
||||||
return false; // Allow admin commands in console
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract String GetAdminCommandPath();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetModOnly() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +1,28 @@
|
||||||
package buttondevteam.chat.commands.ucmds.admin;
|
package buttondevteam.chat.commands.ucmds.admin;
|
||||||
|
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import buttondevteam.chat.PluginMain;
|
@CommandClass(helpText = {
|
||||||
|
"Debug mode",
|
||||||
|
"Toggles debug mode, which prints debug messages to the console."
|
||||||
|
})
|
||||||
public class DebugCommand extends AdminCommandBase {
|
public class DebugCommand extends AdminCommandBase {
|
||||||
private static boolean DebugMode = false;
|
public static boolean DebugMode = false;
|
||||||
|
|
||||||
@Override
|
@Command2.Subcommand
|
||||||
public String[] GetHelpText(String alias) {
|
public boolean def(CommandSender sender) {
|
||||||
return new String[] { "§6---- Debug mode ----",
|
sender.sendMessage("§eDebug mode " + ((DebugMode = !DebugMode) ? "§aenabled." : "§cdisabled."));
|
||||||
"Toggles debug mode, which prints debug messages to the console." };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetAdminCommandPath() {
|
|
||||||
return "debug";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
sender.sendMessage("§eDebug mode "
|
|
||||||
+ ((DebugMode = !DebugMode) ? "§aenabled." : "§cdisabled."));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SendDebugMessage(String message) {
|
public static void SendDebugMessage(String message) {
|
||||||
if (DebugMode)
|
if (DebugMode)
|
||||||
|
if (PluginMain.Instance != null)
|
||||||
PluginMain.Instance.getLogger().info(message);
|
PluginMain.Instance.getLogger().info(message);
|
||||||
|
else
|
||||||
|
System.out.println(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
package buttondevteam.chat.commands.ucmds.admin;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
import buttondevteam.chat.ChatPlayer;
|
|
||||||
import buttondevteam.lib.TBMCPlayer;
|
|
||||||
|
|
||||||
public class PlayerInfoCommand extends AdminCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- Player info ----",
|
|
||||||
"Shows some info about the player's flair, Reddit username(s) and other data known by the plugin",
|
|
||||||
"Usage: /u admin playerinfo <player>" };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
if (args.length == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ChatPlayer p = TBMCPlayer.getFromName(args[0]).asPluginPlayer(ChatPlayer.class);
|
|
||||||
if (p == null) {
|
|
||||||
sender.sendMessage("§cPlayer not found: " + args[0] + "§r");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("§6Usernames:");
|
|
||||||
for (String username : p.getUserNames())
|
|
||||||
sb.append(" ").append(username);
|
|
||||||
sender.sendMessage(new String[] { //
|
|
||||||
"Player name: " + p.getPlayerName(), //
|
|
||||||
"User flair: " + p.GetFormattedFlair(), //
|
|
||||||
"Username: " + p.getUserName(), //
|
|
||||||
"Flair state: " + p.getFlairState(), //
|
|
||||||
sb.toString(), //
|
|
||||||
"FCount: " + p.getFCount(), //
|
|
||||||
"FDeaths: " + p.getFDeaths() //
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetAdminCommandPath() {
|
|
||||||
return "playerinfo";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
package buttondevteam.chat.commands.ucmds.admin;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
import buttondevteam.chat.PluginMain;
|
|
||||||
|
|
||||||
public class SaveCommand extends AdminCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- Save config ----",
|
|
||||||
"This command saves the config file(s)" };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias,
|
|
||||||
String[] args) {
|
|
||||||
PluginMain.SaveFiles(); // 2015.08.09.
|
|
||||||
sender.sendMessage("§bSaved files. Now you can edit them and reload if you want.§r");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetAdminCommandPath() {
|
|
||||||
return "save";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
package buttondevteam.chat.commands.ucmds.admin;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import buttondevteam.chat.ChatPlayer;
|
|
||||||
import buttondevteam.chat.FlairStates;
|
|
||||||
import buttondevteam.lib.TBMCPlayer;
|
|
||||||
|
|
||||||
public class SetFlairCommand extends AdminCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- Set flair -----", "Set a flair for a player",
|
|
||||||
"Usage: /u admin setflair <player> <flairtime (or non-presser, cant-press, none)> <cheater(true/false)> [username]",
|
|
||||||
"Example 1: /u admin setflair NorbiPeti 19 false NorbiPeti --> orange (19s)",
|
|
||||||
"Example 2: /u admin setflair iie 0 true asde --> purple (0s)" };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
if (args.length < 3) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Player p = Bukkit.getPlayer(args[0]);
|
|
||||||
if (p == null) {
|
|
||||||
sender.sendMessage("§cPlayer not found.&r");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
short flairtime = 0x00;
|
|
||||||
if (args[1].equalsIgnoreCase("non-presser"))
|
|
||||||
flairtime = ChatPlayer.FlairTimeNonPresser;
|
|
||||||
else if (args[1].equalsIgnoreCase("cant-press"))
|
|
||||||
flairtime = ChatPlayer.FlairTimeCantPress;
|
|
||||||
else if (args[1].equalsIgnoreCase("none"))
|
|
||||||
flairtime = ChatPlayer.FlairTimeNone;
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
flairtime = Short.parseShort(args[1]);
|
|
||||||
} catch (Exception e) {
|
|
||||||
sender.sendMessage(
|
|
||||||
"§cFlairtime must be a number, \"non-presser\", \"cant-press\" or \"none\". Run without args to see usage.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
boolean cheater = false;
|
|
||||||
if (args[2].equalsIgnoreCase("true"))
|
|
||||||
cheater = true;
|
|
||||||
else if (args[2].equalsIgnoreCase("false"))
|
|
||||||
cheater = false;
|
|
||||||
else {
|
|
||||||
sender.sendMessage("§cUnknown value for cheater parameter. Run without args to see usage.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
ChatPlayer mp = TBMCPlayer.getPlayerAs(p, ChatPlayer.class);
|
|
||||||
mp.SetFlair(flairtime, cheater);
|
|
||||||
mp.setFlairState(FlairStates.Accepted);
|
|
||||||
if (args.length < 4)
|
|
||||||
mp.setUserName("");
|
|
||||||
else {
|
|
||||||
mp.setUserName(args[3]);
|
|
||||||
if (!mp.getUserNames().contains(args[3]))
|
|
||||||
mp.getUserNames().add(args[3]);
|
|
||||||
}
|
|
||||||
sender.sendMessage(
|
|
||||||
"§bThe flair has been set. Player: " + mp.getPlayerName() + " Flair: " + mp.GetFormattedFlair() + "§r");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetAdminCommandPath() {
|
|
||||||
return "setflair";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
package buttondevteam.chat.commands.ucmds.admin;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
import buttondevteam.chat.PluginMain;
|
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
|
||||||
|
|
||||||
public class UpdatePlugin extends AdminCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { //
|
|
||||||
"§6---- Update plugin ----", //
|
|
||||||
"This command downloads the latest version of a TBMC plugin from GitHub", //
|
|
||||||
"To update a plugin: /" + alias + " <plugin>", //
|
|
||||||
"To list the plugin names: /" + alias //
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias, String[] args) {
|
|
||||||
if (args.length == 0) {
|
|
||||||
sender.sendMessage("Downloading plugin names...");
|
|
||||||
boolean first = true;
|
|
||||||
for (String plugin : TBMCCoreAPI.GetPluginNames()) {
|
|
||||||
if (first) {
|
|
||||||
sender.sendMessage("§6---- Plugin names ----");
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
sender.sendMessage("- " + plugin);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
|
|
||||||
TBMCCoreAPI.UpdatePlugin(args[0], sender, args.length == 1 ? "master" : args[1]);
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetAdminCommandPath() {
|
|
||||||
return "updateplugin";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
package buttondevteam.chat.commands.ucmds.announce;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
import buttondevteam.chat.PluginMain;
|
|
||||||
|
|
||||||
public class AddCommand extends AnnounceCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] {
|
|
||||||
"§6---- Add announcement ----",
|
|
||||||
"This command adds a new announcement",
|
|
||||||
"Note: Please avoid using this command, if possible",
|
|
||||||
"Instead, use the command blocks in flatworld to set announcements",
|
|
||||||
"This makes editing announcements easier" };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias,
|
|
||||||
String[] args) {
|
|
||||||
if (args.length < 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (int i = 2; i < args.length; i++) {
|
|
||||||
sb.append(args[i]);
|
|
||||||
if (i != args.length - 1)
|
|
||||||
sb.append(" ");
|
|
||||||
}
|
|
||||||
String finalmessage = sb.toString().replace('&', '§');
|
|
||||||
PluginMain.AnnounceMessages.add(finalmessage);
|
|
||||||
sender.sendMessage("§bAnnouncement added. - Plase avoid using this command if possible, see /u announce add without args.§r");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetAnnounceCommandPath() {
|
|
||||||
return "add";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
package buttondevteam.chat.commands.ucmds.announce;
|
|
||||||
|
|
||||||
import buttondevteam.chat.commands.ucmds.UCommandBase;
|
|
||||||
|
|
||||||
public abstract class AnnounceCommandBase extends UCommandBase {
|
|
||||||
|
|
||||||
public abstract String[] GetHelpText(String alias);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetUCommandPath() {
|
|
||||||
return "announce " + GetAnnounceCommandPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract String GetAnnounceCommandPath();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean GetPlayerOnly() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
package buttondevteam.chat.commands.ucmds.announce;
|
|
||||||
|
|
||||||
import org.bukkit.command.BlockCommandSender;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
import buttondevteam.chat.PluginMain;
|
|
||||||
|
|
||||||
public class EditCommand extends AnnounceCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- Edit announcement ----",
|
|
||||||
"This command can only be used in a command block.",
|
|
||||||
"Usage: /u annonunce edit <index> <text>" };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias,
|
|
||||||
String[] args) {
|
|
||||||
if (!(sender instanceof BlockCommandSender)) {
|
|
||||||
sender.sendMessage("§cError: This command can only be used from a command block. You can use add and remove, though it's not recommended.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (args.length < 4) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
StringBuilder sb1 = new StringBuilder();
|
|
||||||
for (int i1 = 3; i1 < args.length; i1++) {
|
|
||||||
sb1.append(args[i1]);
|
|
||||||
if (i1 != args.length - 1)
|
|
||||||
sb1.append(" ");
|
|
||||||
}
|
|
||||||
String finalmessage1 = sb1.toString().replace('&', '§');
|
|
||||||
int index = Integer.parseInt(args[2]);
|
|
||||||
if (index > 100)
|
|
||||||
return false;
|
|
||||||
while (PluginMain.AnnounceMessages.size() <= index)
|
|
||||||
PluginMain.AnnounceMessages.add("");
|
|
||||||
PluginMain.AnnounceMessages.set(Integer.parseInt(args[2]),
|
|
||||||
finalmessage1);
|
|
||||||
sender.sendMessage("Announcement edited.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetAnnounceCommandPath() {
|
|
||||||
return "edit";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
package buttondevteam.chat.commands.ucmds.announce;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
import buttondevteam.chat.PluginMain;
|
|
||||||
|
|
||||||
public class ListCommand extends AnnounceCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- List announcements ----",
|
|
||||||
"This command lists the announcements and the time between them" };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias,
|
|
||||||
String[] args) {
|
|
||||||
sender.sendMessage("§bList of announce messages:§r");
|
|
||||||
sender.sendMessage("§bFormat: [index] message§r");
|
|
||||||
int i = 0;
|
|
||||||
for (String message : PluginMain.AnnounceMessages)
|
|
||||||
sender.sendMessage("[" + i++ + "] " + message);
|
|
||||||
sender.sendMessage("§bCurrent wait time between announcements: "
|
|
||||||
+ PluginMain.AnnounceTime / 60 / 1000 + " minute(s)§r");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetAnnounceCommandPath() {
|
|
||||||
return "list";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
package buttondevteam.chat.commands.ucmds.announce;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
import buttondevteam.chat.PluginMain;
|
|
||||||
|
|
||||||
public class RemoveCommand extends AnnounceCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] {
|
|
||||||
"§6---- Remove announcement ----",
|
|
||||||
"This command removes an announcement",
|
|
||||||
"Note: Please avoid using this command, if possible",
|
|
||||||
"Instead, use the command blocks in flatworld to set announcements",
|
|
||||||
"This makes editing announcements easier" };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias,
|
|
||||||
String[] args) {
|
|
||||||
if (args.length < 1) {
|
|
||||||
sender.sendMessage("§cUsage: /u announce remove <index>");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
PluginMain.AnnounceMessages.remove(Integer.parseInt(args[0]));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetAnnounceCommandPath() {
|
|
||||||
return "remove";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
package buttondevteam.chat.commands.ucmds.announce;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
import buttondevteam.chat.PluginMain;
|
|
||||||
|
|
||||||
public class SetTimeCommand extends AnnounceCommandBase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] GetHelpText(String alias) {
|
|
||||||
return new String[] { "§6---- Set time ----",
|
|
||||||
"This command sets the time between the announcements",
|
|
||||||
"Usage: /u anonunce settime <minutes>", "Default: 15" };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean OnCommand(CommandSender sender, String alias,
|
|
||||||
String[] args) {
|
|
||||||
if (args.length < 3) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
PluginMain.AnnounceTime = Integer.parseInt(args[0]) * 60 * 1000;
|
|
||||||
} catch (Exception e) {
|
|
||||||
sender.sendMessage("§cMinutes argument must be a number. Got: "
|
|
||||||
+ args[0]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
sender.sendMessage("Time set between announce messages");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String GetAnnounceCommandPath() {
|
|
||||||
return "settime";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
package buttondevteam.chat.components.announce;
|
||||||
|
|
||||||
|
import buttondevteam.chat.commands.ucmds.UCommandBase;
|
||||||
|
import buttondevteam.chat.components.formatter.FormatterComponent;
|
||||||
|
import buttondevteam.core.ComponentManager;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.val;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
import static net.kyori.adventure.text.Component.text;
|
||||||
|
import static net.kyori.adventure.text.event.ClickEvent.Action.SUGGEST_COMMAND;
|
||||||
|
import static net.kyori.adventure.text.event.ClickEvent.clickEvent;
|
||||||
|
import static net.kyori.adventure.text.event.HoverEvent.Action.SHOW_TEXT;
|
||||||
|
import static net.kyori.adventure.text.event.HoverEvent.hoverEvent;
|
||||||
|
|
||||||
|
@CommandClass(modOnly = true)
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AnnounceCommand extends UCommandBase {
|
||||||
|
private final AnnouncerComponent component;
|
||||||
|
|
||||||
|
@Command2.Subcommand(helpText = {
|
||||||
|
"Add announcement",
|
||||||
|
"This command adds a new announcement",
|
||||||
|
})
|
||||||
|
public boolean add(CommandSender sender, @Command2.TextArg String text) {
|
||||||
|
String finalmessage = text.replace('&', '§');
|
||||||
|
component.announceMessages.get().add(finalmessage);
|
||||||
|
sender.sendMessage("§bAnnouncement added.§r");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command2.Subcommand(helpText = {
|
||||||
|
"Edit announcement",
|
||||||
|
"This command lets you edit an announcement by its index.",
|
||||||
|
"Shouldn't be used directly, use either command blocks or click on an announcement in /u announce list instead."
|
||||||
|
})
|
||||||
|
public boolean edit(CommandSender sender, byte index, @Command2.TextArg String text) {
|
||||||
|
String finalmessage1 = text.replace('&', '§');
|
||||||
|
if (index > 100)
|
||||||
|
return false;
|
||||||
|
while (component.announceMessages.get().size() <= index)
|
||||||
|
component.announceMessages.get().add("");
|
||||||
|
component.announceMessages.get().set(index, finalmessage1);
|
||||||
|
sender.sendMessage("Announcement edited.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command2.Subcommand(helpText = {
|
||||||
|
"List announcements",
|
||||||
|
"This command lists the announcements and the time between them"
|
||||||
|
})
|
||||||
|
public boolean list(CommandSender sender) {
|
||||||
|
sender.sendMessage("§bList of announce messages:§r");
|
||||||
|
sender.sendMessage("§bFormat: [index] message§r");
|
||||||
|
int i = 0;
|
||||||
|
for (String message : component.announceMessages.get()) {
|
||||||
|
String msg = "[" + i++ + "] " + message;
|
||||||
|
//noinspection SuspiciousMethodCalls
|
||||||
|
if (!ComponentManager.isEnabled(FormatterComponent.class) || !Bukkit.getOnlinePlayers().contains(sender)) {
|
||||||
|
sender.sendMessage(msg);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sender.sendMessage(text(msg)
|
||||||
|
.hoverEvent(hoverEvent(SHOW_TEXT, text("Click to edit")))
|
||||||
|
.clickEvent(clickEvent(SUGGEST_COMMAND, "/" + getCommandPath() + " edit " + (i - 1) + " " + message.replace('§', '&'))));
|
||||||
|
}
|
||||||
|
sender.sendMessage("§bCurrent wait time between announcements: "
|
||||||
|
+ component.announceTime.get() / 60 / 1000 + " minute(s)§r");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command2.Subcommand(helpText = {
|
||||||
|
"Remove announcement",
|
||||||
|
"This command removes an announcement"
|
||||||
|
})
|
||||||
|
public boolean remove(CommandSender sender, int index) {
|
||||||
|
val msgs = component.announceMessages.get();
|
||||||
|
if (index < 0 || index > msgs.size()) return false;
|
||||||
|
msgs.remove(index);
|
||||||
|
sender.sendMessage("Announcement removed.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command2.Subcommand(helpText = {
|
||||||
|
"Set time",
|
||||||
|
"This command sets the time between the announcements"
|
||||||
|
})
|
||||||
|
public boolean settime(CommandSender sender, int minutes) {
|
||||||
|
component.announceTime.set(minutes * 60 * 1000);
|
||||||
|
sender.sendMessage("Time set between announce messages to " + minutes + " minutes");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package buttondevteam.chat.components.announce;
|
||||||
|
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.core.component.channel.Channel;
|
||||||
|
import buttondevteam.lib.TBMCSystemChatEvent;
|
||||||
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import buttondevteam.lib.architecture.ComponentMetadata;
|
||||||
|
import buttondevteam.lib.architecture.config.IConfigData;
|
||||||
|
import buttondevteam.lib.architecture.config.IListConfigData;
|
||||||
|
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the configured messages at the set interval when someone is online.
|
||||||
|
*/
|
||||||
|
@ComponentMetadata(enabledByDefault = false)
|
||||||
|
public class AnnouncerComponent extends Component<PluginMain> implements Runnable {
|
||||||
|
/**
|
||||||
|
* The messages to display to players.
|
||||||
|
*/
|
||||||
|
public IListConfigData<String> announceMessages = getConfig().getListData("announceMessages", Collections.emptyList());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The time in milliseconds between the messages. Use /u announce settime to set minutes.
|
||||||
|
*/
|
||||||
|
public IConfigData<Integer> announceTime = getConfig().getData("announceTime", 15 * 60 * 1000);
|
||||||
|
|
||||||
|
private TBMCSystemChatEvent.BroadcastTarget target;
|
||||||
|
|
||||||
|
private int AnnounceMessageIndex = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (isEnabled()) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(announceTime.get());
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
if (Bukkit.getOnlinePlayers().size() == 0) continue; //Don't post to Discord if nobody is on
|
||||||
|
if (announceMessages.get().size() > AnnounceMessageIndex) {
|
||||||
|
TBMCChatAPI.SendSystemMessage(Channel.globalChat, Channel.RecipientTestResult.ALL, announceMessages.get().get(AnnounceMessageIndex), target);
|
||||||
|
AnnounceMessageIndex++;
|
||||||
|
if (AnnounceMessageIndex == announceMessages.get().size())
|
||||||
|
AnnounceMessageIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void enable() {
|
||||||
|
target = TBMCSystemChatEvent.BroadcastTarget.add("announcements");
|
||||||
|
registerCommand(new AnnounceCommand(this));
|
||||||
|
new Thread(this).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void disable() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
package buttondevteam.chat.components.appendext;
|
||||||
|
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import buttondevteam.lib.architecture.IHaveConfig;
|
||||||
|
import buttondevteam.lib.architecture.config.IConfigData;
|
||||||
|
import buttondevteam.lib.chat.*;
|
||||||
|
import lombok.val;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows players to append tableflips and other things to their messages. Everything is configurable here.
|
||||||
|
*/
|
||||||
|
public class AppendTextComponent extends Component<PluginMain> {
|
||||||
|
private Map<String, IHaveConfig> appendTexts;
|
||||||
|
|
||||||
|
private IConfigData<String[]> helpText(IHaveConfig config) {
|
||||||
|
return config.getData("helpText", new String[]{
|
||||||
|
"Tableflip", //
|
||||||
|
"This command appends a tableflip after your message", //
|
||||||
|
"Or just makes you tableflip", //
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private IConfigData<String> appendedText(IHaveConfig config) {
|
||||||
|
return config.getData("appendedText", "tableflip");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void enable() {
|
||||||
|
val map = new HashMap<String, Consumer<IHaveConfig>>();
|
||||||
|
map.put("tableflip", conf -> {
|
||||||
|
helpText(conf).set(new String[]{
|
||||||
|
"Tableflip", //
|
||||||
|
"This command appends a tableflip after your message", //
|
||||||
|
"Or just makes you tableflip", //
|
||||||
|
});
|
||||||
|
appendedText(conf).set("(╯°□°)╯︵ ┻━┻");
|
||||||
|
});
|
||||||
|
map.put("unflip", conf -> {
|
||||||
|
helpText(conf).set(new String[]{
|
||||||
|
"Unflip", //
|
||||||
|
"This command appends an unflip after your message", //
|
||||||
|
"Or just unflips as you", //
|
||||||
|
});
|
||||||
|
appendedText(conf).set("┬─┬ ノ( ゜-゜ノ)");
|
||||||
|
});
|
||||||
|
map.put("shrug", conf -> {
|
||||||
|
helpText(conf).set(new String[]{
|
||||||
|
"Shrug", //
|
||||||
|
"This command appends a shrug after your message", //
|
||||||
|
"Or just makes you shrug", //
|
||||||
|
});
|
||||||
|
appendedText(conf).set("¯\\\\\\_(ツ)\\_/¯");
|
||||||
|
});
|
||||||
|
map.put("lenny", conf -> {
|
||||||
|
helpText(conf).set(new String[]{
|
||||||
|
"Lenny", //
|
||||||
|
"This command appends a Lenny face after your message", //
|
||||||
|
"Or just sends one", //
|
||||||
|
});
|
||||||
|
appendedText(conf).set("( ͡° ͜ʖ ͡°)");
|
||||||
|
});
|
||||||
|
map.put("waitwhat", conf -> {
|
||||||
|
helpText(conf).set(new String[]{
|
||||||
|
"Wait what", //
|
||||||
|
"Wait what" //
|
||||||
|
});
|
||||||
|
appendedText(conf).set("wait what");
|
||||||
|
});
|
||||||
|
appendTexts = getConfigMap("texts", map);
|
||||||
|
for (String cmd : appendTexts.keySet())
|
||||||
|
registerCommand(new CommandHandler(cmd));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void disable() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@CommandClass
|
||||||
|
public class CommandHandler extends ICommand2MC {
|
||||||
|
private final String path;
|
||||||
|
private final String[] helpText;
|
||||||
|
private final String appendedText;
|
||||||
|
|
||||||
|
CommandHandler(String command) {
|
||||||
|
val conf = appendTexts.get(command);
|
||||||
|
if (conf == null) throw new NoSuchElementException("AppendText command not found: " + command);
|
||||||
|
path = command;
|
||||||
|
helpText = helpText(conf).get();
|
||||||
|
appendedText = appendedText(conf).get();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command2.Subcommand
|
||||||
|
public void def(Command2MCSender sender, @Command2.OptionalArg @Command2.TextArg String message) {
|
||||||
|
TBMCChatAPI.sendChatMessage(ChatMessage.builder(sender.getSender(),
|
||||||
|
(message == null ? "" : message + " ") + appendedText).fromCommand(true).permCheck(sender.getPermCheck()).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCommandPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getHelpText(Method method, Command2.Subcommand ann) {
|
||||||
|
return helpText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package buttondevteam.chat.components.chatonly;
|
||||||
|
|
||||||
|
import buttondevteam.chat.ChatPlayer;
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.core.ComponentManager;
|
||||||
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import buttondevteam.lib.architecture.ComponentMetadata;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayer;
|
||||||
|
import lombok.val;
|
||||||
|
import net.kyori.adventure.text.TextComponent;
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.event.player.PlayerMoveEvent;
|
||||||
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
|
|
||||||
|
import static net.kyori.adventure.text.Component.text;
|
||||||
|
import static net.kyori.adventure.text.event.HoverEvent.Action.SHOW_TEXT;
|
||||||
|
import static net.kyori.adventure.text.event.HoverEvent.hoverEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows players to enter chat-only mode which puts them into spectator mode and disallows moving.
|
||||||
|
*/
|
||||||
|
@ComponentMetadata(enabledByDefault = false)
|
||||||
|
public class ChatOnlyComponent extends Component<PluginMain> implements Listener {
|
||||||
|
@Override
|
||||||
|
protected void enable() {
|
||||||
|
registerListener(this);
|
||||||
|
registerCommand(new ChatonlyCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void disable() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void playerJoin(PlayerJoinEvent event) {
|
||||||
|
val p = event.getPlayer();
|
||||||
|
val cp = TBMCPlayer.getPlayer(p.getUniqueId(), ChatPlayer.class);
|
||||||
|
if (cp.ChatOnly || p.getGameMode().equals(GameMode.SPECTATOR)) {
|
||||||
|
cp.ChatOnly = false;
|
||||||
|
p.setGameMode(GameMode.SURVIVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void tellrawCreate(ChatPlayer mp, TextComponent.Builder json) {
|
||||||
|
if (!ComponentManager.isEnabled(ChatOnlyComponent.class))
|
||||||
|
return;
|
||||||
|
if (mp != null && mp.ChatOnly) {
|
||||||
|
json.append(text("[C]").hoverEvent(hoverEvent(SHOW_TEXT, text("Chat only"))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerMove(PlayerMoveEvent e) {
|
||||||
|
ChatPlayer mp = TBMCPlayer.getPlayer(e.getPlayer().getUniqueId(), ChatPlayer.class);
|
||||||
|
if (mp.ChatOnly)
|
||||||
|
e.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
|
public void onPlayerTeleport(PlayerTeleportEvent e) {
|
||||||
|
if (TBMCPlayer.getPlayer(e.getPlayer().getUniqueId(), ChatPlayer.class).ChatOnly) {
|
||||||
|
e.setCancelled(true);
|
||||||
|
e.getPlayer().sendMessage("§cYou are not allowed to teleport while in chat-only mode.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package buttondevteam.chat.components.chatonly;
|
||||||
|
|
||||||
|
import buttondevteam.chat.ChatPlayer;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayer;
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
@CommandClass(modOnly = false, helpText = {
|
||||||
|
"Chat-only mode", //
|
||||||
|
"This mode makes you invincible but unable to move, teleport or interact with the world in any way", //
|
||||||
|
"It was designed for chat clients", //
|
||||||
|
"Once enabled, the only way of disabling it is by relogging to the server" //
|
||||||
|
})
|
||||||
|
public final class ChatonlyCommand extends ICommand2MC {
|
||||||
|
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean def(Player player) {
|
||||||
|
ChatPlayer p = TBMCPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class);
|
||||||
|
p.ChatOnly = true;
|
||||||
|
player.setGameMode(GameMode.SPECTATOR);
|
||||||
|
player.sendMessage("§bChat-only mode enabled. You are now invincible.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
package buttondevteam.chat.components.flair;
|
||||||
|
|
||||||
|
import buttondevteam.chat.ChatPlayer;
|
||||||
|
import buttondevteam.chat.PlayerJoinTimerTask;
|
||||||
|
import buttondevteam.chat.commands.ucmds.UCommandBase;
|
||||||
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayer;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.Timer;
|
||||||
|
|
||||||
|
@CommandClass(modOnly = false, helpText = {
|
||||||
|
"Accept flair", //
|
||||||
|
"Accepts a flair from Reddit", //
|
||||||
|
"Use /u accept <username> if you commented from multiple accounts"
|
||||||
|
})
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AcceptCommand extends UCommandBase {
|
||||||
|
private final FlairComponent component;
|
||||||
|
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean def(Player player, @Command2.OptionalArg String username) {
|
||||||
|
ChatPlayer p = TBMCPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class);
|
||||||
|
if (username == null && p.UserNames.get().size() > 1) {
|
||||||
|
player.sendMessage("§9Multiple users commented your name. §bPlease pick one using /u accept <username>");
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("§6Usernames:");
|
||||||
|
for (String name : p.UserNames.get())
|
||||||
|
sb.append(" ").append(name);
|
||||||
|
player.sendMessage(sb.toString());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (p.FlairState.get().equals(FlairStates.NoComment) || p.UserNames.get().size() == 0) {
|
||||||
|
player.sendMessage("§cError: You need to write your username to the reddit thread§r");
|
||||||
|
player.sendMessage(component.flairThreadURL.get());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (username != null && !p.UserNames.get().contains(username)) {
|
||||||
|
player.sendMessage("§cError: Unknown name: " + username + "§r");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (p.Working) {
|
||||||
|
player.sendMessage("§cError: Something is already in progress.§r");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((username != null ? username : p.UserNames.get().get(0)).equals(p.UserName.get())) {
|
||||||
|
player.sendMessage("§cYou already have this user's flair.§r");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (username != null)
|
||||||
|
p.UserName.set(username);
|
||||||
|
else
|
||||||
|
p.UserName.set(p.UserNames.get().get(0));
|
||||||
|
|
||||||
|
player.sendMessage("§bObtaining flair...");
|
||||||
|
p.Working = true;
|
||||||
|
Timer timer = new Timer();
|
||||||
|
PlayerJoinTimerTask tt = new PlayerJoinTimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
component.DownloadFlair(mp);
|
||||||
|
} catch (Exception e) {
|
||||||
|
TBMCCoreAPI.SendException("An error occured while downloading flair for " + player.getCustomName() + "!", e, component);
|
||||||
|
player.sendMessage("Sorry, but an error occured while trying to get your flair. Please contact a mod.");
|
||||||
|
mp.Working = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mp.FlairState.get().equals(FlairStates.Commented)) {
|
||||||
|
player.sendMessage("Sorry, but your flair isn't recorded. Please ask an admin to set it for you. Also, prepare a comment on /r/thebutton, if possible.");
|
||||||
|
mp.Working = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String flair = mp.GetFormattedFlair();
|
||||||
|
mp.FlairState.set(FlairStates.Accepted);
|
||||||
|
FlairComponent.ConfirmUserMessage(mp);
|
||||||
|
player.sendMessage("§bYour flair has been set:§r " + flair);
|
||||||
|
mp.Working = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
tt.mp = p;
|
||||||
|
timer.schedule(tt, 20);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,189 @@
|
||||||
|
package buttondevteam.chat.components.flair;
|
||||||
|
|
||||||
|
import buttondevteam.chat.ChatPlayer;
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import buttondevteam.lib.architecture.ComponentMetadata;
|
||||||
|
import buttondevteam.lib.architecture.config.IConfigData;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component checks a specific Reddit thread every 10 seconds for comments such as "IGN: NorbiPeti" to link Reddit accounts and to determine their /r/thebutton flair.
|
||||||
|
* This was the original goal of this plugin when it was made.
|
||||||
|
*/
|
||||||
|
@ComponentMetadata(enabledByDefault = false)
|
||||||
|
public class FlairComponent extends Component<PluginMain> {
|
||||||
|
/**
|
||||||
|
* The Reddit thread to check for account connections. Re-enable the component if this was empty.
|
||||||
|
*/
|
||||||
|
IConfigData<String> flairThreadURL = getConfig().getData("flairThreadURL", "");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* This variable is used as a cache for flair state checking when reading the flair thread.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* It's used because normally it has to load all associated player files every time to read the flair state
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
private final Set<String> PlayersWithFlairs = new HashSet<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void enable() {
|
||||||
|
registerCommand(new AcceptCommand(this));
|
||||||
|
registerCommand(new IgnoreCommand());
|
||||||
|
registerCommand(new SetFlairCommand());
|
||||||
|
new Thread(this::FlairGetterThreadMethod).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void disable() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FlairGetterThreadMethod() {
|
||||||
|
int errorcount = 0;
|
||||||
|
while (isEnabled() && flairThreadURL.get().length() > 0) {
|
||||||
|
try {
|
||||||
|
String body = TBMCCoreAPI.DownloadString(flairThreadURL.get() + ".json?limit=1000");
|
||||||
|
JsonArray json = new JsonParser().parse(body).getAsJsonArray().get(1).getAsJsonObject().get("data")
|
||||||
|
.getAsJsonObject().get("children").getAsJsonArray();
|
||||||
|
for (Object obj : json) {
|
||||||
|
JsonObject item = (JsonObject) obj;
|
||||||
|
String author = item.get("data").getAsJsonObject().get("author").getAsString();
|
||||||
|
String ign = item.get("data").getAsJsonObject().get("body").getAsString();
|
||||||
|
int start = ign.indexOf("IGN:") + "IGN:".length();
|
||||||
|
if (start == -1 + "IGN:".length())
|
||||||
|
continue;
|
||||||
|
int end = ign.indexOf(' ', start);
|
||||||
|
if (end == -1 || end == start)
|
||||||
|
end = ign.indexOf('\n', start);
|
||||||
|
if (end == -1 || end == start)
|
||||||
|
ign = ign.substring(start);
|
||||||
|
else
|
||||||
|
ign = ign.substring(start, end);
|
||||||
|
ign = ign.trim();
|
||||||
|
if (PlayersWithFlairs.contains(ign))
|
||||||
|
continue;
|
||||||
|
ChatPlayer mp = TBMCPlayerBase.getFromName(ign, ChatPlayer.class); // Loads player file
|
||||||
|
if (mp == null)
|
||||||
|
continue;
|
||||||
|
/*
|
||||||
|
* if (!JoinedBefore(mp, 2015, 6, 5)) continue;
|
||||||
|
*/
|
||||||
|
if (!mp.UserNames.get().contains(author))
|
||||||
|
mp.UserNames.get().add(author);
|
||||||
|
if (mp.FlairState.get().equals(FlairStates.NoComment)) {
|
||||||
|
mp.FlairState.set(FlairStates.Commented);
|
||||||
|
ConfirmUserMessage(mp);
|
||||||
|
}
|
||||||
|
PlayersWithFlairs.add(ign); // Don't redownload even if flair isn't accepted
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
errorcount++;
|
||||||
|
if (errorcount >= 10) {
|
||||||
|
errorcount = 0;
|
||||||
|
if (!e.getMessage().contains("Server returned HTTP response code")
|
||||||
|
&& !(e instanceof UnknownHostException))
|
||||||
|
TBMCCoreAPI.SendException("Error while getting flairs from Reddit!", e, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(10000);
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DownloadFlair(ChatPlayer mp) throws IOException {
|
||||||
|
String[] flairdata = TBMCCoreAPI
|
||||||
|
.DownloadString("http://karmadecay.com/thebutton-data.php?users=" + mp.UserName.get())
|
||||||
|
.replace("\"", "").split(":");
|
||||||
|
String flair;
|
||||||
|
if (flairdata.length > 1)
|
||||||
|
flair = flairdata[1];
|
||||||
|
else
|
||||||
|
flair = "";
|
||||||
|
String flairclass;
|
||||||
|
if (flairdata.length > 2)
|
||||||
|
flairclass = flairdata[2];
|
||||||
|
else
|
||||||
|
flairclass = "unknown";
|
||||||
|
SetFlair(mp, flair, flairclass, mp.UserName.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetFlair(ChatPlayer p, String text, String flairclass, String username) {
|
||||||
|
p.UserName.set(username);
|
||||||
|
p.FlairState.set(FlairStates.Recognised);
|
||||||
|
switch (flairclass) {
|
||||||
|
case "cheater":
|
||||||
|
p.SetFlair(Short.parseShort(text), true);
|
||||||
|
return;
|
||||||
|
case "unknown":
|
||||||
|
try {
|
||||||
|
if (CheckForJoinDate(p)) {
|
||||||
|
if (text.equals("-1")) // If true, only non-presser/can't press; if false, any flair (but we can still detect can't press)
|
||||||
|
p.SetFlair(ChatPlayer.FlairTimeNonPresser);
|
||||||
|
else
|
||||||
|
p.SetFlair(ChatPlayer.FlairTimeNone); // Flair unknown
|
||||||
|
} else {
|
||||||
|
p.SetFlair(ChatPlayer.FlairTimeCantPress);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
p.FlairState.set(FlairStates.Commented); // Flair unknown
|
||||||
|
p.SetFlair(ChatPlayer.FlairTimeNone);
|
||||||
|
TBMCCoreAPI.SendException("Error while checking join date for player " + p.getPlayerName() + "!", e, this);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p.SetFlair(Short.parseShort(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean CheckForJoinDate(ChatPlayer mp) throws Exception {
|
||||||
|
return JoinedBefore(mp, 2015, 4, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean JoinedBefore(ChatPlayer mp, int year, int month, int day) throws Exception {
|
||||||
|
/*URL url = new URL("https://www.reddit.com/u/" + mp.UserName());
|
||||||
|
URLConnection con = url.openConnection();
|
||||||
|
con.setRequestProperty("User-Agent", "TheButtonAutoFlair");
|
||||||
|
InputStream in = con.getInputStream();
|
||||||
|
HtmlCleaner cleaner = new HtmlCleaner();
|
||||||
|
TagNode node = cleaner.clean(in);
|
||||||
|
|
||||||
|
node = node.getElementsByAttValue("class", "age", true, true)[0];
|
||||||
|
node = node.getElementsByName("time", false)[0];
|
||||||
|
String joindate = node.getAttributeByName("datetime");
|
||||||
|
SimpleDateFormat parserSDF = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
joindate = joindate.split("T")[0];
|
||||||
|
Date date = parserSDF.parse(joindate);
|
||||||
|
return date.before(new Calendar.Builder().setTimeZone(TimeZone.getTimeZone("UTC")).setDate(year, month, day)
|
||||||
|
.build().getTime());*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ConfirmUserMessage(ChatPlayer mp) {
|
||||||
|
Player p = Bukkit.getPlayer(mp.getUniqueId());
|
||||||
|
if (mp.FlairState.get().equals(FlairStates.Commented) && p != null)
|
||||||
|
if (mp.UserNames.get().size() > 1)
|
||||||
|
p.sendMessage(
|
||||||
|
"§9Multiple Reddit users commented your name. You can select with /u accept.§r §6Type /u accept or /u ignore§r");
|
||||||
|
else
|
||||||
|
p.sendMessage("§9A Reddit user commented your name. Is that you?§r §6Type /u accept or /u ignore§r");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package buttondevteam.chat;
|
package buttondevteam.chat.components.flair;
|
||||||
|
|
||||||
public enum FlairStates {
|
public enum FlairStates {
|
||||||
Accepted, Ignored, Recognised, Commented, NoComment
|
Accepted, Ignored, Recognised, Commented, NoComment
|
|
@ -0,0 +1,35 @@
|
||||||
|
package buttondevteam.chat.components.flair;
|
||||||
|
|
||||||
|
import buttondevteam.chat.ChatPlayer;
|
||||||
|
import buttondevteam.chat.commands.ucmds.UCommandBase;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
@CommandClass(modOnly = false, helpText = {
|
||||||
|
"Ignore flair",
|
||||||
|
"Stop the \"write your name in the thread\" message from showing up"
|
||||||
|
})
|
||||||
|
public final class IgnoreCommand extends UCommandBase {
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean def(Player player) {
|
||||||
|
ChatPlayer p = TBMCPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class);
|
||||||
|
if (p.FlairState.get().equals(FlairStates.Accepted)) {
|
||||||
|
player.sendMessage("§cYou can only ignore the \"write your name in the thread\" message.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (p.FlairState.get().equals(FlairStates.Commented)) {
|
||||||
|
player.sendMessage("Sorry, but your flair isn't recorded. Please ask a mod to set it for you.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!p.FlairState.get().equals(FlairStates.Ignored)) {
|
||||||
|
p.FlairState.set(FlairStates.Ignored);
|
||||||
|
p.SetFlair(ChatPlayer.FlairTimeNone);
|
||||||
|
p.UserName.set("");
|
||||||
|
player.sendMessage("§bYou have ignored the message.§r");
|
||||||
|
} else
|
||||||
|
player.sendMessage("§cYou already ignored the message.§r");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package buttondevteam.chat.components.flair;
|
||||||
|
|
||||||
|
import buttondevteam.chat.ChatPlayer;
|
||||||
|
import buttondevteam.chat.commands.ucmds.admin.AdminCommandBase;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
@CommandClass(helpText = {
|
||||||
|
"Set flair", "Set a flair for a player",
|
||||||
|
"Usage: /u admin setflair <player> <flairtime (or non-presser, cant-press, none)> <cheater(true/false)> [username]",
|
||||||
|
"Example 1: /u admin setflair NorbiPeti 19 false NorbiPeti --> orange (19s)",
|
||||||
|
"Example 2: /u admin setflair iie 0 true asde --> purple (0s)"
|
||||||
|
})
|
||||||
|
public class SetFlairCommand extends AdminCommandBase {
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean def(CommandSender sender, String player, String flairtime, boolean cheater, @Command2.OptionalArg String username) {
|
||||||
|
Player p = Bukkit.getPlayer(player);
|
||||||
|
if (p == null) {
|
||||||
|
sender.sendMessage("§cPlayer not found.&r");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
short ft;
|
||||||
|
if (flairtime.equalsIgnoreCase("non-presser"))
|
||||||
|
ft = ChatPlayer.FlairTimeNonPresser;
|
||||||
|
else if (flairtime.equalsIgnoreCase("cant-press"))
|
||||||
|
ft = ChatPlayer.FlairTimeCantPress;
|
||||||
|
else if (flairtime.equalsIgnoreCase("none"))
|
||||||
|
ft = ChatPlayer.FlairTimeNone;
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
ft = Short.parseShort(flairtime);
|
||||||
|
} catch (Exception e) {
|
||||||
|
sender.sendMessage(
|
||||||
|
"§cFlairtime must be a number, \"non-presser\", \"cant-press\" or \"none\". Run without args to see usage.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ChatPlayer mp = TBMCPlayerBase.getPlayer(p.getUniqueId(), ChatPlayer.class);
|
||||||
|
mp.SetFlair(ft, cheater);
|
||||||
|
mp.FlairState.set(FlairStates.Accepted);
|
||||||
|
if (username == null)
|
||||||
|
mp.UserName.set("");
|
||||||
|
else {
|
||||||
|
mp.UserName.set(username);
|
||||||
|
if (!mp.UserNames.get().contains(username))
|
||||||
|
mp.UserNames.get().add(username);
|
||||||
|
}
|
||||||
|
sender.sendMessage("§bThe flair has been set. Player: " + mp.getPlayerName() + " Flair: " + mp.GetFormattedFlair() + "§r");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,318 @@
|
||||||
|
package buttondevteam.chat.components.formatter;
|
||||||
|
|
||||||
|
import buttondevteam.chat.ChatPlayer;
|
||||||
|
import buttondevteam.chat.ChatUtils;
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.chat.VanillaUtils;
|
||||||
|
import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
|
||||||
|
import buttondevteam.chat.components.chatonly.ChatOnlyComponent;
|
||||||
|
import buttondevteam.chat.components.formatter.formatting.*;
|
||||||
|
import buttondevteam.chat.components.fun.FunComponent;
|
||||||
|
import buttondevteam.chat.components.towny.TownyComponent;
|
||||||
|
import buttondevteam.chat.listener.PlayerListener;
|
||||||
|
import buttondevteam.core.ComponentManager;
|
||||||
|
import buttondevteam.core.component.channel.Channel;
|
||||||
|
import buttondevteam.lib.ChromaUtils;
|
||||||
|
import buttondevteam.lib.TBMCChatEvent;
|
||||||
|
import buttondevteam.lib.TBMCChatEventBase;
|
||||||
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayer;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||||
|
import com.earth2me.essentials.User;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import lombok.val;
|
||||||
|
import net.ess3.api.events.AfkStatusChangeEvent;
|
||||||
|
import net.kyori.adventure.text.TextComponent;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.format.TextColor;
|
||||||
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import static net.kyori.adventure.text.Component.text;
|
||||||
|
import static net.kyori.adventure.text.event.ClickEvent.suggestCommand;
|
||||||
|
import static net.kyori.adventure.text.event.HoverEvent.Action.SHOW_TEXT;
|
||||||
|
import static net.kyori.adventure.text.event.HoverEvent.hoverEvent;
|
||||||
|
import static net.kyori.adventure.text.format.NamedTextColor.*;
|
||||||
|
|
||||||
|
public class ChatProcessing {
|
||||||
|
private static final Pattern HASHTAG_PATTERN = Pattern.compile("#(\\w+)");
|
||||||
|
private static final Pattern URL_PATTERN = Pattern.compile("(http[\\w:/?=$\\-_.+!*'(),&]+(?:#[\\w]+)?)");
|
||||||
|
private static final Pattern MASKED_LINK_PATTERN = Pattern.compile("\\[([^\\[\\]]+)]\\(([^()]+)\\)");
|
||||||
|
private static final NamedTextColor[] RainbowPresserColors = new NamedTextColor[]{RED, GOLD, YELLOW, GREEN,
|
||||||
|
BLUE, DARK_PURPLE};
|
||||||
|
private static final Pattern WORD_PATTERN = Pattern.compile("\\S+");
|
||||||
|
private static final Pattern GREENTEXT_PATTERN = Pattern.compile("^>(?:.|\\s)*");
|
||||||
|
private static boolean pingedconsole = false;
|
||||||
|
|
||||||
|
private static final ArrayList<MatchProviderBase> commonFormatters = Lists.newArrayList(
|
||||||
|
new RangeMatchProvider("bold", "**", FormatSettings.builder().bold(true).build()),
|
||||||
|
new RangeMatchProvider("italic", "*", FormatSettings.builder().italic(true).build()),
|
||||||
|
new RangeMatchProvider("underlined", "__", FormatSettings.builder().underlined(true).build()),
|
||||||
|
new RangeMatchProvider("italic2", "_", FormatSettings.builder().italic(true).build()),
|
||||||
|
new RangeMatchProvider("strikethrough", "~~", FormatSettings.builder().strikethrough(true).build()),
|
||||||
|
new RangeMatchProvider("spoiler", "||", FormatSettings.builder().obfuscated(true)
|
||||||
|
.onmatch((match, cf, fs) -> {
|
||||||
|
cf.setHoverText(match);
|
||||||
|
return match;
|
||||||
|
}).build()),
|
||||||
|
new StringMatchProvider("nullMention", FormatSettings.builder().color(DARK_RED).build(), true, "null"), // Properly added a bug as a feature
|
||||||
|
new StringMatchProvider("consolePing", FormatSettings.builder().color(AQUA)
|
||||||
|
.onmatch((match, builder, section) -> {
|
||||||
|
if (!pingedconsole) {
|
||||||
|
System.out.print("\007");
|
||||||
|
pingedconsole = true; // Will set it to false in ProcessChat
|
||||||
|
}
|
||||||
|
return "@console";
|
||||||
|
}).build(), true, "@console"),
|
||||||
|
|
||||||
|
new StringMatchProvider("cyan", FormatSettings.builder().color(AQUA).build(), true, "cyan"), // #55
|
||||||
|
new RangeMatchProvider("code", "`", FormatSettings.builder().color(DARK_GRAY).build()),
|
||||||
|
new RegexMatchProvider("maskedLink", MASKED_LINK_PATTERN, FormatSettings.builder().underlined(true)
|
||||||
|
.onmatch((match, builder, section) -> {
|
||||||
|
String text, link;
|
||||||
|
if (section.Matches.size() < 2 || (text = section.Matches.get(0)).length() == 0 || (link = section.Matches.get(1)).length() == 0)
|
||||||
|
return "[MISSING LINK]"; //Doesn't actually happen, because of the regex
|
||||||
|
builder.setOpenlink(link);
|
||||||
|
return text;
|
||||||
|
}).build()),
|
||||||
|
new RegexMatchProvider("url", URL_PATTERN, FormatSettings.builder().underlined(true).openlink("$1").build()),
|
||||||
|
new RegexMatchProvider("hashtag", HASHTAG_PATTERN, FormatSettings.builder().color(BLUE).openlink("https://twitter.com/hashtag/$1").build()),
|
||||||
|
new StringMatchProvider("someone", FormatSettings.builder().color(AQUA)
|
||||||
|
.onmatch((match, builder, section) -> {
|
||||||
|
if (Bukkit.getOnlinePlayers().size() == 0) return match;
|
||||||
|
var players = ImmutableList.copyOf(Bukkit.getOnlinePlayers());
|
||||||
|
var playerC = new Random().nextInt(players.size());
|
||||||
|
var player = players.get(playerC);
|
||||||
|
playPingSound(player, ComponentManager.getIfEnabled(FormatterComponent.class));
|
||||||
|
return "@someone (" + player.getDisplayName() + "§r)";
|
||||||
|
}).build(), true, "@someone"),
|
||||||
|
new RegexMatchProvider("greentext", GREENTEXT_PATTERN, FormatSettings.builder().color(GREEN).build()));
|
||||||
|
private static final String[] testPlayers = {"Koiiev", "iie", "Alisolarflare", "NorbiPeti", "Arsen_Derby_FTW", "carrot_lynx"};
|
||||||
|
|
||||||
|
private ChatProcessing() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean ProcessChat(TBMCChatEvent e, FormatterComponent component) {
|
||||||
|
Channel channel = e.getChannel();
|
||||||
|
ChromaGamerBase cuser = e.getUser();
|
||||||
|
String message = e.getMessage();
|
||||||
|
long processstart = System.nanoTime();
|
||||||
|
Player player = (cuser instanceof TBMCPlayerBase ? ((TBMCPlayerBase) cuser).getPlayer() : null);
|
||||||
|
User user = PluginMain.essentials.getUser(player);
|
||||||
|
|
||||||
|
if (player != null && PluginMain.essentials.getSettings().cancelAfkOnInteract()) {
|
||||||
|
user.updateActivity(true, AfkStatusChangeEvent.Cause.CHAT); //Could talk in a private channel, so broadcast
|
||||||
|
if (user.isMuted())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatPlayer mp;
|
||||||
|
if (player != null)
|
||||||
|
mp = TBMCPlayerBase.getPlayer(player.getUniqueId(), ChatPlayer.class);
|
||||||
|
else //Due to the online player map, getPlayer() can be more efficient than getAs()
|
||||||
|
mp = e.getUser().getAs(ChatPlayer.class); //May be null
|
||||||
|
|
||||||
|
if (mp != null) {
|
||||||
|
if (System.nanoTime() - mp.LastMessageTime < 1000L * 1000L * component.minTimeBetweenMessages.get()) { //0.1s by default
|
||||||
|
cuser.sendMessage("§cYou are sending messages too quickly!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
mp.LastMessageTime = System.nanoTime();
|
||||||
|
}
|
||||||
|
//DimensionManager.a()
|
||||||
|
//IRegistry.ae
|
||||||
|
//Bukkit.createWorld()
|
||||||
|
//MinecraftServer.reload()
|
||||||
|
//IRegistry
|
||||||
|
//CraftServer
|
||||||
|
|
||||||
|
doFunStuff(cuser, e, message);
|
||||||
|
|
||||||
|
final String channelidentifier = getChannelID(channel, e.getOrigin());
|
||||||
|
|
||||||
|
PluginMain.Instance.getServer().getConsoleSender()
|
||||||
|
.sendMessage(String.format("%s <%s§r> %s", channelidentifier, cuser.getName(), message));
|
||||||
|
|
||||||
|
if (Bukkit.getOnlinePlayers().size() == 0) return false; //Don't try to send to nobody (errors on 1.14)
|
||||||
|
|
||||||
|
TextColor colormode = NAMES.value(channel.color.get().getName());
|
||||||
|
boolean colorModeChanged = false;
|
||||||
|
if (mp != null && mp.OtherColorMode != null) {
|
||||||
|
colormode = NAMES.value(mp.OtherColorMode.getName());
|
||||||
|
colorModeChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<MatchProviderBase> formatters;
|
||||||
|
if (component.allowFormatting.get()) {
|
||||||
|
formatters = addFormatters(sender -> e.shouldSendTo(ChromaGamerBase.getFromSender(sender)), component);
|
||||||
|
if (colorModeChanged && mp.RainbowPresserColorMode) { // Only overwrite channel color
|
||||||
|
createRPC(colormode, formatters);
|
||||||
|
}
|
||||||
|
pingedconsole = false; // Will set it to true onmatch (static constructor)
|
||||||
|
} else
|
||||||
|
formatters = Lists.newArrayList();
|
||||||
|
|
||||||
|
TextComponent.Builder builder = createEmptyMessageLine(cuser, message, player, channelidentifier, e.getOrigin());
|
||||||
|
long combinetime = System.nanoTime();
|
||||||
|
ChatFormatter.Combine(formatters, message, builder, component.getConfig(), FormatSettings.builder().color(colormode).build());
|
||||||
|
combinetime = System.nanoTime() - combinetime;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!channel.isGlobal()) {
|
||||||
|
String senderGroup = e.getGroupID(cuser);
|
||||||
|
if (senderGroup == null) { // Never send messages if the group is null
|
||||||
|
cuser.sendMessage("§cYou don't have permission to send this message or something went wrong");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
val tc = ComponentManager.getIfEnabled(TownyComponent.class);
|
||||||
|
Consumer<Player> spyConsumer = null;
|
||||||
|
if (tc != null)
|
||||||
|
spyConsumer = tc.handleSpiesInit(channel, builder);
|
||||||
|
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||||
|
final String group;
|
||||||
|
if (player != null
|
||||||
|
&& PluginMain.essentials.getUser(p).isIgnoredPlayer(PluginMain.essentials.getUser(player)))
|
||||||
|
group = null; // Don't send the message to them
|
||||||
|
else
|
||||||
|
group = VanillaUtils.getGroupIfChatOn(p, e);
|
||||||
|
if (senderGroup.equals(group)) {
|
||||||
|
p.sendMessage(builder.build());
|
||||||
|
if (tc != null) spyConsumer.accept(p);
|
||||||
|
}
|
||||||
|
//Only sends if didn't send normally
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
for (Player p : Bukkit.getOnlinePlayers())
|
||||||
|
p.sendMessage(builder.build());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
TBMCCoreAPI.SendException("An error occured while sending a chat message!", ex, PluginMain.Instance);
|
||||||
|
cuser.sendMessage("§cAn error occured while sending the message.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
DebugCommand.SendDebugMessage(
|
||||||
|
"-- Full ChatProcessing time: " + (System.nanoTime() - processstart) / 1000000f + " ms");
|
||||||
|
DebugCommand.SendDebugMessage("-- ChatFormatter.Combine time: " + combinetime / 1000000f + " ms");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void createRPC(TextColor colormode, ArrayList<MatchProviderBase> formatters) {
|
||||||
|
final AtomicInteger rpc = new AtomicInteger(0);
|
||||||
|
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)]);
|
||||||
|
return match;
|
||||||
|
}).build()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextComponent.Builder createEmptyMessageLine(ChromaGamerBase user, String message, @Nullable Player player,
|
||||||
|
final String channelidentifier, String origin) {
|
||||||
|
val json = text();
|
||||||
|
ChatOnlyComponent.tellrawCreate(user.getAs(ChatPlayer.class), json);
|
||||||
|
val channelHover = (ChatUtils.MCORIGIN.equals(origin) ? "" : "From " + origin + "\n") + "Copy message";
|
||||||
|
json.append(text(channelidentifier)
|
||||||
|
.hoverEvent(hoverEvent(SHOW_TEXT, text(channelHover).color(BLUE))).clickEvent(suggestCommand(message)));
|
||||||
|
if (player != null) {
|
||||||
|
if (PluginMain.permission.has(player, "tbmc.badge.diamond")) // TODO: Cross-platform permissions
|
||||||
|
json.append(text("[P]").color(AQUA).decorate(TextDecoration.BOLD)
|
||||||
|
.hoverEvent(hoverEvent(SHOW_TEXT, text("Diamond Patreon supporter"))));
|
||||||
|
else if (PluginMain.permission.has(player, "tbmc.badge.gold"))
|
||||||
|
json.append(text("[P]").color(GOLD).decorate(TextDecoration.BOLD)
|
||||||
|
.hoverEvent(hoverEvent(SHOW_TEXT, text("Gold Patreon supporter"))));
|
||||||
|
}
|
||||||
|
json.append(text(" <"));
|
||||||
|
json.append(text(user.getName()).hoverEvent(hoverEvent(SHOW_TEXT, text(user.getInfo(ChromaGamerBase.InfoTarget.MCHover)))));
|
||||||
|
json.append(text("> "));
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getChannelID(Channel channel, String origin) {
|
||||||
|
return ("[" + (ChatUtils.MCORIGIN.equals(origin) ? "" : "§8" + origin.charAt(0) + "§r|") + channel.displayName.get())
|
||||||
|
+ "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
static ArrayList<MatchProviderBase> addFormatters(Predicate<Player> canSee, @Nullable FormatterComponent component) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
ArrayList<MatchProviderBase> formatters = (ArrayList<MatchProviderBase>) commonFormatters.clone();
|
||||||
|
|
||||||
|
boolean nottest; //Not assigning a default value, so that it can only be used in the if
|
||||||
|
if ((nottest = Bukkit.getOnlinePlayers().size() > 0) || ChromaUtils.isTest()) {
|
||||||
|
String[] names;
|
||||||
|
if (nottest)
|
||||||
|
names = Bukkit.getOnlinePlayers().stream().filter(canSee).map(CommandSender::getName).toArray(String[]::new);
|
||||||
|
else {
|
||||||
|
names = new String[testPlayers.length];
|
||||||
|
System.arraycopy(testPlayers, 0, names, 0, testPlayers.length);
|
||||||
|
}
|
||||||
|
String[] nicknames = Bukkit.getOnlinePlayers().stream().filter(canSee).map(Player::getUniqueId).map(PlayerListener.nicknames.inverse()::get)
|
||||||
|
.filter(Objects::nonNull).toArray(String[]::new);
|
||||||
|
|
||||||
|
Consumer<String> error = message -> {
|
||||||
|
if (PluginMain.Instance != null)
|
||||||
|
PluginMain.Instance.getLogger().warning(message);
|
||||||
|
else
|
||||||
|
System.out.println(message);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (names.length > 0) //Add as first so it handles special characters (_) - though the order of the different types are defined
|
||||||
|
formatters.add(0, new StringMatchProvider("name", FormatSettings.builder().color(AQUA)
|
||||||
|
.onmatch((match, builder, section) -> {
|
||||||
|
Player p = Bukkit.getPlayer(match);
|
||||||
|
Optional<String> pn = nottest ? Optional.empty()
|
||||||
|
: Arrays.stream(testPlayers).filter(tp -> tp.equalsIgnoreCase(match)).findAny();
|
||||||
|
if (nottest ? p == null : pn.isEmpty()) {
|
||||||
|
error.accept("Error: Can't find player " + match + " but was reported as online.");
|
||||||
|
return "§c" + match + "§r";
|
||||||
|
}
|
||||||
|
ChatPlayer mpp = TBMCPlayer.getPlayer(nottest ? p.getUniqueId() : new UUID(0, 0), ChatPlayer.class);
|
||||||
|
if (nottest) {
|
||||||
|
playPingSound(p, component);
|
||||||
|
}
|
||||||
|
String color = String.format("§%x", (mpp.GetFlairColor() == 0x00 ? 0xb : mpp.GetFlairColor()));
|
||||||
|
return color + (nottest ? p.getName() : pn.get()) + "§r"; //Fix name casing, except when testing
|
||||||
|
}).build(), true, names));
|
||||||
|
|
||||||
|
if (nicknames.length > 0) //Add as first so it handles special characters
|
||||||
|
formatters.add(0, new StringMatchProvider("nickname", FormatSettings.builder().color(AQUA)
|
||||||
|
.onmatch((match, builder, section) -> {
|
||||||
|
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()));
|
||||||
|
if (p == null) {
|
||||||
|
error.accept("Error: Can't find player nicknamed "
|
||||||
|
+ match.toLowerCase() + " but was reported as online.");
|
||||||
|
return "§c" + match + "§r";
|
||||||
|
}
|
||||||
|
playPingSound(p, component);
|
||||||
|
return PluginMain.essentials.getUser(p).getNickname();
|
||||||
|
}
|
||||||
|
error.accept("Player nicknamed " + match.toLowerCase()
|
||||||
|
+ " not found in nickname map but was reported as online.");
|
||||||
|
return "§c" + match + "§r";
|
||||||
|
}).build(), true, nicknames));
|
||||||
|
}
|
||||||
|
return formatters;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void playPingSound(Player p, @Nullable FormatterComponent component) {
|
||||||
|
if (component == null || component.notificationSound.get().length() == 0)
|
||||||
|
p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 0.5f); // TODO: Airhorn
|
||||||
|
else
|
||||||
|
p.playSound(p.getLocation(), component.notificationSound.get(), 1.0f,
|
||||||
|
component.notificationPitch.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void doFunStuff(ChromaGamerBase user, TBMCChatEventBase event, String message) {
|
||||||
|
val fc = ComponentManager.getIfEnabled(FunComponent.class);
|
||||||
|
if (fc != null) fc.onChat(user, event, message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package buttondevteam.chat.components.formatter;
|
||||||
|
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.core.ComponentManager;
|
||||||
|
import buttondevteam.core.MainPlugin;
|
||||||
|
import buttondevteam.lib.TBMCChatEvent;
|
||||||
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import buttondevteam.lib.architecture.config.IConfigData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component handles the custom processing of chat messages. If this component is disabled channels won't be supported in Minecraft.
|
||||||
|
* If you only want to disable the formatting features, set allowFormatting to false.
|
||||||
|
* If you're using another chat plugin, you should disable the whole component but that will make it impossible to use channels.
|
||||||
|
*/
|
||||||
|
public class FormatterComponent extends Component<PluginMain> {
|
||||||
|
/**
|
||||||
|
* Determines whether Markdown formatting, name mentioning and similar features are enabled.
|
||||||
|
*/
|
||||||
|
IConfigData<Boolean> allowFormatting = getConfig().getData("allowFormatting", true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sound to play when a player is mentioned. Leave empty to use default.
|
||||||
|
*/
|
||||||
|
public IConfigData<String> notificationSound = getConfig().getData("notificationSound", "");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The pitch of the notification sound.
|
||||||
|
*/
|
||||||
|
public IConfigData<Float> notificationPitch = getConfig().getData("notificationPitch", 1.0f);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum time between messages in milliseconds.
|
||||||
|
*/
|
||||||
|
public IConfigData<Integer> minTimeBetweenMessages = getConfig().getData("minTimeBetweenMessages", 100);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void enable() {
|
||||||
|
MainPlugin.getInstance().setChatHandlerEnabled(false); //Disable Core chat handler - if this component is disabled then let it do its job
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void disable() {
|
||||||
|
MainPlugin.getInstance().setChatHandlerEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the chat if the component is enabled.
|
||||||
|
*
|
||||||
|
* @param event The chat event
|
||||||
|
* @return Whether the chat message shouldn't be sent for some reason
|
||||||
|
*/
|
||||||
|
public static boolean handleChat(TBMCChatEvent event) {
|
||||||
|
FormatterComponent component = ComponentManager.getIfEnabled(FormatterComponent.class);
|
||||||
|
if (component == null) return false;
|
||||||
|
return ChatProcessing.ProcessChat(event, component);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,264 @@
|
||||||
|
package buttondevteam.chat.components.formatter.formatting;
|
||||||
|
|
||||||
|
import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
|
||||||
|
import buttondevteam.lib.architecture.IHaveConfig;
|
||||||
|
import lombok.val;
|
||||||
|
import net.kyori.adventure.text.TextComponent;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static net.kyori.adventure.text.Component.text;
|
||||||
|
import static net.kyori.adventure.text.event.ClickEvent.Action.OPEN_URL;
|
||||||
|
import static net.kyori.adventure.text.event.ClickEvent.clickEvent;
|
||||||
|
import static net.kyori.adventure.text.event.HoverEvent.Action.SHOW_TEXT;
|
||||||
|
import static net.kyori.adventure.text.event.HoverEvent.hoverEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link MatchProvider} finds where the given {@link FormatSettings} need to be applied. {@link ChatFormatter#Combine(List, String, TextComponent.Builder, IHaveConfig, FormatSettings)}} is used to turn it into a {@link TellrawPart}, combining
|
||||||
|
* intersecting parts found, for example when {@code _abc*def*ghi_} is said in chat, it'll turn it into an underlined part, then an underlined <i>and italics</i> part, finally an underlined part
|
||||||
|
* again.
|
||||||
|
*
|
||||||
|
* @author NorbiPeti
|
||||||
|
*/
|
||||||
|
public final class ChatFormatter {
|
||||||
|
private ChatFormatter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface TriFunc<T1, T2, T3, R> {
|
||||||
|
R apply(T1 x1, T2 x2, T3 x3);
|
||||||
|
}
|
||||||
|
|
||||||
|
//synchronized: Some of the formatters are reused, see createSections(...)
|
||||||
|
public static synchronized void Combine(List<MatchProviderBase> formatters, String str, TextComponent.Builder tp, IHaveConfig config, FormatSettings defaults) {
|
||||||
|
/*
|
||||||
|
* A global formatter is no longer needed
|
||||||
|
*/
|
||||||
|
header("ChatFormatter.Combine begin");
|
||||||
|
ArrayList<FormattedSection> sections = new ArrayList<>();
|
||||||
|
|
||||||
|
if (config != null) //null if testing
|
||||||
|
formatters.removeIf(cf -> !cf.enabled(config).get()); //Remove disabled formatters
|
||||||
|
var excluded = new ArrayList<int[]>();
|
||||||
|
/*
|
||||||
|
* 0: Start - 1: End index
|
||||||
|
*/
|
||||||
|
val remchars = new ArrayList<int[]>();
|
||||||
|
|
||||||
|
escapeThings(str, excluded, remchars);
|
||||||
|
|
||||||
|
sections.add(new FormattedSection(defaults, 0, str.length() - 1, Collections.emptyList())); //Add entire message
|
||||||
|
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");
|
||||||
|
combineSections(str, sections);
|
||||||
|
|
||||||
|
header("Section applying");
|
||||||
|
applySections(str, tp, sections, remchars);
|
||||||
|
header("ChatFormatter.Combine done");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void escapeThings(String str, ArrayList<int[]> ignoredAreas, ArrayList<int[]> remchars) {
|
||||||
|
boolean escaped = false;
|
||||||
|
for (int i = 0; i < str.length(); i++) {
|
||||||
|
if (str.charAt(i) == '\\') {
|
||||||
|
remchars.add(new int[]{i, i});
|
||||||
|
ignoredAreas.add(new int[]{i + 1, i + 1});
|
||||||
|
i++; //Ignore a potential second slash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createSections(List<MatchProviderBase> formatters, String str, ArrayList<FormattedSection> sections,
|
||||||
|
ArrayList<int[]> excludedAreas, ArrayList<int[]> removedCharacters) {
|
||||||
|
formatters.forEach(MatchProviderBase::reset); //Reset state information, as we aren't doing deep cloning
|
||||||
|
while (formatters.size() > 0) {
|
||||||
|
for (var iterator = formatters.iterator(); iterator.hasNext(); ) {
|
||||||
|
MatchProviderBase formatter = iterator.next();
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void combineSections(String str, ArrayList<FormattedSection> sections) {
|
||||||
|
for (int i = 1; i < sections.size(); i++) {
|
||||||
|
DebugCommand.SendDebugMessage("i: " + i);
|
||||||
|
final FormattedSection firstSection;
|
||||||
|
final FormattedSection lastSection;
|
||||||
|
{
|
||||||
|
FormattedSection firstSect = sections.get(i - 1);
|
||||||
|
FormattedSection lastSect = sections.get(i);
|
||||||
|
if (firstSect.Start > lastSect.Start //The first can't start later
|
||||||
|
|| (firstSect.Start == lastSect.Start && firstSect.End < lastSect.End)) {
|
||||||
|
var section = firstSect;
|
||||||
|
firstSect = lastSect;
|
||||||
|
lastSect = section;
|
||||||
|
}
|
||||||
|
firstSection = firstSect;
|
||||||
|
lastSection = lastSect;
|
||||||
|
}
|
||||||
|
DebugCommand.SendDebugMessage("Combining sections " + firstSection);
|
||||||
|
ChatFormatUtils.sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
||||||
|
DebugCommand.SendDebugMessage(" and " + lastSection);
|
||||||
|
ChatFormatUtils.sendMessageWithPointer(str, lastSection.Start, lastSection.End);
|
||||||
|
if (firstSection.Start == lastSection.Start && firstSection.End == lastSection.End) {
|
||||||
|
firstSection.Settings.copyFrom(lastSection.Settings);
|
||||||
|
firstSection.Matches.addAll(lastSection.Matches);
|
||||||
|
DebugCommand.SendDebugMessage("To section " + firstSection);
|
||||||
|
ChatFormatUtils.sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
||||||
|
sections.remove(i);
|
||||||
|
i = 0;
|
||||||
|
sortSections(sections);
|
||||||
|
continue;
|
||||||
|
} else if (firstSection.End >= lastSection.Start && firstSection.Start <= lastSection.End) {
|
||||||
|
int middleStart = lastSection.Start;
|
||||||
|
// |----|-- |------|
|
||||||
|
// --|----| -|----|-
|
||||||
|
int middleEnd = Math.min(lastSection.End, firstSection.End);
|
||||||
|
int lastSectEnd = Math.max(lastSection.End, firstSection.End);
|
||||||
|
FormattedSection section = new FormattedSection(firstSection.Settings, middleStart, middleEnd,
|
||||||
|
firstSection.Matches);
|
||||||
|
section.Settings.copyFrom(lastSection.Settings);
|
||||||
|
section.Matches.addAll(lastSection.Matches);
|
||||||
|
sections.add(i, section);
|
||||||
|
|
||||||
|
if (firstSection.End > lastSection.End) { //Copy first section info to last as the lastSection initially cuts the firstSection in half
|
||||||
|
lastSection.Settings = FormatSettings.builder().build();
|
||||||
|
lastSection.Settings.copyFrom(firstSection.Settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
firstSection.End = middleStart - 1;
|
||||||
|
lastSection.Start = middleEnd + 1;
|
||||||
|
lastSection.End = lastSectEnd;
|
||||||
|
|
||||||
|
Predicate<FormattedSection> removeIfNeeded = s -> {
|
||||||
|
if (s.Start < 0 || s.End < 0 || s.Start > s.End) {
|
||||||
|
DebugCommand.SendDebugMessage(" Removed: " + s);
|
||||||
|
ChatFormatUtils.sendMessageWithPointer(str, s.Start, s.End);
|
||||||
|
sections.remove(s);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
DebugCommand.SendDebugMessage("To sections");
|
||||||
|
if (!removeIfNeeded.test(firstSection)) {
|
||||||
|
DebugCommand.SendDebugMessage(" 1:" + firstSection);
|
||||||
|
ChatFormatUtils.sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
||||||
|
}
|
||||||
|
if (!removeIfNeeded.test(section)) {
|
||||||
|
DebugCommand.SendDebugMessage(" 2:" + section);
|
||||||
|
ChatFormatUtils.sendMessageWithPointer(str, section.Start, section.End);
|
||||||
|
}
|
||||||
|
if (!removeIfNeeded.test(lastSection)) {
|
||||||
|
DebugCommand.SendDebugMessage(" 3:" + lastSection);
|
||||||
|
ChatFormatUtils.sendMessageWithPointer(str, lastSection.Start, lastSection.End);
|
||||||
|
}
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
sortSections(sections);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applySections(String str, TextComponent.Builder tp, ArrayList<FormattedSection> sections, ArrayList<int[]> remchars) {
|
||||||
|
TextComponent lasttp = null;
|
||||||
|
String lastlink = null;
|
||||||
|
for (FormattedSection section : sections) {
|
||||||
|
DebugCommand.SendDebugMessage("Applying section: " + section);
|
||||||
|
String originaltext;
|
||||||
|
int start = section.Start, end = section.End;
|
||||||
|
DebugCommand.SendDebugMessage("Start: " + start + " - End: " + end);
|
||||||
|
ChatFormatUtils.sendMessageWithPointer(str, start, end);
|
||||||
|
val rci = remchars.stream().filter(rc -> (rc[0] <= start && rc[1] >= start)
|
||||||
|
|| (rc[0] >= start && rc[1] <= end)
|
||||||
|
|| (rc[0] <= end && rc[1] >= end)).sorted(Comparator.comparingInt(rc -> rc[0] * 10000 + rc[1])).toArray(int[][]::new);
|
||||||
|
DebugCommand.SendDebugMessage("Applying RC: " + Arrays.stream(rci).map(Arrays::toString).collect(Collectors.joining(", ", "[", "]")));
|
||||||
|
originaltext = str.substring(start, end + 1);
|
||||||
|
val sb = new StringBuilder(originaltext);
|
||||||
|
for (int x = rci.length - 1; x >= 0; x--)
|
||||||
|
sb.delete(Math.max(rci[x][0] - start, 0), Math.min(rci[x][1] - start, end) + 1); //Delete going backwards
|
||||||
|
originaltext = sb.toString();
|
||||||
|
if (originaltext.length() == 0) {
|
||||||
|
DebugCommand.SendDebugMessage("Skipping section because of remchars");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DebugCommand.SendDebugMessage("Section text: " + originaltext);
|
||||||
|
String openlink = null;
|
||||||
|
var settings = section.Settings;
|
||||||
|
DebugCommand.SendDebugMessage("Applying settings: " + settings);
|
||||||
|
if (lasttp != null && hasSameDecorations(lasttp, settings) && Objects.equals(lastlink, settings.openlink)
|
||||||
|
&& settings.onmatch == null) { // The onmatch function can change the settings
|
||||||
|
DebugCommand.SendDebugMessage("This part has the same properties as the previous one, combining.");
|
||||||
|
lasttp = lasttp.content(lasttp.content() + originaltext);
|
||||||
|
continue; //Combine parts with the same properties
|
||||||
|
}
|
||||||
|
TextComponent.@NotNull Builder newtp = text();
|
||||||
|
if (settings.onmatch != null)
|
||||||
|
originaltext = settings.onmatch.apply(originaltext, settings, section);
|
||||||
|
if (settings.color != null)
|
||||||
|
newtp.color(settings.color);
|
||||||
|
if (settings.bold)
|
||||||
|
newtp.decorate(TextDecoration.BOLD);
|
||||||
|
if (settings.italic)
|
||||||
|
newtp.decorate(TextDecoration.ITALIC);
|
||||||
|
if (settings.underlined)
|
||||||
|
newtp.decorate(TextDecoration.UNDERLINED);
|
||||||
|
if (settings.strikethrough)
|
||||||
|
newtp.decorate(TextDecoration.STRIKETHROUGH);
|
||||||
|
if (settings.obfuscated)
|
||||||
|
newtp.decorate(TextDecoration.OBFUSCATED);
|
||||||
|
if (settings.openlink != null)
|
||||||
|
openlink = settings.openlink;
|
||||||
|
if (settings.hoverText != null)
|
||||||
|
newtp.hoverEvent(hoverEvent(SHOW_TEXT, text(settings.hoverText)));
|
||||||
|
if (lasttp != null) tp.append(lasttp);
|
||||||
|
lastlink = openlink;
|
||||||
|
newtp.content(originaltext);
|
||||||
|
if (openlink != null && openlink.length() > 0) {
|
||||||
|
if (section.Matches.size() > 0)
|
||||||
|
openlink = openlink.replace("$1", section.Matches.get(0));
|
||||||
|
newtp.clickEvent(clickEvent(OPEN_URL, openlink)).hoverEvent(hoverEvent(SHOW_TEXT, text("Click to open").color(NamedTextColor.BLUE)));
|
||||||
|
}
|
||||||
|
lasttp = newtp.build();
|
||||||
|
}
|
||||||
|
if (lasttp != null) tp.append(lasttp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasSameDecorations(TextComponent c1, FormatSettings settings) {
|
||||||
|
return Objects.equals(c1.color(), settings.color)
|
||||||
|
&& c1.hasDecoration(TextDecoration.BOLD) == settings.bold
|
||||||
|
&& c1.hasDecoration(TextDecoration.ITALIC) == settings.italic
|
||||||
|
&& c1.hasDecoration(TextDecoration.UNDERLINED) == settings.underlined
|
||||||
|
&& c1.hasDecoration(TextDecoration.STRIKETHROUGH) == settings.strikethrough
|
||||||
|
&& c1.hasDecoration(TextDecoration.OBFUSCATED) == settings.obfuscated;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void sortSections(ArrayList<FormattedSection> sections) {
|
||||||
|
sections.sort(
|
||||||
|
(s1, s2) -> s1.Start == s2.Start
|
||||||
|
? s1.End == s2.End ? 0 : Integer.compare(s1.End, s2.End)
|
||||||
|
: Integer.compare(s1.Start, s2.Start));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void header(String message) {
|
||||||
|
DebugCommand.SendDebugMessage("\n--------\n" + message + "\n--------\n");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package buttondevteam.chat.components.formatter.formatting;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import net.kyori.adventure.text.format.TextColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes how a matched section of the message should look. May be combined with other format settings.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class FormatSettings {
|
||||||
|
boolean italic;
|
||||||
|
boolean bold;
|
||||||
|
boolean underlined;
|
||||||
|
boolean strikethrough;
|
||||||
|
boolean obfuscated;
|
||||||
|
TextColor 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) {
|
||||||
|
field.set(this, field.get(settings));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package buttondevteam.chat.components.formatter.formatting;
|
||||||
|
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ToString
|
||||||
|
public class FormattedSection {
|
||||||
|
public int Start;
|
||||||
|
public int End;
|
||||||
|
public FormatSettings Settings;
|
||||||
|
public List<String> Matches = new ArrayList<>();
|
||||||
|
|
||||||
|
FormattedSection(FormatSettings settings, int start, int end, List<String> matches) {
|
||||||
|
Start = start;
|
||||||
|
End = end;
|
||||||
|
Settings = FormatSettings.builder().build();
|
||||||
|
Settings.copyFrom(settings);
|
||||||
|
Matches.addAll(matches);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.IHaveConfig;
|
||||||
|
import buttondevteam.lib.architecture.config.IConfigData;
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
IConfigData<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 final 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,36 +1,33 @@
|
||||||
package buttondevteam.chat.formatting;
|
package buttondevteam.chat.components.formatter.formatting;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import buttondevteam.lib.chat.TellrawSerializableEnum;
|
import buttondevteam.lib.chat.TellrawSerializableEnum;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
public final class TellrawEvent<T extends TellrawEvent.Action> implements Serializable {
|
public final class TellrawEvent<T extends TellrawEvent.Action> implements Serializable {
|
||||||
private static final long serialVersionUID = -1681364161210561505L;
|
private static final long serialVersionUID = -1681364161210561505L;
|
||||||
private transient boolean hoverEvent;
|
private final transient boolean hoverEvent;
|
||||||
private T action;
|
private final T action;
|
||||||
private Object value;
|
private final Object value;
|
||||||
|
|
||||||
private TellrawEvent(Class<T> cl, T action, String value) {
|
private TellrawEvent(T action, String value) {
|
||||||
this.hoverEvent = HoverAction.class.equals(cl);
|
this.hoverEvent = action instanceof HoverAction;
|
||||||
this.action = action;
|
this.action = action;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TellrawEvent(Class<T> cl, T action, TellrawPart value) {
|
private TellrawEvent(T action, TellrawPart value) {
|
||||||
this.hoverEvent = HoverAction.class.equals(cl);
|
this.hoverEvent = action instanceof HoverAction;
|
||||||
this.action = action;
|
this.action = action;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Class<HoverAction> HoverAC = HoverAction.class;
|
public static <V extends TellrawEvent.Action> TellrawEvent<V> create(V action, String value) {
|
||||||
public static final Class<ClickAction> ClickAC = ClickAction.class;
|
return new TellrawEvent<>(action, value);
|
||||||
|
|
||||||
public static <V extends TellrawEvent.Action> TellrawEvent<V> create(Class<V> cl, V action, String value) {
|
|
||||||
return new TellrawEvent<>(cl, action, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V extends TellrawEvent.Action> TellrawEvent<V> create(Class<V> cl, V action, TellrawPart value) {
|
public static <V extends TellrawEvent.Action> TellrawEvent<V> create(V action, TellrawPart value) {
|
||||||
return new TellrawEvent<>(cl, action, value);
|
return new TellrawEvent<>(action, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isHoverEvent() {
|
public boolean isHoverEvent() {
|
||||||
|
@ -47,7 +44,7 @@ public final class TellrawEvent<T extends TellrawEvent.Action> implements Serial
|
||||||
|
|
||||||
public enum ClickAction implements Action {
|
public enum ClickAction implements Action {
|
||||||
OPEN_URL("open_url"), RUN_COMMAND("run_command"), SUGGEST_COMMAND("suggest_command");
|
OPEN_URL("open_url"), RUN_COMMAND("run_command"), SUGGEST_COMMAND("suggest_command");
|
||||||
private String action;
|
private final String action;
|
||||||
|
|
||||||
ClickAction(String action) {
|
ClickAction(String action) {
|
||||||
this.action = action;
|
this.action = action;
|
||||||
|
@ -62,7 +59,7 @@ public final class TellrawEvent<T extends TellrawEvent.Action> implements Serial
|
||||||
public enum HoverAction implements Action {
|
public enum HoverAction implements Action {
|
||||||
SHOW_TEXT("show_text"), SHOW_ITEM("show_item"), SHOW_ACHIEVEMENT("show_achievement"), SHOW_ENTITY(
|
SHOW_TEXT("show_text"), SHOW_ITEM("show_item"), SHOW_ACHIEVEMENT("show_achievement"), SHOW_ENTITY(
|
||||||
"show_entity");
|
"show_entity");
|
||||||
private String action;
|
private final String action;
|
||||||
|
|
||||||
HoverAction(String action) {
|
HoverAction(String action) {
|
||||||
this.action = action;
|
this.action = action;
|
||||||
|
@ -74,6 +71,6 @@ public final class TellrawEvent<T extends TellrawEvent.Action> implements Serial
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static interface Action extends TellrawSerializableEnum {
|
public interface Action extends TellrawSerializableEnum {
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,22 +1,20 @@
|
||||||
package buttondevteam.chat.formatting;
|
package buttondevteam.chat.components.formatter.formatting;
|
||||||
|
|
||||||
|
import buttondevteam.lib.chat.Color;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import buttondevteam.lib.chat.*;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public final class TellrawPart implements Serializable {
|
public final class TellrawPart implements Serializable {
|
||||||
private static final long serialVersionUID = 4125357644462144024L;
|
private static final long serialVersionUID = 4125357644462144024L;
|
||||||
private Color color;
|
private Color color;
|
||||||
private transient int format;
|
|
||||||
private boolean italic;
|
private boolean italic;
|
||||||
private boolean bold;
|
private boolean bold;
|
||||||
private boolean underlined;
|
private boolean underlined;
|
||||||
private boolean strikethrough;
|
private boolean strikethrough;
|
||||||
private boolean obfuscated;
|
private boolean obfuscated;
|
||||||
private List<TellrawPart> extra = new ArrayList<>();
|
private final List<TellrawPart> extra = new ArrayList<>();
|
||||||
private String text;
|
private String text;
|
||||||
private TellrawEvent<TellrawEvent.HoverAction> hoverEvent;
|
private TellrawEvent<TellrawEvent.HoverAction> hoverEvent;
|
||||||
private TellrawEvent<TellrawEvent.ClickAction> clickEvent;
|
private TellrawEvent<TellrawEvent.ClickAction> clickEvent;
|
||||||
|
@ -34,29 +32,48 @@ public final class TellrawPart implements Serializable {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getFormat() {
|
public boolean isItalic() {
|
||||||
return format;
|
return italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TellrawPart setFormat(int format) {
|
public TellrawPart setItalic(boolean italic) {
|
||||||
this.format = format;
|
this.italic = italic;
|
||||||
this.italic = false;
|
return this;
|
||||||
this.bold = false;
|
}
|
||||||
this.underlined = false;
|
|
||||||
this.strikethrough = false;
|
public boolean isBold() {
|
||||||
this.obfuscated = false;
|
return bold;
|
||||||
if ((format & Format.Italic.getFlag()) != 0)
|
}
|
||||||
this.italic = true;
|
|
||||||
else if ((format & Format.Bold.getFlag()) != 0)
|
public TellrawPart setBold(boolean bold) {
|
||||||
this.bold = true;
|
this.bold = bold;
|
||||||
else if ((format & Format.Underlined.getFlag()) != 0)
|
return this;
|
||||||
this.underlined = true;
|
}
|
||||||
else if ((format & Format.Strikethrough.getFlag()) != 0)
|
|
||||||
this.strikethrough = true;
|
public boolean isUnderlined() {
|
||||||
else if ((format & Format.Obfuscated.getFlag()) != 0)
|
return underlined;
|
||||||
this.obfuscated = true;
|
}
|
||||||
else
|
|
||||||
throw new UnsupportedOperationException("Trying to set to an unknown format!");
|
public TellrawPart setUnderlined(boolean underlined) {
|
||||||
|
this.underlined = underlined;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStrikethrough() {
|
||||||
|
return strikethrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TellrawPart setStrikethrough(boolean strikethrough) {
|
||||||
|
this.strikethrough = strikethrough;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isObfuscated() {
|
||||||
|
return obfuscated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TellrawPart setObfuscated(boolean obfuscated) {
|
||||||
|
this.obfuscated = obfuscated;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
package buttondevteam.chat.formatting;
|
package buttondevteam.chat.components.formatter.formatting;
|
||||||
|
|
||||||
|
import buttondevteam.lib.chat.TellrawSerializableEnum;
|
||||||
|
import com.google.gson.*;
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import com.google.gson.*;
|
|
||||||
import com.google.gson.stream.*;
|
|
||||||
|
|
||||||
import buttondevteam.lib.chat.TellrawSerializableEnum;
|
|
||||||
|
|
||||||
public abstract class TellrawSerializer {
|
public abstract class TellrawSerializer {
|
||||||
public static class TwEnum extends TypeAdapter<TellrawSerializableEnum> {
|
public static class TwEnum extends TypeAdapter<TellrawSerializableEnum> {
|
||||||
@Override
|
@Override
|
||||||
|
@ -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)
|
|
@ -0,0 +1,63 @@
|
||||||
|
package buttondevteam.chat.components.fun;
|
||||||
|
|
||||||
|
import buttondevteam.chat.ChatPlayer;
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.lib.chat.*;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@CommandClass(path = "u c", helpText = {
|
||||||
|
"Rainbow mode",
|
||||||
|
"This command allows you to talk in rainbow colors"
|
||||||
|
})
|
||||||
|
public class CCommand extends ICommand2MC {
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean def(Player player, @Command2.OptionalArg String color) {
|
||||||
|
ChatPlayer p = TBMCPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class);
|
||||||
|
if (color == null) {
|
||||||
|
if (PluginMain.permission.has(player, "chroma.color.rainbow")) {
|
||||||
|
p.RainbowPresserColorMode = !p.RainbowPresserColorMode;
|
||||||
|
p.OtherColorMode = null;
|
||||||
|
if (p.RainbowPresserColorMode)
|
||||||
|
player.sendMessage("§eRainbow colors §aenabled.");
|
||||||
|
else
|
||||||
|
player.sendMessage("§eRainbow colors §cdisabled.");
|
||||||
|
} else {
|
||||||
|
player.sendMessage("§cYou don't have permission for this command.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (PluginMain.permission.has(player, "chroma.color.custom")) {
|
||||||
|
String x = color.toLowerCase();
|
||||||
|
if ("off".equals(x)) {
|
||||||
|
p.OtherColorMode = null;
|
||||||
|
player.sendMessage("§eMessage color reset.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Optional<Color> oc = Arrays.stream(Color.values()).filter(c -> c.getName().equals(x)).findAny();
|
||||||
|
if (!oc.isPresent()) {
|
||||||
|
player.sendMessage("§cUnknown message color: " + color);
|
||||||
|
player.sendMessage("§cUse color names, like blue, or dark_aqua");
|
||||||
|
player.sendMessage("§cOr use 'off' to disable");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
p.RainbowPresserColorMode = false;
|
||||||
|
p.OtherColorMode = oc.get();
|
||||||
|
player.sendMessage(String.format("§eMessage color set to %s", p.OtherColorMode));
|
||||||
|
} else {
|
||||||
|
player.sendMessage("§cYou don't have permission for this command.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@CustomTabCompleteMethod(param = "color")
|
||||||
|
public Iterable<String> def() {
|
||||||
|
return Stream.concat(Stream.of("off"), Arrays.stream(Color.values()).map(Color::getName))::iterator;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package buttondevteam.chat.components.fun;
|
||||||
|
|
||||||
|
import buttondevteam.chat.ChatPlayer;
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||||
|
import lombok.val;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@CommandClass(helpText = {
|
||||||
|
"F Top", //
|
||||||
|
"Shows the respect leaderboard" //
|
||||||
|
})
|
||||||
|
public class FTopCommand extends ICommand2MC {
|
||||||
|
|
||||||
|
private final File playerdir = new File("TBMC/players/");
|
||||||
|
private ChatPlayer[] cached;
|
||||||
|
private long lastcache = 0;
|
||||||
|
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean def(CommandSender sender, @Command2.OptionalArg int page) {
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
|
||||||
|
if (cached == null || lastcache < System.nanoTime() - 60000000000L) { // 1m - (no guarantees of nanoTime's relation to 0, so we need the null check too)
|
||||||
|
cached = Arrays.stream(Objects.requireNonNull(playerdir.listFiles())).sequential()
|
||||||
|
.filter(f -> f.getName().length() > 4)
|
||||||
|
.map(f -> {
|
||||||
|
try {
|
||||||
|
return TBMCPlayerBase.getPlayer(
|
||||||
|
UUID.fromString(f.getName().substring(0, f.getName().length() - 4)), ChatPlayer.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.sorted((cp1, cp2) -> Double.compare(cp2.getF(), cp1.getF()))
|
||||||
|
.toArray(ChatPlayer[]::new); // TODO: Properly implement getting all players
|
||||||
|
lastcache = System.nanoTime();
|
||||||
|
}
|
||||||
|
int i;
|
||||||
|
try {
|
||||||
|
i = page < 1 ? 1 : page;
|
||||||
|
} catch (Exception e) {
|
||||||
|
i = 1;
|
||||||
|
}
|
||||||
|
val ai = new AtomicInteger();
|
||||||
|
sender.sendMessage("§6---- Top Fs ----");
|
||||||
|
sender.sendMessage(Arrays.stream(cached).skip((i - 1) * 10L).limit(i * 10L)
|
||||||
|
.map(cp -> String.format("%d. %s - %f.2", ai.incrementAndGet(), cp.getPlayerName(), cp.getF()))
|
||||||
|
.collect(Collectors.joining("\n")));
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,182 @@
|
||||||
|
package buttondevteam.chat.components.fun;
|
||||||
|
|
||||||
|
import buttondevteam.chat.ChatPlayer;
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.core.component.channel.Channel;
|
||||||
|
import buttondevteam.lib.TBMCChatEventBase;
|
||||||
|
import buttondevteam.lib.TBMCCommandPreprocessEvent;
|
||||||
|
import buttondevteam.lib.TBMCSystemChatEvent;
|
||||||
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import buttondevteam.lib.architecture.config.IConfigData;
|
||||||
|
import buttondevteam.lib.architecture.config.IListConfigData;
|
||||||
|
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||||
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayer;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import lombok.val;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
import org.bukkit.help.HelpTopic;
|
||||||
|
import org.bukkit.potion.PotionEffect;
|
||||||
|
import org.bukkit.potion.PotionEffectType;
|
||||||
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Random things I added over the years.
|
||||||
|
*/
|
||||||
|
public class FunComponent extends Component<PluginMain> implements Listener {
|
||||||
|
private boolean ActiveF = false;
|
||||||
|
private ChatPlayer FPlayer = null;
|
||||||
|
private BukkitTask Ftask = null;
|
||||||
|
private final HashSet<ChromaGamerBase> Fs = new HashSet<>();
|
||||||
|
private UnlolCommand command;
|
||||||
|
private TBMCSystemChatEvent.BroadcastTarget unlolTarget;
|
||||||
|
private TBMCSystemChatEvent.BroadcastTarget fTarget;
|
||||||
|
private final Random random = new Random();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The strings that count as laughs, see unlol.
|
||||||
|
*/
|
||||||
|
private final IListConfigData<String> laughStrings = getConfig().getListData("laughStrings", Lists.newArrayList("xd", "lel", "lawl", "kek", "lmao", "hue", "hah", "rofl"));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "Press F to pay respects" meme in Minecraft. It will randomly appear on player death and keep track of how many "F"s are said in chat.
|
||||||
|
* You can hover over a player's name to see their respect.
|
||||||
|
*/
|
||||||
|
private final IConfigData<Boolean> respect = getConfig().getData("respect", true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is an inside joke on our server.
|
||||||
|
* It keeps track of laughs (lols and what's defined in laughStrings) and if someone does /unlol or /unlaugh it will unlaugh the last person who laughed.
|
||||||
|
* Which also blinds the laughing person for a few seconds. This action can only be performed once per laugh.
|
||||||
|
*/
|
||||||
|
private final IConfigData<Boolean> unlol = getConfig().getData("unlol", true);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void enable() {
|
||||||
|
unlolTarget = TBMCSystemChatEvent.BroadcastTarget.add("unlol");
|
||||||
|
fTarget = TBMCSystemChatEvent.BroadcastTarget.add("respect");
|
||||||
|
val pc = new PressCommand();
|
||||||
|
registerCommand(pc);
|
||||||
|
registerListener(pc);
|
||||||
|
registerCommand(command = new UnlolCommand(unlolTarget));
|
||||||
|
registerListener(this);
|
||||||
|
registerCommand(new FTopCommand());
|
||||||
|
registerCommand(new OpmeCommand());
|
||||||
|
registerCommand(new YeehawCommand());
|
||||||
|
registerCommand(new CCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void disable() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onChat(ChromaGamerBase sender, TBMCChatEventBase event, String message) {
|
||||||
|
if (ActiveF && !Fs.contains(sender) && message.equalsIgnoreCase("F"))
|
||||||
|
Fs.add(sender);
|
||||||
|
|
||||||
|
if (unlol.get()) {
|
||||||
|
String msg = message.toLowerCase();
|
||||||
|
val lld = new UnlolCommand.LastlolData(sender, event, System.nanoTime());
|
||||||
|
boolean add = msg.contains("lol");
|
||||||
|
if (add)
|
||||||
|
lld.setLolornot(true);
|
||||||
|
else {
|
||||||
|
val laughs = laughStrings.get();
|
||||||
|
for (String laugh : laughs) {
|
||||||
|
add = msg.contains(laugh);
|
||||||
|
if (add) {
|
||||||
|
lld.setLolornot(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (add)
|
||||||
|
command.Lastlol.put(event.getChannel(), lld);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerDeath(PlayerDeathEvent e) {
|
||||||
|
// MinigamePlayer mgp = Minigames.plugin.pdata.getMinigamePlayer(e.getEntity());
|
||||||
|
if (e.getDeathMessage().length() > 0 && respect.get() && random.nextBoolean()) { // Don't store Fs for NPCs
|
||||||
|
Runnable tt = () -> {
|
||||||
|
if (ActiveF) {
|
||||||
|
ActiveF = false;
|
||||||
|
if (FPlayer != null && FPlayer.FCount.get() < Integer.MAX_VALUE - 1)
|
||||||
|
FPlayer.FCount.set(FPlayer.FCount.get() + Fs.size());
|
||||||
|
TBMCChatAPI.SendSystemMessage(Channel.globalChat, Channel.RecipientTestResult.ALL,
|
||||||
|
"§b" + Fs.size() + " " + (Fs.size() == 1 ? "person" : "people")
|
||||||
|
+ " paid their respects.§r", fTarget);
|
||||||
|
Fs.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (Ftask != null) {
|
||||||
|
Ftask.cancel();
|
||||||
|
tt.run(); //Finish previous one
|
||||||
|
}
|
||||||
|
ActiveF = true;
|
||||||
|
Fs.clear();
|
||||||
|
FPlayer = TBMCPlayer.getPlayer(e.getEntity().getUniqueId(), ChatPlayer.class);
|
||||||
|
FPlayer.FDeaths.set(FPlayer.FDeaths.get() + 1);
|
||||||
|
TBMCChatAPI.SendSystemMessage(Channel.globalChat, Channel.RecipientTestResult.ALL,
|
||||||
|
"§bPress F to pay respects.§r", fTarget);
|
||||||
|
Ftask = Bukkit.getScheduler().runTaskLaterAsynchronously(PluginMain.Instance, tt, 15 * 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerLeave(PlayerQuitEvent event) {
|
||||||
|
if (unlol.get())
|
||||||
|
command.Lastlol.values().removeIf(lld -> lld.getLolowner().equals(ChromaGamerBase.getFromSender(event.getPlayer())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
|
public void onCommandPreprocess(TBMCCommandPreprocessEvent event) {
|
||||||
|
if (event.isCancelled()) return;
|
||||||
|
if (!unlol.get()) return;
|
||||||
|
final String cmd = event.getMessage();
|
||||||
|
// We don't care if we have arguments
|
||||||
|
if (cmd.toLowerCase().startsWith("/un")) {
|
||||||
|
for (HelpTopic ht : PluginMain.Instance.getServer().getHelpMap().getHelpTopics()) {
|
||||||
|
if (ht.getName().equalsIgnoreCase(cmd))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
val user = event.getSender();
|
||||||
|
if (!(user instanceof TBMCPlayerBase)) {
|
||||||
|
// TODO: Cross-platform permission check; console is not supported here
|
||||||
|
user.sendMessage("§cError: You must be a player to use this command.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
val player = ((TBMCPlayerBase) user).getPlayer();
|
||||||
|
if (player != null && PluginMain.permission.has(player, "chroma.unanything")) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
int index = cmd.lastIndexOf(' ');
|
||||||
|
if (index == -1) {
|
||||||
|
event.getSender().sendMessage("§cUsage: " + cmd + " <player>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String s = cmd.substring(3, index);
|
||||||
|
Player target = Bukkit.getPlayer(cmd.substring(index + 1));
|
||||||
|
if (target == null) {
|
||||||
|
event.getSender().sendMessage("§cError: Player not found. (/un" + s + " <player>)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 10 * 20, 5, false, false));
|
||||||
|
val chan = user.getChannel().get();
|
||||||
|
TBMCChatAPI.SendSystemMessage(chan, chan.getRTR(event.getSender()), event.getSender().getName() + " un" + s
|
||||||
|
+ "'d " + target.getDisplayName(), unlolTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package buttondevteam.chat.components.fun;
|
||||||
|
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
@CommandClass(modOnly = false, path = "u opme", helpText = {
|
||||||
|
"OP me",
|
||||||
|
"Totally makes you OP"
|
||||||
|
})
|
||||||
|
public class OpmeCommand extends ICommand2MC {
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean def(CommandSender sender) {
|
||||||
|
sender.sendMessage("It would be nice, wouldn't it?");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package buttondevteam.chat.components.fun;
|
||||||
|
|
||||||
|
import buttondevteam.core.component.channel.Channel;
|
||||||
|
import buttondevteam.core.component.restart.RestartComponent;
|
||||||
|
import buttondevteam.core.component.restart.ScheduledRestartCommand;
|
||||||
|
import buttondevteam.lib.ChromaUtils;
|
||||||
|
import buttondevteam.lib.ScheduledServerRestartEvent;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
|
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
@CommandClass(helpText = {
|
||||||
|
"Press",
|
||||||
|
"This command resets the restart countdown if it's active. Can only be used once per player.",
|
||||||
|
"It's based on Reddit's /r/thebutton"
|
||||||
|
})
|
||||||
|
public class PressCommand extends ICommand2MC implements Listener {
|
||||||
|
private HashSet<CommandSender> pressers; //Will be cleared with this class on shutdown/disable
|
||||||
|
private ScheduledRestartCommand command;
|
||||||
|
private int startTicks;
|
||||||
|
|
||||||
|
@Command2.Subcommand
|
||||||
|
public void def(CommandSender sender) {
|
||||||
|
if (command == null) {
|
||||||
|
sender.sendMessage("§cThe timer isn't ticking... yet.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pressers.contains(sender)) {
|
||||||
|
sender.sendMessage("§cYou cannot press more than once.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pressers.add(sender);
|
||||||
|
TBMCChatAPI.SendSystemMessage(Channel.globalChat, Channel.RecipientTestResult.ALL, String.format("§b-- %s §bpressed at %.0fs", ChromaUtils.getDisplayName(sender), command.getRestartCounter() / 20f), ((RestartComponent) command.getComponent()).getRestartBroadcast());
|
||||||
|
command.setRestartCounter(startTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void restartEvent(ScheduledServerRestartEvent event) {
|
||||||
|
command = event.getCommand();
|
||||||
|
pressers = new HashSet<>();
|
||||||
|
startTicks = event.getRestartTicks();
|
||||||
|
if (Bukkit.getOnlinePlayers().size() > 0)
|
||||||
|
TBMCChatAPI.SendSystemMessage(Channel.globalChat, Channel.RecipientTestResult.ALL, "§b-- Do /press to reset the timer. You may only press once.", ((RestartComponent) command.getComponent()).getRestartBroadcast());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package buttondevteam.chat.components.fun;
|
||||||
|
|
||||||
|
import buttondevteam.core.component.channel.Channel;
|
||||||
|
import buttondevteam.lib.TBMCChatEventBase;
|
||||||
|
import buttondevteam.lib.TBMCSystemChatEvent;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
|
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||||
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.bukkit.potion.PotionEffect;
|
||||||
|
import org.bukkit.potion.PotionEffectType;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@CommandClass(modOnly = false, helpText = {
|
||||||
|
"Unlol/unlaugh",
|
||||||
|
"This command is based on an inside joke",
|
||||||
|
"It will make the last person saying one of the recognized laugh strings blind for a few seconds",
|
||||||
|
"Note that you can only unlaugh laughs that weren't unlaughed before"
|
||||||
|
})
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public final class UnlolCommand extends ICommand2MC {
|
||||||
|
|
||||||
|
public Map<Channel, LastlolData> Lastlol = new HashMap<>();
|
||||||
|
|
||||||
|
private final TBMCSystemChatEvent.BroadcastTarget target;
|
||||||
|
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean def(ChromaGamerBase sender) {
|
||||||
|
LastlolData lol = Lastlol.values().stream().filter(lld -> lld.Chatevent.shouldSendTo(sender))
|
||||||
|
.max(Comparator.comparingLong(lld -> lld.Loltime)).orElse(null);
|
||||||
|
if (lol == null)
|
||||||
|
return true;
|
||||||
|
if (lol.Lolowner instanceof TBMCPlayerBase) {
|
||||||
|
var player = ((TBMCPlayerBase) lol.Lolowner).getPlayer();
|
||||||
|
if (player != null)
|
||||||
|
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 2 * 20, 5, false, false));
|
||||||
|
}
|
||||||
|
String msg = sender.getName() + (lol.Lolornot ? " unlolled " : " unlaughed ") + lol.Lolowner.getName();
|
||||||
|
TBMCChatAPI.SendSystemMessage(Channel.globalChat, Channel.RecipientTestResult.ALL, msg, target);
|
||||||
|
Lastlol.remove(lol.Chatevent.getChannel());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class LastlolData {
|
||||||
|
private boolean Lolornot;
|
||||||
|
private final ChromaGamerBase Lolowner;
|
||||||
|
private final TBMCChatEventBase Chatevent;
|
||||||
|
private final long Loltime;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package buttondevteam.chat.components.fun;
|
||||||
|
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.ICommand2MC;
|
||||||
|
import buttondevteam.lib.player.TBMCYEEHAWEvent;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
@CommandClass(modOnly = false, helpText = {
|
||||||
|
"YEEHAW command",
|
||||||
|
"This command makes you YEEHAW."
|
||||||
|
})
|
||||||
|
public class YeehawCommand extends ICommand2MC {
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean def(CommandSender sender) {
|
||||||
|
final String message = "§b* "
|
||||||
|
+ (sender instanceof Player ? ((Player) sender).getDisplayName() : sender.getName()) + " §bYEEHAWs.";
|
||||||
|
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||||
|
p.playSound(p.getLocation(), "tbmc.yeehaw", 1f, 1f);
|
||||||
|
p.sendMessage(message); //Not broadcasting, so the Discord plugin can handle the event in a special way
|
||||||
|
} // Even a cmdblock could yeehaw in theory
|
||||||
|
// Or anyone from Discord
|
||||||
|
Bukkit.getPluginManager().callEvent(new TBMCYEEHAWEvent(sender));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package buttondevteam.chat.components.towncolors;
|
||||||
|
|
||||||
|
import buttondevteam.chat.ChatPlayer;
|
||||||
|
import buttondevteam.chat.commands.ucmds.UCommandBase;
|
||||||
|
import buttondevteam.chat.components.towny.TownyComponent;
|
||||||
|
import buttondevteam.lib.chat.Color;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import com.palmergames.bukkit.towny.object.Resident;
|
||||||
|
import com.palmergames.bukkit.towny.object.Town;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@CommandClass(helpText = {
|
||||||
|
"Name color", //
|
||||||
|
"This command allows you to set how the town colors look on your name.", //
|
||||||
|
"To use this command, you need to be in a town which has town colors set.", //
|
||||||
|
"Use a vertical line (or a colon) as a separator between the colors.", //
|
||||||
|
"Example: /u ncolor Norbi|Peti --> §6Norbi§ePeti" //
|
||||||
|
})
|
||||||
|
public class NColorCommand extends UCommandBase {
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean def(Player player, String nameWithLines) {
|
||||||
|
Resident res;
|
||||||
|
Town town;
|
||||||
|
try {
|
||||||
|
if ((res = TownyComponent.dataSource.getResident(player.getName())) == null || !res.hasTown()
|
||||||
|
|| (town = res.getTown()) == null) {
|
||||||
|
player.sendMessage("§cYou need to be in a town.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
player.sendMessage("§cYou need to be in a town. (" + e + ")");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
final String name = ChatColor.stripColor(player.getDisplayName()).replace("~", ""); //Remove ~
|
||||||
|
//Don't add ~ for nicknames
|
||||||
|
if (!nameWithLines.replace("|", "").replace(":", "").equalsIgnoreCase(name)) {
|
||||||
|
player.sendMessage("§cThe name you gave doesn't match your name. Make sure to use "
|
||||||
|
+ name + "§c with added vertical lines (|) or colons (:).");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
String[] nameparts = nameWithLines.split("[|:]");
|
||||||
|
Color[] towncolors = TownColorComponent.TownColors.get(town.getName().toLowerCase());
|
||||||
|
if (towncolors == null) {
|
||||||
|
player.sendMessage("§cYour town doesn't have a color set. The town mayor can set it using /u towncolor.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var component = TownColorComponent.getComponent();
|
||||||
|
byte nationColors = (byte) (component.useNationColors.get() ? 1 : 0);
|
||||||
|
if (nameparts.length < towncolors.length + nationColors) { //+1: Nation color
|
||||||
|
player.sendMessage("§cYou need more vertical lines (|) or colons (:) in your name. (Should have " + (towncolors.length - 1 + 1) + ")"); //Nation color
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (nameparts.length > (towncolors.length + nationColors) * 2) {
|
||||||
|
player.sendMessage("§cYou have waay too many vertical lines (|) or colons (:) in your name. (Should have " + (towncolors.length - 1 + 1) + ")");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (nameparts.length > towncolors.length + nationColors) {
|
||||||
|
player.sendMessage("§cYou have too many vertical lines (|) or colons (:) in your name. (Should have " + (towncolors.length - 1 + 1) + ")");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var cp = ChatPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class);
|
||||||
|
var list = Arrays.stream(nameparts).map(String::length).collect(Collectors.toList());
|
||||||
|
if (list.contains(0)) {
|
||||||
|
player.sendMessage("§cAll colors need to be represented in your name. (Use as Test|name|123 instead of |Testname123|)");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var clist = cp.NameColorLocations.get(); // No byte[], no TIntArrayList
|
||||||
|
clist.clear();
|
||||||
|
clist.addAll(list);
|
||||||
|
TownColorComponent.updatePlayerColors(player, cp);
|
||||||
|
player.sendMessage("§bName colors set: " + player.getDisplayName());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package buttondevteam.chat.components.towncolors;
|
||||||
|
|
||||||
|
import buttondevteam.chat.commands.ucmds.UCommandBase;
|
||||||
|
import buttondevteam.chat.components.towncolors.admin.TownColorCommand;
|
||||||
|
import buttondevteam.chat.components.towny.TownyComponent;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.CustomTabCompleteMethod;
|
||||||
|
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException;
|
||||||
|
import com.palmergames.bukkit.towny.object.Nation;
|
||||||
|
import com.palmergames.bukkit.towny.object.Resident;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
@CommandClass(helpText = {
|
||||||
|
"Nation Color", //
|
||||||
|
"This command allows setting a color for a nation.", //
|
||||||
|
"Each town in the nation will have it's first color (border) set to this color.", //
|
||||||
|
"See the help text for /u towncolor for more details.", //
|
||||||
|
})
|
||||||
|
public class NationColorCommand extends UCommandBase {
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean def(Player player, String color) {
|
||||||
|
String msg = "§cYou need to be the king of a nation to set it's colors.";
|
||||||
|
try {
|
||||||
|
Resident res = TownyComponent.dataSource.getResident(player.getName());
|
||||||
|
if (!res.isKing()) {
|
||||||
|
player.sendMessage(msg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
final Nation n = res.getTown().getNation();
|
||||||
|
return buttondevteam.chat.components.towncolors.admin.NationColorCommand.SetNationColor(player, n, color);
|
||||||
|
} catch (NotRegisteredException e) {
|
||||||
|
player.sendMessage(msg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@CustomTabCompleteMethod(param = "color")
|
||||||
|
public Iterable<String> def() {
|
||||||
|
return TownColorCommand.tabcompleteColor();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package buttondevteam.chat.components.towncolors;
|
||||||
|
|
||||||
|
import buttondevteam.chat.commands.ucmds.UCommandBase;
|
||||||
|
import buttondevteam.chat.components.towny.TownyComponent;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.CustomTabCompleteMethod;
|
||||||
|
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException;
|
||||||
|
import com.palmergames.bukkit.towny.object.Resident;
|
||||||
|
import com.palmergames.bukkit.towny.object.Town;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.val;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
@CommandClass(helpText = {
|
||||||
|
"Town Color", //
|
||||||
|
"This command allows setting a color for a town.", //
|
||||||
|
"The town will be shown with this color on Dynmap and all players in the town will appear in chat with these colors.", //
|
||||||
|
"The colors will split the name evenly but residents can override that with /u ncolor.", //
|
||||||
|
})
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TownColorCommand extends UCommandBase {
|
||||||
|
private final TownColorComponent component;
|
||||||
|
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean def(Player player, String... colornames) {
|
||||||
|
String msg = "§cYou need to be the mayor of a town to set its colors.";
|
||||||
|
try {
|
||||||
|
Resident res = TownyComponent.dataSource.getResident(player.getName());
|
||||||
|
if (!res.isMayor()) {
|
||||||
|
player.sendMessage(msg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
val cc = component.colorCount.get();
|
||||||
|
if (colornames.length > cc) {
|
||||||
|
player.sendMessage("You can only use " + cc + " color" + (cc > 1 ? "s" : "") + ".");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
final Town t = res.getTown();
|
||||||
|
return buttondevteam.chat.components.towncolors.admin.TownColorCommand.SetTownColor(player, t, colornames);
|
||||||
|
} catch (NotRegisteredException e) {
|
||||||
|
player.sendMessage(msg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@CustomTabCompleteMethod(param = "colornames")
|
||||||
|
public Iterable<String> def() {
|
||||||
|
return buttondevteam.chat.components.towncolors.admin.TownColorCommand.tabcompleteColor();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,224 @@
|
||||||
|
package buttondevteam.chat.components.towncolors;
|
||||||
|
|
||||||
|
import buttondevteam.chat.ChatPlayer;
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.chat.components.towncolors.admin.TCCount;
|
||||||
|
import buttondevteam.chat.components.towny.TownyComponent;
|
||||||
|
import buttondevteam.core.ComponentManager;
|
||||||
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import buttondevteam.lib.architecture.ComponentMetadata;
|
||||||
|
import buttondevteam.lib.architecture.config.IConfigData;
|
||||||
|
import buttondevteam.lib.chat.Color;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayer;
|
||||||
|
import com.earth2me.essentials.User;
|
||||||
|
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException;
|
||||||
|
import com.palmergames.bukkit.towny.object.Nation;
|
||||||
|
import com.palmergames.bukkit.towny.object.Resident;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.val;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.dynmap.towny.DTBridge;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Town colors for Towny. It allows mayors and kings to set a color for their town/nation (nation can be disabled).
|
||||||
|
* This color is applied to the player names in chat and on Dynmap, if used.
|
||||||
|
*/
|
||||||
|
@ComponentMetadata(depends = TownyComponent.class)
|
||||||
|
public class TownColorComponent extends Component<PluginMain> implements Listener {
|
||||||
|
/**
|
||||||
|
* Names lowercased
|
||||||
|
*/
|
||||||
|
public static final Map<String, Color[]> TownColors = new HashMap<>();
|
||||||
|
/**
|
||||||
|
* Names lowercased - nation color gets added to town colors when needed
|
||||||
|
*/
|
||||||
|
public static final Map<String, Color> NationColor = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount of town colors allowed. If more than one is used (or nation colors are enabled), players can change how many letters to be in a specific color using /u ncolor.
|
||||||
|
*/
|
||||||
|
public final IConfigData<Byte> colorCount = getConfig().getData("colorCount", (byte) 1, cc -> ((Integer) cc).byteValue(), Byte::intValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If enabled, players will have a nation-defined color in addition to town colors, white by default.
|
||||||
|
* They can change how much of each color they want with this as well.
|
||||||
|
*/
|
||||||
|
public final IConfigData<Boolean> useNationColors = getConfig().getData("useNationColors", true);
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static TownColorComponent component;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
protected void enable() {
|
||||||
|
component = this;
|
||||||
|
Consumer<ConfigurationSection> loadTC = cs -> TownColorComponent.TownColors.putAll(cs.getValues(true).entrySet().stream()
|
||||||
|
.collect(Collectors.toMap(Map.Entry::getKey, v -> ((List<String>) v.getValue()).stream()
|
||||||
|
.map(Color::valueOf).toArray(Color[]::new))));
|
||||||
|
boolean usenc = useNationColors.get();
|
||||||
|
Consumer<ConfigurationSection> loadNC = ncs ->
|
||||||
|
TownColorComponent.NationColor.putAll(ncs.getValues(true).entrySet().stream()
|
||||||
|
.collect(Collectors.toMap(Map.Entry::getKey, v -> Color.valueOf((String) v.getValue()))));
|
||||||
|
var cs = getConfig().getConfig().getConfigurationSection("towncolors");
|
||||||
|
if (cs != null)
|
||||||
|
loadTC.accept(cs);
|
||||||
|
if (usenc) {
|
||||||
|
var ncs = getConfig().getConfig().getConfigurationSection("nationcolors");
|
||||||
|
if (ncs != null)
|
||||||
|
loadNC.accept(ncs);
|
||||||
|
}
|
||||||
|
|
||||||
|
TownColors.keySet().removeIf(t -> TownyComponent.dataSource.getTown(t) == null); // Removes town colors for deleted/renamed towns
|
||||||
|
if (usenc)
|
||||||
|
NationColor.keySet().removeIf(n -> TownyComponent.dataSource.getNation(n) == null); // Removes nation colors for deleted/renamed nations
|
||||||
|
|
||||||
|
initDynmap();
|
||||||
|
|
||||||
|
registerCommand(new TownColorCommand(this));
|
||||||
|
if (useNationColors.get())
|
||||||
|
registerCommand(new NationColorCommand());
|
||||||
|
registerCommand(new buttondevteam.chat.components.towncolors.admin.TownColorCommand());
|
||||||
|
if (useNationColors.get())
|
||||||
|
registerCommand(new buttondevteam.chat.components.towncolors.admin.NationColorCommand());
|
||||||
|
registerCommand(new TCCount());
|
||||||
|
registerCommand(new NColorCommand());
|
||||||
|
registerListener(new TownyListener());
|
||||||
|
registerListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void disable() {
|
||||||
|
getConfig().getConfig().createSection("towncolors", TownColors.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
|
||||||
|
v -> Arrays.stream(v.getValue()).map(Enum::toString).toArray(String[]::new))));
|
||||||
|
if (useNationColors.get())
|
||||||
|
getConfig().getConfig().createSection("nationcolors", NationColor.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
|
||||||
|
v -> v.getValue().toString())));
|
||||||
|
getConfig().signalChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initDynmap() {
|
||||||
|
Bukkit.getScheduler().runTask(getPlugin(), () -> {
|
||||||
|
val dtp = Bukkit.getPluginManager().getPlugin("Dynmap-Towny");
|
||||||
|
if (dtp == null)
|
||||||
|
return;
|
||||||
|
for (val entry : TownColors.entrySet()) {
|
||||||
|
try {
|
||||||
|
val town = TownyComponent.dataSource.getTown(entry.getKey());
|
||||||
|
Nation nation;
|
||||||
|
Color nc;
|
||||||
|
if (!useNationColors.get())
|
||||||
|
nc = null;
|
||||||
|
else if (!town.hasNation() || (nation = town.getNation()) == null || (nc = NationColor.get(nation.getName().toLowerCase())) == null)
|
||||||
|
nc = Color.White;
|
||||||
|
setTownColor(dtp, buttondevteam.chat.components.towncolors.admin.TownColorCommand.getTownNameCased(entry.getKey()), entry.getValue(), nc);
|
||||||
|
} catch (Exception e) {
|
||||||
|
TBMCCoreAPI.SendException("Error while setting town color for town " + entry.getKey() + "!", e, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a town's color on Dynmap.
|
||||||
|
*
|
||||||
|
* @param dtp A reference for the Dynmap-Towny plugin
|
||||||
|
* @param town The town's name using the correct casing
|
||||||
|
* @param colors The town's colors
|
||||||
|
*/
|
||||||
|
public static void setTownColor(Plugin dtp, String town, Color[] colors, Color nationcolor) {
|
||||||
|
Function<Color, Integer> c2i = c -> c.getRed() << 16 | c.getGreen() << 8 | c.getBlue();
|
||||||
|
try {
|
||||||
|
DTBridge.setTownColor(dtp, town, c2i.apply(nationcolor == null ? colors[0] : nationcolor),
|
||||||
|
c2i.apply(colors.length > 1 && nationcolor != null ? colors[1] : colors[0]));
|
||||||
|
} catch (Exception e) {
|
||||||
|
TBMCCoreAPI.SendException("Failed to set town color for town " + town + "!", e, component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getPlayerNickname(Player player, User user, ChatPlayer cp) {
|
||||||
|
String nickname = user.getNick(true);
|
||||||
|
if (nickname.contains("~")) //StartsWith doesn't work because of color codes
|
||||||
|
nickname = nickname.replace("~", ""); //It gets stacked otherwise
|
||||||
|
String name = ChatColor.stripColor(nickname); //Enforce "town colors" on non-members
|
||||||
|
Resident res = TownyComponent.dataSource.getResident(player.getName());
|
||||||
|
if (res == null || !res.hasTown())
|
||||||
|
return name;
|
||||||
|
try {
|
||||||
|
Color[] clrs = Optional.ofNullable(
|
||||||
|
TownColors.get(res.getTown().getName().toLowerCase())
|
||||||
|
).orElse(new Color[]{Color.White}); //Use white as default town color
|
||||||
|
StringBuilder ret = new StringBuilder();
|
||||||
|
AtomicInteger prevlen = new AtomicInteger();
|
||||||
|
BiFunction<Color, Integer, String> anyColoredNamePart = (c, len) -> "§" //Len==0 if last part
|
||||||
|
+ Integer.toHexString(c.ordinal()) // 'Odds' are the last character is chopped off so we make sure to include all chars at the end
|
||||||
|
+ (len == 0 ? name.substring(prevlen.get())
|
||||||
|
: name.substring(prevlen.get(), prevlen.addAndGet(len)));
|
||||||
|
BiFunction<Integer, Integer, String> coloredNamePart = (len, i)
|
||||||
|
-> anyColoredNamePart.apply(clrs[i], i + 1 == clrs.length ? 0 : len);
|
||||||
|
final int len = name.length() / (clrs.length + 1); //The above param is needed because this isn't always passed
|
||||||
|
Color nc;
|
||||||
|
/*if(res.getTown().hasNation()
|
||||||
|
&&(nc=PluginMain.NationColor.get(res.getTown().getNation().getName().toLowerCase()))!=null)
|
||||||
|
len = name.length() / (clrs.length+1);
|
||||||
|
else
|
||||||
|
len = name.length() / clrs.length;*/
|
||||||
|
boolean usenc = component.useNationColors.get();
|
||||||
|
val nclar = cp.NameColorLocations.get();
|
||||||
|
int[] ncl = nclar == null ? null : nclar.stream().mapToInt(Integer::intValue).toArray();
|
||||||
|
if (ncl != null && (Arrays.stream(ncl).sum() != name.length() || ncl.length != clrs.length + (usenc ? 1 : 0))) //+1: Nation color
|
||||||
|
ncl = null; // Reset if name length changed
|
||||||
|
//System.out.println("ncl: "+Arrays.toString(ncl)+" - sum: "+Arrays.stream(ncl).sum()+" - name len: "+name.length());
|
||||||
|
if (usenc) {
|
||||||
|
if (!res.getTown().hasNation()
|
||||||
|
|| (nc = NationColor.get(res.getTown().getNation().getName().toLowerCase())) == null)
|
||||||
|
nc = Color.White;
|
||||||
|
ret.append(anyColoredNamePart.apply(nc, ncl == null ? len : ncl[0])); //Make first color the nation color
|
||||||
|
}
|
||||||
|
for (int i = 0; i < clrs.length; i++)
|
||||||
|
ret.append(coloredNamePart.apply(ncl == null ? len : (usenc ? ncl[i + 1] : ncl[i]), i));
|
||||||
|
return ret.toString();
|
||||||
|
} catch (NotRegisteredException e) {
|
||||||
|
return nickname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the component is enabled
|
||||||
|
*/
|
||||||
|
public static void updatePlayerColors(Player player) { //Probably while ingame (/u ncolor - not anymore)
|
||||||
|
updatePlayerColors(player, ChatPlayer.getPlayer(player.getUniqueId(), ChatPlayer.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the component is enabled
|
||||||
|
*/
|
||||||
|
public static void updatePlayerColors(Player player, ChatPlayer cp) { //Probably at join - nop, nicknames
|
||||||
|
if (!ComponentManager.isEnabled(TownColorComponent.class))
|
||||||
|
return;
|
||||||
|
User user = PluginMain.essentials.getUser(player);
|
||||||
|
user.setNickname(getPlayerNickname(player, user, cp));
|
||||||
|
user.setDisplayNick(); //These won't fire the nick change event
|
||||||
|
cp.FlairUpdate(); //Update in list
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||||
|
updatePlayerColors(event.getPlayer(), TBMCPlayer.getPlayer(event.getPlayer().getUniqueId(), ChatPlayer.class));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
package buttondevteam.chat.components.towncolors;
|
||||||
|
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import com.earth2me.essentials.User;
|
||||||
|
import com.palmergames.bukkit.towny.event.*;
|
||||||
|
import com.palmergames.bukkit.towny.object.Town;
|
||||||
|
import lombok.val;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class TownyListener implements Listener {
|
||||||
|
@EventHandler
|
||||||
|
public void onTownRename(RenameTownEvent event) {
|
||||||
|
val clrs = TownColorComponent.TownColors.remove(event.getOldName().toLowerCase());
|
||||||
|
if (clrs != null)
|
||||||
|
TownColorComponent.TownColors.put(event.getTown().getName().toLowerCase(), clrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler //Gets called on town load as well
|
||||||
|
public void onTownJoin(TownAddResidentEvent event) {
|
||||||
|
Player p = Bukkit.getPlayer(event.getResident().getName());
|
||||||
|
if (p != null)
|
||||||
|
TownColorComponent.updatePlayerColors(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateTownMembers(Town town) {
|
||||||
|
town.getResidents().stream().map(r -> Bukkit.getPlayer(r.getName()))
|
||||||
|
.filter(Objects::nonNull).forEach(TownColorComponent::updatePlayerColors);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onTownLeave(TownRemoveResidentEvent event) {
|
||||||
|
Player p = Bukkit.getPlayer(event.getResident().getName());
|
||||||
|
if (p != null)
|
||||||
|
resetNameColor(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetNameColor(Player p) {
|
||||||
|
User user = PluginMain.essentials.getUser(p);
|
||||||
|
user.setNickname(ChatColor.stripColor(user.getNick(true).replace("~", "")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onTownDelete(DeleteTownEvent event) {
|
||||||
|
TownColorComponent.TownColors.remove(event.getTownName().toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onTownCreate(NewTownEvent event) {
|
||||||
|
Player p = Bukkit.getPlayer(event.getTown().getMayor().getName());
|
||||||
|
if (p != null)
|
||||||
|
p.sendMessage("§6Use /u towncolor to set a color for the town.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onNationRename(RenameNationEvent event) {
|
||||||
|
if (!TownColorComponent.getComponent().useNationColors.get()) return;
|
||||||
|
val clrs = TownColorComponent.NationColor.remove(event.getOldName().toLowerCase());
|
||||||
|
if (clrs != null)
|
||||||
|
TownColorComponent.NationColor.put(event.getNation().getName().toLowerCase(), clrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler //Gets called on town load as well
|
||||||
|
public void onNationJoin(NationAddTownEvent event) {
|
||||||
|
if (!TownColorComponent.getComponent().useNationColors.get()) return;
|
||||||
|
updateTownMembers(event.getTown());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onNationLeave(NationRemoveTownEvent event) {
|
||||||
|
if (!TownColorComponent.getComponent().useNationColors.get()) return;
|
||||||
|
updateTownMembers(event.getTown()); //The town still has it's colours
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onNationDelete(DeleteNationEvent event) {
|
||||||
|
if (!TownColorComponent.getComponent().useNationColors.get()) return;
|
||||||
|
TownColorComponent.NationColor.remove(event.getNationName().toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onNationCreate(NewNationEvent event) {
|
||||||
|
if (!TownColorComponent.getComponent().useNationColors.get()) return;
|
||||||
|
Player p = Bukkit.getPlayer(event.getNation().getCapital().getMayor().getName());
|
||||||
|
if (p != null)
|
||||||
|
p.sendMessage("§6Use /u nationcolor to set a color for the nation.");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package buttondevteam.chat.components.towncolors.admin;
|
||||||
|
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.chat.commands.ucmds.admin.AdminCommandBase;
|
||||||
|
import buttondevteam.chat.components.towncolors.TownColorComponent;
|
||||||
|
import buttondevteam.chat.components.towncolors.TownyListener;
|
||||||
|
import buttondevteam.chat.components.towny.TownyComponent;
|
||||||
|
import buttondevteam.lib.chat.Color;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.CustomTabCompleteMethod;
|
||||||
|
import com.palmergames.bukkit.towny.object.Nation;
|
||||||
|
import com.palmergames.bukkit.towny.object.Town;
|
||||||
|
import com.palmergames.bukkit.towny.object.TownyObject;
|
||||||
|
import lombok.val;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
@CommandClass(helpText = {
|
||||||
|
"Nation color", //
|
||||||
|
"Sets the color of the nation.", //
|
||||||
|
})
|
||||||
|
public class NationColorCommand extends AdminCommandBase {
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean def(CommandSender sender, String nation, String color) {
|
||||||
|
final Nation n = TownyComponent.dataSource.getNation(nation);
|
||||||
|
if (n == null) {
|
||||||
|
sender.sendMessage("§cThe nation '" + nation + "' cannot be found.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return SetNationColor(sender, n, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@CustomTabCompleteMethod(param = "color")
|
||||||
|
public Iterable<String> def(String nation) {
|
||||||
|
return TownColorCommand.tabcompleteColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@CustomTabCompleteMethod(param = "nation")
|
||||||
|
public Iterable<String> def() {
|
||||||
|
return TownyComponent.dataSource.getNations().stream().map(TownyObject::getName)::iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean SetNationColor(CommandSender sender, Nation nation, String color) {
|
||||||
|
val c = TownColorCommand.getColorOrSendError(color, sender);
|
||||||
|
if (!c.isPresent()) return true;
|
||||||
|
if (!c.get().getName().equals(Color.White.getName())) { //Default nation color
|
||||||
|
for (val e : TownColorComponent.NationColor.entrySet()) {
|
||||||
|
if (e.getValue().getName().equals(c.get().getName())) {
|
||||||
|
sender.sendMessage("§cThe nation " + e.getKey() + " already uses this color!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TownColorComponent.NationColor.put(nation.getName().toLowerCase(), c.get());
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
|
||||||
|
for (Town t : nation.getTowns())
|
||||||
|
TownyListener.updateTownMembers(t);
|
||||||
|
});
|
||||||
|
sender.sendMessage("§bNation color set to " + TownColorCommand.getColorText(c.get()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package buttondevteam.chat.components.towncolors.admin;
|
||||||
|
|
||||||
|
import buttondevteam.chat.commands.ucmds.admin.AdminCommandBase;
|
||||||
|
import buttondevteam.chat.components.towncolors.TownColorComponent;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import lombok.val;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
@CommandClass(helpText = {
|
||||||
|
"Town Color Count", //
|
||||||
|
"Sets how many colors can be used for a town." //
|
||||||
|
})
|
||||||
|
public class TCCount extends AdminCommandBase {
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean def(CommandSender sender, byte count) {
|
||||||
|
val comp = TownColorComponent.getComponent();
|
||||||
|
comp.colorCount.set(count);
|
||||||
|
sender.sendMessage("Color count set to " + count);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
package buttondevteam.chat.components.towncolors.admin;
|
||||||
|
|
||||||
|
import buttondevteam.chat.commands.ucmds.admin.AdminCommandBase;
|
||||||
|
import buttondevteam.chat.components.towncolors.TownColorComponent;
|
||||||
|
import buttondevteam.chat.components.towncolors.TownyListener;
|
||||||
|
import buttondevteam.chat.components.towny.TownyComponent;
|
||||||
|
import buttondevteam.lib.chat.Color;
|
||||||
|
import buttondevteam.lib.chat.Command2;
|
||||||
|
import buttondevteam.lib.chat.CommandClass;
|
||||||
|
import buttondevteam.lib.chat.CustomTabCompleteMethod;
|
||||||
|
import com.palmergames.bukkit.towny.object.Town;
|
||||||
|
import com.palmergames.bukkit.towny.object.TownyObject;
|
||||||
|
import lombok.val;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@CommandClass(helpText = {
|
||||||
|
"Town Color", //
|
||||||
|
"This command allows setting a color for a town.", //
|
||||||
|
"The town will be shown with this color on Dynmap and all players in the town will appear in chat with these colors.", //
|
||||||
|
"The colors will split the name evenly.", //
|
||||||
|
})
|
||||||
|
public class TownColorCommand extends AdminCommandBase {
|
||||||
|
@Command2.Subcommand
|
||||||
|
public boolean def(CommandSender sender, String town, String... colornames) {
|
||||||
|
if (TownyComponent.dataSource.getTown(town) == null) {
|
||||||
|
sender.sendMessage("§cThe town '" + town + "' cannot be found.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Town targetTown = TownyComponent.dataSource.getTown(town);
|
||||||
|
if (targetTown == null) {
|
||||||
|
sender.sendMessage("§cThe town '" + town + "' cannot be found.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return SetTownColor(sender, targetTown, colornames);
|
||||||
|
}
|
||||||
|
|
||||||
|
@CustomTabCompleteMethod(param = "colornames")
|
||||||
|
public Iterable<String> def(String town) {
|
||||||
|
return TownColorCommand.tabcompleteColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@CustomTabCompleteMethod(param = "town")
|
||||||
|
public Iterable<String> def() {
|
||||||
|
return TownyComponent.dataSource.getTowns().stream().map(TownyObject::getName)::iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean SetTownColor(CommandSender sender, Town town, String[] colors) {
|
||||||
|
Color[] clrs = new Color[colors.length];
|
||||||
|
for (int i = 0; i < colors.length; i++) {
|
||||||
|
val c = getColorOrSendError(colors[i], sender);
|
||||||
|
if (!c.isPresent())
|
||||||
|
return true;
|
||||||
|
clrs[i] = c.get();
|
||||||
|
}
|
||||||
|
Color tnc;
|
||||||
|
boolean usenc = TownColorComponent.getComponent().useNationColors.get();
|
||||||
|
if (usenc) {
|
||||||
|
try {
|
||||||
|
tnc = TownColorComponent.NationColor.get(town.getNation().getName().toLowerCase());
|
||||||
|
} catch (Exception e) {
|
||||||
|
tnc = null;
|
||||||
|
}
|
||||||
|
if (tnc == null) tnc = Color.White; //Default nation color - TODO: Make configurable
|
||||||
|
} else tnc = null;
|
||||||
|
for (Map.Entry<String, Color[]> other : TownColorComponent.TownColors.entrySet()) {
|
||||||
|
Color nc;
|
||||||
|
if (usenc) {
|
||||||
|
try {
|
||||||
|
nc = TownColorComponent.NationColor.get(TownyComponent.dataSource.getTown(other.getKey()).getNation().getName().toLowerCase());
|
||||||
|
} catch (Exception e) { //Too lazy for lots of null-checks and it may throw exceptions anyways
|
||||||
|
nc = null;
|
||||||
|
}
|
||||||
|
if (nc == null) nc = Color.White; //Default nation color
|
||||||
|
} else nc = null;
|
||||||
|
if (!usenc || nc.getName().equals(tnc.getName())) {
|
||||||
|
int C = 0;
|
||||||
|
if (clrs.length == other.getValue().length)
|
||||||
|
for (int i = 0; i < clrs.length; i++)
|
||||||
|
if (clrs[i].getName().equals(other.getValue()[i].getName()))
|
||||||
|
C++;
|
||||||
|
else break;
|
||||||
|
if (C == clrs.length) {
|
||||||
|
sender.sendMessage("§cThis town color combination is already used!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TownColorComponent.TownColors.put(town.getName().toLowerCase(), clrs);
|
||||||
|
TownyListener.updateTownMembers(town);
|
||||||
|
|
||||||
|
val dtp = Bukkit.getPluginManager().getPlugin("Dynmap-Towny");
|
||||||
|
if (dtp != null) //If it's not found then it's not loaded, it'll be noticed by the admins if needed
|
||||||
|
TownColorComponent.setTownColor(dtp, town.getName(), clrs, tnc);
|
||||||
|
sender.sendMessage("§bColor(s) set.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Optional<Color> getColorOrSendError(String name, CommandSender sender) {
|
||||||
|
val c = Arrays.stream(Color.values()).skip(1).filter(cc -> cc.getName().equalsIgnoreCase(name)).findAny();
|
||||||
|
if (!c.isPresent()) { //^^ Skip black
|
||||||
|
sender.sendMessage("§cThe color '" + name + "' cannot be found."); //ˇˇ Skip black
|
||||||
|
sender.sendMessage("§cAvailable colors: " + Arrays.stream(Color.values()).skip(1).map(TownColorCommand::getColorText).collect(Collectors.joining(", ")));
|
||||||
|
sender.sendMessage("§cMake sure to type them exactly as shown above.");
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getColorText(Color col) {
|
||||||
|
return String.format("§%x%s§r", col.ordinal(), col.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getTownNameCased(String name) {
|
||||||
|
val town = TownyComponent.dataSource.getTown(name);
|
||||||
|
if (town == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return town.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Iterable<String> tabcompleteColor() {
|
||||||
|
return Arrays.stream(Color.values()).skip(1).map(Color::getName)::iterator;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
package buttondevteam.chat.components.towny;
|
||||||
|
|
||||||
|
import buttondevteam.chat.ChatUtils;
|
||||||
|
import buttondevteam.core.component.channel.Channel;
|
||||||
|
import buttondevteam.lib.TBMCSystemChatEvent;
|
||||||
|
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||||
|
import lombok.val;
|
||||||
|
import org.apache.logging.log4j.Level;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.core.Filter;
|
||||||
|
import org.apache.logging.log4j.core.LogEvent;
|
||||||
|
import org.apache.logging.log4j.core.Logger;
|
||||||
|
import org.apache.logging.log4j.core.LoggerContext;
|
||||||
|
import org.apache.logging.log4j.core.appender.AbstractAppender;
|
||||||
|
import org.apache.logging.log4j.core.filter.LevelRangeFilter;
|
||||||
|
import org.apache.logging.log4j.core.layout.PatternLayout;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class TownyAnnouncer {
|
||||||
|
private static final Pattern LOG_TYPE_PATTERN = Pattern.compile("\\[(\\w+) (?:Msg|Message)](?: (\\w+):)?");
|
||||||
|
private static final String APPENDER_NAME = "Chroma";
|
||||||
|
private static final AbstractAppender HANDLER = new AbstractAppender(APPENDER_NAME,
|
||||||
|
LevelRangeFilter.createFilter(Level.INFO, Level.INFO, Filter.Result.ACCEPT, Filter.Result.ACCEPT),
|
||||||
|
PatternLayout.createDefaultLayout()) {
|
||||||
|
@Override
|
||||||
|
public void append(LogEvent logRecord) {
|
||||||
|
if (logRecord.getMessage() == null) return;
|
||||||
|
String message = logRecord.getMessage().getFormattedMessage();
|
||||||
|
val m = LOG_TYPE_PATTERN.matcher(message);
|
||||||
|
if (!m.find()) return;
|
||||||
|
String groupID = m.group(2); //The group ID is correctly cased
|
||||||
|
switch (String.valueOf(m.group(1))) { //valueOf: Handles null
|
||||||
|
case "Town":
|
||||||
|
if (townChannel == null) return;
|
||||||
|
TBMCChatAPI.SendSystemMessage(townChannel,
|
||||||
|
new Channel.RecipientTestResult(TownyComponent.getTownNationIndex(groupID, false), groupID),
|
||||||
|
message, target, ChatUtils.MCORIGIN);
|
||||||
|
break;
|
||||||
|
case "Nation":
|
||||||
|
if (nationChannel == null) return;
|
||||||
|
TBMCChatAPI.SendSystemMessage(nationChannel,
|
||||||
|
new Channel.RecipientTestResult(TownyComponent.getTownNationIndex(groupID, true), groupID),
|
||||||
|
message, target, ChatUtils.MCORIGIN);
|
||||||
|
break;
|
||||||
|
case "Global":
|
||||||
|
TBMCChatAPI.SendSystemMessage(Channel.globalChat,
|
||||||
|
Channel.RecipientTestResult.ALL,
|
||||||
|
message, target, ChatUtils.MCORIGIN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static TBMCSystemChatEvent.BroadcastTarget target;
|
||||||
|
private static Channel townChannel;
|
||||||
|
private static Channel nationChannel;
|
||||||
|
|
||||||
|
public static void setup(Channel townChannel, Channel nationChannel) {
|
||||||
|
target = TBMCSystemChatEvent.BroadcastTarget.add("towny");
|
||||||
|
TownyAnnouncer.townChannel = townChannel;
|
||||||
|
TownyAnnouncer.nationChannel = nationChannel;
|
||||||
|
/*System.out.println(LogManager.getLogger("com.palmergames.bukkit.towny"));
|
||||||
|
((Logger) LogManager.getLogger("com.palmergames.bukkit.towny")).getContext().getConfiguration().addAppender(HANDLER);
|
||||||
|
System.out.println(((Logger) LogManager.getLogger("com.palmergames.bukkit.towny")).getAppenders());
|
||||||
|
((LoggerContext)LogManager.getContext(false)).updateLoggers();
|
||||||
|
System.out.println(((Logger) LogManager.getLogger("com.palmergames.bukkit.towny")).getAppenders());
|
||||||
|
((Logger) LogManager.getLogger("com.palmergames.bukkit.towny")).getContext().updateLoggers();
|
||||||
|
System.out.println(((Logger) LogManager.getLogger("com.palmergames.bukkit.towny")).getAppenders());*/
|
||||||
|
val lc = (LoggerContext) LogManager.getContext(false);
|
||||||
|
HANDLER.start();
|
||||||
|
lc.getConfiguration().addAppender(HANDLER);
|
||||||
|
Logger logger = lc.getLogger("com.palmergames.bukkit.towny");
|
||||||
|
//System.out.println(logger);
|
||||||
|
//System.out.println(lc.getConfiguration().<Appender>getAppender(HANDLER.getName())); //T defaults to String because of the context which results in a cast exception
|
||||||
|
logger.addAppender(lc.getConfiguration().getAppender(HANDLER.getName()));
|
||||||
|
logger.get().addAppender(HANDLER, Level.INFO, HANDLER.getFilter());
|
||||||
|
lc.updateLoggers();
|
||||||
|
//System.out.println(logger.getAppenders());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setdown() {
|
||||||
|
TBMCSystemChatEvent.BroadcastTarget.remove(target);
|
||||||
|
target = null;
|
||||||
|
TownyAnnouncer.townChannel = null;
|
||||||
|
TownyAnnouncer.nationChannel = null;
|
||||||
|
((Logger) LogManager.getLogger("com.palmergames.bukkit.towny")).getAppenders().remove(APPENDER_NAME);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
package buttondevteam.chat.components.towny;
|
||||||
|
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.core.component.channel.Channel;
|
||||||
|
import buttondevteam.lib.architecture.Component;
|
||||||
|
import buttondevteam.lib.chat.Color;
|
||||||
|
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||||
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||||
|
import com.palmergames.bukkit.towny.TownyAPI;
|
||||||
|
import com.palmergames.bukkit.towny.TownyUniverse;
|
||||||
|
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException;
|
||||||
|
import com.palmergames.bukkit.towny.object.Nation;
|
||||||
|
import com.palmergames.bukkit.towny.object.Resident;
|
||||||
|
import com.palmergames.bukkit.towny.object.Town;
|
||||||
|
import lombok.val;
|
||||||
|
import net.kyori.adventure.text.TextComponent;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component manages the town and nation chat. It's also needed for the TownColorComponent.
|
||||||
|
* It provides the TC and NC channels, and posts Towny messages (global, town, nation) to the correct channels for other platforms like Discord.
|
||||||
|
* You can disable /tc and /nc in Chroma-Core's config if you only want to use the TownColorComponent.
|
||||||
|
*/
|
||||||
|
public class TownyComponent extends Component<PluginMain> {
|
||||||
|
public static TownyAPI dataSource;
|
||||||
|
private static ArrayList<String> Towns;
|
||||||
|
private static ArrayList<String> Nations;
|
||||||
|
|
||||||
|
private Channel TownChat;
|
||||||
|
private Channel NationChat;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void enable() {
|
||||||
|
dataSource = TownyAPI.getInstance();
|
||||||
|
Towns = TownyUniverse.getInstance().getTowns().stream().map(Town::getName).collect(Collectors.toCollection(ArrayList::new)); // Creates a snapshot of towns, new towns will be added when needed
|
||||||
|
Nations = TownyUniverse.getInstance().getNations().stream().map(Nation::getName).collect(Collectors.toCollection(ArrayList::new)); // Same here but with nations
|
||||||
|
TBMCChatAPI.registerChatChannel(
|
||||||
|
TownChat = new Channel("§3TC§f", Color.DarkAqua, "tc", s -> checkTownNationChat(s, false)));
|
||||||
|
TBMCChatAPI.registerChatChannel(
|
||||||
|
NationChat = new Channel("§6NC§f", Color.Gold, "nc", s -> checkTownNationChat(s, true)));
|
||||||
|
TownyAnnouncer.setup(TownChat, NationChat);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void disable() {
|
||||||
|
TownyAnnouncer.setdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Consumer<Player> handleSpiesInit(Channel channel, TextComponent.Builder json) {
|
||||||
|
if (channel.getIdentifier().equals(TownChat.getIdentifier()) || channel.getIdentifier().equals(NationChat.getIdentifier())) {
|
||||||
|
// TODO: Cannot prepend to json, so we need to run this ealier
|
||||||
|
//((List<TellrawPart>) json.getExtra()).add(0, new TellrawPart("[SPY]"));
|
||||||
|
return p -> handleSpies(channel, p, json);
|
||||||
|
}
|
||||||
|
return p -> {};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleSpies(Channel channel, Player p, TextComponent.Builder jsonstr) {
|
||||||
|
if (channel.getIdentifier().equals(TownChat.getIdentifier()) || channel.getIdentifier().equals(NationChat.getIdentifier())) {
|
||||||
|
val res = dataSource.getResident(p.getName());
|
||||||
|
if (res == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (res.hasMode("spy"))
|
||||||
|
p.sendMessage(jsonstr.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the error message for the message sender if they can't send it and the score
|
||||||
|
*/
|
||||||
|
private static Channel.RecipientTestResult checkTownNationChat(ChromaGamerBase user, boolean nationchat) {
|
||||||
|
if (!(user instanceof TBMCPlayerBase))
|
||||||
|
return new Channel.RecipientTestResult("§cYou are not a player!");
|
||||||
|
val sender = ((TBMCPlayerBase) user).getOfflinePlayer();
|
||||||
|
Resident resident = dataSource.getResident(sender.getName());
|
||||||
|
Channel.RecipientTestResult result = checkTownNationChatInternal(nationchat, resident);
|
||||||
|
if (result.errormessage != null && resident != null && resident.getModes().contains("spy")) // Only use spy if they wouldn't see it
|
||||||
|
result = new Channel.RecipientTestResult(1000, "allspies"); // There won't be more than a thousand towns/nations probably
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Channel.RecipientTestResult checkTownNationChatInternal(boolean nationchat,
|
||||||
|
Resident resident) {
|
||||||
|
try {
|
||||||
|
/*
|
||||||
|
* p.sendMessage(String.format("[SPY-%s] - %s: %s", channel.DisplayName, ((Player) sender).getDisplayName(), message));
|
||||||
|
*/
|
||||||
|
Town town = null;
|
||||||
|
if (resident != null && resident.hasTown())
|
||||||
|
town = resident.getTown();
|
||||||
|
if (town == null)
|
||||||
|
return new Channel.RecipientTestResult("You aren't in a town.");
|
||||||
|
Nation nation = null;
|
||||||
|
int index;
|
||||||
|
if (nationchat) {
|
||||||
|
if (town.hasNation())
|
||||||
|
nation = town.getNation();
|
||||||
|
if (nation == null)
|
||||||
|
return new Channel.RecipientTestResult("Your town isn't in a nation.");
|
||||||
|
index = getTownNationIndex(nation.getName(), true);
|
||||||
|
} else
|
||||||
|
index = getTownNationIndex(town.getName(), false);
|
||||||
|
return new Channel.RecipientTestResult(index, nationchat ? nation.getName() : town.getName());
|
||||||
|
} catch (NotRegisteredException e) {
|
||||||
|
return new Channel.RecipientTestResult("You (probably) aren't knwon by Towny! (Not in a town)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getTownNationIndex(String name, boolean nation) {
|
||||||
|
val list = nation ? Nations : Towns;
|
||||||
|
int index = list.indexOf(name);
|
||||||
|
if (index < 0) {
|
||||||
|
list.add(name);
|
||||||
|
index = list.size() - 1;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,197 +0,0 @@
|
||||||
package buttondevteam.chat.formatting;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
|
|
||||||
import buttondevteam.lib.chat.*;
|
|
||||||
|
|
||||||
public final class ChatFormatter {
|
|
||||||
private Pattern regex;
|
|
||||||
private Format format;
|
|
||||||
private Color color;
|
|
||||||
private Function<String, String> onmatch;
|
|
||||||
private String openlink;
|
|
||||||
private Priority priority;
|
|
||||||
private short removecharcount = 0;
|
|
||||||
private short removecharpos = -1;
|
|
||||||
|
|
||||||
public ChatFormatter(Pattern regex, Format format, Color color, Function<String, String> onmatch, String openlink,
|
|
||||||
Priority priority, short removecharcount, short removecharpos) {
|
|
||||||
this.regex = regex;
|
|
||||||
this.format = format;
|
|
||||||
this.color = color;
|
|
||||||
this.onmatch = onmatch;
|
|
||||||
this.openlink = openlink;
|
|
||||||
this.priority = Priority.High;
|
|
||||||
this.removecharcount = removecharcount;
|
|
||||||
this.removecharpos = removecharpos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Combine(List<ChatFormatter> formatters, String str, TellrawPart tp) {
|
|
||||||
/*
|
|
||||||
* This method assumes that there is always a global formatter
|
|
||||||
*/
|
|
||||||
ArrayList<FormattedSection> sections = new ArrayList<FormattedSection>();
|
|
||||||
for (ChatFormatter formatter : formatters) {
|
|
||||||
Matcher matcher = formatter.regex.matcher(str);
|
|
||||||
while (matcher.find()) {
|
|
||||||
DebugCommand.SendDebugMessage("Found match from " + matcher.start() + " to " + (matcher.end() - 1));
|
|
||||||
DebugCommand.SendDebugMessage("With formatter:" + formatter);
|
|
||||||
ArrayList<String> groups = new ArrayList<String>();
|
|
||||||
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.removecharcount, formatter.removecharcount, formatter.removecharpos);
|
|
||||||
sections.add(section);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sections.sort((s1, s2) -> {
|
|
||||||
if (s1.Start == s2.Start)
|
|
||||||
return Integer.compare(s1.End, s2.End);
|
|
||||||
else
|
|
||||||
return Integer.compare(s1.Start, s2.Start);
|
|
||||||
});
|
|
||||||
boolean cont = true;
|
|
||||||
boolean found = false;
|
|
||||||
for (int i = 1; cont;) {
|
|
||||||
int nextindex = i + 1;
|
|
||||||
if (sections.size() < 2)
|
|
||||||
break;
|
|
||||||
DebugCommand.SendDebugMessage("i: " + i);
|
|
||||||
FormattedSection firstSection = sections.get(i - 1);
|
|
||||||
DebugCommand.SendDebugMessage("Combining sections " + firstSection + " and " + sections.get(i));
|
|
||||||
if (firstSection.Start == sections.get(i).Start && firstSection.End == sections.get(i).End) {
|
|
||||||
firstSection.Formatters.addAll(sections.get(i).Formatters);
|
|
||||||
firstSection.Matches.addAll(sections.get(i).Matches);
|
|
||||||
if (firstSection.RemCharFromStart < sections.get(i).RemCharFromStart)
|
|
||||||
firstSection.RemCharFromStart = sections.get(i).RemCharFromStart;
|
|
||||||
if (firstSection.RemCharFromEnd < sections.get(i).RemCharFromEnd)
|
|
||||||
firstSection.RemCharFromEnd = sections.get(i).RemCharFromEnd;
|
|
||||||
firstSection.RemCharPos.addAll(sections.get(i).RemCharPos);
|
|
||||||
DebugCommand.SendDebugMessage("To section " + firstSection);
|
|
||||||
sections.remove(i);
|
|
||||||
found = true;
|
|
||||||
} else if (firstSection.End > sections.get(i).Start && firstSection.Start < sections.get(i).End) {
|
|
||||||
int origend = firstSection.End;
|
|
||||||
firstSection.End = sections.get(i).Start - 1;
|
|
||||||
int origend2 = sections.get(i).End;
|
|
||||||
boolean switchends;
|
|
||||||
if (switchends = origend2 < origend) {
|
|
||||||
int tmp = origend;
|
|
||||||
origend = origend2;
|
|
||||||
origend2 = tmp;
|
|
||||||
}
|
|
||||||
FormattedSection section = new FormattedSection(firstSection.Formatters, sections.get(i).Start, origend,
|
|
||||||
firstSection.Matches, sections.get(i).RemCharFromStart, firstSection.RemCharFromEnd,
|
|
||||||
Collections.emptyList());
|
|
||||||
section.Formatters.addAll(sections.get(i).Formatters);
|
|
||||||
section.Matches.addAll(sections.get(i).Matches); // TODO: Clean
|
|
||||||
sections.add(i, section);
|
|
||||||
nextindex++;
|
|
||||||
FormattedSection thirdFormattedSection = sections.get(i + 1);
|
|
||||||
if (switchends) { // Use the properties of the first section not the second one
|
|
||||||
thirdFormattedSection.Formatters.clear();
|
|
||||||
thirdFormattedSection.Formatters.addAll(firstSection.Formatters);
|
|
||||||
thirdFormattedSection.Matches.clear();
|
|
||||||
thirdFormattedSection.Matches.addAll(firstSection.Matches);
|
|
||||||
short remchar = section.RemCharFromEnd;
|
|
||||||
section.RemCharFromEnd = thirdFormattedSection.RemCharFromEnd;
|
|
||||||
thirdFormattedSection.RemCharFromEnd = remchar;
|
|
||||||
}
|
|
||||||
firstSection.RemCharFromEnd = 0;
|
|
||||||
thirdFormattedSection.RemCharFromStart = 0;
|
|
||||||
thirdFormattedSection.Start = origend + 1;
|
|
||||||
thirdFormattedSection.End = origend2;
|
|
||||||
for (int x = 0; x < firstSection.RemCharPos.size(); x++) {
|
|
||||||
if (firstSection.RemCharPos.get(x) > firstSection.End) {
|
|
||||||
if (firstSection.RemCharPos.get(x) > section.End)
|
|
||||||
thirdFormattedSection.RemCharPos.add(
|
|
||||||
firstSection.RemCharPos.get(x) - thirdFormattedSection.Start + firstSection.Start);
|
|
||||||
else
|
|
||||||
section.RemCharPos.add(firstSection.RemCharPos.get(x) - section.Start + firstSection.Start);
|
|
||||||
firstSection.RemCharPos.remove(x--);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DebugCommand.SendDebugMessage("To sections 1:" + firstSection + "");
|
|
||||||
DebugCommand.SendDebugMessage(" 2:" + section + "");
|
|
||||||
DebugCommand.SendDebugMessage(" 3:" + thirdFormattedSection);
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
for (int j = i - 1; j <= i + 1; j++) {
|
|
||||||
if (j < sections.size() && sections.get(j).End < sections.get(j).Start) {
|
|
||||||
DebugCommand.SendDebugMessage("Removing section: " + sections.get(j));
|
|
||||||
sections.remove(j);
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i = nextindex - 1;
|
|
||||||
i++;
|
|
||||||
if (i >= sections.size()) {
|
|
||||||
if (found) {
|
|
||||||
i = 1;
|
|
||||||
found = false;
|
|
||||||
sections.sort((s1, s2) -> {
|
|
||||||
if (s1.Start == s2.Start)
|
|
||||||
return Integer.compare(s1.End, s2.End);
|
|
||||||
else
|
|
||||||
return Integer.compare(s1.Start, s2.Start);
|
|
||||||
});
|
|
||||||
} else
|
|
||||||
cont = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < sections.size(); i++) {
|
|
||||||
FormattedSection section = sections.get(i);
|
|
||||||
DebugCommand.SendDebugMessage("Applying section: " + section);
|
|
||||||
String originaltext;
|
|
||||||
int start = section.Start + section.RemCharFromStart, end = section.End + 1 - section.RemCharFromEnd; // TODO: RemCharPos
|
|
||||||
StringBuilder textsb = new StringBuilder(str.substring(start, end));
|
|
||||||
for (int x = 0; x < section.RemCharPos.size(); x++)
|
|
||||||
if (section.RemCharPos.get(x) != -1)
|
|
||||||
textsb.deleteCharAt(section.RemCharPos.get(x));
|
|
||||||
originaltext = textsb.toString();
|
|
||||||
DebugCommand.SendDebugMessage("Section text: " + originaltext);
|
|
||||||
Color color = null;
|
|
||||||
int format = 0;
|
|
||||||
String openlink = null;
|
|
||||||
section.Formatters.sort((cf2, cf1) -> cf1.priority.compareTo(cf2.priority));
|
|
||||||
for (ChatFormatter formatter : section.Formatters) {
|
|
||||||
DebugCommand.SendDebugMessage("Applying formatter: " + formatter);
|
|
||||||
if (formatter.onmatch != null)
|
|
||||||
originaltext = formatter.onmatch.apply(originaltext);
|
|
||||||
if (formatter.color != null)
|
|
||||||
color = formatter.color;
|
|
||||||
if (formatter.format != null)
|
|
||||||
format = formatter.format.getFlag(); //TODO: Fix
|
|
||||||
if (formatter.openlink != null)
|
|
||||||
openlink = formatter.openlink;
|
|
||||||
}
|
|
||||||
TellrawPart newtp = new TellrawPart("");
|
|
||||||
newtp.setText(originaltext);
|
|
||||||
if (color != null)
|
|
||||||
newtp.setColor(color);
|
|
||||||
if (format != 0)
|
|
||||||
newtp.setFormat(format);
|
|
||||||
if (openlink != null && openlink.length() > 0) {
|
|
||||||
newtp.setClickEvent(TellrawEvent.create(TellrawEvent.ClickAC, TellrawEvent.ClickAction.OPEN_URL,
|
|
||||||
(section.Matches.size() > 0 ? openlink.replace("$1", section.Matches.get(0)) : openlink)))
|
|
||||||
.setHoverEvent(TellrawEvent.create(TellrawEvent.HoverAC, TellrawEvent.HoverAction.SHOW_TEXT,
|
|
||||||
new TellrawPart("Click to open").setColor(Color.Blue)));
|
|
||||||
}
|
|
||||||
tp.addExtra(newtp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return new StringBuilder("F(").append(color).append(", ").append(format).append(", ").append(openlink)
|
|
||||||
.append(", ").append(priority).append(")").toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,103 +0,0 @@
|
||||||
package buttondevteam.chat.formatting;
|
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import buttondevteam.lib.chat.*;
|
|
||||||
|
|
||||||
public class ChatFormatterBuilder {
|
|
||||||
private Pattern regex;
|
|
||||||
private Format format;
|
|
||||||
private Color color;
|
|
||||||
private Function<String, String> onmatch;
|
|
||||||
private String openlink;
|
|
||||||
private Priority priority;
|
|
||||||
private short removecharcount = 0;
|
|
||||||
private short removecharpos = -1;
|
|
||||||
|
|
||||||
public ChatFormatter build() {
|
|
||||||
return new ChatFormatter(regex, format, color, onmatch, openlink, priority, removecharcount, removecharpos);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Pattern getRegex() {
|
|
||||||
return regex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChatFormatterBuilder setRegex(Pattern regex) {
|
|
||||||
this.regex = regex;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Format getFormat() {
|
|
||||||
return format;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChatFormatterBuilder setFormat(Format format) {
|
|
||||||
this.format = format;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Color getColor() {
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChatFormatterBuilder setColor(Color color) {
|
|
||||||
this.color = color;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Function<String, String> getOnmatch() {
|
|
||||||
return onmatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChatFormatterBuilder setOnmatch(Function<String, String> onmatch) {
|
|
||||||
this.onmatch = onmatch;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOpenlink() {
|
|
||||||
return openlink;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChatFormatterBuilder setOpenlink(String openlink) {
|
|
||||||
this.openlink = openlink;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Priority getPriority() {
|
|
||||||
return priority;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChatFormatterBuilder setPriority(Priority priority) {
|
|
||||||
this.priority = priority;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getRemoveCharCount() {
|
|
||||||
return removecharcount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the amount of characters to be removed from the start and the end of the match.
|
|
||||||
*
|
|
||||||
* @return This instance
|
|
||||||
*/
|
|
||||||
public ChatFormatterBuilder setRemoveCharCount(short removecharcount) {
|
|
||||||
this.removecharcount = removecharcount;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getRemoveCharPos() {
|
|
||||||
return removecharpos;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the position where a single character should be removed. Setting -1 will disable it.
|
|
||||||
*
|
|
||||||
* @return This instance
|
|
||||||
*/
|
|
||||||
public ChatFormatterBuilder setRemoveCharPos(short removecharpos) {
|
|
||||||
this.removecharpos = removecharpos;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
package buttondevteam.chat.formatting;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
class FormattedSection {
|
|
||||||
int Start;
|
|
||||||
int End;
|
|
||||||
ArrayList<ChatFormatter> Formatters = new ArrayList<ChatFormatter>();
|
|
||||||
ArrayList<String> Matches = new ArrayList<String>();
|
|
||||||
short RemCharFromStart;
|
|
||||||
short RemCharFromEnd;
|
|
||||||
ArrayList<Integer> RemCharPos = new ArrayList<Integer>();
|
|
||||||
|
|
||||||
FormattedSection(ChatFormatter formatter, int start, int end, ArrayList<String> matches, short remcharfromstart,
|
|
||||||
short remcharfromend, int remcharpos) {
|
|
||||||
Start = start;
|
|
||||||
End = end;
|
|
||||||
Formatters.add(formatter);
|
|
||||||
Matches.addAll(matches);
|
|
||||||
RemCharFromStart = remcharfromstart;
|
|
||||||
RemCharFromEnd = remcharfromend;
|
|
||||||
RemCharPos.add(remcharpos);
|
|
||||||
}
|
|
||||||
|
|
||||||
FormattedSection(Collection<ChatFormatter> formatters, int start, int end, ArrayList<String> matches,
|
|
||||||
short remcharfromstart, short remcharfromend, Collection<Integer> remcharpos) {
|
|
||||||
Start = start;
|
|
||||||
End = end;
|
|
||||||
Formatters.addAll(formatters);
|
|
||||||
Matches.addAll(matches);
|
|
||||||
RemCharFromStart = remcharfromstart;
|
|
||||||
RemCharFromEnd = remcharfromend;
|
|
||||||
RemCharPos.addAll(remcharpos);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return new StringBuilder("Section(").append(Start).append(", ").append(End).append(", formatters: ")
|
|
||||||
.append(Formatters.toString()).append(", matches: ").append(Matches.toString()).append(", RemChars: ")
|
|
||||||
.append(RemCharFromStart).append(", ").append(RemCharFromEnd).append(", ").append(RemCharPos)
|
|
||||||
.append(")").toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,82 +1,48 @@
|
||||||
package buttondevteam.chat.listener;
|
package buttondevteam.chat.listener;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.GameMode;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
|
||||||
|
|
||||||
import com.earth2me.essentials.Essentials;
|
|
||||||
|
|
||||||
import buttondevteam.chat.ChatPlayer;
|
import buttondevteam.chat.ChatPlayer;
|
||||||
import buttondevteam.chat.FlairStates;
|
|
||||||
import buttondevteam.chat.PlayerJoinTimerTask;
|
import buttondevteam.chat.PlayerJoinTimerTask;
|
||||||
import buttondevteam.chat.PluginMain;
|
import buttondevteam.chat.PluginMain;
|
||||||
import buttondevteam.lib.TBMCPlayerAddEvent;
|
import buttondevteam.chat.commands.ucmds.HistoryCommand;
|
||||||
import buttondevteam.lib.TBMCPlayerJoinEvent;
|
import buttondevteam.chat.components.flair.FlairComponent;
|
||||||
import buttondevteam.lib.TBMCPlayerLoadEvent;
|
import buttondevteam.chat.components.flair.FlairStates;
|
||||||
import buttondevteam.lib.TBMCPlayerSaveEvent;
|
import buttondevteam.core.ComponentManager;
|
||||||
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayerBase;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
|
||||||
|
import java.util.Timer;
|
||||||
|
|
||||||
public class PlayerJoinLeaveListener implements Listener {
|
public class PlayerJoinLeaveListener implements Listener {
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
public void onPlayerLoad(TBMCPlayerLoadEvent e) {
|
public void onPlayerJoin(PlayerJoinEvent e) {
|
||||||
ChatPlayer cp = e.GetPlayer().asPluginPlayer(ChatPlayer.class);
|
Player p = e.getPlayer();
|
||||||
|
ChatPlayer cp = TBMCPlayerBase.getPlayer(p.getUniqueId(), ChatPlayer.class);
|
||||||
cp.FlairUpdate();
|
cp.FlairUpdate();
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
if (ComponentManager.isEnabled(FlairComponent.class)) {
|
||||||
public void onPlayerTBMCJoin(TBMCPlayerJoinEvent e) {
|
if (!cp.FlairState.get().equals(FlairStates.NoComment)) {
|
||||||
if (PluginMain.essentials == null)
|
FlairComponent.ConfirmUserMessage(cp);
|
||||||
PluginMain.essentials = ((Essentials) Bukkit.getPluginManager().getPlugin("Essentials"));
|
|
||||||
ChatPlayer cp = e.GetPlayer().asPluginPlayer(ChatPlayer.class);
|
|
||||||
Player p = Bukkit.getPlayer(cp.getUuid());
|
|
||||||
|
|
||||||
if (!cp.getFlairState().equals(FlairStates.NoComment)) {
|
|
||||||
PluginMain.ConfirmUserMessage(cp);
|
|
||||||
Timer timer = new Timer();
|
Timer timer = new Timer();
|
||||||
PlayerJoinTimerTask tt = new PlayerJoinTimerTask() {
|
PlayerJoinTimerTask tt = new PlayerJoinTimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
p.setPlayerListName(p.getName() + mp.GetFormattedFlair());
|
mp.FlairUpdate();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
tt.mp = cp;
|
tt.mp = cp;
|
||||||
timer.schedule(tt, 1000);
|
timer.schedule(tt, 1000);
|
||||||
} else {
|
} //TODO: Better Reddit integration (OAuth)
|
||||||
if (cp.getFlairTime() == 0x00)
|
|
||||||
cp.SetFlair(ChatPlayer.FlairTimeNone);
|
|
||||||
Timer timer = new Timer();
|
|
||||||
PlayerJoinTimerTask tt = new PlayerJoinTimerTask() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Player player = Bukkit.getPlayer(mp.getPlayerName());
|
|
||||||
if (player == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (mp.getFlairState().equals(FlairStates.NoComment)) {
|
|
||||||
String json = String.format(
|
|
||||||
"[\"\",{\"text\":\"If you're from Reddit and you'd like your /r/TheButton flair displayed ingame, write your Minecraft name to \",\"color\":\"aqua\"},{\"text\":\"[this thread].\",\"color\":\"aqua\",\"clickEvent\":{\"action\":\"open_url\",\"value\":\"%s\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"\",\"extra\":[{\"text\":\"Click here to go to the Reddit thread\",\"color\":\"aqua\"}]}}}]",
|
|
||||||
PluginMain.FlairThreadURL);
|
|
||||||
PluginMain.Instance.getServer().dispatchCommand(PluginMain.Console,
|
|
||||||
"tellraw " + mp.getPlayerName() + " " + json);
|
|
||||||
json = "[\"\",{\"text\":\"If you aren't from Reddit or don't want the flair, type /u ignore to prevent this message after next login.\",\"color\":\"aqua\"}]";
|
|
||||||
PluginMain.Instance.getServer().dispatchCommand(PluginMain.Console,
|
|
||||||
"tellraw " + mp.getPlayerName() + " " + json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
tt.mp = cp;
|
|
||||||
timer.schedule(tt, 15 * 1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String nwithoutformatting = PluginMain.essentials.getUser(p).getNickname();
|
String nwithoutformatting = PluginMain.essentials.getUser(p).getNickname();
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
if (nwithoutformatting != null) {
|
if (nwithoutformatting != null) {
|
||||||
while ((index = nwithoutformatting.indexOf("§k")) != -1)
|
while ((index = nwithoutformatting.indexOf("§k")) != -1)
|
||||||
|
@ -85,42 +51,15 @@ public class PlayerJoinLeaveListener implements Listener {
|
||||||
nwithoutformatting = nwithoutformatting.replace("§" + nwithoutformatting.charAt(index + 1), "");
|
nwithoutformatting = nwithoutformatting.replace("§" + nwithoutformatting.charAt(index + 1), "");
|
||||||
} else
|
} else
|
||||||
nwithoutformatting = p.getName();
|
nwithoutformatting = p.getName();
|
||||||
PlayerListener.nicknames.put(nwithoutformatting, p.getUniqueId());
|
PlayerListener.nicknames.forcePut(nwithoutformatting.toLowerCase(), p.getUniqueId());
|
||||||
|
|
||||||
cp.RPMode = true;
|
if (PluginMain.Instance.storeChatHistory.get())
|
||||||
|
HistoryCommand.showHistory(ChromaGamerBase.getFromSender(e.getPlayer()), null);
|
||||||
cp.FlairUpdate();
|
|
||||||
|
|
||||||
if (cp.ChatOnly || p.getGameMode().equals(GameMode.SPECTATOR)) {
|
|
||||||
cp.ChatOnly = false;
|
|
||||||
p.setGameMode(GameMode.SURVIVAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerSave(TBMCPlayerSaveEvent e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerAdd(TBMCPlayerAddEvent event) {
|
|
||||||
ChatPlayer cp = event.GetPlayer().asPluginPlayer(ChatPlayer.class);
|
|
||||||
cp.SetFlair(ChatPlayer.FlairTimeNone);
|
|
||||||
cp.setFlairState(FlairStates.NoComment);
|
|
||||||
cp.setUserNames(new ArrayList<>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerLeave(PlayerQuitEvent event) {
|
public void onPlayerLeave(PlayerQuitEvent event) {
|
||||||
String deletenick = null;
|
PlayerListener.nicknames.inverse().remove(event.getPlayer().getUniqueId());
|
||||||
for (String nickname : PlayerListener.nicknames.keySet()) {
|
|
||||||
UUID uuid = PlayerListener.nicknames.get(nickname);
|
|
||||||
if (event.getPlayer().getUniqueId().equals(uuid)) {
|
|
||||||
deletenick = nickname;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (deletenick != null)
|
|
||||||
PlayerListener.nicknames.remove(deletenick);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,342 +1,105 @@
|
||||||
package buttondevteam.chat.listener;
|
package buttondevteam.chat.listener;
|
||||||
|
|
||||||
import java.util.Map.Entry;
|
import buttondevteam.chat.ChatPlayer;
|
||||||
import java.util.Random;
|
import buttondevteam.chat.ChatUtils;
|
||||||
import java.util.Timer;
|
import buttondevteam.chat.PluginMain;
|
||||||
import java.util.TimerTask;
|
import buttondevteam.chat.commands.ucmds.HistoryCommand;
|
||||||
import java.util.UUID;
|
import buttondevteam.chat.components.flair.FlairComponent;
|
||||||
|
import buttondevteam.chat.components.formatter.FormatterComponent;
|
||||||
import com.palmergames.bukkit.towny.Towny;
|
import buttondevteam.chat.components.towncolors.TownColorComponent;
|
||||||
|
import buttondevteam.core.ComponentManager;
|
||||||
|
import buttondevteam.lib.TBMCChatEvent;
|
||||||
|
import buttondevteam.lib.TBMCCoreAPI;
|
||||||
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
|
import buttondevteam.lib.player.ChromaGamerBase.InfoTarget;
|
||||||
|
import buttondevteam.lib.player.TBMCPlayerGetInfoEvent;
|
||||||
|
import com.google.common.collect.BiMap;
|
||||||
|
import com.google.common.collect.HashBiMap;
|
||||||
|
import net.ess3.api.events.NickChangeEvent;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
|
||||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||||
import org.bukkit.event.player.PlayerChatTabCompleteEvent;
|
import org.bukkit.event.player.PlayerChatTabCompleteEvent;
|
||||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
|
||||||
import org.bukkit.event.player.PlayerMoveEvent;
|
import java.util.Map.Entry;
|
||||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
import java.util.UUID;
|
||||||
import org.bukkit.event.server.ServerCommandEvent;
|
|
||||||
import org.bukkit.help.HelpTopic;
|
|
||||||
import org.bukkit.potion.PotionEffect;
|
|
||||||
import org.bukkit.potion.PotionEffectType;
|
|
||||||
import buttondevteam.chat.ChatPlayer;
|
|
||||||
import buttondevteam.chat.ChatProcessing;
|
|
||||||
import buttondevteam.chat.PluginMain;
|
|
||||||
import buttondevteam.lib.TBMCChatEvent;
|
|
||||||
import buttondevteam.lib.TBMCPlayer;
|
|
||||||
import buttondevteam.lib.TBMCPlayer.InfoTarget;
|
|
||||||
import buttondevteam.lib.chat.Channel;
|
|
||||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
|
||||||
import buttondevteam.lib.TBMCPlayerGetInfoEvent;
|
|
||||||
import com.google.common.collect.BiMap;
|
|
||||||
import com.google.common.collect.HashBiMap;
|
|
||||||
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException;
|
|
||||||
import com.palmergames.bukkit.towny.object.Resident;
|
|
||||||
import com.palmergames.bukkit.towny.object.Town;
|
|
||||||
import com.palmergames.bukkit.towny.object.TownBlock;
|
|
||||||
import com.palmergames.bukkit.towny.object.TownyUniverse;
|
|
||||||
import com.palmergames.bukkit.towny.war.eventwar.War;
|
|
||||||
import com.palmergames.bukkit.towny.object.WorldCoord;
|
|
||||||
import com.vexsoftware.votifier.model.Vote;
|
|
||||||
import com.vexsoftware.votifier.model.VotifierEvent;
|
|
||||||
|
|
||||||
public class PlayerListener implements Listener {
|
public class PlayerListener implements Listener {
|
||||||
/**
|
/**
|
||||||
* Does not contain format codes
|
* Does not contain format codes, lowercased
|
||||||
*/
|
*/
|
||||||
public static BiMap<String, UUID> nicknames = HashBiMap.create();
|
public static final BiMap<String, UUID> nicknames = HashBiMap.create();
|
||||||
|
|
||||||
public static boolean Enable = false;
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
|
||||||
public static int LoginWarningCountTotal = 5;
|
|
||||||
|
|
||||||
public static String NotificationSound;
|
|
||||||
public static double NotificationPitch;
|
|
||||||
|
|
||||||
public static boolean ShowRPTag = false;
|
|
||||||
|
|
||||||
public final static String[] LaughStrings = new String[] { "xd", "lel", "lawl", "kek", "lmao", "hue", "hah" };
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerChat(AsyncPlayerChatEvent event) {
|
public void onPlayerChat(AsyncPlayerChatEvent event) {
|
||||||
if (event.isCancelled())
|
if (event.isCancelled())
|
||||||
return;
|
return;
|
||||||
TBMCChatAPI.SendChatMessage(
|
//The custom event is called in the core, but doesn't cancel the MC event
|
||||||
TBMCPlayer.getPlayer(event.getPlayer()).asPluginPlayer(ChatPlayer.class).CurrentChannel,
|
if (ComponentManager.isEnabled(FormatterComponent.class)) //If not enabled, then let the other plugins deal with the message
|
||||||
event.getPlayer(), event.getMessage());
|
event.setCancelled(true); // The custom event should only be cancelled when muted or similar
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
|
||||||
public void PlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
|
|
||||||
if (event.getMessage().length() < 2)
|
|
||||||
return;
|
|
||||||
int index = event.getMessage().indexOf(" ");
|
|
||||||
ChatPlayer mp = TBMCPlayer.getPlayer(event.getPlayer()).asPluginPlayer(ChatPlayer.class);
|
|
||||||
String cmd = "";
|
|
||||||
if (index == -1) {
|
|
||||||
cmd = event.getMessage().substring(1);
|
|
||||||
for (Channel channel : Channel.getChannels()) {
|
|
||||||
if (cmd.equalsIgnoreCase(channel.Command)) {
|
|
||||||
if (mp.CurrentChannel.equals(channel))
|
|
||||||
mp.CurrentChannel = Channel.GlobalChat;
|
|
||||||
else
|
|
||||||
mp.CurrentChannel = channel;
|
|
||||||
event.getPlayer().sendMessage("§6You are now talking in: §b" + mp.CurrentChannel.DisplayName);
|
|
||||||
event.setCancelled(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cmd = event.getMessage().substring(1, index);
|
|
||||||
for (Channel channel : Channel.getChannels()) {
|
|
||||||
if (cmd.equalsIgnoreCase(channel.Command)) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
Channel c = mp.CurrentChannel;
|
|
||||||
mp.CurrentChannel = channel;
|
|
||||||
event.getPlayer().chat(event.getMessage().substring(index + 1));
|
|
||||||
mp.CurrentChannel = c;
|
|
||||||
} else if (cmd.equalsIgnoreCase("tpahere")) {
|
|
||||||
Player player = Bukkit.getPlayer(event.getMessage().substring(index + 1));
|
|
||||||
if (player != null)
|
|
||||||
player.sendMessage("§b" + event.getPlayer().getDisplayName() + " §bis in this world: "
|
|
||||||
+ event.getPlayer().getWorld().getName());
|
|
||||||
} else if (cmd.equalsIgnoreCase("minecraft:me")) {
|
|
||||||
if (!PluginMain.essentials.getUser(event.getPlayer()).isMuted()) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
String message = event.getMessage().substring(index + 1);
|
|
||||||
for (Player p : PluginMain.GetPlayers())
|
|
||||||
p.sendMessage(String.format("* %s %s", event.getPlayer().getDisplayName(), message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cmd.equalsIgnoreCase("sethome")) { // TODO: Move out?
|
|
||||||
TownyUniverse tu = PluginMain.Instance.TU;
|
|
||||||
try {
|
|
||||||
TownBlock tb = WorldCoord.parseWorldCoord(event.getPlayer()).getTownBlock();
|
|
||||||
if (tb.hasTown()) {
|
|
||||||
Town town = tb.getTown();
|
|
||||||
if (town.hasNation()) {
|
|
||||||
Resident res = tu.getResidentMap().get(event.getPlayer().getName());
|
|
||||||
if (res != null && res.hasTown()) {
|
|
||||||
Town town2 = res.getTown();
|
|
||||||
if (town2.hasNation()) {
|
|
||||||
if (town.getNation().getEnemies().contains(town2.getNation())) {
|
|
||||||
event.getPlayer().sendMessage("§cYou cannot set homes in enemy territory.");
|
|
||||||
event.setCancelled(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (NotRegisteredException e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (cmd.equalsIgnoreCase("home") || cmd.equalsIgnoreCase("tpa") || cmd.equalsIgnoreCase("tp")) {
|
|
||||||
String currentWorld = event.getPlayer().getLocation().getWorld().getName();
|
|
||||||
Location currentLocation = event.getPlayer().getLocation();
|
|
||||||
TownyUniverse universe = Towny.getPlugin(Towny.class).getTownyUniverse();
|
|
||||||
if (TownyUniverse.isWarTime()) {
|
|
||||||
War war = universe.getWarEvent();
|
|
||||||
if (war.isWarZone(
|
|
||||||
new WorldCoord(currentWorld, currentLocation.getBlockX(), currentLocation.getBlockZ()))) {
|
|
||||||
event.getPlayer().sendMessage("§cError: You can't teleport out of a war zone!");
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (cmd.toLowerCase().startsWith("un")) {
|
|
||||||
for (HelpTopic ht : PluginMain.Instance.getServer().getHelpMap().getHelpTopics()) {
|
|
||||||
if (ht.getName().equalsIgnoreCase("/" + cmd))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (PluginMain.permission.has(event.getPlayer(), "tbmc.admin")) {
|
|
||||||
String s = cmd.substring(2);
|
|
||||||
Player target = null;
|
|
||||||
target = Bukkit.getPlayer(event.getMessage().substring(index + 1));
|
|
||||||
if (target == null) {
|
|
||||||
event.getPlayer().sendMessage("§cError: Player not found. (/un" + s + " <player>)");
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
if (target != null) {
|
|
||||||
target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 10 * 20, 5, false, false));
|
|
||||||
for (Player pl : PluginMain.GetPlayers())
|
|
||||||
pl.sendMessage(
|
|
||||||
event.getPlayer().getDisplayName() + " un" + s + "'d " + target.getDisplayName());
|
|
||||||
Bukkit.getServer().getConsoleSender().sendMessage(
|
|
||||||
event.getPlayer().getDisplayName() + " un" + s + "'d " + target.getDisplayName());
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cmd.equalsIgnoreCase("f")) {
|
|
||||||
String[] args = event.getMessage().substring(index + 1).split(" ");
|
|
||||||
if (args.length > 1) {
|
|
||||||
if (args[0].toLowerCase().equals("enemy") && args[1].equalsIgnoreCase("newhaven")) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
event.getPlayer().sendMessage("§cYou are not allowed to set New Haven as your enemy faction.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onTabComplete(PlayerChatTabCompleteEvent e) {
|
public void onTabComplete(PlayerChatTabCompleteEvent e) {
|
||||||
String name = e.getLastToken();
|
String name = e.getLastToken();
|
||||||
for (Entry<String, UUID> nicknamekv : nicknames.entrySet()) {
|
for (Entry<String, UUID> nicknamekv : nicknames.entrySet()) {
|
||||||
if (nicknamekv.getKey().startsWith(name)
|
if (nicknamekv.getKey().startsWith(name.toLowerCase()))
|
||||||
&& !nicknamekv.getKey().equals(Bukkit.getPlayer(nicknamekv.getValue()).getName()))
|
e.getTabCompletions().add(PluginMain.essentials.getUser(Bukkit.getPlayer(nicknamekv.getValue())).getNick(true)); //Tabcomplete with the correct case
|
||||||
e.getTabCompletions().add(nicknamekv.getKey());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean ActiveF = false;
|
|
||||||
public static int FCount = 0;
|
|
||||||
public static ChatPlayer FPlayer = null;
|
|
||||||
private Timer Ftimer;
|
|
||||||
public static int AlphaDeaths;
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerDeath(PlayerDeathEvent e) {
|
|
||||||
if (e.getEntity().getName().equals("Alpha_Bacca44"))
|
|
||||||
AlphaDeaths++;
|
|
||||||
// MinigamePlayer mgp = Minigames.plugin.pdata.getMinigamePlayer(e.getEntity());
|
|
||||||
if (/* (mgp != null && !mgp.isInMinigame()) && */ new Random().nextBoolean()) { // Don't store Fs for NPCs
|
|
||||||
if (Ftimer != null)
|
|
||||||
Ftimer.cancel();
|
|
||||||
ActiveF = true;
|
|
||||||
FCount = 0;
|
|
||||||
FPlayer = TBMCPlayer.getPlayer(e.getEntity().getUniqueId()).asPluginPlayer(ChatPlayer.class);
|
|
||||||
FPlayer.setFDeaths(FPlayer.getFDeaths() + 1);
|
|
||||||
for (Player p : PluginMain.GetPlayers()) {
|
|
||||||
ChatPlayer mp = TBMCPlayer.getPlayerAs(p.getUniqueId(), ChatPlayer.class);
|
|
||||||
mp.PressedF = false;
|
|
||||||
p.sendMessage("§bPress F to pay respects.§r");
|
|
||||||
}
|
|
||||||
Ftimer = new Timer();
|
|
||||||
TimerTask tt = new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (ActiveF) {
|
|
||||||
ActiveF = false;
|
|
||||||
for (Player p : PluginMain.GetPlayers()) {
|
|
||||||
p.sendMessage("§b" + FCount + " " + (FCount == 1 ? "person" : "people")
|
|
||||||
+ " paid their respects.§r");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Ftimer.schedule(tt, 15 * 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public void onVotifierEvent(VotifierEvent event) {
|
|
||||||
Vote vote = event.getVote();
|
|
||||||
PluginMain.Instance.getLogger().info("Vote: " + vote);
|
|
||||||
org.bukkit.OfflinePlayer op = Bukkit.getOfflinePlayer(vote.getUsername());
|
|
||||||
Player p = Bukkit.getPlayer(vote.getUsername());
|
|
||||||
if (op != null) {
|
|
||||||
PluginMain.economy.depositPlayer(op, 50.0);
|
|
||||||
}
|
|
||||||
if (p != null) {
|
|
||||||
p.sendMessage("§bThanks for voting! $50 was added to your account.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerMove(PlayerMoveEvent e) {
|
|
||||||
ChatPlayer mp = TBMCPlayer.getPlayerAs(e.getPlayer(), ChatPlayer.class);
|
|
||||||
if (mp.ChatOnly)
|
|
||||||
e.setCancelled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
|
||||||
public void onPlayerTeleport(PlayerTeleportEvent e) {
|
|
||||||
if (TBMCPlayer.getPlayerAs(e.getPlayer(), ChatPlayer.class).ChatOnly) {
|
|
||||||
e.setCancelled(true);
|
|
||||||
e.getPlayer().sendMessage("§cYou are not allowed to teleport while in chat-only mode.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Channel ConsoleChannel = Channel.GlobalChat;
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
|
||||||
public void onConsoleCommand(ServerCommandEvent event) {
|
|
||||||
if (event.getCommand().length() < 2)
|
|
||||||
return;
|
|
||||||
int index = event.getCommand().indexOf(" ");
|
|
||||||
String cmd = "";
|
|
||||||
if (index == -1) {
|
|
||||||
cmd = event.getCommand();
|
|
||||||
for (Channel channel : Channel.getChannels()) {
|
|
||||||
if (cmd.equalsIgnoreCase(channel.Command)) {
|
|
||||||
if (ConsoleChannel.equals(channel))
|
|
||||||
ConsoleChannel = Channel.GlobalChat;
|
|
||||||
else
|
|
||||||
ConsoleChannel = channel;
|
|
||||||
event.getSender().sendMessage("§6You are now talking in: §b" + ConsoleChannel.DisplayName);
|
|
||||||
event.setCommand("dontrunthiscmd");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cmd = event.getCommand().substring(0, index);
|
|
||||||
for (Channel channel : Channel.getChannels()) {
|
|
||||||
if (cmd.equalsIgnoreCase(channel.Command)) {
|
|
||||||
Channel c = ConsoleChannel;
|
|
||||||
ConsoleChannel = channel;
|
|
||||||
TBMCChatAPI.SendChatMessage(PlayerListener.ConsoleChannel, Bukkit.getConsoleSender(),
|
|
||||||
event.getCommand().substring(index + 1));
|
|
||||||
ConsoleChannel = c;
|
|
||||||
event.setCommand("dontrunthiscmd");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cmd.toLowerCase().startsWith("un")) {
|
|
||||||
for (HelpTopic ht : PluginMain.Instance.getServer().getHelpMap().getHelpTopics()) {
|
|
||||||
if (ht.getName().equalsIgnoreCase("/" + cmd))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String s = cmd.substring(2);
|
|
||||||
Player target = null;
|
|
||||||
target = Bukkit.getPlayer(event.getCommand().substring(index + 1));
|
|
||||||
if (target == null) {
|
|
||||||
event.getSender().sendMessage("§cError: Player not found. (/un" + s + " <player>)");
|
|
||||||
event.setCommand("dontrunthiscmd");
|
|
||||||
}
|
|
||||||
if (target != null) {
|
|
||||||
target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 10 * 20, 5, false, false));
|
|
||||||
for (Player pl : PluginMain.GetPlayers())
|
|
||||||
pl.sendMessage(event.getSender().getName() + " un" + s + "'d " + target.getDisplayName());
|
|
||||||
Bukkit.getServer().getConsoleSender()
|
|
||||||
.sendMessage(event.getSender().getName() + " un" + s + "'d " + target.getDisplayName());
|
|
||||||
event.setCommand("dontrunthiscmd");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onGetInfo(TBMCPlayerGetInfoEvent e) {
|
public void onGetInfo(TBMCPlayerGetInfoEvent e) {
|
||||||
ChatPlayer cp = e.getPlayer().asPluginPlayer(ChatPlayer.class);
|
ChatPlayer cp = e.getPlayer().getAs(ChatPlayer.class);
|
||||||
|
if (cp == null)
|
||||||
|
return;
|
||||||
e.addInfo("Minecraft name: " + cp.getPlayerName());
|
e.addInfo("Minecraft name: " + cp.getPlayerName());
|
||||||
if (cp.getUserName() != null && cp.getUserName().length() > 0)
|
if (cp.UserName.get() != null && cp.UserName.get().length() > 0)
|
||||||
e.addInfo("Reddit name: " + cp.getUserName());
|
e.addInfo("Reddit name: " + cp.UserName.get());
|
||||||
|
if (ComponentManager.isEnabled(FlairComponent.class)) {
|
||||||
final String flair = cp.GetFormattedFlair(e.getTarget() != InfoTarget.MCCommand);
|
final String flair = cp.GetFormattedFlair(e.getTarget() != InfoTarget.MCCommand);
|
||||||
if (flair.length() > 0)
|
if (flair.length() > 0)
|
||||||
e.addInfo("/r/TheButton flair: " + flair);
|
e.addInfo("/r/TheButton flair: " + flair);
|
||||||
e.addInfo("Respect: " + (double) cp.getFCount() / (double) cp.getFDeaths());
|
|
||||||
}
|
}
|
||||||
|
e.addInfo(String.format("Respect: %.2f", cp.getF()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private long lastError = 0;
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerTBMCChat(TBMCChatEvent e) {
|
public void onPlayerTBMCChat(TBMCChatEvent e) {
|
||||||
ChatProcessing.ProcessChat(e.getChannel(), e.getSender(), e.getMessage());
|
try {
|
||||||
|
if (e.isCancelled())
|
||||||
|
return;
|
||||||
|
HistoryCommand.addChatMessage(e.getChatMessage(), e.getChannel());
|
||||||
|
e.setCancelled(FormatterComponent.handleChat(e));
|
||||||
|
} catch (NoClassDefFoundError | Exception ex) { // Weird things can happen
|
||||||
|
if (lastError < System.nanoTime() - 1000L * 1000L * 1000L * 60 * 60 //60 mins
|
||||||
|
&& Bukkit.getOnlinePlayers().size() > 0) { //If there are no players on, display to the first person
|
||||||
|
lastError = System.nanoTime(); //I put the whole thing in the if to protect against race conditions
|
||||||
|
for (Player p : Bukkit.getOnlinePlayers())
|
||||||
|
if (e.shouldSendTo(ChromaGamerBase.getFromSender(p)))
|
||||||
|
p.sendMessage("[" + e.getChannel().displayName.get() + "] §cSome features in the message below might be unavailable due to an error.");
|
||||||
|
}
|
||||||
|
ChatUtils.sendChatMessage(e);
|
||||||
|
TBMCCoreAPI.SendException("An error occured while processing a chat message!", ex, PluginMain.Instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onNickChange(NickChangeEvent e) {
|
||||||
|
String nick = e.getValue();
|
||||||
|
if (nick == null)
|
||||||
|
nicknames.inverse().remove(e.getController().getBase().getUniqueId()); //EssentialsX has it swapped
|
||||||
|
else
|
||||||
|
nicknames.inverse().forcePut(e.getController().getBase().getUniqueId(), ChatColor.stripColor(nick).toLowerCase());
|
||||||
|
|
||||||
|
Bukkit.getScheduler().runTaskLater(PluginMain.Instance, () -> {
|
||||||
|
TownColorComponent.updatePlayerColors(e.getAffected().getBase()); //Won't fire this event again
|
||||||
|
}, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
4
src/main/java/com/palmergames/bukkit/TownyChat/Chat.java
Normal file
4
src/main/java/com/palmergames/bukkit/TownyChat/Chat.java
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
package com.palmergames.bukkit.TownyChat;
|
||||||
|
|
||||||
|
public class Chat {
|
||||||
|
}
|
51
src/main/java/org/dynmap/towny/DTBridge.java
Normal file
51
src/main/java/org/dynmap/towny/DTBridge.java
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
package org.dynmap.towny;
|
||||||
|
|
||||||
|
import lombok.val;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.dynmap.DynmapCommonAPI;
|
||||||
|
import org.dynmap.markers.MarkerAPI;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class DTBridge {
|
||||||
|
/**
|
||||||
|
* Sets the town color on Dynmap.
|
||||||
|
*
|
||||||
|
* @param dtp The Dynmap-Towny plugin
|
||||||
|
* @param townname The name of the town, using correct casing
|
||||||
|
* @param strokecolor The stroke color in RGB format
|
||||||
|
* @param fillcolor The fill color in RGB format
|
||||||
|
* @throws Exception When couldn't set the town color
|
||||||
|
*/
|
||||||
|
public static void setTownColor(Plugin dtp, String townname, int strokecolor, int fillcolor)
|
||||||
|
throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, // Keeping these because why not
|
||||||
|
IllegalAccessException, NoSuchMethodException, InstantiationException, InvocationTargetException {
|
||||||
|
Class<?> cl = Class.forName(DynmapTownyPlugin.class.getName() + "$AreaStyle");
|
||||||
|
Field field = DynmapTownyPlugin.class.getDeclaredField("cusstyle");
|
||||||
|
field.setAccessible(true); // Doesn't allow accessing it from the same package, if it's from a different plugin
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
val map = (Map<String, Object>) field.get(dtp);
|
||||||
|
Object style = map.get(townname);
|
||||||
|
if (style == null) {
|
||||||
|
Constructor<?> c = cl.getDeclaredConstructor(FileConfiguration.class, String.class, MarkerAPI.class);
|
||||||
|
c.setAccessible(true);
|
||||||
|
style = c.newInstance(dtp.getConfig(), "custstyle." + townname,
|
||||||
|
((DynmapCommonAPI) Bukkit.getPluginManager().getPlugin("dynmap")).getMarkerAPI());
|
||||||
|
map.put(townname, style);
|
||||||
|
}
|
||||||
|
set(cl, style, "fillcolor", fillcolor);
|
||||||
|
set(cl, style, "strokecolor", strokecolor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> void set(Class<?> cl, Object style, String fieldname, T value)
|
||||||
|
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||||
|
Field field = cl.getDeclaredField(fieldname);
|
||||||
|
field.setAccessible(true);
|
||||||
|
field.set(style, value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +1,14 @@
|
||||||
name: ButtonChat
|
name: Chroma-Chat
|
||||||
main: buttondevteam.chat.PluginMain
|
main: buttondevteam.chat.PluginMain
|
||||||
version: 4.0
|
version: '${noprefix.version}'
|
||||||
commands:
|
commands:
|
||||||
u:
|
u:
|
||||||
description: Auto-flair system. Accept or ignore flair.
|
description: The main command for Chroma-Chat.
|
||||||
ooc:
|
|
||||||
description: Send message in Out-of-Character.
|
|
||||||
alias: nrp
|
|
||||||
unlol:
|
unlol:
|
||||||
description: Unlaugh the last laugh.
|
description: Unlaugh the last laugh.
|
||||||
alias: unlaugh
|
alias: unlaugh
|
||||||
mwiki:
|
mwiki:
|
||||||
description: Search the wiki.
|
description: Search the wiki.
|
||||||
dontrunthiscmd: null
|
|
||||||
tableflip:
|
tableflip:
|
||||||
description: Flip a table.
|
description: Flip a table.
|
||||||
unflip:
|
unflip:
|
||||||
|
@ -23,19 +19,29 @@ commands:
|
||||||
description: Shrug.
|
description: Shrug.
|
||||||
yeehaw:
|
yeehaw:
|
||||||
description: This command makes you yeehaw.
|
description: This command makes you yeehaw.
|
||||||
|
waitwhat:
|
||||||
|
description: Wait what
|
||||||
|
aliases: ww
|
||||||
|
lenny:
|
||||||
|
description: Lenny face.
|
||||||
|
ftop:
|
||||||
|
description: Top respect.
|
||||||
|
me:
|
||||||
|
description: Me command with Chroma support.
|
||||||
author: NorbiPeti
|
author: NorbiPeti
|
||||||
depend:
|
depend:
|
||||||
- Essentials
|
- Essentials
|
||||||
- Towny
|
|
||||||
- Votifier
|
|
||||||
- WorldGuard
|
|
||||||
- WorldEdit
|
|
||||||
- Vault
|
- Vault
|
||||||
- ButtonCore
|
- Chroma-Core
|
||||||
soft-depend:
|
softdepend:
|
||||||
- Minigames
|
- Dynmap-Towny
|
||||||
|
- Towny
|
||||||
|
- dynmap
|
||||||
permissions:
|
permissions:
|
||||||
tbmc.admin:
|
tbmc.badge.gold:
|
||||||
description: Gives access to /un- commands and /u admin commands
|
description: Gives a patron badge.
|
||||||
tbmc.rainbow:
|
default: false
|
||||||
description: Gives access to rainbow colors (/u c).
|
tbmc.badge.diamond:
|
||||||
|
description: Gives a cool patron badge.
|
||||||
|
default: false
|
||||||
|
api-version: '1.13'
|
||||||
|
|
108
src/test/java/buttondevteam/chat/ObjectTestRunner.java
Normal file
108
src/test/java/buttondevteam/chat/ObjectTestRunner.java
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
package buttondevteam.chat;
|
||||||
|
|
||||||
|
import org.junit.runner.Runner;
|
||||||
|
import org.junit.runner.notification.RunNotifier;
|
||||||
|
import org.junit.runners.BlockJUnit4ClassRunner;
|
||||||
|
import org.junit.runners.Parameterized;
|
||||||
|
import org.junit.runners.Suite;
|
||||||
|
import org.junit.runners.model.FrameworkMethod;
|
||||||
|
import org.junit.runners.model.InitializationError;
|
||||||
|
import org.junit.runners.model.Statement;
|
||||||
|
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}
|
||||||
|
*
|
||||||
|
* @author NorbiPeti
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ObjectTestRunner extends Suite {
|
||||||
|
/**
|
||||||
|
* Annotation for a method which provides parameters to be injected into the test class constructor by <code>Parameterized</code>
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
public @interface Objects {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestClassRunnerForObjects extends BlockJUnit4ClassRunner {
|
||||||
|
|
||||||
|
private List<Object> objectList;
|
||||||
|
private int fParameterSetNumber;
|
||||||
|
|
||||||
|
TestClassRunnerForObjects(Class<?> type, List<Object> objectList, int i) throws InitializationError {
|
||||||
|
super(type);
|
||||||
|
this.objectList = objectList;
|
||||||
|
fParameterSetNumber = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object createTest() throws Exception {
|
||||||
|
return objectList.get(fParameterSetNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getName() {
|
||||||
|
return String.format("[%s]", fParameterSetNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String testName(final FrameworkMethod method) {
|
||||||
|
return String.format("%s[%s]", method.getName(), fParameterSetNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validateConstructor(List<Throwable> errors) {
|
||||||
|
validateOnlyOneConstructor(errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Statement classBlock(RunNotifier notifier) {
|
||||||
|
return childrenInvoker(notifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Annotation[] getRunnerAnnotations() {
|
||||||
|
return new Annotation[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ArrayList<Runner> runners = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only called reflectively. Do not use programmatically.
|
||||||
|
*/
|
||||||
|
public ObjectTestRunner(Class<?> klass) throws Throwable {
|
||||||
|
super(klass, Collections.emptyList());
|
||||||
|
List<Object> objectsList = getObjectsList(getTestClass());
|
||||||
|
for (int i = 0; i < objectsList.size(); i++)
|
||||||
|
runners.add(new TestClassRunnerForObjects(getTestClass().getJavaClass(), objectsList, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<Runner> getChildren() {
|
||||||
|
return runners;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private List<Object> getObjectsList(TestClass klass) throws Throwable {
|
||||||
|
return (List<Object>) getObjectsMethod(klass).invokeExplosively(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FrameworkMethod getObjectsMethod(TestClass testClass) throws Exception {
|
||||||
|
List<FrameworkMethod> methods = testClass.getAnnotatedMethods(Objects.class);
|
||||||
|
for (FrameworkMethod each : methods) {
|
||||||
|
int modifiers = each.getMethod().getModifiers();
|
||||||
|
if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))
|
||||||
|
return each;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception("No public static parameters method on class " + testClass.getName());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
package buttondevteam.chat.components.formatter;
|
||||||
|
|
||||||
|
import buttondevteam.chat.ChatPlayer;
|
||||||
|
import buttondevteam.chat.ChatUtils;
|
||||||
|
import buttondevteam.chat.ObjectTestRunner;
|
||||||
|
import buttondevteam.chat.ObjectTestRunner.Objects;
|
||||||
|
import buttondevteam.chat.PluginMain;
|
||||||
|
import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
|
||||||
|
import buttondevteam.chat.components.formatter.formatting.ChatFormatter;
|
||||||
|
import buttondevteam.chat.components.formatter.formatting.FormatSettings;
|
||||||
|
import buttondevteam.chat.components.formatter.formatting.MatchProviderBase;
|
||||||
|
import buttondevteam.core.MainPlugin;
|
||||||
|
import buttondevteam.core.component.channel.Channel;
|
||||||
|
import buttondevteam.lib.player.ChromaGamerBase;
|
||||||
|
import buttondevteam.lib.test.TestPermissions;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.TextComponent;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static be.seeseemelk.mockbukkit.MockBukkit.load;
|
||||||
|
import static be.seeseemelk.mockbukkit.MockBukkit.mock;
|
||||||
|
import static net.kyori.adventure.text.Component.text;
|
||||||
|
import static net.kyori.adventure.text.event.ClickEvent.Action.OPEN_URL;
|
||||||
|
import static net.kyori.adventure.text.event.ClickEvent.clickEvent;
|
||||||
|
import static net.kyori.adventure.text.event.HoverEvent.Action.SHOW_TEXT;
|
||||||
|
import static net.kyori.adventure.text.event.HoverEvent.hoverEvent;
|
||||||
|
import static net.kyori.adventure.text.format.NamedTextColor.*;
|
||||||
|
import static net.kyori.adventure.text.format.TextDecoration.*;
|
||||||
|
|
||||||
|
@RunWith(ObjectTestRunner.class)
|
||||||
|
public class ChatFormatIT {
|
||||||
|
@Objects
|
||||||
|
public static List<Object> data() {
|
||||||
|
mock();
|
||||||
|
load(MainPlugin.class, true);
|
||||||
|
var sender = ChromaGamerBase.getUser(UUID.randomUUID().toString(), ChatPlayer.class);
|
||||||
|
DebugCommand.DebugMode = true;
|
||||||
|
PluginMain.permission = new TestPermissions();
|
||||||
|
|
||||||
|
List<Object> list = new ArrayList<>();
|
||||||
|
|
||||||
|
list.add(new ChatFormatIT(sender, "*test*", text("test").decorate(ITALIC).color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, "**test**", text("test").decorate(BOLD).color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, "***test***", text("test").decorate(BOLD, ITALIC).color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, "***__test__***", text("test").decorate(BOLD, ITALIC, UNDERLINED).color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, "***__~~test~~__***", text("test").decorate(BOLD, ITALIC, UNDERLINED, STRIKETHROUGH).color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, "¯\\\\\\_(ツ)\\_/¯", text("¯\\_(ツ)_/¯").color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, "https://google.hu/",
|
||||||
|
text("https://google.hu/").color(WHITE).decorate(UNDERLINED)
|
||||||
|
.hoverEvent(hoverEvent(SHOW_TEXT, text("Click to open").color(BLUE)))
|
||||||
|
.clickEvent(clickEvent(OPEN_URL, "https://google.hu/"))));
|
||||||
|
list.add(new ChatFormatIT(sender, "*test", text("*test").color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, "**test*", text("**test*").color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, "***test", text("***test").color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, "Koiiev", text("§bKoiiev§r").color(AQUA)));
|
||||||
|
list.add(new ChatFormatIT(sender, "norbipeti", text("§bNorbiPeti§r").color(AQUA)));
|
||||||
|
list.add(new ChatFormatIT(sender, "Arsen_Derby_FTW", text("§bArsen_Derby_FTW§r").color(AQUA)));
|
||||||
|
list.add(new ChatFormatIT(sender, "carrot_lynx", text("§bcarrot_lynx§r").color(AQUA)));
|
||||||
|
list.add(new ChatFormatIT(sender, "*carrot_lynx*", text("§bcarrot_lynx§r").decorate(ITALIC).color(AQUA)));
|
||||||
|
list.add(new ChatFormatIT(sender, "https://norbipeti.github.io/", text("https://norbipeti.github.io/")
|
||||||
|
.color(WHITE).decorate(UNDERLINED)
|
||||||
|
.hoverEvent(hoverEvent(SHOW_TEXT, text("Click to open").color(BLUE)))
|
||||||
|
.clickEvent(clickEvent(OPEN_URL, "https://norbipeti.github.io/"))));
|
||||||
|
list.add(new ChatFormatIT(sender, "*https://norbipeti.github.io/ heh*", text("https://norbipeti.github.io/").decorate(ITALIC).decorate(UNDERLINED)
|
||||||
|
.hoverEvent(hoverEvent(SHOW_TEXT, text("Click to open").color(BLUE)))
|
||||||
|
.clickEvent(clickEvent(OPEN_URL, "https://norbipeti.github.io/")).color(WHITE), text(" heh").decorate(ITALIC).color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, "*test _test_ test*", text("test test test").decorate(ITALIC).color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, "*test __test__ test*", text("test ").decorate(ITALIC).color(WHITE),
|
||||||
|
text("test").decorate(ITALIC).decorate(UNDERLINED).color(WHITE), text(" test").decorate(ITALIC).color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, "**test __test__ test**", text("test ").decorate(BOLD).color(WHITE),
|
||||||
|
text("test").decorate(BOLD).decorate(UNDERLINED).color(WHITE), text(" test").decorate(BOLD).color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, "**test _test_ test**", text("test ").decorate(BOLD).color(WHITE),
|
||||||
|
text("test").decorate(ITALIC).decorate(BOLD).color(WHITE), text(" test").decorate(BOLD).color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, "https://norbipeti.github.io/test?test&test#test", text("https://norbipeti.github.io/test?test&test#test")
|
||||||
|
.color(WHITE).decorate(UNDERLINED)
|
||||||
|
.hoverEvent(hoverEvent(SHOW_TEXT, text("Click to open").color(BLUE)))
|
||||||
|
.clickEvent(clickEvent(OPEN_URL, "https://norbipeti.github.io/test?test&test#test"))));
|
||||||
|
list.add(new ChatFormatIT(sender, "[hmm](https://norbipeti.github.io/test)", text("hmm")
|
||||||
|
.color(WHITE).decorate(UNDERLINED)
|
||||||
|
.hoverEvent(hoverEvent(SHOW_TEXT, text("Click to open").color(BLUE)))
|
||||||
|
.clickEvent(clickEvent(OPEN_URL, "https://norbipeti.github.io/test"))));
|
||||||
|
var space = text(" ").color(WHITE);
|
||||||
|
list.add(new ChatFormatIT(sender, "A rainbow text for testing. O", text("A").color(RED),
|
||||||
|
space, text("rainbow").color(GOLD), space, text("text").color(YELLOW),
|
||||||
|
space, text("for").color(GREEN), space, text("testing.").color(BLUE),
|
||||||
|
space, text("O").color(DARK_PURPLE)).setRainbowMode());
|
||||||
|
list.add(new ChatFormatIT(sender, "***test*** test", text("test").color(WHITE)
|
||||||
|
.decorate(ITALIC).decorate(BOLD), text(" test").color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, ">test message\nheh", text(">test message\nheh").color(GREEN)));
|
||||||
|
list.add(new ChatFormatIT(sender, "[here's a link]()", text("[here's a link]()").color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, "[](fakelink)", text("[](fakelink)").color(WHITE)));
|
||||||
|
list.add(new ChatFormatIT(sender, "||this is a spoiler||", text("this is a spoiler").color(WHITE)
|
||||||
|
.decorate(OBFUSCATED).hoverEvent(hoverEvent(SHOW_TEXT, text("this is a spoiler")))));
|
||||||
|
Function<String, TextComponent> whiteBoldItalic = text -> text(text).color(WHITE).decorate(BOLD).decorate(ITALIC);
|
||||||
|
list.add(new ChatFormatIT(sender, "***some complicated ||test message|| with [links](https://chromagaming.figytuna.com) and other __greatness__ by NorbiPeti***",
|
||||||
|
whiteBoldItalic.apply("some complicated "),
|
||||||
|
whiteBoldItalic.apply("test message").decorate(OBFUSCATED).hoverEvent(hoverEvent(SHOW_TEXT, text("test message"))),
|
||||||
|
whiteBoldItalic.apply(" with "),
|
||||||
|
whiteBoldItalic.apply("links").clickEvent(clickEvent(OPEN_URL, "https://chromagaming.figytuna.com"))
|
||||||
|
.decorate(UNDERLINED).hoverEvent(hoverEvent(SHOW_TEXT, text("Click to open").color(BLUE))),
|
||||||
|
whiteBoldItalic.apply(" and other "),
|
||||||
|
whiteBoldItalic.apply("greatness").decorate(UNDERLINED),
|
||||||
|
whiteBoldItalic.apply(" by "),
|
||||||
|
whiteBoldItalic.apply("§bNorbiPeti§r").color(AQUA))); //§b: flair color
|
||||||
|
list.add(new ChatFormatIT(sender, "hey @console", text("hey ").color(WHITE),
|
||||||
|
text("@console").color(AQUA)));
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ChromaGamerBase sender;
|
||||||
|
private final String message;
|
||||||
|
private final Component[] extras;
|
||||||
|
private boolean rainbowMode;
|
||||||
|
|
||||||
|
public ChatFormatIT(ChromaGamerBase sender, String message, Component... expectedExtras) {
|
||||||
|
this.sender = sender;
|
||||||
|
this.message = message;
|
||||||
|
this.extras = expectedExtras;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ChatFormatIT setRainbowMode() {
|
||||||
|
rainbowMode = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMessage() {
|
||||||
|
System.out.println("Testing: " + message);
|
||||||
|
ArrayList<MatchProviderBase> cfs = ChatProcessing.addFormatters(p -> true, null);
|
||||||
|
final String chid = ChatProcessing.getChannelID(Channel.globalChat, ChatUtils.MCORIGIN);
|
||||||
|
if (rainbowMode)
|
||||||
|
ChatProcessing.createRPC(WHITE, cfs);
|
||||||
|
final TextComponent.Builder tp = ChatProcessing.createEmptyMessageLine(sender, message, null, chid, ChatUtils.MCORIGIN);
|
||||||
|
ChatFormatter.Combine(cfs, message, tp, null, FormatSettings.builder().color(WHITE).build());
|
||||||
|
final TextComponent.Builder expectedtp = ChatProcessing.createEmptyMessageLine(sender, message, null, chid, ChatUtils.MCORIGIN);
|
||||||
|
for (Component extra : extras)
|
||||||
|
expectedtp.append(extra);
|
||||||
|
Assert.assertEquals(expectedtp.build(), tp.build());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue