Compare commits

..
109 Commits
Author SHA1 Message Date
Elikill58 26b71376b1 Upgrade to 2.4.6 2023-02-27 22:59:58 +01:00
Elikill58 9b25f2e0ae Fix control 2023-02-27 17:39:50 +01:00
dependabot[bot] cd40bc0894 Bump EcoEnchants from 9.17.0 to 9.17.1 (#63)
Bumps [EcoEnchants](https://github.com/Auxilor/EcoEnchants) from 9.17.0 to 9.17.1.
- [Release notes](https://github.com/Auxilor/EcoEnchants/releases)
- [Commits](https://github.com/Auxilor/EcoEnchants/compare/9.17.0...9.17.1)

---
updated-dependencies:
- dependency-name: com.willfp:EcoEnchants
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-21 18:08:33 +01:00
dependabot[bot] 06493ab38c Bump EcoEnchants from 9.16.0 to 9.17.0 (#62)
Bumps [EcoEnchants](https://github.com/Auxilor/EcoEnchants) from 9.16.0 to 9.17.0.
- [Release notes](https://github.com/Auxilor/EcoEnchants/releases)
- [Commits](https://github.com/Auxilor/EcoEnchants/compare/9.16.0...9.17.0)

---
updated-dependencies:
- dependency-name: com.willfp:EcoEnchants
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 21:00:23 +01:00
Elikill58 5c3519171e Change for string 2023-02-13 20:59:48 +01:00
Elikill58 ca6982d7b0 Clean for empty lines 2023-02-11 16:19:06 +01:00
dependabot[bot] 1c5a8dbdcc Bump EcoEnchants from 9.15.0 to 9.16.0 (#61)
Bumps [EcoEnchants](https://github.com/Auxilor/EcoEnchants) from 9.15.0 to 9.16.0.
- [Release notes](https://github.com/Auxilor/EcoEnchants/releases)
- [Commits](https://github.com/Auxilor/EcoEnchants/compare/9.15.0...9.16.0)

---
updated-dependencies:
- dependency-name: com.willfp:EcoEnchants
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-30 12:26:33 +01:00
Elikill58 0cf3c25b2c Prevent NPE 2023-01-27 10:04:47 +01:00
Elikill58 d0122a123e Update few things 2023-01-26 10:49:59 +01:00
dependabot[bot] 5493d76d00 Bump EcoEnchants from 9.14.4 to 9.15.0 (#56)
Bumps [EcoEnchants](https://github.com/Auxilor/EcoEnchants) from 9.14.4 to 9.15.0.
- [Release notes](https://github.com/Auxilor/EcoEnchants/releases)
- [Commits](https://github.com/Auxilor/EcoEnchants/compare/9.14.4...9.15.0)

---
updated-dependencies:
- dependency-name: com.willfp:EcoEnchants
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 17:54:58 +01:00
Elikill58 7fc535ffc6 Introduce chat object (#57)
* Refactor how manager check messages

* Rename config variables

* Fix searching chat id

* Remove some debug lines

* Change default config

* Fix for empty recipients
2023-01-09 17:54:46 +01:00
Elikill58 8b9f9a2842 Merge branch 'v2' of https://github.com/dadus33-plugins/ChatItem into v2 2023-01-03 17:10:38 +01:00
Elikill58 c60ade6a9c Skip mmo item wrong val 2023-01-03 17:10:27 +01:00
dependabot[bot] a0265599f6 Bump EcoEnchants from 9.14.3 to 9.14.4 (#55)
Bumps [EcoEnchants](https://github.com/Auxilor/EcoEnchants) from 9.14.3 to 9.14.4.
- [Release notes](https://github.com/Auxilor/EcoEnchants/releases)
- [Commits](https://github.com/Auxilor/EcoEnchants/compare/9.14.3...9.14.4)

---
updated-dependencies:
- dependency-name: com.willfp:EcoEnchants
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-02 11:12:09 +01:00
dependabot[bot] 9f45069c08 Bump EcoEnchants from 9.13.0-all to 9.14.3 (#54)
Bumps EcoEnchants from 9.13.0-all to 9.14.3.

---
updated-dependencies:
- dependency-name: com.willfp:EcoEnchants
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-26 23:44:33 +01:00
Elikill58 f3b95ad32d Prevent trying to save file 2022-12-18 11:28:33 +01:00
dependabot[bot] 444d58900e Bump viaversion-api from 4.3.0 to 4.5.1 (#50)
Bumps viaversion-api from 4.3.0 to 4.5.1.

---
updated-dependencies:
- dependency-name: com.viaversion:viaversion-api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-12 21:10:16 +01:00
Elikill58 72f239b293 Fix ComponentNMS 2022-12-12 21:09:11 +01:00
Elikill58 6bc0b919c5 Be able to continue to next manager 2022-12-10 12:53:07 +01:00
Elikill58 4864272c34 Multiple quick fix 2022-12-10 12:49:23 +01:00
Elikill58 a421e6e167 Be able to use direct base component object 2022-12-09 10:56:26 +01:00
Elikill58 76c6bafea7 Fix for children and adventure 2022-12-09 10:43:53 +01:00
Elikill58 f50dd5a1f8 Update adventure support 2022-12-09 00:04:41 +01:00
Elikill58 0dbc6c14bb Fix wrong var used 2022-12-07 21:41:41 +01:00
Elikill58 1d41b02f79 Fix #46 2022-12-07 18:02:07 +01:00
Elikill58 ec278c7d08 Update versions 2022-12-07 17:15:57 +01:00
dependabot[bot] 5729dbf4a6 Bump discordsrv from 1.25.1 to 1.26.0 (#48)
Bumps [discordsrv](https://github.com/DiscordSRV/DiscordSRV) from 1.25.1 to 1.26.0.
- [Release notes](https://github.com/DiscordSRV/DiscordSRV/releases)
- [Commits](https://github.com/DiscordSRV/DiscordSRV/compare/v1.25.1...v1.26.0)

---
updated-dependencies:
- dependency-name: com.discordsrv:discordsrv
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-07 16:05:38 +01:00
Elikill58 4129b52dc5 Update workflow versions 2022-12-07 16:05:22 +01:00
Elikill58 55c9cc6673 Update ViaVersion (Fix #49) 2022-12-07 16:04:14 +01:00
dependabot[bot] 59e75770fb Bump netty-all from 4.1.53.Final to 4.1.58.Final (#47)
Bumps netty-all from 4.1.53.Final to 4.1.58.Final.

---
updated-dependencies:
- dependency-name: io.netty:netty-all
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-07 16:01:30 +01:00
Elikill58 d6ce0c62ff Delete travis file 2022-12-07 16:00:45 +01:00
Elikill58 0ef13e39ae Add dependabot 2022-12-07 15:59:28 +01:00
Elikill58 26b0837784 Temporary remove EcoEnchants support to prevent error 2022-12-07 15:58:18 +01:00
Elikill58 1f3a510411 Remove log4j unused thing 2022-12-07 15:29:46 +01:00
Elikill58 039d5fb6d5 Remove name showed 2022-12-07 14:54:20 +01:00
Elikill58 048fe69204 Missing one change 2022-12-04 23:28:39 +01:00
Elikill58 358c574153 Maybe fix empty extra 2022-12-04 23:27:18 +01:00
Elikill58 efa0a345f9 Add more loggers 2022-12-04 22:58:53 +01:00
Elikill58 78670bf8ec Fix multiple send 2022-11-19 08:58:36 +01:00
Elikill58 a47b93ea1a Upgrade to snapshot 2022-11-16 19:11:17 +01:00
Elikill58 f4d56b56e1 Fix double name 2022-11-16 19:10:51 +01:00
Elikill58 3eb54bb4d6 Fix mistake 2022-11-15 12:09:23 +01:00
Elikill58 a0f54df9b7 Fix color codes 2022-11-15 12:07:22 +01:00
Elikill58 80a000cee7 Update NMS behavior 2022-11-15 11:56:13 +01:00
Elikill58 8bd6bed5fb rename components 2022-11-15 11:11:42 +01:00
Elikill58 ba5e8d9935 Complete refactor of String ComponentGetter 2022-11-15 11:10:39 +01:00
Elikill58 8d6b3e7987 Quickly change for some extra/text things 2022-11-14 23:13:27 +01:00
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
54 changed files with 1884 additions and 1366 deletions

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "maven"
directory: "/"
schedule:
interval: "weekly"
+3 -3
View File
@@ -10,11 +10,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
name: Checkout repo
- name: Set up JDK 17 (LTS)
uses: actions/setup-java@v2
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
@@ -23,7 +23,7 @@ jobs:
- name: Build with Maven
run: mvn install --file pom.xml
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
name: Upload Artifact
with:
name: ChatItem.jar
+3 -3
View File
@@ -10,11 +10,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
name: Checkout repo
- name: Set up JDK 17 (LTS)
uses: actions/setup-java@v2
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
@@ -23,7 +23,7 @@ jobs:
- name: Build with Maven
run: mvn install --file pom.xml
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
name: Upload Artifact
with:
name: ChatItem.jar
-2
View File
@@ -1,2 +0,0 @@
language: java
script: "mvn clean package -DskipTests"
+12 -24
View File
@@ -6,7 +6,7 @@
<groupId>me.dadus33</groupId>
<artifactId>chatitem</artifactId>
<version>2.4</version>
<version>2.4.6</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -70,18 +70,6 @@
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
@@ -101,9 +89,9 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>us.myles</groupId>
<artifactId>viaversion</artifactId>
<version>3.0.0</version>
<groupId>com.viaversion</groupId>
<artifactId>viaversion-api</artifactId>
<version>4.5.1</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -115,7 +103,7 @@
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.53.Final</version>
<version>4.1.58.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -133,25 +121,25 @@
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.10.1</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>
<artifactId>adventure-platform-bukkit</artifactId>
<version>4.1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.discordsrv</groupId>
<artifactId>discordsrv</artifactId>
<version>1.24.1-SNAPSHOT</version>
<version>1.26.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.willfp</groupId>
<artifactId>EcoEnchants</artifactId>
<version>8.57.2</version>
<version>9.17.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -183,7 +171,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
@@ -223,7 +211,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<version>3.3.0</version>
<configuration>
<outputDirectory>${export_dir}</outputDirectory>
</configuration>
+39 -45
View File
@@ -1,20 +1,13 @@
package me.dadus33.chatitem;
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;
import me.dadus33.chatitem.commands.CIReloadCommand;
import me.dadus33.chatitem.commands.ChatItemCommand;
import me.dadus33.chatitem.filters.Log4jFilter;
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 java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.StringJoiner;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
@@ -23,16 +16,29 @@ import org.bukkit.command.TabCompleter;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.*;
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;
import me.dadus33.chatitem.commands.CIReloadCommand;
import me.dadus33.chatitem.commands.ChatItemCommand;
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;
public class ChatItem extends JavaPlugin {
public final static int CFG_VER = 13;
public static boolean discordSrvSupport = false, ecoEnchantsSupport = false, hasNewVersion = false;
public static boolean discordSrvSupport = 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;
public static void reload(CommandSender sender) {
@@ -40,13 +46,12 @@ public class ChatItem extends JavaPlugin {
if (pl.getConfig().getKeys(false).isEmpty())
pl.saveDefaultConfig();
pl.reloadConfig();
String oldChatManager = pl.storage.MANAGER;
String oldChatManager = pl.storage.manager;
pl.storage = new Storage(pl.getConfig());
pl.chooseManagers();
pl.filter.setStorage(pl.storage);
if (!pl.storage.RELOAD_MESSAGE.isEmpty())
sender.sendMessage(pl.storage.RELOAD_MESSAGE);
if (!oldChatManager.equalsIgnoreCase(pl.storage.MANAGER))
if (!pl.storage.messageReload.isEmpty())
sender.sendMessage(pl.storage.messageReload);
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.");
}
@@ -55,15 +60,15 @@ public class ChatItem extends JavaPlugin {
}
public static void debug(String msg) {
if (getInstance().getStorage().DEBUG)
getInstance().getLogger().info("[Debug] " + msg);
if (getInstance().getStorage().debug)
getInstance().getLogger().info("[Debug] " + msg.replace(ChatManager.SEPARATOR, 'S').replace(ChatManager.SEPARATOR_END, 'E'));
}
private void chooseManagers() {
this.chatManager.forEach((cm) -> cm.unload(this));
this.chatManager.clear();
PluginManager pm = getServer().getPluginManager();
String managerName = getStorage().MANAGER;
String managerName = getStorage().manager;
switch (managerName.toLowerCase(Locale.ROOT)) {
case "both":
@@ -103,7 +108,7 @@ public class ChatItem extends JavaPlugin {
}
private List<String> getPluginThatRequirePacket() {
return Arrays.asList("DeluxeChat", "HexNicks", "VentureChat");
return Arrays.asList("DeluxeChat", "HexNicks", "VentureChat", "ItemsAdder");
}
@Override
@@ -113,7 +118,8 @@ public class ChatItem extends JavaPlugin {
getLogger().info("Detected server version: " + Version.getVersion().name().toLowerCase());
//Load config
saveDefaultConfig();
if(!new File(getDataFolder(), "config.yml").exists())
saveDefaultConfig();
storage = new Storage(getConfig());
//Commands
@@ -127,30 +133,19 @@ public class ChatItem extends JavaPlugin {
chooseManagers();
//Initialize Log4J filter (remove ugly console messages)
filter = new Log4jFilter(storage);
StringJoiner plugins = new StringJoiner(", ");
if (pm.getPlugin("DiscordSRV") != null) {
if (pm.isPluginEnabled("DiscordSRV")) {
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.");
getServer().getMessenger().registerIncomingPluginChannel(this, brandChannelName, (chan, p, msg) -> {
String client = new String(msg);
ChatItem.debug("Detected client " + client + " for " + p.getName());
ItemPlayer.getPlayer(p).setClientName(client);
});
getServer().getMessenger().registerIncomingPluginChannel(this, brandChannelName, (chan, p, msg) -> ItemPlayer.getPlayer(p).setClientName(new String(msg).substring(1)));
if (storage.CHECK_UPDATE) {
if (storage.checkUpdate) {
getServer().getScheduler().runTaskAsynchronously(this, () -> {
String urlName = "https://api.spigotmc.org/legacy/update.php?resource=19064";
String content = Utils.getFromURL(urlName);
@@ -162,9 +157,8 @@ public class ChatItem extends JavaPlugin {
SemVer latestVersion = SemVer.parse(content);
if (latestVersion != null && latestVersion.isNewerThan(currentVersion)) {
hasNewVersion = !content.equalsIgnoreCase(getDescription().getVersion());
if (hasNewVersion) {
getLogger().info(storage.JOIN_UPDATE_MESSAGE);
}
if (hasNewVersion)
getLogger().info(storage.updateMessage);
}
});
}
@@ -1,7 +1,7 @@
package me.dadus33.chatitem;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@@ -11,7 +11,7 @@ import me.dadus33.chatitem.utils.Version;
public class ItemPlayer {
private static final HashMap<UUID, ItemPlayer> PLAYERS = new HashMap<>();
private static final ConcurrentHashMap<UUID, ItemPlayer> PLAYERS = new ConcurrentHashMap<>();
public static ItemPlayer getPlayer(Player p) {
return PLAYERS.computeIfAbsent(p.getUniqueId(), ItemPlayer::new);
}
@@ -0,0 +1,86 @@
package me.dadus33.chatitem.chatmanager;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.ItemPlayer;
import me.dadus33.chatitem.utils.Utils;
public class Chat {
private static int actualId = 0;
private static final List<Chat> CHAT = new ArrayList<>();
public static Optional<Chat> getChat(int id) {
synchronized (CHAT) {
CHAT.removeIf(Chat::isOld);
return CHAT.stream().filter(o -> o.getId() == id).findFirst();
}
}
public static Chat create(Player p, String message) {
return new Chat(actualId++, p, message);
}
public static Chat getFrom(String message) {
boolean found = false;
String id = "";
for(char c : ChatManager.fixSeparator(message).toCharArray()) {
if(c == ChatManager.SEPARATOR)
found = true;
else if(c == ChatManager.SEPARATOR_END)
break;
else if(found)
id += c;
}
ChatItem.debug("Search in " + message + ", id found: " + id);
return (id != "" && Utils.isInteger(id)) ? Chat.getChat(Integer.parseInt(id)).orElse(null) : null;
}
private final long time;
private final int id;
private final Player p;
private final String message;
public Chat(int id, Player p, String message) {
this.time = System.currentTimeMillis();
this.id = id;
this.p = p;
this.message = message;
CHAT.add(this);
}
public long getTime() {
return time;
}
public int getId() {
return id;
}
public Player getPlayer() {
return p;
}
public String getMessage() {
return message;
}
public ItemPlayer getItemPlayer() {
return ItemPlayer.getPlayer(getPlayer());
}
private boolean isOld() {
return System.currentTimeMillis() > time + 10000;
}
public void remove() {
CHAT.remove(this);
}
@Override
public String toString() {
return "Chat{id=" + id + ",message=" + message + ",time=" + time + "}";
}
}
@@ -5,6 +5,8 @@ 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;
@@ -13,21 +15,51 @@ 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 {
public final static HashMap<UUID, Long> COOLDOWNS = new HashMap<>();
public final static HashMap<UUID, Long> LAST_INFO_MESSAGE = new HashMap<>();
public final static String NAME = "{name}";
public final static String AMOUNT = "{amount}";
public final static String TIMES = "{times}";
public final static String LEFT = "{remaining}";
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);
public final static String SEPARATOR_STR = "\\u0007";
public final static char SEPARATOR_END = ((char) 0x0003);
public final static String SEPARATOR_END_STR = "\\u0003";
public static String removeSeparator(String message) {
return fixSeparator(message).replace(Character.toString(SEPARATOR), "").replace(Character.toString(SEPARATOR_END), "");
}
public static String replaceSeparator(Chat chat, String message, String replacement) {
return fixSeparator(message).replace(Character.toString(SEPARATOR) + (chat != null ? chat.getId() : "") + Character.toString(SEPARATOR_END), replacement);
}
public static String fixSeparator(String s) {
return s == null ? "" : s.replace(SEPARATOR_STR, Character.toString(SEPARATOR)).replace(SEPARATOR_END_STR, Character.toString(SEPARATOR_END));
}
public static boolean equalsSeparator(String s) {
return s != null && (s.equalsIgnoreCase(SEPARATOR_STR) || s.equalsIgnoreCase(Character.toString(SEPARATOR)));
}
public static boolean containsSeparator(String s) {
return s != null && (s.contains(SEPARATOR_STR) || s.contains(Character.toString(SEPARATOR)));
}
public static boolean equalsSeparatorEnd(String s) {
return s != null && (s.equalsIgnoreCase(SEPARATOR_END_STR) || s.equalsIgnoreCase(Character.toString(SEPARATOR_END)));
}
public static boolean containsSeparatorEnd(String s) {
return s != null && (s.contains(SEPARATOR_END_STR) || s.contains(Character.toString(SEPARATOR_END)));
}
protected Storage s;
@@ -48,7 +80,7 @@ public abstract class ChatManager {
}
public abstract void unload(ChatItem pl);
/**
* Get the item in hand as usable one.<br>
* Will include, in lore, all informations from other plugins.
@@ -58,36 +90,61 @@ public abstract class ChatManager {
*/
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);
}
}
/*
* 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
* 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
* @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;
String replacer = c.nameFormat;
String amount = c.amountFormat;
boolean dname = item.hasItemMeta() && item.getItemMeta().hasDisplayName();
if (item.getAmount() == 1) {
if (c.FORCE_ADD_AMOUNT) {
if (c.addAmountForced) {
amount = amount.replace(TIMES, "1");
replacer = replacer.replace(AMOUNT, amount);
} else {
@@ -99,7 +156,8 @@ public abstract class ChatManager {
}
if (dname) {
String trp = item.getItemMeta().getDisplayName();
if (c.COLOR_IF_ALREADY_COLORED) {
ChatItem.debug("trp: " + trp);
if (c.colorIfColored) {
replacer = replacer.replace(NAME, ChatColor.stripColor(trp));
} else {
replacer = replacer.replace(NAME, trp);
@@ -113,43 +171,19 @@ public abstract class ChatManager {
/**
* Get the name of item according to player & config
*
* @param p the player
* @param p the player that is owner of item
* @param item the item
* @param c the config
* @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);
if (ItemUtils.isEmpty(item)) {
if (c.handDisabled)
return c.placeholders.get(0);
else
return c.HAND_NAME;
return c.handName;
}
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;
return styleItem(p, item, c);
}
public static String calculateTime(long seconds) {
@@ -160,7 +194,7 @@ public abstract class ChatManager {
if (seconds < 3600) {
StringBuilder builder = new StringBuilder();
int minutes = (int) seconds / 60;
builder.append(minutes).append(c.MINUTES);
builder.append(minutes).append(c.minutes);
int secs = (int) seconds - minutes * 60;
if (secs != 0) {
builder.append(" ").append(secs).append(c.SECONDS);
@@ -169,10 +203,10 @@ public abstract class ChatManager {
}
StringBuilder builder = new StringBuilder();
int hours = (int) seconds / 3600;
builder.append(hours).append(c.HOURS);
builder.append(hours).append(c.hours);
int minutes = (int) (seconds / 60) - (hours * 60);
if (minutes != 0) {
builder.append(" ").append(minutes).append(c.MINUTES);
builder.append(" ").append(minutes).append(c.minutes);
}
int secs = (int) (seconds - ((seconds / 60) * 60));
if (secs != 0) {
@@ -181,42 +215,45 @@ public abstract class ChatManager {
return builder.toString();
}
public static boolean canShowItem(Player p, ItemStack item, Cancellable e) {
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) {
e.setCancelled(true);
if (c.permissionEnabled && !p.hasPermission(c.permissionName)) {
if (!c.letMessageThrough) {
if (e != null)
e.setCancelled(true);
}
if (!c.NO_PERMISSION_MESSAGE.isEmpty() && c.SHOW_NO_PERM_NORMAL) {
sendIfNeed(p, c.NO_PERMISSION_MESSAGE);
if (!c.messageNoPermission.isEmpty() && c.showNoPermissionMessage) {
sendIfNeed(p, c.messageNoPermission);
}
return false;
}
if (item.getType().equals(Material.AIR)) {
if (c.DENY_IF_NO_ITEM) {
e.setCancelled(true);
if (!c.DENY_MESSAGE.isEmpty())
sendIfNeed(p, c.DENY_MESSAGE);
if (c.denyIfNoItem) {
if (e != null)
e.setCancelled(true);
if (!c.messageDeny.isEmpty())
sendIfNeed(p, c.messageDeny);
return false;
}
if (c.HAND_DISABLED) {
if (c.handDisabled) {
return false;
}
}
if (c.COOLDOWN > 0 && !p.hasPermission("chatitem.ignore-cooldown")) {
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) {
if (elapsed >= c.cooldown) {
COOLDOWNS.remove(p.getUniqueId());
} else {
if (!c.LET_MESSAGE_THROUGH) {
e.setCancelled(true);
if (!c.letMessageThrough) {
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)));
if (!c.messageCooldown.isEmpty()) {
long left = (start + c.cooldown) - current;
sendIfNeed(p, c.messageCooldown.replace(LEFT, ChatManager.calculateTime(left)));
}
ChatItem.debug("Cooldown");
return false;
@@ -226,20 +263,24 @@ public abstract class ChatManager {
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) {
if (time != null) {
long diff = System.currentTimeMillis() - time;
if(diff < 100)
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);
}
}
@@ -1,69 +1,89 @@
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.JSONManipulatorCurrent;
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.PacketManager;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.Storage;
public class PacketEditingChatManager extends ChatManager {
private final JSONManipulatorCurrent jsonManipulator;
private boolean baseComponentAvailable = true;
private final ChatItemPacketManager packetManager;
private final ChatEventListener chatEventListener;
private final ChatPacketManager chatPacketManager;
public PacketEditingChatManager(ChatItem pl) {
jsonManipulator = new JSONManipulatorCurrent();
packetManager = new ChatItemPacketManager(pl);
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;
}
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);
Bukkit.getPluginManager().registerEvents(chatEventListener, pl);
packetManager.getPacketManager().addHandler(chatPacketManager);
PacketManager pm = packetManager.getPacketManager();
pm.addHandler(chatPacketManager);
Bukkit.getOnlinePlayers().forEach(pm::addPlayer); // add actual online players
}
@Override
public void unload(ChatItem pl) {
HandlerList.unregisterAll(chatEventListener);
packetManager.getPacketManager().removeHandler(chatPacketManager);
packetManager.getPacketManager().stop();
PacketManager pm = packetManager.getPacketManager();
pm.removeHandler(chatPacketManager);
pm.stop();
}
public JSONManipulatorCurrent getManipulator(){
return jsonManipulator;
}
public boolean supportsChatComponentApi(){
return baseComponentAvailable;
}
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;
}
}
@@ -1,14 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
public interface IBaseComponentGetter {
default boolean hasConditions() {
return true;
}
String getBaseComponentAsJSON(ChatItemPacket packet);
void writeJson(ChatItemPacket packet, String json);
}
@@ -0,0 +1,128 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp;
import javax.annotation.Nullable;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
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.ItemPlayer;
import me.dadus33.chatitem.chatmanager.Chat;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulator;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.utils.Storage;
import me.dadus33.chatitem.utils.Utils;
public interface IComponentManager {
default boolean hasConditions() {
return true;
}
String getBaseComponentAsJSON(ChatItemPacket packet);
void writeJson(ChatItemPacket packet, String json);
default @Nullable Chat getChat(String json) {
json = ChatManager.fixSeparator(json);
try {
Chat possibleChat = Chat.getFrom(json);
if (possibleChat != null) // found something with basic search
return possibleChat;
Chat chat = new Searching(json).search();
if (chat == null)
ChatItem.debug("Failed to find chat for JSON " + json);
return chat;
} catch (Exception e) {
e.printStackTrace();
} // not JSON
return null;
}
default Object manageItem(Player p, Chat chat, ChatItemPacket packet, ItemStack item, Storage c) throws Exception {
String message = JSONManipulator.getInstance().parse(getBaseComponentAsJSON(packet), item, ChatManager.styleItem(chat.getPlayer(), item, c),
ItemPlayer.getPlayer(p).getProtocolVersion());
if (message != null) {
ChatItem.debug("(v1) Writing message: " + message);
writeJson(packet, message);
}
return packet.getPacket();
}
default Object manageEmpty(Player p, Chat chat, ChatItemPacket packet, Storage c) {
String message = JSONManipulator.getInstance().parseEmpty(getBaseComponentAsJSON(packet), c.handName, c.tooltipHand, chat.getPlayer());
if (message != null) {
ChatItem.debug("(v1) Writing empty message: " + message);
writeJson(packet, message);
}
return packet.getPacket();
}
public static class Searching {
private boolean found = false;
private String id = "", json;
public Searching(String json) {
this.json = json;
}
private Chat search() {
JsonObject jsonObj = JsonParser.parseString(json).getAsJsonObject();
if (jsonObj.has("extra")) {
if (searchInExtra(jsonObj.getAsJsonArray("extra"))) {
return getWithId();
}
}
if (jsonObj.has("text")) {
JsonElement text = jsonObj.get("text");
if(text.isJsonObject() && searchInObject(text.getAsJsonObject()))
return getWithId();
else if(text.isJsonArray() && searchInExtra(text.getAsJsonArray()))
return getWithId();
else if(text.isJsonPrimitive() && searchInString(text.getAsString()))
return getWithId();
}
return null;
}
private Chat getWithId() {
return id != "" && Utils.isInteger(id) ? Chat.getChat(Integer.parseInt(id)).orElse(null) : null;
}
private boolean searchInExtra(JsonArray json) {
for (JsonElement element : json) {
if (element.isJsonObject()) {
JsonObject withObj = element.getAsJsonObject();
if (withObj.has("extra") && searchInExtra(withObj.getAsJsonArray("extra")))
return true;
else if (withObj.has("text") && searchInObject(withObj))
return true;
}
}
return false;
}
private boolean searchInObject(JsonObject json) {
return json.has("text") && json.get("text").isJsonPrimitive() && searchInString(json.get("text").getAsString());
}
private boolean searchInString(String s) {
for (char c : ChatManager.fixSeparator(s).toCharArray()) {
if (c == ChatManager.SEPARATOR)
found = true;
else if (c == ChatManager.SEPARATOR_END)
return true;
else if (found)
id += c;
}
return false;
}
}
}
@@ -1,100 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import java.util.Arrays;
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.basecomp.IBaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.utils.PacketUtils;
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 {
@Override
public boolean hasConditions() {
try {
for (String cl : Arrays.asList("net.kyori.adventure.text.Component",
"net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer"))
Class.forName(cl);
} catch (ClassNotFoundException e) { // can't support this, adventure comp not found
return false;
}
try {
PacketUtils.getNmsClass("PacketPlayOutChat", "network.protocol.game.").getField("adventure$message");
} catch (NoSuchFieldException e) {
return false;
}
return true;
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Component comp = packet.getContent().getSpecificModifier(Component.class).readSafely(0);
if(comp == null)
return null;
String json = ComponentSerializer.toString(BungeeComponentSerializer.legacy().serialize(comp).clone());
JsonObject jsonObj = JsonParser.parseString(json).getAsJsonObject();
JsonObject next = new JsonObject();
next.add("extra", jsonObj.get("with"));
return next.toString();
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
JsonObject next = new JsonObject();
next.addProperty("translate", "chat.type.text");
next.add("with", fixParsedArray(JsonParser.parseString(json).getAsJsonObject().getAsJsonArray("extra")));
ChatItem.debug("Adventure Json: " + next.toString());
packet.getContent().getSpecificModifier(Component.class).write(0, BungeeComponentSerializer.legacy().deserialize(ComponentSerializer.parse(next.toString())));
}
private 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");
hoverObject.add("contents", JsonParser.parseString("{" + val.substring(1, val.length() - 1) + "}"));
o.add("hoverEvent", hoverObject);
}
}
}
return e;
}
}
@@ -0,0 +1,114 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.Chat;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IComponentManager;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent.ContentModifier;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.Storage;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.nbt.api.BinaryTagHolder;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TranslatableComponent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
public class AdventureComponentManager implements IComponentManager {
@Override
public boolean hasConditions() {
try {
for (String cl : Arrays.asList("net.kyori.adventure.text.Component", "net.kyori.adventure.text.serializer.gson.GsonComponentSerializer"))
Class.forName(cl);
} catch (Exception e) { // can't support this, adventure comp not found
ChatItem.debug("Can't load AdventureComponentManager : " + e.getMessage());
return false;
}
return true;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Component comp = packet.getContent().getSpecificModifier(Component.class).readSafely(0);
if (comp == null)
return null;
String json = GsonComponentSerializer.gson().serialize(comp);
JsonObject jsonObj = JsonParser.parseString(json).getAsJsonObject();
ChatItem.debug("AdventureJSON : " + json);
if (jsonObj.has("with")) {
JsonObject next = new JsonObject();
next.add("extra", jsonObj.get("with"));
return next.toString();
}
return json;
}
@Override
public Object manageItem(Player p, Chat chat, ChatItemPacket packet, ItemStack item, Storage c) throws Exception {
String itemName = ChatManager.getNameOfItem(chat.getPlayer(), item, c);
return manage(p, chat, packet, itemName, HoverEvent.showItem(Key.key(item.getType().getKey().getKey()), item.getAmount(), BinaryTagHolder.of(PacketUtils.getNbtTag(item))));
}
@Override
public Object manageEmpty(Player p, Chat chat, ChatItemPacket packet, Storage c) {
Component builder = Component.text("");
c.tooltipHand.forEach(s -> builder.append(Component.text(s)));
Player sender = chat.getPlayer();
String handName = c.handName.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName());
return manage(p, chat, packet, handName, HoverEvent.showText(builder));
}
private Object manage(Player p, Chat chat, ChatItemPacket packet, String replacement, HoverEvent<?> hover) {
ContentModifier<Component> modifier = packet.getContent().getSpecificModifier(Component.class);
Component comp = modifier.readSafely(0);
if (comp == null) {
ChatItem.debug("The component is null.");
return null;
}
comp = checkComponent(comp, hover, replacement, chat);
ChatItem.debug("Result: " + GsonComponentSerializer.gson().serialize(comp));
modifier.write(0, comp);
packet.setPacket(modifier.getObj());
return packet.getPacket();
}
private Component checkComponent(Component comp, HoverEvent<?> hover, String itemName, Chat chat) {
if (comp instanceof TextComponent) {
TextComponent tc = (TextComponent) comp;
if (ChatManager.containsSeparator(tc.content())) {
ChatItem.debug("Changing text " + tc.content() + " to " + itemName);
comp = tc.content(ChatManager.replaceSeparator(chat, tc.content(), itemName)).hoverEvent(hover);
} else
ChatItem.debug("No insert of text without separator: " + tc.content());
} else if(comp instanceof TranslatableComponent) {
TranslatableComponent tc = (TranslatableComponent) comp;
List<Component> next = new ArrayList<>();
for (Component extra : tc.args()) {
next.add(checkComponent(extra, hover, itemName, chat));
}
comp = tc.args(next);
} else
ChatItem.debug("Not valid comp class " + comp.getClass().getSimpleName() + " : " + comp);
List<Component> next = new ArrayList<>();
for (Component extra : comp.children()) {
next.add(checkComponent(extra, hover, itemName, chat));
}
return comp.children(next);
}
}
@@ -1,26 +0,0 @@
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));
}
}
@@ -1,23 +1,22 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IBaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IComponentManager;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.utils.PacketUtils;
public class ComponentGetter implements IBaseComponentGetter {
public class ComponentNMSManager implements IComponentManager {
@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();
return PacketUtils.CHAT_SERIALIZER.getMethod("a", PacketUtils.COMPONENT_CLASS).invoke(null, chatBaseComp).toString();
} catch (Exception exc) {
exc.printStackTrace();
}
@@ -1,55 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import java.lang.reflect.Method;
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.utils.PacketUtils;
public class IChatBaseComponentGetter implements IBaseComponentGetter {
private Method serializerGetJson;
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 {
packet.getContent().getChatComponents().write(0, PacketUtils.CHAT_SERIALIZER.getMethod("a", String.class).invoke(null, json));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,90 @@
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.IComponentManager;
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 IChatBaseComponentManager implements IComponentManager {
private Method serializerGetJson, fromJson;
private boolean canEditVariable = true;
public IChatBaseComponentManager() {
try {
Class<?> chatSerializer = PacketUtils.CHAT_SERIALIZER;
fromJson = chatSerializer.getMethod("a", String.class);
for (Method m : chatSerializer.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: " + chatSerializer.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 = fromJson.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 IChatBaseComponentManager. 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();
}
}
}
@@ -1,24 +0,0 @@
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 StringComponentGetter implements IBaseComponentGetter{
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
return packet.getContent().getStrings().read(0);
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
Class<?> packetClass = PacketUtils.getNmsClass("ClientboundSystemChatPacket", "network.protocol.game.");
packet.setPacket(packetClass.getConstructor(String.class, int.class).newInstance(json, 1));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,137 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
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.Chat;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IComponentManager;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.utils.Storage;
import me.dadus33.chatitem.utils.Utils;
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.TextComponent;
import net.md_5.bungee.chat.ComponentSerializer;
public class StringComponentManager implements IComponentManager {
@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();
} else if (json == null) {
BaseComponent[] comp = packet.getContent().getSpecificModifier(BaseComponent[].class).readSafely(0);
if (comp != null)
return ComponentSerializer.toString(comp);
}
return json;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json));
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Object manageItem(Player p, Chat chat, ChatItemPacket packet, ItemStack item, Storage c) throws Exception {
return manage(p, chat, packet, ChatManager.getNameOfItem(chat.getPlayer(), item, c), Utils.createItemHover(item));
}
@Override
public Object manageEmpty(Player p, Chat chat, ChatItemPacket packet, Storage c) {
ComponentBuilder builder = new ComponentBuilder("");
c.tooltipHand.forEach(s -> builder.append(s));
Player sender = chat.getPlayer();
String handName = c.handName.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName());
return manage(p, chat, packet, handName, Utils.createTextHover(builder.create()));
}
private Object manage(Player p, Chat chat, ChatItemPacket packet, String replacement, HoverEvent hover) {
BaseComponent[] components = packet.getContent().getSpecificModifier(BaseComponent[].class).readSafely(0);
if (components == null) {
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();
}
try {
components = ComponentSerializer.parse(json);
} catch (Exception e) {
ChatItem.getInstance().getLogger().severe("Failed to parse JSON: " + json + ". Error:");
e.printStackTrace();
return packet.getPacket();
}
}
ChatItem.debug("Checking for " + components.length + " components");
Arrays.asList(components).forEach(comp -> checkComponent(comp, hover, replacement, chat));
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(ComponentSerializer.toString(components)));
} catch (Exception e) {
e.printStackTrace();
}
return packet.getPacket();
}
private void checkComponent(BaseComponent comp, HoverEvent hover, String itemName, Chat chat) {
if (comp instanceof TextComponent) {
TextComponent tc = (TextComponent) comp;
if (ChatManager.containsSeparator(tc.getText())) {
ChatItem.debug("Changing text " + tc.getText() + " to " + itemName);
tc.setText(ChatManager.replaceSeparator(chat, tc.getText(), itemName));
tc.setHoverEvent(hover);
List<BaseComponent> extra = new ArrayList<>();
for (BaseComponent legacyExtra : TextComponent.fromLegacyText(itemName, tc.getColor())) {
extra.add(legacyExtra);
}
if (tc.getExtra() != null)
extra.addAll(tc.getExtra());
tc.setExtra(extra);
} else
ChatItem.debug("No insert of text without separator: " + tc.getText() + " (legacy: " + tc.toLegacyText() + ")");
}
if (comp.getExtra() != null) {
for (BaseComponent extra : comp.getExtra()) {
checkComponent(extra, hover, itemName, chat);
}
}
}
}
@@ -0,0 +1,292 @@
package me.dadus33.chatitem.chatmanager.v1.json;
import static me.dadus33.chatitem.utils.PacketUtils.getNmsClass;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
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.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
import me.dadus33.chatitem.utils.Version;
public class JSONManipulator {
private static JSONManipulator instance = new JSONManipulator();
public static JSONManipulator getInstance() {
return instance;
}
private static final List<String> SKIPPED = Arrays.asList("HSTRY_ENCHANTS");
public static final Class<?> CRAFT_ITEM_STACK_CLASS = PacketUtils.getObcClass("inventory.CraftItemStack");
public static final Class<?> NMS_ITEM_STACK_CLASS = getNmsClass("ItemStack", "world.item.");
public static final Method AS_NMS_COPY = ReflectionUtils.getMethod(CRAFT_ITEM_STACK_CLASS, "asNMSCopy", ItemStack.class);
public static final Class<?> NBT_TAG_COMPOUND = getNmsClass("NBTTagCompound", "nbt.");
public static final Method SAVE_NMS_ITEM_STACK_METHOD = ReflectionUtils.getMethod(NMS_ITEM_STACK_CLASS, NBT_TAG_COMPOUND, NBT_TAG_COMPOUND);
public static final Field MAP = ReflectionUtils.getField(NBT_TAG_COMPOUND, "map", "x");
private static final ConcurrentHashMap<Map.Entry<Version, ItemStack>, JsonObject> STACKS = new ConcurrentHashMap<>();
private JsonObject itemTooltip;
private JsonArray classicTooltip;
public String parse(String json, ItemStack item, String replacement, int protocol) throws Exception {
JsonObject obj = JsonParser.parseString(json).getAsJsonObject();
final AbstractMap.SimpleEntry<Version, ItemStack> p = new AbstractMap.SimpleEntry<>(Version.getVersion(protocol), item);
JsonObject wrapper = new JsonObject(); // Create a wrapper object for the whole array
if ((itemTooltip = STACKS.get(p)) == null) {
JsonArray use = Translator.toJson(replacement); // We get the json representation of the old color
// formatting method
ChatItem.debug("Remplacement: " + replacement + " use: " + use.toString());
// There's no public clone method for JSONObjects so we need to parse them every
// time
JsonObject hover = new JsonObject();
hover.addProperty("action", "show_item");
// Get the JSON representation of the item (well, not really JSON, but rather a
// string representation of NBT data)
hover.addProperty("value", stringifyItem(item));
if (use.size() == 1) {
JsonElement extraElement = use.get(0);
if (extraElement.isJsonPrimitive())
wrapper.addProperty("text", extraElement.getAsString());
else if (extraElement.isJsonObject())
wrapper.addProperty("text", extraElement.getAsJsonObject().get("text").getAsString());
else
wrapper.add("extra", use); // add it only if
} else if (!use.isEmpty())
wrapper.add("extra", use); // add it only if
if (!wrapper.has("text"))
wrapper.addProperty("text", ""); // The text field is compulsory, even if it's empty
wrapper.add("hoverEvent", hover);
itemTooltip = wrapper; // Save the tooltip for later use when we encounter a placeholder
STACKS.put(p, itemTooltip); // Save it in the cache too so when parsing other packets with the same item
// (and client version) we no longer have to create it again
// We remove it later when no longer needed to save memory
Bukkit.getScheduler().runTaskLaterAsynchronously(ChatItem.getInstance(), () -> STACKS.remove(p), 100L);
}
if (obj.size() == 1 && obj.has("text")) {
itemTooltip.add("text", obj.get("text"));
ChatItem.debug("[JsonManipulator] Parsed quick: " + obj.toString() + ", wrapper: " + itemTooltip);
return itemTooltip.toString().replace(Character.toString(ChatManager.SEPARATOR), "").replace(ChatManager.SEPARATOR_STR, "");
}
obj.add("extra", parseArray(obj.has("extra") ? obj.getAsJsonArray("extra") : new JsonArray(), itemTooltip));
if (!obj.has("text")) {
obj.addProperty("text", "");
}
ChatItem.debug("Parsed array for item: " + obj.toString() + ", wrapper: " + itemTooltip);
return obj.toString();
}
public String parseEmpty(String json, String repl, List<String> tooltip, Player sender) {
JsonObject obj = JsonParser.parseString(json).getAsJsonObject();
JsonArray array = obj.has("extra") ? obj.getAsJsonArray("extra") : new JsonArray();
JsonArray use = Translator.toJson(repl.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName()));
JsonObject hover = JsonParser.parseString("{\"action\":\"show_text\", \"value\": \"\"}").getAsJsonObject();
StringBuilder oneLineTooltip = new StringBuilder("");
int index = 0;
for (String m : tooltip) {
oneLineTooltip.append(m.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName()));
++index;
if (index != tooltip.size()) {
oneLineTooltip.append('\n');
}
}
hover.add("value", new JsonPrimitive(oneLineTooltip.toString()));
if (!tooltip.isEmpty()) {
for (JsonElement ob : use)
ob.getAsJsonObject().add("hoverEvent", hover);
classicTooltip = use;
}
obj.add("extra", parseArray(array, classicTooltip));
if (!obj.has("text")) {
obj.addProperty("text", "");
}
return obj.toString();
}
private JsonArray parseArray(JsonArray arr, JsonElement tooltip) {
JsonArray replacer = new JsonArray();
boolean isComplex = false;
for (int i = 0; i < arr.size(); ++i) {
JsonElement element = arr.get(i);
if (element.isJsonNull()) {
continue;
} else if (element.isJsonObject()) {
isComplex = true;
addParsedJsonObjectToArray(element.getAsJsonObject(), replacer, tooltip);
} else if (element.isJsonArray()) {
isComplex = true;
JsonArray jar = element.getAsJsonArray();
if (jar.size() != 0) {
jar = parseArray(element.getAsJsonArray(), tooltip);
replacer.set(i, jar);
}
} else if (element.isJsonPrimitive() && isComplex) {
ChatItem.debug("[JSONManipulator] Put " + element + " to trash as it's primitive with complex things");
// ignore
} else {
addParsedStringToArray(element.getAsString(), replacer, element, tooltip);
}
}
return replacer;
}
private void addParsedJsonObjectToArray(JsonObject o, JsonArray rep, JsonElement tooltip) {
JsonElement text = o.get("text");
if (text == null) {
JsonElement el = o.get("extra");
if (el != null) {
JsonArray jar = el.getAsJsonArray();
if (jar.size() != 0) {
JsonArray tmpArray = parseArray(jar, tooltip);
if (!tmpArray.isEmpty())
o.add("extra", tmpArray);
else
o.remove("extra");
} else {
o.remove("extra");
}
}
return;
} else {
if (text.getAsString().isEmpty()) {
JsonElement el = o.get("extra");
if (el != null) {
JsonArray jar = el.getAsJsonArray();
if (!jar.isEmpty()) {
JsonArray tmpArray = parseArray(jar, tooltip);
if (!tmpArray.isEmpty())
o.add("extra", tmpArray);
else
o.remove("extra");
} else {
o.remove("extra");
}
}
}
}
addParsedStringToArray(text.getAsString(), rep, o, tooltip);
}
private void addParsedStringToArray(String msg, JsonArray rep, JsonElement o, JsonElement tooltip) {
ChatItem.debug("Checking " + msg + " > " + rep + ", o: " + o);
if (!ChatManager.containsSeparator(msg)) {
rep.add(o);
return;
}
String current = "";
boolean wasSep = false;
for (String parts : msg.split("")) {
if (ChatManager.equalsSeparator(parts)) {
if (!current.isEmpty()) {
rep.add(current);
current = "";
}
rep.add(tooltip);
wasSep = true;
} else if (wasSep) {
if (ChatManager.equalsSeparatorEnd(parts)) // sep finished
wasSep = false;
} else {
current += parts;
}
}
if (!current.isEmpty())
rep.add(current);
}
public static String stringifyItem(ItemStack is) {
try {
return stringifyItemInternal(is);
} catch (Exception e) {
e.printStackTrace();
return "{}";
}
}
@SuppressWarnings({ "deprecation" })
public static String stringifyItemInternal(ItemStack is) throws Exception {
Object nmsStack = JSONManipulator.AS_NMS_COPY.invoke(null, is);
Object nmsTag = JSONManipulator.NBT_TAG_COMPOUND.newInstance();
JSONManipulator.SAVE_NMS_ITEM_STACK_METHOD.invoke(nmsStack, nmsTag);
HashMap<String, String> tagMap = new HashMap<>();
Map<String, Object> nmsMap = (Map<String, Object>) JSONManipulator.MAP.get(nmsTag);
String id = nmsMap.get("id").toString().replace("\"", "");
Object realTag = nmsMap.get("tag");
if (JSONManipulator.NBT_TAG_COMPOUND.isInstance(realTag)) { // We need to make sure this is indeed an
// NBTTagCompound
Map<String, Object> realMap = (Map<String, Object>) JSONManipulator.MAP.get(realTag);
Set<Map.Entry<String, Object>> entrySet = realMap.entrySet();
for (Map.Entry<String, Object> entry : entrySet) {
tagMap.put(entry.getKey(), entry.getValue().toString());
}
}
// TODO check for ID remapping
// ItemRewriter.remapIds(Version.getVersion().MAX_VER, protocolVersion.MAX_VER,
// is);
StringBuilder sb = new StringBuilder("{id:");
sb.append("\"").append(id).append("\"").append(","); // Append the id
sb.append("Count:").append(is.getAmount()).append("b"); // Append the amount
if (!tagMap.containsKey("Damage")) { // for new versions
sb.append(",Damage:").append(is.getDurability()).append("s"); // Append the durability data
}
if (tagMap.isEmpty()) {
sb.append("}");
return sb.toString();
}
Set<Map.Entry<String, String>> entrySet = tagMap.entrySet();
boolean first = true;
sb.append(",tag:{"); // Start of the tag
for (Map.Entry<String, String> entry : entrySet) {
if (SKIPPED.contains(entry.getKey()))
continue;
if (!first)
sb.append(",");
first = false;
if (!entry.getKey().isEmpty()) {
if (entry.getKey().contains(";"))
sb.append("\"" + entry.getKey() + "\"");
else
sb.append(entry.getKey());
sb.append(":");
}
ChatItem.debug("Cleaning " + entry.getKey() + ": " + entry.getValue() + " > " + cleanStr(entry.getValue()));
sb.append(cleanStr(entry.getValue()));
}
sb.append("}}"); // End of tag and end of item
return sb.toString();
}
private static String cleanStr(String s) {
return s.startsWith("'") && s.endsWith("'") ? s.substring(1, s.length() - 1) : s;
}
}
@@ -1,250 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.json;
import static me.dadus33.chatitem.utils.PacketUtils.getNmsClass;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
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.utils.PacketUtils;
import me.dadus33.chatitem.utils.Reflect;
import me.dadus33.chatitem.utils.Version;
@SuppressWarnings({ "unchecked" })
public class JSONManipulatorCurrent {
private static final Class<?> CRAFT_ITEM_STACK_CLASS = PacketUtils.getObcClass("inventory.CraftItemStack");
private static final Class<?> NMS_ITEM_STACK_CLASS = getNmsClass("ItemStack", "world.item.");
private static final Method AS_NMS_COPY = Reflect.getMethod(CRAFT_ITEM_STACK_CLASS, "asNMSCopy", ItemStack.class);
private static final Class<?> NBT_TAG_COMPOUND = getNmsClass("NBTTagCompound", "nbt.");
private static final Method SAVE_NMS_ITEM_STACK_METHOD = Reflect.getMethod(NMS_ITEM_STACK_CLASS, NBT_TAG_COMPOUND,
NBT_TAG_COMPOUND);
private static final Field MAP = Reflect.getField(NBT_TAG_COMPOUND, "map", "x");
private static final ConcurrentHashMap<Map.Entry<Version, ItemStack>, JsonObject> STACKS = new ConcurrentHashMap<>();
private Version protocolVersion;
private JsonObject itemTooltip;
private JsonArray classicTooltip;
public String parse(String json, String placeholder, ItemStack item, String replacement, int protocol)
throws Exception {
ChatItem.debug("Parsing: " + json);
JsonObject obj = JsonParser.parseString(json).getAsJsonObject();
JsonArray array = obj.has("extra") ? obj.getAsJsonArray("extra") : new JsonArray();
final AbstractMap.SimpleEntry<Version, ItemStack> p = new AbstractMap.SimpleEntry<>(
protocolVersion = Version.getVersion(protocol), item);
if ((itemTooltip = STACKS.get(p)) == null) {
JsonArray use = Translator.toJson(replacement); // We get the json representation of the old color
// formatting method
// There's no public clone method for JSONObjects so we need to parse them every
// time
JsonObject hover = JsonParser.parseString("{\"action\":\"show_item\", \"value\": \"\"}").getAsJsonObject();
String jsonRep = stringifyItem(this, item, protocolVersion);// stringifyItem(item); // Get the JSON
// representation of the item (well, not really
// JSON, but
// rather a string representation of NBT data)
hover.addProperty("value", jsonRep);
JsonObject wrapper = new JsonObject(); // Create a wrapper object for the whole array
wrapper.addProperty("text", ""); // The text field is compulsory, even if it's empty
wrapper.add("extra", use);
wrapper.add("hoverEvent", hover);
itemTooltip = wrapper; // Save the tooltip for later use when we encounter a placeholder
STACKS.put(p, itemTooltip); // Save it in the cache too so when parsing other packets with the same item
// (and client version) we no longer have to create it again
// We remove it later when no longer needed to save memory
Bukkit.getScheduler().runTaskLaterAsynchronously(ChatItem.getInstance(), () -> STACKS.remove(p), 100L);
}
obj.add("extra", parseArray(placeholder, array, itemTooltip));
if (!obj.has("text")) {
obj.addProperty("text", "");
}
return obj.toString();
}
public String parseEmpty(String json, String placeholder, String repl, List<String> tooltip, Player sender) {
JsonObject obj = JsonParser.parseString(json).getAsJsonObject();
JsonArray array = obj.has("extra") ? obj.getAsJsonArray("extra") : new JsonArray();
JsonArray use = Translator
.toJson(repl.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName()));
JsonObject hover = JsonParser.parseString("{\"action\":\"show_text\", \"value\": \"\"}").getAsJsonObject();
StringBuilder oneLineTooltip = new StringBuilder("");
int index = 0;
for (String m : tooltip) {
oneLineTooltip
.append(m.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName()));
++index;
if (index != tooltip.size()) {
oneLineTooltip.append('\n');
}
}
hover.add("value", new JsonPrimitive(oneLineTooltip.toString()));
if (!tooltip.isEmpty()) {
for (JsonElement ob : use)
ob.getAsJsonObject().add("hoverEvent", hover);
classicTooltip = use;
}
obj.add("extra", parseArray(placeholder, array, classicTooltip));
if (!obj.has("text")) {
obj.addProperty("text", "");
}
return obj.toString();
}
private JsonArray parseArray(String placeholder, JsonArray arr, JsonElement tooltip) {
JsonArray replacer = new JsonArray();
for (int i = 0; i < arr.size(); ++i) {
if (arr.get(i).isJsonNull()) {
continue;
} else if (arr.get(i).isJsonObject()) {
addParsedJsonObjectToArray(arr.get(i).getAsJsonObject(), placeholder, replacer, tooltip);
} else if (arr.get(i).isJsonArray()) {
JsonArray jar = arr.get(i).getAsJsonArray();
if (jar.size() != 0) {
jar = parseArray(placeholder, arr.get(i).getAsJsonArray(), tooltip);
replacer.set(i, jar);
}
} else {
addParsedStringToArray(arr.get(i).getAsString(), placeholder, replacer, arr.get(i), tooltip);
}
}
return replacer;
}
private void addParsedJsonObjectToArray(JsonObject o, String placeholder, JsonArray rep, JsonElement tooltip) {
JsonElement text = o.get("text");
if (text == null) {
JsonElement el = o.get("extra");
if (el != null) {
JsonArray jar = el.getAsJsonArray();
if (jar.size() != 0) {
o.add("extra", parseArray(placeholder, jar, tooltip));
} else {
o.remove("extra");
}
}
return;
} else {
if (text.getAsString().isEmpty()) {
JsonElement el = o.get("extra");
if (el != null) {
JsonArray jar = el.getAsJsonArray();
if (jar.size() != 0) {
o.add("extra", parseArray(placeholder, jar, tooltip));
} else {
o.remove("extra");
}
}
}
}
addParsedStringToArray(text.getAsString(), placeholder, rep, o, tooltip);
}
private void addParsedStringToArray(String msg, String placeholder, JsonArray rep, JsonElement o, JsonElement tooltip) {
boolean isLast = msg.endsWith(placeholder);
if (isLast) {
msg = msg.concat(".");
}
String[] splits = msg.split(Pattern.quote(placeholder));
if (splits.length != 1) {
for (int j = 0; j < splits.length; ++j) {
boolean endDot = (j == splits.length - 1) && isLast;
if (!splits[j].isEmpty() && !endDot) {
String st = o.toString();
JsonElement element = JsonParser.parseString(st);
if(element.isJsonObject()) {
JsonObject fix = element.getAsJsonObject();
fix.addProperty("text", splits[j]);
rep.add(fix);
} else
rep.add(new JsonPrimitive(splits[j]));
}
if (j != splits.length - 1) {
rep.add(tooltip);
}
}
} else {
rep.add(o);
}
}
@SuppressWarnings({ "deprecation" })
public static String stringifyItem(JSONManipulatorCurrent j, ItemStack is, Version protocolVersion)
throws Exception {
Object nmsStack = JSONManipulatorCurrent.AS_NMS_COPY.invoke(null, is);
Object nmsTag = JSONManipulatorCurrent.NBT_TAG_COMPOUND.newInstance();
JSONManipulatorCurrent.SAVE_NMS_ITEM_STACK_METHOD.invoke(nmsStack, nmsTag);
HashMap<String, String> tagMap = new HashMap<>();
Map<String, Object> nmsMap = (Map<String, Object>) JSONManipulatorCurrent.MAP.get(nmsTag);
String id = nmsMap.get("id").toString().replace("\"", "");
Object realTag = nmsMap.get("tag");
if (JSONManipulatorCurrent.NBT_TAG_COMPOUND.isInstance(realTag)) { // We need to make sure this is indeed an
// NBTTagCompound
Map<String, Object> realMap = (Map<String, Object>) JSONManipulatorCurrent.MAP.get(realTag);
Set<Map.Entry<String, Object>> entrySet = realMap.entrySet();
for (Map.Entry<String, Object> entry : entrySet) {
tagMap.put(entry.getKey(), entry.getValue().toString());
}
}
// TODO check for ID remapping
// ItemRewriter.remapIds(Version.getVersion().MAX_VER, protocolVersion.MAX_VER,
// is);
StringBuilder sb = new StringBuilder("{id:");
if (protocolVersion.equals(Version.V1_7))
sb.append(id).append(","); // Append the id
else
sb.append("\"").append(id).append("\"").append(","); // Append the id
sb.append("Count:").append(is.getAmount()).append("b"); // Append the amount
if (!tagMap.containsKey("Damage")) { // for new versions
sb.append(",Damage:").append(is.getDurability()).append("s"); // Append the durability data
}
if (tagMap.isEmpty()) {
sb.append("}");
return sb.toString();
}
Set<Map.Entry<String, String>> entrySet = tagMap.entrySet();
boolean first = true;
sb.append(",tag:{"); // Start of the tag
for (Map.Entry<String, String> entry : entrySet) {
if (!first)
sb.append(",");
first = false;
if (!entry.getKey().isEmpty())
sb.append(entry.getKey()).append(":");
sb.append(cleanStr(entry.getValue()));
}
sb.append("}}"); // End of tag and end of item
return sb.toString();
}
private static String cleanStr(String s) {
return s.startsWith("'") && s.endsWith("'") ? s.substring(1, s.length() - 1) : s;
}
}
@@ -3,14 +3,81 @@ 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();
@@ -104,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){
@@ -115,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
}
}
@@ -1,20 +1,17 @@
package me.dadus33.chatitem.chatmanager.v1.listeners;
import static me.dadus33.chatitem.chatmanager.ChatManager.SEPARATOR;
import static me.dadus33.chatitem.chatmanager.ChatManager.SEPARATOR_END;
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.Chat;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.utils.Storage;
@@ -32,23 +29,19 @@ public class ChatEventListener implements Listener {
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
@EventHandler(priority = EventPriority.LOWEST)
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);
if (ChatManager.containsSeparator(e.getMessage())) { // If the BELL character is found, we have to remove it
e.setMessage(ChatManager.removeSeparator(e.getMessage()));
}
boolean found = false;
final String oldMsg = e.getMessage();
for (String rep : getStorage().PLACEHOLDERS)
for (String rep : getStorage().placeholders) {
if (oldMsg.contains(rep)) {
found = true;
break;
}
}
if (!found) {
ChatItem.debug("(v1) not found placeholders in: " + e.getMessage());
return;
@@ -56,107 +49,22 @@ public class ChatEventListener implements Listener {
Player p = e.getPlayer();
ItemStack item = ChatManager.getUsableItem(p);
if(!ChatManager.canShowItem(p, item, e))
if (!ChatManager.canShowItem(p, item, e))
return;
String s = e.getMessage(), firstPlaceholder = getStorage().PLACEHOLDERS.get(0);
for (String placeholder : getStorage().PLACEHOLDERS) {
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) {
if (Utils.countMatches(s, firstPlaceholder) > getStorage().limit) {
e.setCancelled(true);
if (getStorage().LIMIT_MESSAGE.isEmpty()) {
return;
}
p.sendMessage(getStorage().LIMIT_MESSAGE);
if (!getStorage().messageLimit.isEmpty())
p.sendMessage(getStorage().messageLimit);
return;
}
ChatItem.debug("(v1) Set placeholder: " + e.getMessage());
try {
StringJoiner msg = new StringJoiner(" ");
for(String part : s.split(" ")) {
if(part.equalsIgnoreCase(firstPlaceholder)) {
msg.add(firstPlaceholder + 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();
}
if (getStorage().COOLDOWN > 0 && !p.hasPermission("chatitem.ignore-cooldown")) {
ChatManager.COOLDOWNS.put(p.getUniqueId(), System.currentTimeMillis() / 1000);
}
}
@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(firstPlaceholder + SEPARATOR + p.getName());
} else {
msg.add(part);
}
}
e.setMessage(msg.toString());
} catch (Exception exc) {
exc.printStackTrace();
}
if (getStorage().COOLDOWN > 0 && !p.hasPermission("chatitem.ignore-cooldown")) {
ChatManager.COOLDOWNS.put(p.getUniqueId(), System.currentTimeMillis() / 1000);
}
Chat c = Chat.create(p, oldMsg);
ChatItem.debug("(v1) Set placeholder to message " + c);
e.setMessage(s.replace(firstPlaceholder, SEPARATOR + Integer.toString(c.getId()) + SEPARATOR_END));
e.setFormat(e.getFormat().replace(oldMsg, e.getMessage())); // set own message for plugin that already put the message into the format
}
}
@@ -1,16 +1,14 @@
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.Field;
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.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.entity.Player;
@@ -21,23 +19,22 @@ import org.bukkit.inventory.meta.ItemMeta;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.ItemPlayer;
import me.dadus33.chatitem.chatmanager.Chat;
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.basecomp.IComponentManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.AdventureComponentManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.ComponentNMSManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.IChatBaseComponentManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.StringComponentManager;
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulator;
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.itemnamer.NamerManager;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.Storage;
import me.dadus33.chatitem.utils.Utils;
import me.dadus33.chatitem.utils.Version;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.chat.ComponentSerializer;
@@ -47,29 +44,38 @@ public class ChatPacketManager extends PacketHandler {
private Object lastSentPacket = null;
private Method serializerGetJson;
private PacketEditingChatManager manager;
private final List<IBaseComponentGetter> baseComponentGetter = new ArrayList<>();
private final List<IComponentManager> componentManager = 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)) {
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());
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 AdventureComponentGetter())) {
if(getter.hasConditions())
baseComponentGetter.add(getter);
for (IComponentManager getter : Arrays.asList(new StringComponentManager(), new IChatBaseComponentManager(), new ComponentNMSManager())) {
tryRegister(getter);
}
ChatItem.getInstance().getLogger().info("Loaded " + baseComponentGetter.size() + " getter for base components.");
try {
if (Class.forName("net.kyori.adventure.text.Component") != null)
tryRegister(new AdventureComponentManager());
} catch (Exception e) {
}
ChatItem.getInstance().getLogger().info("Loaded " + componentManager.size() + " getter for base components.");
ChatItem.debug("ComponentManager: " + String.join(", ", componentManager.stream().map(IComponentManager::getClass).map(Class::getSimpleName).collect(Collectors.toList())));
}
private void tryRegister(IComponentManager getter) {
if (getter.hasConditions())
componentManager.add(getter);
}
@Override
@@ -78,161 +84,125 @@ public class ChatPacketManager extends PacketHandler {
return;
if (lastSentPacket != null && lastSentPacket == e.getPacket())
return; // prevent infinite loop
ChatItem.debug("Checking: " + e.getPacketType().getFullName() + " to " + e.getPlayername());
PacketContent packet = e.getContent();
Version version = Version.getVersion();
String json = "{}";
IBaseComponentGetter choosedGetter = null;
IComponentManager choosedGetter = null;
if (version.isNewerOrEquals(Version.V1_19)) {
if(packet.getIntegers().readSafely(0) != 1)
if (packet.getIntegers().readSafely(0, 0) > 1) { // not parsed chat message type
ChatItem.debug("Invalid int: " + packet.getIntegers().read(0));
return;
String foundedJson = packet.getStrings().read(0); // for final things
json = foundedJson;
choosedGetter = new StringComponentGetter();
}
choosedGetter = new StringComponentManager();
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) {
// only if action bar messages are supported
if (((Enum<?>) packet.getSpecificModifier(PacketUtils.getNmsClass("ChatMessageType", "network.chat.")).read(0)).name().equals("GAME_INFO"))
return; // It's an actionbar message, ignoring
} else if (version.isNewerOrEquals(Version.V1_8) && packet.getBytes().readSafely(0) == (byte) 2)
return; // It's an actionbar message, ignoring
if (json == null || choosedGetter == null) {
for (IComponentManager getters : componentManager) {
String tmpJson = getters.getBaseComponentAsJSON(e);
if(tmpJson != null) {
ChatItem.debug("Found " + tmpJson + " with " + getters.getClass().getName());
json = tmpJson;
if (tmpJson != null) {
json = ChatManager.fixSeparator(tmpJson);
choosedGetter = getters;
break;
if (ChatManager.containsSeparator(json))
break; // be sure it's valid one
}
}
}
boolean found = false;
for (String rep : getStorage().PLACEHOLDERS) {
if (json.contains(rep)) {
found = true;
break;
if (json == null || choosedGetter == null) {
ChatItem.debug("Can't find valid json getter or json itself");
ChatItem.debug("String: " + packet.getStrings().getContent());
for (Field f : e.getPacket().getClass().getDeclaredFields()) {
f.setAccessible(true);
try {
ChatItem.debug(f.getName() + ": " + f.get(e.getPacket()));
} catch (Exception exc) {
exc.printStackTrace();
}
}
return; // can't find something
}
if (!found) {
ChatItem.debug("No placeholders founded in " + json);
return; // then it's just a normal message without placeholders, so we leave it alone
}
Object toReplace = null;
if (json.lastIndexOf(SEPARATOR) != -1)
toReplace = SEPARATOR;
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);
if (!ChatManager.containsSeparator(json)) { // if the message doesn't contain the BELL separator
ChatItem.debug("Not containing bell " + json + " (manager: " + choosedGetter.getClass().getName() + ")");
return;
}
ChatItem.debug("Add packet meta to json: " + json);
IBaseComponentGetter fchoosedGetter = choosedGetter;
String fjson = json, toReplaceStr = toReplace.toString();
e.setCancelled(true); // We cancel the packet as we're going to resend it anyways (ignoring listeners
// this time)
ChatItem.debug("Found with " + choosedGetter.getClass().getName());
Chat chat = choosedGetter.getChat(json);
if (chat == null) { // something went really bad, so we run away and hide (AKA the player left or is
// on another server)
ChatItem.debug("Chat null for " + json);
return;
}
Player itemPlayer = chat.getPlayer();
IComponentManager getter = choosedGetter;
e.setCancelled(true); // We cancel the packet as we're going to resends it anyways
Bukkit.getScheduler().runTaskAsynchronously(ChatItem.getInstance(), () -> {
Player p = e.getPlayer();
int topIndex = -1;
String name = null;
for (Player pl : Bukkit.getOnlinePlayers()) {
String pname = toReplaceStr + pl.getName();
if (!fjson.contains(pname)) {
continue;
}
int index = fjson.lastIndexOf(pname) + pname.length();
if (index > topIndex) {
topIndex = index;
name = pname.replace(toReplaceStr, "");
}
}
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 itemPlayer = 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 = fjson.replace(toReplaceStr + itemPlayer.getName(), "");// builder.toString();
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 (ItemPlayer.getPlayer(p).isBuggedClient()) { // if the guy that will receive it is bugged
String act = getStorage().buggedClientAction;
List<String> tooltip;
if (act.equalsIgnoreCase("tooltip"))
tooltip = getStorage().BUGGED_CLIENTS_TOOLTIP;
tooltip = getStorage().tooltipBuggedClient;
else if (act.equalsIgnoreCase("item"))
tooltip = getMaxLinesFromItem(p, copy);
tooltip = ChatManager.getMaxLinesFromItem(p, copy);
else if (act.equalsIgnoreCase("show_both")) {
tooltip = getMaxLinesFromItem(p, copy);
tooltip.addAll(getStorage().BUGGED_CLIENTS_TOOLTIP);
tooltip = ChatManager.getMaxLinesFromItem(p, copy);
tooltip.addAll(getStorage().tooltipBuggedClient);
} else
tooltip = new ArrayList<>();
message = manager.getManipulator().parseEmpty(localJson, getStorage().PLACEHOLDERS.get(0),
ChatManager.styleItem(p, copy, getStorage()), tooltip, itemPlayer);
message = JSONManipulator.getInstance().parseEmpty(getter.getBaseComponentAsJSON(e), ChatManager.styleItem(p, copy, getStorage()), tooltip, chat.getPlayer());
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));
packet.getSpecificModifier(BaseComponent[].class).write(0, ComponentSerializer.parse(message));
}
lastSentPacket = e.getPacket();
PacketUtils.sendPacket(p, lastSentPacket);
return;
}
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 itemInv : sb.getInventory()) {
stripData(itemInv);
}
bsm.setBlockState(sb);
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);
}
copy.setItemMeta(bsm);
bsm.setBlockState(sb);
}
copy.setItemMeta(bsm);
}
}
message = manager.getManipulator().parse(localJson, getStorage().PLACEHOLDERS.get(0), copy,
ChatManager.styleItem(p, copy, getStorage()), ItemPlayer.getPlayer(itemPlayer).getProtocolVersion());
lastSentPacket = getter.manageItem(p, chat, e, item, getStorage());
} else {
if (!getStorage().HAND_DISABLED) {
message = manager.getManipulator().parseEmpty(localJson, getStorage().PLACEHOLDERS.get(0),
getStorage().HAND_NAME, getStorage().HAND_TOOLTIP, itemPlayer);
if (!getStorage().handDisabled) {
lastSentPacket = getter.manageEmpty(p, chat, e, getStorage());
}
}
if (lastSentPacket == null)
ChatItem.debug("(v1) No packet to sent with manager " + getter.getClass().getName());
else
PacketUtils.sendPacket(p, lastSentPacket);
} 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);
});
}
@@ -266,23 +236,4 @@ public class ChatPacketManager extends PacketHandler {
public Storage getStorage() {
return manager.getStorage();
}
private 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, 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, getStorage()));
}
return lines;
}
}
@@ -67,7 +67,6 @@ public class PacketContent {
return new ContentModifier<byte[]>(obj, byte[].class);
}
@SuppressWarnings("unchecked")
public ContentModifier<Object> getChatComponents() {
return (ContentModifier<Object>) getSpecificModifier(PacketUtils.COMPONENT_CLASS);
}
@@ -77,7 +76,6 @@ public class PacketContent {
private Object obj;
private HashMap<Field, T> content = new HashMap<>();
@SuppressWarnings("unchecked")
public ContentModifier(Object obj, Class<?> clazz) {
this.obj = obj;
@@ -105,6 +103,10 @@ public class PacketContent {
}
}
public Object getObj() {
return obj;
}
/**
* Get the size of the Map of content
*
@@ -43,7 +43,7 @@ public interface PacketType {
public static enum Server implements PacketType {
CHAT("Chat", "ClientboundSystemChatPacket"),
CHAT("Chat", "ClientboundPlayerChatPacket", "ClientboundSystemChatPacket"),
UNSET("Unset");
private final String packetName, fullName;
@@ -10,7 +10,6 @@ import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.Plugin;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketManager;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
@@ -84,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);
@@ -4,6 +4,8 @@ import java.util.ArrayList;
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;
@@ -12,6 +14,7 @@ import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
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 {
@@ -71,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) {
@@ -26,7 +26,6 @@ public class INC2Channel extends ChannelAbstract {
private final ChannelInboundHandler boundHandler;
private ChannelPipeline pipeline;
@SuppressWarnings("unchecked")
public INC2Channel(CustomPacketManager customPacketManager) {
super(customPacketManager);
boundHandler = new ChannelInboundHandler(customPacketManager);
@@ -87,8 +86,9 @@ public class INC2Channel extends ChannelAbstract {
@Override
public Channel getChannel(Player p) throws Exception {
Object playerConnection = ReflectionUtils.getObject(getPlayerConnection(p), Version.getVersion().isNewerOrEquals(Version.V1_19) ? "b" : "a");
return ReflectionUtils.getFirstWith(playerConnection, playerConnection.getClass(), Channel.class);//(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 {
@@ -22,7 +22,6 @@ import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
@SuppressWarnings("unchecked")
public class INCChannel extends ChannelAbstract {
private final ChannelInboundHandler boundHandler;
@@ -36,7 +36,6 @@ public class NMUChannel extends ChannelAbstract {
Object dedicatedSrv = PacketUtils.getCraftServer();
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.getObject(co, "g", "e");
g.forEach((channelFuture) -> {
pipeline = channelFuture.channel().pipeline();
@@ -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,14 +24,20 @@ 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());
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;
@@ -3,9 +3,13 @@ package me.dadus33.chatitem.chatmanager.v2;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -15,6 +19,8 @@ import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.ItemPlayer;
import me.dadus33.chatitem.chatmanager.Chat;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.hook.DiscordSrvSupport;
import me.dadus33.chatitem.playernamer.PlayerNamerManager;
@@ -27,21 +33,14 @@ 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;
import net.md_5.bungee.api.chat.hover.content.Text;
@SuppressWarnings("deprecation")
public class ChatListener implements Listener {
private ChatListenerChatManager manage;
private Method saveMethod;
private boolean shouldUseAppendMethod = false;
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.");
@@ -62,14 +61,19 @@ public class ChatListener implements Listener {
}
Logger log = ChatItem.getInstance().getLogger();
String appendMethodMsg = shouldUseAppendMethod ? "Use ComponentBuilder's method."
: "Use own ComponentBuilder append method.";
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
log.info("Save method founded: " + saveMethod.getName() + ". " + appendMethodMsg);
}
private ChatListenerChatManager manage;
public ChatListener(ChatListenerChatManager manage) {
this.manage = manage;
}
public Storage getStorage() {
return manage.getStorage();
}
@@ -80,10 +84,9 @@ public class ChatListener implements Listener {
if (e.isCancelled()) {
if (ChatItem.getInstance().getChatManager().size() == 1) { // only chat
String msg = e.getMessage().toLowerCase();
for (String rep : c.PLACEHOLDERS) {
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");
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;
}
}
@@ -92,16 +95,17 @@ public class ChatListener implements Listener {
return;
}
Player p = e.getPlayer();
boolean hasv1 = false;
String placeholder = null;
for (String rep : c.PLACEHOLDERS) {
// v1 try to manage it, but the message have not been changed by another plugin
if (e.getMessage().contains(rep + ChatManager.SEPARATOR + p.getName())) {
hasv1 = true;
ChatItem.debug("Found v1 placeholders in v2");
placeholder = rep;
break;
if(ChatManager.containsSeparator(e.getMessage())) { // fix for v1
Chat chat = Chat.getFrom(e.getMessage());
if(chat == null)
ChatItem.debug("Chat for message " + e.getMessage() + " can't be found");
else {
e.setMessage(ChatManager.replaceSeparator(chat, e.getMessage(), c.placeholders.get(0)));
chat.remove();
}
}
String placeholder = null;
for (String rep : c.placeholders) {
if (e.getMessage().contains(rep)) {
placeholder = rep;
break;
@@ -113,74 +117,73 @@ public class ChatListener implements Listener {
return;
}
ItemStack item = ChatManager.getUsableItem(p);
if(!ChatManager.canShowItem(p, item, e))
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(rep + ChatManager.SEPARATOR + p.getName(), String.valueOf(ChatManager.SEPARATOR));
else
defMsg = defMsg.replace(rep, String.valueOf(ChatManager.SEPARATOR));
for (String rep : c.placeholders) {
defMsg = defMsg.replace(rep, Character.toString(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);
if (Utils.countMatches(defMsg, Character.toString(ChatManager.SEPARATOR)) > getStorage().limit) {
if (!getStorage().messageLimit.isEmpty())
p.sendMessage(getStorage().messageLimit);
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()));
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());
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);
e.getRecipients().forEach((pl) -> showItem(pl, p, item, msg));
if (c.COOLDOWN > 0 && !p.hasPermission("chatitem.ignore-cooldown")) {
ChatManager.COOLDOWNS.put(p.getUniqueId(), System.currentTimeMillis() / 1000);
}
DiscordSrvSupport.sendChatMessage(p, defMsg.replace(ChatManager.SEPARATOR + "", itemName).replace("{name}", p.getName()).replace("{display-name}", p.getDisplayName()));
Set<Player> recipients = e.getRecipients().isEmpty() ? new HashSet<>(Bukkit.getOnlinePlayers()) : e.getRecipients();
ChatItem.debug("Msg: " + msg.replace(ChatColor.COLOR_CHAR, '&') + ", format: " + format + " to " + recipients.size() + " players");
recipients.forEach((pl) -> showItem(pl, p, item, msg));
if (c.cooldown > 0 && !p.hasPermission("chatitem.ignore-cooldown"))
ChatManager.applyCooldown(p);
}
private void showItem(Player to, Player origin, ItemStack item, String msg) {
public static void showItem(Player to, Player origin, ItemStack item, String msg) {
ComponentBuilder builder = new ComponentBuilder("");
ChatColor color = ChatColor.RESET;
ChatColor color = ChatColor.WHITE;
String colorCode = "", text = "";
boolean waiting = false, isHex = false;
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());
ChatItem.debug("Append '" + text + "' (len: " + text.length() + ")");
appendToComponentBuilder(builder, createComponent(text, color));
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()) {
if (args == 'r' && colorCode.isEmpty()) {
color = ChatColor.RESET;
continue;
}
if(args == 'x' && colorCode.isEmpty())
isHex = true;
colorCode += args; // a color by itself
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(isHex && colorCode.length() >= 7)
color = ColorManager.getColor(colorCode);
else if(colorCode.length() == 1) // if only one color code
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);
@@ -188,7 +191,7 @@ public class ChatListener implements Listener {
}
if (args == ChatManager.SEPARATOR) {
// here put the item
appendToComponentBuilder(builder, new ComponentBuilder(text).color(color).create());
appendToComponentBuilder(builder, fixColorComponent(text, color));
addItem(builder, to, origin, item);
text = "";
} else {
@@ -197,77 +200,50 @@ public class ChatListener implements Listener {
}
}
}
if(!text.isEmpty())
appendToComponentBuilder(builder, new ComponentBuilder(text).color(color).create());
if (!text.isEmpty())
appendToComponentBuilder(builder, createComponent(text, color));
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
* @return the Json string representation of the item
*/
public String convertItemStackToJson(ItemStack itemStack) {
try {
Class<?> nbtTag = PacketUtils.getNmsClass("NBTTagCompound", "nbt.");
Class<?> craftItemClass = PacketUtils.getObcClass("inventory.CraftItemStack");
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();
} else {
Object nmsItemStackObj = craftItemClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, itemStack);
return saveMethod.invoke(nmsItemStackObj, nmsNbtTagCompoundObj).toString();
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public void addItem(ComponentBuilder builder, Player to, Player origin, ItemStack item) {
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(ChatManager.styleItem(to, item, getStorage()));
String itemJson = convertItemStackToJson(item);
itemComponent.event(new HoverEvent(Action.SHOW_ITEM, new ComponentBuilder(itemJson).create()));
ComponentBuilder itemComponent = new ComponentBuilder("");
appendToComponentBuilder(itemComponent, fixColorComponent(ChatManager.getNameOfItem(to, item, c), ChatColor.WHITE, item));
ChatItem.debug("Item for " + to.getName() + " (ver: " + ItemPlayer.getPlayer(to).getVersion().name() + ") : " + PacketUtils.getNbtTag(item));
// itemComponent.event(new HoverEvent(Action.SHOW_ITEM, itemBaseComponent));
appendToComponentBuilder(builder, itemComponent.create());
} else {
String handName = getStorage().HAND_NAME;
String handName = c.handName;
ComponentBuilder handComp = new ComponentBuilder("");
ComponentBuilder handTooltip = new ComponentBuilder("");
int stay = getStorage().HAND_TOOLTIP.size();
for (String line : getStorage().HAND_TOOLTIP) {
int stay = c.tooltipHand.size();
for (String line : c.tooltipHand) {
stay--;
handTooltip.append(
line.replace("{name}", origin.getName()).replace("{display-name}", origin.getDisplayName()));
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, new Text(handTooltip.create())));
if (handName.contains("{name}")) {
String[] splitted = handName.split("\\{name\\}");
handComp.event(Utils.createTextHover(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("{display-name}", origin.getDisplayName()));
handComp.append(handName.replace("{name}", origin.getName()));
appendToComponentBuilder(builder, handComp.create());
}
}
@SuppressWarnings("unchecked")
public void appendToComponentBuilder(ComponentBuilder builder, BaseComponent[] comps) {
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.");
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 {
@@ -282,4 +258,73 @@ public class ChatListener implements Listener {
}
}
}
public static BaseComponent[] fixColorComponent(String message, ChatColor color) {
return fixColorComponent(message, color, null);
}
public static BaseComponent[] fixColorComponent(String message, ChatColor color, @Nullable ItemStack item) {
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));
appendToComponentBuilder(builder, createComponent(ColorManager.isHexColor(color) ? ColorManager.removeColorAtBegin(text) : text, color, item));
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()) {
appendToComponentBuilder(builder, createComponent(text, color, item));
}
return builder.create();
}
private static BaseComponent[] createComponent(String text, ChatColor color) {
return createComponent(text, color, null);
}
private static BaseComponent[] createComponent(String text, ChatColor color, ItemStack item) {
ComponentBuilder littleBuilder = new ComponentBuilder(text);
if(color != null && color != ChatColor.RESET) // don't add reset thing
littleBuilder.color(color);
if (item != null) // add to all possible sub parts
littleBuilder.event(Utils.createItemHover(item));
return littleBuilder.create();
}
}
@@ -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,10 +24,10 @@ 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)) {
@@ -37,6 +41,25 @@ public class ChatItemCommand implements CommandExecutor, TabExecutor {
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.commandFormat.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.commandFormat.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");
@@ -47,7 +70,7 @@ public class ChatItemCommand implements CommandExecutor, TabExecutor {
String hover = Storage.color(linkConfig.getString("hover"));
if (hover != null)
linkComp.setHoverEvent(
new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(hover).create()));
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));
@@ -64,7 +87,7 @@ public class ChatItemCommand implements CommandExecutor, TabExecutor {
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", "link"))
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;
@@ -1,81 +0,0 @@
package me.dadus33.chatitem.filters;
import static org.apache.logging.log4j.core.Filter.Result.NEUTRAL;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.Logger;
import org.apache.logging.log4j.message.Message;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.utils.Storage;
public class Log4jFilter implements Filter {
private Storage c;
public Log4jFilter(Storage st) {
c = st;
((Logger) LogManager.getRootLogger()).addFilter(this);
}
@Override
public Result getOnMismatch() {
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, 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(LogEvent logEvent) {
return checkMessage(logEvent.getMessage().getFormattedMessage());
}
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(ChatManager.SEPARATOR + p.getName())) {
return Result.DENY;
}
}
}
}
return Result.NEUTRAL;
}
public void setStorage(Storage nst) {
this.c = nst;
}
}
@@ -6,6 +6,7 @@ import github.scarsz.discordsrv.DiscordSRV;
public class DiscordSrvSupport {
@SuppressWarnings("deprecation")
public static void sendChatMessage(Player p, String message) {
DiscordSRV pl = DiscordSRV.getPlugin();
if (DiscordSRV.config().getBooleanElse("UseModernPaperChatEvent", false) && pl.isModernChatEventAvailable()) {
@@ -1,21 +0,0 @@
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;
}
}
@@ -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) {
@@ -17,7 +17,7 @@ public class ChatItemTranslationNamer implements INamer {
@Override
public String getName(Player p, ItemStack item, Storage storage) {
HashMap<Short, String> translationSection = storage.TRANSLATIONS.get(item.getType().name());
HashMap<Short, String> translationSection = storage.translations.get(item.getType().name());
if (translationSection != null) {
@SuppressWarnings("deprecation")
String translated = translationSection.get(item.getDurability());
@@ -18,7 +18,7 @@ public class ItemDisplayNamer implements INamer {
public String getName(Player p, ItemStack item, Storage storage) {
if(item.hasItemMeta() && item.getItemMeta().hasDisplayName()) {
String name = item.getItemMeta().getDisplayName();
return storage.COLOR_IF_ALREADY_COLORED ? ChatColor.stripColor(name) : name;
return storage.colorIfColored ? ChatColor.stripColor(name) : name;
}
return null;
}
@@ -42,30 +42,33 @@ public class InventoryListener implements Listener {
ChatItem.reload(p);
}
} else if(type.equals(ItemUtils.INK_SAC)) {
setInConfig("general.color-if-already-colored", c.COLOR_IF_ALREADY_COLORED = !c.COLOR_IF_ALREADY_COLORED);
setInConfig("general.color-if-already-colored", c.colorIfColored = !c.colorIfColored);
open(p);
} else if(type.equals(Material.REDSTONE)) {
setInConfig("general.deny-if-no-item", c.DENY_IF_NO_ITEM = !c.DENY_IF_NO_ITEM);
setInConfig("general.deny-if-no-item", c.denyIfNoItem = !c.denyIfNoItem);
open(p);
} else if(type.equals(Material.STICK)) {
setInConfig("general.hand.disabled", c.HAND_DISABLED = !c.HAND_DISABLED);
setInConfig("general.hand.disabled", c.handDisabled = !c.handDisabled);
open(p);
} else if(type.equals(Material.BOOK)) {
setInConfig("general.check-update", c.checkUpdate = !c.checkUpdate);
open(p);
} else if(type.equals(ItemUtils.FIREWORK_CHARGE)) {
setInConfig("debug", c.DEBUG = !c.DEBUG);
setInConfig("debug", c.debug = !c.debug);
open(p);
} else if(type.equals(Material.IRON_DOOR)) {
if(e.getClick().equals(ClickType.RIGHT))
c.LIMIT--;
c.limit--;
else if(e.getClick().equals(ClickType.LEFT))
c.LIMIT++;
setInConfig("general.limit-per-message", c.LIMIT);
c.limit++;
setInConfig("general.limit-per-message", c.limit);
open(p);
} else if(type.equals(Material.APPLE)) {
if(e.getClick().equals(ClickType.RIGHT))
c.COOLDOWN--;
c.cooldown--;
else if(e.getClick().equals(ClickType.LEFT))
c.COOLDOWN++;
setInConfig("general.cooldown", c.COOLDOWN);
c.cooldown++;
setInConfig("general.cooldown", c.cooldown);
open(p);
}
}
@@ -88,15 +91,16 @@ public class InventoryListener implements Listener {
holder.keyBySlot.put(slot, manager);
inv.setItem(slot++, getManagerItem(manager));
}
inv.setItem(slot + 1, getManagerItem("actual", "%manager%", Messages.getMessage("admin-inv.manager." + c.MANAGER + ".name")));
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(8, getBoolChangeItem(ItemUtils.FIREWORK_CHARGE, "debug", c.debug));
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(18, getBoolChangeItem(ItemUtils.INK_SAC, "color-if-already-colored", c.colorIfColored));
inv.setItem(19, getBoolChangeItem(Material.REDSTONE, "deny-no-item", c.denyIfNoItem));
inv.setItem(20, getBoolChangeItem(Material.STICK, "hand-disabled", c.handDisabled));
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.checkUpdate));
inv.setItem(26, createItem(ItemUtils.MATERIAL_CLOSE, Messages.getMessage("admin-inv.close")));
p.openInventory(inv);
@@ -12,10 +12,10 @@ 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();
@@ -23,8 +23,8 @@ public class JoinListener implements Listener {
return;
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()));
TextComponent text = new TextComponent(pl.getStorage().updateMessage);
text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(new ComponentBuilder(pl.getStorage().updateHover).create())));
text.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.spigotmc.org/resources/19064/"));
p.spigot().sendMessage(text);
}
@@ -12,12 +12,12 @@ public class PlayerVersionManager {
static {
ChatItem pl = ChatItem.getInstance();
if (Bukkit.getPluginManager().getPlugin("ViaVersion") != null) {
playerVersionAdapter = new ViaVersionHook();
pl.getLogger().info("Loading ViaVersion support ...");
} else if (Bukkit.getPluginManager().getPlugin("ProtocolSupport") != null) {
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();
}
@@ -2,8 +2,9 @@ package me.dadus33.chatitem.playerversion.hooks;
import org.bukkit.entity.Player;
import com.viaversion.viaversion.api.Via;
import me.dadus33.chatitem.playerversion.IPlayerVersion;
import us.myles.ViaVersion.api.Via;
public class ViaVersionHook implements IPlayerVersion {
@@ -1,38 +1,75 @@
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())
if (input == null || input.isEmpty())
return "";
StringBuilder str = new StringBuilder();
if(Version.getVersion().isNewerOrEquals(Version.V1_16) && input.startsWith("x")) { // x mean it's an hex
ChatItem.debug("Removing char x at begin: " + input.substring(1));
if (isHexColor(input)) { // x mean it's an hex
input = input.substring(1);
if(input.length() >= 6) { // at least hex
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
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())
for (char c : input.toCharArray())
str.append(ChatColor.getByChar(c));
return str.toString();
}
public static ChatColor getColor(String input) {
if(input == null || input.isEmpty())
if (input == null || input.isEmpty())
return ChatColor.RESET;
if(Version.getVersion().isNewerOrEquals(Version.V1_16) && input.startsWith("x")) { // 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"
if (isHexColor(input)) { // x mean it's an hex
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());
@@ -40,4 +77,45 @@ public class ColorManager {
// 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
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,7 +18,6 @@ public class Messages {
return colorAndPlaceholders(ChatItem.getInstance().getConfig().getString("messages." + key, key), placeholders);
}
@SuppressWarnings("unchecked")
public static List<String> getMessageList(String key, Object... placeholders) {
Object obj = ChatItem.getInstance().getConfig().get("messages." + key);
if(obj == null)
@@ -6,6 +6,9 @@ import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulator;
public class PacketUtils {
@@ -14,88 +17,91 @@ public class PacketUtils {
public static final String NMS_PREFIX;
public static final String OBC_PREFIX;
public static final boolean IS_THERMOS;
public static final Class<?> CRAFT_PLAYER_CLASS, CRAFT_SERVER_CLASS, CHAT_SERIALIZER, COMPONENT_CLASS;
public static final Class<?> CHAT_SERIALIZER, COMPONENT_CLASS;
/**
* This Map is to reduce Reflection action which take more resources than just RAM action
* This Map is to reduce Reflection action which take more resources than just
* RAM action
*/
private static final Map<String, Class<?>> ALL_CLASS = Collections.synchronizedMap(new HashMap<String, Class<?>>());
static {
IS_THERMOS = isClassExist("thermos.Thermos");
NMS_PREFIX = Version.getVersion().isNewerOrEquals(Version.V1_17) || IS_THERMOS ? "net.minecraft." : "net.minecraft.server." + VERSION + ".";
NMS_PREFIX = Version.getVersion().isNewerOrEquals(Version.V1_17) || IS_THERMOS ? "net.minecraft."
: "net.minecraft.server." + VERSION + ".";
OBC_PREFIX = "org.bukkit.craftbukkit." + VERSION + ".";
CRAFT_PLAYER_CLASS = getObcClass("entity.CraftPlayer");
CHAT_SERIALIZER = getNmsClass("IChatBaseComponent$ChatSerializer", "network.chat.", "ChatSerializer");
COMPONENT_CLASS = getNmsClass("IChatBaseComponent", "network.chat.");
CRAFT_SERVER_CLASS = getObcClass("CraftServer");
}
/**
* Get the Class in NMS, with a processing reducer
*
* @param name of the NMS class (in net.minecraft.server package ONLY, because it's NMS)
* @param name of the NMS class (in net.minecraft.server package ONLY, because
* it's NMS)
* @return clazz the searched class
*/
public static Class<?> getNmsClass(String name, String packagePrefix, String... alias){
public static Class<?> getNmsClass(String name, String packagePrefix, String... alias) {
return ALL_CLASS.computeIfAbsent(name, (a) -> {
String fullPrefix = NMS_PREFIX + (Version.getVersion().isNewerOrEquals(Version.V1_17) || IS_THERMOS ? packagePrefix : "");
String fullPrefix = NMS_PREFIX
+ (Version.getVersion().isNewerOrEquals(Version.V1_17) || IS_THERMOS ? packagePrefix : "");
try {
Class<?> clazz = Class.forName(fullPrefix + name);
if(clazz != null)
if (clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
if(alias.length == 0)
if (alias.length == 0)
e.printStackTrace(); // no alias, print error
// else ignore and go check for alias
}
for(String className : alias) {
for (String className : alias) {
try {
Class<?> clazz = Class.forName(fullPrefix + className);
if(clazz != null)
if (clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
if(className == alias[alias.length - 1]) // if it's last alias, print error
if (className == alias[alias.length - 1]) // if it's last alias, print error
e.printStackTrace();
}
}
return null;
});
}
/**
* Get the Class in NMS, with a processing reducer
*
* @param name of the NMS class (in net.minecraft.server package ONLY, because it's NMS)
* @param name of the NMS class (in net.minecraft.server package ONLY, because
* it's NMS)
* @return clazz the searched class
*/
public static Class<?> getObcClass(String name, String... alias){
public static Class<?> getObcClass(String name, String... alias) {
return ALL_CLASS.computeIfAbsent(name, (a) -> {
try {
Class<?> clazz = Class.forName(OBC_PREFIX + name);
if(clazz != null)
if (clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
if(alias.length == 0)
if (alias.length == 0)
e.printStackTrace(); // no alias, print error
// else ignore and go check for alias
}
for(String className : alias) {
for (String className : alias) {
try {
Class<?> clazz = Class.forName(OBC_PREFIX + className);
if(clazz != null)
if (clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
if(className == alias[alias.length - 1]) // if it's last alias, print error
if (className == alias[alias.length - 1]) // if it's last alias, print error
e.printStackTrace();
}
}
return null;
});
}
/**
* Get NMS entity player of specified one
*
@@ -104,14 +110,13 @@ public class PacketUtils {
*/
public static Object getEntityPlayer(Player p) {
try {
Object craftPlayer = CRAFT_PLAYER_CLASS.cast(p);
return craftPlayer.getClass().getMethod("getHandle").invoke(craftPlayer);
return getObcClass("entity.CraftPlayer").getMethod("getHandle").invoke(p);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static boolean isClassExist(String name) {
try {
Class.forName(name);
@@ -130,7 +135,7 @@ public class PacketUtils {
public static Object getPlayerConnection(Player p) {
try {
Object entityPlayer = getEntityPlayer(p);
if(Version.getVersion().isNewerOrEquals(Version.V1_17))
if (Version.getVersion().isNewerOrEquals(Version.V1_17))
return entityPlayer.getClass().getField("b").get(entityPlayer);
else
return entityPlayer.getClass().getField("playerConnection").get(entityPlayer);
@@ -139,7 +144,7 @@ public class PacketUtils {
return null;
}
}
/**
* Get NMS entity player of specified one
*
@@ -148,8 +153,7 @@ public class PacketUtils {
*/
public static Object getCraftServer() {
try {
Object craftServer = CRAFT_SERVER_CLASS.cast(Bukkit.getServer());
return craftServer.getClass().getMethod("getHandle").invoke(craftServer);
return getObcClass("CraftServer").getMethod("getHandle").invoke(Bukkit.getServer());
} catch (Exception e) {
e.printStackTrace();
return null;
@@ -159,15 +163,39 @@ public class PacketUtils {
/**
* Send the packet to the specified player
*
* @param p which will receive the packet
* @param p which will receive the packet
* @param packet the packet to sent
*/
public static void sendPacket(Player p, Object packet) {
try {
Object playerConnection = getPlayerConnection(p);
playerConnection.getClass().getMethod(Version.getVersion().isNewerOrEquals(Version.V1_18) ? "a" : "sendPacket", getNmsClass("Packet", "network.protocol.")).invoke(playerConnection, packet);
playerConnection.getClass()
.getMethod(Version.getVersion().isNewerOrEquals(Version.V1_18) ? "a" : "sendPacket",
getNmsClass("Packet", "network.protocol."))
.invoke(playerConnection, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Converts an {@link org.bukkit.inventory.ItemStack} to a Json string for
* sending with {@link net.md_5.bungee.api.chat.BaseComponent}'s.
*
* @param item the item to convert
* @return the Json string representation of the item
*/
public static String getNbtTag(ItemStack item) {
try {
Object nmsStack = JSONManipulator.AS_NMS_COPY.invoke(null, item);
Version v = Version.getVersion();
Object tag = getNmsClass("ItemStack", "world.item.")
.getMethod(v.equals(Version.V1_18) ? "t" : (v.isNewerOrEquals(Version.V1_19) ? "u" : "getTag"))
.invoke(nmsStack);
return tag == null ? "{}" : tag.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "{}";
}
}
@@ -1,56 +0,0 @@
package me.dadus33.chatitem.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import me.dadus33.chatitem.ChatItem;
public class Reflect {
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... params) {
try {
return clazz.getMethod(methodName, params);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static Method getMethod(Class<?> clazz, Class<?> returned, Class<?>... params) {
try {
for(Method m : clazz.getDeclaredMethods()) {
if(returned.equals(m.getReturnType()) && areParamsEquals(m.getParameterTypes(), params))
return m;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static boolean areParamsEquals(Class<?>[] p1, Class<?>[] p2) {
if(p1.length != p2.length)
return false;
for(int i = 0; i < p1.length; i++) {
if(!p1[i].equals(p2[i]))
return false;
}
return true;
}
public static Field getField(Class<?> clazz, String... fieldNames){
for(String field : fieldNames) {
try{
Field f = clazz.getDeclaredField(field);
f.setAccessible(true);
return f;
} catch (NoSuchFieldException e) {
// go to next
}
}
ChatItem.getInstance().getLogger().severe("Failed to find field: " + Arrays.asList(fieldNames) + " in class: " + clazz.getCanonicalName());
return null;
}
}
@@ -1,11 +1,58 @@
package me.dadus33.chatitem.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import me.dadus33.chatitem.ChatItem;
public class ReflectionUtils {
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... params) {
try {
return clazz.getMethod(methodName, params);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static Method getMethod(Class<?> clazz, Class<?> returned, Class<?>... params) {
try {
for(Method m : clazz.getDeclaredMethods()) {
if(returned.equals(m.getReturnType()) && areParamsEquals(m.getParameterTypes(), params))
return m;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static boolean areParamsEquals(Class<?>[] p1, Class<?>[] p2) {
if(p1.length != p2.length)
return false;
for(int i = 0; i < p1.length; i++) {
if(!p1[i].equals(p2[i]))
return false;
}
return true;
}
public static Field getField(Class<?> clazz, String... fieldNames){
for(String field : fieldNames) {
try{
Field f = clazz.getDeclaredField(field);
f.setAccessible(true);
return f;
} catch (NoSuchFieldException e) {
// go to next
}
}
ChatItem.getInstance().getLogger().severe("Failed to find field: " + Arrays.asList(fieldNames) + " in class: " + clazz.getCanonicalName());
return null;
}
public static Object getPrivateField(Object object, String field)
throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
@@ -84,7 +131,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
@@ -92,7 +139,6 @@ public class ReflectionUtils {
* @return the field (or null if not found)
* @throws Exception if something gone wrong
*/
@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) && !Modifier.isStatic(f.getModifiers())) {
@@ -102,4 +148,23 @@ public class ReflectionUtils {
}
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;
}
}
@@ -1,38 +1,35 @@
package me.dadus33.chatitem.utils;
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 java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.ChatColor;
import org.bukkit.configuration.file.FileConfiguration;
import com.google.common.collect.ImmutableList;
import me.dadus33.chatitem.ChatItem;
public class Storage {
public final HashMap<String, HashMap<Short, String>> TRANSLATIONS = new HashMap<>();
public final String HAND_NAME, NAME_FORMAT, AMOUNT_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;
public final HashMap<String, HashMap<Short, String>> translations = new HashMap<>();
public final String handName, nameFormat, amountFormat, commandFormat, manager, permissionName, buggedClientAction;
public final String messageNoPermission, messageDeny, messageReload, messageCooldown, messageLimit;
public final String SECONDS, minutes, hours;
public final String updateMessage, updateHover;
public final List<String> placeholders, tooltipHand, tooltipBuggedClient;
public boolean colorIfColored, addAmountForced, letMessageThrough, denyIfNoItem, debug,
handDisabled, showNoPermissionMessage, checkUpdate, permissionEnabled;
public int configVersion, limit, cooldown;
private FileConfiguration conf;
public Storage(FileConfiguration cnf) {
this.conf = cnf;
CONFIG_VERSION = conf.getInt("config-version", 13);
configVersion = conf.getInt("config-version", 13);
checkConfigVersion();
this.MANAGER = conf.getString("manager", "auto");
this.manager = conf.getString("manager", "auto");
Set<String> keys = conf.getConfigurationSection("translations").getKeys(false);
for (String key : keys) {
HashMap<Short, String> entry = new HashMap<>();
@@ -42,54 +39,43 @@ public class Storage {
color(conf.getString("translations.".concat(key).concat(".").concat(subKey))));
}
TRANSLATIONS.put(key, entry);
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}"));
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);
SHOW_NO_PERM_COMMAND = conf.getBoolean("general.show-no-permission-message.command", false);
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",
debug = conf.getBoolean("debug", false);
placeholders = ImmutableList.copyOf(conf.getStringList("general.placeholders"));
nameFormat = color(conf.getString("general.name-format", "&b&l&o{name} {amount}&r"));
amountFormat = color(conf.getString("general.amount-format", "x{times}"));
commandFormat = color(conf.getString("general.command-format", "&6%name%'s item is %item%"));
colorIfColored = conf.getBoolean("general.color-if-already-colored", true);
letMessageThrough = conf.getBoolean("general.let-message-through", true);
addAmountForced = conf.getBoolean("general.force-add-amount", true);
denyIfNoItem = conf.getBoolean("general.deny-if-no-item", false);
limit = conf.getInt("general.limit", 8);
cooldown = conf.getInt("general.cooldown", 60);
showNoPermissionMessage = conf.getBoolean("general.show-no-permission-message.normal", true);
permissionEnabled = conf.getBoolean("general.permission.enabled", false);
permissionName = conf.getString("general.permission.name", "chatitem.use");
handDisabled = conf.getBoolean("general.hand.disabled", false);
handName = color(conf.getString("general.hand.name", "&b&l&o{display-name}&b&l&o's hand"));
tooltipHand = conf.getStringList("general.hand.tooltip").stream().map(Storage::color).collect(Collectors.toList());
buggedClientAction = conf.getString("general.bugged_client.action", "show_both");
tooltipBuggedClient = conf.getStringList("general.bugged_client.tooltip").stream().map(Storage::color).collect(Collectors.toList());
checkUpdate = conf.getBoolean("general.check-update", true);
messageDeny = color(conf.getString("messages.deny-message", "&c&lYou have no item in hand!"));
messageReload = color(conf.getString("messages.reload-success", "&b&lSuccessful reload!"));
messageNoPermission = 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",
messageCooldown = 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",
updateMessage = 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!"));
updateHover = color(conf.getString("messages.join-update.hover", "&6Click to go to spigot page !"));
messageLimit = 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);
minutes = color(conf.getString("messages.minutes", " minutes"));
hours = color(conf.getString("messages.hours", " hours"));
colorStringList(tooltipHand);
}
@@ -105,7 +91,7 @@ public class Storage {
private void checkConfigVersion() {
int latestVersion = ChatItem.CFG_VER;
if (latestVersion != CONFIG_VERSION) {
if (latestVersion != configVersion) {
ChatItem pl = ChatItem.getInstance();
pl.getLogger().warning(ChatColor.RED
+ "ChatItem detected an older or invalid configuration file. Replacing it with the default config...");
@@ -1,19 +1,33 @@
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.*;
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.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.TreeMap;
import org.bukkit.Bukkit;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulator;
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.ItemTag;
import net.md_5.bungee.api.chat.hover.content.Item;
import net.md_5.bungee.api.chat.hover.content.Text;
public class Utils {
private final static TreeMap<Integer, String> ROMAN_KEYS = new TreeMap<>();
@@ -54,7 +68,7 @@ public class Utils {
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_ENVIRONMENTAL", "Protection");
ENCHANTS_NAMES.put("PROTECTION_EXPLOSIONS", "Blast Protection");
ENCHANTS_NAMES.put("PROTECTION_FALL", "Feather Falling");
ENCHANTS_NAMES.put("PROTECTION_FIRE", "Fire Protection");
@@ -82,7 +96,6 @@ public class Utils {
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.");
}
@@ -138,4 +151,62 @@ public class Utils {
}
return b;
}
@SuppressWarnings("deprecation")
public static HoverEvent createItemHover(ItemStack item) {
if(Version.getVersion().isNewerOrEquals(Version.V1_13)) {
return new HoverEvent(HoverEvent.Action.SHOW_ITEM, new Item(item.getType().getKey().getKey(), item.getAmount(), ItemTag.ofNbt(PacketUtils.getNbtTag(item))));
} else {
return new HoverEvent(HoverEvent.Action.SHOW_ITEM, new ComponentBuilder(JSONManipulator.stringifyItem(item)).create());
}
}
public static HoverEvent createTextHover(String text) {
return createTextHover(new ComponentBuilder(text).create());
}
@SuppressWarnings("deprecation")
public static HoverEvent createTextHover(BaseComponent[] comps) {
if(Version.getVersion().isNewerOrEquals(Version.V1_13)) {
return new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(comps));
} else {
return new HoverEvent(HoverEvent.Action.SHOW_TEXT, comps);
}
}
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;
}
}
}
@@ -21,7 +21,7 @@ public enum Version {
V1_16(100, 700, 754),
V1_17(100, 755, 756),
V1_18(100, 757, 758),
V1_19(100, 759, 1000),
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
@@ -84,6 +84,8 @@ public enum Version {
}
public static String stringifyAdress(InetSocketAddress address) {
if(address == null)
return "0.0.0.0:0";
String port = String.valueOf(address.getPort());
String ip = address.getAddress().getHostAddress();
return ip + ":" + port;
+9 -9
View File
@@ -24,6 +24,8 @@ general:
# The placeholders to display an item in chat.
placeholders:
- "[i]"
- "{i}"
- "[item]"
- "{item}"
# The format of the item placeholders.
name-format: "&b&l&o{name} {amount}&r"
@@ -65,15 +67,10 @@ general:
action: "show_both"
tooltip:
- "&7Failed to parse item for your client"
# 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
# bellow containing an alias (or name) for that command.
# It is enough to add only ONE alias for each command, and the others will automatically be supported. However,
# this is only available for plugin commands. If you're planning to add bukkit or mojang commands here, you'll have
# to manually specify ALL aliases for those.
commands:
- "msg"
# Format used with using /chatitem show
command-format: "&6%name%'s item is %item%"
# Here you can set when the players should see the no-permission message (defined in the 'Messages' section bellow).
# 'normal' dictates whether the user should see the message when using the placeholder in normal chat, and 'command'
# sets whether the user should see it when using the placeholder in a command.
@@ -113,6 +110,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:
@@ -158,6 +157,7 @@ messages:
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: