Compare commits

..
166 Commits
Author SHA1 Message Date
Elikill58 3fd14b3bdb Upgrade to 2.4.5 2022-10-18 19:40:45 +02:00
Elikill58 6c3784e662 Fix multiple quick issues 2022-10-12 17:27:34 +02:00
Elikill58 6256de065e Change base component 2022-10-03 16:10:59 +02:00
Elikill58 4c1d64f04c Fix v1 detection in v2 2022-09-26 09:20:34 +02:00
Elikill58 4475f19268 Upgrade to snapshot 2022-09-14 15:50:01 +02:00
Elikill58 2b5065dbec Update multiple things into v1 2022-09-14 15:49:27 +02:00
Elikill58 ba54582f7f Fix only first line take in count 2022-08-30 12:31:08 +02:00
Elikill58 2b0de9aa3c Upgrade to 2.4.4 2022-08-26 08:11:55 +02:00
Elikill58 3981992e37 Fix for new packet version 2022-08-24 09:56:51 +02:00
Elikill58 439710086e Fix color and hover 2022-08-12 08:43:51 +02:00
Elikill58 f5381b0430 Fix unknow color code 2022-08-12 08:28:06 +02:00
Elikill58 3cce52953a Make things more global 2022-08-12 08:16:58 +02:00
Elikill58 797de9c602 Fix issue with shulker check 2022-08-08 14:43:23 +02:00
Elikill58 c7f76d9f7b Fix #43 2022-08-08 14:37:28 +02:00
Elikill58 3947ea88d5 Add debug things 2022-07-26 15:56:02 +02:00
Elikill58 cc30049fdf Prevent error with books 2022-07-26 15:54:41 +02:00
Elikill58 7a964bb97c Upgrade to snapshot 2022-07-26 15:50:12 +02:00
Elikill58 13bbf3e5ca Fix first color thing 2022-07-22 12:44:11 +02:00
Elikill58 46de91b2ff Add some messages in config 2022-07-22 11:37:33 +02:00
Elikill58 cb5b3acab0 Add check update in admin inv 2022-07-22 11:36:52 +02:00
Elikill58 6f6d4dc263 Fix hex color 2022-07-22 11:33:29 +02:00
Elikill58 250b119391 Several fix 2022-07-21 23:00:51 +02:00
Elikill58 beee98d5d6 Upgrade to 2.4.3 2022-07-21 17:58:33 +02:00
Elikill58 4d270891be Fix when not using extra 2022-07-21 17:21:37 +02:00
Elikill58 7e9352661e Fix multiple color for same chat line 2022-07-21 17:17:31 +02:00
Elikill58 3f47d56bed Add chatitem broadcast command 2022-07-21 11:27:51 +02:00
Elikill58 1d0cac3a2b Fix chatitem show 2022-07-20 19:31:31 +02:00
Elikill58 64da26ea9f Use protocollib for all versions 2022-07-19 17:18:37 +02:00
Elikill58 4e53b6d5b0 Fix diff for spigot & paper 2022-07-16 09:50:01 +02:00
Elikill58 3b4ede3c22 Fix lib issue 2022-07-15 22:42:50 +02:00
Elikill58 59aade10a7 Prevent higher version 2022-07-15 10:53:05 +02:00
Elikill58 cd5bf7281b Change how color are managed 2022-07-15 10:48:59 +02:00
Elikill58 cd5bd87835 Fix wrong version detection 2022-07-12 21:36:49 +02:00
Elikill58 9384277901 Update few debugger 2022-07-12 19:42:57 +02:00
Elikill58 3b43e647a4 Update color management for v2 2022-07-12 19:34:23 +02:00
Elikill58 f28ad44e62 Fix color code 2022-07-12 18:53:21 +02:00
Elikill58 0baec19db1 Upgrade to snpashot 2022-07-12 18:13:02 +02:00
Elikill58 8ea83b3fab Prevent cooldown 2022-07-12 18:12:17 +02:00
Elikill58 7eaadd9ad6 Fix color 2022-07-08 11:27:05 +02:00
Elikill58 506985c9d1 Fix custom enchants 2022-07-08 10:04:55 +02:00
Elikill58 3fb0181ad7 Wrong char <.< 2022-07-08 09:29:14 +02:00
Elikill58 fc56bb6017 Add command to show item in chat 2022-07-05 23:10:14 +02:00
Elikill58 d9c60f45a4 Quick several fix 2022-07-02 14:32:25 +02:00
Elikill58 342060b86e Upgrade to 2.4.2 2022-06-30 16:10:38 +02:00
Elikill58 b5b30bd9d8 Fix hex color 2022-06-27 18:28:17 +02:00
Elikill58 55eaac0bd4 Update players 2022-06-25 18:27:29 +02:00
Elikill58 7583aeade7 Update constructor 2022-06-25 18:27:04 +02:00
Elikill58 4be3712082 Fix compatibility with old PL 2022-06-23 16:22:51 +02:00
Elikill58 c1e28709ac Fix array as string 2022-06-23 01:01:06 +02:00
Elikill58 f0965efe73 Fix wrong constructor used 2022-06-23 00:20:09 +02:00
Elikill58 529cdd1e04 Second wave to fix with other plugins 2022-06-22 17:35:23 +02:00
Elikill58 ce867d4065 Remove tag for adventure 2022-06-21 17:29:08 +02:00
Elikill58 1eefb78157 Fix adventure not found 2022-06-21 16:44:08 +02:00
Elikill58 ff0c8d2a8d Upgrade to snapshot 2022-06-21 15:29:22 +02:00
Elikill58 5a250d854d Upgrade to 2.4.1 2022-06-15 00:53:36 +02:00
Elikill58 caacf0d8ae Don't use deprecated things 2022-06-15 00:52:18 +02:00
Elikill58 0f7d4a0548 Remove strange char 2022-06-15 00:49:33 +02:00
Elikill58 4529f74f0a Update dependencies 2022-06-15 00:49:06 +02:00
Elikill58 1eaf32983a Fix purpur issue 2022-06-14 10:15:49 +02:00
Elikill58 24b0682e8b Go to snapshot 2022-06-14 09:25:28 +02:00
Elikill58 cbf3326de6 Fix, again 2022-06-13 19:12:40 +02:00
Elikill58 c4ae9198a4 Fix #41 (included in spigot release) 2022-06-13 15:28:15 +02:00
Elikill58 c01798f2e2 Upgrade to 2.4 2022-06-12 20:27:49 +02:00
Elikill58 5de8dbe98a Update item method 2022-06-10 18:01:41 +02:00
Elikill58 00eecd1841 Remove other useless debug 2022-06-10 16:37:00 +02:00
Elikill58 54783d657e Remove useless debug 2022-06-10 16:36:03 +02:00
Elikill58 e17b618b18 Fix v1 packets 2022-06-10 16:30:44 +02:00
Elikill58 3c8371fe28 Fix v2 chat manager for empty items 2022-06-10 14:42:29 +02:00
Elikill58 aafb677d01 Fix channel detection 2022-06-10 11:03:02 +02:00
Elikill58 3a945560a8 If it doesn't works, it's not because of me. Sorry for github msg 2022-06-06 20:57:01 +02:00
Elikill58 516156624e Upgrade maven compiler 2022-06-06 20:45:25 +02:00
Elikill58 b6e37edfa3 Update maven's plugin 2022-06-06 20:30:27 +02:00
Elikill58 6772d26747 Use java version 2022-06-06 20:26:17 +02:00
Elikill58 145ff70e3d Let maven manage own things 2022-06-06 20:24:12 +02:00
Elikill58 cd57c3d37f Change maven copmpiler option 2022-06-06 20:11:18 +02:00
Elikill58 80413bab3a Remove jitpack file and just use maven things 2022-06-06 20:00:59 +02:00
Elikill58 319e70696e Add target java versions 2022-06-06 19:46:20 +02:00
Elikill58 dfda46bcb7 Make jitpack use JDK 17 2022-06-06 19:29:32 +02:00
Elikill58 848a44c5da Finally fix with Kyori adventure messae 2022-06-01 19:01:06 +02:00
Elikill58 48a0666c79 Fix writing issue 2022-06-01 17:15:44 +02:00
Elikill58 d828a747db Possible fix for cmd 2022-06-01 17:02:12 +02:00
Elikill58 7ff7eb20b9 Change how base component is obtained 2022-06-01 16:57:15 +02:00
Elikill58 bae9d14ae5 Add discordSRV as soft dep 2022-05-31 22:44:04 +02:00
Elikill58 9b2fc7da65 Rename method 2022-05-30 13:33:32 +02:00
Elikill58 163686cf77 Fix discord srv message 2022-05-30 12:21:57 +02:00
Elikill58 895fbcf07e Fix ProtocolLib support 2022-05-23 22:14:46 +02:00
Elikill58 004131ddc3 Remove some useless color codes 2022-05-23 22:03:19 +02:00
Elikill58 e59d116918 Prevent some message to be sent multiple times 2022-05-23 17:10:07 +02:00
Elikill58 4ee9d4525a Fix cooldown 2022-05-15 11:11:12 +02:00
Elikill58 3d1672d4ef Upgrade to 2.3 2022-05-11 10:52:34 +02:00
Elikill58 91fc9ee913 Don't use removed class 2022-05-09 19:57:14 +02:00
Elikill58 15604b0ec4 Wtf wrong item 2022-05-08 17:38:37 +02:00
Elikill58 8108b949f7 Refactor of json manipulator 2022-05-06 11:55:36 +02:00
Elikill58 aabaa2a332 Remove wtf file 2022-05-03 22:03:08 +02:00
Elikill58 0896a7c63e Fix packet manager not well working 2022-05-03 22:02:52 +02:00
Elikill58 b4b6b19ec3 Fix limit message wrong triggering 2022-05-03 13:52:12 +02:00
Elikill58 93289f5b24 Fix possible NPE 2022-05-02 12:52:31 +02:00
Elikill58 5810652007 Add EcoEnchants support 2022-04-28 20:50:11 +02:00
Elikill58 1e92763497 Make method generic to fix for cmd in v1 2022-04-23 21:57:37 +02:00
Elikill58 a699c807fd Fix limit not working 2022-04-23 21:49:37 +02:00
Elikill58 7ef48f4202 Move some methods 2022-04-23 21:42:21 +02:00
Elikill58 7dc8042de7 Fix multiple items 2022-04-18 17:13:24 +02:00
Elikill58 9d13bd482c Fix loading managers 2022-04-18 16:50:10 +02:00
outsparkled 306ab41f08 Code cleanups (#39) 2022-04-15 18:17:44 +02:00
Elikill58 aea4950398 Fix error for PR without discord link 2022-04-15 11:24:45 +02:00
Elikill58 042c27c088 Fix building by using own ProtocolSupport build 2022-04-10 19:01:23 +02:00
Elikill58 b699d2ffad Fix object can't be founded 2022-04-10 17:12:11 +02:00
Elikill58 0400b0beaf Fix wrong name of item 2022-03-10 14:37:44 +01:00
Elikill58 88030f82b6 Fix wrong ID for 1.7 clients 2022-03-10 13:42:37 +01:00
Elikill58 e8f8bd5af4 Add way to show item with less informations for bugged clients 2022-03-10 13:39:48 +01:00
Elikill58 bfbcaf1598 Remove some debug messages 2022-03-10 13:07:39 +01:00
Elikill58 ffc57dd69a Clean code specially for json formatting 2022-03-10 13:03:29 +01:00
Elikill58 07fa5c256b Prevent some type of issues 2022-03-10 11:51:25 +01:00
Elikill58 c07357b89b Fix other placeholders 2022-03-10 01:01:40 +01:00
Elikill58 629d492fad Remove unused field 2022-03-10 00:58:00 +01:00
Elikill58 693ca51315 Fix NMU & content modifier 2022-03-10 00:56:36 +01:00
Elikill58 f65444cfe9 Put player as var 2022-03-10 00:30:09 +01:00
Elikill58 464b887ed5 Begin of prevent lunar issue 2022-03-10 00:26:24 +01:00
Elikill58 1bdf20feb0 Deprecated unused class to check in the future if they are useful 2022-03-06 02:00:57 +01:00
Elikill58 db89bfb5b5 Clean JSON use 2022-03-06 01:57:44 +01:00
Elikill58 efe2dd22e9 Use new json manager 2022-03-06 01:46:09 +01:00
Elikill58 144be87448 Upgrade to 2.2.1 2022-02-28 12:30:18 +01:00
Elikill58 217e7316b9 Add jitpack support 2022-02-26 14:10:11 +01:00
CatAndPaste 9bf2900bb5 Hot fix for hex-colored nicknames changed by Essentials-X. After the general hex-colored fix by Elikill58 that fixed 99% of the problem, first character formatting still was off (as you can see on screenshot: https://media.discordapp.net/attachments/171243756849201153/946441326205993010/unknown.png), this was caused by §r added to the begining of the name. I fixed an error by adding check for char 'r' in showItem function (ChatListener.java : 235). (#37) 2022-02-24 19:31:10 +01:00
Elikill58 23640b1772 Fix hex color ... again 2022-02-23 23:45:44 +01:00
Elikill58 fecf35b3a9 Add discord srv support and fix logged messages 2022-02-23 20:42:05 +01:00
Elikill58 8068fe6a7f Fix append for legacy versions 2022-02-23 19:31:23 +01:00
Elikill58 2f21538c76 Possible fix fox colors codes 2022-02-23 17:48:44 +01:00
Elikill58 340cad0b2f Fix item for old spigot version 2022-02-20 23:11:01 +01:00
Elikill58 0c51c73f31 Add option in inv to manage debug mode 2022-02-20 23:08:53 +01:00
Elikill58 717db94dc2 Prefer manage v1 rep if v2 is enabled 2022-02-20 23:02:11 +01:00
Elikill58 51e6708fcb Update which item is showed 2022-02-19 21:59:37 +01:00
Elikill58 a6f22d090a Fix some color for v1 2022-02-19 21:44:32 +01:00
Elikill58 979f39a171 If not comp, try to use chat base comp 2022-02-19 21:38:43 +01:00
Elikill58 0f057720b8 Prevent one method not found on some paper 2022-02-19 19:37:50 +01:00
Elikill58 a4eb8bd8fe Fix duplicated text 2022-02-19 19:21:11 +01:00
Elikill58 38a8f24c9c Add way to find ichatbase comp 2022-02-19 19:09:01 +01:00
Elikill58 82de0cf4dc Fix wrong parsing fields 2022-02-19 19:05:24 +01:00
Elikill58 13fcea5b57 Change how chat manager works 2022-02-19 15:52:35 +01:00
Elikill58 4292871294 Fix items messages (From XeonZ's config) 2022-02-18 11:06:22 +01:00
Elikill58 827c7f92ae Merge branch 'v2' of https://github.com/dadus33-plugins/ChatItem into v2 2022-02-16 16:16:58 +01:00
Elikill58 bcd28eddca Prevent instance error 2022-02-16 15:32:51 +01:00
outsparkled 4d873146dd Fix gson compatibility issues on 1.8 and clean up pom (#36)
* Fix gson compatibility issues on 1.8 and clean up pom

* re-add export_dir
2022-02-15 19:42:33 +01:00
Elikill58 95bcd6ceff Upgrade to v2.2 2022-02-14 21:20:24 +01:00
Elikill58 b596873300 Prevent too many char in color code 2022-02-08 18:37:47 +01:00
Elikill58 0425336f67 Prevent concurrent modifications 2022-02-02 12:17:56 +01:00
Elikill58 1a27bcbec2 Fix hex support with chat manager 2022-01-31 15:19:46 +01:00
Elikill58 17761fb649 Fix enchants issue with json 2022-01-31 14:37:58 +01:00
Elikill58 9b287c5f83 Add option to disable permission and change it 2022-01-31 13:54:36 +01:00
Elikill58 ce44cd7297 Fix for 1.12 only 2022-01-27 19:59:22 +01:00
Elikill58 4ee5a69a28 Edit auto manager 2022-01-26 23:43:09 +01:00
Elikill58 e7f19acc7f Prevent bell not found because of \ 2022-01-26 23:35:48 +01:00
Elikill58 9d557260ae Prevent bell not set 2022-01-26 23:20:53 +01:00
Elikill58 6bbf12182a Add some debugging message 2022-01-26 22:27:37 +01:00
Elikill58 54a582d3eb Prevent issue that show own item 2022-01-26 22:19:18 +01:00
Elikill58 0cbf4edbd1 Prevent ink sack not supported 2022-01-26 22:16:30 +01:00
Elikill58 0d4d8a7bf1 Merge branch 'v2' of https://github.com/dadus33-plugins/ChatItem into v2 2022-01-20 16:33:45 +01:00
Elikill58 332bed1bcb Fix for snapshot new ver message 2022-01-20 16:32:42 +01:00
Elikill58 ecbcbbab12 Go to snapshot 2022-01-20 15:49:23 +01:00
Elikill58 e143dd14bf Make link secret (and invalidate old one) 2022-01-20 15:42:45 +01:00
Elikill58 5234812a49 Change uploaded fild 2022-01-20 01:55:20 +01:00
Elikill58 ec770ddd15 Publish on discord 2022-01-20 01:50:23 +01:00
Elikill58 fbe0538a71 Make auto-run show artifact (#35 from averyanalex/v2)
Make auto-run show artifact
2022-01-11 21:59:02 +01:00
Alex Averyanov fb1027f4a8 Update build workflow 2022-01-11 18:37:58 +03:00
Elikill58 97e6ad4245 Add auto-upload of artifact 2022-01-11 16:11:11 +01:00
Elikill58 2ef74e9166 Upgrade to JDK 16 2022-01-11 12:54:58 +01:00
70 changed files with 3217 additions and 2441 deletions

No files matched your search

+30
View File
@@ -0,0 +1,30 @@
name: Build v2 for PR
on:
pull_request:
branches: [ v2 ]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
name: Checkout repo
- name: Set up JDK 17 (LTS)
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'adopt'
cache: maven
- name: Build with Maven
run: mvn install --file pom.xml
- uses: actions/upload-artifact@v2
name: Upload Artifact
with:
name: ChatItem.jar
path: target/ChatItem-*.jar
+18 -8
View File
@@ -1,26 +1,36 @@
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Build v2
on:
push:
branches: [ v2 ]
pull_request:
branches: [ v2 ]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
name: Checkout repo
- name: Set up JDK 17 (LTS)
uses: actions/setup-java@v2
with:
java-version: '11'
java-version: '17'
distribution: 'adopt'
cache: maven
- name: Build with Maven
run: mvn install --file pom.xml
- uses: actions/upload-artifact@v2
name: Upload Artifact
with:
name: ChatItem.jar
path: target/ChatItem-*.jar
- name: Send file README.md to discord channel
uses: sinshutu/upload-to-discord@master
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
with:
args: target/ChatItem-*.jar
+71 -23
View File
@@ -6,7 +6,7 @@
<groupId>me.dadus33</groupId>
<artifactId>chatitem</artifactId>
<version>2.1</version>
<version>2.4.5</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -45,6 +45,14 @@
<id>elikill-repo</id>
<url>https://repo.eliapp.fr:8081/repository/internal/</url>
</repository>
<repository>
<id>dv8tion</id>
<url>https://m2.dv8tion.net/releases</url>
</repository>
<repository>
<id>Scarsz-Nexus</id>
<url>https://nexus.scarsz.me/content/groups/public/</url>
</repository>
</repositories>
@@ -65,13 +73,20 @@
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.1</version>
<version>2.17.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version>
<version>2.17.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.meowj</groupId>
@@ -82,7 +97,7 @@
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>4.7.0</version>
<version>5.0.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -92,16 +107,16 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.ProtocolSupport</groupId>
<groupId>io.shevchik</groupId>
<artifactId>ProtocolSupport</artifactId>
<version>f34959c331</version>
<version>1.18.2-1-dev</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.53.Final</version>
<scope>compile</scope>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.GeyserMC</groupId>
@@ -118,7 +133,25 @@
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.9.3</version>
<version>4.11.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bungeecord</artifactId>
<version>4.1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.discordsrv</groupId>
<artifactId>discordsrv</artifactId>
<version>1.25.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.willfp</groupId>
<artifactId>EcoEnchants</artifactId>
<version>8.57.2</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -137,29 +170,20 @@
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<version>3.10.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<outputDirectory>${dir}</outputDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<version>3.3.0</version>
<executions>
<execution>
<phase>package</phase>
@@ -168,6 +192,30 @@
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<relocations>
<relocation>
<pattern>com.google.gson</pattern>
<shadedPattern>me.dadus33.libs.gson</shadedPattern>
</relocation>
<relocation>
<pattern>net.kyori.adventure.text.serializer.bungeecord</pattern>
<shadedPattern>me.dadus33.libs.kyori.serializer.bungeecord</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*</artifact>
<excludes>
<exclude>net.kyori:examination-api:**</exclude>
<exclude>net.kyori:examination-string:**</exclude>
<exclude>net.kyori:adventure-platform-api:**</exclude>
<exclude>net.kyori:adventure-text-serializer-legacy:**</exclude>
<exclude>net.kyori:adventure-text-serializer-gson:**</exclude>
<exclude>net.kyori:adventure-platform-facet:**</exclude>
<exclude>net.kyori:adventure-nbt:**</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
@@ -175,10 +223,10 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<outputDirectory>${export_dir}</outputDirectory>
</configuration>
<version>3.2.2</version>
<configuration>
<outputDirectory>${export_dir}</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>
+136 -108
View File
@@ -1,18 +1,6 @@
package me.dadus33.chatitem;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabCompleter;
import org.bukkit.plugin.java.JavaPlugin;
import com.google.common.base.Strings;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.chatmanager.v2.ChatListenerChatManager;
@@ -23,59 +11,34 @@ import me.dadus33.chatitem.itemnamer.NamerManager;
import me.dadus33.chatitem.listeners.InventoryListener;
import me.dadus33.chatitem.listeners.JoinListener;
import me.dadus33.chatitem.playernamer.PlayerNamerManager;
import me.dadus33.chatitem.utils.SemVer;
import me.dadus33.chatitem.utils.Storage;
import me.dadus33.chatitem.utils.Utils;
import me.dadus33.chatitem.utils.Version;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabCompleter;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.*;
public class ChatItem extends JavaPlugin {
public final static int CFG_VER = 13;
public static boolean discordSrvSupport = false, ecoEnchantsSupport = false, hasNewVersion = false;
private static ChatItem instance;
private final String brandChannelName = Version.getVersion().isNewerOrEquals(Version.V1_13) ? "minecraft:brand" : "MC|Brand";
private final List<ChatManager> chatManager = new ArrayList<>();
private Log4jFilter filter;
private Storage storage;
private boolean hasNewVersion = false;
private List<ChatManager> chatManager = new ArrayList<>();
private void chooseManagers() {
this.chatManager.forEach((cm) -> cm.unload(this));
this.chatManager.clear();
String managerName = getStorage().MANAGER;
if(managerName.equalsIgnoreCase("both")) {
this.chatManager.add(new PacketEditingChatManager(this));
this.chatManager.add(new ChatListenerChatManager(this));
getLogger().info("Manager automatically choosed: " + getVisualChatManagers());
} else if(managerName.equalsIgnoreCase("auto")) {
if(getServer().getPluginManager().getPlugin("DeluxeChat") != null && Version.getVersion().isNewerThan(Version.V1_7))
this.chatManager.add(new PacketEditingChatManager(this));
else
this.chatManager.add(new ChatListenerChatManager(this));
getLogger().info("Manager automatically choosed: " + getVisualChatManagers());
} else {
if(managerName.equalsIgnoreCase("packet")) {
this.chatManager.add(new PacketEditingChatManager(this));
getLogger().info("Manager choosed: " + getVisualChatManagers());
} else if(managerName.equalsIgnoreCase("chat")) {
this.chatManager.add(new ChatListenerChatManager(this));
getLogger().info("Manager choosed: " + getVisualChatManagers());
} else {
getLogger().severe("----- WARN -----");
getLogger().severe("Failed to find manager: " + managerName + ".");
getLogger().severe("Please reset your config and/or check wiki for more informations");
getLogger().severe("Using default manager: chat.");
getLogger().severe("----- WARN -----");
this.chatManager.add(new ChatListenerChatManager(this));
}
}
this.chatManager.forEach((cm) -> cm.load(this, getStorage()));
NamerManager.load(this);
PlayerNamerManager.load(this);
}
public static void reload(CommandSender sender) {
ChatItem pl = getInstance();
if(pl.getConfig() == null || pl.getConfig().getKeys(false).isEmpty())
pl.saveDefaultConfig();
if (pl.getConfig().getKeys(false).isEmpty())
pl.saveDefaultConfig();
pl.reloadConfig();
String oldChatManager = pl.storage.MANAGER;
pl.storage = new Storage(pl.getConfig());
@@ -83,89 +46,154 @@ public class ChatItem extends JavaPlugin {
pl.filter.setStorage(pl.storage);
if (!pl.storage.RELOAD_MESSAGE.isEmpty())
sender.sendMessage(pl.storage.RELOAD_MESSAGE);
if(!oldChatManager.equalsIgnoreCase(pl.storage.MANAGER))
sender.sendMessage(ChatColor.GOLD + "Changing the manager with command reloading CAN produce issue. It's mostly suggested to restart after finding the better manager for you.");
if (!oldChatManager.equalsIgnoreCase(pl.storage.MANAGER))
sender.sendMessage(ChatColor.GOLD + "Changing the manager with command reloading CAN produce issue. It's mostly suggested to restart after finding the better manager for you.");
}
public static ChatItem getInstance() {
return instance;
}
public static void debug(String msg) {
if (getInstance().getStorage().DEBUG)
getInstance().getLogger().info("[Debug] " + msg.replace(ChatManager.SEPARATOR, 'S'));
}
private void chooseManagers() {
this.chatManager.forEach((cm) -> cm.unload(this));
this.chatManager.clear();
PluginManager pm = getServer().getPluginManager();
String managerName = getStorage().MANAGER;
switch (managerName.toLowerCase(Locale.ROOT)) {
case "both":
this.chatManager.add(new PacketEditingChatManager(this));
this.chatManager.add(new ChatListenerChatManager(this));
getLogger().info("Manager automatically chosen: " + getVisualChatManagers());
break;
case "auto":
if (getPluginThatRequirePacket().stream().map(pm::getPlugin).anyMatch(Objects::nonNull) && Version.getVersion().isNewerThan(Version.V1_7))
this.chatManager.add(new PacketEditingChatManager(this));
else
this.chatManager.add(new ChatListenerChatManager(this));
getLogger().info("Manager automatically chosen: " + getVisualChatManagers());
break;
case "packet":
this.chatManager.add(new PacketEditingChatManager(this));
getLogger().info("Manager chosen: " + getVisualChatManagers());
break;
case "chat":
this.chatManager.add(new ChatListenerChatManager(this));
getLogger().info("Manager chosen: " + getVisualChatManagers());
break;
default:
getLogger().severe("----- WARN -----");
getLogger().severe("Failed to find manager: " + managerName + ".");
getLogger().severe("Please reset your config and/or check wiki for more information");
getLogger().severe("Using default manager: chat.");
getLogger().severe("----- WARN -----");
this.chatManager.add(new ChatListenerChatManager(this));
break;
}
this.chatManager.forEach((cm) -> cm.load(this, getStorage()));
NamerManager.load(this);
PlayerNamerManager.load(this);
}
private List<String> getPluginThatRequirePacket() {
return Arrays.asList("DeluxeChat", "HexNicks", "VentureChat");
}
@Override
public void onEnable() {
//Save the instance (we're basically a singleton)
instance = this;
//Load ProtocolManager
//pm = ProtocolLibrary.getProtocolManager();
getLogger().info("Detected server version: " + Version.getVersion().name().toLowerCase());
//Load config
saveDefaultConfig();
storage = new Storage(getConfig());
//We halt the use of this system for now, until we can solve the infamous getProtocolVersion issue
//Till then, users of both ViaVersion and ProtocolSupport should do just fine
/*if(!protocolSupport && !viaVersion) {
//We only implement our own way of getting protocol versions if we have no other choice
pm.addPacketListener(new HandshakeListener(this, ListenerPriority.MONITOR, PacketType.Handshake.Client.SET_PROTOCOL));
}*/
//Commands
loadCommand(getCommand("cireload"), new CIReloadCommand());
loadCommand(getCommand("chatitem"), new ChatItemCommand());
// events
getServer().getPluginManager().registerEvents(new JoinListener(), this);
getServer().getPluginManager().registerEvents(new InventoryListener(), this);
PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new JoinListener(), this);
pm.registerEvents(new InventoryListener(), this);
chooseManagers();
//Initialize Log4J filter (remove ugly console messages)
filter = new Log4jFilter(storage);
StringJoiner plugins = new StringJoiner(", ");
if (pm.getPlugin("DiscordSRV") != null) {
discordSrvSupport = true;
plugins.add("DiscordSRV");
}
if (pm.getPlugin("EcoEnchants") != null) {
ecoEnchantsSupport = true;
plugins.add("EcoEnchants");
}
if(plugins.length() > 0)
getLogger().info("Load " + plugins.toString() + " support.");
if(storage.CHECK_UPDATE) {
getServer().getScheduler().runTaskAsynchronously(this, () -> {
String urlName = "https://api.spigotmc.org/legacy/update.php?resource=19064";
String content = Utils.getFromURL(urlName);
if(!Strings.isNullOrEmpty(content)) {
hasNewVersion = !content.equalsIgnoreCase(getDescription().getVersion());
if(hasNewVersion) {
getLogger().info(storage.JOIN_UPDATE_MESSAGE);
}
}
});
getServer().getMessenger().registerIncomingPluginChannel(this, brandChannelName, (chan, p, msg) -> {
String client = new String(msg).substring(1);
ChatItem.debug("Detected client " + client + " for " + p.getName());
ItemPlayer.getPlayer(p).setClientName(client);
});
if (storage.CHECK_UPDATE) {
getServer().getScheduler().runTaskAsynchronously(this, () -> {
String urlName = "https://api.spigotmc.org/legacy/update.php?resource=19064";
String content = Utils.getFromURL(urlName);
if (Strings.isNullOrEmpty(content))
return;
SemVer currentVersion = SemVer.parse(getDescription().getVersion());
if (currentVersion == null)
return;
SemVer latestVersion = SemVer.parse(content);
if (latestVersion != null && latestVersion.isNewerThan(currentVersion)) {
hasNewVersion = !content.equalsIgnoreCase(getDescription().getVersion());
if (hasNewVersion) {
getLogger().info(storage.JOIN_UPDATE_MESSAGE);
}
}
});
}
}
public void loadCommand(PluginCommand cmd, Object obj) {
if(obj instanceof CommandExecutor)
cmd.setExecutor((CommandExecutor) obj);
if(obj instanceof TabCompleter)
cmd.setTabCompleter((TabCompleter) obj);
}
public Storage getStorage() {
return storage;
}
public List<ChatManager> getChatManager() {
return chatManager;
}
public String getVisualChatManagers() {
StringJoiner sj = new StringJoiner(", ");
for(ChatManager cm : chatManager) {
sj.add(cm.getName() + " (" + cm.getId() + ")");
}
return sj.toString();
public void loadCommand(PluginCommand cmd, Object obj) {
if (obj instanceof CommandExecutor)
cmd.setExecutor((CommandExecutor) obj);
if (obj instanceof TabCompleter)
cmd.setTabCompleter((TabCompleter) obj);
}
public Storage getStorage() {
return storage;
}
public List<ChatManager> getChatManager() {
return chatManager;
}
public String getVisualChatManagers() {
StringJoiner sj = new StringJoiner(", ");
for (ChatManager cm : chatManager) {
sj.add(cm.getName() + " (" + cm.getId() + ")");
}
return sj.toString();
}
public boolean isHasNewVersion() {
return hasNewVersion;
}
public static void debug(String msg) {
if(getInstance().getConfig().getBoolean("debug", false))
getInstance().getLogger().info(msg);
return hasNewVersion;
}
}
@@ -0,0 +1,83 @@
package me.dadus33.chatitem;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.playerversion.PlayerVersionManager;
import me.dadus33.chatitem.utils.Version;
public class ItemPlayer {
private static final ConcurrentHashMap<UUID, ItemPlayer> PLAYERS = new ConcurrentHashMap<>();
public static ItemPlayer getPlayer(Player p) {
return PLAYERS.computeIfAbsent(p.getUniqueId(), ItemPlayer::new);
}
public static ItemPlayer getPlayer(UUID uuid) {
return PLAYERS.computeIfAbsent(uuid, ItemPlayer::new);
}
private final UUID uuid;
private int protocolVersion = 0;
private Version version = null;
private String clientName = "unknow";
public ItemPlayer(UUID uuid) {
this.uuid = uuid;
Player p = Bukkit.getPlayer(uuid);
if(p != null)
setVersion(PlayerVersionManager.getPlayerVersionAdapter().getPlayerVersion(p));
}
public UUID getUUID() {
return uuid;
}
public Player getPlayer() {
return Bukkit.getPlayer(uuid);
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public int getProtocolVersion() {
if(protocolVersion == 0)
setProtocolVersion(PlayerVersionManager.getPlayerVersionAdapter().getProtocolVersion(getPlayer()));
return protocolVersion;
}
public void setProtocolVersion(int protocolVersion) {
this.protocolVersion = protocolVersion;
if(version == Version.getVersion()) {// if is default
version = Version.getVersion(protocolVersion);
ChatItem.debug("Detected version " + version.name() + " (protocol: " + protocolVersion + ")");
}
}
public Version getVersion() {
if(version == null)
setVersion(PlayerVersionManager.getPlayerVersionAdapter().getPlayerVersion(getPlayer()));
return version;
}
public void setVersion(Version version) {
this.version = version;
if(protocolVersion == 0)
this.protocolVersion = version.MAX_VER;
}
public boolean isBuggedClient() {
return getVersion().equals(Version.V1_7) && getClientName().toLowerCase().contains("lunarclient");
}
@Override
public String toString() {
return "ItemPlayer[uuid=" + uuid + ",name=" + (getPlayer() != null ? getPlayer().getName() : "-") + ",version=" + version.name() + ",protocol=" + protocolVersion + ",client=" + clientName + "]";
}
}
@@ -1,29 +1,315 @@
package me.dadus33.chatitem.chatmanager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import javax.annotation.Nullable;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.hook.EcoEnchantsSupport;
import me.dadus33.chatitem.itemnamer.NamerManager;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.Storage;
import me.dadus33.chatitem.utils.Utils;
public abstract class ChatManager {
private final static HashMap<UUID, Long> COOLDOWNS = new HashMap<>();
private final static HashMap<UUID, Long> LAST_INFO_MESSAGE = new HashMap<>();
private final static String NAME = "{name}";
private final static String AMOUNT = "{amount}";
private final static String TIMES = "{times}";
private final static String LEFT = "{remaining}";
public final static char SEPARATOR = ((char) 0x0007);
protected Storage s;
public ChatManager() {
public final static String SEPARATOR_STR = "\\u0007";
public static String fixSeparator(String s) {
return s.replace(ChatManager.SEPARATOR_STR, Character.toString(ChatManager.SEPARATOR));
}
public static boolean equalsSeparator(String s) {
return s.equalsIgnoreCase(SEPARATOR_STR) || s.equalsIgnoreCase(Character.toString(SEPARATOR));
}
public static boolean containsSeparator(String s) {
return s.contains(SEPARATOR_STR) || s.contains(Character.toString(SEPARATOR));
}
public static boolean endsWithSeparator(String s) {
return s.endsWith(SEPARATOR_STR) || s.endsWith(Character.toString(SEPARATOR));
}
public static String[] splitWithSeparator(String msg) {
List<String> list = new ArrayList<>();
String current = "";
for(String s : msg.split("")) {
if(equalsSeparator(s)) {
if(!current.isEmpty())
list.add(current);
current = "";
} else
current += s;
}
if(!current.isEmpty())
list.add(current);
return list.toArray(new String[] {});
}
protected Storage s;
public ChatManager() {
}
public abstract String getName();
public abstract String getId();
public Storage getStorage() {
return s;
}
public void load(ChatItem pl, Storage s) {
this.s = s;
}
public abstract void unload(ChatItem pl);
/**
* Get the item in hand as usable one.<br>
* Will include, in lore, all informations from other plugins.
*
* @param p the player
* @return the usable item
*/
public static ItemStack getUsableItem(Player p) {
ItemStack item = HandItem.getBetterItem(p).clone();
if(ChatItem.ecoEnchantsSupport) {
List<String> addLore = EcoEnchantsSupport.getLores(item);
if(!addLore.isEmpty()) {
ItemMeta meta = item.getItemMeta();
List<String> lores = meta.hasLore() ? meta.getLore() : new ArrayList<>();
for(int i = 0; i < addLore.size(); i++)
lores.add(i, addLore.get(i));
meta.setLore(lores);
item.setItemMeta(meta);
ChatItem.debug("Added " + addLore.size() + " lores from EcoEnchants");
} else
ChatItem.debug("No lore to add from EcoEnchants");
}
return item;
}
/**
* Get all lores lines of an item, to replace the show_item action which is not working with ViaBackwards
*
* @param item the item to get lines from
* @return all lores
*/
public static List<String> getMaxLinesFromItem(Player p, ItemStack item) {
List<String> lines = new ArrayList<>();
if (item.hasItemMeta()) {
ItemMeta meta = item.getItemMeta();
lines.add(meta.hasDisplayName() ? meta.getDisplayName()
: NamerManager.getName(p, item, ChatItem.getInstance().getStorage()));
if (meta.hasEnchants()) {
meta.getEnchants().forEach((enchant, lvl) -> {
lines.add(ChatColor.RESET + Utils.getEnchantName(enchant) + " " + Utils.toRoman(lvl));
});
}
if (meta.hasLore())
lines.addAll(meta.getLore());
} else {
lines.add(NamerManager.getName(p, item, ChatItem.getInstance().getStorage()));
}
return lines;
}
/**
* Get the name of item according to player & config<br>
* Prefer use {@link #getNameOfItem(Player, ItemStack, Storage)} if you want take in count the empty item
*
* @param p the player
* @param item the item
* @param c the config
* @return the name of item
*/
public static String styleItem(Player p, ItemStack item, Storage c) {
String replacer = c.NAME_FORMAT;
String amount = c.AMOUNT_FORMAT;
boolean dname = item.hasItemMeta() && item.getItemMeta().hasDisplayName();
if (item.getAmount() == 1) {
if (c.FORCE_ADD_AMOUNT) {
amount = amount.replace(TIMES, "1");
replacer = replacer.replace(AMOUNT, amount);
} else {
replacer = replacer.replace(AMOUNT, "");
}
} else {
amount = amount.replace(TIMES, String.valueOf(item.getAmount()));
replacer = replacer.replace(AMOUNT, amount);
}
if (dname) {
String trp = item.getItemMeta().getDisplayName();
ChatItem.debug("trp: " + trp);
if (c.COLOR_IF_ALREADY_COLORED) {
replacer = replacer.replace(NAME, ChatColor.stripColor(trp));
} else {
replacer = replacer.replace(NAME, trp);
}
} else {
replacer = replacer.replace(NAME, NamerManager.getName(p, item, c));
}
return replacer;
}
/**
* Get the name of item according to player & config
*
* @param p the player
* @param item the item
* @param c the config
* @return the name of item or hand
*/
public static String getNameOfItem(Player p, ItemStack item, Storage c) {
if(ItemUtils.isEmpty(item)) {
if(c.HAND_DISABLED)
return c.PLACEHOLDERS.get(0);
else
return c.HAND_NAME;
}
String replacer = c.NAME_FORMAT;
String amount = c.AMOUNT_FORMAT;
boolean dname = item.hasItemMeta() && item.getItemMeta().hasDisplayName();
if (item.getAmount() == 1) {
if (c.FORCE_ADD_AMOUNT) {
amount = amount.replace(TIMES, "1");
replacer = replacer.replace(AMOUNT, amount);
} else {
replacer = replacer.replace(AMOUNT, "");
}
} else {
amount = amount.replace(TIMES, String.valueOf(item.getAmount()));
replacer = replacer.replace(AMOUNT, amount);
}
if (dname) {
String trp = item.getItemMeta().getDisplayName();
if (c.COLOR_IF_ALREADY_COLORED) {
replacer = replacer.replace(NAME, ChatColor.stripColor(trp));
} else {
replacer = replacer.replace(NAME, trp);
}
} else {
replacer = replacer.replace(NAME, NamerManager.getName(p, item, c));
}
return replacer;
}
public static String calculateTime(long seconds) {
Storage c = ChatItem.getInstance().getStorage();
if (seconds < 60) {
return seconds + c.SECONDS;
}
if (seconds < 3600) {
StringBuilder builder = new StringBuilder();
int minutes = (int) seconds / 60;
builder.append(minutes).append(c.MINUTES);
int secs = (int) seconds - minutes * 60;
if (secs != 0) {
builder.append(" ").append(secs).append(c.SECONDS);
}
return builder.toString();
}
StringBuilder builder = new StringBuilder();
int hours = (int) seconds / 3600;
builder.append(hours).append(c.HOURS);
int minutes = (int) (seconds / 60) - (hours * 60);
if (minutes != 0) {
builder.append(" ").append(minutes).append(c.MINUTES);
}
int secs = (int) (seconds - ((seconds / 60) * 60));
if (secs != 0) {
builder.append(" ").append(secs).append(c.SECONDS);
}
return builder.toString();
}
public static boolean canShowItem(Player p, ItemStack item, @Nullable Cancellable e) {
Storage c = ChatItem.getInstance().getStorage();
if (c.PERMISSION_ENABLED && !p.hasPermission(c.PERMISSION_NAME)) {
if (!c.LET_MESSAGE_THROUGH) {
if(e != null)
e.setCancelled(true);
}
if (!c.NO_PERMISSION_MESSAGE.isEmpty() && c.SHOW_NO_PERM_NORMAL) {
sendIfNeed(p, c.NO_PERMISSION_MESSAGE);
}
return false;
}
if (item.getType().equals(Material.AIR)) {
if (c.DENY_IF_NO_ITEM) {
if(e != null)
e.setCancelled(true);
if (!c.DENY_MESSAGE.isEmpty())
sendIfNeed(p, c.DENY_MESSAGE);
return false;
}
if (c.HAND_DISABLED) {
return false;
}
}
if (c.COOLDOWN > 0 && !p.hasPermission("chatitem.ignore-cooldown")) {
if (COOLDOWNS.containsKey(p.getUniqueId())) {
long start = COOLDOWNS.get(p.getUniqueId());
long current = System.currentTimeMillis() / 1000;
long elapsed = current - start;
if (elapsed >= c.COOLDOWN) {
COOLDOWNS.remove(p.getUniqueId());
} else {
if (!c.LET_MESSAGE_THROUGH) {
if(e != null)
e.setCancelled(true);
}
if (!c.COOLDOWN_MESSAGE.isEmpty()) {
long left = (start + c.COOLDOWN) - current;
sendIfNeed(p, c.COOLDOWN_MESSAGE.replace(LEFT, ChatManager.calculateTime(left)));
}
ChatItem.debug("Cooldown");
return false;
}
}
}
LAST_INFO_MESSAGE.put(p.getUniqueId(), System.currentTimeMillis()); // prevent showing item then send cooldown error message
return true;
}
private static void sendIfNeed(Player p, String msg) {
Long time = LAST_INFO_MESSAGE.remove(p.getUniqueId());
if(time != null) {
long diff = System.currentTimeMillis() - time;
if(diff < 100)
return; // don't show message
}
p.sendMessage(msg);
LAST_INFO_MESSAGE.put(p.getUniqueId(), System.currentTimeMillis());
}
public static void clear(Player p) {
COOLDOWNS.remove(p.getUniqueId());
LAST_INFO_MESSAGE.remove(p.getUniqueId());
}
public static void applyCooldown(Player p) {
COOLDOWNS.put(p.getUniqueId(), System.currentTimeMillis() / 1000);
}
}
@@ -0,0 +1,22 @@
package me.dadus33.chatitem.chatmanager;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.Version;
public class HandItem {
@SuppressWarnings("deprecation")
public static ItemStack getBetterItem(Player p) {
if(Version.getVersion().isNewerOrEquals(Version.V1_9)) {
ItemStack main = p.getInventory().getItemInMainHand();
if(!ItemUtils.isEmpty(main))
return main;
ItemStack off = p.getInventory().getItemInOffHand();
return ItemUtils.isEmpty(off) ? main : off;
}
return p.getItemInHand();
}
}
@@ -1,23 +1,19 @@
package me.dadus33.chatitem.chatmanager.v1;
import java.lang.reflect.Constructor;
import org.bukkit.Bukkit;
import org.bukkit.event.HandlerList;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulator;
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulatorCurrent;
import me.dadus33.chatitem.chatmanager.v1.listeners.v15lower.ChatEventListener;
import me.dadus33.chatitem.chatmanager.v1.listeners.v15lower.ChatPacket15Manager;
import me.dadus33.chatitem.chatmanager.v1.listeners.v16upper.ChatPacket16Manager;
import me.dadus33.chatitem.chatmanager.v1.listeners.ChatEventListener;
import me.dadus33.chatitem.chatmanager.v1.listeners.ChatPacketManager;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacketManager;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketHandler;
import me.dadus33.chatitem.chatmanager.v1.playerversion.IPlayerVersion;
import me.dadus33.chatitem.chatmanager.v1.playerversion.hooks.DefaultVersionHook;
import me.dadus33.chatitem.chatmanager.v1.playerversion.hooks.ProtocolSupportHook;
import me.dadus33.chatitem.chatmanager.v1.playerversion.hooks.ViaVersionHook;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketManager;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.Storage;
import me.dadus33.chatitem.utils.Version;
public class PacketEditingChatManager extends ChatManager {
@@ -25,79 +21,76 @@ public class PacketEditingChatManager extends ChatManager {
private boolean baseComponentAvailable = true;
private final ChatItemPacketManager packetManager;
private final ChatEventListener chatEventListener;
private final PacketHandler chatPacketManager;
private IPlayerVersion playerVersionAdapter;
private final ChatPacketManager chatPacketManager;
public PacketEditingChatManager(ChatItem pl) {
jsonManipulator = new JSONManipulatorCurrent();
packetManager = new ChatItemPacketManager(pl);
if(Version.getVersion().isNewerOrEquals(Version.V1_16)) {
chatPacketManager = new ChatPacket16Manager(this);
chatEventListener = null;
} else {
chatEventListener = new ChatEventListener(this);
chatPacketManager = new ChatPacket15Manager(this);
}
//Check for existence of BaseComponent class (only on spigot)
try {
Class.forName("net.md_5.bungee.api.chat.BaseComponent");
} catch (ClassNotFoundException e) {
baseComponentAvailable = false;
}
packetManager = new ChatItemPacketManager(pl);
chatEventListener = new ChatEventListener(this);
chatPacketManager = new ChatPacketManager(this);
// Check for existence of BaseComponent class (only on spigot)
try {
Class.forName("net.md_5.bungee.api.chat.BaseComponent");
} catch (ClassNotFoundException e) {
baseComponentAvailable = false;
}
}
@Override
public String getName() {
return "PacketEditing";
}
@Override
public String getId() {
return "packet";
}
@Override
public void load(ChatItem pl, Storage s) {
super.load(pl, s);
if(chatEventListener != null)
Bukkit.getPluginManager().registerEvents(chatEventListener, pl);
packetManager.getPacketManager().addHandler(chatPacketManager);
if(Bukkit.getPluginManager().getPlugin("ViaVersion") != null){
playerVersionAdapter = new ViaVersionHook();
pl.getLogger().info("Loading ViaVersion support ...");
} else if(Bukkit.getPluginManager().getPlugin("ProtocolSupport") != null){
playerVersionAdapter = new ProtocolSupportHook();
pl.getLogger().info("Loading ProtocolSupport support ...");
} else {
playerVersionAdapter = new DefaultVersionHook();
}
Bukkit.getPluginManager().registerEvents(chatEventListener, pl);
PacketManager pm = packetManager.getPacketManager();
pm.addHandler(chatPacketManager);
Bukkit.getOnlinePlayers().forEach(pm::addPlayer); // add actual online players
}
@Override
public void unload(ChatItem pl) {
if(chatEventListener != null)
HandlerList.unregisterAll(chatEventListener);
packetManager.getPacketManager().removeHandler(chatPacketManager);
packetManager.getPacketManager().stop();
}
public JSONManipulator getManipulator(){
/*
We used to have 2 kinds of JSONManipulators because of my bad understanding of the 1.7 way of parsing JSON chat
The interface should however stay as there might be great changes in future versions in JSON parsing (most likely 1.13)
*/
return jsonManipulator;
//We just return a new one whenever requested for the moment, should implement a cache of some sort some time though
}
public IPlayerVersion getPlayerVersionAdapter() {
return playerVersionAdapter;
HandlerList.unregisterAll(chatEventListener);
PacketManager pm = packetManager.getPacketManager();
pm.removeHandler(chatPacketManager);
pm.stop();
}
public boolean supportsChatComponentApi(){
return baseComponentAvailable;
}
public JSONManipulatorCurrent getManipulator() {
return jsonManipulator;
}
public boolean supportsChatComponentApi() {
return baseComponentAvailable;
}
public static Object createSystemChatPacket(String json) throws Exception {
Class<?> packetClass = PacketUtils.getNmsClass("ClientboundSystemChatPacket", "network.protocol.game.");
for (Constructor<?> cons : packetClass.getDeclaredConstructors()) {
if (!cons.isAccessible())
cons.setAccessible(true);
if (cons.getParameterCount() == 2 && cons.getParameterTypes()[0].equals(String.class)
&& cons.getParameterTypes()[1].equals(int.class)) { // "string, int"
return cons.newInstance(json, 1);
} else if (cons.getParameterCount() == 3 && cons.getParameterTypes()[1].equals(String.class)) { // "component", "string", <something not checked>
Class<?> secondParam = cons.getParameterTypes()[2];
if(secondParam.equals(int.class)) // "component", "string", "int"
return cons.newInstance(null, json, 1);
else if(secondParam.equals(boolean.class)) // "component", "string", "boolean"
return cons.newInstance(null, json, false);
}
}
ChatItem.getInstance().getLogger()
.warning("Can't create a new packet for json " + json + ": no constructor found.");
return null;
}
}
@@ -0,0 +1,188 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp;
import javax.annotation.Nullable;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.utils.Storage;
public interface IBaseComponentGetter {
default boolean hasConditions() {
return true;
}
String getBaseComponentAsJSON(ChatItemPacket packet);
void writeJson(ChatItemPacket packet, String json);
/**
* Use actual base component getter to check if the given json has placeholders
*
* @param c the storage config
* @param json the json
* @return the founded placeholder or null
*/
default @Nullable String hasPlaceholders(Storage c, String json) {
if(json == null || json.isEmpty())
return null;
String placeholder = hasPlaceholdersSpecificMessage(c, json);
if(placeholder != null)
return placeholder;
try {
JsonObject jsonObj = JsonParser.parseString(json).getAsJsonObject();
if(!jsonObj.has("extra"))
return null;
for(JsonElement element : jsonObj.get("extra").getAsJsonArray()) {
if(element.isJsonObject()) {
JsonObject withObj = element.getAsJsonObject();
if(withObj.has("extra")) {
String text = "";
for(JsonElement extra : withObj.get("extra").getAsJsonArray()) {
if(extra.isJsonObject()) {
JsonObject extraObj = extra.getAsJsonObject();
if(extraObj.has("text") && extraObj.get("text").isJsonPrimitive())
text += extraObj.get("text").getAsString();
}
}
placeholder = hasPlaceholdersSpecificMessage(c, text);
if(placeholder != null)
return placeholder;
} else if(withObj.has("text")) {
placeholder = hasPlaceholdersSpecificMessage(c, withObj.get("text").getAsString());
if(placeholder != null)
return placeholder;
}
} // ignoring all others because it should not appear
}
} catch (Exception e) {} // not JSON
return null;
}
default @Nullable String hasPlaceholdersSpecificMessage(Storage c, String json) {
if(json == null || json.isEmpty())
return null;
for (String rep : c.PLACEHOLDERS) {
if (json.contains(rep)) {
return rep;
}
}
return null;
}
default @Nullable String getNameFromMessage(String json, String toReplace) {
String checkedName = getNameFromSpecificMessage(json, toReplace);
if(checkedName != null)
return checkedName;
try {
JsonObject jsonObj = JsonParser.parseString(json).getAsJsonObject();
if(!jsonObj.has("extra"))
return null;
String text = "";
for(JsonElement element : jsonObj.get("extra").getAsJsonArray()) {
if(element.isJsonObject()) {
JsonObject withObj = element.getAsJsonObject();
if(withObj.has("extra")) {
for(JsonElement extra : withObj.get("extra").getAsJsonArray()) {
if(extra.isJsonObject()) {
JsonObject extraObj = extra.getAsJsonObject();
if(extraObj.has("text") && extraObj.get("text").isJsonPrimitive())
text += extraObj.get("text").getAsString();
}
}
} else if(withObj.has("text")) {
text += withObj.get("text").getAsString();
}
} // ignoring all others because it should not appear
}
String possibleName = getNameFromSpecificMessage(text, toReplace);
if(possibleName != null)
return possibleName;
} catch (Exception e) {} // not JSON
return null;
}
default @Nullable String getNameFromSpecificMessage(String json, String toReplace) {
for (Player p : Bukkit.getOnlinePlayers()) {
String name = toReplace + p.getName();
if (json.contains(name))
return p.getName();
}
return null;
}
/**
* Use actual base component getter to remove the player and the name.<br>
* This is for special component which split message into sub string
*
* @param json the global json
* @param toReplace the string which contains the placeholder
* @param foundedPlayer the player which has the name in message
* @return the replaced json
*/
default String removePlaceholdersAndName(String json, String toReplace, Player foundedPlayer) {
String remove = toReplace + foundedPlayer.getName();
boolean firstRemove = true;
try {
JsonObject jsonObj = JsonParser.parseString(json).getAsJsonObject();
if(!jsonObj.has("extra")) {
ChatItem.debug("[IBase] No extra in json");
return json.replace(remove, Character.toString(ChatManager.SEPARATOR));
}
JsonArray extraArray = jsonObj.get("extra").getAsJsonArray();
for(int i = 0; i < extraArray.size(); i++) {
JsonElement element = extraArray.get(i);
if(element.isJsonObject()) {
JsonObject withObj = element.getAsJsonObject();
if(withObj.has("extra")) {
for(JsonElement extra : withObj.get("extra").getAsJsonArray()) {
if(extra.isJsonObject()) {
JsonObject extraObj = extra.getAsJsonObject();
if(extraObj.has("text") && extraObj.get("text").isJsonPrimitive()) {
String s = extraObj.get("text").getAsString();
if(remove.startsWith(s)) {
extraObj.addProperty("text", firstRemove ? Character.toString(ChatManager.SEPARATOR) : "");
firstRemove = false;
remove = remove.substring(s.length());
if(remove.isEmpty())
return jsonObj.toString();
}
}
}
}
} else if(withObj.has("text")) {
String s = withObj.get("text").getAsString();
if(remove.startsWith(s)) {
withObj.addProperty("text", firstRemove ? Character.toString(ChatManager.SEPARATOR) : "");
firstRemove = false;
remove = remove.substring(s.length());
if(remove.isEmpty())
return jsonObj.toString();
}
}
} else if(element.isJsonPrimitive()) {
String s = element.getAsString();
if(s.contains(remove)) {
extraArray.set(i, new JsonPrimitive(s.replace(remove, Character.toString(ChatManager.SEPARATOR))));
return jsonObj.toString();
}
}
// ignoring all others because it should not appear
}
ChatItem.debug("[IBase] Remove not fully managed: " + remove + " > " + jsonObj.toString());
return jsonObj.toString();
} catch (Exception e) {} // not JSON
return json.replace(remove, Character.toString(ChatManager.SEPARATOR));
}
}
@@ -0,0 +1,213 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.stream.Collectors;
import org.bukkit.entity.Player;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IBaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.utils.ReflectionUtils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.chat.ComponentSerializer;
public class AdventureComponentGetter implements IBaseComponentGetter {
private boolean useExtra = false;
@Override
public boolean hasConditions() {
try {
for (String cl : Arrays.asList("net.kyori.adventure.text.Component", "net.kyori.adventure.builder.AbstractBuilder",
"net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer"))
Class.forName(cl);
} catch (Exception e) { // can't support this, adventure comp not found
return false;
}
return true;
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Component comp = packet.getContent().getSpecificModifier(Component.class).readSafely(0);
if(comp == null) {
ChatItem.debug("The component is null.");
return null;
}
String json = ComponentSerializer.toString(BungeeComponentSerializer.get().serialize(comp).clone());
JsonObject jsonObj = JsonParser.parseString(json).getAsJsonObject();
ChatItem.debug("AdventureJSON : " + json + ", use extra: " + (!jsonObj.has("with")));
if(jsonObj.has("with")) {
JsonObject next = new JsonObject();
next.add("extra", jsonObj.get("with"));
return next.toString();
}
useExtra = true;
return json;
}
@Override
public String removePlaceholdersAndName(String json, String toReplace, Player foundedPlayer) {
String tmpName = IBaseComponentGetter.super.removePlaceholdersAndName(json, toReplace, foundedPlayer);
if(!tmpName.equals(json)) // if not the same -> name found and removed
return tmpName;
JsonObject jsonObj = JsonParser.parseString(json).getAsJsonObject();
if(!jsonObj.has("extra"))
return json;
String searched = toReplace + foundedPlayer.getName();
for(JsonElement element : jsonObj.get("extra").getAsJsonArray()) {
if(element.isJsonObject()) {
JsonObject withObj = element.getAsJsonObject();
if(withObj.has("extra")) {
String text = "";
int possibleId = -1;
JsonArray extraArray = withObj.get("extra").getAsJsonArray();
for(int i = 0; i < extraArray.size(); i++) {
JsonElement extra = extraArray.get(i);
if(!extra.isJsonObject())
continue; // prevent error but should not appear
JsonObject extraObj = extra.getAsJsonObject();
if(extraObj.has("text") && extraObj.get("text").isJsonPrimitive()) {
String extraTxt = extraObj.get("text").getAsString();
if(possibleId == -1) { // don't found the begin yet
if(searched.startsWith(extraTxt)) { // begin of replaced
possibleId = i;
text = extraTxt;
}
} else {
if(searched.startsWith(extraTxt, text.length()) || ChatManager.equalsSeparator(extraTxt)) {
text += extraTxt;
if(searched.equals(text)) { // found everything
// change actual, then remove all old
extraArray.set(i, JsonParser.parseString("{\"text\":\"" + Character.toString(ChatManager.SEPARATOR) + "\"}"));
for(int x = possibleId; x < i; x++)
extraArray.remove(possibleId); // remove elements
ChatItem.debug("Cleaned: " + jsonObj.toString());
return jsonObj.toString();
}
} else {
possibleId = -1; // was not good things
text = "";
}
}
}
}
ChatItem.debug("Failed to find: " + text + ", id: " + possibleId + " for " + withObj);
}
} // ignoring all others because it should not appear
}
ChatItem.debug("Nothing founded while trying to remove placeholders");
return IBaseComponentGetter.super.removePlaceholdersAndName(json, toReplace, foundedPlayer);
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
JsonElement globalElement = JsonParser.parseString(json);
JsonArray extraArray = fixParsedArray(globalElement.getAsJsonObject().getAsJsonArray("extra"));
String localJson;
if(useExtra) {
globalElement.getAsJsonObject().add("extra", extraArray);
localJson = globalElement.toString();
} else {
JsonObject next = new JsonObject();
next.addProperty("translate", "chat.type.text");
next.add("with", extraArray);
localJson = next.toString();
}
ChatItem.debug("Adventure Json: " + localJson);
try {
Class<?> packetClass = packet.getPacket().getClass();
if(packetClass.getSimpleName().equalsIgnoreCase("PacketPlayOutChat")) {
Field componentField = ReflectionUtils.getFirstFieldWith(packetClass, Component.class);
if(componentField != null) {
componentField.setAccessible(true);
componentField.set(packet.getPacket(), BungeeComponentSerializer.legacy().deserialize(ComponentSerializer.parse(localJson)));
} else {
throw new UnsupportedOperationException("The packet PacketPlayOutChat doesn't have Kyori's field. It has: " + Arrays.asList(packetClass.getDeclaredFields()).stream().map(f -> f.getName() + ": " + f.getType().getName()).collect(Collectors.toList()));
}
} else if(packetClass.getSimpleName().equalsIgnoreCase("ClientboundSystemChatPacket")) {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(localJson));
} else {
throw new UnsupportedOperationException("The packet " + packetClass.getSimpleName() + " isn't supported by the AdventureGetter. Please report this.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public JsonArray fixParsedArray(JsonArray arr) {
JsonArray next = new JsonArray();
for(JsonElement e : arr) {
if(e.isJsonArray()) {
JsonObject obj = null;
JsonArray extra = new JsonArray();
for(JsonElement element : e.getAsJsonArray()) {
JsonElement fixed = checkElement(element);
if(obj == null && fixed.isJsonObject()) {
obj = fixed.getAsJsonObject();
} else {
extra.add(fixed);
}
}
if(obj != null && extra.size() > 0) {
obj.add("extra", extra);
}
next.add(obj);
} else
next.add(checkElement(e));
}
return next;
}
private JsonElement checkElement(JsonElement e) {
if(e.isJsonObject()) {
JsonObject o = e.getAsJsonObject();
if(o.has("hoverEvent")) {// only hover event
JsonObject hoverObject = o.getAsJsonObject("hoverEvent");
if(hoverObject.get("action").getAsString().equalsIgnoreCase("show_item") && hoverObject.has("value")) {// if it's item to fix
String val = hoverObject.get("value").getAsString();
// now, we should fix the value
val = val.replaceAll("\\\"", "\"");
ChatItem.debug("Fixed json: " + ("{" + val.substring(1, val.length() - 1) + "}"));
hoverObject.remove("value");
JsonElement tagElement = JsonParser.parseString("{" + val.substring(1, val.length() - 1) + "}");
tagElement.getAsJsonObject().remove("tag");
/*if(tagElement.getAsJsonObject().has("tag")) {
JsonElement tag = tagElement.getAsJsonObject().get("tag");
if(tag.isJsonObject()) {
JsonObject tagObj = tag.getAsJsonObject();
tagObj.entrySet().forEach(entry -> {
ChatItem.debug("Tag json: " + entry.getKey() + " > " + entry.getValue());
JsonElement value = entry.getValue();
String sval = value.getAsString();
if(Utils.isInteger(sval)) {
if(Utils.isByte(sval))
tagObj.addProperty(entry.getKey(), sval + "b");
else if(Utils.isShort(sval))
tagObj.addProperty(entry.getKey(), sval + "s");
else if(Utils.isLong(sval))
tagObj.addProperty(entry.getKey(), sval + "l");
else
tagObj.addProperty(entry.getKey(), value + "i");
}
});
}
}*/
hoverObject.add("contents", tagElement);
o.add("hoverEvent", hoverObject);
}
}
}
return e;
}
}
@@ -0,0 +1,26 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IBaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.utils.Version;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.chat.ComponentSerializer;
public class BaseComponentGetter implements IBaseComponentGetter {
@Override
public boolean hasConditions() {
return Version.getVersion().isNewerOrEquals(Version.V1_8);
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
BaseComponent[] comps = packet.getContent().getSpecificModifier(BaseComponent[].class).readSafely(0);
return comps == null ? null : ComponentSerializer.toString(comps);
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
packet.getContent().getSpecificModifier(BaseComponent[].class).write(0, ComponentSerializer.parse(json));
}
}
@@ -0,0 +1,36 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IBaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.utils.PacketUtils;
public class ComponentGetter implements IBaseComponentGetter {
@Override
public boolean hasConditions() {
return PacketUtils.COMPONENT_CLASS != null;
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Object chatBaseComp = packet.getContent().getSpecificModifier(PacketUtils.COMPONENT_CLASS).readSafely(0);
if (chatBaseComp != null) {
try {
return PacketUtils.CHAT_SERIALIZER.getMethod("a", PacketUtils.COMPONENT_CLASS)
.invoke(null, packet.getPacket()).toString();
} catch (Exception exc) {
exc.printStackTrace();
}
}
return null;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
packet.getContent().getChatComponents().write(0, PacketUtils.CHAT_SERIALIZER.getMethod("a", String.class).invoke(null, json));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,95 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.time.Instant;
import java.util.Optional;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IBaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
public class IChatBaseComponentGetter implements IBaseComponentGetter {
private Method serializerGetJson;
private boolean canEditVariable = true;
public IChatBaseComponentGetter() {
try {
for (Method m : PacketUtils.CHAT_SERIALIZER.getDeclaredMethods()) {
if (m.getParameterCount() == 1 && m.getParameterTypes()[0].equals(PacketUtils.COMPONENT_CLASS)
&& m.getReturnType().equals(String.class)) {
serializerGetJson = m;
break;
}
}
if (serializerGetJson == null)
ChatItem.getInstance().getLogger().warning(
"Failed to find JSON serializer in class: " + PacketUtils.CHAT_SERIALIZER.getCanonicalName());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public boolean hasConditions() {
return serializerGetJson != null;
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
try {
Object obj = packet.getContent().getChatComponents().readSafely(0);
return obj == null ? null : (String) serializerGetJson.invoke(null, obj);
} catch (Exception exc) {
exc.printStackTrace();
}
return null;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
PacketContent content = packet.getContent();
Object chatComponent = PacketUtils.CHAT_SERIALIZER.getMethod("a", String.class).invoke(null, json);
if (canEditVariable)
content.getChatComponents().write(0, chatComponent);
else {
try {
Class<?> packetClass = packet.getPacket().getClass();
if (packetClass.getSimpleName().equalsIgnoreCase("ClientboundSystemChatPacket")) {
for (Constructor<?> cons : packetClass.getConstructors()) {
if (cons.getParameterCount() == 6) {
Object newPacket = cons.newInstance(chatComponent, Optional.empty(),
content.getIntegers().readSafely(0, 0),
content.getSpecificModifier(
PacketUtils.getNmsClass("ChatSender", "network.chat.")).read(0),
content.getSpecificModifier(Instant.class).read(0),
ReflectionUtils.getObject(packet.getPacket(), "f"));
packet.setPacket(newPacket);
}
}
throw new UnsupportedOperationException("Failed to find valid constructor for packet "
+ packetClass.getSimpleName() + ". Please report this.");
} else {
throw new UnsupportedOperationException("The packet " + packetClass.getSimpleName()
+ " isn't supported by the AdventureGetter. Please report this.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (IllegalAccessException e) {
if (canEditVariable) {
canEditVariable = false;
writeJson(packet, json); // try again with good config
} else
e.printStackTrace(); // something else
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,44 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IBaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
public class StringComponentGetter implements IBaseComponentGetter{
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
String json = packet.getContent().getStrings().readSafely(0);
if(json != null && json.startsWith("[") && json.endsWith("]")) { // if used as array instead of json obj
JsonArray extra = new JsonArray();
for(JsonElement element : JsonParser.parseString(json).getAsJsonArray()) {
if(element.isJsonObject()) { // ignore this
extra.add(element);
} else {
ChatItem.debug("Ignoring element " + element);
}
}
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("text", "");
jsonObject.add("extra", extra);
json = jsonObject.toString();
}
return json;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -1,14 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.json;
import java.util.List;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public interface JSONManipulator {
String parse(String json, List<String> replacements, ItemStack item, String repl, int protocol) throws Exception;
String parseEmpty(String json, List<String> replacements, String repl, List<String> tooltip, Player sender);
}
File diff suppressed because it is too large. Load diff
@@ -1,14 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.json;
public class NBTUtils {
@SuppressWarnings("unchecked")
public static <T> T get(Object obj, String methodName){
try {
return (T) obj.getClass().getDeclaredMethod(methodName).invoke(obj);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
@@ -1,17 +1,83 @@
package me.dadus33.chatitem.chatmanager.v1.json;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.bukkit.ChatColor;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.utils.ColorManager;
import net.md_5.bungee.api.ChatColor;
//Based on DarkSeraphim's system, but using Gson and supporting some more edge cases
public class Translator {
private static final String STYLES = "klmnor"; //All style codes
public static JsonArray toJson(String old){
if(old.lastIndexOf(ChatColor.COLOR_CHAR) == -1){
JsonArray arr = new JsonArray();
JsonObject obj = new JsonObject();
obj.addProperty("text", old);
arr.add(obj);
return arr;
}
JsonArray message = new JsonArray();
JsonObject next = new JsonObject();
String colorCode = "", text = "";
boolean waiting = false;
for (char args : old.toCharArray()) {
if (args == '§') { // begin of color
if(!text.isEmpty()) {
next.addProperty("text", text);
message.add(next);
next = new JsonObject();
text = "";
}
waiting = true; // waiting for color code
} else if (waiting) { // if waiting for code and valid str
// if it's hexademical value and with enough space for full color
waiting = false;
if(isStyle(args)) { // is style and not making rich color code
next.addProperty(getStyleName(args), true);
continue;
}
if(args == 'x' && !colorCode.isEmpty()) {
if(!text.isEmpty()) // ignore this if no text before
text += ColorManager.getColorString(colorCode);
colorCode = "x";
} else
colorCode += args; // a color by itself
} else {
waiting = false;
if(!colorCode.isEmpty()) { // manage color
if(colorCode.startsWith("x") && colorCode.length() == 7) { // hex color code
next.addProperty("color", ColorManager.getColor(colorCode).getName());
} else if(colorCode.length() == 1) { // if only one color code
if(next.has("color"))
text += ColorManager.getColor(colorCode);
else
next.addProperty("color", ColorManager.getColor(colorCode).getName());
} else if(!text.isEmpty())// no text before -> color will be used as "color"
text += ColorManager.getColorString(colorCode);
ChatItem.debug("Add " + colorCode + " to " + text + ", msg: " + message);
colorCode = "";
}
// basic text, not waiting for code after '§'
text += args;
}
}
if(!text.isEmpty() || message.isEmpty()) {
next.addProperty("text", text);
if(!next.has("color"))
next.addProperty("color", "white");
message.add(next);
}
return message;
}
public static JsonArray toJsonOld(String old){
if(old.lastIndexOf(ChatColor.COLOR_CHAR) == -1){
JsonArray arr = new JsonArray();
JsonObject obj = new JsonObject();
@@ -105,7 +171,7 @@ public class Translator {
}
private static String getColorName(char code){
return ChatColor.getByChar(code).name().toLowerCase();
return ChatColor.getByChar(code).getName().toLowerCase();
}
private static String getStyleName(char code){
@@ -116,7 +182,9 @@ public class Translator {
case 'n': return "underlined";
case 'o': return "italic";
case 'r': return "reset";
default: return null; //Should never happen. Made it return null to throw errors if a new format pops up and it really happens
default:
ChatItem.getInstance().getLogger().severe("Can't find code for style " + code);
return null; //Should never happen. Made it return null to throw errors if a new format pops up and it really happens
}
}
@@ -0,0 +1,156 @@
package me.dadus33.chatitem.chatmanager.v1.listeners;
import static me.dadus33.chatitem.chatmanager.ChatManager.SEPARATOR;
import java.util.StringJoiner;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
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.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.utils.Storage;
import me.dadus33.chatitem.utils.Utils;
public class ChatEventListener implements Listener {
private final PacketEditingChatManager manage;
public ChatEventListener(PacketEditingChatManager manage) {
this.manage = manage;
}
public Storage getStorage() {
return this.manage.getStorage();
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) // We need to have lowest priority in order
// to get to the event before DeluxeChat or
// other plugins do
public void onChat(AsyncPlayerChatEvent e) {
if (e.getMessage().indexOf(SEPARATOR) != -1) { // If the BELL character is found, we have to remove it
String msg = e.getMessage().replace(Character.toString(SEPARATOR), "");
ChatItem.debug("Already bell in message: " + e.getMessage());
e.setMessage(msg);
}
boolean found = false;
final String oldMsg = e.getMessage();
for (String rep : getStorage().PLACEHOLDERS)
if (oldMsg.contains(rep)) {
found = true;
break;
}
if (!found) {
ChatItem.debug("(v1) not found placeholders in: " + e.getMessage());
return;
}
Player p = e.getPlayer();
ItemStack item = ChatManager.getUsableItem(p);
if(!ChatManager.canShowItem(p, item, e))
return;
String s = e.getMessage(), firstPlaceholder = getStorage().PLACEHOLDERS.get(0);
for (String placeholder : getStorage().PLACEHOLDERS) {
s = s.replace(placeholder, firstPlaceholder);
}
if (Utils.countMatches(s, firstPlaceholder) > getStorage().LIMIT) {
e.setCancelled(true);
if (getStorage().LIMIT_MESSAGE.isEmpty()) {
return;
}
p.sendMessage(getStorage().LIMIT_MESSAGE);
return;
}
ChatItem.debug("(v1) Set placeholder: " + e.getMessage());
try {
StringJoiner msg = new StringJoiner(" ");
for(String part : s.split(" ")) {
if(part.equalsIgnoreCase(firstPlaceholder)) {
msg.add(SEPARATOR + p.getName());
} else {
msg.add(part);
}
}
e.setMessage(msg.toString());
e.setFormat(e.getFormat().replace(oldMsg, e.getMessage())); // set own message for plugin that already put the message into the format
ChatItem.debug("Message: " + e.getMessage() + ", format: " + e.getFormat());
} catch (Exception exc) {
exc.printStackTrace();
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onCommand(final PlayerCommandPreprocessEvent e) {
if (e.getMessage().indexOf(SEPARATOR) != -1) { // If the BELL character is found, we have to remove it
String msg = e.getMessage().replace(Character.toString(SEPARATOR), "");
e.setMessage(msg);
}
String commandString = e.getMessage().split(" ")[0].replaceAll("^/+", ""); // First part of the command, without
// leading slashes and without
// arguments
Command cmd = Bukkit.getPluginCommand(commandString);
if (cmd == null) { // not a plugin command
if (!getStorage().ALLOWED_DEFAULT_COMMANDS.contains(commandString)) {
return;
}
} else {
if (!getStorage().ALLOWED_PLUGIN_COMMANDS.contains(cmd)) {
return;
}
}
Player p = e.getPlayer();
boolean found = false;
for (String rep : getStorage().PLACEHOLDERS) {
if (e.getMessage().contains(rep)) {
found = true;
break;
}
}
if (!found) {
return;
}
ItemStack item = ChatManager.getUsableItem(p);
if(!ChatManager.canShowItem(p, item, e))
return;
String s = e.getMessage(), firstPlaceholder = getStorage().PLACEHOLDERS.get(0);
for (String placeholder : getStorage().PLACEHOLDERS) {
s = s.replace(placeholder, firstPlaceholder);
}
if (Utils.countMatches(s, firstPlaceholder) > getStorage().LIMIT) {
e.setCancelled(true);
if (getStorage().LIMIT_MESSAGE.isEmpty()) {
return;
}
p.sendMessage(getStorage().LIMIT_MESSAGE);
return;
}
ChatItem.debug("(v1) Set placeholder: " + e.getMessage());
try {
StringJoiner msg = new StringJoiner(" ");
for(String part : s.split(" ")) {
if(part.equalsIgnoreCase(firstPlaceholder)) {
msg.add(SEPARATOR + p.getName());
} else {
msg.add(part);
}
}
e.setMessage(msg.toString());
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
@@ -0,0 +1,247 @@
package me.dadus33.chatitem.chatmanager.v1.listeners;
import static me.dadus33.chatitem.chatmanager.ChatManager.SEPARATOR;
import static me.dadus33.chatitem.chatmanager.ChatManager.SEPARATOR_STR;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.ItemMeta;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.ItemPlayer;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IBaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.AdventureComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.BaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.ComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.IChatBaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.StringComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketHandler;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.Storage;
import me.dadus33.chatitem.utils.Version;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.chat.ComponentSerializer;
public class ChatPacketManager extends PacketHandler {
private Object lastSentPacket = null;
private Method serializerGetJson;
private PacketEditingChatManager manager;
private final List<IBaseComponentGetter> baseComponentGetter = new ArrayList<>();
public ChatPacketManager(PacketEditingChatManager manager) {
this.manager = manager;
try {
for (Method m : PacketUtils.CHAT_SERIALIZER.getDeclaredMethods()) {
if (m.getParameterCount() == 1 && m.getParameterTypes()[0].equals(PacketUtils.COMPONENT_CLASS)
&& m.getReturnType().equals(String.class)) {
serializerGetJson = m;
break;
}
}
if (serializerGetJson == null)
ChatItem.getInstance().getLogger().warning(
"Failed to find JSON serializer in class: " + PacketUtils.CHAT_SERIALIZER.getCanonicalName());
} catch (Exception e) {
e.printStackTrace();
}
for(IBaseComponentGetter getter : Arrays.asList(new IChatBaseComponentGetter(), new BaseComponentGetter(), new ComponentGetter(), new StringComponentGetter(), new AdventureComponentGetter())) {
if(getter.hasConditions())
baseComponentGetter.add(getter);
}
ChatItem.getInstance().getLogger().info("Loaded " + baseComponentGetter.size() + " getter for base components.");
ChatItem.debug("BaseComponentGetters: " + String.join(", ", baseComponentGetter.stream().map(IBaseComponentGetter::getClass).map(Class::getSimpleName).collect(Collectors.toList())));
}
@Override
public void onSend(ChatItemPacket e) {
if (!e.hasPlayer() || !e.getPacketType().equals(PacketType.Server.CHAT))
return;
ChatItem.debug("Checking: " + e.getPacketType().getFullName() + " to " + e.getPlayername());
if (lastSentPacket != null && lastSentPacket == e.getPacket())
return; // prevent infinite loop
PacketContent packet = e.getContent();
Version version = Version.getVersion();
String json = "{}";
IBaseComponentGetter choosedGetter = null;
if (version.isNewerOrEquals(Version.V1_19)) {
if(packet.getIntegers().readSafely(0, 0) > 1) { // not parsed chat message type
ChatItem.debug("Invalid int: " + packet.getIntegers().read(0));
return;
}
choosedGetter = new StringComponentGetter();
json = choosedGetter.getBaseComponentAsJSON(e); // if null, will be re-checked so anyway
} else if (version.isNewerOrEquals(Version.V1_12)) {
// only if action bar messages are supported in this version of minecraft
try {
if (((Enum<?>) packet
.getSpecificModifier(PacketUtils.getNmsClass("ChatMessageType", "network.chat.")).read(0))
.name().equals("GAME_INFO")) {
return; // It means it's an actionbar message, and we ain't intercepting those
}
} catch (Exception exc) {
exc.printStackTrace();
}
} else if (version.isNewerOrEquals(Version.V1_8) && packet.getBytes().readSafely(0) == (byte) 2) {
return; // It means it's an actionbar message, and we ain't intercepting those
}
if(json == null || choosedGetter == null) {
for(IBaseComponentGetter getters : baseComponentGetter) {
String tmpJson = getters.getBaseComponentAsJSON(e);
if(tmpJson != null) {
json = ChatManager.fixSeparator(tmpJson);
choosedGetter = getters;
break;
}
}
}
if(json == null || choosedGetter == null) {
ChatItem.debug("Can't find valid json getter or json itself");
ChatItem.debug("String: " + packet.getStrings().getContent());
return; // can't find something
}
ChatItem.debug("Found with " + choosedGetter.getClass().getName());
String toReplace = null;
if (json.lastIndexOf(SEPARATOR) != -1)
toReplace = ((Object) SEPARATOR).toString();
if (json.lastIndexOf(SEPARATOR_STR) != -1)
toReplace = SEPARATOR_STR;
if (toReplace == null) { // if the message doesn't contain the BELL separator
ChatItem.debug("Not containing bell " + json);
return;
}
String name = choosedGetter.getNameFromMessage(json, toReplace);
if (name == null) { // something went really bad, so we run away and hide (AKA the player left or is
// on another server)
ChatItem.debug("Name null for " + json);
return;
}
Player itemPlayer = Bukkit.getPlayer(name);
String localJson = choosedGetter.removePlaceholdersAndName(json, toReplace, itemPlayer);
ChatItem.debug("Local json: " + localJson);
IBaseComponentGetter fchoosedGetter = choosedGetter;
e.setCancelled(true); // We cancel the packet as we're going to resend it anyways (ignoring listeners
// this time)
Bukkit.getScheduler().runTaskAsynchronously(ChatItem.getInstance(), () -> {
Player p = e.getPlayer();
if (getStorage().COOLDOWN > 0 && !itemPlayer.hasPermission("chatitem.ignore-cooldown")) {
ChatManager.applyCooldown(itemPlayer);
}
String message = null;
try {
ItemStack item = ChatManager.getUsableItem(itemPlayer);
if (!ItemUtils.isEmpty(item)) {
ItemStack copy = item.clone();
if (ItemPlayer.getPlayer(p).isBuggedClient()) {
String act = getStorage().BUGGED_CLIENT_ACTION;
List<String> tooltip;// = act.equalsIgnoreCase("nothing") ? new ArrayList<>() : null;
if (act.equalsIgnoreCase("tooltip"))
tooltip = getStorage().BUGGED_CLIENTS_TOOLTIP;
else if (act.equalsIgnoreCase("item"))
tooltip = ChatManager.getMaxLinesFromItem(p, copy);
else if (act.equalsIgnoreCase("show_both")) {
tooltip = ChatManager.getMaxLinesFromItem(p, copy);
tooltip.addAll(getStorage().BUGGED_CLIENTS_TOOLTIP);
} else
tooltip = new ArrayList<>();
message = manager.getManipulator().parseEmpty(localJson,
ChatManager.styleItem(p, copy, getStorage()), tooltip, itemPlayer);
if (!manager.supportsChatComponentApi()) {
ChatItem.debug("Use basic for 1.7 lunar");
packet.getChatComponents().write(0, jsonToChatComponent(message));
} else {
ChatItem.debug("Use baseComponent for 1.7 lunar");
packet.getSpecificModifier(BaseComponent[].class).write(0,
ComponentSerializer.parse(message));
}
lastSentPacket = e.getPacket();
PacketUtils.sendPacket(p, lastSentPacket);
return;
}
if(copy.hasItemMeta()) {
ItemMeta meta = copy.getItemMeta();
if (meta instanceof BookMeta) { // filtering written books
BookMeta bm = (BookMeta) copy.getItemMeta();
bm.setPages(Collections.emptyList());
copy.setItemMeta(bm);
} else if (meta instanceof BlockStateMeta && Version.getVersion().isNewerOrEquals(Version.V1_9)) { // if it's a block
BlockStateMeta bsm = (BlockStateMeta) copy.getItemMeta();
if (bsm.hasBlockState() && bsm.getBlockState() instanceof ShulkerBox) {
ShulkerBox sb = (ShulkerBox) bsm.getBlockState();
for (ItemStack itemInv : sb.getInventory()) {
stripData(itemInv);
}
bsm.setBlockState(sb);
}
copy.setItemMeta(bsm);
}
}
message = manager.getManipulator().parse(localJson, copy,
ChatManager.styleItem(p, copy, getStorage()), ItemPlayer.getPlayer(itemPlayer).getProtocolVersion());
} else {
if (!getStorage().HAND_DISABLED) {
message = manager.getManipulator().parseEmpty(localJson, getStorage().HAND_NAME, getStorage().HAND_TOOLTIP, itemPlayer);
}
}
} catch (Exception e1) {
e1.printStackTrace();
}
if (message != null) {
ChatItem.debug("(v1) Writing message: " + message);
fchoosedGetter.writeJson(e, message);
}
lastSentPacket = e.getPacket();
PacketUtils.sendPacket(p, lastSentPacket);
});
}
private Object jsonToChatComponent(String json) {
try {
return PacketUtils.CHAT_SERIALIZER.getMethod("a", String.class).invoke(null, json);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private void stripData(ItemStack i) {
if (i == null) {
return;
}
if (i.getType().equals(Material.AIR)) {
return;
}
if (!i.hasItemMeta()) {
return;
}
ItemMeta im = Bukkit.getItemFactory().getItemMeta(i.getType());
ItemMeta original = i.getItemMeta();
if (original.hasDisplayName()) {
im.setDisplayName(original.getDisplayName());
}
i.setItemMeta(im);
}
public Storage getStorage() {
return manager.getStorage();
}
}
@@ -8,7 +8,7 @@ import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.playerversion.hooks.DefaultVersionHook;
import me.dadus33.chatitem.playerversion.hooks.DefaultVersionHook;
import me.dadus33.chatitem.utils.Version;
public class HandshakeListener extends PacketAdapter {
@@ -1,270 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.listeners.v15lower;
import static me.dadus33.chatitem.chatmanager.ChatManager.SEPARATOR;
import java.util.HashMap;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.command.Command;
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.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.utils.Storage;
public class ChatEventListener implements Listener {
private final static String LEFT = "{remaining}";
private final HashMap<String, Long> COOLDOWNS = new HashMap<>();
private final PacketEditingChatManager manage;
public ChatEventListener(PacketEditingChatManager manage) {
this.manage = manage;
}
public Storage getStorage() {
return this.manage.getStorage();
}
private String calculateTime(long seconds) {
if (seconds < 60) {
return seconds + getStorage().SECONDS;
}
if (seconds < 3600) {
StringBuilder builder = new StringBuilder();
int minutes = (int) seconds / 60;
builder.append(minutes).append(getStorage().MINUTES);
int secs = (int) seconds - minutes * 60;
if (secs != 0) {
builder.append(" ").append(secs).append(getStorage().SECONDS);
}
return builder.toString();
}
StringBuilder builder = new StringBuilder();
int hours = (int) seconds / 3600;
builder.append(hours).append(getStorage().HOURS);
int minutes = (int) (seconds / 60) - (hours * 60);
if (minutes != 0) {
builder.append(" ").append(minutes).append(getStorage().MINUTES);
}
int secs = (int) (seconds - ((seconds / 60) * 60));
if (secs != 0) {
builder.append(" ").append(secs).append(getStorage().SECONDS);
}
return builder.toString();
}
private int countOccurrences(String findStr, String str) {
int lastIndex = 0;
int count = 0;
while (lastIndex != -1) {
lastIndex = str.indexOf(findStr, lastIndex);
if (lastIndex != -1) {
count++;
lastIndex += findStr.length();
}
}
return count;
}
@SuppressWarnings("deprecation")
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) // We need to have lowest priority in order
// to get to the event before DeluxeChat or
// other plugins do
public void onChat(final AsyncPlayerChatEvent e) {
ChatItem.debug("(v1) Check for v1 system. Cancelled: " + e.isCancelled());
if (e.getMessage().indexOf(SEPARATOR) != -1) { // If the BELL character is found, we have to remove it
String msg = e.getMessage().replace(Character.toString(SEPARATOR), "");
ChatItem.debug("Already bell in message: " + e.getMessage());
e.setMessage(msg);
}
boolean found = false;
for (String rep : getStorage().PLACEHOLDERS)
if (e.getMessage().contains(rep)) {
found = true;
break;
}
if (!found) {
ChatItem.debug("(v1) not found placeholders in: " + e.getMessage());
return;
}
Player p = e.getPlayer();
if (!p.hasPermission("chatitem.use")) {
if (!getStorage().LET_MESSAGE_THROUGH) {
e.setCancelled(true);
}
if (!getStorage().NO_PERMISSION_MESSAGE.isEmpty() && getStorage().SHOW_NO_PERM_NORMAL) {
p.sendMessage(getStorage().NO_PERMISSION_MESSAGE);
}
ChatItem.debug("(v1) Don't have permission");
return;
}
if (p.getItemInHand().getType().equals(Material.AIR)) {
if (getStorage().DENY_IF_NO_ITEM) {
e.setCancelled(true);
if (!getStorage().DENY_MESSAGE.isEmpty())
e.getPlayer().sendMessage(getStorage().DENY_MESSAGE);
ChatItem.debug("(v1) No item and must deny");
return;
}
if (getStorage().HAND_DISABLED) {
ChatItem.debug("(v1) Hand disabled");
return;
}
}
if (getStorage().COOLDOWN > 0 && !p.hasPermission("chatitem.ignore-cooldown")) {
if (COOLDOWNS.containsKey(p.getName())) {
long start = COOLDOWNS.get(p.getName());
long current = System.currentTimeMillis() / 1000;
long elapsed = current - start;
if (elapsed >= getStorage().COOLDOWN) {
COOLDOWNS.remove(p.getName());
} else {
if (!getStorage().LET_MESSAGE_THROUGH) {
e.setCancelled(true);
}
if (!getStorage().COOLDOWN_MESSAGE.isEmpty()) {
long left = (start + getStorage().COOLDOWN) - current;
p.sendMessage(getStorage().COOLDOWN_MESSAGE.replace(LEFT, calculateTime(left)));
}
ChatItem.debug("(v1) Cooldown");
return;
}
}
}
String s = e.getMessage();
for (String placeholder : getStorage().PLACEHOLDERS) {
s = s.replace(placeholder, getStorage().PLACEHOLDERS.get(0));
}
int occurrences = countOccurrences(getStorage().PLACEHOLDERS.get(0), s);
if (occurrences > getStorage().LIMIT) {
e.setCancelled(true);
ChatItem.debug("(v1) Reach message limit");
if (getStorage().LIMIT_MESSAGE.isEmpty()) {
return;
}
e.getPlayer().sendMessage(getStorage().LIMIT_MESSAGE);
return;
}
String oldmsg = e.getMessage();
StringBuilder sb = new StringBuilder(oldmsg);
sb.append(SEPARATOR).append(e.getPlayer().getName());
e.setMessage(sb.toString());
ChatItem.debug("(v1) Set placeholder: " + e.getMessage());
if (!p.hasPermission("chatitem.ignore-cooldown")) {
COOLDOWNS.put(p.getName(), System.currentTimeMillis() / 1000);
}
}
@SuppressWarnings("deprecation")
@EventHandler(priority = EventPriority.LOWEST)
public void onCommand(final PlayerCommandPreprocessEvent e) {
if (e.getMessage().indexOf(SEPARATOR) != -1) { // If the BELL character is found, we have to remove it
String msg = e.getMessage().replace(Character.toString(SEPARATOR), "");
e.setMessage(msg);
}
String commandString = e.getMessage().split(" ")[0].replaceAll("^/+", ""); // First part of the command, without
// leading slashes and without
// arguments
Command cmd = Bukkit.getPluginCommand(commandString);
if (cmd == null) { // not a plugin command
if (!getStorage().ALLOWED_DEFAULT_COMMANDS.contains(commandString)) {
return;
}
} else {
if (!getStorage().ALLOWED_PLUGIN_COMMANDS.contains(cmd)) {
return;
}
}
Player p = e.getPlayer();
boolean found = false;
for (String rep : getStorage().PLACEHOLDERS) {
if (e.getMessage().contains(rep)) {
found = true;
break;
}
}
if (!found) {
return;
}
if (!p.hasPermission("chatitem.use")) {
if (!getStorage().NO_PERMISSION_MESSAGE.isEmpty() && getStorage().SHOW_NO_PERM_COMMAND) {
p.sendMessage(getStorage().NO_PERMISSION_MESSAGE);
}
e.setCancelled(true);
return;
}
if (e.getPlayer().getItemInHand().getType().equals(Material.AIR)) {
if (getStorage().DENY_IF_NO_ITEM) {
e.setCancelled(true);
if (!getStorage().DENY_MESSAGE.isEmpty()) {
e.getPlayer().sendMessage(getStorage().DENY_MESSAGE);
}
}
if (getStorage().HAND_DISABLED) {
return;
}
}
if (getStorage().COOLDOWN > 0 && !p.hasPermission("chatitem.ignore-cooldown")) {
if (COOLDOWNS.containsKey(p.getName())) {
long start = COOLDOWNS.get(p.getName());
long current = System.currentTimeMillis() / 1000;
long elapsed = current - start;
if (elapsed >= getStorage().COOLDOWN) {
COOLDOWNS.remove(p.getName());
} else {
if (!getStorage().LET_MESSAGE_THROUGH) {
e.setCancelled(true);
}
if (!getStorage().COOLDOWN_MESSAGE.isEmpty()) {
long left = (start + getStorage().COOLDOWN) - current;
p.sendMessage(getStorage().COOLDOWN_MESSAGE.replace(LEFT, calculateTime(left)));
}
return;
}
}
}
String s = e.getMessage();
for (String placeholder : getStorage().PLACEHOLDERS) {
s = s.replace(placeholder, getStorage().PLACEHOLDERS.get(0));
}
int occurrences = countOccurrences(getStorage().PLACEHOLDERS.get(0), s);
if (occurrences > getStorage().LIMIT) {
e.setCancelled(true);
if (getStorage().LIMIT_MESSAGE.isEmpty()) {
return;
}
e.getPlayer().sendMessage(getStorage().LIMIT_MESSAGE);
return;
}
StringBuilder sb = new StringBuilder(e.getMessage());
sb.append(SEPARATOR).append(e.getPlayer().getName());
e.setMessage(sb.toString());
if (!p.hasPermission("chatitem.ignore-cooldown")) {
COOLDOWNS.put(p.getName(), System.currentTimeMillis() / 1000);
}
}
}
@@ -1,294 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.listeners.v15lower;
import static me.dadus33.chatitem.chatmanager.ChatManager.SEPARATOR;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.ItemMeta;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketHandler;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.Storage;
import me.dadus33.chatitem.utils.Version;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.chat.ComponentSerializer;
public class ChatPacket15Manager extends PacketHandler {
private final static String NAME = "{name}";
private final static String AMOUNT = "{amount}";
private final static String TIMES = "{times}";
private Method serializerGetJson;
private PacketEditingChatManager manager;
public ChatPacket15Manager(PacketEditingChatManager manager) {
this.manager = manager;
try {
for (Method m : PacketUtils.CHAT_SERIALIZER.getDeclaredMethods()) {
if (m.getParameterCount() == 1 && m.getParameterTypes()[0].equals(PacketUtils.COMPONENT_CLASS)
&& m.getReturnType().equals(String.class)) {
serializerGetJson = m;
break;
}
}
if (serializerGetJson == null)
ChatItem.getInstance().getLogger().warning(
"Failed to find JSON serializer in class: " + PacketUtils.CHAT_SERIALIZER.getCanonicalName());
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressWarnings("deprecation")
@Override
public void onSend(ChatItemPacket e) {
if (!e.hasPlayer() || !e.getPacketType().equals(PacketType.Server.CHAT)) {
return;
}
Version version = Version.getVersion();
if (version.isNewerOrEquals(Version.V1_8)) { // only if action bar messages are supported in this
// version of minecraft
if (version.isNewerOrEquals(Version.V1_12)) {
try {
if (((Enum<?>) e.getContent()
.getSpecificModifier(PacketUtils.getNmsClass("ChatMessageType", "network.chat.")).read(0))
.name().equals("GAME_INFO")) {
return; // It means it's an actionbar message, and we ain't intercepting those
}
} catch (Exception exc) {
exc.printStackTrace();
}
} else if (e.getContent().getBytes().readSafely(0) == (byte) 2) {
return; // It means it's an actionbar message, and we ain't intercepting those
}
}
ChatItem.debug("UUID: " + e.getContent().getSpecificModifier(UUID.class).readSafely(0, null));
boolean usesBaseComponents = false;
PacketContent packet = e.getContent();
String json;
if (packet.getChatComponents().readSafely(0) == null) { // null check for some cases of messages sent using
// spigot's Chat Component API or other means
if (!manager.supportsChatComponentApi()) // only if the API is supported in this server distribution
return;// We don't know how to deal with anything else. Most probably some mod message
// we shouldn't mess with anyways
BaseComponent[] components = packet.getSpecificModifier(BaseComponent[].class).readSafely(0);
if (components == null) {
ChatItem.debug("No base components");
return;
}
json = ComponentSerializer.toString(components);
usesBaseComponents = true;
} else {
try {
json = (String) serializerGetJson.invoke(null, packet.getChatComponents().readSafely(0));
} catch (Exception exc) {
exc.printStackTrace();
json = "{}";
}
}
boolean found = false;
for (String rep : getStorage().PLACEHOLDERS) {
if (json.contains(rep)) {
found = true;
break;
}
}
if (!found) {
ChatItem.debug("No placeholders founded");
return; // then it's just a normal message without placeholders, so we leave it alone
}
if (json.lastIndexOf(SEPARATOR) == -1) { // if the message doesn't contain the BELL separator, then it's
// certainly NOT a message we want to parse
ChatItem.debug("Not contains bell " + json);
return;
}
ChatItem.debug("Add packet meta");
String fjson = json;
boolean bUsesBaseComponents = usesBaseComponents;
e.setCancelled(true); // We cancel the packet as we're going to resend it anyways (ignoring listeners
// this time)
Bukkit.getScheduler().runTaskAsynchronously(ChatItem.getInstance(), () -> {
int topIndex = -1;
String name = null;
for (Player p : Bukkit.getOnlinePlayers()) {
String pname = SEPARATOR + p.getName();
if (!fjson.contains(pname)) {
continue;
}
int index = fjson.lastIndexOf(pname) + pname.length();
if (index > topIndex) {
topIndex = index;
name = pname.replace(SEPARATOR + "", "");
}
}
if (name == null) { // something went really bad, so we run away and hide (AKA the player left or is
// on another server)
ChatItem.debug("Name null for " + fjson);
return;
}
Player p = Bukkit.getPlayer(name);
StringBuilder builder = new StringBuilder(fjson);
builder.replace(topIndex - (name.length() + 6), topIndex, ""); // we remove both the name and the separator
// from the json string
String localJson = builder.toString();
String message = null;
try {
if (!p.getItemInHand().getType().equals(Material.AIR)) {
ItemStack copy = p.getItemInHand().clone();
if (copy.getType().name().contains("_BOOK")) { // filtering written books
BookMeta bm = (BookMeta) copy.getItemMeta();
bm.setPages(Collections.emptyList());
copy.setItemMeta(bm);
} else {
if (copy.getType().name().contains("SHULKER_BOX")) { // if it's shulker
if (copy.hasItemMeta()) {
BlockStateMeta bsm = (BlockStateMeta) copy.getItemMeta();
if (bsm.hasBlockState()) {
ShulkerBox sb = (ShulkerBox) bsm.getBlockState();
for (ItemStack item : sb.getInventory()) {
stripData(item);
}
bsm.setBlockState(sb);
}
copy.setItemMeta(bsm);
}
}
}
message = manager.getManipulator().parse(localJson, getStorage().PLACEHOLDERS, copy,
styleItem(copy, getStorage()), manager.getPlayerVersionAdapter().getProtocolVersion(p));
} else {
if (!getStorage().HAND_DISABLED) {
message = manager.getManipulator().parseEmpty(localJson, getStorage().PLACEHOLDERS,
getStorage().HAND_NAME, getStorage().HAND_TOOLTIP, p);
}
}
} catch (Exception e1) {
e1.printStackTrace();
}
if (message != null) {
if (!bUsesBaseComponents) {
packet.getChatComponents().write(0, jsonToChatComponent(message));
} else {
packet.getSpecificModifier(BaseComponent[].class).write(0, ComponentSerializer.parse(message));
}
}
PacketUtils.sendPacket(e.getPlayer(), e.getPacket());
});
}
private Object jsonToChatComponent(String json) {
try {
return PacketUtils.CHAT_SERIALIZER.getMethod("a", String.class).invoke(null, json);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String styleItem(ItemStack item, Storage c) {
String replacer = c.NAME_FORMAT;
String amount = c.AMOUNT_FORMAT;
boolean dname = item.hasItemMeta() ? item.getItemMeta().hasDisplayName() : false;
if (item.getAmount() == 1) {
if (c.FORCE_ADD_AMOUNT) {
amount = amount.replace(TIMES, "1");
replacer = replacer.replace(AMOUNT, amount);
} else {
replacer = replacer.replace(AMOUNT, "");
}
} else {
amount = amount.replace(TIMES, String.valueOf(item.getAmount()));
replacer = replacer.replace(AMOUNT, amount);
}
if (dname) {
String trp = item.getItemMeta().getDisplayName();
if (c.COLOR_IF_ALREADY_COLORED) {
replacer = replacer.replace(NAME, ChatColor.stripColor(trp));
} else {
replacer = replacer.replace(NAME, trp);
}
} else {
HashMap<Short, String> translationSection = c.TRANSLATIONS.get(item.getType().name());
if (translationSection == null) {
String trp = materialToName(item.getType());
replacer = replacer.replace(NAME, trp);
} else {
@SuppressWarnings("deprecation")
String translated = translationSection.get(item.getDurability());
if (translated != null) {
replacer = replacer.replace(NAME, translated);
} else {
replacer = replacer.replace(NAME, materialToName(item.getType()));
}
}
}
return replacer;
}
private static String materialToName(Material m) {
if (m.equals(Material.TNT)) {
return "TNT";
}
String orig = m.toString().toLowerCase();
String[] splits = orig.split("_");
StringBuilder sb = new StringBuilder(orig.length());
int pos = 0;
for (String split : splits) {
sb.append(split);
int loc = sb.lastIndexOf(split);
char charLoc = sb.charAt(loc);
if (!(split.equalsIgnoreCase("of") || split.equalsIgnoreCase("and") || split.equalsIgnoreCase("with")
|| split.equalsIgnoreCase("on")))
sb.setCharAt(loc, Character.toUpperCase(charLoc));
if (pos != splits.length - 1)
sb.append(' ');
++pos;
}
return sb.toString();
}
private void stripData(ItemStack i) {
if (i == null) {
return;
}
if (i.getType().equals(Material.AIR)) {
return;
}
if (!i.hasItemMeta()) {
return;
}
ItemMeta im = Bukkit.getItemFactory().getItemMeta(i.getType());
ItemMeta original = i.getItemMeta();
if (original.hasDisplayName()) {
im.setDisplayName(original.getDisplayName());
}
i.setItemMeta(im);
}
public Storage getStorage() {
return manager.getStorage();
}
}
@@ -1,234 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.listeners.v16upper;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.ItemMeta;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketHandler;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.Storage;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.chat.ComponentSerializer;
public class ChatPacket16Manager extends PacketHandler {
private final static String NAME = "{name}";
private final static String AMOUNT = "{amount}";
private final static String TIMES = "{times}";
private Method serializerGetJson;
private PacketEditingChatManager manager;
public ChatPacket16Manager(PacketEditingChatManager manager) {
this.manager = manager;
try {
for (Method m : PacketUtils.CHAT_SERIALIZER.getDeclaredMethods()) {
if (m.getParameterCount() == 1 && m.getParameterTypes()[0].equals(PacketUtils.COMPONENT_CLASS)
&& m.getReturnType().equals(String.class)) {
serializerGetJson = m;
break;
}
}
if (serializerGetJson == null)
ChatItem.getInstance().getLogger().warning(
"Failed to find JSON serializer in class: " + PacketUtils.CHAT_SERIALIZER.getCanonicalName());
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressWarnings("deprecation")
@Override
public void onSend(ChatItemPacket e) {
if (!e.hasPlayer() || !e.getPacketType().equals(PacketType.Server.CHAT)) {
return;
}
UUID sender = e.getContent().getSpecificModifier(UUID.class).readSafely(0, null);
if(sender.equals(UUID.fromString("00000000-0000-0000-0000-000000000000"))) // not chat message
return;
ChatItem.debug("UUID: " + sender);
PacketContent packet = e.getContent();
String nfJson;
Object possibleChatComponent = packet.getChatComponents().readSafely(0);
if (possibleChatComponent == null) {
BaseComponent[] components = packet.getSpecificModifier(BaseComponent[].class).readSafely(0);
if (components == null) {
ChatItem.debug("No base components");
return;
}
nfJson = ComponentSerializer.toString(components);
} else {
try {
nfJson = (String) serializerGetJson.invoke(null, possibleChatComponent);
} catch (Exception exc) {
exc.printStackTrace();
nfJson = "{}";
}
}
String json = nfJson;
boolean found = false;
for (String rep : getStorage().PLACEHOLDERS) {
if (json.contains(rep)) {
found = true;
break;
}
}
if (!found) {
ChatItem.debug("No placeholders founded");
return; // then it's just a normal message without placeholders, so we leave it alone
}
Player p = Bukkit.getPlayer(sender);
String message = null;
try {
if (!p.getItemInHand().getType().equals(Material.AIR)) {
ItemStack copy = p.getItemInHand().clone();
if (copy.getType().name().contains("_BOOK")) { // filtering written books
BookMeta bm = (BookMeta) copy.getItemMeta();
bm.setPages(Collections.emptyList());
copy.setItemMeta(bm);
} else {
if (copy.getType().name().contains("SHULKER_BOX")) { // if it's shulker
if (copy.hasItemMeta()) {
BlockStateMeta bsm = (BlockStateMeta) copy.getItemMeta();
if (bsm.hasBlockState()) {
ShulkerBox sb = (ShulkerBox) bsm.getBlockState();
for (ItemStack item : sb.getInventory()) {
stripData(item);
}
bsm.setBlockState(sb);
}
copy.setItemMeta(bsm);
}
}
}
message = manager.getManipulator().parse(json, getStorage().PLACEHOLDERS, copy,
styleItem(copy, getStorage()), manager.getPlayerVersionAdapter().getProtocolVersion(p));
} else {
if (!getStorage().HAND_DISABLED) {
message = manager.getManipulator().parseEmpty(json, getStorage().PLACEHOLDERS,
getStorage().HAND_NAME, getStorage().HAND_TOOLTIP, p);
}
}
} catch (Exception e1) {
e1.printStackTrace();
}
if (message != null) {
if (json.equalsIgnoreCase("{}")) {
packet.getChatComponents().write(0, jsonToChatComponent(message));
} else {
packet.getSpecificModifier(BaseComponent[].class).write(0, ComponentSerializer.parse(message));
}
}
}
private Object jsonToChatComponent(String json) {
try {
return PacketUtils.CHAT_SERIALIZER.getMethod("a", String.class).invoke(null, json);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String styleItem(ItemStack item, Storage c) {
String replacer = c.NAME_FORMAT;
String amount = c.AMOUNT_FORMAT;
boolean dname = item.hasItemMeta() ? item.getItemMeta().hasDisplayName() : false;
if (item.getAmount() == 1) {
if (c.FORCE_ADD_AMOUNT) {
amount = amount.replace(TIMES, "1");
replacer = replacer.replace(AMOUNT, amount);
} else {
replacer = replacer.replace(AMOUNT, "");
}
} else {
amount = amount.replace(TIMES, String.valueOf(item.getAmount()));
replacer = replacer.replace(AMOUNT, amount);
}
if (dname) {
String trp = item.getItemMeta().getDisplayName();
if (c.COLOR_IF_ALREADY_COLORED) {
replacer = replacer.replace(NAME, ChatColor.stripColor(trp));
} else {
replacer = replacer.replace(NAME, trp);
}
} else {
HashMap<Short, String> translationSection = c.TRANSLATIONS.get(item.getType().name());
if (translationSection == null) {
String trp = materialToName(item.getType());
replacer = replacer.replace(NAME, trp);
} else {
@SuppressWarnings("deprecation")
String translated = translationSection.get(item.getDurability());
if (translated != null) {
replacer = replacer.replace(NAME, translated);
} else {
replacer = replacer.replace(NAME, materialToName(item.getType()));
}
}
}
return replacer;
}
private static String materialToName(Material m) {
if (m.equals(Material.TNT)) {
return "TNT";
}
String orig = m.toString().toLowerCase();
String[] splits = orig.split("_");
StringBuilder sb = new StringBuilder(orig.length());
int pos = 0;
for (String split : splits) {
sb.append(split);
int loc = sb.lastIndexOf(split);
char charLoc = sb.charAt(loc);
if (!(split.equalsIgnoreCase("of") || split.equalsIgnoreCase("and") || split.equalsIgnoreCase("with")
|| split.equalsIgnoreCase("on")))
sb.setCharAt(loc, Character.toUpperCase(charLoc));
if (pos != splits.length - 1)
sb.append(' ');
++pos;
}
return sb.toString();
}
private void stripData(ItemStack i) {
if (i == null) {
return;
}
if (i.getType().equals(Material.AIR)) {
return;
}
if (!i.hasItemMeta()) {
return;
}
ItemMeta im = Bukkit.getItemFactory().getItemMeta(i.getType());
ItemMeta original = i.getItemMeta();
if (original.hasDisplayName()) {
im.setDisplayName(original.getDisplayName());
}
i.setItemMeta(im);
}
public Storage getStorage() {
return manager.getStorage();
}
}
@@ -4,11 +4,10 @@ import org.bukkit.entity.Player;
public class ChatItemPacket {
protected Player player;
protected final Player player;
protected Object packet;
protected PacketType type;
protected boolean cancel = false;
protected PacketMetadata metaData = new PacketMetadata();
public ChatItemPacket(PacketType type, Object packet, Player player) {
this.player = player;
@@ -31,6 +30,10 @@ public class ChatItemPacket {
public Object getPacket() {
return packet;
}
public void setPacket(Object packet) {
this.packet = packet;
}
public String getPacketName() {
return packet.getClass().getSimpleName();
@@ -51,8 +54,4 @@ public class ChatItemPacket {
public PacketContent getContent() {
return new PacketContent(this);
}
public PacketMetadata getMetaData() {
return metaData;
}
}
@@ -1,5 +1,7 @@
package me.dadus33.chatitem.chatmanager.v1.packets;
import java.util.Arrays;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
@@ -18,7 +20,7 @@ public class ChatItemPacketManager {
pl.getLogger().info("The plugin ProtocolLib has been detected. Loading Protocollib support ...");
packetManager = new ProtocollibPacketManager(pl);
} else {
pl.getLogger().warning("The plugin ProtocolLib has been detected but you have an OLD version, so we cannot use it.");
pl.getLogger().warning("The plugin ProtocolLib has been detected but you have an old or too new version, so we cannot use it.");
pl.getLogger().warning("Fallback to default Packet system ...");
packetManager = new CustomPacketManager(pl);
}
@@ -33,11 +35,12 @@ public class ChatItemPacketManager {
}
private boolean checkProtocollibConditions() {
try {
Class.forName("com.comphenix.protocol.injector.server.TemporaryPlayer");
return true;
} catch (ClassNotFoundException e) {
return false;
for(String searchedClass : Arrays.asList("com.comphenix.protocol.injector.server.TemporaryPlayer", "com.comphenix.protocol.injector.temporary.TemporaryPlayer")) { // class since 4.4.0 until 4.8.0, then the new one
try {
Class.forName(searchedClass);
return true; // class found
} catch (ClassNotFoundException e) {}
}
return false;
}
}
@@ -2,8 +2,10 @@ package me.dadus33.chatitem.chatmanager.v1.packets;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.stream.Collectors;
import me.dadus33.chatitem.utils.PacketUtils;
@@ -148,7 +150,7 @@ public class PacketContent {
* @throws NoSuchElementException if the value doesn't exist
*/
public T read(int i) {
return content.values().stream().filter(Objects::nonNull).findFirst().get();
return content.values().stream().filter(Objects::nonNull).collect(Collectors.toList()).get(i);
}
/**
@@ -169,7 +171,8 @@ public class PacketContent {
* @return the requested value.
*/
public T readSafely(int i, T defaultValue) {
return content.values().stream().filter(Objects::nonNull).findFirst().orElse(defaultValue);
List<T> vals = content.values().stream().filter(Objects::nonNull).collect(Collectors.toList());
return vals.size() <= i ? defaultValue : vals.get(i);
}
/**
@@ -185,6 +188,12 @@ public class PacketContent {
} else {
content.put(key, value);
try {
key.setAccessible(true);
/*if(Modifier.isFinal(key.getModifiers())) {
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(key, key.getModifiers() & ~Modifier.FINAL);
}*/
key.set(obj, value);
} catch (Exception e) {
e.printStackTrace();
@@ -1,29 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.packets;
import java.util.HashMap;
public class PacketMetadata {
private final HashMap<String, Object> metas = new HashMap<>();
public void setMeta(String key, Object obj) {
this.metas.put(key, obj);
}
public boolean hasMeta(String key) {
return metas.containsKey(key);
}
public void removeMeta(String key) {
metas.remove(key);
}
@SuppressWarnings("unchecked")
public <T> T getMeta(String key, T def) {
return (T) metas.getOrDefault(key, def);
}
public HashMap<String, Object> getMetas() {
return metas;
}
}
@@ -1,6 +1,7 @@
package me.dadus33.chatitem.chatmanager.v1.packets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public interface PacketType {
@@ -10,6 +11,13 @@ public interface PacketType {
String getFullName();
List<String> getAlias();
public static List<PacketType> values() {
List<PacketType> list = new ArrayList<>();
list.addAll(Arrays.asList(Server.values()));
list.addAll(Arrays.asList(Handshake.values()));
return list;
}
static final String SERVER_PREFIX = "PacketPlayOut", HANDSHAKE_PREFIX = "PacketHandshaking";
public static PacketType getType(String packetName) {
@@ -18,6 +26,10 @@ public interface PacketType {
} else if(packetName.startsWith(HANDSHAKE_PREFIX)) {
return getPacketTypeFor(packetName, Handshake.values(), Handshake.UNSET);
} else {
for(PacketType types : values()) {
if(types.getFullName().equalsIgnoreCase(packetName) || types.getAlias().contains(packetName))
return types;
}
return null;
}
}
@@ -31,7 +43,7 @@ public interface PacketType {
public static enum Server implements PacketType {
CHAT("Chat"),
CHAT("Chat", "ClientboundPlayerChatPacket", "ClientboundSystemChatPacket"),
UNSET("Unset");
private final String packetName, fullName;
@@ -41,7 +53,7 @@ public interface PacketType {
this.packetName = packetName;
this.fullName = SERVER_PREFIX + packetName;
for(String al : alias)
this.alias.add(SERVER_PREFIX + al);
this.alias.add(al);
}
@Override
@@ -83,7 +83,6 @@ public class CustomPacketManager extends PacketManager implements Listener {
public ChatItemPacket onPacketSent(PacketType type, Player sender, Object packet) {
if(type == null) {
//ChatItem.debug("Failed to find packet type for " + packet.getClass().getSimpleName());
return null;
}
ChatItemPacket customPacket = new ChatItemPacket(type, packet, sender);
@@ -9,8 +9,8 @@ import java.util.concurrent.Executors;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.ItemPlayer;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
import me.dadus33.chatitem.chatmanager.v1.playerversion.hooks.DefaultVersionHook;
public abstract class ChannelAbstract {
@@ -54,7 +54,7 @@ public abstract class ChannelAbstract {
try {
Integer protocol = customPacketManager.protocolVersionPerChannel.remove(getChannel(p));
if(protocol != null)
DefaultVersionHook.PROTOCOL_PER_UUID.put(p.getUniqueId(), protocol);
ItemPlayer.getPlayer(p).setProtocolVersion(protocol);
} catch (Exception e) {
e.printStackTrace();
}
@@ -1,24 +1,24 @@
package me.dadus33.chatitem.chatmanager.v1.packets.custom.channel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent.ContentModifier;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
public class ChannelInboundHandler extends ChannelInboundHandlerAdapter {
public static final HashMap<Channel, ChatItemPacket> TMP = new HashMap<>();
private CustomPacketManager packetManager;
private List<ChannelPipeline> pipelines = new ArrayList<>();
@@ -74,7 +74,13 @@ public class ChannelInboundHandler extends ChannelInboundHandlerAdapter {
try {
PacketType packetType = PacketType.getType(packet.getClass().getSimpleName());
if(packetType != null && packetType == PacketType.Handshake.IS_SET_PROTOCOL) {
packetManager.protocolVersionPerChannel.put(channel, new PacketContent(packet).getIntegers().readSafely(0, 0));
ContentModifier<Integer> ints = new PacketContent(packet).getIntegers();
int possibleProtocol = ints.readSafely(0, 0);
if(possibleProtocol == Bukkit.getPort())
possibleProtocol = ints.readSafely(1, 0);
if(possibleProtocol == -1 || possibleProtocol == 255)
possibleProtocol = ints.readSafely(2, 0);
packetManager.protocolVersionPerChannel.put(channel, possibleProtocol);
}
super.channelRead(ctx, packet);
} catch (Exception e) {
@@ -17,7 +17,6 @@ import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
import me.dadus33.chatitem.chatmanager.v1.playerversion.hooks.DefaultVersionHook;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
import me.dadus33.chatitem.utils.Version;
@@ -34,7 +33,7 @@ public class INC2Channel extends ChannelAbstract {
try {
Object mcServer = ReflectionUtils.callMethod(PacketUtils.getCraftServer(), Version.getVersion().equals(Version.V1_17) ? "getServer" : "b");
Object co = ReflectionUtils.getFirstWith(mcServer, PacketUtils.getNmsClass("MinecraftServer", "server."), PacketUtils.getNmsClass("ServerConnection", "server.network."));
((List<ChannelFuture>) ReflectionUtils.getField(co, "f")).forEach((channelFuture) -> {
((List<ChannelFuture>) ReflectionUtils.getObject(co, "f")).forEach((channelFuture) -> {
pipeline = channelFuture.channel().pipeline();
pipeline.addFirst(boundHandler);
});
@@ -58,10 +57,6 @@ public class INC2Channel extends ChannelAbstract {
Channel channel = getChannel(player);
// Managing outgoing packet (to the player)
channel.pipeline().addAfter(KEY_HANDLER_SERVER, KEY_SERVER + endChannelName, new ChannelHandlerSent(player));
ChatItemPacket pa = ChannelInboundHandler.TMP.remove(channel);
if(pa != null)
DefaultVersionHook.PROTOCOL_PER_UUID.put(player.getUniqueId(), pa.getContent().getIntegers().readSafely(0, Version.getVersion().MAX_VER));
} catch (NoSuchElementException e) {
// appear when the player's channel isn't accessible because of reload.
getPacketManager().getPlugin().getLogger().warning("Please, don't use reload, this can produce some problem. Currently, " + player.getName() + " isn't fully checked because of that. More details: " + e.getMessage() + " (NoSuchElementException)");
@@ -92,9 +87,9 @@ public class INC2Channel extends ChannelAbstract {
@Override
public Channel getChannel(Player p) throws Exception {
Object playerConnection = getPlayerConnection(p);
Object networkManager = playerConnection.getClass().getField("a").get(playerConnection);
return (Channel) networkManager.getClass().getDeclaredField("k").get(networkManager);//(Channel) networkManager.getClass().getDeclaredField("channel").get(networkManager);
Class<?> networkClass = PacketUtils.getNmsClass("NetworkManager", "network.");
Object networkManager = ReflectionUtils.getFirstWith(getPlayerConnection(p), PacketUtils.getNmsClass("PlayerConnection", "server.network."), networkClass);
return ReflectionUtils.getFirstWith(networkManager, networkClass, Channel.class);
}
private class ChannelHandlerSent extends ChannelOutboundHandlerAdapter {
@@ -110,7 +105,7 @@ public class INC2Channel extends ChannelAbstract {
ChatItemPacket nextPacket = getPacketManager().onPacketSent(PacketType.getType(packet.getClass().getSimpleName()), owner, packet);
if(nextPacket != null && nextPacket.isCancelled())
return;
super.write(ctx, packet, promise);
super.write(ctx, nextPacket == null ? packet : nextPacket.getPacket(), promise);
}
}
}
@@ -19,10 +19,8 @@ import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
import me.dadus33.chatitem.chatmanager.v1.playerversion.hooks.DefaultVersionHook;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
import me.dadus33.chatitem.utils.Version;
@SuppressWarnings("unchecked")
public class INCChannel extends ChannelAbstract {
@@ -70,10 +68,6 @@ public class INCChannel extends ChannelAbstract {
Channel channel = getChannel(player);
// Managing outgoing packet (to the player)
channel.pipeline().addAfter(KEY_HANDLER_SERVER, KEY_SERVER + endChannelName, new ChannelHandlerSent(player));
ChatItemPacket pa = ChannelInboundHandler.TMP.remove(channel);
if(pa != null)
DefaultVersionHook.PROTOCOL_PER_UUID.put(player.getUniqueId(), pa.getContent().getIntegers().readSafely(0, Version.getVersion().MAX_VER));
} catch (NoSuchElementException e) {
// appear when the player's channel isn't accessible because of reload.
getPacketManager().getPlugin().getLogger().warning("Please, don't use reload, this can produce some problem. Currently, " + player.getName() + " isn't fully checked because of that. More details: " + e.getMessage() + " (NoSuchElementException)");
@@ -123,7 +117,7 @@ public class INCChannel extends ChannelAbstract {
ChatItemPacket nextPacket = getPacketManager().onPacketSent(PacketType.getType(packet.getClass().getSimpleName()), owner, packet);
if(nextPacket != null && nextPacket.isCancelled())
return;
super.write(ctx, packet, promise);
super.write(ctx, nextPacket == null ? packet : nextPacket.getPacket(), promise);
}
}
}
@@ -37,7 +37,7 @@ public class NMUChannel extends ChannelAbstract {
Object mcServer = dedicatedSrv.getClass().getMethod("getServer").invoke(dedicatedSrv);
Object co = ReflectionUtils.getFirstWith(mcServer, PacketUtils.getNmsClass("MinecraftServer", "server."), PacketUtils.getNmsClass("ServerConnection", "network."));
@SuppressWarnings("unchecked")
List<ChannelFuture> g = (List<ChannelFuture>) ReflectionUtils.getField(co, "g");
List<ChannelFuture> g = (List<ChannelFuture>) ReflectionUtils.getObject(co, "g", "e");
g.forEach((channelFuture) -> {
pipeline = channelFuture.channel().pipeline();
pipeline.addFirst(boundHandler = new ChannelInboundHandlerAdapter() {
@@ -139,7 +139,7 @@ public class NMUChannel extends ChannelAbstract {
ChatItemPacket nextPacket = getPacketManager().onPacketSent(PacketType.getType(packet.getClass().getSimpleName()), owner, packet);
if(nextPacket != null && nextPacket.isCancelled())
return;
super.write(ctx, packet, promise);
super.write(ctx, nextPacket == null ? packet : nextPacket.getPacket(), promise);
}
}
@@ -156,7 +156,7 @@ public class NMUChannel extends ChannelAbstract {
try {
PacketType packetType = PacketType.getType(packet.getClass().getSimpleName());
if(packetType != null && packetType == PacketType.Handshake.IS_SET_PROTOCOL) {
getPacketManager().protocolVersionPerChannel.put(channel, new PacketContent(packet).getIntegers().readSafely(0, 0));
getPacketManager().protocolVersionPerChannel.put(channel, new PacketContent(packet).getIntegers().readSafely(1, 0));
}
super.channelRead(ctx, packet);
} catch (Exception e) {
@@ -1,6 +1,7 @@
package me.dadus33.chatitem.chatmanager.v1.packets.protocollib;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.entity.Player;
@@ -23,16 +24,24 @@ public class ProtocollibPacketManager extends PacketManager {
public ProtocollibPacketManager(ChatItem pl) {
protocolManager = ProtocolLibrary.getProtocolManager();
protocolManager.addPacketListener(new PacketAdapter(pl, ListenerPriority.LOWEST, Arrays.asList(Play.Server.CHAT)) {
List<com.comphenix.protocol.PacketType> list = new ArrayList<>();
list.add(Play.Server.CHAT);
try {
list.add((com.comphenix.protocol.PacketType) Play.Server.class.getDeclaredField("SYSTEM_CHAT").get(null));
} catch (Exception e) {
// ignore because using old version
}
protocolManager.addPacketListener(new PacketAdapter(pl, ListenerPriority.LOWEST, list) {
@Override
public void onPacketSending(PacketEvent e) {
Player p = e.getPlayer();
if (p == null || e.isPlayerTemporary())
return;
ChatItemPacket packet = onPacketSent(PacketType.getType(e.getPacket().getHandle().getClass().getSimpleName()),
p, e.getPacket().getHandle());
if(packet == null)
ChatItemPacket packet = onPacketSent(PacketType.getType(e.getPacket().getHandle().getClass().getSimpleName()), p, e.getPacket().getHandle());
if(packet == null) {
ChatItem.debug("Can't find packet: " + e.getPacket().getHandle().getClass().getName());
return;
}
if(!e.isCancelled())
e.setCancelled(packet.isCancelled());
}
@@ -3,6 +3,7 @@ package me.dadus33.chatitem.chatmanager.v1.utils;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
@Deprecated
public class Item {
private String id;
private byte amount;
@@ -5,19 +5,25 @@ import static me.dadus33.chatitem.utils.Version.V1_11;
import static me.dadus33.chatitem.utils.Version.V1_8;
import static me.dadus33.chatitem.utils.Version.V1_9;
import org.bukkit.inventory.ItemStack;
@Deprecated
public class ItemRewriter {
public static void remapIds(int server, int player, Item item) {
public static String remapIds(int server, int player, ItemStack is) {
Item item = new Item();
item.setAmount((byte)is.getAmount());
//item.setData(is.getDurability());
//item.setId(id);
//item.setTag(tag);
if (areIdsCompatible(server, player)) {
return;
return item.getId();
}
if ((server >= V1_9.MIN_VER && player <= V1_8.MAX_VER) || (player >= V1_9.MIN_VER && server <= V1_8.MAX_VER)) {
if ((server >= V1_9.MIN_VER && player <= V1_8.MAX_VER)) {
ItemRewriter_1_9_TO_1_8.reversedToClient(item);
return;
}
ItemRewriter_1_9_TO_1_8.toClient(item);
return;
} else
ItemRewriter_1_9_TO_1_8.toClient(item);
}
if ((server <= V1_10.MAX_VER && player >= V1_11.MIN_VER)
|| (player <= V1_10.MAX_VER && server >= V1_11.MIN_VER)) {
@@ -27,6 +33,7 @@ public class ItemRewriter {
ItemRewriter_1_11_TO_1_10.reverseToClient(item);
}
}
return item.getId();
}
public static boolean areIdsCompatible(int version1, int version2) {
@@ -10,6 +10,7 @@ import com.google.common.collect.HashBiMap;
/**
* Thanks to the developers of ViaVersion for this!
*/
@Deprecated
public class ItemRewriter_1_11_TO_1_10 {
private static BiMap<String, String> oldToNewNames = HashBiMap.create();
@@ -9,6 +9,7 @@ import java.util.Map;
/**
* Thanks to the developers of ViaVersion for this!
*/
@Deprecated
public class ItemRewriter_1_9_TO_1_8 {
private static final Map<String, Integer> ENTTIY_NAME_TO_ID = new HashMap<>();
@@ -1,243 +1,238 @@
package me.dadus33.chatitem.chatmanager.v2;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
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.AsyncPlayerChatEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.ItemPlayer;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.itemnamer.NamerManager;
import me.dadus33.chatitem.hook.DiscordSrvSupport;
import me.dadus33.chatitem.playernamer.PlayerNamerManager;
import me.dadus33.chatitem.utils.ColorManager;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
import me.dadus33.chatitem.utils.Storage;
import me.dadus33.chatitem.utils.Utils;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.HoverEvent.Action;
import net.md_5.bungee.api.chat.TextComponent;
@SuppressWarnings("deprecation")
public class ChatListener implements Listener {
public final static char SEPARATOR = ((char)0x0007);
private final static String NAME = "{name}";
private final static String AMOUNT = "{amount}";
private final static String TIMES = "{times}";
private final static String LEFT = "{remaining}";
private final HashMap<String, Long> COOLDOWNS = new HashMap<>();
private ChatListenerChatManager manage;
private Method saveMethod;
public ChatListener(ChatListenerChatManager manage) {
this.manage = manage;
private static Method saveMethod;
private static boolean shouldUseAppendMethod = false;
static {
try {
Class<?> nbtTag = PacketUtils.getNmsClass("NBTTagCompound", "nbt.");
Class<?> itemClass = PacketUtils.getNmsClass("ItemStack", "world.item.");
for(Method m : itemClass.getDeclaredMethods()) {
if(m.getParameterTypes().length == 1) {
if(m.getParameterTypes()[0].equals(nbtTag) && m.getReturnType().equals(nbtTag)) {
saveMethod = m;
}
}
}
for (Method m : itemClass.getDeclaredMethods()) {
if (m.getParameterTypes().length == 1) {
if (m.getParameterTypes()[0].equals(nbtTag) && m.getReturnType().equals(nbtTag)) {
saveMethod = m;
}
}
}
try {
ComponentBuilder.class.getDeclaredMethod("append", BaseComponent[].class);
shouldUseAppendMethod = true;
} catch (Exception e) {
shouldUseAppendMethod = false;
}
} catch (Exception e) {
}
if(saveMethod == null)
ChatItem.getInstance().getLogger().info("Failed to find save method. Using default system...");
Logger log = ChatItem.getInstance().getLogger();
String appendMethodMsg = shouldUseAppendMethod ? "Use ComponentBuilder's method."
: "Use own ComponentBuilder append method.";
if (saveMethod == null)
log.info("Failed to find save method. Using default system. " + appendMethodMsg);
else
ChatItem.getInstance().getLogger().info("Save method founded: " + saveMethod.getName() + ".");
log.info("Save method founded: " + saveMethod.getName() + ". " + appendMethodMsg);
}
private ChatListenerChatManager manage;
public ChatListener(ChatListenerChatManager manage) {
this.manage = manage;
}
public Storage getStorage() {
return manage.getStorage();
}
private String calculateTime(long seconds){
if(seconds < 60){
return seconds+getStorage().SECONDS;
}
if(seconds < 3600){
StringBuilder builder = new StringBuilder();
int minutes = (int) seconds / 60;
builder.append(minutes).append(getStorage().MINUTES);
int secs = (int) seconds - minutes*60;
if(secs != 0){
builder.append(" ").append(secs).append(getStorage().SECONDS);
}
return builder.toString();
}
StringBuilder builder = new StringBuilder();
int hours = (int) seconds / 3600;
builder.append(hours).append(getStorage().HOURS);
int minutes = (int) (seconds/60) - (hours*60);
if(minutes != 0){
builder.append(" ").append(minutes).append(getStorage().MINUTES);
}
int secs = (int) (seconds - ((seconds/60)*60));
if(secs != 0){
builder.append(" ").append(secs).append(getStorage().SECONDS);
}
return builder.toString();
}
@SuppressWarnings("deprecation")
@EventHandler(priority = EventPriority.MONITOR)
public void onChat(AsyncPlayerChatEvent e) {
if(e.isCancelled())
return;
Player p = e.getPlayer();
for (String rep : getStorage().PLACEHOLDERS) {
if (e.getMessage().contains(rep + ChatManager.SEPARATOR + p.getName())) { // already managed by v1
return;
}
}
boolean found = false;
for(String key : e.getMessage().split(" ")) {
if(found)
break;
for (String rep : getStorage().PLACEHOLDERS) {
if (key.equalsIgnoreCase(rep)) {
found = true;
break;
}
}
}
if (!found) {
return;
}
if (!p.hasPermission("chatitem.use")) {
if(!getStorage().LET_MESSAGE_THROUGH) {
e.setCancelled(true);
}
if(!getStorage().NO_PERMISSION_MESSAGE.isEmpty() && getStorage().SHOW_NO_PERM_NORMAL){
p.sendMessage(getStorage().NO_PERMISSION_MESSAGE);
}
return;
}
if (p.getItemInHand().getType().equals(Material.AIR)) {
if (getStorage().DENY_IF_NO_ITEM) {
e.setCancelled(true);
if (!getStorage().DENY_MESSAGE.isEmpty())
e.getPlayer().sendMessage(getStorage().DENY_MESSAGE);
return;
}
if(getStorage().HAND_DISABLED) {
return;
}
}
if(getStorage().COOLDOWN > 0 && !p.hasPermission("chatitem.ignore-cooldown")){
if(COOLDOWNS.containsKey(p.getName())){
long start = COOLDOWNS.get(p.getName());
long current = System.currentTimeMillis()/1000;
long elapsed = current - start;
if(elapsed >= getStorage().COOLDOWN){
COOLDOWNS.remove(p.getName());
} else {
if(!getStorage().LET_MESSAGE_THROUGH) {
e.setCancelled(true);
}
if(!getStorage().COOLDOWN_MESSAGE.isEmpty()){
long left = (start + getStorage().COOLDOWN) - current;
p.sendMessage(getStorage().COOLDOWN_MESSAGE.replace(LEFT, calculateTime(left)));
}
return;
}
}
}
e.setCancelled(true);
String format = e.getFormat(), defMsg = e.getMessage();
Bukkit.getConsoleSender().sendMessage(String.format(e.getFormat(), e.getPlayer().getDisplayName(), defMsg)); // show in log
boolean isAlreadyParsed = false;
if(format.contains("%1$s") && format.contains("%2$s")) // message not parsed but not default way
isAlreadyParsed = false;
if(format.equalsIgnoreCase(defMsg)) // is message already parsed
isAlreadyParsed = true;
if(format.equalsIgnoreCase("<%1$s> %2$s")) // default MC message
isAlreadyParsed = false;
String msg = isAlreadyParsed ? format : String.format(format, p.getDisplayName(), defMsg);
ItemStack item = p.getItemInHand();
ItemMeta meta = item == null ? null : item.getItemMeta();
e.getRecipients().forEach((pl) -> {
TextComponent component = new TextComponent("");
ChatColor color = ChatColor.getByChar(getColorChat(e.getFormat()));
for (String args : msg.split(" ")) {
if (getStorage().PLACEHOLDERS.contains(args)) {
if(meta != null) {
TextComponent itemComponent = new TextComponent(ChatListener.styleItem(pl, item, getStorage()));
String itemJson = convertItemStackToJson(item);
itemComponent.setHoverEvent(
new HoverEvent(Action.SHOW_ITEM, new BaseComponent[] { new TextComponent(itemJson) }));
component.addExtra(itemComponent);
} else {
if(getStorage().HAND_DISABLED)
component.addExtra(color + args);
else {
String handName = getStorage().HAND_NAME;
TextComponent handComp = new TextComponent("");
ComponentBuilder handTooltip = new ComponentBuilder();
int stay = getStorage().HAND_TOOLTIP.size();
for(String line : getStorage().HAND_TOOLTIP) {
stay--;
handTooltip.append(line.replace("{name}", p.getName()).replace("{display-name}", p.getDisplayName()));
if(stay > 0)
handTooltip.append("\n");
}
handComp.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,handTooltip.create()));
if(handName.contains("{name}")) {
String[] splitted = handName.split("{name}");
for(int i = 0; i < (splitted.length - 1); i++) {
handComp.addExtra(new TextComponent(splitted[i]));
handComp.addExtra(PlayerNamerManager.getPlayerNamer().getName(p));
}
handComp.addExtra(new TextComponent(splitted[splitted.length - 1]));
} else
handComp.addExtra(handName.replace("{display-name}", p.getDisplayName()));
component.addExtra(handComp);
}
Storage c = getStorage();
if (e.isCancelled()) {
if (ChatItem.getInstance().getChatManager().size() == 1) { // only chat
String msg = e.getMessage().toLowerCase();
for (String rep : c.PLACEHOLDERS) {
if (msg.contains(rep)) {
ChatItem.debug(
"You choose 'chat' manager but it seems to don't be the good choice. More informations here: https://github.com/dadus33-plugins/ChatItem/wiki");
return;
}
} else {
component.addExtra(color + args);
}
component.addExtra(" ");
char maybeNextCode = getColorChat(args);
if(maybeNextCode != 'r') {
color = ChatColor.getByChar(maybeNextCode);
}
}
pl.spigot().sendMessage(component);
});
//Utils.getOnlinePlayers().forEach((pl) -> pl.spigot().sendMessage(component));
ChatItem.debug("Chat cancelled for " + e.getPlayer().getName());
return;
}
Player p = e.getPlayer();
boolean hasv1 = false;
String placeholder = null;
// v1 try to manage it, but the message have not been changed by another plugin
if (e.getMessage().contains(ChatManager.SEPARATOR + p.getName())) {
hasv1 = true;
ChatItem.debug("Found v1 placeholders in v2");
placeholder = "";
} else {
for (String rep : c.PLACEHOLDERS) {
if (e.getMessage().contains(rep)) {
placeholder = rep;
break;
}
}
}
if (placeholder == null) { // if not found
ChatItem.debug("(v2) Can't found placeholder in: " + e.getMessage() + " > " + PlayerNamerManager.getPlayerNamer().getName(p));
return;
}
ItemStack item = ChatManager.getUsableItem(p);
if(!ChatManager.canShowItem(p, item, e))
return;
e.setCancelled(true);
String format = e.getFormat();
String msg, defMsg = e.getMessage();
for (String rep : c.PLACEHOLDERS) {
if (hasv1) // remove v1 char
defMsg = defMsg.replace(ChatManager.SEPARATOR + p.getName(), String.valueOf(ChatManager.SEPARATOR));
else
defMsg = defMsg.replace(rep, String.valueOf(ChatManager.SEPARATOR));
}
if (Utils.countMatches(defMsg, String.valueOf(ChatManager.SEPARATOR)) > getStorage().LIMIT) {
e.setCancelled(true);
if (getStorage().LIMIT_MESSAGE.isEmpty()) {
return;
}
p.sendMessage(getStorage().LIMIT_MESSAGE);
return;
}
if (format.contains("%1$s") || format.contains("%2$s")) {
msg = (format.contains("%2$s") ? String.format(format, p.getDisplayName(), defMsg)
: String.format(format, p.getDisplayName()));
} else {
msg = format.replace(e.getMessage(), defMsg);
}
String itemName = ChatManager.getNameOfItem(p, item, c);
String loggedMessage = msg.replace(ChatManager.SEPARATOR + "", itemName).replace("{name}", p.getName())
.replace("{display-name}", p.getDisplayName());
Bukkit.getConsoleSender().sendMessage(loggedMessage); // show in log
if (ChatItem.discordSrvSupport)
DiscordSrvSupport.sendChatMessage(p, defMsg.replace(ChatManager.SEPARATOR + "", itemName).replace("{name}", p.getName())
.replace("{display-name}", p.getDisplayName()));
ChatItem.debug("Msg: " + msg.replace(ChatColor.COLOR_CHAR, '&') + ", format: " + format + " to " + e.getRecipients().size() + " players");
if(e.getRecipients().isEmpty()) {// should not appear
ChatItem.debug("Empty recipients ???");
} else
e.getRecipients().forEach((pl) -> showItem(pl, p, item, msg));
if (c.COOLDOWN > 0 && !p.hasPermission("chatitem.ignore-cooldown"))
ChatManager.applyCooldown(p);
}
public static void showItem(Player to, Player origin, ItemStack item, String msg) {
ComponentBuilder builder = new ComponentBuilder("");
ChatColor color = ChatColor.WHITE;
String colorCode = "", text = "";
boolean waiting = false;
for (char args : msg.toCharArray()) {
if (args == '§') { // begin of color
if (colorCode.isEmpty() && !text.isEmpty()) { // text before this char
ChatItem.debug("Append " + text);
appendToComponentBuilder(builder, new ComponentBuilder(text).color(color).create());
text = "";
}
waiting = true; // waiting for color code
} else if (waiting) { // if waiting for code and valid str
// if it's hexademical value and with enough space for full color
waiting = false;
if(args == 'r' && colorCode.isEmpty()) {
color = ChatColor.RESET;
continue;
}
if(args == 'x' && !colorCode.isEmpty()) {
text += ColorManager.getColorString(colorCode);
colorCode = "x";
} else
colorCode += args; // a color by itself
} else {
waiting = false;
if(!colorCode.isEmpty()) {
if(colorCode.startsWith("x") && colorCode.length() >= 7) {
if(colorCode.length() == 7)
color = ColorManager.getColor(colorCode);
else {
color = ColorManager.getColor(colorCode.substring(0, 7)); // only the hex code
ChatItem.debug("Adding color for " + colorCode.substring(7, colorCode.length()) + " (in " + colorCode + ")");
text += ColorManager.getColorString(colorCode.substring(7, colorCode.length()));
}
} else if(colorCode.length() == 1) // if only one color code
color = ColorManager.getColor(colorCode);
else
text += ColorManager.getColorString(colorCode);
colorCode = "";
}
if (args == ChatManager.SEPARATOR) {
// here put the item
appendToComponentBuilder(builder, fixColorComponent(text, color));
addItem(builder, to, origin, item);
text = "";
} else {
// basic text, not waiting for code after '§'
text += args;
}
}
}
if(!text.isEmpty())
appendToComponentBuilder(builder, new ComponentBuilder(text).color(color).create());
to.spigot().sendMessage(builder.create());
}
/**
* Converts an {@link org.bukkit.inventory.ItemStack} to a Json string for
* sending with {@link net.md_5.bungee.api.chat.BaseComponent}'s.
*
* @param itemStack
* the item to convert
* @param itemStack the item to convert
* @return the Json string representation of the item
*/
public String convertItemStackToJson(ItemStack itemStack) {
public static String convertItemStackToJson(ItemStack itemStack) {
try {
Class<?> nbtTag = PacketUtils.getNmsClass("NBTTagCompound", "nbt.");
Class<?> craftItemClass = PacketUtils.getObcClass("inventory.CraftItemStack");
Object nmsNbtTagCompoundObj = nbtTag.newInstance();
if(saveMethod == null) {
Object nmsNbtTagCompoundObj = nbtTag.getConstructor().newInstance();
if (saveMethod == null) {
Object nmsItemStackObj = craftItemClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, itemStack);
return nmsItemStackObj.getClass().getMethod("save", nbtTag).invoke(nmsItemStackObj, nmsNbtTagCompoundObj).toString();
return nmsItemStackObj.getClass().getMethod("save", nbtTag)
.invoke(nmsItemStackObj, nmsNbtTagCompoundObj).toString();
} else {
Object nmsItemStackObj = craftItemClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, itemStack);
return saveMethod.invoke(nmsItemStackObj, nmsNbtTagCompoundObj).toString();
@@ -247,42 +242,125 @@ public class ChatListener implements Listener {
return null;
}
}
/**
* Get the latest color chat
*
* @param msg the message that contains color
* @return the char of the color or 'r' if nothing found
*/
private char getColorChat(String msg) {
if(msg.length() < 2)
return 'r';
for(int i = msg.length() - 2; i > 0; i--) {
char s = msg.charAt(i);
if(ChatColor.COLOR_CHAR == s) {
return msg.charAt(i + 1);
public static void addItem(ComponentBuilder builder, Player to, Player origin, ItemStack item) {
Storage c = ChatItem.getInstance().getStorage();
if (!ItemUtils.isEmpty(item)) {
ComponentBuilder itemComponent = new ComponentBuilder("");
String itemJson = convertItemStackToJson(item);
BaseComponent[] itemBaseComponent = new ComponentBuilder(itemJson).create();
appendToComponentBuilder(itemComponent, fixColorComponent(ChatManager.getNameOfItem(to, item, c), ChatColor.WHITE, itemBaseComponent));
ChatItem.debug("Item for " + to.getName() + " (ver: " + ItemPlayer.getPlayer(to).getVersion().name() + ") : " + itemJson);
//itemComponent.event(new HoverEvent(Action.SHOW_ITEM, itemBaseComponent));
appendToComponentBuilder(builder, itemComponent.create());
} else {
String handName = c.HAND_NAME;
ComponentBuilder handComp = new ComponentBuilder("");
ComponentBuilder handTooltip = new ComponentBuilder("");
int stay = c.HAND_TOOLTIP.size();
for (String line : c.HAND_TOOLTIP) {
stay--;
handTooltip.append(ColorManager.fixColor(line.replace("{name}", origin.getName()).replace("{display-name}", origin.getDisplayName())));
if (stay > 0)
handTooltip.append("\n");
}
handComp.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, handTooltip.create()));
if (handName.contains("{display-name}")) {
String[] splitted = handName.split("\\{display-name\\}");
for (int i = 0; i < (splitted.length - 1); i++) {
handComp.append(splitted[i]);
appendToComponentBuilder(handComp, PlayerNamerManager.getPlayerNamer().getName(origin));
}
handComp.append(splitted[splitted.length - 1]);
} else
handComp.append(handName.replace("{name}", origin.getName()));
appendToComponentBuilder(builder, handComp.create());
}
return 'r';
}
public static String styleItem(Player p, ItemStack item, Storage c) {
String replacer = c.NAME_FORMAT;
String amount = c.AMOUNT_FORMAT;
if (item.getAmount() == 1) {
if (c.FORCE_ADD_AMOUNT) {
amount = amount.replace(TIMES, "1");
replacer = replacer.replace(AMOUNT, amount);
} else {
replacer = replacer.replace(AMOUNT, "");
public static void appendToComponentBuilder(ComponentBuilder builder, BaseComponent[] comps) {
if (shouldUseAppendMethod) {
try {
builder.append(comps);
} catch (Exception e) {
ChatItem.getInstance().getLogger().severe(
"This should NEVER append. The ComponentBuilder#append(BaseComponent[]) was found but it's NOT. Using own next time.");
shouldUseAppendMethod = false;
}
} else {
amount = amount.replace(TIMES, String.valueOf(item.getAmount()));
replacer = replacer.replace(AMOUNT, amount);
try {
Field currentField = ReflectionUtils.getField(builder, "current");
List<BaseComponent> parts = (List<BaseComponent>) ReflectionUtils.getObject(builder, "parts");
parts.add(new TextComponent((TextComponent) currentField.get(builder)));
parts.addAll(Arrays.asList(comps));
currentField.set(builder, new TextComponent(""));
} catch (Exception e) {
e.printStackTrace();
}
}
replacer = replacer.replace(NAME, NamerManager.getName(p, item, c));
return replacer;
}
public static BaseComponent[] fixColorComponent(String message, ChatColor color) {
return fixColorComponent(message, color, null);
}
public static BaseComponent[] fixColorComponent(String message, ChatColor color, @Nullable BaseComponent[] jsonItem) {
ComponentBuilder builder = new ComponentBuilder("");
String colorCode = "", text = "";
boolean waiting = false;
for (char args : message.toCharArray()) {
if (args == '§') { // begin of color
if (colorCode.isEmpty() && !text.isEmpty()) { // text before this char
ChatItem.debug("Append while fixing name " + (ColorManager.isHexColor(color) && builder.getParts().isEmpty() ? ColorManager.removeColorAtBegin(text) : text));
ComponentBuilder littleBuilder = new ComponentBuilder(ColorManager.isHexColor(color) ? ColorManager.removeColorAtBegin(text) : text).color(color);
if(jsonItem != null) { // add to all possible sub parts
littleBuilder.event(new HoverEvent(Action.SHOW_ITEM, jsonItem));
}
appendToComponentBuilder(builder, littleBuilder.create());
text = "";
}
waiting = true; // waiting for color code
} else if (waiting) { // if waiting for code and valid str
// if it's hexademical value and with enough space for full color
waiting = false;
if(args == 'r' && colorCode.isEmpty()) {
color = ChatColor.RESET;
continue;
}
if(args == 'x' && !colorCode.isEmpty()) {
text += ColorManager.getColorString(colorCode);
colorCode = "x";
} else
colorCode += args; // a color by itself
} else {
waiting = false;
if(!colorCode.isEmpty()) {
if(colorCode.startsWith("x") && colorCode.length() >= 7) {
if(colorCode.length() == 7)
color = ColorManager.getColor(colorCode);
else {
color = ColorManager.getColor(colorCode.substring(0, 7)); // only the hex code
ChatItem.debug("Adding color for " + colorCode.substring(7, colorCode.length()) + " (in " + colorCode + ")");
text += ColorManager.getColorString(colorCode.substring(7, colorCode.length()));
}
} else if(colorCode.length() == 1) // if only one color code
color = ColorManager.getColor(colorCode);
else
text += ColorManager.getColorString(colorCode);
ChatItem.debug("Color: " + color + ", text: " + text + ", code: " + colorCode);
colorCode = "";
}
// basic text, not waiting for code after '§'
text += args;
}
}
if(!text.isEmpty()) {
ComponentBuilder littleBuilder = new ComponentBuilder(text).color(color);
if(jsonItem != null) { // add to all possible sub parts
littleBuilder.event(new HoverEvent(Action.SHOW_ITEM, jsonItem));
}
appendToComponentBuilder(builder, littleBuilder.create());
}
return builder.create();
}
}
@@ -5,18 +5,14 @@ import org.bukkit.event.HandlerList;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulator;
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulatorCurrent;
import me.dadus33.chatitem.utils.Storage;
public class ChatListenerChatManager extends ChatManager {
private final JSONManipulatorCurrent jsonManipulator;
private final ChatListener chatListener;
private boolean baseComponentAvailable = true;
public ChatListenerChatManager(ChatItem pl) {
jsonManipulator = new JSONManipulatorCurrent();
chatListener = new ChatListener(this);
//Check for existence of BaseComponent class (only on spigot)
@@ -48,15 +44,6 @@ public class ChatListenerChatManager extends ChatManager {
public void unload(ChatItem pl) {
HandlerList.unregisterAll(chatListener);
}
public JSONManipulator getManipulator(){
/*
We used to have 2 kinds of JSONManipulators because of my bad understanding of the 1.7 way of parsing JSON chat
The interface should however stay as there might be great changes in future versions in JSON parsing (most likely 1.13)
*/
return jsonManipulator;
//We just return a new one whenever requested for the moment, should implement a cache of some sort some time though
}
public boolean supportsChatComponentApi(){
return baseComponentAvailable;
@@ -5,14 +5,18 @@ import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v2.ChatListener;
import me.dadus33.chatitem.listeners.InventoryListener;
import me.dadus33.chatitem.utils.Messages;
import me.dadus33.chatitem.utils.Storage;
@@ -20,50 +24,71 @@ import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.hover.content.Text;
public class ChatItemCommand implements CommandExecutor, TabExecutor {
@SuppressWarnings("deprecation")
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if(!(sender instanceof Player)) {
Messages.sendMessage(sender, "only-players");
return false;
}
Player p = (Player) sender;
if(args.length == 0) {
Messages.sendMessage(p, "chatitem-cmd.help");
} else if(args[0].equalsIgnoreCase("admin")) {
InventoryListener.open(p);
} else if(args[0].equalsIgnoreCase("reload")) {
ChatItem.reload(sender);
} else if(args[0].equalsIgnoreCase("link") || args[0].equalsIgnoreCase("links")) {
ConfigurationSection config = ChatItem.getInstance().getConfig().getConfigurationSection("messages.chatitem-cmd.links");
TextComponent text = new TextComponent(Storage.color(config.getString("begin")));
for(String key : config.getConfigurationSection("list").getKeys(false)) {
ConfigurationSection linkConfig = config.getConfigurationSection("list." + key);
TextComponent linkComp = new TextComponent(Storage.color(linkConfig.getString("message")));
String hover = Storage.color(linkConfig.getString("hover"));
if(hover != null)
linkComp.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(hover).create()));
String link = linkConfig.getString("link");
if(link != null)
linkComp.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, link));
text.addExtra(linkComp);
}
p.spigot().sendMessage(text);
} else {
Messages.sendMessage(p, "chatitem-cmd.help");
}
return false;
}
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (!(sender instanceof Player)) {
Messages.sendMessage(sender, "only-players");
return false;
}
Player p = (Player) sender;
if (args.length == 0) {
Messages.sendMessage(p, "chatitem-cmd.help");
} else if (args[0].equalsIgnoreCase("admin")) {
InventoryListener.open(p);
} else if (args[0].equalsIgnoreCase("reload")) {
ChatItem.reload(sender);
} else if (args[0].equalsIgnoreCase("show")) {
Player cible = args.length == 1 ? p : Bukkit.getPlayer(args[1]);
if(cible == null) {
Messages.sendMessage(p, "player-not-found", "%arg%", args[1]);
return false;
}
Storage c = ChatItem.getInstance().getStorage();
ItemStack item = ChatManager.getUsableItem(cible);
ChatListener.showItem(p, cible, item, c.COMMAND_FORMAT.replace("%name%", cible.getName()).replace("%item%", ChatManager.SEPARATOR + ""));
} else if (args[0].equalsIgnoreCase("broadcast")) {
Player cible = args.length == 1 ? p : Bukkit.getPlayer(args[1]);
if(cible == null) {
Messages.sendMessage(p, "player-not-found", "%arg%", args[1]);
return false;
}
Storage c = ChatItem.getInstance().getStorage();
ItemStack item = ChatManager.getUsableItem(cible);
for(Player all : Bukkit.getOnlinePlayers())
ChatListener.showItem(all, cible, item, c.COMMAND_FORMAT.replace("%name%", cible.getName()).replace("%item%", ChatManager.SEPARATOR + ""));
} else if (args[0].equalsIgnoreCase("link") || args[0].equalsIgnoreCase("links")) {
ConfigurationSection config = ChatItem.getInstance().getConfig()
.getConfigurationSection("messages.chatitem-cmd.links");
TextComponent text = new TextComponent(Storage.color(config.getString("begin")));
for (String key : config.getConfigurationSection("list").getKeys(false)) {
ConfigurationSection linkConfig = config.getConfigurationSection("list." + key);
TextComponent linkComp = new TextComponent(Storage.color(linkConfig.getString("message")));
String hover = Storage.color(linkConfig.getString("hover"));
if (hover != null)
linkComp.setHoverEvent(
new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(new ComponentBuilder(hover).create())));
String link = linkConfig.getString("link");
if (link != null)
linkComp.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, link));
text.addExtra(linkComp);
}
p.spigot().sendMessage(text);
} else {
Messages.sendMessage(p, "chatitem-cmd.help");
}
return false;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] arg) {
List<String> list = new ArrayList<>();
String prefix = arg[arg.length - 1].toLowerCase(Locale.ROOT);
for(String s : Arrays.asList("help", "admin", "reload"))
if(prefix.isEmpty() || s.startsWith(prefix))
for (String s : Arrays.asList("help", "admin", "reload", "link", "show", "broadcast"))
if (prefix.isEmpty() || s.startsWith(prefix))
list.add(s);
return list.isEmpty() ? null : list;
}
@@ -12,72 +12,70 @@ import org.apache.logging.log4j.message.Message;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.chatmanager.v2.ChatListener;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.utils.Storage;
public class Log4jFilter implements Filter {
private Storage c;
private Storage c;
public Log4jFilter(Storage st){
c = st;
((Logger) LogManager.getRootLogger()).addFilter(this);
}
public Log4jFilter(Storage st) {
c = st;
((Logger) LogManager.getRootLogger()).addFilter(this);
}
@Override
public Result getOnMismatch() {
return NEUTRAL;
}
@Override
public Result getOnMismatch() {
return NEUTRAL;
}
@Override
public Result getOnMatch() {
return NEUTRAL;
}
@Override
public Result getOnMatch() {
return NEUTRAL;
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String s, Object... objects) {
return checkMessage(s);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String s, Object... objects) {
return checkMessage(s);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, Object o, Throwable throwable) {
return checkMessage(((Message) o).getFormattedMessage());
}
@Override
public Result filter(Logger logger, Level level, Marker marker, Object o, Throwable throwable) {
return checkMessage(((Message)o).getFormattedMessage());
}
@Override
public Result filter(Logger logger, Level level, Marker marker, Message message, Throwable throwable) {
return checkMessage(message.getFormattedMessage());
}
@Override
public Result filter(Logger logger, Level level, Marker marker, Message message, Throwable throwable) {
return checkMessage(message.getFormattedMessage());
}
@Override
public Result filter(LogEvent logEvent) {
return checkMessage(logEvent.getMessage().getFormattedMessage());
}
@Override
public Result filter(LogEvent logEvent) {
return checkMessage(logEvent.getMessage().getFormattedMessage());
}
public void stop() {
// seems to be required
}
public void stop() {
// seems to be required
}
private Result checkMessage(String msg){
if(msg==null){
return Result.NEUTRAL;
}
for(String placeholder : c.PLACEHOLDERS){
if(msg.contains(placeholder)){
for(Player p : Bukkit.getOnlinePlayers()){
if(msg.contains(ChatListener.SEPARATOR +p.getName())){
return Result.DENY;
}
}
private Result checkMessage(String msg) {
if (msg == null) {
return Result.NEUTRAL;
}
for (String placeholder : c.PLACEHOLDERS) {
if (msg.contains(placeholder)) {
for (Player p : Bukkit.getOnlinePlayers()) {
if (msg.contains(ChatManager.SEPARATOR + p.getName())) {
return Result.DENY;
}
}
}
}
return Result.NEUTRAL;
}
}
}
return Result.NEUTRAL;
}
public void setStorage(Storage nst){
this.c = nst;
}
public void setStorage(Storage nst) {
this.c = nst;
}
}
@@ -0,0 +1,16 @@
package me.dadus33.chatitem.hook;
import org.bukkit.entity.Player;
import github.scarsz.discordsrv.DiscordSRV;
public class DiscordSrvSupport {
public static void sendChatMessage(Player p, String message) {
DiscordSRV pl = DiscordSRV.getPlugin();
if (DiscordSRV.config().getBooleanElse("UseModernPaperChatEvent", false) && pl.isModernChatEventAvailable()) {
return;
}
pl.processChatMessage(p, message, pl.getOptionalChannel("global"), false);
}
}
@@ -0,0 +1,21 @@
package me.dadus33.chatitem.hook;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.inventory.ItemStack;
import com.willfp.ecoenchants.display.EnchantmentCache;
import com.willfp.ecoenchants.enchantments.util.EnchantChecks;
public class EcoEnchantsSupport {
public static List<String> getLores(ItemStack item) {
List<String> lores = new ArrayList<>();
EnchantChecks.getEnchantsOnItem(item).forEach((en, lvl) -> {
lores.add(EnchantmentCache.getEntry(en).getNameWithLevel(lvl));
});
return lores;
}
}
@@ -30,7 +30,7 @@ public interface INamer {
*/
String getName(Player p, ItemStack item, Storage storage);
public static enum Priority {
enum Priority {
MAJOR(4),
IMPORTANT(3),
MEDIUM(2),
@@ -39,7 +39,7 @@ public interface INamer {
private final int priority;
private Priority(int priority) {
Priority(int priority) {
this.priority = priority;
}
@@ -48,7 +48,7 @@ public interface INamer {
}
public static List<Priority> getOrderedPriorities() {
return Arrays.asList(values()).stream().sorted((p1, p2) -> p2.getPriority() - p1.getPriority()).collect(Collectors.toList());
return Arrays.stream(values()).sorted((p1, p2) -> p2.getPriority() - p1.getPriority()).collect(Collectors.toList());
}
}
}
@@ -56,8 +56,9 @@ public class NamerManager {
/**
* Get the name of this item, according to this storage.
*
* @param item
* @param storage
* @param p the player that will see the name
* @param item the item to show
* @param storage the storage
* @return the name (should NOT return null)
*/
public static String getName(Player p, ItemStack item, Storage storage) {
@@ -21,9 +21,7 @@ public class ChatItemTranslationNamer implements INamer {
if (translationSection != null) {
@SuppressWarnings("deprecation")
String translated = translationSection.get(item.getDurability());
if (translated != null) {
return translated;
}
return translated;
}
return null;
}
@@ -41,7 +41,7 @@ public class InventoryListener implements Listener {
p.closeInventory();
ChatItem.reload(p);
}
} else if(type.equals(Material.INK_SAC)) {
} else if(type.equals(ItemUtils.INK_SAC)) {
setInConfig("general.color-if-already-colored", c.COLOR_IF_ALREADY_COLORED = !c.COLOR_IF_ALREADY_COLORED);
open(p);
} else if(type.equals(Material.REDSTONE)) {
@@ -50,6 +50,12 @@ public class InventoryListener implements Listener {
} else if(type.equals(Material.STICK)) {
setInConfig("general.hand.disabled", c.HAND_DISABLED = !c.HAND_DISABLED);
open(p);
} else if(type.equals(Material.BOOK)) {
setInConfig("general.check-update", c.CHECK_UPDATE = !c.CHECK_UPDATE);
open(p);
} else if(type.equals(ItemUtils.FIREWORK_CHARGE)) {
setInConfig("debug", c.DEBUG = !c.DEBUG);
open(p);
} else if(type.equals(Material.IRON_DOOR)) {
if(e.getClick().equals(ClickType.RIGHT))
c.LIMIT--;
@@ -86,12 +92,15 @@ public class InventoryListener implements Listener {
inv.setItem(slot++, getManagerItem(manager));
}
inv.setItem(slot + 1, getManagerItem("actual", "%manager%", Messages.getMessage("admin-inv.manager." + c.MANAGER + ".name")));
inv.setItem(8, getBoolChangeItem(ItemUtils.FIREWORK_CHARGE, "debug", c.DEBUG));
inv.setItem(18, getBoolChangeItem(Material.INK_SAC, "color-if-already-colored", c.COLOR_IF_ALREADY_COLORED));
inv.setItem(18, getBoolChangeItem(ItemUtils.INK_SAC, "color-if-already-colored", c.COLOR_IF_ALREADY_COLORED));
inv.setItem(19, getBoolChangeItem(Material.REDSTONE, "deny-no-item", c.DENY_IF_NO_ITEM));
inv.setItem(20, getBoolChangeItem(Material.STICK, "hand-disabled", c.HAND_DISABLED));
inv.setItem(21, getAmountChangeItem(Material.IRON_DOOR, "limit-per-message", c.LIMIT));
inv.setItem(22, getAmountChangeItem(Material.APPLE, "cooldown", c.COOLDOWN));
inv.setItem(23, getBoolChangeItem(Material.BOOK, "check-update", c.CHECK_UPDATE));
inv.setItem(26, createItem(ItemUtils.MATERIAL_CLOSE, Messages.getMessage("admin-inv.close")));
p.openInventory(inv);
@@ -4,16 +4,18 @@ import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.hover.content.Text;
public class JoinListener implements Listener {
@SuppressWarnings("deprecation")
@EventHandler
public void onJoin(PlayerJoinEvent e) {
Player p = e.getPlayer();
@@ -22,9 +24,14 @@ public class JoinListener implements Listener {
ChatItem pl = ChatItem.getInstance();
if(pl.isHasNewVersion()) {
TextComponent text = new TextComponent(pl.getStorage().JOIN_UPDATE_MESSAGE);
text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(pl.getStorage().JOIN_UPDATE_HOVER).create()));
text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(new ComponentBuilder(pl.getStorage().JOIN_UPDATE_HOVER).create())));
text.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.spigotmc.org/resources/19064/"));
p.spigot().sendMessage(text);
}
}
@EventHandler
public void onLeft(PlayerQuitEvent e) {
ChatManager.clear(e.getPlayer());
}
}
@@ -2,10 +2,10 @@ package me.dadus33.chatitem.playernamer;
import org.bukkit.entity.Player;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.BaseComponent;
public interface IPlayerNamer {
public TextComponent getName(Player p);
public BaseComponent[] getName(Player p);
}
@@ -22,7 +22,6 @@ public class PlayerNamerManager {
pl.getLogger().info("Enable support for HexNicks plugin !");
} else {
setPlayerNamer(new DefaultPlayerNamer());
pl.getLogger().info("Use default player namer.");
}
}
}
@@ -3,12 +3,13 @@ package me.dadus33.chatitem.playernamer.hook;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.playernamer.IPlayerNamer;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ComponentBuilder;
public class DefaultPlayerNamer implements IPlayerNamer {
@Override
public TextComponent getName(Player p) {
return new TextComponent(p.getName());
public BaseComponent[] getName(Player p) {
return new ComponentBuilder(p.getName()).create();
}
}
@@ -4,15 +4,14 @@ import org.bukkit.entity.Player;
import dev.majek.hexnicks.Nicks;
import me.dadus33.chatitem.playernamer.IPlayerNamer;
import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer;
import net.md_5.bungee.api.chat.TextComponent;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.chat.BaseComponent;
public class HexNicksPlayerNamer implements IPlayerNamer {
@Override
public TextComponent getName(Player p) {
return new TextComponent(BukkitComponentSerializer.legacy().toBuilder().hexColors()
.useUnusualXRepeatedCharacterHexFormat().build().serialize(Nicks.api().getStoredNick(p).join()));
public BaseComponent[] getName(Player p) {
return BungeeComponentSerializer.get().serialize(Nicks.api().getStoredNick(p).join());
}
}
@@ -1,4 +1,4 @@
package me.dadus33.chatitem.chatmanager.v1.playerversion;
package me.dadus33.chatitem.playerversion;
import org.bukkit.entity.Player;
@@ -9,6 +9,6 @@ public interface IPlayerVersion {
public int getProtocolVersion(Player p);
default Version getPlayerVersion(Player p) {
return Version.getVersion(getProtocolVersion(p));
return Version.getVersion(getProtocolVersion(p), Version.getVersion());
}
}
@@ -0,0 +1,29 @@
package me.dadus33.chatitem.playerversion;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.playerversion.hooks.DefaultVersionHook;
import me.dadus33.chatitem.playerversion.hooks.ProtocolSupportHook;
import me.dadus33.chatitem.playerversion.hooks.ViaVersionHook;
import org.bukkit.Bukkit;
public class PlayerVersionManager {
private static final IPlayerVersion playerVersionAdapter;
static {
ChatItem pl = ChatItem.getInstance();
if (Bukkit.getPluginManager().getPlugin("ProtocolSupport") != null) {
playerVersionAdapter = new ProtocolSupportHook();
pl.getLogger().info("Loading ProtocolSupport support ...");
} else if (Bukkit.getPluginManager().getPlugin("ViaVersion") != null) {
playerVersionAdapter = new ViaVersionHook();
pl.getLogger().info("Loading ViaVersion support ...");
} else {
playerVersionAdapter = new DefaultVersionHook();
}
}
public static IPlayerVersion getPlayerVersionAdapter() {
return playerVersionAdapter;
}
}
@@ -1,22 +1,18 @@
package me.dadus33.chatitem.chatmanager.v1.playerversion.hooks;
package me.dadus33.chatitem.playerversion.hooks;
import java.util.HashMap;
import java.util.UUID;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.chatmanager.v1.playerversion.IPlayerVersion;
import me.dadus33.chatitem.playerversion.IPlayerVersion;
import me.dadus33.chatitem.utils.Version;
public class DefaultVersionHook implements IPlayerVersion {
public static final HashMap<String, Integer> PROTOCOL_PER_ADDRESS = new HashMap<>();
public static final HashMap<UUID, Integer> PROTOCOL_PER_UUID = new HashMap<>();
@Override
public int getProtocolVersion(Player p) {
if(PROTOCOL_PER_UUID.containsKey(p.getUniqueId()))
return PROTOCOL_PER_UUID.get(p.getUniqueId());
return PROTOCOL_PER_ADDRESS.getOrDefault(Version.stringifyAdress(p.getAddress()), Version.getVersion().MAX_VER);
}
}
@@ -1,8 +1,8 @@
package me.dadus33.chatitem.chatmanager.v1.playerversion.hooks;
package me.dadus33.chatitem.playerversion.hooks;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.chatmanager.v1.playerversion.IPlayerVersion;
import me.dadus33.chatitem.playerversion.IPlayerVersion;
import protocolsupport.api.ProtocolSupportAPI;
public class ProtocolSupportHook implements IPlayerVersion {
@@ -1,8 +1,8 @@
package me.dadus33.chatitem.chatmanager.v1.playerversion.hooks;
package me.dadus33.chatitem.playerversion.hooks;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.chatmanager.v1.playerversion.IPlayerVersion;
import me.dadus33.chatitem.playerversion.IPlayerVersion;
import us.myles.ViaVersion.api.Via;
public class ViaVersionHook implements IPlayerVersion {
@@ -0,0 +1,125 @@
package me.dadus33.chatitem.utils;
import java.util.Arrays;
import java.util.List;
import me.dadus33.chatitem.ChatItem;
import net.md_5.bungee.api.ChatColor;
public class ColorManager {
public static final List<String> COLORS = Arrays.asList("4", "c", "6", "e", "2", "a", "b", "3", "1", "9", "d", "5", "f", "7", "8", "0");
public static boolean isHexColor(ChatColor c) {
return Version.getVersion().isNewerOrEquals(Version.V1_16) && c.getName().startsWith("#");
}
public static boolean isHexColor(String c) {
return Version.getVersion().isNewerOrEquals(Version.V1_16) && c.startsWith("x");
}
public static String removeColorAtBegin(String s) {
if(s == null || s.isEmpty())
return "";
boolean wasColorChar = s.startsWith(Character.toString(ChatColor.COLOR_CHAR));
if(!wasColorChar)
return s;
String next = "";
for(int i = 1; i < s.length(); i++) {
char c = s.charAt(i);
if(wasColorChar) {
if(!COLORS.contains(Character.toString(c)))
next = next + ChatColor.COLOR_CHAR + "" + c;
wasColorChar = false;
} else {
wasColorChar = c == ChatColor.COLOR_CHAR;
if(!wasColorChar) { // something other than color code
next += s.substring(i);
break;
}
}
}
if(next.isEmpty())
next = s;
return next;
}
public static String getColorString(String input) {
if (input == null || input.isEmpty())
return "";
StringBuilder str = new StringBuilder();
if (isHexColor(input)) { // x mean it's an hex
ChatItem.debug("Removing char x at begin: " + input.substring(1));
input = input.substring(1);
if (input.length() >= 6) { // at least hex
str.append(ChatColor.of("#" + input.substring(0, 6))); // get first hex color code
ChatItem.debug("Str with hex: " + str);
if (input.length() > 6) // if as another color code
str.append(getColorString(input.substring(6))); // get color for after
return str.toString();
} else
ChatItem.debug("Low len: " + input.length());
}
// not hex
for (char c : input.toCharArray())
str.append(ChatColor.getByChar(c));
return str.toString();
}
public static ChatColor getColor(String input) {
if (input == null || input.isEmpty())
return ChatColor.RESET;
if (isHexColor(input)) { // x mean it's an hex
ChatItem.debug("Removing char x at begin: " + input.substring(1));
if (input.length() >= 7) { // at least hex, and 7 because we count the "x"
return ChatColor.of("#" + input.substring(1, 7)); // get first hex color code
} else
ChatItem.debug("Low len: " + input.length());
}
// not hex
return ChatColor.getByChar(input.charAt(0));
}
public static String fixColor(String message) {
String colorCode = "", text = "";
boolean waiting = false;
for (char args : message.toCharArray()) {
if (args == '§') { // begin of color
waiting = true; // waiting for color code
} else if (waiting) { // if waiting for code and valid str
// if it's hexademical value and with enough space for full color
waiting = false;
if (args == 'r' && colorCode.isEmpty()) {
text += ChatColor.RESET;
continue;
}
if (args == 'x' && !colorCode.isEmpty()) {
text += ColorManager.getColorString(colorCode);
colorCode = "x";
} else if(Character.digit(Character.toLowerCase(args), 16) != -1)
colorCode += args; // a color by itself
} else {
waiting = false;
if (!colorCode.isEmpty()) {
if (isHexColor(colorCode) && colorCode.length() >= 7) {
if (colorCode.length() == 7)
text += ColorManager.getColor(colorCode);
else {
text += ColorManager.getColor(colorCode.substring(0, 7)); // only the hex code
ChatItem.debug("Adding color for " + colorCode.substring(7, colorCode.length()) + " (in "
+ colorCode + ")");
text += ColorManager.getColorString(colorCode.substring(7, colorCode.length()));
}
} else if (colorCode.length() == 1) // if only one color code
text += ColorManager.getColor(colorCode);
else
text += ColorManager.getColorString(colorCode);
colorCode = "";
}
// basic text, not waiting for code after '§'
text += args;
}
}
return text;
}
}
@@ -18,6 +18,8 @@ public class ItemUtils {
public static final Material BOOK_AND_QUILL = getMaterialWithCompatibility("BOOK_AND_QUILL", "WRITTEN_BOOK");
public static final Material WEB = getMaterialWithCompatibility("WEB", "COBWEB");
public static final Material FIREBALL = getMaterialWithCompatibility("FIREBALL", "FIRE_CHARGE");
public static final Material INK_SAC = getMaterialWithCompatibility("INK_SAC", "INK_SACK", "DYE", "GRAY_DYE");
public static final Material FIREWORK_CHARGE = getMaterialWithCompatibility("FIREWORK_CHARGE", "FIRE_CHARGE");
public static final Material BIRCH_WOOD_STAIRS = getMaterialWithCompatibility("BIRCH_WOOD_STAIRS", "BIRCH_STAIRS");
@@ -83,4 +85,8 @@ public class ItemUtils {
}
return stack;
}
public static boolean isEmpty(ItemStack item) {
return item == null || item.getType().equals(Material.AIR);
}
}
@@ -1,6 +1,8 @@
package me.dadus33.chatitem.utils;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@@ -17,10 +19,9 @@ public class PacketUtils {
/**
* This Map is to reduce Reflection action which take more resources than just RAM action
*/
private static final HashMap<String, Class<?>> ALL_CLASS;
private static final Map<String, Class<?>> ALL_CLASS = Collections.synchronizedMap(new HashMap<String, Class<?>>());
static {
ALL_CLASS = new HashMap<>();
IS_THERMOS = isClassExist("thermos.Thermos");
NMS_PREFIX = Version.getVersion().isNewerOrEquals(Version.V1_17) || IS_THERMOS ? "net.minecraft." : "net.minecraft.server." + VERSION + ".";
OBC_PREFIX = "org.bukkit.craftbukkit." + VERSION + ".";
@@ -1,6 +1,9 @@
package me.dadus33.chatitem.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import me.dadus33.chatitem.ChatItem;
public class ReflectionUtils {
@@ -21,6 +24,31 @@ public class ReflectionUtils {
}
}
/**
* Get the specified field name in the object source
*
* @param source where we will find the field
* @param field the name of the field
* @return the requested object of the field
*/
public static Object getObject(Object source, String... field) {
try {
for(String fieldName : field) {
try {
Field f = source.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
return f.get(source);
} catch (NoSuchFieldException e) {
// ignore because going to next item
}
}
ChatItem.getInstance().getLogger().severe("Failed to find fields: " + String.join(", ", field) + " in " + source.getClass().getSimpleName());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Get the specified field name in the object source
*
@@ -28,11 +56,11 @@ public class ReflectionUtils {
* @param field the name of the field
* @return the requested field
*/
public static Object getField(Object source, String field) {
public static Field getField(Object source, String field) {
try {
Field f = source.getClass().getDeclaredField(field);
f.setAccessible(true);
return f.get(source);
return f;
} catch (Exception e) {
e.printStackTrace();
return null;
@@ -56,7 +84,7 @@ public class ReflectionUtils {
}
/**
* Get the first field which have the searching for class type
* Get the first object which have the searching for class type
*
* @param from the object where we will try to find the field
* @param clazz the class that have to define the field
@@ -67,11 +95,30 @@ public class ReflectionUtils {
@SuppressWarnings("unchecked")
public static <T> T getFirstWith(Object from, Class<?> clazz, Class<T> searchingFor) throws Exception {
for (Field f : clazz.getDeclaredFields()) {
if (f.getType().equals(searchingFor)) {
if (f.getType().equals(searchingFor) && !Modifier.isStatic(f.getModifiers())) {
f.setAccessible(true);
return (T) f.get(from);
}
}
return null;
}
/**
* Get the first field which have the searching for class type
*
* @param from the object where we will try to find the field
* @param clazz the class that have to define the field
* @param searchingFor the class of the required field
* @return the field (or null if not found)
* @throws Exception if something gone wrong
*/
public static Field getFirstFieldWith(Class<?> clazz, Class<?> searchingFor) throws Exception {
for (Field f : clazz.getDeclaredFields()) {
if (f.getType().equals(searchingFor) && !Modifier.isStatic(f.getModifiers())) {
f.setAccessible(true);
return f;
}
}
return null;
}
}
@@ -0,0 +1,208 @@
package me.dadus33.chatitem.utils;
import java.util.Locale;
import java.util.Objects;
import javax.annotation.Nullable;
/**
* Represents the simplified SemVer schema Negativity uses for its plugin versions.
*/
public final class SemVer implements Comparable<SemVer> {
private final int major;
private final int minor;
private final int patch;
private final @Nullable Suffix suffix;
public SemVer(int major, int minor, int patch, @Nullable Suffix suffix) {
this.major = major;
this.minor = minor;
this.patch = patch;
this.suffix = suffix;
}
public boolean isNewerThan(SemVer other) {
return this.compareTo(other) > 0;
}
public boolean isOlderThan(SemVer other) {
return this.compareTo(other) < 0;
}
/**
* Slightly different from {@link #equals} in that this method will return
* true if the suffix has the same {@link Suffix#getWeight() weight}
* but not the same {@link Suffix#getText()} text
*/
public boolean isEquivalentTo(SemVer other) {
return this.compareTo(other) == 0;
}
public int getMajor() {
return major;
}
public int getMinor() {
return minor;
}
public int getPatch() {
return patch;
}
public @Nullable Suffix getSuffix() {
return suffix;
}
@Override
public int compareTo(SemVer o) {
int majorDelta = Integer.compare(this.major, o.major);
if (majorDelta != 0) {
return majorDelta;
}
int minorDelta = Integer.compare(this.minor, o.minor);
if (minorDelta != 0) {
return minorDelta;
}
int patchDelta = Integer.compare(this.patch, o.patch);
if (patchDelta != 0) {
return patchDelta;
}
if (this.suffix != null) {
return o.suffix != null ? this.suffix.compareTo(o.suffix) : -1;
}
if (o.suffix != null) {
return 1;
}
return 0;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SemVer semVer = (SemVer) o;
return major == semVer.major && minor == semVer.minor && patch == semVer.patch && Objects.equals(suffix, semVer.suffix);
}
@Override
public int hashCode() {
return Objects.hash(major, minor, patch, suffix);
}
@Override
public String toString() {
return "SemVer{major=" + major + ", minor=" + minor + ", patch=" + patch + ", suffix=" + suffix + '}';
}
public String toFormattedString() {
if (suffix == null) {
if(patch > 0)
return major + "." + minor + (patch > 0 ? "." + patch : "");
}
return major + "." + minor + (patch > 0 ? "." + patch : "") + (suffix == null ? "" : "-" + suffix.getText());
}
public static @Nullable SemVer parse(String text) {
if (text == null || text.isEmpty()) {
return null;
}
String[] suffixSplit = text.split("-", 2);
Suffix suffix = null;
if (suffixSplit.length > 1) {
suffix = Suffix.of(suffixSplit[1]);
}
String[] parts = suffixSplit[0].split("\\.");
int major;
try {
major = Integer.parseInt(parts[0]);
} catch (NumberFormatException e) {
return null;
}
int minor = 0;
if (parts.length > 1) {
try {
minor = Integer.parseInt(parts[1]);
} catch (NumberFormatException ignore) {
}
}
int patch = 0;
if (parts.length > 2) {
try {
patch = Integer.parseInt(parts[2]);
} catch (NumberFormatException ignore) {
}
}
return new SemVer(major, minor, patch, suffix);
}
public static final class Suffix implements Comparable<Suffix> {
public static final Suffix SNAPSHOT = new Suffix(0, "SNAPSHOT");
public static final Suffix ALPHA = new Suffix(1, "ALPHA");
public static final Suffix BETA = new Suffix(2, "BETA");
public static final Suffix GAMMA = new Suffix(3, "GAMMA");
public static final Suffix DELTA = new Suffix(4, "DELTA");
private final int weight;
private final String text;
public Suffix(int weight, String text) {
this.weight = weight;
this.text = text;
}
public int getWeight() {
return weight;
}
public String getText() {
return text;
}
@Override
public int compareTo(Suffix o) {
return Integer.compare(this.weight, o.weight);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Suffix suffix = (Suffix) o;
return weight == suffix.weight && text.equals(suffix.text);
}
@Override
public int hashCode() {
return Objects.hash(weight, text);
}
@Override
public String toString() {
return "Suffix{weight=" + weight + ", text='" + text + "'}";
}
public static Suffix of(String text) {
String uppercaseText = text.toUpperCase(Locale.ROOT);
switch (uppercaseText) {
case "SNAPSHOT":
return SNAPSHOT;
case "ALPHA":
return ALPHA;
case "BETA":
return BETA;
case "GAMMA":
return GAMMA;
case "DELTA":
return DELTA;
default:
return new Suffix(-1, uppercaseText);
}
}
}
}
@@ -1,118 +1,123 @@
package me.dadus33.chatitem.utils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import com.google.common.collect.ImmutableList;
import me.dadus33.chatitem.ChatItem;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.configuration.file.FileConfiguration;
import com.google.common.collect.ImmutableList;
import me.dadus33.chatitem.ChatItem;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class Storage {
private FileConfiguration conf;
public final HashMap<String, HashMap<Short, String>> TRANSLATIONS = new HashMap<>();
public boolean COLOR_IF_ALREADY_COLORED, FORCE_ADD_AMOUNT, LET_MESSAGE_THROUGH, DENY_IF_NO_ITEM,
HAND_DISABLED, SHOW_NO_PERM_NORMAL, CHECK_UPDATE, SHOW_NO_PERM_COMMAND;
public final String HAND_NAME, NAME_FORMAT, AMOUNT_FORMAT, MANAGER;
public final String NO_PERMISSION_MESSAGE, DENY_MESSAGE, RELOAD_MESSAGE, COOLDOWN_MESSAGE, LIMIT_MESSAGE;
public final String SECONDS, MINUTES, HOURS;
public final String JOIN_UPDATE_MESSAGE, JOIN_UPDATE_HOVER;
public int CONFIG_VERSION, LIMIT, COOLDOWN;
public final List<Command> ALLOWED_PLUGIN_COMMANDS = new ArrayList<>();
public final List<String> ALLOWED_DEFAULT_COMMANDS = new ArrayList<>();
public final List<String> PLACEHOLDERS, HAND_TOOLTIP;
public final HashMap<String, HashMap<Short, String>> TRANSLATIONS = new HashMap<>();
public final String HAND_NAME, NAME_FORMAT, AMOUNT_FORMAT, COMMAND_FORMAT, MANAGER, PERMISSION_NAME, BUGGED_CLIENT_ACTION;
public final String NO_PERMISSION_MESSAGE, DENY_MESSAGE, RELOAD_MESSAGE, COOLDOWN_MESSAGE, LIMIT_MESSAGE;
public final String SECONDS, MINUTES, HOURS;
public final String JOIN_UPDATE_MESSAGE, JOIN_UPDATE_HOVER;
public final List<Command> ALLOWED_PLUGIN_COMMANDS = new ArrayList<>();
public final List<String> ALLOWED_DEFAULT_COMMANDS = new ArrayList<>();
public final List<String> PLACEHOLDERS, HAND_TOOLTIP, BUGGED_CLIENTS_TOOLTIP;
public boolean COLOR_IF_ALREADY_COLORED, FORCE_ADD_AMOUNT, LET_MESSAGE_THROUGH, DENY_IF_NO_ITEM, DEBUG,
HAND_DISABLED, SHOW_NO_PERM_NORMAL, CHECK_UPDATE, SHOW_NO_PERM_COMMAND, PERMISSION_ENABLED;
public int CONFIG_VERSION, LIMIT, COOLDOWN;
private FileConfiguration conf;
public Storage(FileConfiguration cnf) {
this.conf = cnf;
CONFIG_VERSION = conf.getInt("config-version", 13);
checkConfigVersion();
this.MANAGER = conf.getString("manager", "auto");
Set<String> keys = conf.getConfigurationSection("translations").getKeys(false);
for (String key : keys) {
HashMap<Short, String> entry = new HashMap<>();
Set<String> subKeys = conf.getConfigurationSection("translations.".concat(key)).getKeys(false);
for (String subKey : subKeys) {
entry.put(Short.parseShort(subKey),
color(conf.getString("translations.".concat(key).concat(".").concat(subKey))));
}
public Storage(FileConfiguration cnf) {
this.conf = cnf;
CONFIG_VERSION = conf.getInt("config-version", 13);
checkConfigVersion();
this.MANAGER = conf.getString("manager", "auto");
Set<String> keys = conf.getConfigurationSection("translations").getKeys(false);
for (String key : keys) {
HashMap<Short, String> entry = new HashMap<>();
Set<String> subKeys = conf.getConfigurationSection("translations.".concat(key)).getKeys(false);
for (String subKey : subKeys) {
entry.put(Short.parseShort(subKey),
color(conf.getString("translations.".concat(key).concat(".").concat(subKey))));
}
TRANSLATIONS.put(key, entry);
}
PLACEHOLDERS = ImmutableList.copyOf(conf.getStringList("general.placeholders"));
NAME_FORMAT = color(conf.getString("general.name-format", "&b&l&o{name} {amount}&r"));
AMOUNT_FORMAT = color(conf.getString("general.amount-format", "x{times}"));
COLOR_IF_ALREADY_COLORED = conf.getBoolean("general.color-if-already-colored", true);
LET_MESSAGE_THROUGH = conf.getBoolean("general.let-message-through", true);
FORCE_ADD_AMOUNT = conf.getBoolean("general.force-add-amount", true);
DENY_IF_NO_ITEM = conf.getBoolean("general.deny-if-no-item", false);
TRANSLATIONS.put(key, entry);
}
DEBUG = conf.getBoolean("debug", false);
PLACEHOLDERS = ImmutableList.copyOf(conf.getStringList("general.placeholders"));
NAME_FORMAT = color(conf.getString("general.name-format", "&b&l&o{name} {amount}&r"));
AMOUNT_FORMAT = color(conf.getString("general.amount-format", "x{times}"));
COMMAND_FORMAT = color(conf.getString("general.command-format", "&6%name%'s item is %item%"));
COLOR_IF_ALREADY_COLORED = conf.getBoolean("general.color-if-already-colored", true);
LET_MESSAGE_THROUGH = conf.getBoolean("general.let-message-through", true);
FORCE_ADD_AMOUNT = conf.getBoolean("general.force-add-amount", true);
DENY_IF_NO_ITEM = conf.getBoolean("general.deny-if-no-item", false);
LIMIT = conf.getInt("general.limit", 8);
COOLDOWN = conf.getInt("general.cooldown", 60);
SHOW_NO_PERM_NORMAL = conf.getBoolean("general.show-no-permission-message.normal", true);
COOLDOWN = conf.getInt("general.cooldown", 60);
SHOW_NO_PERM_NORMAL = conf.getBoolean("general.show-no-permission-message.normal", true);
SHOW_NO_PERM_COMMAND = conf.getBoolean("general.show-no-permission-message.command", false);
HAND_DISABLED = conf.getBoolean("general.hand.disabled", false);
HAND_NAME = color(conf.getString("general.hand.name", "&b&l&o{display-name}&b&l&o's hand"));
HAND_TOOLTIP = conf.getStringList("general.hand.tooltip");
CHECK_UPDATE = conf.getBoolean("general.check-update", true);
DENY_MESSAGE = color(conf.getString("messages.deny-message", "&c&lYou have no item in hand!"));
RELOAD_MESSAGE = color(conf.getString("messages.reload-success", "&b&lSuccessful reload!"));
NO_PERMISSION_MESSAGE = color(conf.getString("messages.no-permission",
"&c&lI'm sorry, but you are not allowed to use the placeholder in chat!"));
COOLDOWN_MESSAGE = color(conf.getString("messages.cooldown-message",
"&c&lYou can only use items in chat once a minute! You have {remaining} left!"));
JOIN_UPDATE_MESSAGE = color(conf.getString("messages.join-update.message",
"&cA new version of ChatItem is available. &aClick here to download."));
JOIN_UPDATE_HOVER = color(conf.getString("messages.join-update.hover", "&6Click to go to spigot page !"));
LIMIT_MESSAGE = color(conf.getString("messages.limit-message"));
PERMISSION_ENABLED = conf.getBoolean("general.permission.enabled", false);
PERMISSION_NAME = conf.getString("general.permission.name", "chatitem.use");
HAND_DISABLED = conf.getBoolean("general.hand.disabled", false);
HAND_NAME = color(conf.getString("general.hand.name", "&b&l&o{display-name}&b&l&o's hand"));
HAND_TOOLTIP = conf.getStringList("general.hand.tooltip").stream().map(Storage::color).collect(Collectors.toList());
BUGGED_CLIENT_ACTION = conf.getString("general.bugged_client.action", "show_both");
BUGGED_CLIENTS_TOOLTIP = conf.getStringList("general.bugged_client.tooltip").stream().map(Storage::color).collect(Collectors.toList());
CHECK_UPDATE = conf.getBoolean("general.check-update", true);
DENY_MESSAGE = color(conf.getString("messages.deny-message", "&c&lYou have no item in hand!"));
RELOAD_MESSAGE = color(conf.getString("messages.reload-success", "&b&lSuccessful reload!"));
NO_PERMISSION_MESSAGE = color(conf.getString("messages.no-permission",
"&c&lI'm sorry, but you are not allowed to use the placeholder in chat!"));
COOLDOWN_MESSAGE = color(conf.getString("messages.cooldown-message",
"&c&lYou can only use items in chat once a minute! You have {remaining} left!"));
JOIN_UPDATE_MESSAGE = color(conf.getString("messages.join-update.message",
"&cA new version of ChatItem is available. &aClick here to download."));
JOIN_UPDATE_HOVER = color(conf.getString("messages.join-update.hover", "&6Click to go to spigot page !"));
LIMIT_MESSAGE = color(conf.getString("messages.limit-message", "&c&lYou can only add 8 item placeholders per message!"));
SECONDS = color(conf.getString("messages.seconds", " seconds"));
MINUTES = color(conf.getString("messages.minutes", " minutes"));
HOURS = color(conf.getString("messages.hours", " hours"));
colorStringList(HAND_TOOLTIP);
final List<String> cmds = conf.getStringList("general.commands");
Bukkit.getScheduler().runTaskLaterAsynchronously(ChatItem.getInstance(), () -> {
for (String s : cmds) {
Command c = Bukkit.getPluginCommand(s);
if (c != null) {
ALLOWED_PLUGIN_COMMANDS.add(c);
} else {
ALLOWED_DEFAULT_COMMANDS.add(s);
}
}
}, 100L);
SECONDS = color(conf.getString("messages.seconds", " seconds"));
MINUTES = color(conf.getString("messages.minutes", " minutes"));
HOURS = color(conf.getString("messages.hours", " hours"));
colorStringList(HAND_TOOLTIP);
final List<String> cmds = conf.getStringList("general.commands");
Bukkit.getScheduler().runTaskLaterAsynchronously(ChatItem.getInstance(), () -> {
for (String s : cmds) {
Command c = Bukkit.getPluginCommand(s);
if (c != null) {
ALLOWED_PLUGIN_COMMANDS.add(c);
} else {
ALLOWED_DEFAULT_COMMANDS.add(s);
}
}
}, 100L);
}
}
public static String color(String s) {
return s == null || s.isEmpty() ? s : ChatColor.translateAlternateColorCodes('&', s);
}
public static String color(String s) {
return s == null || s.isEmpty() ? s : ChatColor.translateAlternateColorCodes('&', s);
}
private void checkConfigVersion() {
int latestVersion = ChatItem.CFG_VER;
if (latestVersion != CONFIG_VERSION) {
ChatItem pl = ChatItem.getInstance();
pl.getLogger().warning(ChatColor.RED
+ "ChatItem detected an older or invalid configuration file. Replacing it with the default config...");
performOverwrite();
conf = pl.getConfig();
pl.getLogger().warning(ChatColor.RED + "Replacement complete!");
}
}
private static void colorStringList(List<String> input) {
for (int i = 0; i < input.size(); ++i) {
input.set(i, color(input.get(i)));
}
}
private void performOverwrite() {
ChatItem.getInstance().saveResource("config.yml", true);
}
private void checkConfigVersion() {
int latestVersion = ChatItem.CFG_VER;
if (latestVersion != CONFIG_VERSION) {
ChatItem pl = ChatItem.getInstance();
pl.getLogger().warning(ChatColor.RED
+ "ChatItem detected an older or invalid configuration file. Replacing it with the default config...");
performOverwrite();
conf = pl.getConfig();
pl.getLogger().warning(ChatColor.RED + "Replacement complete!");
}
}
private static void colorStringList(List<String> input) {
for (int i = 0; i < input.size(); ++i) {
input.set(i, color(input.get(i)));
}
}
private void performOverwrite() {
ChatItem.getInstance().saveResource("config.yml", true);
}
}
@@ -1,34 +1,93 @@
package me.dadus33.chatitem.utils;
import me.dadus33.chatitem.ChatItem;
import org.bukkit.Bukkit;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.UnknownHostException;
import java.net.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.ChatItem;
import java.util.TreeMap;
public class Utils {
@SuppressWarnings("unchecked")
public static List<Player> getOnlinePlayers() {
Object players = Bukkit.getOnlinePlayers();
if(players instanceof Player[])
return Arrays.asList((Player[]) players);
return new ArrayList<>((Collection<Player>) players);
private final static TreeMap<Integer, String> ROMAN_KEYS = new TreeMap<>();
private final static HashMap<String, String> ENCHANTS_NAMES = new HashMap<>();
static {
ROMAN_KEYS.put(1000, "M");
ROMAN_KEYS.put(900, "CM");
ROMAN_KEYS.put(500, "D");
ROMAN_KEYS.put(400, "CD");
ROMAN_KEYS.put(100, "C");
ROMAN_KEYS.put(90, "XC");
ROMAN_KEYS.put(50, "L");
ROMAN_KEYS.put(40, "XL");
ROMAN_KEYS.put(10, "X");
ROMAN_KEYS.put(9, "IX");
ROMAN_KEYS.put(5, "V");
ROMAN_KEYS.put(4, "IV");
ROMAN_KEYS.put(1, "I");
ENCHANTS_NAMES.put("ARROW_DAMAGE", "Power");
ENCHANTS_NAMES.put("ARROW_FIRE", "Flame");
ENCHANTS_NAMES.put("ARROW_INFINITE", "Infinity");
ENCHANTS_NAMES.put("ARROW_KNOCKBACK", "Punch");
ENCHANTS_NAMES.put("BINDING_CURSE", "Curse of Binding");
ENCHANTS_NAMES.put("DAMAGE_ALL", "Sharpness");
ENCHANTS_NAMES.put("DAMAGE_ARTHROPODS", "Bane of Arthropods");
ENCHANTS_NAMES.put("DAMAGE_UNDEAD", "Smite");
ENCHANTS_NAMES.put("DEPTH_STRIDER", "Depth Strider");
ENCHANTS_NAMES.put("DIG_SPEED", "Efficiency");
ENCHANTS_NAMES.put("DURABILITY", "Unbreaking");
ENCHANTS_NAMES.put("FIRE_ASPECT", "Fire Aspect");
ENCHANTS_NAMES.put("FROST_WALKER", "Frost Walker");
ENCHANTS_NAMES.put("KNOCKBACK", "Knockback");
ENCHANTS_NAMES.put("LOOT_BONUS_BLOCKS", "Fortune");
ENCHANTS_NAMES.put("LOOT_BONUS_MOBS", "Looting");
ENCHANTS_NAMES.put("LUCK", "Luck of the Sea");
ENCHANTS_NAMES.put("LURE", "Lure");
ENCHANTS_NAMES.put("MENDING", "Mending");
ENCHANTS_NAMES.put("OXYGEN", "Respiration");
ENCHANTS_NAMES.put("PROTECTION_ENVIRONMENTAL", "Protection");
ENCHANTS_NAMES.put("PROTECTION_EXPLOSIONS", "Blast Protection");
ENCHANTS_NAMES.put("PROTECTION_FALL", "Feather Falling");
ENCHANTS_NAMES.put("PROTECTION_FIRE", "Fire Protection");
ENCHANTS_NAMES.put("PROTECTION_PROJECTILE", "Projectile Protection");
ENCHANTS_NAMES.put("SILK_TOUCH", "Silk Touch");
ENCHANTS_NAMES.put("SWEEPING_EDGE", "Sweeping Edge");
ENCHANTS_NAMES.put("THORNS", "Thorns");
ENCHANTS_NAMES.put("VANISHING_CURSE", "Cure of Vanishing");
ENCHANTS_NAMES.put("WATER_WORKER", "Aqua Affinity");
}
public static List<Player> getOnlinePlayers() {
return new ArrayList<>(Bukkit.getOnlinePlayers());
}
public static String toRoman(int number) {
int l = ROMAN_KEYS.floorKey(number);
if (number == l) {
return ROMAN_KEYS.get(number);
}
return ROMAN_KEYS.get(l) + toRoman(number - l);
}
@SuppressWarnings("deprecation")
public static String getEnchantName(Enchantment enchant) {
String name = ENCHANTS_NAMES.get(enchant.getName());
if (name == null) {
ChatItem.getInstance().getLogger()
.warning("Unknown enchant " + enchant.getName() + ". Please report this to Elikill58.");
}
return name;
}
public static String getFromURL(String urlName) {
ChatItem pl = ChatItem.getInstance();
try {
@@ -41,21 +100,77 @@ public class Utils {
connection.setDoOutput(true);
connection.setRequestMethod("GET");
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String content = "";
StringBuilder content = new StringBuilder();
String input;
while ((input = br.readLine()) != null)
content = content + input;
content.append(input);
br.close();
return content;
} catch (SocketTimeoutException e) {
pl.getLogger().info("Failed to access to " + urlName + " (Reason: timed out).");
} catch (UnknownHostException | MalformedURLException e) {
pl.getLogger().info("Could not use the internet connection to check for update or send stats");
} catch (ConnectException e) {
pl.getLogger().warning("Cannot connect to " + urlName + " (Reason: " + e.getMessage() + ").");
} catch (IOException e) {
e.printStackTrace();
return content.toString();
} catch (SocketTimeoutException e) {
pl.getLogger().info("Failed to access to " + urlName + " (Reason: timed out).");
} catch (UnknownHostException | MalformedURLException e) {
pl.getLogger().info("Could not use the internet connection to check for update or send stats");
} catch (ConnectException e) {
pl.getLogger().warning("Cannot connect to " + urlName + " (Reason: " + e.getMessage() + ").");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static int indexOf(CharSequence s, CharSequence searched, int i) {
return s.toString().indexOf(searched.toString(), i);
}
public static boolean isEmpty(CharSequence s) {
return (s == null || s.length() == 0);
}
public static int countMatches(CharSequence str, CharSequence searched) {
if (isEmpty(str) || isEmpty(searched))
return 0;
byte b = 0;
int i = 0;
while ((i = indexOf(str, searched, i)) != -1) {
b++;
i += searched.length();
}
return b;
}
public static boolean isInteger(String s) {
try {
Integer.parseInt(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isByte(String s) {
try {
Byte.parseByte(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isShort(String s) {
try {
Short.parseShort(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isLong(String s) {
try {
Long.parseLong(s);
return true;
} catch (Exception e) {
return false;
}
}
}
@@ -4,6 +4,8 @@ import java.net.InetSocketAddress;
import org.bukkit.Bukkit;
import me.dadus33.chatitem.ChatItem;
public enum Version {
// http://wiki.vg/Protocol_version_numbers
@@ -18,8 +20,8 @@ public enum Version {
V1_15(100, 550, 578),
V1_16(100, 700, 754),
V1_17(100, 755, 756),
V1_18(100, 757, 800),
V1_19(100, 801, 1000),
V1_18(100, 757, 758),
V1_19(100, 761, 1000),
HIGHER(Integer.MAX_VALUE, -1, Integer.MAX_VALUE);
// Latest version should always have the upper limit set to Integer.MAX_VALUE so
@@ -67,6 +69,16 @@ public enum Version {
return HIGHER;
}
public static Version getVersion(int protocolVersion, Version def) {
for (Version ver : Version.values()) {
if (protocolVersion >= ver.MIN_VER && protocolVersion <= ver.MAX_VER) {
return ver;
}
}
ChatItem.debug("Failed to find version for protocol " + protocolVersion);
return def;
}
public static Version getVersion() {
return SERVER_VERSION;
}
+38 -17
View File
@@ -2,10 +2,10 @@
# For info visit
# Spigotmc: https://www.spigotmc.org/resources/chatitem.19064/
# Discord: https://discord.gg/ttA5CjMhk7
# Version info, DON'T TOUCH
config-version: 13
# By default, it's in "both" mode.
#
# Available mode :
@@ -50,6 +50,24 @@ general:
tooltip:
- "&7Nothing to see here"
- "&7Just the empty hand of {display-name}."
# Manage what is showed for bugged client.
# Specially lunar client with old version (1.7)
bugged_client:
# You can try to show the most informations as possible:
# item name & lore. You will not see specific item meta-data
# Or just show the bugged tooltip.
#
# Action available:
# nothing: no hover
# item: only try to get values from item
# tooltip: only show tooltip
# show_both: show item & tooltip below
action: "show_both"
tooltip:
- "&7Failed to parse item for your client"
# Format used with using /chatitem show
command-format: "&6%name%'s item is %item%"
# Here you can choose which commands will the plugin attempt to parse. Console commands will all be ignored,
# however player commands will be taken into consideration. To add a command, simply add an element to the list
@@ -65,6 +83,10 @@ general:
show-no-permission-message:
normal: true
command: false
# Manage permission to use placeholders
permission:
enabled: false
name: "chatitem.use"
# Here you can set the limit on how many placeholders a user is allowed to use inside a message.
# Allowing too many placeholders can result in client crashes.
limit: 8
@@ -73,8 +95,8 @@ general:
cooldown: 60
# Check if the plugin have update
check-update: true
# Messages section. You can disable any of them by simply leaving them empty, like this: ""
messages:
# The message sent if showing off hands is disabled and the user isn't holding an item.
@@ -94,6 +116,8 @@ messages:
hover: "&6Click to go to spigot page !"
# For all commands ran by console by reserved to player
only-players: "&cOnly players can run this command"
# The player is not found
player-not-found: "&cThe player %arg% can't be founded."
# All messages for the /chatitem command
chatitem-cmd:
help:
@@ -138,6 +162,8 @@ messages:
hand-disabled: "&6Hand disabled: %state%"
limit-per-message: "&6Limit per message: &a%state%"
cooldown: "&6Cooldown: &a%state%"
debug: "&6Debug: &a%state%"
check-update: "&6Check updates: &a%state%"
# Change name and lore of all managers
manager:
both:
@@ -180,14 +206,14 @@ messages:
seconds: " seconds"
minutes: " minutes"
hours: " hours"
enabled: "&aEnabled"
disabled: "&cDisabled"
# Translations
# This is used to display prettier names in chat for items/blocks. Modifying this is usually unnecessary unless you know what you're doing.
translations:
## Blocks ##
STONE:
1: "Granite"
STONE:
0: "Stone"
1: "Granite"
@@ -780,8 +806,8 @@ translations:
STONE_PICKAXE:
0: "Stone Pickaxe"
STONE_AXE:
0: "Stone Axe
DIAMOND_SWORD: "
0: "Stone Axe"
DIAMOND_SWORD:
0: "Diamond Sword"
DIAMOND_SPADE:
0: "Diamond Shovel"
@@ -933,8 +959,6 @@ translations:
1: "Raw Salmon"
2: "Clownfish"
3: "Pufferfish"
COOKED_FISH:
0: "Cooked Fish"
COOKED_FISH:
0: "Cooked Salmon"
INK_SACK:
@@ -1066,9 +1090,6 @@ translations:
16394: "Splash Potion of Slowness"
16426: "Splash Potion of Slowness II"
16458: "Extended Splash Potion of Slowness"
16395: "Splash Potion of Leaping"
16427: "Splash Potion of Leaping II"
16459: "Extended Splash Potion of Leaping"
16396: "Splash Potion of Harming"
16428: "Splash Potion of Harming II"
16460: "Extended Splash Potion of Harming"
@@ -1149,8 +1170,8 @@ translations:
POISONOUS_POTATO:
0: "Poisonous Potato"
EMPTY_MAP:
0: "Empty Map
GOLDEN_CARROT: "
0: "Empty Map"
GOLDEN_CARROT:
0: "Golden Carrot"
SKULL_ITEM:
0: "Skeleton Head"
+1 -1
View File
@@ -2,7 +2,7 @@ name: ChatItem
main: me.dadus33.chatitem.ChatItem
version: ${project.version}
softdepend: [ViaVersion, ProtocolSupport, ProtocolLib, LangUtils, HexNicks]
softdepend: [ViaVersion, ProtocolSupport, ProtocolLib, LangUtils, HexNicks, EcoEnchants, DiscordSRV]
authors: [dadus33, WOLFI3654, Elikill58]
api-version: 1.13