Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
824cf62e4c | ||
|
|
8f5c90557f | ||
|
|
7e6cb9910c | ||
|
|
0e6f35804d | ||
|
|
fbcfbceaa4 | ||
|
|
4a6d46d1da | ||
|
|
8779653211 | ||
|
|
c4c511315a | ||
|
|
bcc0bbdd2a | ||
|
|
ffe1bb8b44 | ||
|
|
64cdccc2d1 | ||
|
|
920a055f02 | ||
|
|
4d524244d6 | ||
|
|
429e4a597c | ||
|
|
5a310e3f60 | ||
|
|
58c5f4607f | ||
|
|
b436c73f47 | ||
|
|
806ceea250 | ||
|
|
9a4ef0fe5b | ||
|
|
241f80ca3c | ||
|
|
710bbf3163 | ||
|
|
4ee561c18f | ||
|
|
17754f2dfe | ||
|
|
6a683508d4 | ||
|
|
bcc8ac08f2 | ||
|
|
429a664e81 | ||
|
|
49dadb897a | ||
|
|
3cf54d39a1 | ||
|
|
187d1212f5 | ||
|
|
d3776e161f | ||
|
|
010ea46ff2 | ||
|
|
db8119affd | ||
|
|
484a6b46a0 | ||
|
|
a48f259b99 | ||
|
|
2b9ae264fd | ||
|
|
207b066ecb | ||
|
|
587432269a | ||
|
|
a080e18571 | ||
|
|
7b758882be | ||
|
|
beafc6a635 | ||
|
|
0da4039b70 | ||
|
|
b89e18b149 | ||
|
|
07243fbf91 | ||
|
|
4b90aaa070 | ||
|
|
9d74eb067a | ||
|
|
c51f62a9fb | ||
|
|
badddd29ed | ||
|
|
d188289e84 | ||
|
|
1b9fd3bf90 | ||
|
|
0d98b4408e | ||
|
|
769abab65c | ||
|
|
78311f60b4 | ||
|
|
bd31b5791c | ||
|
|
cd5cfa47ec | ||
|
|
d31bdbef68 | ||
|
|
a82b50b1d0 | ||
|
|
912bbcf371 | ||
|
|
af5d63ea93 | ||
|
|
69681553c8 | ||
|
|
3f6856ddab | ||
|
|
9d55208563 | ||
|
|
2b8ce53553 | ||
|
|
6b157320c4 | ||
|
|
ba3da92061 | ||
|
|
dc6ce9c260 | ||
|
|
cf45b8e436 | ||
|
|
fc8966dab0 | ||
|
|
c537e72a27 | ||
|
|
dee359a37d | ||
|
|
34f67345e2 | ||
|
|
d937f5d89e | ||
|
|
856a5f182f | ||
|
|
6653b9c057 | ||
|
|
0b60780fe2 | ||
|
|
a16b2ea462 | ||
|
|
05771d975c | ||
|
|
417b63e86d | ||
|
|
01da231510 | ||
|
|
5e2559c1ee | ||
|
|
0bb784f7f2 | ||
|
|
eef3bf80c8 | ||
|
|
2d97d5fd45 | ||
|
|
32e71bc683 | ||
|
|
31c08cbb37 | ||
|
|
084cc40f88 | ||
|
|
c322fb2eec | ||
|
|
4e90d96f48 | ||
|
|
828a8e3824 | ||
|
|
7da5adf264 | ||
|
|
513185de26 | ||
|
|
2f17aa897a | ||
|
|
dd2359f96d | ||
|
|
8799aa6fc0 | ||
|
|
4dfe50038b | ||
|
|
51c4311233 | ||
|
|
72557594eb | ||
|
|
708e995ac7 | ||
|
|
589318ea8d | ||
|
|
17e9edbd53 | ||
|
|
f5124f749f | ||
|
|
fe10f7ca5b | ||
|
|
d590b66630 | ||
|
|
e68b843f73 | ||
|
|
2cf594f9ed | ||
|
|
1b33b42e94 | ||
|
|
77ba7e65ce | ||
|
|
7375f970af | ||
|
|
870d9052a0 | ||
|
|
4ea4aa43bf | ||
|
|
39ffa60e7a | ||
|
|
fc1c9b0019 | ||
|
|
ed3ad9db85 | ||
|
|
c38d68d081 | ||
|
|
352dcb82b7 | ||
|
|
7981ccaa1e | ||
|
|
e5444216ce | ||
|
|
207159bb17 | ||
|
|
32d4d3556d | ||
|
|
9102b6a11f | ||
|
|
587d6bbb93 | ||
|
|
9ea5d6ffb7 | ||
|
|
7ac7369a7f | ||
|
|
d548b68c8a | ||
|
|
92f4118015 | ||
|
|
3cae31998e | ||
|
|
396b8ccc05 | ||
|
|
70fece6c4f | ||
|
|
7ad2f1923e | ||
|
|
f1796cee43 | ||
|
|
e460940fcd | ||
|
|
26b71376b1 | ||
|
|
9b25f2e0ae | ||
|
|
cd40bc0894 | ||
|
|
06493ab38c | ||
|
|
5c3519171e | ||
|
|
ca6982d7b0 | ||
|
|
1c5a8dbdcc | ||
|
|
0cf3c25b2c | ||
|
|
d0122a123e | ||
|
|
5493d76d00 | ||
|
|
7fc535ffc6 | ||
|
|
8b9f9a2842 | ||
|
|
c60ade6a9c | ||
|
|
a0265599f6 | ||
|
|
9f45069c08 | ||
|
|
f3b95ad32d | ||
|
|
444d58900e | ||
|
|
72f239b293 | ||
|
|
6bc0b919c5 | ||
|
|
4864272c34 | ||
|
|
a421e6e167 | ||
|
|
76c6bafea7 | ||
|
|
f50dd5a1f8 | ||
|
|
0dbc6c14bb | ||
|
|
1d41b02f79 | ||
|
|
ec278c7d08 | ||
|
|
5729dbf4a6 | ||
|
|
4129b52dc5 | ||
|
|
55c9cc6673 | ||
|
|
59e75770fb | ||
|
|
d6ce0c62ff | ||
|
|
0ef13e39ae | ||
|
|
26b0837784 | ||
|
|
1f3a510411 | ||
|
|
039d5fb6d5 | ||
|
|
048fe69204 | ||
|
|
358c574153 | ||
|
|
efa0a345f9 | ||
|
|
78670bf8ec | ||
|
|
a47b93ea1a | ||
|
|
f4d56b56e1 | ||
|
|
3eb54bb4d6 | ||
|
|
a0f54df9b7 | ||
|
|
80a000cee7 | ||
|
|
8bd6bed5fb | ||
|
|
ba5e8d9935 | ||
|
|
8d6b3e7987 | ||
|
|
3fd14b3bdb | ||
|
|
6c3784e662 | ||
|
|
6256de065e | ||
|
|
4c1d64f04c | ||
|
|
4475f19268 | ||
|
|
2b5065dbec | ||
|
|
ba54582f7f | ||
|
|
2b0de9aa3c | ||
|
|
3981992e37 | ||
|
|
439710086e | ||
|
|
f5381b0430 | ||
|
|
3cce52953a | ||
|
|
797de9c602 | ||
|
|
c7f76d9f7b | ||
|
|
3947ea88d5 | ||
|
|
cc30049fdf | ||
|
|
7a964bb97c | ||
|
|
13bbf3e5ca | ||
|
|
46de91b2ff | ||
|
|
cb5b3acab0 | ||
|
|
6f6d4dc263 | ||
|
|
250b119391 | ||
|
|
beee98d5d6 | ||
|
|
4d270891be | ||
|
|
7e9352661e | ||
|
|
3f47d56bed | ||
|
|
1d0cac3a2b | ||
|
|
64da26ea9f | ||
|
|
4e53b6d5b0 | ||
|
|
3b4ede3c22 | ||
|
|
59aade10a7 | ||
|
|
cd5bf7281b | ||
|
|
cd5bd87835 | ||
|
|
9384277901 | ||
|
|
3b43e647a4 | ||
|
|
f28ad44e62 | ||
|
|
0baec19db1 | ||
|
|
8ea83b3fab | ||
|
|
7eaadd9ad6 | ||
|
|
506985c9d1 | ||
|
|
3fb0181ad7 | ||
|
|
fc56bb6017 | ||
|
|
d9c60f45a4 | ||
|
|
342060b86e | ||
|
|
b5b30bd9d8 | ||
|
|
55eaac0bd4 | ||
|
|
7583aeade7 | ||
|
|
4be3712082 | ||
|
|
c1e28709ac | ||
|
|
f0965efe73 | ||
|
|
529cdd1e04 | ||
|
|
ce867d4065 | ||
|
|
1eefb78157 | ||
|
|
ff0c8d2a8d | ||
|
|
5a250d854d | ||
|
|
caacf0d8ae | ||
|
|
0f7d4a0548 | ||
|
|
4529f74f0a | ||
|
|
1eaf32983a | ||
|
|
24b0682e8b | ||
|
|
cbf3326de6 | ||
|
|
c4ae9198a4 | ||
|
|
c01798f2e2 | ||
|
|
5de8dbe98a | ||
|
|
00eecd1841 | ||
|
|
54783d657e | ||
|
|
e17b618b18 | ||
|
|
3c8371fe28 | ||
|
|
aafb677d01 | ||
|
|
3a945560a8 | ||
|
|
516156624e | ||
|
|
b6e37edfa3 | ||
|
|
6772d26747 | ||
|
|
145ff70e3d | ||
|
|
cd57c3d37f | ||
|
|
80413bab3a | ||
|
|
319e70696e | ||
|
|
dfda46bcb7 | ||
|
|
848a44c5da | ||
|
|
48a0666c79 | ||
|
|
d828a747db | ||
|
|
7ff7eb20b9 | ||
|
|
bae9d14ae5 | ||
|
|
9b2fc7da65 | ||
|
|
163686cf77 | ||
|
|
895fbcf07e | ||
|
|
004131ddc3 | ||
|
|
e59d116918 | ||
|
|
4ee9d4525a | ||
|
|
3d1672d4ef | ||
|
|
91fc9ee913 | ||
|
|
15604b0ec4 | ||
|
|
8108b949f7 | ||
|
|
aabaa2a332 | ||
|
|
0896a7c63e | ||
|
|
b4b6b19ec3 | ||
|
|
93289f5b24 | ||
|
|
5810652007 | ||
|
|
1e92763497 | ||
|
|
a699c807fd | ||
|
|
7ef48f4202 | ||
|
|
7dc8042de7 | ||
|
|
9d13bd482c | ||
|
|
306ab41f08 | ||
|
|
aea4950398 | ||
|
|
042c27c088 | ||
|
|
b699d2ffad | ||
|
|
0400b0beaf | ||
|
|
88030f82b6 | ||
|
|
e8f8bd5af4 | ||
|
|
bfbcaf1598 | ||
|
|
ffc57dd69a | ||
|
|
07fa5c256b | ||
|
|
c07357b89b | ||
|
|
629d492fad | ||
|
|
693ca51315 | ||
|
|
f65444cfe9 | ||
|
|
464b887ed5 | ||
|
|
1bdf20feb0 | ||
|
|
db89bfb5b5 | ||
|
|
efe2dd22e9 | ||
|
|
144be87448 | ||
|
|
217e7316b9 | ||
|
|
9bf2900bb5 | ||
|
|
23640b1772 | ||
|
|
fecf35b3a9 | ||
|
|
8068fe6a7f | ||
|
|
2f21538c76 | ||
|
|
340cad0b2f | ||
|
|
0c51c73f31 | ||
|
|
717db94dc2 | ||
|
|
51e6708fcb | ||
|
|
a6f22d090a | ||
|
|
979f39a171 | ||
|
|
0f057720b8 | ||
|
|
a4eb8bd8fe | ||
|
|
38a8f24c9c | ||
|
|
82de0cf4dc | ||
|
|
13fcea5b57 | ||
|
|
4292871294 | ||
|
|
827c7f92ae | ||
|
|
bcd28eddca | ||
|
|
4d873146dd | ||
|
|
95bcd6ceff | ||
|
|
b596873300 | ||
|
|
0425336f67 | ||
|
|
1a27bcbec2 | ||
|
|
17761fb649 | ||
|
|
9b287c5f83 | ||
|
|
ce44cd7297 | ||
|
|
4ee5a69a28 | ||
|
|
e7f19acc7f | ||
|
|
9d557260ae | ||
|
|
6bbf12182a | ||
|
|
54a582d3eb | ||
|
|
0cbf4edbd1 | ||
|
|
0d4d8a7bf1 | ||
|
|
332bed1bcb | ||
|
|
ecbcbbab12 | ||
|
|
e143dd14bf | ||
|
|
5234812a49 | ||
|
|
ec770ddd15 | ||
|
|
fbe0538a71 | ||
|
|
fb1027f4a8 | ||
|
|
97e6ad4245 | ||
|
|
2ef74e9166 | ||
|
|
05ce1fb059 | ||
|
|
3dcd31807f | ||
|
|
d026aeea41 | ||
|
|
5ab5ce9e95 | ||
|
|
cf5b5feb9c | ||
|
|
d579eb8e4a | ||
|
|
fec31fe4bb | ||
|
|
b6d25866c1 | ||
|
|
58fe4a2aeb | ||
|
|
37e9359b1f | ||
|
|
78adf1c9d0 | ||
|
|
19ad0c362c | ||
|
|
3785534b0e | ||
|
|
8e8fa85ec3 | ||
|
|
ad340f239e | ||
|
|
3e53c370ec | ||
|
|
dff6d30e78 | ||
|
|
275a7bb773 | ||
|
|
26ec7ec819 | ||
|
|
592981a678 | ||
|
|
fbe286ded5 | ||
|
|
7780e8a406 | ||
|
|
b70bc7ee51 | ||
|
|
57baf6675a | ||
|
|
8998498383 | ||
|
|
94a7c549d7 | ||
|
|
988b0e8080 | ||
|
|
22e51bf668 | ||
|
|
1f70b0048e | ||
|
|
e18ef8a927 | ||
|
|
86078e7869 | ||
|
|
212bf7174e | ||
|
|
284396ea28 | ||
|
|
0bd697cbd4 | ||
|
|
72be8e243e | ||
|
|
445fb84a40 | ||
|
|
1ebf5b4edb | ||
|
|
8869bc88d1 | ||
|
|
aae9708647 | ||
|
|
e9736c4031 | ||
|
|
28199b5e0b | ||
|
|
fe743d8302 | ||
|
|
2f08ea9509 | ||
|
|
854dcca6ee | ||
|
|
9072db7c1b | ||
|
|
2b0ca413b4 | ||
|
|
0f1ce81a31 | ||
|
|
1b714f25b8 | ||
|
|
c03b8b4810 | ||
|
|
5f0744dd0e | ||
|
|
fe1676620f | ||
|
|
ec5b2fe509 | ||
|
|
3efe63bb49 | ||
|
|
48a1dfbc26 | ||
|
|
0a604cf83d | ||
|
|
4bc657ab63 | ||
|
|
165e8f4474 | ||
|
|
a4ca8611f4 | ||
|
|
0f354e2dd9 | ||
|
|
c9bd62dc47 | ||
|
|
f8304aeb28 | ||
|
|
1fdf1312a0 | ||
|
|
295a7c406c | ||
|
|
78fbeed7d2 | ||
|
|
446127f7bb | ||
|
|
9dd172447c | ||
|
|
38cb530993 | ||
|
|
6bfd45727f | ||
|
|
9f69f078fc | ||
|
|
2050c6c044 | ||
|
|
26d57460d5 | ||
|
|
a36c8ef09b | ||
|
|
45ee278b61 | ||
|
|
0470810eb8 | ||
|
|
2c01b03982 | ||
|
|
f285a7ceee | ||
|
|
b25e229e17 | ||
|
|
e8869dfcdf | ||
|
|
b9cc5ad202 | ||
|
|
4c9efd5d39 | ||
|
|
b75325998d | ||
|
|
c23de3969c | ||
|
|
f1c9511c50 | ||
|
|
bd2b4df822 | ||
|
|
f33e0c8ad4 | ||
|
|
eeb1e40c11 | ||
|
|
7c84b3a85e | ||
|
|
146fc3abe5 | ||
|
|
e9aa99ad82 | ||
|
|
89d6a60235 | ||
|
|
d69c0e02f3 | ||
|
|
7f337c0f49 | ||
|
|
a403b35602 | ||
|
|
0cdb2eccda | ||
|
|
a5cfb6216a | ||
|
|
a219e7c61e | ||
|
|
f932d56bf1 | ||
|
|
d925b2d922 | ||
|
|
4b4de6426c | ||
|
|
0e75d355c6 | ||
|
|
523d13f9c5 | ||
|
|
cd6b79d946 | ||
|
|
5ecbffacbd | ||
|
|
2c84f0c60e | ||
|
|
9a77c68685 | ||
|
|
a597d86710 | ||
|
|
8f3ed60b8c | ||
|
|
37e08ffb40 | ||
|
|
e400de8cc4 | ||
|
|
bfd78444e3 | ||
|
|
ed1934be36 | ||
|
|
99a980476b | ||
|
|
f581ccad1c | ||
|
|
2c29af8a6a | ||
|
|
306cae8bcb | ||
|
|
781d0b3a70 | ||
|
|
355ff63318 | ||
|
|
243e117538 | ||
|
|
f1a1f795d2 | ||
|
|
bcb092f29f | ||
|
|
4500161341 | ||
|
|
79e1cd3951 | ||
|
|
77c8abf457 | ||
|
|
847b6ddc92 | ||
|
|
d234858ec5 | ||
|
|
e7a3cf69fd | ||
|
|
ee41588a91 | ||
|
|
1b160bdd28 | ||
|
|
c33fe83030 | ||
|
|
eaeba41c53 | ||
|
|
34905cbfeb | ||
|
|
78e8b7f8a7 |
No files matched your search
@@ -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"
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
name: Build v2 for PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ v2 ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
name: Checkout repo
|
||||
|
||||
- name: Set up JDK 17 (LTS)
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'adopt'
|
||||
cache: maven
|
||||
|
||||
- name: Build with Maven
|
||||
run: mvn install --file pom.xml
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
name: Upload Artifact
|
||||
with:
|
||||
name: ChatItem.jar
|
||||
path: target/ChatItem-*.jar
|
||||
@@ -0,0 +1,36 @@
|
||||
name: Build v2
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ v2 ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
name: Checkout repo
|
||||
|
||||
- name: Set up JDK 17 (LTS)
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'adopt'
|
||||
cache: maven
|
||||
|
||||
- name: Build with Maven
|
||||
run: mvn install --file pom.xml
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
name: Upload Artifact
|
||||
with:
|
||||
name: ChatItem.jar
|
||||
path: target/ChatItem-*.jar
|
||||
- name: Send file README.md to discord channel
|
||||
uses: sinshutu/upload-to-discord@master
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
with:
|
||||
args: target/ChatItem-*.jar
|
||||
@@ -1,5 +1,11 @@
|
||||
.idea/
|
||||
src/test/
|
||||
bin/
|
||||
target/
|
||||
*.iml
|
||||
dependency-reduced-pom.xml
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
/.apt_generated/
|
||||
/.apt_generated_tests/
|
||||
@@ -1 +0,0 @@
|
||||
language: java
|
||||
@@ -1,5 +1,29 @@
|
||||
# ChatItem [](https://travis-ci.org/dadus33/ChatItem)
|
||||
# ChatItem
|
||||
|
||||
The official repository of the ChatItem Spigot/Bukkit plugin.
|
||||
|
||||
You can:
|
||||
|
||||
- [Download latest dev build](https://nightly.link/dadus33-plugins/ChatItem/workflows/build/v2/ChatItem.jar.zip)
|
||||
- [  ](https://discord.gg/yng5PPf62h)
|
||||
- [Check the wiki](https://github.com/dadus33-plugins/ChatItem/wiki)
|
||||
|
||||
# Item not well showed in chat
|
||||
|
||||
You can try to do `/chatitem admin` then select different paper item. It will change how the plugin try to add item in chat.
|
||||
|
||||
**If you already have issue, please do**:
|
||||
1) Do `/chatitem admin` then select on "Debug" item at top right
|
||||
2) Try to use ChatItem in chat
|
||||
3) Come on discord [here](https://discord.gg/yng5PPf62h) or in private message: `Elikill58#0743`
|
||||
4) Send the **full file `logs/latest.log`**
|
||||
|
||||
PS: Yes you can disable the debug behavior after.
|
||||
|
||||
# Building
|
||||
|
||||
Building this is simple as we use Maven.
|
||||
|
||||
To build it, simply clone this repository and then run `mvn clean install`.
|
||||
|
||||
You can add the parameter `export_dir` to set the URL where the JAR will be exported.
|
||||
@@ -6,106 +6,192 @@
|
||||
|
||||
<groupId>me.dadus33</groupId>
|
||||
<artifactId>ChatItem</artifactId>
|
||||
<version>1.2.5</version>
|
||||
<version>2.5.1</version>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>Bungeecord</id>
|
||||
<url>https://repo.md-5.net/content/groups/public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>dmulloy2-repo</id>
|
||||
<url>http://repo.dmulloy2.net/content/groups/public/</url>
|
||||
<id>sonatype</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>Plugin Metrics</id>
|
||||
<url>http://repo.mcstats.org/content/repositories/public</url>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>lang-utils-repo</id>
|
||||
<url>https://raw.github.com/MascusJeoraly/LanguageUtils/mvn-repo/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>protocollib-repo</id>
|
||||
<url>https://repo.dmulloy2.net/nexus/repository/public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>viaversion-repo</id>
|
||||
<url>https://repo.viaversion.com</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>elikill-repo</id>
|
||||
<url>https://repo.eliapp.fr:8081/repository/internal/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>dv8tion</id>
|
||||
<url>https://m2.dv8tion.net/releases</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>Scarsz-Nexus</id>
|
||||
<url>https://nexus.scarsz.me/content/groups/public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.10-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<version>1.10-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<version>3.6.5</version>
|
||||
<version>1.17-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>minecraft-server</artifactId>
|
||||
<version>1.7.10</version>
|
||||
<type>jar</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.7</version>
|
||||
<version>2.9.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.meowj</groupId>
|
||||
<artifactId>LangUtils</artifactId>
|
||||
<version>1.9</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<version>5.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.viaversion</groupId>
|
||||
<artifactId>viaversion-api</artifactId>
|
||||
<version>4.9.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.shevchik</groupId>
|
||||
<artifactId>ProtocolSupport</artifactId>
|
||||
<version>1.18.2-1-dev</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>4.1.58.Final</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.GeyserMC</groupId>
|
||||
<artifactId>opennbt</artifactId>
|
||||
<version>1.5</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mcstats.bukkit</groupId>
|
||||
<artifactId>metrics-lite</artifactId>
|
||||
<version>R8-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
<groupId>dev.majek</groupId>
|
||||
<artifactId>HexNicks</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<version>2.0</version>
|
||||
<groupId>com.github.MajekDev</groupId>
|
||||
<artifactId>HexNicks</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>2.0</version>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-api</artifactId>
|
||||
<version>4.14.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-platform-bukkit</artifactId>
|
||||
<version>4.3.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.discordsrv</groupId>
|
||||
<artifactId>discordsrv</artifactId>
|
||||
<version>1.26.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.willfp</groupId>
|
||||
<artifactId>EcoEnchants</artifactId>
|
||||
<version>8.57.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.Auxilor</groupId>
|
||||
<artifactId>EcoEnchants</artifactId>
|
||||
<version>12.2.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.ryderbelserion</groupId>
|
||||
<artifactId>ChatManager</artifactId>
|
||||
<version>3.7.7</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.willfp</groupId>
|
||||
<artifactId>eco</artifactId>
|
||||
<version>6.66.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>ChatItem-${project.version}</finalName>
|
||||
<directory>./target</directory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<includes>
|
||||
<include>plugin.yml</include>
|
||||
<include>config.yml</include>
|
||||
</includes>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<version>3.10.1</version>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<configuration>
|
||||
<outputDirectory>${dir}</outputDirectory>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.4.3</version>
|
||||
<version>3.4.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
@@ -113,17 +199,44 @@
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>com.google.gson</pattern>
|
||||
<shadedPattern>me.dadus33.gson</shadedPattern>
|
||||
<shadedPattern>me.dadus33.libs.gson</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.github.steveice10.opennbt</pattern>
|
||||
<shadedPattern>me.dadus33.libs.opennbt</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*</artifact>
|
||||
<excludes>
|
||||
<exclude>net.kyori:examination-api:**</exclude>
|
||||
<exclude>net.kyori:examination-string:**</exclude>
|
||||
<exclude>net.kyori:adventure-platform-api:**</exclude>
|
||||
<exclude>net.kyori:adventure-text-serializer-legacy:**</exclude>
|
||||
<exclude>net.kyori:adventure-text-serializer-gson:**</exclude>
|
||||
<exclude>net.kyori:adventure-platform-facet:**</exclude>
|
||||
<exclude>net.kyori:adventure-nbt:**</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<configuration>
|
||||
<outputDirectory>${export_dir}</outputDirectory>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
@@ -1,117 +1,229 @@
|
||||
package me.dadus33.chatitem;
|
||||
|
||||
import com.comphenix.protocol.AsynchronousManager;
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.ProtocolManager;
|
||||
import com.comphenix.protocol.async.AsyncListenerHandler;
|
||||
import com.comphenix.protocol.events.ListenerPriority;
|
||||
import me.dadus33.chatitem.commands.CIReload;
|
||||
import me.dadus33.chatitem.filters.Log4jFilter;
|
||||
import me.dadus33.chatitem.json.JSONManipulator;
|
||||
import me.dadus33.chatitem.json.JSONManipulatorCurrent;
|
||||
import me.dadus33.chatitem.listeners.ChatEventListener;
|
||||
import me.dadus33.chatitem.listeners.ChatPacketListener;
|
||||
import me.dadus33.chatitem.utils.General;
|
||||
import me.dadus33.chatitem.utils.Storage;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.mcstats.MetricsLite;
|
||||
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 java.util.concurrent.CompletableFuture;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import me.dadus33.chatitem.chatmanager.ChatEventListener;
|
||||
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.hook.ChatControlSupport;
|
||||
import me.dadus33.chatitem.hook.ChatManagerSupport;
|
||||
import me.dadus33.chatitem.hook.ecoenchants.EcoEnchantsSupport;
|
||||
import me.dadus33.chatitem.invsee.InvShower;
|
||||
import me.dadus33.chatitem.itemnamer.NamerManager;
|
||||
import me.dadus33.chatitem.listeners.InventoryListener;
|
||||
import me.dadus33.chatitem.listeners.JoinListener;
|
||||
import me.dadus33.chatitem.listeners.TranslationInventoryListener;
|
||||
import me.dadus33.chatitem.playernamer.PlayerNamerManager;
|
||||
import me.dadus33.chatitem.utils.ReflectionUtils;
|
||||
import me.dadus33.chatitem.utils.SemVer;
|
||||
import me.dadus33.chatitem.utils.Utils;
|
||||
import me.dadus33.chatitem.utils.Version;
|
||||
|
||||
public class ChatItem extends JavaPlugin {
|
||||
|
||||
public final static int CFG_VER = 6;
|
||||
private static ChatItem instance;
|
||||
private ChatEventListener chatEventListener;
|
||||
private Log4jFilter filter;
|
||||
private Storage storage;
|
||||
private ProtocolManager pm;
|
||||
private ChatPacketListener listener;
|
||||
private static JSONManipulator manip;
|
||||
public static boolean post17 = false;
|
||||
public final static int CFG_VER = 13;
|
||||
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 Storage storage;
|
||||
|
||||
public static void reload(CommandSender sender) {
|
||||
ChatItem obj = getInstance();
|
||||
obj.pm = ProtocolLibrary.getProtocolManager();
|
||||
obj.saveDefaultConfig();
|
||||
obj.reloadConfig();
|
||||
obj.storage = new Storage(obj.getConfig());
|
||||
General.init(obj.storage);
|
||||
General.checkConfigVersion();
|
||||
obj.listener.setStorage(obj.storage);
|
||||
obj.chatEventListener.setStorage(obj.storage);
|
||||
obj.filter.setStorage(obj.storage);
|
||||
if (!obj.storage.RELOAD_MESSAGE.isEmpty())
|
||||
sender.sendMessage(obj.storage.RELOAD_MESSAGE);
|
||||
}
|
||||
public static void reload(CommandSender sender) {
|
||||
ChatItem pl = getInstance();
|
||||
if (pl.getConfig().getKeys(false).isEmpty())
|
||||
pl.saveDefaultConfig();
|
||||
pl.reloadConfig();
|
||||
String oldChatManager = pl.storage.manager;
|
||||
pl.storage = new Storage(pl.getConfig());
|
||||
pl.chooseManagers();
|
||||
Translation.load(pl);
|
||||
InvShower.getInvShower().clear();
|
||||
if(sender != null) {
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
public static ChatItem getInstance() {
|
||||
return instance;
|
||||
}
|
||||
public static ChatItem getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
pm = ProtocolLibrary.getProtocolManager();
|
||||
saveDefaultConfig();
|
||||
storage = new Storage(getConfig());
|
||||
General.init(storage);
|
||||
General.checkConfigVersion();
|
||||
listener = new ChatPacketListener(this, ListenerPriority.HIGHEST, storage, PacketType.Play.Server.CHAT);
|
||||
AsynchronousManager am = pm.getAsynchronousManager();
|
||||
AsyncListenerHandler packetListenerAsyncThread = am.registerAsyncHandler(listener);
|
||||
packetListenerAsyncThread.start();
|
||||
CIReload rld = new CIReload();
|
||||
Bukkit.getPluginCommand("cireload").setExecutor(rld);
|
||||
chatEventListener = new ChatEventListener(storage);
|
||||
Bukkit.getPluginManager().registerEvents(chatEventListener, this);
|
||||
if(isMc18OrLater()) {
|
||||
post17 = true;
|
||||
}
|
||||
manip = new JSONManipulatorCurrent();
|
||||
public static void debug(String msg) {
|
||||
if (getInstance().getStorage().debug)
|
||||
getInstance().getLogger().info("[Debug] " + msg.replace(ChatManager.SEPARATOR, 'S').replace(ChatManager.SEPARATOR_END, 'E'));
|
||||
}
|
||||
public static boolean hasDebug() {
|
||||
return getInstance().getStorage().debug;
|
||||
}
|
||||
|
||||
try {
|
||||
MetricsLite metrics = new MetricsLite(this);
|
||||
metrics.start();
|
||||
} catch (IOException e) {
|
||||
getLogger().log(Level.WARNING, ChatColor.RED + "Couldn't start metrics!");
|
||||
}
|
||||
filter = new Log4jFilter(storage);
|
||||
}
|
||||
private void chooseManagers() {
|
||||
this.chatManager.forEach((cm) -> cm.unload(this));
|
||||
this.chatManager.clear();
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
String managerName = getStorage().manager;
|
||||
|
||||
switch (managerName.toLowerCase(Locale.ROOT)) {
|
||||
case "both":
|
||||
this.chatManager.add(new PacketEditingChatManager(this));
|
||||
this.chatManager.add(new ChatListenerChatManager(this));
|
||||
getLogger().info("Manager automatically chosen: " + getVisualChatManagers());
|
||||
break;
|
||||
case "auto":
|
||||
if (getPluginThatRequirePacket().stream().map(pm::getPlugin).anyMatch(Objects::nonNull) && Version.getVersion().isNewerThan(Version.V1_7))
|
||||
this.chatManager.add(new PacketEditingChatManager(this));
|
||||
else
|
||||
this.chatManager.add(new ChatListenerChatManager(this));
|
||||
getLogger().info("Manager automatically chosen: " + getVisualChatManagers());
|
||||
break;
|
||||
case "packet":
|
||||
this.chatManager.add(new PacketEditingChatManager(this));
|
||||
getLogger().info("Manager chosen: " + getVisualChatManagers());
|
||||
break;
|
||||
case "chat":
|
||||
this.chatManager.add(new ChatListenerChatManager(this));
|
||||
getLogger().info("Manager chosen: " + getVisualChatManagers());
|
||||
break;
|
||||
default:
|
||||
getLogger().severe("----- WARN -----");
|
||||
getLogger().severe("Failed to find manager: " + managerName + ".");
|
||||
getLogger().severe("Please reset your config and/or check wiki for more information");
|
||||
getLogger().severe("Using default manager: chat.");
|
||||
getLogger().severe("----- WARN -----");
|
||||
this.chatManager.add(new ChatListenerChatManager(this));
|
||||
break;
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
instance = null;
|
||||
post17 = false;
|
||||
}
|
||||
this.chatManager.forEach((cm) -> cm.load(this, getStorage()));
|
||||
|
||||
private boolean isMc18OrLater(){
|
||||
switch(getVersion(Bukkit.getServer())){
|
||||
case "v1_8_R1": return true;
|
||||
case "v1_8_R2": return true;
|
||||
case "v1_8_R3": return true;
|
||||
case "v1_9_R1": return true;
|
||||
case "v1_9_R2": return true;
|
||||
case "v1_10_R1": return true;
|
||||
case "v1_10_R2": return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
NamerManager.load(this);
|
||||
PlayerNamerManager.load(this);
|
||||
}
|
||||
|
||||
private List<String> getPluginThatRequirePacket() {
|
||||
return Arrays.asList("DeluxeChat", "HexNicks", "VentureChat", "ItemsAdder");
|
||||
}
|
||||
|
||||
private static String getVersion(Server server) {
|
||||
final String packageName = server.getClass().getPackage().getName();
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// Save the instance (we're basically a singleton)
|
||||
instance = this;
|
||||
getLogger().info("Detected server version: " + Version.getVersion().name().toLowerCase());
|
||||
|
||||
return packageName.substring(packageName.lastIndexOf('.') + 1);
|
||||
}
|
||||
// Load config
|
||||
if (!new File(getDataFolder(), "config.yml").exists()) {
|
||||
getLogger().info("--------------");
|
||||
getLogger().info("");
|
||||
getLogger().info("Welcome on ChatItem !");
|
||||
getLogger().info("If you need help for setup, USE: /chatitem select");
|
||||
getLogger().info("Then follow steps.");
|
||||
getLogger().info("");
|
||||
getLogger().info("--------------");
|
||||
saveDefaultConfig();
|
||||
}
|
||||
storage = new Storage(getConfig());
|
||||
|
||||
// Commands
|
||||
loadCommand(getCommand("cireload"), new CIReloadCommand());
|
||||
loadCommand(getCommand("chatitem"), new ChatItemCommand());
|
||||
|
||||
public static JSONManipulator getManipulator(){
|
||||
return manip;
|
||||
}
|
||||
// events
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
pm.registerEvents(new JoinListener(), this);
|
||||
pm.registerEvents(new InventoryListener(), this);
|
||||
pm.registerEvents(new TranslationInventoryListener(), this);
|
||||
pm.registerEvents(new ChatEventListener(), this);
|
||||
|
||||
chooseManagers();
|
||||
|
||||
StringJoiner plugins = new StringJoiner(", ");
|
||||
if (pm.isPluginEnabled("DiscordSRV")) {
|
||||
discordSrvSupport = true;
|
||||
plugins.add("DiscordSRV");
|
||||
}
|
||||
if (pm.isPluginEnabled("ChatControl") && ReflectionUtils.isClassExist("org.mineacademy.chatcontrol.settings.Settings")) {
|
||||
ChatControlSupport.init(this);
|
||||
plugins.add("ChatControl");
|
||||
}
|
||||
if (pm.isPluginEnabled("ChatManager") && ReflectionUtils.isClassExist("me.h1dd3nxn1nja.chatmanager.Main")) {
|
||||
ChatManagerSupport.init(this);
|
||||
plugins.add("ChatManager");
|
||||
}
|
||||
if (pm.isPluginEnabled("EcoEnchants") && EcoEnchantsSupport.load()) {
|
||||
plugins.add("EcoEnchants");
|
||||
}
|
||||
|
||||
if (plugins.length() > 0)
|
||||
getLogger().info("Load " + plugins.toString() + " support.");
|
||||
|
||||
Translation.load(this);
|
||||
|
||||
getServer().getMessenger().registerIncomingPluginChannel(this, brandChannelName, (chan, p, msg) -> ItemPlayer.getPlayer(p).setClientName(new String(msg).substring(1)));
|
||||
|
||||
if (storage.checkUpdate) {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
String urlName = "https://api.spigotmc.org/legacy/update.php?resource=19064";
|
||||
String content = Utils.getFromURL(urlName);
|
||||
if (Strings.isNullOrEmpty(content))
|
||||
return;
|
||||
SemVer currentVersion = SemVer.parse(getDescription().getVersion());
|
||||
if (currentVersion == null)
|
||||
return;
|
||||
SemVer latestVersion = SemVer.parse(content);
|
||||
if (latestVersion != null && latestVersion.isNewerThan(currentVersion)) {
|
||||
hasNewVersion = !content.equalsIgnoreCase(getDescription().getVersion());
|
||||
if (hasNewVersion)
|
||||
getLogger().info(storage.updateMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void loadCommand(PluginCommand cmd, Object obj) {
|
||||
if (obj instanceof CommandExecutor)
|
||||
cmd.setExecutor((CommandExecutor) obj);
|
||||
if (obj instanceof TabCompleter)
|
||||
cmd.setTabCompleter((TabCompleter) obj);
|
||||
}
|
||||
|
||||
public Storage getStorage() {
|
||||
return storage;
|
||||
}
|
||||
|
||||
public List<ChatManager> getChatManager() {
|
||||
return chatManager;
|
||||
}
|
||||
|
||||
public String getVisualChatManagers() {
|
||||
StringJoiner sj = new StringJoiner(", ");
|
||||
for (ChatManager cm : chatManager) {
|
||||
sj.add(cm.getName() + " (" + cm.getId() + ")");
|
||||
}
|
||||
return sj.toString();
|
||||
}
|
||||
|
||||
public boolean isHasNewVersion() {
|
||||
return hasNewVersion;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package me.dadus33.chatitem;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.dadus33.chatitem.playerversion.PlayerVersionManager;
|
||||
import me.dadus33.chatitem.utils.Version;
|
||||
|
||||
public class ItemPlayer {
|
||||
|
||||
private static final ConcurrentHashMap<UUID, ItemPlayer> PLAYERS = new ConcurrentHashMap<>();
|
||||
public static ItemPlayer getPlayer(Player p) {
|
||||
return PLAYERS.computeIfAbsent(p.getUniqueId(), ItemPlayer::new);
|
||||
}
|
||||
public static ItemPlayer getPlayer(UUID uuid) {
|
||||
return PLAYERS.computeIfAbsent(uuid, ItemPlayer::new);
|
||||
}
|
||||
private final UUID uuid;
|
||||
private int protocolVersion = 0;
|
||||
private Version version = null;
|
||||
private String clientName = "unknow";
|
||||
|
||||
public ItemPlayer(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
Player p = Bukkit.getPlayer(uuid);
|
||||
if(p != null)
|
||||
setVersion(PlayerVersionManager.getPlayerVersionAdapter().getPlayerVersion(p));
|
||||
}
|
||||
|
||||
public UUID getUUID() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return Bukkit.getPlayer(uuid);
|
||||
}
|
||||
|
||||
public String getClientName() {
|
||||
return clientName;
|
||||
}
|
||||
|
||||
public void setClientName(String clientName) {
|
||||
this.clientName = clientName;
|
||||
}
|
||||
|
||||
public int getProtocolVersion() {
|
||||
if(protocolVersion == 0)
|
||||
setProtocolVersion(PlayerVersionManager.getPlayerVersionAdapter().getProtocolVersion(getPlayer()));
|
||||
return protocolVersion;
|
||||
}
|
||||
|
||||
public void setProtocolVersion(int protocolVersion) {
|
||||
this.protocolVersion = protocolVersion;
|
||||
if(version == Version.getVersion()) {// if is default
|
||||
version = Version.getVersion(protocolVersion);
|
||||
ChatItem.debug("Detected version " + version.name() + " (protocol: " + protocolVersion + ")");
|
||||
}
|
||||
}
|
||||
|
||||
public Version getVersion() {
|
||||
if(version == null)
|
||||
setVersion(PlayerVersionManager.getPlayerVersionAdapter().getPlayerVersion(getPlayer()));
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(Version version) {
|
||||
this.version = version;
|
||||
if(protocolVersion == 0)
|
||||
this.protocolVersion = version.MAX_VER;
|
||||
}
|
||||
|
||||
public boolean isBuggedClient() {
|
||||
return (getVersion().equals(Version.V1_7) && getClientName().toLowerCase().contains("lunarclient")) || (!getVersion().isNewerOrEquals(Version.V1_15) && Version.getVersion().isNewerOrEquals(Version.V1_16));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ItemPlayer[uuid=" + uuid + ",name=" + (getPlayer() != null ? getPlayer().getName() : "-") + ",version=" + version.name() + ",protocol=" + protocolVersion + ",client=" + clientName + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package me.dadus33.chatitem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import me.dadus33.chatitem.chatmanager.ChatManager;
|
||||
|
||||
public enum ItemSlot {
|
||||
|
||||
HAND(true, "", false),
|
||||
HELMET(false, "helmet", false),
|
||||
CHESTPLATE(false, "chestplate", false),
|
||||
LEGGINGS(false, "leggings", false),
|
||||
BOOTS(false, "boots", false),
|
||||
INVENTORY(false, "inventory", true),
|
||||
ENDERCHEST(false, "enderchest", true);
|
||||
|
||||
private final boolean basic, command;
|
||||
private final String key;
|
||||
|
||||
private ItemSlot(boolean basic, String key, boolean command) {
|
||||
this.basic = basic;
|
||||
this.command = command;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public boolean isBasic() {
|
||||
return basic;
|
||||
}
|
||||
|
||||
public boolean isCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public List<String> getPlaceholders() {
|
||||
return ChatItem.getInstance().getConfig().getStringList(basic ? "general.placeholders" : "general.other-placeholders." + key + ".keys");
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return basic || ChatItem.getInstance().getConfig().getBoolean("general.other-placeholders." + key + ".enabled", true);
|
||||
}
|
||||
|
||||
public boolean isDenyIfNoItem() {
|
||||
return ChatItem.getInstance().getConfig().getBoolean("general" + (basic ? "" : ".other-placeholders." + key) + ".deny-if-no-item", true);
|
||||
}
|
||||
|
||||
public boolean hasPlaceholders(String message) {
|
||||
for (String rep : getPlaceholders()) {
|
||||
if (message.contains(rep)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String replacePlaceholdersToSeparator(String message) {
|
||||
for(String rep : getPlaceholders())
|
||||
message = message.replace(rep, Character.toString(ChatManager.SEPARATOR));
|
||||
return message;
|
||||
}
|
||||
|
||||
public static ItemSlot getItemSlotFromMessage(String message) {
|
||||
for(ItemSlot slot : ItemSlot.values()) {
|
||||
if(slot.isEnabled() && slot.hasPlaceholders(message)) {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package me.dadus33.chatitem;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
public class Storage {
|
||||
|
||||
public String handName, nameFormat, amountFormat, commandFormat, manager, permissionName, buggedClientAction, language;
|
||||
public final String messageNoPermission, messageDeny, messageReload, messageCooldown, messageLimit, messageIgnoredItem;
|
||||
public final String SECONDS, minutes, hours;
|
||||
public final String updateMessage, updateHover;
|
||||
public final List<String> tooltipHand, tooltipBuggedClient, ignoredItems;
|
||||
public boolean colorIfColored, addAmountForced, letMessageThrough, debug, handDisabled, showNoPermissionMessage, checkUpdate, permissionEnabled, cmdBroadcast, cmdShow, discordSrvSendMsg;
|
||||
public int configVersion, limit, cooldown;
|
||||
private FileConfiguration conf;
|
||||
|
||||
public Storage(FileConfiguration cnf) {
|
||||
this.conf = cnf;
|
||||
configVersion = conf.getInt("config-version", 13);
|
||||
checkConfigVersion();
|
||||
this.manager = conf.getString("manager", "auto");
|
||||
language = conf.getString("general.language", "en_gb");
|
||||
debug = conf.getBoolean("debug", false);
|
||||
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);
|
||||
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());
|
||||
ignoredItems = conf.getStringList("general.ignored_items");
|
||||
checkUpdate = conf.getBoolean("general.check-update", true);
|
||||
cmdShow = conf.getBoolean("general.sub-commands.broadcast", true);
|
||||
cmdBroadcast = conf.getBoolean("general.sub-commands.show", 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!"));
|
||||
messageCooldown = color(conf.getString("messages.cooldown-message", "&c&lYou can only use items in chat once a minute! You have {remaining} left!"));
|
||||
updateMessage = color(conf.getString("messages.join-update.message", "&cA new version of ChatItem is available. &aClick here to download."));
|
||||
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!"));
|
||||
messageIgnoredItem = color(conf.getString("messages.ignored-item", "&cThis item is not allowed to be showed."));
|
||||
discordSrvSendMsg = conf.getBoolean("discord-srv-send-our", true);
|
||||
|
||||
SECONDS = color(conf.getString("messages.seconds", " seconds"));
|
||||
minutes = color(conf.getString("messages.minutes", " minutes"));
|
||||
hours = color(conf.getString("messages.hours", " hours"));
|
||||
colorStringList(tooltipHand);
|
||||
}
|
||||
|
||||
public static String color(String s) {
|
||||
return s == null || s.isEmpty() ? s : ChatColor.translateAlternateColorCodes('&', s);
|
||||
}
|
||||
|
||||
private static void colorStringList(List<String> input) {
|
||||
for (int i = 0; i < input.size(); ++i) {
|
||||
input.set(i, color(input.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
private void checkConfigVersion() {
|
||||
int latestVersion = ChatItem.CFG_VER;
|
||||
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...");
|
||||
performOverwrite();
|
||||
conf = pl.getConfig();
|
||||
pl.getLogger().warning(ChatColor.RED + "Replacement complete!");
|
||||
}
|
||||
}
|
||||
|
||||
private void performOverwrite() {
|
||||
ChatItem.getInstance().saveResource("config.yml", true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package me.dadus33.chatitem;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import me.dadus33.chatitem.utils.Utils;
|
||||
|
||||
public class Translation {
|
||||
|
||||
private static File folder;
|
||||
private static YamlConfiguration legacy, allLangsConfig;
|
||||
private static JsonObject messages;
|
||||
private static HashMap<String, String> allLangs = new HashMap<>();
|
||||
|
||||
public static void load(ChatItem pl) {
|
||||
folder = new File(pl.getDataFolder(), "lang");
|
||||
if (!folder.exists())
|
||||
folder.mkdir();
|
||||
legacy = Utils.copyLoadFile(folder, "legacy.yml", "lang/legacy.yml");
|
||||
allLangsConfig = Utils.copyLoadFile(pl.getDataFolder(), "langs.yml", "langs.yml");
|
||||
|
||||
allLangsConfig.getStringList("all").forEach(langKey -> {
|
||||
try {
|
||||
JsonObject content = JsonParser.parseReader(new InputStreamReader(pl.getResource("lang/" + langKey + ".json"))).getAsJsonObject();
|
||||
allLangs.put(langKey, content.get("language.name").getAsString() + " (" + content.get("language.region").getAsString() + ")");
|
||||
} catch (Exception e) {
|
||||
pl.getLogger().severe("Failed to load lang with key " + langKey + " : " + e.getMessage() + " (" + e.getStackTrace()[0].toString() + ")");
|
||||
}
|
||||
});
|
||||
allLangs = allLangs.entrySet().stream().sorted(Entry.comparingByValue()).collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
|
||||
loadLang(pl.getStorage().language);
|
||||
}
|
||||
|
||||
public static HashMap<String, String> getAllLangs() {
|
||||
return allLangs;
|
||||
}
|
||||
|
||||
public static JsonObject getMessages() {
|
||||
return messages;
|
||||
}
|
||||
|
||||
public static void loadLang(String lang) {
|
||||
ChatItem pl = ChatItem.getInstance();
|
||||
File langFile = new File(folder, lang + ".json");
|
||||
if (!langFile.exists()) {
|
||||
if (pl.getResource("lang/" + lang + ".json") != null) {
|
||||
Utils.copyFile("lang/" + lang + ".json", langFile);
|
||||
} else {
|
||||
pl.getLogger().severe("Failed to find lang file for " + lang);
|
||||
if(lang != "en_gb")
|
||||
loadLang("en_gb");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
messages = JsonParser.parseReader(new FileReader(langFile)).getAsJsonObject();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
pl.getLogger().info("Loaded translation for " + lang + ".");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static String get(ItemStack item) {
|
||||
String key = (item.getType().isBlock() ? "block" : "item") + ".minecraft." + item.getType().name().toLowerCase();
|
||||
if (messages != null && messages.has(key)) {
|
||||
return messages.get(key).getAsString();
|
||||
} else
|
||||
ChatItem.debug("Failed to find translation for " + key);
|
||||
return legacy.getString(item.getType().name() + "." + item.getDurability(), item.getType().name().toLowerCase().replace("_", " "));
|
||||
}
|
||||
|
||||
protected void thisMethodShouldNotBeUsed_InsteadToUpdateLangFileFromLocalInstall() throws Exception {
|
||||
File dir = new File("dir/to/result");
|
||||
File folder = new File("C:\\Dir\\To\\AppData\\Roaming\\.minecraft\\assets");// here we are looking for 1.19
|
||||
JsonObject json = JsonParser.parseReader(new FileReader(new File(folder, "indexes/1.19.json"))).getAsJsonObject().get("objects").getAsJsonObject();
|
||||
for (String key : json.keySet()) {
|
||||
if (key.startsWith("minecraft/lang")) { // only lang files
|
||||
String lang = key.toString().replace("minecraft/lang/", "");
|
||||
String hash = json.get(key).getAsJsonObject().get("hash").getAsString();
|
||||
File langFile = new File(folder, "objects/" + hash.substring(0, 2) + "/" + hash);
|
||||
JsonObject langs = JsonParser.parseReader(new FileReader(langFile)).getAsJsonObject();
|
||||
for (String langKey : new ArrayList<>(langs.keySet())) {
|
||||
if (!(langKey.startsWith("block.") || langKey.startsWith("language"))) { // only what we want
|
||||
langs.remove(langKey); // removing not needed
|
||||
}
|
||||
}
|
||||
File langDir = new File(dir, lang);
|
||||
Files.write(langDir.toPath(), Arrays.asList(langs.toString()));
|
||||
System.out.println("Copied " + lang); // using sysout as it's made for basic java, not mc
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
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.ItemSlot;
|
||||
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, ChatAction action) {
|
||||
return new Chat(actualId++, p, message, action);
|
||||
}
|
||||
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;
|
||||
private final ChatAction action;
|
||||
|
||||
public Chat(int id, Player p, String message, ChatAction action) {
|
||||
this.time = System.currentTimeMillis();
|
||||
this.id = id;
|
||||
this.p = p;
|
||||
this.message = message;
|
||||
this.action = action;
|
||||
CHAT.add(this);
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return p;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public ItemSlot getSlot() {
|
||||
return action.getSlot();
|
||||
}
|
||||
|
||||
public ChatAction getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
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 + "}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package me.dadus33.chatitem.chatmanager;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import me.dadus33.chatitem.ItemSlot;
|
||||
|
||||
public class ChatAction {
|
||||
|
||||
private boolean isItem;
|
||||
private ItemSlot slot;
|
||||
private String command;
|
||||
private ItemStack item;
|
||||
|
||||
public ChatAction(ItemSlot slot, ItemStack item) {
|
||||
this.slot = slot;
|
||||
this.item = item;
|
||||
this.isItem = true;
|
||||
}
|
||||
|
||||
public ChatAction(ItemSlot slot, String command) {
|
||||
this.slot = slot;
|
||||
this.command = command;
|
||||
this.isItem = false;
|
||||
}
|
||||
|
||||
public ItemSlot getSlot() {
|
||||
return slot;
|
||||
}
|
||||
|
||||
public boolean isItem() {
|
||||
return isItem;
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public ItemStack getItem() {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package me.dadus33.chatitem.chatmanager;
|
||||
|
||||
import static me.dadus33.chatitem.chatmanager.ChatManager.SEPARATOR;
|
||||
import static me.dadus33.chatitem.chatmanager.ChatManager.SEPARATOR_END;
|
||||
|
||||
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 me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.ItemSlot;
|
||||
import me.dadus33.chatitem.Storage;
|
||||
import me.dadus33.chatitem.utils.Utils;
|
||||
|
||||
public class ChatEventListener implements Listener {
|
||||
|
||||
private Storage getStorage() {
|
||||
return ChatItem.getInstance().getStorage();
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onChat(AsyncPlayerChatEvent e) {
|
||||
if (ChatManager.isTestingEnabled() && !ChatManager.isTesting("packet"))
|
||||
return;
|
||||
if (ChatManager.containsSeparator(e.getMessage())) { // If the BELL character is found, we have to remove it
|
||||
e.setMessage(ChatManager.removeSeparator(e.getMessage()));
|
||||
}
|
||||
Player p = e.getPlayer();
|
||||
String oldMsg = e.getMessage();
|
||||
ItemSlot slot = ItemSlot.getItemSlotFromMessage(e.getMessage());
|
||||
if (slot == null) {
|
||||
ChatItem.debug("(v1) not found placeholders in: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
ChatAction action = ChatManager.getChatAction(slot, p);
|
||||
if(action.isItem() && !ChatManager.canShowItem(p, action.getItem(), slot, e))
|
||||
return;
|
||||
String s = slot.replacePlaceholdersToSeparator(e.getMessage());
|
||||
if (Utils.countMatches(s, Character.toString(ChatManager.SEPARATOR)) > getStorage().limit) {
|
||||
e.setCancelled(true);
|
||||
if (!getStorage().messageLimit.isEmpty())
|
||||
p.sendMessage(getStorage().messageLimit);
|
||||
return;
|
||||
}
|
||||
|
||||
Chat c = Chat.create(p, oldMsg, action);
|
||||
ChatItem.debug("(v1) Set placeholder to message " + c);
|
||||
e.setMessage(s.replace(Character.toString(ChatManager.SEPARATOR), 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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
package me.dadus33.chatitem.chatmanager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
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.block.ShulkerBox;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.BlockStateMeta;
|
||||
import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.ItemSlot;
|
||||
import me.dadus33.chatitem.Storage;
|
||||
import me.dadus33.chatitem.hook.ecoenchants.EcoEnchantsSupport;
|
||||
import me.dadus33.chatitem.invsee.InvShower;
|
||||
import me.dadus33.chatitem.invsee.hook.EnderChestShower;
|
||||
import me.dadus33.chatitem.invsee.hook.PlayerInventoryShower;
|
||||
import me.dadus33.chatitem.itemnamer.NamerManager;
|
||||
import me.dadus33.chatitem.utils.ItemUtils;
|
||||
import me.dadus33.chatitem.utils.Utils;
|
||||
import me.dadus33.chatitem.utils.Version;
|
||||
|
||||
public abstract class ChatManager {
|
||||
|
||||
public static String inTest = null;
|
||||
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;
|
||||
|
||||
public ChatManager() {
|
||||
|
||||
}
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
public abstract String getId();
|
||||
|
||||
public Storage getStorage() {
|
||||
return s;
|
||||
}
|
||||
|
||||
public void load(ChatItem pl, Storage s) {
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
public abstract void unload(ChatItem pl);
|
||||
|
||||
/**
|
||||
* Get the item in hand as usable one.<br>
|
||||
* Will include, in lore, all informations from other plugins.
|
||||
*
|
||||
* @param p the player
|
||||
* @return the usable item
|
||||
*/
|
||||
public static ItemStack getUsableItem(Player p, ItemSlot slot) {
|
||||
if(slot == null)
|
||||
return null;
|
||||
ItemStack betterItem = HandItem.getBetterItem(p, slot);
|
||||
if(betterItem == null)
|
||||
return null;
|
||||
|
||||
ItemStack item = betterItem.clone();
|
||||
if(slot.isDenyIfNoItem() && ItemUtils.isEmpty(item))
|
||||
return null;
|
||||
if (EcoEnchantsSupport.hasSupport()) {
|
||||
item = EcoEnchantsSupport.manageItem(item);
|
||||
} else if (item.hasItemMeta()) {
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
if (meta instanceof BookMeta) { // filtering written books
|
||||
BookMeta bm = (BookMeta) item.getItemMeta();
|
||||
bm.setPages(Collections.emptyList());
|
||||
item.setItemMeta(bm);
|
||||
} else if (meta instanceof BlockStateMeta && Version.getVersion().isNewerOrEquals(Version.V1_9)) { // if it's a block
|
||||
BlockStateMeta bsm = (BlockStateMeta) item.getItemMeta();
|
||||
if (bsm.hasBlockState() && bsm.getBlockState() instanceof ShulkerBox) {
|
||||
ShulkerBox sb = (ShulkerBox) bsm.getBlockState();
|
||||
for (ItemStack itemInv : sb.getInventory()) {
|
||||
ItemUtils.stripData(itemInv);
|
||||
}
|
||||
bsm.setBlockState(sb);
|
||||
}
|
||||
item.setItemMeta(bsm);
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
public static ChatAction getChatAction(ItemSlot slot, Player p) {
|
||||
if(slot.isCommand()) {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
InvShower.add(uuid.toString(), slot == ItemSlot.INVENTORY ? new PlayerInventoryShower(p) : new EnderChestShower(p));
|
||||
return new ChatAction(slot, "/chatitem seeinv " + uuid.toString());
|
||||
}
|
||||
return new ChatAction(slot, getUsableItem(p, slot));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all lores lines of an item, to replace the show_item action which is not
|
||||
* working with ViaBackwards
|
||||
*
|
||||
* @param item the item to get lines from
|
||||
* @return all lores
|
||||
*/
|
||||
public static List<String> getMaxLinesFromItem(Player p, ItemStack item) {
|
||||
List<String> lines = new ArrayList<>();
|
||||
if (item.hasItemMeta()) {
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
lines.add(meta.hasDisplayName() ? meta.getDisplayName() : NamerManager.getName(p, item, ChatItem.getInstance().getStorage()));
|
||||
if (meta.hasEnchants()) {
|
||||
meta.getEnchants().forEach((enchant, lvl) -> {
|
||||
lines.add(ChatColor.RESET + Utils.getEnchantName(enchant) + " " + Utils.toRoman(lvl));
|
||||
});
|
||||
}
|
||||
if (meta.hasLore())
|
||||
lines.addAll(meta.getLore());
|
||||
} else {
|
||||
lines.add(NamerManager.getName(p, item, ChatItem.getInstance().getStorage()));
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of item according to player & config<br>
|
||||
* Prefer use {@link #getNameOfItem(Player, ItemStack, Storage)} if you want
|
||||
* take in count the empty item
|
||||
*
|
||||
* @param p the player
|
||||
* @param item the item
|
||||
* @param c the config
|
||||
* @return the name of item
|
||||
*/
|
||||
public static String styleItem(Player p, ItemStack item, Storage c) {
|
||||
String replacer = c.nameFormat;
|
||||
String amount = c.amountFormat;
|
||||
if (item.getAmount() == 1) {
|
||||
if (c.addAmountForced) {
|
||||
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);
|
||||
}
|
||||
return replacer.replace(NAME, NamerManager.getName(p, item, c));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of item according to player & config
|
||||
*
|
||||
* @param p the player that is owner of item
|
||||
* @param item the item
|
||||
* @param c the config
|
||||
* @return the name of item or hand
|
||||
*/
|
||||
public static String getNameOfItem(Player p, ItemStack item, Storage c) {
|
||||
if (ItemUtils.isEmpty(item)) {
|
||||
if (c.handDisabled)
|
||||
return ItemSlot.HAND.getPlaceholders().get(0);
|
||||
else
|
||||
return c.handName;
|
||||
}
|
||||
return styleItem(p, item, c);
|
||||
}
|
||||
|
||||
public static String getNameForChatAction(Player p, ChatAction action, Storage c) {
|
||||
if(action.isItem()) {
|
||||
ItemStack item = action.getItem();
|
||||
if (ItemUtils.isEmpty(item)) {
|
||||
if (c.handDisabled)
|
||||
return ItemSlot.HAND.getPlaceholders().get(0);
|
||||
else
|
||||
return c.handName;
|
||||
}
|
||||
return styleItem(p, item, c);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String calculateTime(long seconds) {
|
||||
Storage c = ChatItem.getInstance().getStorage();
|
||||
if (seconds < 60) {
|
||||
return seconds + c.SECONDS;
|
||||
}
|
||||
if (seconds < 3600) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int minutes = (int) seconds / 60;
|
||||
builder.append(minutes).append(c.minutes);
|
||||
int secs = (int) seconds - minutes * 60;
|
||||
if (secs != 0) {
|
||||
builder.append(" ").append(secs).append(c.SECONDS);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int hours = (int) seconds / 3600;
|
||||
builder.append(hours).append(c.hours);
|
||||
int minutes = (int) (seconds / 60) - (hours * 60);
|
||||
if (minutes != 0) {
|
||||
builder.append(" ").append(minutes).append(c.minutes);
|
||||
}
|
||||
int secs = (int) (seconds - ((seconds / 60) * 60));
|
||||
if (secs != 0) {
|
||||
builder.append(" ").append(secs).append(c.SECONDS);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static boolean canShowItem(Player p, ItemStack item, ItemSlot slot, @Nullable Cancellable e) {
|
||||
if(item == null)
|
||||
return false;
|
||||
Storage c = ChatItem.getInstance().getStorage();
|
||||
if (c.permissionEnabled && !p.hasPermission(c.permissionName)) {
|
||||
if (!c.letMessageThrough) {
|
||||
if (e != null)
|
||||
e.setCancelled(true);
|
||||
}
|
||||
if (!c.messageNoPermission.isEmpty() && c.showNoPermissionMessage) {
|
||||
sendIfNeed(p, c.messageNoPermission);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (item.getType().equals(Material.AIR)) {
|
||||
if (slot.isDenyIfNoItem()) {
|
||||
if (e != null)
|
||||
e.setCancelled(true);
|
||||
if (!c.messageDeny.isEmpty())
|
||||
sendIfNeed(p, c.messageDeny);
|
||||
return false;
|
||||
}
|
||||
if (c.handDisabled) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (c.cooldown > 0 && !p.hasPermission("chatitem.ignore-cooldown")) {
|
||||
if (COOLDOWNS.containsKey(p.getUniqueId())) {
|
||||
long start = COOLDOWNS.get(p.getUniqueId());
|
||||
long current = System.currentTimeMillis() / 1000;
|
||||
long elapsed = current - start;
|
||||
if (elapsed >= c.cooldown) {
|
||||
COOLDOWNS.remove(p.getUniqueId());
|
||||
} else {
|
||||
if (!c.letMessageThrough) {
|
||||
if (e != null)
|
||||
e.setCancelled(true);
|
||||
}
|
||||
if (!c.messageCooldown.isEmpty()) {
|
||||
long left = (start + c.cooldown) - current;
|
||||
sendIfNeed(p, c.messageCooldown.replace(LEFT, ChatManager.calculateTime(left)));
|
||||
}
|
||||
ChatItem.debug("Cooldown");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (String ignored : c.ignoredItems) {
|
||||
if (item.getType().name().toLowerCase().contains(ignored.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LAST_INFO_MESSAGE.put(p.getUniqueId(), System.currentTimeMillis()); // prevent showing item then send cooldown error message
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void sendIfNeed(Player p, String msg) {
|
||||
Long time = LAST_INFO_MESSAGE.remove(p.getUniqueId());
|
||||
if (time != null) {
|
||||
long diff = System.currentTimeMillis() - time;
|
||||
if (diff < 100)
|
||||
return; // don't show message
|
||||
}
|
||||
p.sendMessage(msg);
|
||||
LAST_INFO_MESSAGE.put(p.getUniqueId(), System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public static void clear(Player p) {
|
||||
COOLDOWNS.remove(p.getUniqueId());
|
||||
LAST_INFO_MESSAGE.remove(p.getUniqueId());
|
||||
}
|
||||
|
||||
public static void applyCooldown(Player p) {
|
||||
COOLDOWNS.put(p.getUniqueId(), System.currentTimeMillis() / 1000);
|
||||
}
|
||||
|
||||
public static boolean isTestingEnabled() {
|
||||
return inTest != null;
|
||||
}
|
||||
|
||||
public static boolean isTesting(String actual) {
|
||||
return inTest != null && (inTest == "both" || inTest.equalsIgnoreCase(actual));
|
||||
}
|
||||
|
||||
public static void setTesting(String actual) {
|
||||
inTest = actual;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package me.dadus33.chatitem.chatmanager;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import me.dadus33.chatitem.ItemSlot;
|
||||
import me.dadus33.chatitem.utils.ItemUtils;
|
||||
import me.dadus33.chatitem.utils.Version;
|
||||
|
||||
public class HandItem {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static ItemStack getBetterItem(Player p, ItemSlot slot) {
|
||||
switch (slot) {
|
||||
case HAND:
|
||||
if(Version.getVersion().isNewerOrEquals(Version.V1_9)) {
|
||||
ItemStack main = p.getInventory().getItemInMainHand();
|
||||
if(!ItemUtils.isEmpty(main))
|
||||
return main;
|
||||
return p.getInventory().getItemInOffHand();
|
||||
}
|
||||
return p.getItemInHand();
|
||||
case HELMET:
|
||||
return p.getInventory().getHelmet();
|
||||
case CHESTPLATE:
|
||||
return p.getInventory().getChestplate();
|
||||
case LEGGINGS:
|
||||
return p.getInventory().getLeggings();
|
||||
case BOOTS:
|
||||
return p.getInventory().getBoots();
|
||||
case ENDERCHEST:
|
||||
break;
|
||||
case INVENTORY:
|
||||
break;
|
||||
}
|
||||
return null; // should never happen
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.Storage;
|
||||
import me.dadus33.chatitem.chatmanager.ChatManager;
|
||||
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.ReflectionUtils;
|
||||
import me.dadus33.chatitem.utils.Utils;
|
||||
|
||||
public class PacketEditingChatManager extends ChatManager {
|
||||
|
||||
private boolean baseComponentAvailable = true;
|
||||
private final ChatItemPacketManager packetManager;
|
||||
private final ChatPacketManager chatPacketManager;
|
||||
|
||||
public PacketEditingChatManager(ChatItem pl) {
|
||||
packetManager = new ChatItemPacketManager(pl);
|
||||
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);
|
||||
|
||||
PacketManager pm = packetManager.getPacketManager();
|
||||
pm.addHandler(chatPacketManager);
|
||||
Bukkit.getOnlinePlayers().forEach(pm::addPlayer); // add actual online players
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload(ChatItem pl) {
|
||||
PacketManager pm = packetManager.getPacketManager();
|
||||
pm.removeHandler(chatPacketManager);
|
||||
pm.stop();
|
||||
}
|
||||
|
||||
public boolean supportsChatComponentApi() {
|
||||
return baseComponentAvailable;
|
||||
}
|
||||
|
||||
private static String checkPacketSize(String packet, int maxSize) {
|
||||
int size = packet.getBytes().length;
|
||||
while(size > maxSize) {
|
||||
packet = packet.replaceFirst(" ", " ");
|
||||
if(size == packet.getBytes().length)
|
||||
break; // could not fix myself
|
||||
size = packet.getBytes().length;
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
public static Object createSystemChatPacket(String json) throws Exception {
|
||||
json = checkPacketSize(json, 150000);
|
||||
Object packet = internalCreateSystemChatPacket(json);
|
||||
if(packet != null)
|
||||
return packet;
|
||||
packet = internalCreateSystemChatPacket(PacketUtils.ICB_FROM_JSON.invoke(null, json));
|
||||
if(packet != null)
|
||||
return packet;
|
||||
ChatItem.getInstance().getLogger().warning("Can't create a new packet for json " + json);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Object internalCreateSystemChatPacket(Object obj) throws Exception {
|
||||
Class<?> packetClass = PacketUtils.getNmsClass("ClientboundPlayerChatPacket", "network.protocol.game.", "ClientboundSystemChatPacket", "PacketPlayOutChat");
|
||||
Class<?> chatMessageTypeClass = PacketUtils.isClassExist("net.minecraft.network.chat.ChatMessageType") ? PacketUtils.getNmsClass("ChatMessageType", "network.chat.") : null;
|
||||
Constructor<?> betterOne = null;
|
||||
Object[] betterParam = null;
|
||||
for (Constructor<?> cons : packetClass.getDeclaredConstructors()) {
|
||||
if (!cons.isAccessible())
|
||||
cons.setAccessible(true);
|
||||
|
||||
// check for basic method
|
||||
if(obj instanceof String) {
|
||||
if (cons.getParameterCount() == 2 && cons.getParameterTypes()[0].equals(String.class) && cons.getParameterTypes()[1].equals(int.class)) { // "string, int"
|
||||
return cons.newInstance(obj, 1);
|
||||
} else if (cons.getParameterCount() == 2 && cons.getParameterTypes()[0].equals(String.class) && cons.getParameterTypes()[1].equals(boolean.class)) { // "string, boolean"
|
||||
return cons.newInstance(obj, false); // false for no overlay
|
||||
} 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, obj, 1);
|
||||
else if (secondParam.equals(boolean.class)) // "component", "string", "boolean"
|
||||
return cons.newInstance(null, obj, false);
|
||||
}
|
||||
}
|
||||
|
||||
int nbPut = 0;
|
||||
Object[] params = new Object[cons.getParameterCount()];
|
||||
for(int i = 0; i < params.length; i++) {
|
||||
if(cons.getParameterTypes()[i].isAssignableFrom(obj.getClass())) {
|
||||
params[i] = obj;
|
||||
nbPut++;
|
||||
} else if(chatMessageTypeClass != null && cons.getParameterTypes()[i].isAssignableFrom(chatMessageTypeClass)) {
|
||||
params[i] = getChatMessageType();
|
||||
} else if(cons.getParameterTypes()[i].isAssignableFrom(boolean.class)) // need to set primitives
|
||||
params[i] = false;
|
||||
else if(cons.getParameterTypes()[i].isAssignableFrom(int.class)) // need to set primitives
|
||||
params[i] = 0;
|
||||
}
|
||||
if(nbPut == 1) {
|
||||
if((betterOne == null && betterParam == null) || betterParam.length > params.length) {
|
||||
betterOne = cons;
|
||||
betterParam = params;
|
||||
if(params.length == 1) // only what we need
|
||||
break;
|
||||
continue; // check for something better?
|
||||
}
|
||||
} else if(nbPut > 1)
|
||||
ChatItem.getInstance().getLogger().warning("Some constructor seems to have too many " + obj.getClass().getSimpleName() + ". Class: " + packetClass.getSimpleName());
|
||||
}
|
||||
if(betterOne != null && betterParam != null) {
|
||||
try {
|
||||
return betterOne.newInstance(betterParam);
|
||||
} catch (IllegalArgumentException e) {
|
||||
ChatItem.getInstance().getLogger().warning("Failed to create a new packet to send. " + betterOne.getParameterCount() + " (" + Utils.arrayToString(betterOne.getParameterTypes()) + "). Params: " + Utils.arrayToString(betterParam));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Object getChatMessageType() throws Exception {
|
||||
Class<?> c = PacketUtils.getNmsClass("ChatMessageType", "network.chat.");
|
||||
return ReflectionUtils.getMethod(c, c, byte.class).invoke(null, (byte) 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
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.Storage;
|
||||
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.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, String json, Storage c) throws Exception {
|
||||
String message;
|
||||
if (Utils.isBeforeChatJson(p))
|
||||
message = JSONManipulator.getInstance().parseEmpty(json, ChatManager.styleItem(chat.getPlayer(), item, c), ChatManager.getMaxLinesFromItem(p, item), chat.getPlayer());
|
||||
else
|
||||
message = JSONManipulator.getInstance().parse(chat, json, chat.getAction(), ChatManager.styleItem(chat.getPlayer(), item, c));
|
||||
if (message != null) {
|
||||
ChatItem.debug("(v1) Writing message: " + message);
|
||||
writeJson(packet, message);
|
||||
}
|
||||
return packet.getPacket();
|
||||
}
|
||||
|
||||
default Object manageEmpty(Player p, Chat chat, ChatItemPacket packet, String json, Storage c) {
|
||||
String message = JSONManipulator.getInstance().parseEmpty(json, 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 id != "" && Utils.isInteger(id) && Chat.getChat(Integer.parseInt(id)).isPresent();
|
||||
}
|
||||
}
|
||||
}
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
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.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.Storage;
|
||||
import me.dadus33.chatitem.chatmanager.Chat;
|
||||
import me.dadus33.chatitem.chatmanager.ChatAction;
|
||||
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.hook.DiscordSrvSupport;
|
||||
import me.dadus33.chatitem.utils.Messages;
|
||||
import me.dadus33.chatitem.utils.PacketUtils;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
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.ClickEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
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 (Throwable 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;
|
||||
try {
|
||||
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;
|
||||
} catch (JsonParseException e) { // ignore this and just let skip this
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object manageItem(Player p, Chat chat, ChatItemPacket packet, ItemStack item, String json, Storage c) throws Exception {
|
||||
ChatAction action = chat.getAction();
|
||||
if (action.isItem()) {
|
||||
String itemName = ChatManager.getNameOfItem(chat.getPlayer(), item, c);
|
||||
ChatItem.debug("NBT tag: " + PacketUtils.getNbtTag(item));
|
||||
return manage(p, chat, packet, itemName, HoverEvent.showItem(Key.key(item.getType().getKey().getKey()), item.getAmount(), BinaryTagHolder.of(PacketUtils.getNbtTag(item))), null);
|
||||
}
|
||||
return manage(p, chat, packet, Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat", "%cible%", chat.getPlayer().getName()),
|
||||
HoverEvent.showText(Component.text(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", chat.getPlayer().getName()))),
|
||||
ClickEvent.runCommand(action.getCommand()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object manageEmpty(Player p, Chat chat, ChatItemPacket packet, String json, Storage c) {
|
||||
Component builder = Component.text("");
|
||||
c.tooltipHand.forEach(s -> builder.append(Component.text(s)));
|
||||
Player sender = chat.getPlayer();
|
||||
ChatAction action = chat.getAction();
|
||||
if (action.isItem()) {
|
||||
String handName = c.handName.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName());
|
||||
return manage(p, chat, packet, handName, HoverEvent.showText(builder), null);
|
||||
}
|
||||
return manage(p, chat, packet, Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat", "%cible%", chat.getPlayer().getName()),
|
||||
HoverEvent.showText(Component.text(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", chat.getPlayer().getName()))),
|
||||
ClickEvent.runCommand(action.getCommand()));
|
||||
}
|
||||
|
||||
private Object manage(Player p, Chat chat, ChatItemPacket packet, String replacement, HoverEvent<?> hover, ClickEvent click) {
|
||||
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, click, replacement, chat);
|
||||
if(ChatItem.discordSrvSupport && DiscordSrvSupport.isSendingMessage())
|
||||
DiscordSrvSupport.sendChatMessage(p, comp, null);
|
||||
try {
|
||||
((Audience) Audience.class.getDeclaredMethod("audience", Audience.class).invoke(null, p)).sendMessage(comp);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null; // send by manager
|
||||
}
|
||||
|
||||
private Component checkComponent(Component comp, HoverEvent<?> hover, ClickEvent click, 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);
|
||||
TextColor color = tc.color();
|
||||
comp = tc.content(ChatManager.replaceSeparator(chat, tc.content(), itemName)).hoverEvent(hover);
|
||||
if (click != null)
|
||||
comp.clickEvent(click);
|
||||
comp.append(Component.text("").color(color)); // reset color
|
||||
} 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, click, 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, click, itemName, chat));
|
||||
}
|
||||
return comp.children(next);
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
|
||||
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
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.hook.DiscordSrvSupport;
|
||||
import me.dadus33.chatitem.utils.PacketUtils;
|
||||
|
||||
public class ComponentNMSManager implements IComponentManager {
|
||||
|
||||
@Override
|
||||
public boolean hasConditions() {
|
||||
return PacketUtils.COMPONENT_CLASS != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBaseComponentAsJSON(ChatItemPacket packet) {
|
||||
Object chatBaseComp = packet.getContent().getChatComponents().readSafely(0);
|
||||
if (chatBaseComp != null) {
|
||||
try {
|
||||
Object o = PacketUtils.CHAT_SERIALIZER.getMethod("a", PacketUtils.COMPONENT_CLASS).invoke(null, chatBaseComp);
|
||||
if(o != null && o instanceof String && JsonParser.parseString((String) o).isJsonObject()) {
|
||||
return (String) o;
|
||||
}
|
||||
} catch (Exception exc) {
|
||||
exc.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeJson(ChatItemPacket packet, String json) {
|
||||
// Not compatible with that for now
|
||||
if(ChatItem.discordSrvSupport && DiscordSrvSupport.isSendingMessage())
|
||||
ChatItem.debug("(v1 ComponentNMS) Can't send message to discord");
|
||||
// DiscordSrvSupport.sendChatMessage(p, comp, null);
|
||||
try {
|
||||
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
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.PacketUtils;
|
||||
|
||||
public class IChatBaseComponentManager implements IComponentManager {
|
||||
|
||||
private Method serializerGetJson;
|
||||
|
||||
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 {
|
||||
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Arrays;
|
||||
|
||||
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.ContentModifier;
|
||||
import me.dadus33.chatitem.utils.PacketUtils;
|
||||
import me.dadus33.chatitem.utils.ReflectionUtils;
|
||||
|
||||
public class PCMComponentManager implements IComponentManager {
|
||||
|
||||
@Override
|
||||
public boolean hasConditions() {
|
||||
try {
|
||||
for (String cl : Arrays.asList("net.minecraft.network.chat.PlayerChatMessage"))
|
||||
Class.forName(cl);
|
||||
} catch (Exception e) { // can't support this
|
||||
ChatItem.debug("Can't load PCMComponentManager : " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBaseComponentAsJSON(ChatItemPacket packet) {
|
||||
Class<?> pcmClass = PacketUtils.getNmsClass("PlayerChatMessage", "network.chat.");
|
||||
Object pcm = packet.getContent().getSpecificModifier(pcmClass).readSafely(0);
|
||||
if (pcm != null) {
|
||||
try {
|
||||
Object chatBaseComp = ReflectionUtils.getMethod(pcmClass, PacketUtils.COMPONENT_CLASS).invoke(pcm);
|
||||
if(chatBaseComp != null)
|
||||
ChatItem.debug("[PCMManager] Founded " + chatBaseComp.getClass().getSimpleName());
|
||||
return chatBaseComp == null ? null : PacketUtils.CHAT_SERIALIZER.getMethod("a", PacketUtils.COMPONENT_CLASS).invoke(null, chatBaseComp).toString();
|
||||
} catch (Exception exc) {
|
||||
exc.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeJson(ChatItemPacket packet, String json) {
|
||||
try {
|
||||
Object chatComp = PacketUtils.CHAT_SERIALIZER.getMethod("a", String.class).invoke(null, json);
|
||||
Class<?> pcmClass = PacketUtils.getNmsClass("PlayerChatMessage", "network.chat.");
|
||||
ContentModifier<Object> pcmModifier = packet.getContent().getSpecificModifier((Class<Object>) pcmClass);
|
||||
Object pcm = ReflectionUtils.getMethod(pcmClass, pcmClass, PacketUtils.COMPONENT_CLASS).invoke(pcmModifier.readSafely(0), chatComp);
|
||||
for(Constructor<?> cons : packet.getPacket().getClass().getConstructors()) {
|
||||
if(cons.getParameterCount() <= 1)
|
||||
continue;
|
||||
Object[] params = new Object[cons.getParameterCount()];
|
||||
for(int i = 0; i < params.length; i++) {
|
||||
Class<?> cls = cons.getParameterTypes()[i];
|
||||
if(cls.equals(pcmClass)) {
|
||||
params[i] = pcm;
|
||||
} else
|
||||
params[i] = packet.getContent().getSpecificModifier(cls).readSafely(0);
|
||||
}
|
||||
packet.setPacket(cons.newInstance(params));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
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.Storage;
|
||||
import me.dadus33.chatitem.chatmanager.Chat;
|
||||
import me.dadus33.chatitem.chatmanager.ChatAction;
|
||||
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.hook.DiscordSrvSupport;
|
||||
import me.dadus33.chatitem.utils.Messages;
|
||||
import me.dadus33.chatitem.utils.Utils;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
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.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, String json, Storage c) throws Exception {
|
||||
ChatAction action = chat.getAction();
|
||||
if (action.isItem())
|
||||
return manage(p, chat, packet, ChatManager.getNameOfItem(chat.getPlayer(), item, c), Utils.createItemHover(item, p), null);
|
||||
else
|
||||
return manage(p, chat, packet, ChatManager.getNameOfItem(chat.getPlayer(), item, c),
|
||||
Utils.createTextHover(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", chat.getPlayer().getName())),
|
||||
Utils.createRunCommand(action.getCommand()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object manageEmpty(Player p, Chat chat, ChatItemPacket packet, String json, Storage c) {
|
||||
ComponentBuilder builder = new ComponentBuilder("");
|
||||
c.tooltipHand.forEach(s -> builder.append(s));
|
||||
Player sender = chat.getPlayer();
|
||||
HoverEvent hover;
|
||||
ClickEvent click;
|
||||
String rep;
|
||||
ChatAction action = chat.getAction();
|
||||
if (action.isItem()) {
|
||||
hover = Utils.createTextHover(builder.create());
|
||||
rep = c.handName.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName());
|
||||
click = null;
|
||||
} else {
|
||||
hover = Utils.createTextHover(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", chat.getPlayer().getName()));
|
||||
rep = Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat", "%cible%", chat.getPlayer().getName());
|
||||
click = Utils.createRunCommand(action.getCommand());
|
||||
}
|
||||
return manage(p, chat, packet, rep, hover, click);
|
||||
}
|
||||
|
||||
private Object manage(Player p, Chat chat, ChatItemPacket packet, String replacement, HoverEvent hover, ClickEvent click) {
|
||||
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();
|
||||
}
|
||||
ChatItem.debug("[StringComponentManager] Using JSON " + json);
|
||||
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, click, replacement, chat));
|
||||
|
||||
if(ChatItem.discordSrvSupport && DiscordSrvSupport.isSendingMessage())
|
||||
DiscordSrvSupport.sendChatMessage(p, TextComponent.toLegacyText(components), null);
|
||||
try {
|
||||
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(ComponentSerializer.toString(components)));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return packet.getPacket();
|
||||
}
|
||||
|
||||
private void checkComponent(BaseComponent comp, HoverEvent hover, ClickEvent click, String itemName, Chat chat) {
|
||||
if (comp instanceof TextComponent) {
|
||||
TextComponent tc = (TextComponent) comp;
|
||||
if (ChatManager.containsSeparator(tc.getText())) {
|
||||
String oldText = tc.getText();
|
||||
ChatItem.debug("Changing text " + oldText + " to " + itemName + ", extra: " + (tc.getExtra() == null ? "-" : tc.getExtra().size()));
|
||||
tc.setText(ChatManager.replaceSeparator(chat, oldText, itemName));
|
||||
tc.setHoverEvent(hover);
|
||||
if (click != null)
|
||||
tc.setClickEvent(click);
|
||||
} 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, click, itemName, chat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
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.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
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.Chat;
|
||||
import me.dadus33.chatitem.chatmanager.ChatAction;
|
||||
import me.dadus33.chatitem.chatmanager.ChatManager;
|
||||
import me.dadus33.chatitem.utils.Messages;
|
||||
import me.dadus33.chatitem.utils.PacketUtils;
|
||||
import me.dadus33.chatitem.utils.ReflectionUtils;
|
||||
|
||||
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 JsonArray classicTooltip;
|
||||
|
||||
public String parse(Chat chat, String json, ChatAction action, String replacement) throws Exception {
|
||||
JsonObject obj = JsonParser.parseString(json).getAsJsonObject();
|
||||
|
||||
JsonObject wrapper = new JsonObject(); // Create a wrapper object for the whole array
|
||||
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();
|
||||
if (action.isItem()) {
|
||||
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(action.getItem()));
|
||||
} else {
|
||||
hover.addProperty("action", "show_text");
|
||||
|
||||
// Get the JSON representation of the item (well, not really JSON, but rather a
|
||||
// string representation of NBT data)
|
||||
hover.addProperty("value", parseEmpty(json, replacement, Arrays.asList(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", chat.getItemPlayer().getPlayer().getName())), chat.getPlayer()));
|
||||
|
||||
JsonObject click = new JsonObject();
|
||||
click.addProperty("action", "run_command");
|
||||
click.addProperty("value", action.getCommand());
|
||||
wrapper.add("clickEvent", click);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (obj.size() == 1 && obj.has("text")) {
|
||||
wrapper.add("text", obj.get("text"));
|
||||
ChatItem.debug("[JsonManipulator] Parsed quick: " + obj.toString() + ", wrapper: " + wrapper);
|
||||
return ChatManager.replaceSeparator(chat, wrapper.toString(), replacement);
|
||||
}
|
||||
obj.add("extra", parseArray(obj.has("extra") ? obj.getAsJsonArray("extra") : new JsonArray(), wrapper));
|
||||
if (!obj.has("text")) {
|
||||
obj.addProperty("text", "");
|
||||
}
|
||||
ChatItem.debug("Parsed array for item: " + obj.toString() + ", wrapper: " + wrapper);
|
||||
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) {
|
||||
if(ChatManager.containsSeparator(element.getAsString())) {
|
||||
addParsedStringToArray(element.getAsString(), replacer, element, tooltip);
|
||||
} else
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.json;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
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();
|
||||
obj.addProperty("text", old);
|
||||
arr.add(obj);
|
||||
return arr;
|
||||
}
|
||||
boolean startsWithCode = old.startsWith(Character.toString(ChatColor.COLOR_CHAR));
|
||||
JsonArray message = new JsonArray();
|
||||
String[] parts = old.split(Character.toString(ChatColor.COLOR_CHAR));
|
||||
JsonObject next = null; //refers to the object we created before (in time) but next in the message, as we're going from end to start
|
||||
for(int i = parts.length-1; i >= 0; --i){ //We go in reverse order
|
||||
String part = parts[i];
|
||||
|
||||
if(part.isEmpty()){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(i == 0 && !startsWithCode){
|
||||
JsonObject toAdd = new JsonObject();
|
||||
toAdd.addProperty("text", part);
|
||||
message.add(toAdd);
|
||||
break;
|
||||
}
|
||||
|
||||
char code = Character.toLowerCase(part.charAt(0));
|
||||
|
||||
if(!isColorOrStyle(code)){
|
||||
if(next != null){
|
||||
String text = next.get("text").getAsString();
|
||||
text = ChatColor.COLOR_CHAR + part + text;
|
||||
next.addProperty("text", text);
|
||||
}else{
|
||||
JsonObject added = new JsonObject();
|
||||
added.addProperty("text", ChatColor.COLOR_CHAR + part);
|
||||
message.add(added);
|
||||
next = added;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(part.length() == 1){ //If it's just format and no text, we try to format the next element, if it wasn't formatted already (and it's not null)
|
||||
if(next == null){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(isStyle(code)){
|
||||
next.addProperty(getStyleName(code), true);
|
||||
}else{ //it's a color
|
||||
if(isAlreadyColored(next)){
|
||||
continue;
|
||||
}
|
||||
next.addProperty("color", getColorName(code));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//Last possibility that remains is that we have a normal color/format + text situation
|
||||
JsonObject added = new JsonObject();
|
||||
added.addProperty("text", part.substring(1));
|
||||
if(isStyle(code)){
|
||||
added.addProperty(getStyleName(code), true);
|
||||
message.add(added);
|
||||
next = added;
|
||||
continue;
|
||||
}
|
||||
//else it can only be a color
|
||||
added.addProperty("color", getColorName(code));
|
||||
//also try to color the next element if not colored already
|
||||
if(next != null){
|
||||
if(!isAlreadyColored(next)){
|
||||
next.addProperty("color", getColorName(code));
|
||||
}
|
||||
}
|
||||
message.add(added);
|
||||
next = added;
|
||||
}
|
||||
|
||||
int i = message.size()-1;
|
||||
JsonArray orderedMessage = new JsonArray();//This is where we'll store the reverted message (in proper order for being sent to the client)
|
||||
//First we have to copy all elements
|
||||
for(JsonElement el : message){
|
||||
orderedMessage.add(el);
|
||||
}
|
||||
for(JsonElement element : message){
|
||||
JsonObject obj = (JsonObject) element;
|
||||
orderedMessage.set(i, obj); //And then we add the object to the properly ordered array
|
||||
--i;
|
||||
}
|
||||
|
||||
return orderedMessage;
|
||||
}
|
||||
|
||||
private static String getColorName(char code){
|
||||
return ChatColor.getByChar(code).getName().toLowerCase();
|
||||
}
|
||||
|
||||
private static String getStyleName(char code){
|
||||
switch(code){
|
||||
case 'k': return "obfuscated";
|
||||
case 'l': return "bold";
|
||||
case 'm': return "strikethrough";
|
||||
case 'n': return "underlined";
|
||||
case 'o': return "italic";
|
||||
case 'r': return "reset";
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isColorOrStyle(char code){
|
||||
return ChatColor.getByChar(code) != null;
|
||||
}
|
||||
|
||||
private static boolean isStyle(char c){
|
||||
return STYLES.indexOf(c) != -1;
|
||||
}
|
||||
|
||||
private static boolean isAlreadyColored(JsonObject obj){
|
||||
return obj.has("color");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.listeners;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.block.ShulkerBox;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.BlockStateMeta;
|
||||
import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.ItemPlayer;
|
||||
import me.dadus33.chatitem.Storage;
|
||||
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.basecomp.hook.AdventureComponentManager;
|
||||
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.ComponentNMSManager;
|
||||
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.PCMComponentManager;
|
||||
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.utils.ItemUtils;
|
||||
import me.dadus33.chatitem.utils.PacketUtils;
|
||||
import me.dadus33.chatitem.utils.Version;
|
||||
|
||||
public class ChatPacketManager extends PacketHandler {
|
||||
|
||||
private Object lastSentPacket = null;
|
||||
private Method serializerGetJson;
|
||||
private PacketEditingChatManager manager;
|
||||
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)) {
|
||||
serializerGetJson = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (serializerGetJson == null)
|
||||
ChatItem.getInstance().getLogger().warning("Failed to find JSON serializer in class: " + PacketUtils.CHAT_SERIALIZER.getCanonicalName());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
for (IComponentManager getter : Arrays.asList(new StringComponentManager(), new ComponentNMSManager(), new PCMComponentManager())) {
|
||||
tryRegister(getter);
|
||||
}
|
||||
try {
|
||||
Class.forName("net.kyori.adventure.text.Component");
|
||||
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);
|
||||
else
|
||||
ChatItem.debug("Component " + getter.getClass().getSimpleName() + " doesn't answer conditions");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSend(ChatItemPacket e) {
|
||||
if (!e.hasPlayer() || !e.getPacketType().equals(PacketType.Server.CHAT))
|
||||
return;
|
||||
if(ChatManager.isTestingEnabled() && !ChatManager.isTesting("packet"))
|
||||
return;
|
||||
if (lastSentPacket != null && lastSentPacket == e.getPacket())
|
||||
return; // prevent infinite loop
|
||||
ChatItem.debug("Checking: " + e.getPacket().getClass().getSimpleName() + " to " + e.getPlayername());
|
||||
PacketContent packet = e.getContent();
|
||||
Version version = Version.getVersion();
|
||||
String json = "{}";
|
||||
IComponentManager choosedGetter = null;
|
||||
if (version.isNewerOrEquals(Version.V1_19)) {
|
||||
/*if (packet.getIntegers().readSafely(0, 0) > 1) { // not parsed chat message type
|
||||
ChatItem.debug("Invalid int: " + packet.getIntegers().read(0));
|
||||
return;
|
||||
}*/
|
||||
choosedGetter = new 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
|
||||
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) {
|
||||
json = ChatManager.fixSeparator(tmpJson);
|
||||
choosedGetter = getters;
|
||||
if (ChatManager.containsSeparator(json))
|
||||
break; // be sure it's valid one
|
||||
} else
|
||||
ChatItem.debug("Null JSON for manager " + getters.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
if (json == null || choosedGetter == null) {
|
||||
ChatItem.debug("Can't find valid json getter or json itself");
|
||||
ChatItem.debug("String: " + packet.getStrings().getContent());
|
||||
PacketUtils.printPacketToDebug(e.getPacket());
|
||||
return; // can't find something
|
||||
}
|
||||
if (!ChatManager.containsSeparator(json)) // if the message doesn't contain the BELL separator
|
||||
return;
|
||||
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();
|
||||
if (getStorage().cooldown > 0 && !itemPlayer.hasPermission("chatitem.ignore-cooldown"))
|
||||
ChatManager.applyCooldown(itemPlayer);
|
||||
IComponentManager getter = choosedGetter;
|
||||
String fjson = json;
|
||||
ChatItem.debug("Final json used: " + fjson);
|
||||
e.setCancelled(true); // We cancel the packet as we're going to resends it anyways
|
||||
CompletableFuture.runAsync(() -> {
|
||||
Player p = e.getPlayer();
|
||||
String message = null;
|
||||
try {
|
||||
ItemStack item = ChatManager.getUsableItem(itemPlayer, chat.getSlot());
|
||||
if (!ItemUtils.isEmpty(item)) {
|
||||
ItemStack copy = item.clone();
|
||||
|
||||
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().tooltipBuggedClient;
|
||||
else if (act.equalsIgnoreCase("item"))
|
||||
tooltip = ChatManager.getMaxLinesFromItem(p, copy);
|
||||
else if (act.equalsIgnoreCase("show_both")) {
|
||||
tooltip = ChatManager.getMaxLinesFromItem(p, copy);
|
||||
tooltip.addAll(getStorage().tooltipBuggedClient);
|
||||
} else
|
||||
tooltip = new ArrayList<>();
|
||||
message = JSONManipulator.getInstance().parseEmpty(getter.getBaseComponentAsJSON(e), ChatManager.styleItem(p, copy, getStorage()), tooltip, chat.getPlayer());
|
||||
if(message != null) {
|
||||
getter.writeJson(e, message);
|
||||
}
|
||||
lastSentPacket = e.getPacket();
|
||||
}
|
||||
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()) {
|
||||
ItemUtils.stripData(itemInv);
|
||||
}
|
||||
bsm.setBlockState(sb);
|
||||
}
|
||||
copy.setItemMeta(bsm);
|
||||
}
|
||||
}
|
||||
lastSentPacket = getter.manageItem(p, chat, e, item, fjson, getStorage());
|
||||
} else {
|
||||
if (!getStorage().handDisabled) {
|
||||
lastSentPacket = getter.manageEmpty(p, chat, e, fjson, getStorage());
|
||||
}
|
||||
}
|
||||
if (lastSentPacket == null) // maybe sent by the manager directly
|
||||
ChatItem.debug("(v1) No packet to sent with manager " + getter.getClass().getName());
|
||||
else
|
||||
PacketUtils.sendPacket(p, lastSentPacket);
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Storage getStorage() {
|
||||
return manager.getStorage();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.packets;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ChatItemPacket {
|
||||
|
||||
protected final Player player;
|
||||
protected Object packet;
|
||||
protected PacketType type;
|
||||
protected boolean cancel = false;
|
||||
|
||||
public ChatItemPacket(PacketType type, Object packet, Player player) {
|
||||
this.player = player;
|
||||
this.packet = packet;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public boolean hasPlayer() {
|
||||
return player != null;
|
||||
}
|
||||
|
||||
public String getPlayername() {
|
||||
return getPlayer().getName();
|
||||
}
|
||||
|
||||
public Object getPacket() {
|
||||
return packet;
|
||||
}
|
||||
|
||||
public void setPacket(Object packet) {
|
||||
this.packet = packet;
|
||||
}
|
||||
|
||||
public String getPacketName() {
|
||||
return packet.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
public PacketType getPacketType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
return cancel;
|
||||
}
|
||||
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancel = cancel;
|
||||
}
|
||||
|
||||
public PacketContent getContent() {
|
||||
return new PacketContent(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.packets;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.protocollib.ProtocollibPacketManager;
|
||||
|
||||
public class ChatItemPacketManager {
|
||||
|
||||
private PacketManager packetManager;
|
||||
|
||||
public ChatItemPacketManager(ChatItem pl) {
|
||||
Plugin protocolLibPlugin = Bukkit.getPluginManager().getPlugin("ProtocolLib");
|
||||
if (protocolLibPlugin != null) {
|
||||
if(checkProtocollibConditions()) {
|
||||
pl.getLogger().info("The plugin ProtocolLib has been detected. Loading Protocollib support ...");
|
||||
packetManager = new ProtocollibPacketManager(pl);
|
||||
} else {
|
||||
pl.getLogger().warning("The plugin ProtocolLib has been detected but you have an old or too new version, so we cannot use it.");
|
||||
pl.getLogger().warning("Fallback to default Packet system ...");
|
||||
packetManager = new CustomPacketManager(pl);
|
||||
}
|
||||
} else {
|
||||
pl.getLogger().info("Loading own packet system.");
|
||||
packetManager = new CustomPacketManager(pl);
|
||||
}
|
||||
}
|
||||
|
||||
public PacketManager getPacketManager() {
|
||||
return packetManager;
|
||||
}
|
||||
|
||||
private boolean checkProtocollibConditions() {
|
||||
for(String searchedClass : Arrays.asList("com.comphenix.protocol.injector.server.TemporaryPlayer", "com.comphenix.protocol.injector.temporary.TemporaryPlayer")) { // class since 4.4.0 until 4.8.0, then the new one
|
||||
try {
|
||||
Class.forName(searchedClass);
|
||||
return true; // class found
|
||||
} catch (ClassNotFoundException e) {}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.packets;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import me.dadus33.chatitem.utils.PacketUtils;
|
||||
|
||||
public class PacketContent {
|
||||
|
||||
|
||||
private final ChatItemPacket packet;
|
||||
private final Object obj;
|
||||
|
||||
/**
|
||||
* Create a PacketContent to easily read and write value in it
|
||||
*
|
||||
* @param packet the Negativity's packet
|
||||
*/
|
||||
public PacketContent(ChatItemPacket packet) {
|
||||
this.packet = packet;
|
||||
this.obj = packet.getPacket();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a PacketContent to easily read and write to the specified object
|
||||
*
|
||||
* @param obj the object that will be read or edit
|
||||
*/
|
||||
public PacketContent(Object obj) {
|
||||
this.packet = null;
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
public ChatItemPacket getPacket() {
|
||||
return packet;
|
||||
}
|
||||
|
||||
public <T> ContentModifier<T> getSpecificModifier(T type){
|
||||
return new ContentModifier<T>(obj, type.getClass());
|
||||
}
|
||||
|
||||
public <T> ContentModifier<T> getSpecificModifier(Class<T> clazz){
|
||||
return new ContentModifier<T>(obj, clazz);
|
||||
}
|
||||
|
||||
public ContentModifier<String> getStrings(){
|
||||
return new ContentModifier<String>(obj, String.class);
|
||||
}
|
||||
|
||||
public ContentModifier<Byte> getBytes(){
|
||||
return new ContentModifier<Byte>(obj, byte.class);
|
||||
}
|
||||
|
||||
public ContentModifier<Boolean> getBooleans(){
|
||||
return new ContentModifier<Boolean>(obj, boolean.class);
|
||||
}
|
||||
|
||||
public ContentModifier<Integer> getIntegers(){
|
||||
return new ContentModifier<Integer>(obj, int.class);
|
||||
}
|
||||
|
||||
public ContentModifier<byte[]> getByteArrays(){
|
||||
return new ContentModifier<byte[]>(obj, byte[].class);
|
||||
}
|
||||
|
||||
public ContentModifier<Object> getChatComponents() {
|
||||
return (ContentModifier<Object>) getSpecificModifier(PacketUtils.COMPONENT_CLASS);
|
||||
}
|
||||
|
||||
public static class ContentModifier<T> {
|
||||
|
||||
private Object obj;
|
||||
private HashMap<Field, T> content = new HashMap<>();
|
||||
|
||||
public ContentModifier(Object obj, Class<?> clazz) {
|
||||
this.obj = obj;
|
||||
|
||||
for(Field f : obj.getClass().getDeclaredFields()) {
|
||||
try {
|
||||
if(f.getType().isAssignableFrom(clazz)) {
|
||||
f.setAccessible(true);
|
||||
content.put(f, (T) f.get(obj));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if(!obj.getClass().getSuperclass().equals(Object.class)) {
|
||||
for(Field f : obj.getClass().getSuperclass().getDeclaredFields()) {
|
||||
try {
|
||||
if(f.getType().isAssignableFrom(clazz)) {
|
||||
f.setAccessible(true);
|
||||
content.put(f, (T) f.get(obj));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Object getObj() {
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of the Map of content
|
||||
*
|
||||
* @return the number of content
|
||||
*/
|
||||
public int size() {
|
||||
return content.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the field which is named by the given one
|
||||
*
|
||||
* @param fieldName the name of the needed field
|
||||
* @return the value of the field
|
||||
*/
|
||||
public T read(String fieldName) {
|
||||
for(Field field : content.keySet())
|
||||
if(field.getName().equalsIgnoreCase(fieldName))
|
||||
return content.get(field);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the field which is named by the given one
|
||||
*
|
||||
* @param fieldName the name of the needed field
|
||||
* @param defaultValue the returned value if there is no value
|
||||
* @return the value of the field
|
||||
*/
|
||||
public T read(String fieldName, T defaultValue) {
|
||||
for(Field field : content.keySet())
|
||||
if(field.getName().equalsIgnoreCase(fieldName))
|
||||
return content.get(field);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the specified value.
|
||||
*
|
||||
* @param i the number of the value to get getted. Start at 0.
|
||||
* @return the requested value.
|
||||
*
|
||||
* @throws NoSuchElementException if the value doesn't exist
|
||||
*/
|
||||
public T read(int i) {
|
||||
return content.values().stream().filter(Objects::nonNull).collect(Collectors.toList()).get(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the specified value.
|
||||
*
|
||||
* @param i the number of the value to get getted. Start at 0.
|
||||
* @return the requested value, or null if it doesn't exist.
|
||||
*/
|
||||
public T readSafely(int i) {
|
||||
return readSafely(i, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the specified value.
|
||||
*
|
||||
* @param i the number of the value to get getted. Start at 0.
|
||||
* @param defaultValue the value which is return if the key doesn't exist
|
||||
* @return the requested value.
|
||||
*/
|
||||
public T readSafely(int i, T defaultValue) {
|
||||
List<T> vals = content.values().stream().filter(Objects::nonNull).collect(Collectors.toList());
|
||||
return vals.size() <= i ? defaultValue : vals.get(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value in the specified object.
|
||||
*
|
||||
* @param i the key of the value to set
|
||||
* @param value the new value which will be set
|
||||
*/
|
||||
public void write(int i, T value) {
|
||||
Field key = content.keySet().toArray(new Field[] {})[i];
|
||||
if(key == null) {
|
||||
new NoSuchFieldException("Not enough value in " + obj.getClass() + ".").printStackTrace();
|
||||
} else {
|
||||
content.put(key, value);
|
||||
try {
|
||||
key.setAccessible(true);
|
||||
key.set(obj, value);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get field which her value
|
||||
*
|
||||
* @return all content
|
||||
*/
|
||||
public HashMap<Field, T> getContent(){
|
||||
return content;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.packets;
|
||||
|
||||
public abstract class PacketHandler {
|
||||
|
||||
public void onReceive(ChatItemPacket packet) {}
|
||||
public void onSend(ChatItemPacket packet) {}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.packets;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public abstract class PacketManager {
|
||||
|
||||
public void addPlayer(Player p) {}
|
||||
public void removePlayer(Player p) {}
|
||||
public abstract void stop();
|
||||
|
||||
private final ArrayList<PacketHandler> handlers = new ArrayList<>();
|
||||
public boolean addHandler(PacketHandler handler) {
|
||||
return !handlers.add(handler);
|
||||
}
|
||||
|
||||
public boolean removeHandler(PacketHandler handler) {
|
||||
return handlers.remove(handler);
|
||||
}
|
||||
|
||||
public void notifyHandlersSent(ChatItemPacket packet) {
|
||||
handlers.forEach((handler) -> handler.onSend(packet));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.packets;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public interface PacketType {
|
||||
|
||||
String name();
|
||||
String getPacketName();
|
||||
String getFullName();
|
||||
List<String> getAlias();
|
||||
|
||||
public static List<PacketType> values() {
|
||||
List<PacketType> list = new ArrayList<>();
|
||||
list.addAll(Arrays.asList(Server.values()));
|
||||
list.addAll(Arrays.asList(Handshake.values()));
|
||||
return list;
|
||||
}
|
||||
|
||||
static final String SERVER_PREFIX = "PacketPlayOut", HANDSHAKE_PREFIX = "PacketHandshaking";
|
||||
|
||||
public static PacketType getType(String packetName) {
|
||||
if(packetName.startsWith(SERVER_PREFIX)) {
|
||||
return getPacketTypeFor(packetName, Server.values(), Server.UNSET);
|
||||
} else if(packetName.startsWith(HANDSHAKE_PREFIX)) {
|
||||
return getPacketTypeFor(packetName, Handshake.values(), Handshake.UNSET);
|
||||
} else {
|
||||
for(PacketType types : values()) {
|
||||
if(types.getFullName().equalsIgnoreCase(packetName) || types.getAlias().contains(packetName))
|
||||
return types;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static PacketType getPacketTypeFor(String packetName, PacketType[] types, PacketType unset) {
|
||||
for(PacketType packet : types)
|
||||
if(packet.getFullName().equalsIgnoreCase(packetName) || packet.getPacketName().equalsIgnoreCase(packetName) || packet.getAlias().contains(packetName))
|
||||
return packet;
|
||||
return unset;
|
||||
}
|
||||
|
||||
public static enum Server implements PacketType {
|
||||
|
||||
CHAT("Chat", "ClientboundPlayerChatPacket", "ClientboundSystemChatPacket"),
|
||||
UNSET("Unset");
|
||||
|
||||
private final String packetName, fullName;
|
||||
private List<String> alias = new ArrayList<>();
|
||||
|
||||
private Server(String packetName, String... alias) {
|
||||
this.packetName = packetName;
|
||||
this.fullName = SERVER_PREFIX + packetName;
|
||||
for(String al : alias)
|
||||
this.alias.add(al);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPacketName() {
|
||||
return packetName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullName() {
|
||||
return fullName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAlias() {
|
||||
return alias;
|
||||
}
|
||||
}
|
||||
|
||||
public static enum Handshake implements PacketType {
|
||||
|
||||
IS_SET_PROTOCOL("InSetProtocol"),
|
||||
UNSET("Unset");
|
||||
|
||||
private final String packetName, fullName;
|
||||
private List<String> alias = new ArrayList<>();
|
||||
|
||||
private Handshake(String packetName, String... alias) {
|
||||
this.packetName = packetName;
|
||||
for(String al : alias)
|
||||
this.alias.add(HANDSHAKE_PREFIX + al);
|
||||
this.fullName = HANDSHAKE_PREFIX + packetName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPacketName() {
|
||||
return packetName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullName() {
|
||||
return fullName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAlias() {
|
||||
return alias;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.packets.custom;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.PacketManager;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.custom.channel.ChannelAbstract;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.custom.channel.INC2Channel;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.custom.channel.INCChannel;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.custom.channel.NMUChannel;
|
||||
import me.dadus33.chatitem.utils.Utils;
|
||||
import me.dadus33.chatitem.utils.Version;
|
||||
|
||||
public class CustomPacketManager extends PacketManager implements Listener {
|
||||
|
||||
private ChannelAbstract channel;
|
||||
private Plugin pl;
|
||||
public HashMap<Object, Integer> protocolVersionPerChannel = new HashMap<>();
|
||||
private boolean isStarted = false;
|
||||
|
||||
public CustomPacketManager(Plugin pl) {
|
||||
this.pl = pl;
|
||||
Version version = Version.getVersion();
|
||||
if (version.isNewerOrEquals(Version.V1_17))
|
||||
channel = new INC2Channel(this);
|
||||
else if (version.equals(Version.V1_7))
|
||||
channel = new NMUChannel(this);
|
||||
else
|
||||
channel = new INCChannel(this);
|
||||
pl.getServer().getPluginManager().registerEvents(this, pl);
|
||||
|
||||
// we wait the start server
|
||||
CompletableFuture.runAsync(() -> {
|
||||
isStarted = true;
|
||||
for(Player p : Utils.getOnlinePlayers())
|
||||
addPlayer(p);
|
||||
});
|
||||
}
|
||||
|
||||
public Plugin getPlugin() {
|
||||
return pl;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent e) {
|
||||
addPlayer(e.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent e) {
|
||||
removePlayer(e.getPlayer());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPlayer(Player p) {
|
||||
if(isStarted)
|
||||
channel.addPlayer(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePlayer(Player p) {
|
||||
channel.removePlayer(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
for(Player player : Utils.getOnlinePlayers())
|
||||
removePlayer(player);
|
||||
if(channel.getAddChannelExecutor() != null)
|
||||
channel.getAddChannelExecutor().shutdownNow();
|
||||
if(channel.getRemoveChannelExecutor() != null)
|
||||
channel.getRemoveChannelExecutor().shutdownNow();
|
||||
}
|
||||
|
||||
public ChatItemPacket onPacketSent(PacketType type, Player sender, Object packet) {
|
||||
if(type == null) {
|
||||
return null;
|
||||
}
|
||||
ChatItemPacket customPacket = new ChatItemPacket(type, packet, sender);
|
||||
notifyHandlersSent(customPacket);
|
||||
return customPacket;
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.packets.custom.channel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.dadus33.chatitem.ItemPlayer;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
|
||||
|
||||
public abstract class ChannelAbstract {
|
||||
|
||||
private ExecutorService addChannelExecutor, removeChannelExecutor;
|
||||
static final String KEY_HANDSHAKE = "packet_handshake_chatitem", KEY_HANDLER_SERVER = "packet_handler", KEY_SERVER = "packet_server_chatitem";
|
||||
|
||||
private CustomPacketManager customPacketManager;
|
||||
private HashSet<UUID> players = new HashSet<>();
|
||||
|
||||
protected ChannelAbstract(CustomPacketManager customPacketManager) {
|
||||
this.customPacketManager = customPacketManager;
|
||||
}
|
||||
|
||||
public CustomPacketManager getPacketManager() {
|
||||
return customPacketManager;
|
||||
}
|
||||
|
||||
public ExecutorService getAddChannelExecutor() {
|
||||
return addChannelExecutor;
|
||||
}
|
||||
|
||||
public ExecutorService getOrCreateAddChannelExecutor() {
|
||||
if(addChannelExecutor == null || addChannelExecutor.isTerminated())
|
||||
addChannelExecutor = Executors.newSingleThreadExecutor();
|
||||
return addChannelExecutor;
|
||||
}
|
||||
|
||||
public ExecutorService getRemoveChannelExecutor() {
|
||||
return removeChannelExecutor;
|
||||
}
|
||||
|
||||
public ExecutorService getOrCreateRemoveChannelExecutor() {
|
||||
if(removeChannelExecutor == null || removeChannelExecutor.isTerminated())
|
||||
removeChannelExecutor = Executors.newSingleThreadExecutor();
|
||||
return removeChannelExecutor;
|
||||
}
|
||||
|
||||
public void addPlayer(Player p) {
|
||||
if(players.add(p.getUniqueId())) {
|
||||
addChannel(p, p.getUniqueId().toString());
|
||||
try {
|
||||
Integer protocol = customPacketManager.protocolVersionPerChannel.remove(getChannel(p));
|
||||
if(protocol != null)
|
||||
ItemPlayer.getPlayer(p).setProtocolVersion(protocol);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removePlayer(Player p) {
|
||||
if(players.remove(p.getUniqueId()))
|
||||
removeChannel(p, p.getUniqueId().toString());
|
||||
}
|
||||
|
||||
public void removeAllPlayers() {
|
||||
new ArrayList<>(players).forEach((uuid) -> {
|
||||
Player p = Bukkit.getPlayer(uuid);
|
||||
if(p != null) // player don't left
|
||||
removeChannel(Bukkit.getPlayer(uuid), uuid.toString());
|
||||
});
|
||||
players.clear();
|
||||
}
|
||||
|
||||
protected abstract void stopPipelines();
|
||||
|
||||
public abstract void addChannel(Player player, String endChannelName);
|
||||
|
||||
public abstract void removeChannel(Player player, String endChannelName);
|
||||
|
||||
public abstract Object getChannel(Player p) throws Exception;
|
||||
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.packets.custom.channel;
|
||||
|
||||
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;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
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 {
|
||||
|
||||
private CustomPacketManager packetManager;
|
||||
private List<ChannelPipeline> pipelines = new ArrayList<>();
|
||||
|
||||
public ChannelInboundHandler(CustomPacketManager packetManager) {
|
||||
this.packetManager = packetManager;
|
||||
}
|
||||
|
||||
public void clean() {
|
||||
pipelines.forEach(ChannelPipeline::removeFirst);
|
||||
pipelines.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
ctx.fireChannelRead(msg);
|
||||
ChannelPipeline pipe = ((Channel) msg).pipeline();
|
||||
pipelines.add(pipe);
|
||||
pipe.addFirst(new ChannelInitializer<Channel>() {
|
||||
@Override
|
||||
protected void initChannel(Channel channel) {
|
||||
try {
|
||||
channel.eventLoop().submit(() -> {
|
||||
try {
|
||||
ChannelHandler interceptor = channel.pipeline().get(ChannelAbstract.KEY_HANDSHAKE);
|
||||
// Inject our packet interceptor
|
||||
if (interceptor == null) {
|
||||
interceptor = new ChannelHandlerHandshakeReceive(channel);
|
||||
channel.pipeline().addBefore("packet_handler", ChannelAbstract.KEY_HANDSHAKE, interceptor);
|
||||
}
|
||||
return interceptor;
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Try again
|
||||
return channel.pipeline().get(ChannelAbstract.KEY_HANDSHAKE);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
packetManager.getPlugin().getLogger().log(Level.SEVERE, "Cannot inject incoming channel " + channel, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public class ChannelHandlerHandshakeReceive extends ChannelInboundHandlerAdapter {
|
||||
|
||||
private Channel channel;
|
||||
|
||||
public ChannelHandlerHandshakeReceive(Channel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object packet) {
|
||||
try {
|
||||
PacketType packetType = PacketType.getType(packet.getClass().getSimpleName());
|
||||
if(packetType != null && packetType == PacketType.Handshake.IS_SET_PROTOCOL) {
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.packets.custom.channel;
|
||||
|
||||
import static me.dadus33.chatitem.utils.PacketUtils.getPlayerConnection;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
|
||||
import me.dadus33.chatitem.utils.PacketUtils;
|
||||
import me.dadus33.chatitem.utils.ReflectionUtils;
|
||||
import me.dadus33.chatitem.utils.Version;
|
||||
|
||||
public class INC2Channel extends ChannelAbstract {
|
||||
|
||||
private final ChannelInboundHandler boundHandler;
|
||||
private ChannelPipeline pipeline;
|
||||
|
||||
public INC2Channel(CustomPacketManager customPacketManager) {
|
||||
super(customPacketManager);
|
||||
boundHandler = new ChannelInboundHandler(customPacketManager);
|
||||
try {
|
||||
Object mcServer = ReflectionUtils.callMethod(PacketUtils.getCraftServer(), Version.getVersion().equals(Version.V1_17) ? "getServer" : "b");
|
||||
Object co = ReflectionUtils.getFirstWith(mcServer, PacketUtils.getNmsClass("MinecraftServer", "server."), PacketUtils.getNmsClass("ServerConnection", "server.network."));
|
||||
((List<ChannelFuture>) ReflectionUtils.getObject(co, "f")).forEach((channelFuture) -> {
|
||||
pipeline = channelFuture.channel().pipeline();
|
||||
pipeline.addFirst(boundHandler);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopPipelines() {
|
||||
pipeline.remove(boundHandler);
|
||||
boundHandler.clean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChannel(final Player player, String endChannelName) {
|
||||
getOrCreateAddChannelExecutor().execute(() -> {
|
||||
if(!player.isOnline())
|
||||
return;
|
||||
try {
|
||||
Channel channel = getChannel(player);
|
||||
// Managing outgoing packet (to the player)
|
||||
channel.pipeline().addAfter(KEY_HANDLER_SERVER, KEY_SERVER + endChannelName, new ChannelHandlerSent(player));
|
||||
} catch (NoSuchElementException e) {
|
||||
// appear when the player's channel isn't accessible because of reload.
|
||||
getPacketManager().getPlugin().getLogger().warning("Please, don't use reload, this can produce some problem. Currently, " + player.getName() + " isn't fully checked because of that. More details: " + e.getMessage() + " (NoSuchElementException)");
|
||||
} catch (IllegalArgumentException e) {
|
||||
if(e.getMessage().contains("Duplicate handler")) {
|
||||
removeChannel(player, endChannelName);
|
||||
addChannel(player, endChannelName);
|
||||
} else
|
||||
getPacketManager().getPlugin().getLogger().severe("Error while loading Packet channel. " + e.getMessage() + ". Please, prefer restart than reload.");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeChannel(Player player, String endChannelName) {
|
||||
getOrCreateRemoveChannelExecutor().execute(() -> {
|
||||
try {
|
||||
final Channel channel = getChannel(player);
|
||||
if(channel.pipeline().get(KEY_SERVER + endChannelName) != null)
|
||||
channel.pipeline().remove(KEY_SERVER + endChannelName);
|
||||
} catch (Exception e) {
|
||||
ChatItem.getInstance().getLogger().warning("Failed to remove channel for " + player.getName() + ". Reason: " + e.getMessage() + " (" + e.getStackTrace()[0].toString() + ")");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Channel getChannel(Player p) throws Exception {
|
||||
Object playerConnection = getPlayerConnection(p);
|
||||
Object networkManager = ReflectionUtils.getFirstWith(playerConnection, PacketUtils.getNmsClass("NetworkManager", "network."));
|
||||
return ReflectionUtils.getFirstWith(networkManager, Channel.class);
|
||||
}
|
||||
|
||||
private class ChannelHandlerSent extends ChannelOutboundHandlerAdapter {
|
||||
|
||||
private final Player owner;
|
||||
|
||||
public ChannelHandlerSent(Player player) {
|
||||
this.owner = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
|
||||
ChatItemPacket nextPacket = getPacketManager().onPacketSent(PacketType.getType(packet.getClass().getSimpleName()), owner, packet);
|
||||
if(nextPacket != null && nextPacket.isCancelled())
|
||||
return;
|
||||
super.write(ctx, nextPacket == null ? packet : nextPacket.getPacket(), promise);
|
||||
}
|
||||
}
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.packets.custom.channel;
|
||||
|
||||
import static me.dadus33.chatitem.utils.PacketUtils.getPlayerConnection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
|
||||
import me.dadus33.chatitem.utils.PacketUtils;
|
||||
import me.dadus33.chatitem.utils.ReflectionUtils;
|
||||
|
||||
public class INCChannel extends ChannelAbstract {
|
||||
|
||||
private final ChannelInboundHandler boundHandler;
|
||||
private ChannelPipeline pipeline;
|
||||
|
||||
public INCChannel(CustomPacketManager customPacketManager) {
|
||||
super(customPacketManager);
|
||||
boundHandler = new ChannelInboundHandler(customPacketManager);
|
||||
getFuturChannel().forEach((channelFuture) -> {
|
||||
pipeline = channelFuture.channel().pipeline();
|
||||
pipeline.addFirst(boundHandler);
|
||||
});
|
||||
}
|
||||
|
||||
public List<ChannelFuture> getFuturChannel() {
|
||||
try {
|
||||
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."));
|
||||
try {
|
||||
return (List<ChannelFuture>) ReflectionUtils.getPrivateField(co, "g");
|
||||
} catch (NoSuchFieldException e) {
|
||||
return (List<ChannelFuture>) ReflectionUtils.getPrivateField(co, "listeningChannels");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopPipelines() {
|
||||
pipeline.remove(boundHandler);
|
||||
boundHandler.clean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChannel(final Player player, String endChannelName) {
|
||||
getOrCreateAddChannelExecutor().execute(() -> {
|
||||
if(!player.isOnline())
|
||||
return;
|
||||
try {
|
||||
Channel channel = getChannel(player);
|
||||
// Managing outgoing packet (to the player)
|
||||
channel.pipeline().addAfter(KEY_HANDLER_SERVER, KEY_SERVER + endChannelName, new ChannelHandlerSent(player));
|
||||
} catch (NoSuchElementException e) {
|
||||
// appear when the player's channel isn't accessible because of reload.
|
||||
getPacketManager().getPlugin().getLogger().warning("Please, don't use reload, this can produce some problem. Currently, " + player.getName() + " isn't fully checked because of that. More details: " + e.getMessage() + " (NoSuchElementException)");
|
||||
} catch (IllegalArgumentException e) {
|
||||
if(e.getMessage().contains("Duplicate handler")) {
|
||||
removeChannel(player, endChannelName);
|
||||
addChannel(player, endChannelName);
|
||||
} else
|
||||
getPacketManager().getPlugin().getLogger().severe("Error while loading Packet channel. " + e.getMessage() + ". Please, prefer restart than reload.");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeChannel(Player player, String endChannelName) {
|
||||
getOrCreateRemoveChannelExecutor().execute(() -> {
|
||||
try {
|
||||
final Channel channel = getChannel(player);
|
||||
|
||||
if(channel.pipeline().get(KEY_SERVER + endChannelName) != null)
|
||||
channel.pipeline().remove(KEY_SERVER + endChannelName);
|
||||
} catch (Exception e) {
|
||||
ChatItem.getInstance().getLogger().warning("Failed to remove channel for " + player.getName() + ". Reason: " + e.getMessage() + " (" + e.getStackTrace()[0].toString() + ")");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Channel getChannel(Player p) throws Exception {
|
||||
Object playerConnection = getPlayerConnection(p);
|
||||
Object networkManager = playerConnection.getClass().getField("networkManager").get(playerConnection);
|
||||
return new PacketContent(networkManager).getSpecificModifier(Channel.class).readSafely(0);//(Channel) networkManager.getClass().getDeclaredField("channel").get(networkManager);
|
||||
}
|
||||
|
||||
private class ChannelHandlerSent extends ChannelOutboundHandlerAdapter {
|
||||
|
||||
private final Player owner;
|
||||
|
||||
public ChannelHandlerSent(Player player) {
|
||||
this.owner = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
|
||||
ChatItemPacket nextPacket = getPacketManager().onPacketSent(PacketType.getType(packet.getClass().getSimpleName()), owner, packet);
|
||||
if(nextPacket != null && nextPacket.isCancelled())
|
||||
return;
|
||||
super.write(ctx, nextPacket == null ? packet : nextPacket.getPacket(), promise);
|
||||
}
|
||||
}
|
||||
}
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.packets.custom.channel;
|
||||
|
||||
import static me.dadus33.chatitem.utils.PacketUtils.getPlayerConnection;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
|
||||
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
|
||||
import me.dadus33.chatitem.utils.PacketUtils;
|
||||
import me.dadus33.chatitem.utils.ReflectionUtils;
|
||||
import net.minecraft.util.io.netty.channel.Channel;
|
||||
import net.minecraft.util.io.netty.channel.ChannelFuture;
|
||||
import net.minecraft.util.io.netty.channel.ChannelHandler;
|
||||
import net.minecraft.util.io.netty.channel.ChannelHandlerContext;
|
||||
import net.minecraft.util.io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import net.minecraft.util.io.netty.channel.ChannelInitializer;
|
||||
import net.minecraft.util.io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||
import net.minecraft.util.io.netty.channel.ChannelPipeline;
|
||||
import net.minecraft.util.io.netty.channel.ChannelPromise;
|
||||
|
||||
public class NMUChannel extends ChannelAbstract {
|
||||
|
||||
private ChannelInboundHandlerAdapter boundHandler;
|
||||
private ChannelPipeline pipeline;
|
||||
|
||||
public NMUChannel(CustomPacketManager customPacketManager) {
|
||||
super(customPacketManager);
|
||||
try {
|
||||
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."));
|
||||
List<ChannelFuture> g = (List<ChannelFuture>) ReflectionUtils.getObject(co, "g", "e");
|
||||
g.forEach((channelFuture) -> {
|
||||
pipeline = channelFuture.channel().pipeline();
|
||||
pipeline.addFirst(boundHandler = new ChannelInboundHandlerAdapter() {
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
((Channel) msg).pipeline().addFirst(new ChannelInitializer<Channel>() {
|
||||
@Override
|
||||
protected void initChannel(Channel channel) {
|
||||
try {
|
||||
channel.eventLoop().submit(() -> {
|
||||
try {
|
||||
ChannelHandler interceptor = channel.pipeline().get(KEY_HANDSHAKE);
|
||||
// Inject our packet interceptor
|
||||
if (interceptor == null) {
|
||||
interceptor = new ChannelHandlerHandshakeReceive(channel);
|
||||
channel.pipeline().addBefore("packet_handler", KEY_HANDSHAKE, interceptor);
|
||||
}
|
||||
return interceptor;
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Try again
|
||||
return channel.pipeline().get(KEY_HANDSHAKE);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
getPacketManager().getPlugin().getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
ctx.fireChannelRead(msg);
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopPipelines() {
|
||||
pipeline.remove(boundHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChannel(final Player player, String endChannelName) {
|
||||
getOrCreateAddChannelExecutor().execute(() -> {
|
||||
try {
|
||||
Channel channel = getChannel(player);
|
||||
// Managing outgoing packet (to the player)
|
||||
channel.pipeline().addAfter(KEY_HANDLER_SERVER, KEY_SERVER + endChannelName, new ChannelHandlerSent(player));
|
||||
} catch (NoSuchElementException e) {
|
||||
// appear when the player's channel isn't accessible because of reload.
|
||||
getPacketManager().getPlugin().getLogger().warning("Please, don't use reload, this can produce some problem. Currently, " + player.getName() + " isn't fully checked because of that. More details: " + e.getMessage() + " (NoSuchElementException)");
|
||||
} catch (IllegalArgumentException e) {
|
||||
if(e.getMessage().contains("Duplicate")) {
|
||||
removeChannel(player, endChannelName);
|
||||
addChannel(player, endChannelName);
|
||||
} else
|
||||
getPacketManager().getPlugin().getLogger().severe("Error while loading Packet channel. " + e.getMessage() + ". Please, prefer restart than reload.");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeChannel(Player player, String endChannelName) {
|
||||
getOrCreateRemoveChannelExecutor().execute(() -> {
|
||||
try {
|
||||
final Channel channel = getChannel(player);
|
||||
if(channel.pipeline().get(KEY_SERVER + endChannelName) != null)
|
||||
channel.pipeline().remove(KEY_SERVER + endChannelName);
|
||||
} catch (Exception e) {}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Channel getChannel(Player p) throws Exception {
|
||||
Object playerConnection = getPlayerConnection(p);
|
||||
Object networkManager = playerConnection.getClass().getField("networkManager").get(playerConnection);
|
||||
|
||||
for (Field field : networkManager.getClass().getDeclaredFields())
|
||||
if (field.getType().equals(Channel.class)) {
|
||||
field.setAccessible(true);
|
||||
return (Channel) field.get(networkManager);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private class ChannelHandlerSent extends ChannelOutboundHandlerAdapter {
|
||||
|
||||
private final Player owner;
|
||||
|
||||
public ChannelHandlerSent(Player player) {
|
||||
this.owner = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
|
||||
ChatItemPacket nextPacket = getPacketManager().onPacketSent(PacketType.getType(packet.getClass().getSimpleName()), owner, packet);
|
||||
if(nextPacket != null && nextPacket.isCancelled())
|
||||
return;
|
||||
super.write(ctx, nextPacket == null ? packet : nextPacket.getPacket(), promise);
|
||||
}
|
||||
}
|
||||
|
||||
private class ChannelHandlerHandshakeReceive extends ChannelInboundHandlerAdapter {
|
||||
|
||||
private final Channel channel;
|
||||
|
||||
public ChannelHandlerHandshakeReceive(Channel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object packet) {
|
||||
try {
|
||||
PacketType packetType = PacketType.getType(packet.getClass().getSimpleName());
|
||||
if(packetType != null && packetType == PacketType.Handshake.IS_SET_PROTOCOL) {
|
||||
getPacketManager().protocolVersionPerChannel.put(channel, new PacketContent(packet).getIntegers().readSafely(1, 0));
|
||||
}
|
||||
super.channelRead(ctx, packet);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.packets.protocollib;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.comphenix.protocol.PacketType.Play;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.ProtocolManager;
|
||||
import com.comphenix.protocol.events.ListenerPriority;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
|
||||
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;
|
||||
|
||||
public class ProtocollibPacketManager extends PacketManager {
|
||||
|
||||
private final ProtocolManager protocolManager;
|
||||
|
||||
public ProtocollibPacketManager(ChatItem pl) {
|
||||
protocolManager = ProtocolLibrary.getProtocolManager();
|
||||
List<com.comphenix.protocol.PacketType> list = new ArrayList<>();
|
||||
list.add(Play.Server.CHAT);
|
||||
try {
|
||||
list.add((com.comphenix.protocol.PacketType) Play.Server.class.getDeclaredField("SYSTEM_CHAT").get(null));
|
||||
} catch (Exception e) {
|
||||
// ignore because using old version
|
||||
}
|
||||
protocolManager.addPacketListener(new PacketAdapter(pl, ListenerPriority.LOWEST, list) {
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent e) {
|
||||
Player p = e.getPlayer();
|
||||
if (p == null || e.isPlayerTemporary())
|
||||
return;
|
||||
ChatItemPacket packet = onPacketSent(PacketType.getType(e.getPacket().getHandle().getClass().getSimpleName()), p, e.getPacket().getHandle());
|
||||
if(packet == null) {
|
||||
ChatItem.debug("Can't find packet: " + e.getPacket().getHandle().getClass().getName());
|
||||
return;
|
||||
}
|
||||
if(!e.isCancelled())
|
||||
e.setCancelled(packet.isCancelled());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
protocolManager.removePacketListeners(ChatItem.getInstance());
|
||||
}
|
||||
|
||||
public ChatItemPacket onPacketSent(PacketType type, Player sender, Object packet) {
|
||||
if(type == null)
|
||||
return null;
|
||||
ChatItemPacket customPacket = new ChatItemPacket(type, packet, sender);
|
||||
notifyHandlersSent(customPacket);
|
||||
return customPacket;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.utils;
|
||||
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
|
||||
@Deprecated
|
||||
public class Item {
|
||||
private String id;
|
||||
private byte amount;
|
||||
private short data;
|
||||
private CompoundTag tag;
|
||||
|
||||
public CompoundTag getTag(){
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void setTag(CompoundTag newTag){
|
||||
this.tag = newTag;
|
||||
}
|
||||
|
||||
public void setId(String newId){
|
||||
this.id = newId;
|
||||
}
|
||||
|
||||
public void setData(short newData){
|
||||
data = newData;
|
||||
}
|
||||
|
||||
public String getId(){
|
||||
return id;
|
||||
}
|
||||
|
||||
public short getData(){
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setAmount(byte newAmount){
|
||||
this.amount = newAmount;
|
||||
}
|
||||
|
||||
public byte getAmount(){
|
||||
return amount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.utils;
|
||||
|
||||
import static me.dadus33.chatitem.utils.Version.V1_10;
|
||||
import static me.dadus33.chatitem.utils.Version.V1_11;
|
||||
import static me.dadus33.chatitem.utils.Version.V1_8;
|
||||
import static me.dadus33.chatitem.utils.Version.V1_9;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@Deprecated
|
||||
public class ItemRewriter {
|
||||
|
||||
public static String remapIds(int server, int player, ItemStack is) {
|
||||
Item item = new Item();
|
||||
item.setAmount((byte)is.getAmount());
|
||||
//item.setData(is.getDurability());
|
||||
//item.setId(id);
|
||||
//item.setTag(tag);
|
||||
if (areIdsCompatible(server, player)) {
|
||||
return item.getId();
|
||||
}
|
||||
if ((server >= V1_9.MIN_VER && player <= V1_8.MAX_VER) || (player >= V1_9.MIN_VER && server <= V1_8.MAX_VER)) {
|
||||
if ((server >= V1_9.MIN_VER && player <= V1_8.MAX_VER)) {
|
||||
ItemRewriter_1_9_TO_1_8.reversedToClient(item);
|
||||
} else
|
||||
ItemRewriter_1_9_TO_1_8.toClient(item);
|
||||
}
|
||||
if ((server <= V1_10.MAX_VER && player >= V1_11.MIN_VER)
|
||||
|| (player <= V1_10.MAX_VER && server >= V1_11.MIN_VER)) {
|
||||
if (server <= V1_10.MAX_VER && player >= V1_11.MIN_VER) {
|
||||
ItemRewriter_1_11_TO_1_10.toClient(item);
|
||||
} else {
|
||||
ItemRewriter_1_11_TO_1_10.reverseToClient(item);
|
||||
}
|
||||
}
|
||||
return item.getId();
|
||||
}
|
||||
|
||||
public static boolean areIdsCompatible(int version1, int version2) {
|
||||
if ((version1 >= V1_9.MIN_VER && version2 <= V1_8.MAX_VER)
|
||||
|| (version2 >= V1_9.MIN_VER && version1 <= V1_8.MAX_VER)) {
|
||||
return false;
|
||||
}
|
||||
if ((version1 <= V1_10.MAX_VER && version2 >= V1_11.MIN_VER)
|
||||
|| (version1 <= V1_10.MAX_VER && version2 >= V1_11.MIN_VER)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.utils;
|
||||
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
|
||||
|
||||
/**
|
||||
* Thanks to the developers of ViaVersion for this!
|
||||
*/
|
||||
@Deprecated
|
||||
public class ItemRewriter_1_11_TO_1_10 {
|
||||
private static BiMap<String, String> oldToNewNames = HashBiMap.create();
|
||||
|
||||
static {
|
||||
oldToNewNames.put("AreaEffectCloud", "minecraft:area_effect_cloud");
|
||||
oldToNewNames.put("ArmorStand", "minecraft:armor_stand");
|
||||
oldToNewNames.put("Arrow", "minecraft:arrow");
|
||||
oldToNewNames.put("Bat", "minecraft:bat");
|
||||
oldToNewNames.put("Blaze", "minecraft:blaze");
|
||||
oldToNewNames.put("Boat", "minecraft:boat");
|
||||
oldToNewNames.put("CaveSpider", "minecraft:cave_spider");
|
||||
oldToNewNames.put("Chicken", "minecraft:chicken");
|
||||
oldToNewNames.put("Cow", "minecraft:cow");
|
||||
oldToNewNames.put("Creeper", "minecraft:creeper");
|
||||
oldToNewNames.put("Donkey", "minecraft:donkey");
|
||||
oldToNewNames.put("DragonFireball", "minecraft:dragon_fireball");
|
||||
oldToNewNames.put("ElderGuardian", "minecraft:elder_guardian");
|
||||
oldToNewNames.put("EnderCrystal", "minecraft:ender_crystal");
|
||||
oldToNewNames.put("EnderDragon", "minecraft:ender_dragon");
|
||||
oldToNewNames.put("Enderman", "minecraft:enderman");
|
||||
oldToNewNames.put("Endermite", "minecraft:endermite");
|
||||
oldToNewNames.put("EntityHorse", "minecraft:horse");
|
||||
oldToNewNames.put("EyeOfEnderSignal", "minecraft:eye_of_ender_signal");
|
||||
oldToNewNames.put("FallingSand", "minecraft:falling_block");
|
||||
oldToNewNames.put("Fireball", "minecraft:fireball");
|
||||
oldToNewNames.put("FireworksRocketEntity", "minecraft:fireworks_rocket");
|
||||
oldToNewNames.put("Ghast", "minecraft:ghast");
|
||||
oldToNewNames.put("Giant", "minecraft:giant");
|
||||
oldToNewNames.put("Guardian", "minecraft:guardian");
|
||||
oldToNewNames.put("Husk", "minecraft:husk");
|
||||
oldToNewNames.put("Item", "minecraft:item");
|
||||
oldToNewNames.put("ItemFrame", "minecraft:item_frame");
|
||||
oldToNewNames.put("LavaSlime", "minecraft:magma_cube");
|
||||
oldToNewNames.put("LeashKnot", "minecraft:leash_knot");
|
||||
oldToNewNames.put("MinecartChest", "minecraft:chest_minecart");
|
||||
oldToNewNames.put("MinecartCommandBlock", "minecraft:commandblock_minecart");
|
||||
oldToNewNames.put("MinecartFurnace", "minecraft:furnace_minecart");
|
||||
oldToNewNames.put("MinecartHopper", "minecraft:hopper_minecart");
|
||||
oldToNewNames.put("MinecartRideable", "minecraft:minecart");
|
||||
oldToNewNames.put("MinecartSpawner", "minecraft:spawner_minecart");
|
||||
oldToNewNames.put("MinecartTNT", "minecraft:tnt_minecart");
|
||||
oldToNewNames.put("Mule", "minecraft:mule");
|
||||
oldToNewNames.put("MushroomCow", "minecraft:mooshroom");
|
||||
oldToNewNames.put("Ozelot", "minecraft:ocelot");
|
||||
oldToNewNames.put("Painting", "minecraft:painting");
|
||||
oldToNewNames.put("Pig", "minecraft:pig");
|
||||
oldToNewNames.put("PigZombie", "minecraft:zombie_pigman");
|
||||
oldToNewNames.put("PolarBear", "minecraft:polar_bear");
|
||||
oldToNewNames.put("PrimedTnt", "minecraft:tnt");
|
||||
oldToNewNames.put("Rabbit", "minecraft:rabbit");
|
||||
oldToNewNames.put("Sheep", "minecraft:sheep");
|
||||
oldToNewNames.put("Shulker", "minecraft:shulker");
|
||||
oldToNewNames.put("ShulkerBullet", "minecraft:shulker_bullet");
|
||||
oldToNewNames.put("Silverfish", "minecraft:silverfish");
|
||||
oldToNewNames.put("Skeleton", "minecraft:skeleton");
|
||||
oldToNewNames.put("SkeletonHorse", "minecraft:skeleton_horse");
|
||||
oldToNewNames.put("Slime", "minecraft:slime");
|
||||
oldToNewNames.put("SmallFireball", "minecraft:small_fireball");
|
||||
oldToNewNames.put("Snowball", "minecraft:snowball");
|
||||
oldToNewNames.put("SnowMan", "minecraft:snowman");
|
||||
oldToNewNames.put("SpectralArrow", "minecraft:spectral_arrow");
|
||||
oldToNewNames.put("Spider", "minecraft:spider");
|
||||
oldToNewNames.put("Squid", "minecraft:squid");
|
||||
oldToNewNames.put("Stray", "minecraft:stray");
|
||||
oldToNewNames.put("ThrownEgg", "minecraft:egg");
|
||||
oldToNewNames.put("ThrownEnderpearl", "minecraft:ender_pearl");
|
||||
oldToNewNames.put("ThrownExpBottle", "minecraft:xp_bottle");
|
||||
oldToNewNames.put("ThrownPotion", "minecraft:potion");
|
||||
oldToNewNames.put("Villager", "minecraft:villager");
|
||||
oldToNewNames.put("VillagerGolem", "minecraft:villager_golem");
|
||||
oldToNewNames.put("Witch", "minecraft:witch");
|
||||
oldToNewNames.put("WitherBoss", "minecraft:wither");
|
||||
oldToNewNames.put("WitherSkeleton", "minecraft:wither_skeleton");
|
||||
oldToNewNames.put("WitherSkull", "minecraft:wither_skull");
|
||||
oldToNewNames.put("Wolf", "minecraft:wolf");
|
||||
oldToNewNames.put("XPOrb", "minecraft:xp_orb");
|
||||
oldToNewNames.put("Zombie", "minecraft:zombie");
|
||||
oldToNewNames.put("ZombieHorse", "minecraft:zombie_horse");
|
||||
oldToNewNames.put("ZombieVillager", "minecraft:zombie_villager");
|
||||
}
|
||||
|
||||
static void toClient(Item item) {
|
||||
if (hasEntityTag(item)) {
|
||||
CompoundTag entityTag = item.getTag().get("EntityTag");
|
||||
if (entityTag.get("id") instanceof StringTag) {
|
||||
StringTag id = entityTag.get("id");
|
||||
if (oldToNewNames.containsKey(id.getValue())) {
|
||||
id.setValue(oldToNewNames.get(id.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseToClient(Item item) {
|
||||
if (hasEntityTag(item)) {
|
||||
CompoundTag entityTag = item.getTag().get("EntityTag");
|
||||
if (entityTag.get("id") instanceof StringTag) {
|
||||
StringTag id = entityTag.get("id");
|
||||
if (oldToNewNames.containsKey(id.getValue())) {
|
||||
id.setValue(oldToNewNames.get(id.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean hasEntityTag(Item item) {
|
||||
if (item != null && item.getId().equals("minecraft:spawn_egg")) { // Monster Egg
|
||||
CompoundTag tag = item.getTag();
|
||||
if (tag != null && tag.contains("EntityTag") && tag.get("EntityTag") instanceof CompoundTag) {
|
||||
if (((CompoundTag) tag.get("EntityTag")).get("id") instanceof StringTag) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,342 @@
|
||||
package me.dadus33.chatitem.chatmanager.v1.utils;
|
||||
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
/**
|
||||
* Thanks to the developers of ViaVersion for this!
|
||||
*/
|
||||
@Deprecated
|
||||
public class ItemRewriter_1_9_TO_1_8 {
|
||||
|
||||
private static final Map<String, Integer> ENTTIY_NAME_TO_ID = new HashMap<>();
|
||||
private static final Map<Integer, String> ENTTIY_ID_TO_NAME = new HashMap<>();
|
||||
private static final Map<String, Integer> POTION_NAME_TO_ID = new HashMap<>();
|
||||
private static final Map<Integer, String> POTION_ID_TO_NAME = new HashMap<>();
|
||||
|
||||
private static final Map<Integer, Integer> POTION_INDEX = new HashMap<>();
|
||||
|
||||
static {
|
||||
/* Entities */
|
||||
registerEntity(1, "Item");
|
||||
registerEntity(2, "XPOrb");
|
||||
registerEntity(7, "ThrownEgg");
|
||||
registerEntity(8, "LeashKnot");
|
||||
registerEntity(9, "Painting");
|
||||
registerEntity(10, "Arrow");
|
||||
registerEntity(11, "Snowball");
|
||||
registerEntity(12, "Fireball");
|
||||
registerEntity(13, "SmallFireball");
|
||||
registerEntity(14, "ThrownEnderpearl");
|
||||
registerEntity(15, "EyeOfEnderSignal");
|
||||
registerEntity(16, "ThrownPotion");
|
||||
registerEntity(17, "ThrownExpBottle");
|
||||
registerEntity(18, "ItemFrame");
|
||||
registerEntity(19, "WitherSkull");
|
||||
registerEntity(20, "PrimedTnt");
|
||||
registerEntity(21, "FallingSand");
|
||||
registerEntity(22, "FireworksRocketEntity");
|
||||
registerEntity(30, "ArmorStand");
|
||||
registerEntity(40, "MinecartCommandBlock");
|
||||
registerEntity(41, "Boat");
|
||||
registerEntity(42, "MinecartRideable");
|
||||
registerEntity(43, "MinecartChest");
|
||||
registerEntity(44, "MinecartFurnace");
|
||||
registerEntity(45, "MinecartTNT");
|
||||
registerEntity(46, "MinecartHopper");
|
||||
registerEntity(47, "MinecartSpawner");
|
||||
registerEntity(48, "Mob");
|
||||
registerEntity(49, "Monster");
|
||||
registerEntity(50, "Creeper");
|
||||
registerEntity(51, "Skeleton");
|
||||
registerEntity(52, "Spider");
|
||||
registerEntity(53, "Giant");
|
||||
registerEntity(54, "Zombie");
|
||||
registerEntity(55, "Slime");
|
||||
registerEntity(56, "Ghast");
|
||||
registerEntity(57, "PigZombie");
|
||||
registerEntity(58, "Enderman");
|
||||
registerEntity(59, "CaveSpider");
|
||||
registerEntity(60, "Silverfish");
|
||||
registerEntity(61, "Blaze");
|
||||
registerEntity(62, "LavaSlime");
|
||||
registerEntity(63, "EnderDragon");
|
||||
registerEntity(64, "WitherBoss");
|
||||
registerEntity(65, "Bat");
|
||||
registerEntity(66, "Witch");
|
||||
registerEntity(67, "Endermite");
|
||||
registerEntity(68, "Guardian");
|
||||
registerEntity(90, "Pig");
|
||||
registerEntity(91, "Sheep");
|
||||
registerEntity(92, "Cow");
|
||||
registerEntity(93, "Chicken");
|
||||
registerEntity(94, "Squid");
|
||||
registerEntity(95, "Wolf");
|
||||
registerEntity(96, "MushroomCow");
|
||||
registerEntity(97, "SnowMan");
|
||||
registerEntity(98, "Ozelot");
|
||||
registerEntity(99, "VillagerGolem");
|
||||
registerEntity(100, "EntityHorse");
|
||||
registerEntity(101, "Rabbit");
|
||||
registerEntity(120, "Villager");
|
||||
registerEntity(200, "EnderCrystal");
|
||||
|
||||
/* Potions */
|
||||
registerPotion(-1, "empty");
|
||||
registerPotion(0, "water");
|
||||
registerPotion(64, "mundane");
|
||||
registerPotion(32, "thick");
|
||||
registerPotion(16, "awkward");
|
||||
|
||||
registerPotion(8198, "night_vision");
|
||||
registerPotion(8262, "long_night_vision");
|
||||
|
||||
registerPotion(8206, "invisibility");
|
||||
registerPotion(8270, "long_invisibility");
|
||||
|
||||
registerPotion(8203, "leaping");
|
||||
registerPotion(8267, "long_leaping");
|
||||
registerPotion(8235, "strong_leaping");
|
||||
|
||||
registerPotion(8195, "fire_resistance");
|
||||
registerPotion(8259, "long_fire_resistance");
|
||||
|
||||
registerPotion(8194, "swiftness");
|
||||
registerPotion(8258, "long_swiftness");
|
||||
registerPotion(8226, "strong_swiftness");
|
||||
|
||||
registerPotion(8202, "slowness");
|
||||
registerPotion(8266, "long_slowness");
|
||||
|
||||
registerPotion(8205, "water_breathing");
|
||||
registerPotion(8269, "long_water_breathing");
|
||||
|
||||
registerPotion(8261, "healing");
|
||||
registerPotion(8229, "strong_healing");
|
||||
|
||||
registerPotion(8204, "harming");
|
||||
registerPotion(8236, "strong_harming");
|
||||
|
||||
registerPotion(8196, "poison");
|
||||
registerPotion(8260, "long_poison");
|
||||
registerPotion(8228, "strong_poison");
|
||||
|
||||
registerPotion(8193, "regeneration");
|
||||
registerPotion(8257, "long_regeneration");
|
||||
registerPotion(8225, "strong_regeneration");
|
||||
|
||||
registerPotion(8201, "strength");
|
||||
registerPotion(8265, "long_strength");
|
||||
registerPotion(8233, "strong_strength");
|
||||
|
||||
registerPotion(8200, "weakness");
|
||||
registerPotion(8264, "long_weakness");
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void toClient(Item item) {
|
||||
if (item != null) {
|
||||
if (item.getId().equals("minecraft:spawn_egg") && item.getData() != 0) { // Monster Egg
|
||||
CompoundTag tag = item.getTag();
|
||||
if (tag == null) {
|
||||
tag = new CompoundTag("tag");
|
||||
}
|
||||
CompoundTag entityTag = new CompoundTag("EntityTag");
|
||||
if (ENTTIY_ID_TO_NAME.containsKey((int) item.getData())) {
|
||||
StringTag id = new StringTag("id", ENTTIY_ID_TO_NAME.get((int) item.getData()));
|
||||
entityTag.put(id);
|
||||
tag.put(entityTag);
|
||||
}
|
||||
item.setTag(tag);
|
||||
item.setData((short) 0);
|
||||
}
|
||||
if (item.getId().equals("minecraft:potion")) { // Potion
|
||||
CompoundTag tag = item.getTag();
|
||||
if (tag == null) {
|
||||
tag = new CompoundTag("tag");
|
||||
}
|
||||
if (item.getData() >= 16384) {
|
||||
item.setId("minecraft:splash_potion"); // splash id
|
||||
item.setData((short) (item.getData() - 8192));
|
||||
}
|
||||
String name = potionNameFromDamage(item.getData());
|
||||
StringTag potion = new StringTag("Potion", "minecraft:" + name);
|
||||
tag.put(potion);
|
||||
item.setTag(tag);
|
||||
item.setData((short) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void reversedToClient(Item item) {
|
||||
if (item != null) {
|
||||
if (item.getId().equals("minecraft:spawn_egg") && item.getData() == 0) { // Monster Egg
|
||||
CompoundTag tag = item.getTag();
|
||||
int data = 0;
|
||||
if(tag != null) {
|
||||
if (tag.get("EntityTag") instanceof CompoundTag) {
|
||||
CompoundTag entityTag = tag.get("EntityTag");
|
||||
if (entityTag.get("id") instanceof StringTag) {
|
||||
StringTag id = entityTag.get("id");
|
||||
if (ENTTIY_NAME_TO_ID.containsKey(id.getValue()))
|
||||
data = ENTTIY_NAME_TO_ID.get(id.getValue());
|
||||
}
|
||||
tag.remove("EntityTag");
|
||||
}
|
||||
}
|
||||
item.setTag(tag);
|
||||
item.setData((short) data);
|
||||
}
|
||||
if (item.getId().equals("minecraft:potion")) { // Potion
|
||||
CompoundTag tag = item.getTag();
|
||||
int data = 0;
|
||||
if(tag != null) {
|
||||
if (tag.get("Potion") instanceof StringTag) {
|
||||
StringTag potion = tag.get("Potion");
|
||||
String potionName = potion.getValue().replace("minecraft:", "");
|
||||
if (POTION_NAME_TO_ID.containsKey(potionName)) {
|
||||
data = POTION_NAME_TO_ID.get(potionName);
|
||||
}
|
||||
tag.remove("Potion");
|
||||
}
|
||||
}
|
||||
item.setTag(tag);
|
||||
item.setData((short) data);
|
||||
}
|
||||
// Splash potion
|
||||
if (item.getId().equals("minecraft:splash_potion")) {
|
||||
CompoundTag tag = item.getTag();
|
||||
int data = 0;
|
||||
item.setId("minecraft:potion"); // Potion
|
||||
if(tag != null) {
|
||||
if (tag.get("Potion") instanceof StringTag) {
|
||||
StringTag potion = tag.get("Potion");
|
||||
String potionName = potion.getValue().replace("minecraft:", "");
|
||||
if (POTION_NAME_TO_ID.containsKey(potionName)) {
|
||||
data = POTION_NAME_TO_ID.get(potionName) + 8192;
|
||||
}
|
||||
tag.remove("Potion");
|
||||
}
|
||||
}
|
||||
item.setTag(tag);
|
||||
item.setData((short) data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String potionNameFromDamage(short damage) {
|
||||
String cached = POTION_ID_TO_NAME.get((int) damage);
|
||||
if (cached != null) {
|
||||
return cached;
|
||||
}
|
||||
if (damage == 0) {
|
||||
return "water";
|
||||
}
|
||||
|
||||
int effect = damage & 0xF;
|
||||
int name = damage & 0x3F;
|
||||
boolean enhanced = (damage & 0x20) > 0;
|
||||
boolean extended = (damage & 0x40) > 0;
|
||||
|
||||
boolean canEnhance = true;
|
||||
boolean canExtend = true;
|
||||
|
||||
String id;
|
||||
switch (effect) {
|
||||
case 1:
|
||||
id = "regeneration";
|
||||
break;
|
||||
case 2:
|
||||
id = "swiftness";
|
||||
break;
|
||||
case 3:
|
||||
id = "fire_resistance";
|
||||
canEnhance = false;
|
||||
break;
|
||||
case 4:
|
||||
id = "poison";
|
||||
break;
|
||||
case 5:
|
||||
id = "healing";
|
||||
canExtend = false;
|
||||
break;
|
||||
case 6:
|
||||
id = "night_vision";
|
||||
canEnhance = false;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
id = "weakness";
|
||||
canEnhance = false;
|
||||
break;
|
||||
case 9:
|
||||
id = "strength";
|
||||
break;
|
||||
case 10:
|
||||
id = "slowness";
|
||||
canEnhance = false;
|
||||
break;
|
||||
case 11:
|
||||
id = "leaping";
|
||||
break;
|
||||
case 12:
|
||||
id = "harming";
|
||||
canExtend = false;
|
||||
break;
|
||||
case 13:
|
||||
id = "water_breathing";
|
||||
canEnhance = false;
|
||||
break;
|
||||
case 14:
|
||||
id = "invisibility";
|
||||
canEnhance = false;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
canEnhance = false;
|
||||
canExtend = false;
|
||||
switch (name) {
|
||||
case 0:
|
||||
id = "mundane";
|
||||
break;
|
||||
case 16:
|
||||
id = "awkward";
|
||||
break;
|
||||
case 32:
|
||||
id = "thick";
|
||||
break;
|
||||
default:
|
||||
id = "empty";
|
||||
}
|
||||
}
|
||||
|
||||
if (effect > 0) {
|
||||
if (canEnhance && enhanced) {
|
||||
id = "strong_" + id;
|
||||
} else if (canExtend && extended) {
|
||||
id = "long_" + id;
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
private static void registerEntity(Integer id, String name) {
|
||||
ENTTIY_ID_TO_NAME.put(id, name);
|
||||
ENTTIY_NAME_TO_ID.put(name, id);
|
||||
}
|
||||
|
||||
private static void registerPotion(Integer id, String name) {
|
||||
POTION_INDEX.put(id, POTION_ID_TO_NAME.size());
|
||||
POTION_ID_TO_NAME.put(id, name);
|
||||
POTION_NAME_TO_ID.put(name, id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
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 org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.ItemPlayer;
|
||||
import me.dadus33.chatitem.ItemSlot;
|
||||
import me.dadus33.chatitem.Storage;
|
||||
import me.dadus33.chatitem.chatmanager.Chat;
|
||||
import me.dadus33.chatitem.chatmanager.ChatAction;
|
||||
import me.dadus33.chatitem.chatmanager.ChatManager;
|
||||
import me.dadus33.chatitem.hook.DiscordSrvSupport;
|
||||
import me.dadus33.chatitem.playernamer.PlayerNamerManager;
|
||||
import me.dadus33.chatitem.utils.ColorManager;
|
||||
import me.dadus33.chatitem.utils.ItemUtils;
|
||||
import me.dadus33.chatitem.utils.Messages;
|
||||
import me.dadus33.chatitem.utils.PacketUtils;
|
||||
import me.dadus33.chatitem.utils.ReflectionUtils;
|
||||
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.TextComponent;
|
||||
|
||||
public class ChatListener implements Listener {
|
||||
|
||||
private static Method saveMethod;
|
||||
private static boolean shouldUseAppendMethod = false;
|
||||
|
||||
static {
|
||||
try {
|
||||
Class<?> nbtTag = PacketUtils.getNmsClass("NBTTagCompound", "nbt.");
|
||||
Class<?> itemClass = PacketUtils.getNmsClass("ItemStack", "world.item.");
|
||||
for (Method m : itemClass.getDeclaredMethods()) {
|
||||
if (m.getParameterTypes().length == 1) {
|
||||
if (m.getParameterTypes()[0].equals(nbtTag) && m.getReturnType().equals(nbtTag)) {
|
||||
saveMethod = m;
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
ComponentBuilder.class.getDeclaredMethod("append", BaseComponent[].class);
|
||||
shouldUseAppendMethod = true;
|
||||
} catch (Exception e) {
|
||||
shouldUseAppendMethod = false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
Logger log = ChatItem.getInstance().getLogger();
|
||||
String appendMethodMsg = shouldUseAppendMethod ? "Use ComponentBuilder's method." : "Use own ComponentBuilder append method.";
|
||||
if (saveMethod == null)
|
||||
log.info("Failed to find save method. Using default system. " + appendMethodMsg);
|
||||
else
|
||||
log.info("Save method founded: " + saveMethod.getName() + ". " + appendMethodMsg);
|
||||
}
|
||||
|
||||
private ChatListenerChatManager manage;
|
||||
|
||||
public ChatListener(ChatListenerChatManager manage) {
|
||||
this.manage = manage;
|
||||
}
|
||||
|
||||
public Storage getStorage() {
|
||||
return manage.getStorage();
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onChat(AsyncPlayerChatEvent e) {
|
||||
if(ChatManager.isTestingEnabled() && !ChatManager.isTesting("chat"))
|
||||
return;
|
||||
Storage c = getStorage();
|
||||
if (e.isCancelled()) {
|
||||
if (ChatItem.getInstance().getChatManager().size() == 1) { // only chat
|
||||
String msg = e.getMessage().toLowerCase();
|
||||
for(ItemSlot slot : ItemSlot.values()) {
|
||||
for (String rep : slot.getPlaceholders()) {
|
||||
if (msg.contains(rep)) {
|
||||
ChatItem.debug("You choose 'chat' manager but it seems to don't be the good choice. More informations here: https://github.com/dadus33-plugins/ChatItem/wiki");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ChatItem.debug("Chat cancelled for " + e.getPlayer().getName());
|
||||
return;
|
||||
}
|
||||
Player p = e.getPlayer();
|
||||
if(ChatManager.containsSeparator(e.getMessage())) { // fix for v1
|
||||
Chat chat = Chat.getFrom(e.getMessage());
|
||||
if(chat != null)
|
||||
e.setMessage(ChatManager.replaceSeparator(chat, e.getMessage(), chat.getSlot().getPlaceholders().get(0)));
|
||||
}
|
||||
ItemSlot slot = ItemSlot.getItemSlotFromMessage(e.getMessage());
|
||||
if (slot == null) { // if not found
|
||||
ChatItem.debug("(v2) Can't found placeholder in: " + e.getMessage() + " > " + PlayerNamerManager.getPlayerNamer().getName(p));
|
||||
return;
|
||||
}
|
||||
ChatAction action = ChatManager.getChatAction(slot, p);
|
||||
if(action.isItem() && !ChatManager.canShowItem(p, action.getItem(), slot, e))
|
||||
return;
|
||||
e.setCancelled(true);
|
||||
String format = e.getFormat();
|
||||
String defMsg = slot.replacePlaceholdersToSeparator(e.getMessage());
|
||||
if (Utils.countMatches(defMsg, Character.toString(ChatManager.SEPARATOR)) > getStorage().limit) {
|
||||
if (!getStorage().messageLimit.isEmpty())
|
||||
p.sendMessage(getStorage().messageLimit);
|
||||
return;
|
||||
}
|
||||
String msg;
|
||||
if (format.contains("%1$s") || format.contains("%2$s")) {
|
||||
msg = (format.contains("%2$s") ? String.format(format, p.getDisplayName(), defMsg) : String.format(format, p.getDisplayName()));
|
||||
} else {
|
||||
msg = format.replace(e.getMessage(), defMsg);
|
||||
}
|
||||
String itemName = ChatManager.getNameForChatAction(p, action, c);
|
||||
String loggedMessage = msg.replace(ChatManager.SEPARATOR + "", itemName).replace("{name}", p.getName()).replace("{display-name}", p.getDisplayName());
|
||||
Bukkit.getConsoleSender().sendMessage(loggedMessage); // show in log
|
||||
if (ChatItem.discordSrvSupport)
|
||||
DiscordSrvSupport.sendChatMessage(p, defMsg.replace(ChatManager.SEPARATOR + "", itemName).replace("{name}", p.getName()).replace("{display-name}", p.getDisplayName()), e);
|
||||
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, action, msg));
|
||||
if (c.cooldown > 0 && !p.hasPermission("chatitem.ignore-cooldown"))
|
||||
ChatManager.applyCooldown(p);
|
||||
}
|
||||
|
||||
public static void showItem(Player to, Player origin, ChatAction action, String msg) {
|
||||
ComponentBuilder builder = new ComponentBuilder("");
|
||||
ChatColor color = ChatColor.WHITE;
|
||||
String colorCode = "", text = "";
|
||||
boolean waiting = false, removing = false;
|
||||
for (char args : msg.toCharArray()) {
|
||||
if (args == '§') { // begin of color
|
||||
if (colorCode.isEmpty() && !text.isEmpty()) { // text before this char
|
||||
ChatItem.debug("Append '" + text.replace(ChatColor.COLOR_CHAR, '&') + "' (len: " + text.length() + ")");
|
||||
if(text.length() > 2 && text.startsWith("§") && text.substring(2) == ChatColor.stripColor(text)
|
||||
&& color != null && color != ChatColor.WHITE) {
|
||||
text = text.substring(2); // remove some code which should not be here
|
||||
}
|
||||
appendToComponentBuilder(builder, createComponent(to, text, color, action));
|
||||
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;
|
||||
} else if(args == 'x') {
|
||||
if(!colorCode.isEmpty()) {
|
||||
color = ColorManager.getColor(colorCode);
|
||||
colorCode = ""; // clean for previous things
|
||||
}
|
||||
}
|
||||
colorCode += args;
|
||||
} else {
|
||||
waiting = false;
|
||||
if (!colorCode.isEmpty()) {
|
||||
if (colorCode.startsWith("x") && colorCode.length() >= 7) {
|
||||
if (colorCode.length() == 7)
|
||||
color = ColorManager.getColor(colorCode);
|
||||
else {
|
||||
color = ColorManager.getColor(colorCode.substring(0, 7)); // only the hex code
|
||||
ChatItem.debug("Adding color for " + colorCode.substring(7, colorCode.length()) + " (in " + colorCode + ")");
|
||||
text += ColorManager.getColorString(colorCode.substring(7, colorCode.length()));
|
||||
}
|
||||
} else if (colorCode.length() == 1) // if only one color code
|
||||
color = ColorManager.getColor(colorCode);
|
||||
else
|
||||
text += ColorManager.getColorString(colorCode);
|
||||
colorCode = "";
|
||||
}
|
||||
if (args == ChatManager.SEPARATOR) {
|
||||
// here put the item
|
||||
appendToComponentBuilder(builder, fixColorComponent(to, text, color, action));
|
||||
if(action.isItem())
|
||||
addItem(builder, to, origin, action.getItem(), action);
|
||||
else
|
||||
addCommand(builder, to, origin, action.getCommand(), action);
|
||||
text = "";
|
||||
if(ChatManager.containsSeparatorEnd(msg))
|
||||
removing = true;
|
||||
} else if(args == ChatManager.SEPARATOR_END) {
|
||||
removing = false;
|
||||
} else if(!removing) { // not removing content
|
||||
// basic text, not waiting for code after '§'
|
||||
text += args;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!text.isEmpty())
|
||||
appendToComponentBuilder(builder, createComponent(to, text, color, action));
|
||||
to.spigot().sendMessage(builder.create());
|
||||
}
|
||||
|
||||
public static void addItem(ComponentBuilder builder, Player to, Player origin, ItemStack item, ChatAction action) {
|
||||
Storage c = ChatItem.getInstance().getStorage();
|
||||
if (!ItemUtils.isEmpty(item)) {
|
||||
ComponentBuilder itemComponent = new ComponentBuilder("");
|
||||
appendToComponentBuilder(itemComponent, fixColorComponent(to, ChatManager.getNameOfItem(to, item, c), ChatColor.WHITE, action));
|
||||
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 = c.handName;
|
||||
ComponentBuilder handComp = new ComponentBuilder("");
|
||||
ComponentBuilder handTooltip = new ComponentBuilder("");
|
||||
int stay = c.tooltipHand.size();
|
||||
for (String line : c.tooltipHand) {
|
||||
stay--;
|
||||
handTooltip.append(ColorManager.fixColor(line.replace("{name}", origin.getName()).replace("{display-name}", origin.getDisplayName())));
|
||||
if (stay > 0)
|
||||
handTooltip.append("\n");
|
||||
}
|
||||
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("{name}", origin.getName()));
|
||||
appendToComponentBuilder(builder, handComp.create());
|
||||
}
|
||||
}
|
||||
|
||||
public static void addCommand(ComponentBuilder builder, Player to, Player origin, String command, ChatAction action) {
|
||||
ComponentBuilder itemComponent = new ComponentBuilder("");
|
||||
appendToComponentBuilder(itemComponent, fixColorComponent(to, Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat", "%cible%", origin.getName()), ChatColor.WHITE, action));
|
||||
appendToComponentBuilder(builder, itemComponent.create());
|
||||
}
|
||||
|
||||
public static void appendToComponentBuilder(ComponentBuilder builder, BaseComponent[] comps) {
|
||||
if (shouldUseAppendMethod) {
|
||||
try {
|
||||
builder.append(comps);
|
||||
} catch (Exception e) {
|
||||
ChatItem.getInstance().getLogger().severe("This should NEVER append. The ComponentBuilder#append(BaseComponent[]) was found but it's NOT. Using own next time.");
|
||||
shouldUseAppendMethod = false;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
Field currentField = ReflectionUtils.getField(builder, "current");
|
||||
List<BaseComponent> parts = (List<BaseComponent>) ReflectionUtils.getObject(builder, "parts");
|
||||
parts.add(new TextComponent((TextComponent) currentField.get(builder)));
|
||||
parts.addAll(Arrays.asList(comps));
|
||||
currentField.set(builder, new TextComponent(""));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static BaseComponent[] fixColorComponent(Player to, String message, ChatColor color, ChatAction action) {
|
||||
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(to, ColorManager.isHexColor(color) ? ColorManager.removeColorAtBegin(text) : text, color, action));
|
||||
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(to, text, color, action));
|
||||
}
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
private static BaseComponent[] createComponent(Player to, String text, ChatColor color, ChatAction action) {
|
||||
ComponentBuilder littleBuilder = new ComponentBuilder(text);
|
||||
if(color != null && color != ChatColor.RESET) // don't add reset thing
|
||||
littleBuilder.color(color);
|
||||
if (action.isItem())
|
||||
littleBuilder.event(Utils.createItemHover(action.getItem(), to));
|
||||
else {
|
||||
littleBuilder.event(Utils.createTextHover(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover")));
|
||||
littleBuilder.event(Utils.createRunCommand(action.getCommand()));
|
||||
}
|
||||
return littleBuilder.create();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package me.dadus33.chatitem.chatmanager.v2;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.Storage;
|
||||
import me.dadus33.chatitem.chatmanager.ChatManager;
|
||||
|
||||
public class ChatListenerChatManager extends ChatManager {
|
||||
|
||||
private final ChatListener chatListener;
|
||||
private boolean baseComponentAvailable = true;
|
||||
|
||||
public ChatListenerChatManager(ChatItem pl) {
|
||||
chatListener = new ChatListener(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 "ChatListener";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "chat";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(ChatItem pl, Storage s) {
|
||||
super.load(pl, s);
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(chatListener, pl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload(ChatItem pl) {
|
||||
HandlerList.unregisterAll(chatListener);
|
||||
}
|
||||
|
||||
public boolean supportsChatComponentApi(){
|
||||
return baseComponentAvailable;
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -1,16 +1,16 @@
|
||||
package me.dadus33.chatitem.commands;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
|
||||
public class CIReload implements CommandExecutor {
|
||||
public class CIReloadCommand implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
ChatItem.reload(sender);
|
||||
ChatItem.reload(sender);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package me.dadus33.chatitem.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
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.ItemSlot;
|
||||
import me.dadus33.chatitem.Storage;
|
||||
import me.dadus33.chatitem.chatmanager.ChatAction;
|
||||
import me.dadus33.chatitem.chatmanager.ChatManager;
|
||||
import me.dadus33.chatitem.chatmanager.v2.ChatListener;
|
||||
import me.dadus33.chatitem.invsee.InvShower;
|
||||
import me.dadus33.chatitem.listeners.InventoryListener;
|
||||
import me.dadus33.chatitem.utils.Messages;
|
||||
import me.dadus33.chatitem.utils.Utils;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
|
||||
public class ChatItemCommand implements CommandExecutor, TabExecutor {
|
||||
|
||||
private static final List<String> orders = Arrays.asList("packet", "chat", "both");
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
Messages.sendMessage(sender, "only-players");
|
||||
return false;
|
||||
}
|
||||
Player p = (Player) sender;
|
||||
if (args.length == 0) {
|
||||
Messages.sendMessage(p, "chatitem-cmd.help");
|
||||
} else if (args[0].equalsIgnoreCase("admin") && p.hasPermission("chatitem.reload")) {
|
||||
InventoryListener.open(p);
|
||||
} else if (args[0].equalsIgnoreCase("reload") && p.hasPermission("chatitem.reload")) {
|
||||
ChatItem.reload(sender);
|
||||
} else if (args[0].equalsIgnoreCase("show") && ChatItem.getInstance().getStorage().cmdShow) {
|
||||
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, ItemSlot.HAND);
|
||||
ChatListener.showItem(p, cible, new ChatAction(ItemSlot.HAND, item), c.commandFormat.replace("%name%", cible.getName()).replace("%item%", ChatManager.SEPARATOR + ""));
|
||||
} else if (args[0].equalsIgnoreCase("broadcast") && ChatItem.getInstance().getStorage().cmdBroadcast) {
|
||||
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, ItemSlot.HAND);
|
||||
for(Player all : Bukkit.getOnlinePlayers())
|
||||
ChatListener.showItem(all, cible, new ChatAction(ItemSlot.HAND, 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");
|
||||
TextComponent text = new TextComponent(Storage.color(config.getString("begin")));
|
||||
for (String key : config.getConfigurationSection("list").getKeys(false)) {
|
||||
ConfigurationSection linkConfig = config.getConfigurationSection("list." + key);
|
||||
TextComponent linkComp = new TextComponent(Storage.color(linkConfig.getString("message")));
|
||||
String hover = Storage.color(linkConfig.getString("hover"));
|
||||
if (hover != null)
|
||||
linkComp.setHoverEvent(Utils.createTextHover(hover));
|
||||
String link = linkConfig.getString("link");
|
||||
if (link != null)
|
||||
linkComp.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, link));
|
||||
text.addExtra(linkComp);
|
||||
}
|
||||
p.spigot().sendMessage(text);
|
||||
} else if (args[0].equalsIgnoreCase("select") && p.hasPermission("chatitem.reload")) {
|
||||
if(args.length == 1) {
|
||||
p.sendMessage(ChatColor.GRAY + "----------" + ChatColor.GOLD + " ChatItem - Setup " + ChatColor.GRAY + "----------");
|
||||
p.sendMessage(ChatColor.AQUA + "Welcome in the help of setup." + ChatColor.YELLOW + " Please follow step by simply answer to test.");
|
||||
sendCheckSelectMessage(p, orders.get(0));
|
||||
} else {
|
||||
String tested = args[1];
|
||||
if(!orders.contains(tested)) {
|
||||
p.sendMessage(ChatColor.RED + "Unknow test for " + tested + ".");
|
||||
return false;
|
||||
}
|
||||
if(args.length == 2) {
|
||||
p.sendMessage(ChatColor.RED + "Can't find if it works");
|
||||
return false;
|
||||
}
|
||||
if(args[2].equalsIgnoreCase("yes")) {
|
||||
ChatManager.setTesting(null);
|
||||
InventoryListener.setInConfig("manager", tested);
|
||||
p.sendMessage(ChatColor.GREEN + "Perfect ! Updating config ...");
|
||||
ChatItem.reload(p);
|
||||
} else if(args[2].equalsIgnoreCase("no")) {
|
||||
int index = orders.indexOf(tested);
|
||||
if(orders.size() == (index + 1)) {
|
||||
p.sendMessage(ChatColor.RED + "Sad. Sorry but nothing is available. I suggest you to come on discord for more help. Do '/chatitem link' for all links.");
|
||||
ChatManager.setTesting(null);
|
||||
} else {
|
||||
p.sendMessage(ChatColor.RED + "Sad. Checking for next manager ...");
|
||||
sendCheckSelectMessage(p, orders.get(index + 1));
|
||||
}
|
||||
} else {
|
||||
p.sendMessage(ChatColor.RED + "Can't find if it works");
|
||||
}
|
||||
}
|
||||
} else if (args[0].equalsIgnoreCase("seeinv")) {
|
||||
if(args.length == 2 && Utils.isUUID(args[1])) {
|
||||
InvShower inv = InvShower.get(args[1]);
|
||||
if(inv == null) {
|
||||
Messages.sendMessage(p, "seeinv_not_found");
|
||||
} else {
|
||||
inv.open(p);
|
||||
}
|
||||
} // else just ignore
|
||||
} else {
|
||||
Messages.sendMessage(p, "chatitem-cmd.help");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void sendCheckSelectMessage(Player p, String testing) {
|
||||
ChatManager.setTesting(testing);
|
||||
p.chat("Checking for " + testing + ": [i]");
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(ChatItem.getInstance(), () -> {
|
||||
TextComponent text = new TextComponent(ChatColor.GOLD + "Did it worked fine? ");
|
||||
TextComponent agree = new TextComponent(ChatColor.GREEN + "Yes");
|
||||
agree.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/chatitem select " + testing + " yes"));
|
||||
agree.setHoverEvent(Utils.createTextHover(ChatColor.GRAY + "Click to say it worked fine"));
|
||||
text.addExtra(agree);
|
||||
text.addExtra(" ");
|
||||
TextComponent decline = new TextComponent(ChatColor.RED + "No");
|
||||
decline.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/chatitem select " + testing + " no"));
|
||||
decline.setHoverEvent(Utils.createTextHover(ChatColor.GRAY + "Click to say it's not working as expected"));
|
||||
text.addExtra(decline);
|
||||
p.spigot().sendMessage(text);
|
||||
}, 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] arg) {
|
||||
List<String> list = new ArrayList<>();
|
||||
String prefix = arg[arg.length - 1].toLowerCase(Locale.ROOT);
|
||||
if(arg.length <= 2) {
|
||||
if(sender.hasPermission("chatitem.reload")) {
|
||||
for (String s : Arrays.asList("admin", "reload", "select"))
|
||||
if (prefix.isEmpty() || s.startsWith(prefix))
|
||||
list.add(s);
|
||||
}
|
||||
if (ChatItem.getInstance().getStorage().cmdShow && (prefix.isEmpty() || "show".startsWith(prefix)))
|
||||
list.add("show");
|
||||
if (ChatItem.getInstance().getStorage().cmdBroadcast && (prefix.isEmpty() || "broadcast".startsWith(prefix)))
|
||||
list.add("broadcast");
|
||||
for (String s : Arrays.asList("help", "link"))
|
||||
if (prefix.isEmpty() || s.startsWith(prefix))
|
||||
list.add(s);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package me.dadus33.chatitem.filters;
|
||||
|
||||
import me.dadus33.chatitem.utils.Storage;
|
||||
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 java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import static org.apache.logging.log4j.core.Filter.Result.NEUTRAL;
|
||||
|
||||
|
||||
public class Log4jFilter implements Filter {
|
||||
|
||||
private boolean stopped;
|
||||
private final static CopyOnWriteArrayList<String> ls = new CopyOnWriteArrayList<>();
|
||||
public 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());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
stopped = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
stopped = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStarted() {
|
||||
return !this.stopped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStopped() {
|
||||
return this.stopped;
|
||||
}
|
||||
|
||||
private Result checkMessage(String msg){
|
||||
for(String placeholder : c.PLACEHOLDERS){
|
||||
if(msg.contains(placeholder)){
|
||||
ls.add(msg);
|
||||
for(Player p : Bukkit.getOnlinePlayers()){
|
||||
msg = msg.replaceAll("\\p{C}", "");
|
||||
if(msg.endsWith(p.getName()) || msg.lastIndexOf(p.getName())+2+p.getName().length()>=msg.length()){
|
||||
return Result.DENY;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return Result.NEUTRAL;
|
||||
|
||||
}
|
||||
|
||||
public void setStorage(Storage nst){
|
||||
this.c = nst;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package me.dadus33.chatitem.hook;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
|
||||
public class ChatControlSupport {
|
||||
|
||||
public static void init(ChatItem pl) {
|
||||
try {
|
||||
Class<?> clz = Class.forName("org.mineacademy.chatcontrol.settings.Settings$Chat$Grammar");
|
||||
clz.getField("CAPITALIZE").setBoolean(null, false);
|
||||
clz.getField("INSERT_DOT").setBoolean(null, false);
|
||||
pl.getLogger().info("Loaded ChatControl support by disabling 2 options in 'Chat.Grammar' config.");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package me.dadus33.chatitem.hook;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.chatmanager.ChatManager;
|
||||
import me.h1dd3nxn1nja.chatmanager.Main;
|
||||
|
||||
public class ChatManagerSupport {
|
||||
|
||||
public static void init(ChatItem pl) {
|
||||
List<String> whitelist = Main.settings.getConfig().getStringList("Anti_Unicode.Whitelist");
|
||||
whitelist.add(ChatManager.SEPARATOR_STR);
|
||||
whitelist.add(ChatManager.SEPARATOR_END_STR);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package me.dadus33.chatitem.hook;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
|
||||
import github.scarsz.discordsrv.DiscordSRV;
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class DiscordSrvSupport {
|
||||
|
||||
public static boolean isSendingMessage() {
|
||||
return ChatItem.getInstance().getStorage().discordSrvSendMsg;
|
||||
}
|
||||
|
||||
public static void sendChatMessage(Player p, String message, Event e) {
|
||||
DiscordSRV pl = DiscordSRV.getPlugin();
|
||||
if (DiscordSRV.config().getBooleanElse("UseModernPaperChatEvent", false) && pl.isModernChatEventAvailable()) {
|
||||
return;
|
||||
}
|
||||
pl.processChatMessage(p, message, pl.getOptionalChannel("global"), false, e);
|
||||
}
|
||||
|
||||
public static void sendChatMessage(Player p, Component message, Event e) {
|
||||
DiscordSRV pl = DiscordSRV.getPlugin();
|
||||
if (DiscordSRV.config().getBooleanElse("UseModernPaperChatEvent", false) && pl.isModernChatEventAvailable()) {
|
||||
return;
|
||||
}
|
||||
pl.processChatMessage(p, message, pl.getOptionalChannel("global"), false, e);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package me.dadus33.chatitem.hook.ecoenchants;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
|
||||
public class EcoEnchantsSupport {
|
||||
|
||||
private static int supportedVersion = 0;
|
||||
|
||||
public static boolean hasSupport() {
|
||||
return supportedVersion > 0;
|
||||
}
|
||||
|
||||
public static boolean load() {
|
||||
String ver = Bukkit.getPluginManager().getPlugin("EcoEnchants").getDescription().getVersion();
|
||||
if(ver.startsWith("8."))
|
||||
supportedVersion = 8;
|
||||
else if(ver.startsWith("10."))
|
||||
supportedVersion = 10;
|
||||
else if(ver.startsWith("11."))
|
||||
supportedVersion = 11;
|
||||
else if(ver.startsWith("12."))
|
||||
supportedVersion = 12;
|
||||
else {
|
||||
ChatItem.getInstance().getLogger().warning("Failed to find support version for EcoEnchants " + ver);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ItemStack manageItem(ItemStack item) {
|
||||
if(supportedVersion == 8) {
|
||||
List<String> addLore = EcoEnchantsV8Support.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");
|
||||
} else if(supportedVersion >= 10) {
|
||||
EcoEnchantsV10Support.display(item);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package me.dadus33.chatitem.hook.ecoenchants;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.willfp.eco.core.display.DisplayProperties;
|
||||
import com.willfp.ecoenchants.EcoEnchantsPlugin;
|
||||
import com.willfp.ecoenchants.display.EnchantDisplay;
|
||||
|
||||
public class EcoEnchantsV10Support {
|
||||
|
||||
private static EnchantDisplay enchantDisplay;
|
||||
|
||||
public static EnchantDisplay getEnchantDisplay() {
|
||||
if (enchantDisplay == null) {
|
||||
try {
|
||||
enchantDisplay = EnchantDisplay.class.getConstructor(EcoEnchantsPlugin.class).newInstance(Bukkit.getPluginManager().getPlugin("EcoEnchants"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return enchantDisplay;
|
||||
}
|
||||
|
||||
public static void display(ItemStack item) {
|
||||
try {
|
||||
DisplayProperties display = DisplayProperties.class.getDeclaredConstructor(boolean.class, boolean.class, ItemStack.class).newInstance(false, false, item);
|
||||
getEnchantDisplay().display(item, (Player) null, display, new Object[] { false });
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package me.dadus33.chatitem.hook.ecoenchants;
|
||||
|
||||
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 EcoEnchantsV8Support {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package me.dadus33.chatitem.invsee;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
|
||||
public abstract class InvShower {
|
||||
|
||||
private static final HashMap<String, InvShower> INV_SHOWER = new HashMap<>();
|
||||
public static InvShower get(String s) {
|
||||
return INV_SHOWER.get(s);
|
||||
}
|
||||
public static void add(String s, InvShower shower) {
|
||||
INV_SHOWER.put(s, shower);
|
||||
}
|
||||
public static HashMap<String, InvShower> getInvShower() {
|
||||
return INV_SHOWER;
|
||||
}
|
||||
|
||||
static {
|
||||
Bukkit.getScheduler().runTaskTimer(ChatItem.getInstance(), () -> {
|
||||
for(Entry<String, InvShower> entries : new HashMap<>(INV_SHOWER).entrySet())
|
||||
if(entries.getValue().hasExpired())
|
||||
INV_SHOWER.remove(entries.getKey());
|
||||
}, 200, 200);
|
||||
}
|
||||
|
||||
protected final long time;
|
||||
protected final UUID uuid;
|
||||
protected final String name;
|
||||
|
||||
public InvShower(String id, Player cible) {
|
||||
this.time = System.currentTimeMillis() + ChatItem.getInstance().getConfig().getInt("general.other-placeholders." + id + ".time-expire", 1800) * 1000;
|
||||
this.uuid = cible.getUniqueId();
|
||||
this.name = cible.getName();
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public long getTimeExpire() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public boolean hasExpired() {
|
||||
return System.currentTimeMillis() > time || Bukkit.getPlayer(uuid) == null || !Bukkit.getPlayer(uuid).isOnline();
|
||||
}
|
||||
|
||||
public abstract void open(Player p);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package me.dadus33.chatitem.invsee.hook;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import me.dadus33.chatitem.invsee.InvShower;
|
||||
import me.dadus33.chatitem.listeners.holder.CustomInventoryHolder;
|
||||
import me.dadus33.chatitem.utils.ItemUtils;
|
||||
import me.dadus33.chatitem.utils.Messages;
|
||||
|
||||
public class EnderChestShower extends InvShower {
|
||||
|
||||
private final ItemStack[] items;
|
||||
|
||||
public EnderChestShower(Player cible) {
|
||||
super("enderchest", cible);
|
||||
|
||||
Inventory ec = cible.getEnderChest();
|
||||
ItemStack[] tmp = ec.getContents();
|
||||
items = new ItemStack[tmp.length];
|
||||
for(int i = 0; i < ec.getSize(); i++)
|
||||
items[i] = ItemUtils.copyIfExist(tmp[i]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(Player p) {
|
||||
Inventory inv = Bukkit.createInventory(new CustomInventoryHolder(), items.length, Messages.getMessage("enderchest.name", "%cible%", name));
|
||||
|
||||
for(int i = 0; i < items.length; i++)
|
||||
inv.setItem(i, items[i]);
|
||||
|
||||
p.openInventory(inv);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package me.dadus33.chatitem.invsee.hook;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
import me.dadus33.chatitem.invsee.InvShower;
|
||||
import me.dadus33.chatitem.listeners.holder.CustomInventoryHolder;
|
||||
import me.dadus33.chatitem.utils.ItemUtils;
|
||||
import me.dadus33.chatitem.utils.Messages;
|
||||
|
||||
public class PlayerInventoryShower extends InvShower {
|
||||
|
||||
private final HashMap<Integer, ItemStack> items = new HashMap<>();
|
||||
private final int level;
|
||||
|
||||
public PlayerInventoryShower(Player cible) {
|
||||
super("inventory", cible);
|
||||
this.level = cible.getLevel();
|
||||
|
||||
PlayerInventory pi = cible.getInventory();
|
||||
items.put(4, ItemUtils.copyIfExist(pi.getHelmet()));
|
||||
items.put(5, ItemUtils.copyIfExist(pi.getChestplate()));
|
||||
items.put(6, ItemUtils.copyIfExist(pi.getLeggings()));
|
||||
items.put(7, ItemUtils.copyIfExist(pi.getBoots()));
|
||||
|
||||
for(int i = 0; i < pi.getContents().length && i < (54 - 18); i++)
|
||||
items.put(i + 18, ItemUtils.copyIfExist(pi.getContents()[i]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(Player p) {
|
||||
Inventory inv = Bukkit.createInventory(new CustomInventoryHolder(), 54, Messages.getMessage("inventory.name", "%cible%", name));
|
||||
|
||||
for(int i = 0; i < 18; i++)
|
||||
inv.setItem(i, ItemUtils.createItem(ItemUtils.getMaterialWithCompatibility("BROWN_STAINED_GLASS_PANE", "STAINED_GLASS_PANE"), ""));
|
||||
|
||||
inv.setItem(2, new ItemStack(ItemUtils.getMaterialWithCompatibility("EXPERIENCE_BOTTLE", "EXP_BOTTLE"), level == 0 ? 1 : (level >= 64 ? 64 : level)));
|
||||
|
||||
items.forEach(inv::setItem);
|
||||
|
||||
p.openInventory(inv);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package me.dadus33.chatitem.itemnamer;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import me.dadus33.chatitem.Storage;
|
||||
|
||||
public interface INamer {
|
||||
|
||||
/**
|
||||
* Get priority of this namer.<br>
|
||||
* Get first name that is not null, with this order:
|
||||
* - MAJOR
|
||||
*
|
||||
*
|
||||
* @return priority
|
||||
*/
|
||||
Priority getPriority();
|
||||
|
||||
/**
|
||||
* Get the name of the item thanks to this namer.
|
||||
*
|
||||
* @param item the item to get the name
|
||||
* @param storage the actual config
|
||||
* @return the name or null if can't find a name
|
||||
*/
|
||||
String getName(Player p, ItemStack item, Storage storage);
|
||||
|
||||
public enum Priority {
|
||||
MAJOR(4),
|
||||
IMPORTANT(3),
|
||||
MEDIUM(2),
|
||||
SMALL(1),
|
||||
MINOR(0);
|
||||
|
||||
private final int priority;
|
||||
|
||||
Priority(int priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public static List<Priority> getOrderedPriorities() {
|
||||
return Arrays.stream(values()).sorted((p1, p2) -> p2.getPriority() - p1.getPriority()).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package me.dadus33.chatitem.itemnamer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.Storage;
|
||||
import me.dadus33.chatitem.itemnamer.INamer.Priority;
|
||||
import me.dadus33.chatitem.itemnamer.hook.ChatItemTranslationNamer;
|
||||
import me.dadus33.chatitem.itemnamer.hook.DefaultNamer;
|
||||
import me.dadus33.chatitem.itemnamer.hook.ItemDisplayNamer;
|
||||
import me.dadus33.chatitem.itemnamer.hook.LangUtilsNamer;
|
||||
|
||||
public class NamerManager {
|
||||
|
||||
private static final HashMap<Priority, List<INamer>> NAMER_PER_PRIORITY = new HashMap<>();
|
||||
|
||||
public static void load(ChatItem pl) {
|
||||
NAMER_PER_PRIORITY.clear();
|
||||
|
||||
StringJoiner sj = new StringJoiner(", ");
|
||||
PluginManager pm = Bukkit.getPluginManager();
|
||||
if(pm.getPlugin("LangUtils") != null) {
|
||||
addNamer(new LangUtilsNamer());
|
||||
sj.add("LangUtils");
|
||||
}
|
||||
if(sj.length() > 0)
|
||||
pl.getLogger().info("Loaded namer for plugin " + sj.toString() + ".");
|
||||
|
||||
addNamer(new ChatItemTranslationNamer());
|
||||
addNamer(new ItemDisplayNamer());
|
||||
addNamer(new DefaultNamer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add namer according to his {@link INamer#getPriority()}'s value
|
||||
*
|
||||
* @param namer the namer to add
|
||||
*/
|
||||
public static void addNamer(INamer namer) {
|
||||
List<INamer> namers = getOrCreate(namer.getPriority());
|
||||
namers.add(namer);
|
||||
}
|
||||
|
||||
private static List<INamer> getOrCreate(Priority p){
|
||||
return NAMER_PER_PRIORITY.computeIfAbsent(p, (a) -> new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of this item, according to this 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) {
|
||||
for(Priority pr : Priority.getOrderedPriorities()) {
|
||||
List<INamer> allNamers = NAMER_PER_PRIORITY.get(pr);
|
||||
if(allNamers == null || allNamers.isEmpty())
|
||||
continue;
|
||||
for(INamer namer : allNamers) {
|
||||
String tmpName = namer.getName(p, item, storage);
|
||||
if(tmpName != null)
|
||||
return tmpName;
|
||||
}
|
||||
}
|
||||
return null; // this should NEVER append
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package me.dadus33.chatitem.itemnamer.hook;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import me.dadus33.chatitem.Storage;
|
||||
import me.dadus33.chatitem.Translation;
|
||||
import me.dadus33.chatitem.itemnamer.INamer;
|
||||
|
||||
public class ChatItemTranslationNamer implements INamer {
|
||||
|
||||
@Override
|
||||
public Priority getPriority() {
|
||||
return Priority.SMALL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(Player p, ItemStack item, Storage storage) {
|
||||
return Translation.get(item);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package me.dadus33.chatitem.itemnamer.hook;
|
||||
|
||||
import org.apache.commons.lang.WordUtils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import me.dadus33.chatitem.Storage;
|
||||
import me.dadus33.chatitem.itemnamer.INamer;
|
||||
|
||||
public class DefaultNamer implements INamer {
|
||||
|
||||
@Override
|
||||
public Priority getPriority() {
|
||||
return Priority.MINOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(Player p, ItemStack item, Storage storage) {
|
||||
Material m = item.getType();
|
||||
return m.equals(Material.TNT) ? "TNT" : WordUtils.capitalize(m.name().replaceAll("_", " ").toLowerCase());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package me.dadus33.chatitem.itemnamer.hook;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import me.dadus33.chatitem.Storage;
|
||||
import me.dadus33.chatitem.itemnamer.INamer;
|
||||
|
||||
public class ItemDisplayNamer implements INamer {
|
||||
|
||||
@Override
|
||||
public Priority getPriority() {
|
||||
return Priority.MEDIUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(Player p, ItemStack item, Storage storage) {
|
||||
if(item.hasItemMeta() && item.getItemMeta().hasDisplayName()) {
|
||||
String name = item.getItemMeta().getDisplayName();
|
||||
return storage.colorIfColored ? ChatColor.stripColor(name) : name;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package me.dadus33.chatitem.itemnamer.hook;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.meowj.langutils.lang.LanguageHelper;
|
||||
|
||||
import me.dadus33.chatitem.Storage;
|
||||
import me.dadus33.chatitem.itemnamer.INamer;
|
||||
|
||||
public class LangUtilsNamer implements INamer {
|
||||
|
||||
@Override
|
||||
public Priority getPriority() {
|
||||
return Priority.IMPORTANT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(Player p, ItemStack item, Storage storage) {
|
||||
return LanguageHelper.getItemName(item, p);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package me.dadus33.chatitem.json;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
|
||||
public interface JSONManipulator {
|
||||
String parse(String json, String[] replacements, ItemStack item, String repl) throws InvocationTargetException, IllegalAccessException, InstantiationException;
|
||||
}
|
||||
@@ -1,298 +0,0 @@
|
||||
package me.dadus33.chatitem.json;
|
||||
|
||||
|
||||
import com.google.gson.*;
|
||||
import me.dadus33.chatitem.utils.Reflect;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public class JSONManipulatorCurrent implements JSONManipulator{
|
||||
|
||||
private static Class<?> craftItemStackClass = Reflect.getOBCClass("inventory.CraftItemStack");
|
||||
private static Class<?> nmsItemStackClass = Reflect.getNMSClass("ItemStack");
|
||||
private static Method asNMSCopy = Reflect.getMethod(craftItemStackClass, "asNMSCopy", ItemStack.class);
|
||||
private static Class<?> nbtTagCompoundClass = Reflect.getNMSClass("NBTTagCompound");
|
||||
private static Method saveNmsItemStackMethod = Reflect.getMethod(nmsItemStackClass, "save", nbtTagCompoundClass);
|
||||
|
||||
private static String[] replaces;
|
||||
private static String rgx;
|
||||
private static JsonArray toUse;
|
||||
private static JsonParser parser = new JsonParser();
|
||||
|
||||
|
||||
public String parse(String json, String[] replacements, ItemStack item, String repl) throws InvocationTargetException, IllegalAccessException, InstantiationException {
|
||||
JsonObject obj = parser.parse(json).getAsJsonObject();
|
||||
JsonArray array = obj.getAsJsonArray("extra");
|
||||
replaces = replacements;
|
||||
String regex = "";
|
||||
for (int i = 0; i < replacements.length; ++i) {
|
||||
if (replacements.length == 1) {
|
||||
regex = Pattern.quote(replacements[0]);
|
||||
break;
|
||||
}
|
||||
if (i == 0 || i + 1 == replacements.length) {
|
||||
if (i == 0) {
|
||||
regex = "(" + Pattern.quote(replacements[i]);
|
||||
} else {
|
||||
regex = regex.concat("|").concat(Pattern.quote(replacements[i])).concat(")");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
regex = regex.concat("|").concat(Pattern.quote(replacements[i]));
|
||||
}
|
||||
rgx = regex;
|
||||
JsonArray rep = new JsonArray();
|
||||
repl = escapeBackslash(repl);
|
||||
JsonArray use = parser.parse(Translator.toJSON(repl)).getAsJsonArray();
|
||||
|
||||
JsonObject hover = parser.parse("{\"action\":\"show_item\", \"value\": \"\"}").getAsJsonObject();
|
||||
Object nmsStack = asNMSCopy.invoke(null, item);
|
||||
Object tag = nbtTagCompoundClass.newInstance();
|
||||
tag = saveNmsItemStackMethod.invoke(nmsStack, tag);
|
||||
String jsonRep = escapeBackslash(tag.toString());
|
||||
hover.addProperty("value", jsonRep);
|
||||
for (JsonElement ob : use)
|
||||
ob.getAsJsonObject().add("hoverEvent", hover);
|
||||
|
||||
toUse = use;
|
||||
|
||||
for (int i = 0; i < array.size(); ++i) {
|
||||
if (array.get(i).isJsonObject()){
|
||||
JsonObject o = array.get(i).getAsJsonObject();
|
||||
boolean inside = false;
|
||||
for (String replacement : replacements)
|
||||
if (o.toString().contains(replacement)) {
|
||||
if (inside) {
|
||||
break;
|
||||
}
|
||||
inside = true;
|
||||
}
|
||||
JsonElement text = o.get("text");
|
||||
if (text == null) {
|
||||
JsonElement el = o.get("extra");
|
||||
if (el != null) {
|
||||
JsonArray jar = el.getAsJsonArray();
|
||||
jar = parseArray(jar);
|
||||
o.add("extra", jar);
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
if (text.getAsString().isEmpty()) {
|
||||
JsonElement el = o.get("extra");
|
||||
if (el != null) {
|
||||
JsonArray jar = el.getAsJsonArray();
|
||||
jar = parseArray(jar);
|
||||
o.add("extra", jar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String msg = text.getAsString();
|
||||
boolean isLast = false;
|
||||
boolean done = false;
|
||||
boolean fnd;
|
||||
String[] splits;
|
||||
for (String repls : replacements) {
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
isLast = msg.endsWith(repls);
|
||||
if (isLast) {
|
||||
done = true;
|
||||
msg = msg.concat(".");
|
||||
}
|
||||
}
|
||||
splits = msg.split(regex);
|
||||
fnd = splits.length != 1;
|
||||
if (fnd)
|
||||
for (int j = 0; j < splits.length; ++j) {
|
||||
boolean endDot = (j == splits.length - 1) && isLast;
|
||||
if (!splits[j].isEmpty() && !endDot) {
|
||||
String st = o.toString();
|
||||
JsonObject fix = parser.parse(st).getAsJsonObject();
|
||||
fix.addProperty("text", splits[j]);
|
||||
rep.add(fix);
|
||||
}
|
||||
if (j != splits.length - 1) {
|
||||
rep.addAll(use);
|
||||
}
|
||||
}
|
||||
if (!fnd) {
|
||||
rep.add(o);
|
||||
}
|
||||
}else{
|
||||
if(array.get(i).isJsonNull()){
|
||||
continue;
|
||||
}else{
|
||||
if(array.get(i).isJsonArray()){
|
||||
JsonArray jar = parseArray(array.get(i).getAsJsonArray());
|
||||
rep.set(i, jar);
|
||||
}else{
|
||||
|
||||
|
||||
String msg = array.get(i).getAsString();
|
||||
boolean isLast = false;
|
||||
boolean done = false;
|
||||
boolean fnd;
|
||||
String[] splits;
|
||||
for (String repls : replacements) {
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
isLast = msg.endsWith(repls);
|
||||
if (isLast) {
|
||||
done = true;
|
||||
msg = msg.concat(".");
|
||||
}
|
||||
}
|
||||
splits = msg.split(regex);
|
||||
fnd = splits.length != 1;
|
||||
if (fnd)
|
||||
for (int j = 0; j < splits.length; ++j) {
|
||||
boolean endDot = (j == splits.length - 1) && isLast;
|
||||
if (!splits[j].isEmpty() && !endDot) {
|
||||
JsonElement fix = new JsonPrimitive(splits[j]);
|
||||
rep.add(fix);
|
||||
}
|
||||
if (j != splits.length - 1) {
|
||||
rep.addAll(use);
|
||||
}
|
||||
}
|
||||
if (!fnd) {
|
||||
rep.add(array.get(i));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
obj.add("extra", rep);
|
||||
return obj.toString();
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static JsonArray parseArray(JsonArray arr) {
|
||||
JsonArray replacer = new JsonArray();
|
||||
for (int i = 0; i < arr.size(); ++i) {
|
||||
if (arr.get(i).isJsonObject()){
|
||||
JsonObject o = arr.get(i).getAsJsonObject();
|
||||
boolean inside = false;
|
||||
for (String replacement : replaces)
|
||||
if (o.toString().contains(replacement)) {
|
||||
if (inside) {
|
||||
break;
|
||||
}
|
||||
inside = true;
|
||||
}
|
||||
if (!inside) { //the placeholder we're looking for is not inside this element, so we continue searching
|
||||
continue;
|
||||
}
|
||||
JsonElement text = o.get("text");
|
||||
if (text == null) {
|
||||
continue;
|
||||
}
|
||||
if (text.getAsString().isEmpty()) {
|
||||
JsonElement el = o.get("extra");
|
||||
if (el == null) {
|
||||
continue;
|
||||
}
|
||||
JsonArray jar = el.getAsJsonArray();
|
||||
jar = parseArray(jar);
|
||||
o.add("extra", jar);
|
||||
}
|
||||
|
||||
String msg = text.getAsString();
|
||||
boolean isLast = false;
|
||||
boolean done = false;
|
||||
boolean fnd;
|
||||
String[] splits;
|
||||
for (String repls : replaces) {
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
isLast = msg.endsWith(repls);
|
||||
if (isLast) {
|
||||
done = true;
|
||||
msg = msg.concat(".");
|
||||
}
|
||||
}
|
||||
splits = msg.split(rgx);
|
||||
fnd = splits.length != 1;
|
||||
if (fnd)
|
||||
for (int j = 0; j < splits.length; ++j) {
|
||||
boolean endDot = (j == splits.length - 1) && isLast;
|
||||
if (!splits[j].isEmpty() && !endDot) {
|
||||
String st = o.toString();
|
||||
JsonObject fix = parser.parse(st).getAsJsonObject();
|
||||
fix.addProperty("text", splits[j]);
|
||||
replacer.add(fix);
|
||||
}
|
||||
if (j != splits.length - 1) {
|
||||
replacer.addAll(toUse);
|
||||
}
|
||||
}
|
||||
if (!fnd) {
|
||||
replacer.add(o);
|
||||
}
|
||||
}else{
|
||||
if(arr.get(i).isJsonNull()){
|
||||
continue;
|
||||
}else{
|
||||
if(arr.get(i).isJsonArray()){
|
||||
JsonArray jar = parseArray(arr.get(i).getAsJsonArray());
|
||||
replacer.set(i, jar);
|
||||
}else{
|
||||
String msg = arr.get(i).getAsString();
|
||||
boolean isLast = false;
|
||||
boolean done = false;
|
||||
boolean fnd;
|
||||
String[] splits;
|
||||
for (String repls : replaces) {
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
isLast = msg.endsWith(repls);
|
||||
if (isLast) {
|
||||
done = true;
|
||||
msg = msg.concat(".");
|
||||
}
|
||||
}
|
||||
splits = msg.split(rgx);
|
||||
fnd = splits.length != 1;
|
||||
if (fnd)
|
||||
for (int j = 0; j < splits.length; ++j) {
|
||||
boolean endDot = (j == splits.length - 1) && isLast;
|
||||
if (!splits[j].isEmpty() && !endDot) {
|
||||
JsonElement fix = new JsonPrimitive(splits[j]);
|
||||
replacer.add(fix);
|
||||
}
|
||||
if (j != splits.length - 1) {
|
||||
replacer.addAll(toUse);
|
||||
}
|
||||
}
|
||||
if (!fnd) {
|
||||
replacer.add(arr.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return replacer;
|
||||
}
|
||||
|
||||
|
||||
private static String escapeBackslash(String json){
|
||||
json = json.replace("\\", "\\\\");
|
||||
return json;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
package me.dadus33.chatitem.json;
|
||||
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
/*
|
||||
Many thanks to @DarkSeraphim for this!
|
||||
I only modified his work to make it compatible with what I was building.
|
||||
*/
|
||||
public class Translator {
|
||||
private static final StringBuilder BUILDER = new StringBuilder("");
|
||||
private static final StringBuilder STYLE = new StringBuilder();
|
||||
|
||||
static String toJSON(String message) {
|
||||
if (message == null || message.isEmpty())
|
||||
return null;
|
||||
String[] parts = message.split(Character.toString(ChatColor.COLOR_CHAR));
|
||||
boolean first = true;
|
||||
String colour = null;
|
||||
String format = null;
|
||||
BUILDER.setLength(0);
|
||||
BUILDER.append("[");
|
||||
boolean ignoreFirst = !parts[0].isEmpty() && ChatColor.getByChar(parts[0].charAt(0)) != null;
|
||||
for (String part : parts) {
|
||||
if (part.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String newStyle = null;
|
||||
if (!ignoreFirst) {
|
||||
newStyle = getStyle(part.charAt(0));
|
||||
} else {
|
||||
ignoreFirst = false;
|
||||
}
|
||||
|
||||
if (newStyle != null) {
|
||||
part = part.substring(1);
|
||||
if (newStyle.startsWith("\"c"))
|
||||
colour = newStyle;
|
||||
else
|
||||
format = newStyle;
|
||||
}
|
||||
if (!part.isEmpty()) {
|
||||
if (first)
|
||||
first = false;
|
||||
else {
|
||||
BUILDER.append(", ");
|
||||
}
|
||||
BUILDER.append("{");
|
||||
if (colour != null) {
|
||||
BUILDER.append(colour);
|
||||
colour = null;
|
||||
}
|
||||
if (format != null) {
|
||||
BUILDER.append(format);
|
||||
format = null;
|
||||
}
|
||||
BUILDER.append(String.format("\"text\":\"%s\"", part));
|
||||
BUILDER.append("}");
|
||||
}
|
||||
}
|
||||
BUILDER.append("]");
|
||||
return BUILDER.toString();
|
||||
}
|
||||
|
||||
private static String getStyle(char colour) {
|
||||
if (STYLE.length() > 0)
|
||||
STYLE.delete(0, STYLE.length());
|
||||
switch (colour) {
|
||||
case 'k':
|
||||
return "\"obfuscated\": true,";
|
||||
case 'l':
|
||||
return "\"bold\": true,";
|
||||
case 'm':
|
||||
return "\"strikethrough\": true,";
|
||||
case 'n':
|
||||
return "\"underlined\": true,";
|
||||
case 'o':
|
||||
return "\"italic\": true,";
|
||||
case 'r':
|
||||
return "\"reset\": true,";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ChatColor cc = ChatColor.getByChar(colour);
|
||||
if (cc == null)
|
||||
return null;
|
||||
return STYLE.append("\"color\":\"").append(cc.name().toLowerCase()).append("\", ").toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
package me.dadus33.chatitem.listeners;
|
||||
|
||||
import me.dadus33.chatitem.utils.Storage;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.Command;
|
||||
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;
|
||||
|
||||
|
||||
public class ChatEventListener implements Listener {
|
||||
|
||||
private Storage c;
|
||||
private final static char SEPARATOR = ((char)0x0007);
|
||||
|
||||
public ChatEventListener(Storage storage) {
|
||||
c = storage;
|
||||
}
|
||||
|
||||
|
||||
private int countOccurrences(String findStr, String str){
|
||||
int lastIndex = 0;
|
||||
int count = 0;
|
||||
while(lastIndex != -1){
|
||||
|
||||
lastIndex = str.indexOf(findStr,lastIndex);
|
||||
|
||||
if(lastIndex != -1){
|
||||
count ++;
|
||||
lastIndex += findStr.length();
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
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), "");
|
||||
e.setMessage(msg);
|
||||
}
|
||||
boolean found = false;
|
||||
|
||||
for (String rep : c.PLACEHOLDERS)
|
||||
if (e.getMessage().contains(rep)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found) {
|
||||
return;
|
||||
}
|
||||
if (!e.getPlayer().hasPermission("chatitem.use")) {
|
||||
e.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if (e.getPlayer().getItemInHand().getType().equals(Material.AIR)) {
|
||||
if (c.DENY_IF_NO_ITEM) {
|
||||
e.setCancelled(true);
|
||||
if (!c.DENY_MESSAGE.isEmpty())
|
||||
e.getPlayer().sendMessage(c.DENY_MESSAGE);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
String s = e.getMessage();
|
||||
for(String placeholder : c.PLACEHOLDERS){
|
||||
s = s.replace(placeholder, c.PLACEHOLDERS.get(0));
|
||||
}
|
||||
int occurrences = countOccurrences(c.PLACEHOLDERS.get(0), s);
|
||||
|
||||
if(occurrences>c.LIMIT){
|
||||
e.setCancelled(true);
|
||||
if(c.LIMIT_MESSAGE.isEmpty()){
|
||||
return;
|
||||
}
|
||||
e.getPlayer().sendMessage(c.LIMIT_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
String oldmsg = e.getMessage();
|
||||
StringBuilder sb = new StringBuilder(oldmsg);
|
||||
sb.append(SEPARATOR).append(e.getPlayer().getName());
|
||||
e.setMessage(sb.toString());
|
||||
Bukkit.getConsoleSender().sendMessage(String.format(e.getFormat(), e.getPlayer().getDisplayName(), oldmsg));
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onCommand(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);
|
||||
}
|
||||
Command cmd = Bukkit.getPluginCommand(e.getMessage().split(" ")[0].substring(1));
|
||||
if(cmd==null){ //not a plugin command
|
||||
return;
|
||||
}
|
||||
|
||||
if(!c.ALLOWED_COMMANDS.contains(cmd)){
|
||||
return;
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
for (String rep : c.PLACEHOLDERS) {
|
||||
if (e.getMessage().contains(rep)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!e.getPlayer().hasPermission("chatitem.use")) {
|
||||
e.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.getPlayer().getItemInHand().getType().equals(Material.AIR)) {
|
||||
if (c.DENY_IF_NO_ITEM) {
|
||||
e.setCancelled(true);
|
||||
if (!c.DENY_MESSAGE.isEmpty())
|
||||
e.getPlayer().sendMessage(c.DENY_MESSAGE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
String s = e.getMessage();
|
||||
for(String placeholder : c.PLACEHOLDERS){
|
||||
s = s.replace(placeholder, c.PLACEHOLDERS.get(0));
|
||||
}
|
||||
int occurrences = countOccurrences(c.PLACEHOLDERS.get(0), s);
|
||||
|
||||
if(occurrences>c.LIMIT){
|
||||
e.setCancelled(true);
|
||||
if(c.LIMIT_MESSAGE.isEmpty()){
|
||||
return;
|
||||
}
|
||||
e.getPlayer().sendMessage(c.LIMIT_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder(e.getMessage());
|
||||
sb.append(SEPARATOR).append(e.getPlayer().getName());
|
||||
e.setMessage(sb.toString());
|
||||
}
|
||||
|
||||
|
||||
public void setStorage(Storage st) {
|
||||
c = st;
|
||||
}
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
package me.dadus33.chatitem.listeners;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.events.ListenerPriority;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.wrappers.WrappedChatComponent;
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.utils.Storage;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
||||
public class ChatPacketListener extends PacketAdapter {
|
||||
|
||||
private final static String NAME = "{name}";
|
||||
private final static String AMOUNT = "{amount}";
|
||||
private final static String TIMES = "{times}";
|
||||
private ChatItem instance;
|
||||
private Storage c;
|
||||
|
||||
public ChatPacketListener(Plugin plugin, ListenerPriority listenerPriority, Storage s, PacketType... types) {
|
||||
super(plugin, listenerPriority, types);
|
||||
this.instance = (ChatItem) plugin;
|
||||
c = s;
|
||||
}
|
||||
|
||||
private static String materialToName(Material m) {
|
||||
if (m.equals(Material.TNT)) {
|
||||
return "TNT";
|
||||
}
|
||||
String orig = m.toString().toLowerCase();
|
||||
String[] splits = orig.split("_");
|
||||
StringBuilder sb = new StringBuilder(orig.length());
|
||||
int pos = 0;
|
||||
for (String split : splits) {
|
||||
sb.append(split);
|
||||
int loc = sb.lastIndexOf(split);
|
||||
char charLoc = sb.charAt(loc);
|
||||
if (!(split.equalsIgnoreCase("of") || split.equalsIgnoreCase("and") ||
|
||||
split.equalsIgnoreCase("with") || split.equalsIgnoreCase("on")))
|
||||
sb.setCharAt(loc, Character.toUpperCase(charLoc));
|
||||
if (pos != splits.length - 1)
|
||||
sb.append(' ');
|
||||
++pos;
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent e) {
|
||||
if(ChatItem.post17) //actionbar messages are only available after 1.7
|
||||
if (e.getPacket().getBytes().readSafely(0) == (byte) 2) {
|
||||
return; //It means it's an actionbar message, and we ain't intercepting those
|
||||
}
|
||||
|
||||
PacketContainer packet = e.getPacket();
|
||||
|
||||
if(packet.getChatComponents().readSafely(0)==null){ // null check for some cases of messages from other plugins
|
||||
return;
|
||||
}
|
||||
String json = packet.getChatComponents().readSafely(0).getJson();
|
||||
|
||||
boolean found = false;
|
||||
for (String rep : c.PLACEHOLDERS)
|
||||
if (json.contains(rep)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found) {
|
||||
return; //then it's just a normal message without placeholders, so we leave it alone
|
||||
}
|
||||
if(json.lastIndexOf("\\u0007")==-1){ //if the message doesn't contain the BEL separator, then it's certainly NOT a message we want to parse
|
||||
return;
|
||||
}
|
||||
|
||||
//here we find the last player name in the string
|
||||
int topIndex = -1;
|
||||
String name = null;
|
||||
for(Player p : Bukkit.getOnlinePlayers()){
|
||||
String pname = p.getName();
|
||||
if(!json.contains(pname)){
|
||||
continue;
|
||||
}
|
||||
int index = json.lastIndexOf(pname)+pname.length();
|
||||
if(index>topIndex){
|
||||
topIndex = index;
|
||||
name = pname;
|
||||
}
|
||||
}
|
||||
if(name==null){ //something went really bad, so we run away and hide
|
||||
return;
|
||||
}
|
||||
//then we make sure the name is after the BEL separator.
|
||||
if(json.lastIndexOf(name)!=json.lastIndexOf("\\u0007")+6){
|
||||
return; //then it means somehow the message just contained a BEL character not inserted by our plugin
|
||||
}
|
||||
|
||||
Player p = Bukkit.getPlayer(name);
|
||||
StringBuilder buff = new StringBuilder(json);
|
||||
buff.replace(topIndex-(name.length()+6), topIndex, ""); //we remove both the name and the separator from the json string
|
||||
json = buff.toString();
|
||||
|
||||
|
||||
//Item Styling
|
||||
//STYLE BEGIN
|
||||
|
||||
ItemStack inHand = p.getItemInHand();
|
||||
String replacer = c.NAME_FORMAT;
|
||||
String amount = c.AMOUNT_FORMAT;
|
||||
boolean dname = false;
|
||||
if (!c.COLOR_IF_ALREADY_COLORED && inHand.hasItemMeta()) {
|
||||
if (inHand.getItemMeta().hasDisplayName()) {
|
||||
replacer = ChatColor.stripColor(replacer);
|
||||
dname = true;
|
||||
}
|
||||
} else {
|
||||
if (inHand.hasItemMeta()) {
|
||||
if (inHand.getItemMeta().hasDisplayName()) {
|
||||
dname = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inHand.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(inHand.getAmount()));
|
||||
replacer = replacer.replace(AMOUNT, amount);
|
||||
}
|
||||
if (dname) {
|
||||
String trp = inHand.getItemMeta().getDisplayName();
|
||||
replacer = replacer.replace(NAME, trp);
|
||||
} else {
|
||||
HashMap<Short, String> translationSection = c.TRANSLATIONS.get(inHand.getType().name());
|
||||
if(translationSection==null){
|
||||
String trp = materialToName(inHand.getType());
|
||||
replacer = replacer.replace(NAME, trp);
|
||||
}else {
|
||||
String translated = translationSection.get(inHand.getDurability());
|
||||
if (translated != null) {
|
||||
replacer = replacer.replace(NAME, translated);
|
||||
} else {
|
||||
replacer = replacer.replace(NAME, materialToName(inHand.getType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
//STYLE END
|
||||
|
||||
|
||||
String[] reps = new String[c.PLACEHOLDERS.size()];
|
||||
c.PLACEHOLDERS.toArray(reps);
|
||||
String message = null;
|
||||
try {
|
||||
if(!p.getItemInHand().getType().equals(Material.AIR))
|
||||
message = ChatItem.getManipulator().parse(json, reps, p.getItemInHand(), replacer);
|
||||
} catch (InvocationTargetException | IllegalAccessException | InstantiationException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
if(message!=null)
|
||||
packet.getChatComponents().writeSafely(0, WrappedChatComponent.fromJson(message));
|
||||
else
|
||||
e.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
public void setStorage(Storage st) {
|
||||
c = st;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package me.dadus33.chatitem.listeners;
|
||||
|
||||
import static me.dadus33.chatitem.utils.ItemUtils.createItem;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.Storage;
|
||||
import me.dadus33.chatitem.Translation;
|
||||
import me.dadus33.chatitem.listeners.holder.AdminHolder;
|
||||
import me.dadus33.chatitem.listeners.holder.ChatItemHolder;
|
||||
import me.dadus33.chatitem.listeners.holder.CustomInventoryHolder;
|
||||
import me.dadus33.chatitem.utils.ItemUtils;
|
||||
import me.dadus33.chatitem.utils.Messages;
|
||||
|
||||
public class InventoryListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onClick(InventoryClickEvent e) {
|
||||
Player p = (Player) e.getWhoClicked();
|
||||
|
||||
if(e.getClickedInventory() == null || !(e.getWhoClicked() instanceof Player))
|
||||
return;
|
||||
InventoryHolder holder = e.getClickedInventory().getHolder();
|
||||
if(holder == null || !(holder instanceof ChatItemHolder)) {
|
||||
if(e.getClick().equals(ClickType.DOUBLE_CLICK) && p.getOpenInventory() != null && p.getOpenInventory().getTopInventory() != null) {
|
||||
Inventory top = p.getOpenInventory().getTopInventory();
|
||||
if(top.getHolder() != null && top.getHolder() instanceof ChatItemHolder) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(holder instanceof CustomInventoryHolder) {
|
||||
e.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if(!(holder instanceof AdminHolder))
|
||||
return;
|
||||
e.setCancelled(true);
|
||||
if(e.getCurrentItem() == null)
|
||||
return;
|
||||
ItemStack item = e.getCurrentItem();
|
||||
Material type = item.getType();
|
||||
Storage c = ChatItem.getInstance().getStorage();
|
||||
if(type.equals(ItemUtils.MATERIAL_CLOSE)) {
|
||||
p.closeInventory();
|
||||
} else if(type.equals(Material.BOOK)) {
|
||||
TranslationInventoryListener.open(p, 0);
|
||||
} else if(type.equals(Material.PAPER)) {
|
||||
String key = ((AdminHolder) holder).keyBySlot.get(e.getSlot());
|
||||
if(key != null) {
|
||||
setInConfig("manager", key);
|
||||
p.closeInventory();
|
||||
ChatItem.reload(p);
|
||||
}
|
||||
} else if(type.equals(ItemUtils.INK_SAC)) {
|
||||
setInConfig("general.color-if-already-colored", c.colorIfColored = !c.colorIfColored);
|
||||
open(p);
|
||||
} else if(type.equals(Material.STICK)) {
|
||||
setInConfig("general.hand.disabled", c.handDisabled = !c.handDisabled);
|
||||
open(p);
|
||||
} else if(type.equals(Material.BLAZE_ROD)) {
|
||||
setInConfig("general.check-update", c.checkUpdate = !c.checkUpdate);
|
||||
open(p);
|
||||
} else if(type.equals(ItemUtils.FIREWORK_CHARGE)) {
|
||||
setInConfig("debug", c.debug = !c.debug);
|
||||
open(p);
|
||||
} else if(type.equals(Material.IRON_DOOR)) {
|
||||
if(e.getClick().equals(ClickType.RIGHT))
|
||||
c.limit--;
|
||||
else if(e.getClick().equals(ClickType.LEFT))
|
||||
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--;
|
||||
else if(e.getClick().equals(ClickType.LEFT))
|
||||
c.cooldown++;
|
||||
setInConfig("general.cooldown", c.cooldown);
|
||||
open(p);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setInConfig(String key, Object val) {
|
||||
ChatItem pl = ChatItem.getInstance();
|
||||
pl.getConfig().set(key, val);
|
||||
pl.saveConfig();
|
||||
}
|
||||
|
||||
public static void open(Player p) {
|
||||
AdminHolder holder = new AdminHolder();
|
||||
Storage c = ChatItem.getInstance().getStorage();
|
||||
Inventory inv = Bukkit.createInventory(holder, 27, Messages.getMessage("admin-inv.name"));
|
||||
for(int i = 0; i < inv.getSize(); i ++)
|
||||
inv.setItem(i, createItem(ItemUtils.WHITE_STAINED_GLASS, "-"));
|
||||
|
||||
int slot = 0;
|
||||
for(String manager : Arrays.asList("both", "auto", "packet", "chat")) {
|
||||
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(8, getBoolChangeItem(ItemUtils.FIREWORK_CHARGE, "debug", c.debug));
|
||||
|
||||
inv.setItem(18, getBoolChangeItem(ItemUtils.INK_SAC, "color-if-already-colored", c.colorIfColored));
|
||||
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.BLAZE_ROD, "check-update", c.checkUpdate));
|
||||
inv.setItem(24, createItem(Material.BOOK, Messages.getMessage("admin-inv.language.name"),
|
||||
Messages.getMessage("admin-inv.language.lore", "%name%", Translation.getMessages().get("language.name").getAsString())));
|
||||
|
||||
inv.setItem(26, createItem(ItemUtils.MATERIAL_CLOSE, Messages.getMessage("admin-inv.close")));
|
||||
p.openInventory(inv);
|
||||
}
|
||||
|
||||
private static ItemStack getBoolChangeItem(Material type, String key, boolean b) {
|
||||
return createItem(type, Messages.getMessage("admin-inv." + key, "%state%", Messages.getMessage(b ? "enabled" : "disabled")), Messages.getMessageList("admin-inv.bool-lore"));
|
||||
}
|
||||
|
||||
private static ItemStack getAmountChangeItem(Material type, String key, int amount) {
|
||||
return createItem(type, Messages.getMessage("admin-inv." + key, "%state%", amount), Messages.getMessageList("admin-inv.amount-lore"));
|
||||
}
|
||||
|
||||
private static ItemStack getManagerItem(String manager, Object... placeholders) {
|
||||
return createItem(Material.PAPER, Messages.getMessage("admin-inv.manager." + manager + ".name", placeholders),
|
||||
Messages.getMessageList("admin-inv.manager." + manager + ".lore", placeholders));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package me.dadus33.chatitem.listeners;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.chatmanager.ChatManager;
|
||||
import me.dadus33.chatitem.utils.Utils;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
|
||||
public class JoinListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent e) {
|
||||
Player p = e.getPlayer();
|
||||
if(!p.isOp())
|
||||
return;
|
||||
ChatItem pl = ChatItem.getInstance();
|
||||
if(pl.isHasNewVersion()) {
|
||||
TextComponent text = new TextComponent(pl.getStorage().updateMessage);
|
||||
text.setHoverEvent(Utils.createTextHover(pl.getStorage().updateHover));
|
||||
text.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.spigotmc.org/resources/19064/"));
|
||||
p.spigot().sendMessage(text);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onLeft(PlayerQuitEvent e) {
|
||||
ChatManager.clear(e.getPlayer());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package me.dadus33.chatitem.listeners;
|
||||
|
||||
import static me.dadus33.chatitem.utils.ItemUtils.createItem;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.Translation;
|
||||
import me.dadus33.chatitem.listeners.holder.TranslationHolder;
|
||||
import me.dadus33.chatitem.utils.ItemUtils;
|
||||
import me.dadus33.chatitem.utils.Messages;
|
||||
|
||||
public class TranslationInventoryListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onClick(InventoryClickEvent e) {
|
||||
if(e.getClickedInventory() == null || !(e.getWhoClicked() instanceof Player) || e.getCurrentItem() == null
|
||||
|| !(e.getClickedInventory().getHolder() instanceof TranslationHolder))
|
||||
return;
|
||||
e.setCancelled(true);
|
||||
Player p = (Player) e.getWhoClicked();
|
||||
ItemStack item = e.getCurrentItem();
|
||||
Material type = item.getType();
|
||||
TranslationHolder holder = (TranslationHolder) e.getClickedInventory().getHolder();
|
||||
if(type.equals(Material.ARROW)) {
|
||||
if(e.getSlot() == 0)
|
||||
InventoryListener.open(p);
|
||||
else if(e.getSlot() == 3)
|
||||
open(p, holder.getPage() - 1);
|
||||
else if(e.getSlot() == 5)
|
||||
open(p, holder.getPage() + 1);
|
||||
} else if(type.equals(ItemUtils.MATERIAL_CLOSE))
|
||||
p.closeInventory();
|
||||
else if(type.equals(Material.PAPER)) {
|
||||
String lang = holder.langBySlot.get(e.getSlot());
|
||||
if(lang == null)
|
||||
return;
|
||||
p.closeInventory();
|
||||
ChatItem pl = ChatItem.getInstance();
|
||||
pl.getStorage().language = lang;
|
||||
pl.getConfig().set("general.language", lang);
|
||||
pl.saveConfig();
|
||||
Translation.loadLang(lang);
|
||||
p.sendMessage(ChatColor.GREEN + "Language changed to " + Translation.getMessages().get("language.name").getAsString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void open(Player p, int page) {
|
||||
int perPage = 45;
|
||||
List<String> langs = new ArrayList<>(Translation.getAllLangs().keySet());
|
||||
TranslationHolder holder = new TranslationHolder(page);
|
||||
Inventory inv = Bukkit.createInventory(holder, 54, "Change language - " + ChatColor.GOLD + " Page " + (page + 1) + " / " + ((langs.size() / perPage) + 1));
|
||||
for(int i = 0; i < 9; i ++)
|
||||
inv.setItem(i, new ItemStack(ItemUtils.GRAY_STAINED_GLASS_PANE));
|
||||
inv.setItem(0, createItem(Material.ARROW, ChatColor.GRAY + "Back"));
|
||||
|
||||
if(page > 0)
|
||||
inv.setItem(3, createItem(Material.ARROW, ChatColor.RED + "Previous page"));
|
||||
if(langs.size() > (perPage * (page + 1)))
|
||||
inv.setItem(5, createItem(Material.ARROW, ChatColor.GREEN + "Next page"));
|
||||
|
||||
inv.setItem(8, createItem(ItemUtils.MATERIAL_CLOSE, Messages.getMessage("admin-inv.close")));
|
||||
|
||||
int slot = 9;
|
||||
for(int i = (page * perPage); i < langs.size() && (i < ((page + 1) * perPage)); i++) {
|
||||
String lang = langs.get(i);
|
||||
holder.langBySlot.put(slot, lang);
|
||||
ItemStack item = createItem(Material.PAPER, ChatColor.GOLD + Translation.getAllLangs().get(lang), ChatColor.GRAY + "Clic to select this language");
|
||||
if(lang.equalsIgnoreCase(ChatItem.getInstance().getStorage().language)) {
|
||||
item.addUnsafeEnchantment(Enchantment.DURABILITY, 1);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
inv.setItem(slot++, item);
|
||||
}
|
||||
|
||||
p.openInventory(inv);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package me.dadus33.chatitem.listeners.holder;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class AdminHolder extends ChatItemHolder {
|
||||
|
||||
public final HashMap<Integer, String> keyBySlot = new HashMap<>();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package me.dadus33.chatitem.listeners.holder;
|
||||
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
|
||||
public abstract class ChatItemHolder implements InventoryHolder {
|
||||
|
||||
@Override
|
||||
public Inventory getInventory() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package me.dadus33.chatitem.listeners.holder;
|
||||
|
||||
public class CustomInventoryHolder extends ChatItemHolder {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package me.dadus33.chatitem.listeners.holder;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class TranslationHolder extends ChatItemHolder {
|
||||
|
||||
public final HashMap<Integer, String> langBySlot = new HashMap<>();
|
||||
private final int page;
|
||||
|
||||
public TranslationHolder(int page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
public int getPage() {
|
||||
return page;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package me.dadus33.chatitem.playernamer;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
|
||||
public interface IPlayerNamer {
|
||||
|
||||
public BaseComponent[] getName(Player p);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package me.dadus33.chatitem.playernamer;
|
||||
|
||||
import me.dadus33.chatitem.playernamer.hook.HexNicksV3PlayerNamer;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.playernamer.hook.DefaultPlayerNamer;
|
||||
import me.dadus33.chatitem.playernamer.hook.HexNicksV2PlayerNamer;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class PlayerNamerManager {
|
||||
|
||||
private static IPlayerNamer playerNamer;
|
||||
public static IPlayerNamer getPlayerNamer() {
|
||||
return playerNamer;
|
||||
}
|
||||
public static void setPlayerNamer(IPlayerNamer playerNamer) {
|
||||
PlayerNamerManager.playerNamer = playerNamer;
|
||||
}
|
||||
|
||||
public static void load(ChatItem pl) {
|
||||
Plugin plugin = Bukkit.getPluginManager().getPlugin("HexNicks");
|
||||
|
||||
|
||||
if (plugin != null) {
|
||||
char majorVersion = plugin.getDescription().getVersion().charAt(0);
|
||||
|
||||
if (majorVersion == '3')
|
||||
setPlayerNamer(new HexNicksV3PlayerNamer());
|
||||
else
|
||||
setPlayerNamer(new HexNicksV2PlayerNamer());
|
||||
|
||||
pl.getLogger().info("Enable support for HexNicks plugin v" + majorVersion);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
setPlayerNamer(new DefaultPlayerNamer());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package me.dadus33.chatitem.playernamer.hook;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.dadus33.chatitem.playernamer.IPlayerNamer;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
|
||||
public class DefaultPlayerNamer implements IPlayerNamer {
|
||||
|
||||
@Override
|
||||
public BaseComponent[] getName(Player p) {
|
||||
return new ComponentBuilder(p.getName()).create();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package me.dadus33.chatitem.playernamer.hook;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import dev.majek.hexnicks.Nicks;
|
||||
import me.dadus33.chatitem.playernamer.IPlayerNamer;
|
||||
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
|
||||
public class HexNicksV2PlayerNamer implements IPlayerNamer {
|
||||
|
||||
@Override
|
||||
public BaseComponent[] getName(Player p) {
|
||||
return BungeeComponentSerializer.get().serialize(Nicks.api().getStoredNick(p).join());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package me.dadus33.chatitem.playernamer.hook;
|
||||
|
||||
import dev.majek.hexnicks.HexNicks;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.dadus33.chatitem.playernamer.IPlayerNamer;
|
||||
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
|
||||
public class HexNicksV3PlayerNamer implements IPlayerNamer {
|
||||
|
||||
@Override
|
||||
public BaseComponent[] getName(Player p) {
|
||||
return BungeeComponentSerializer.get().serialize(HexNicks.api().getStoredNick(p).join());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package me.dadus33.chatitem.playerversion;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.dadus33.chatitem.utils.Version;
|
||||
|
||||
public interface IPlayerVersion {
|
||||
|
||||
public int getProtocolVersion(Player p);
|
||||
|
||||
default Version getPlayerVersion(Player p) {
|
||||
return Version.getVersion(getProtocolVersion(p), Version.getVersion());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package me.dadus33.chatitem.playerversion;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.playerversion.hooks.DefaultVersionHook;
|
||||
import me.dadus33.chatitem.playerversion.hooks.ProtocolSupportHook;
|
||||
import me.dadus33.chatitem.playerversion.hooks.ViaVersionHook;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class PlayerVersionManager {
|
||||
|
||||
private static final IPlayerVersion playerVersionAdapter;
|
||||
|
||||
static {
|
||||
ChatItem pl = ChatItem.getInstance();
|
||||
if (Bukkit.getPluginManager().getPlugin("ProtocolSupport") != null) {
|
||||
playerVersionAdapter = new ProtocolSupportHook();
|
||||
pl.getLogger().info("Loading ProtocolSupport support ...");
|
||||
} else if (Bukkit.getPluginManager().getPlugin("ViaVersion") != null) {
|
||||
playerVersionAdapter = new ViaVersionHook();
|
||||
pl.getLogger().info("Loading ViaVersion support ...");
|
||||
} else {
|
||||
playerVersionAdapter = new DefaultVersionHook();
|
||||
}
|
||||
}
|
||||
|
||||
public static IPlayerVersion getPlayerVersionAdapter() {
|
||||
return playerVersionAdapter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package me.dadus33.chatitem.playerversion.hooks;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.dadus33.chatitem.playerversion.IPlayerVersion;
|
||||
import me.dadus33.chatitem.utils.Version;
|
||||
|
||||
public class DefaultVersionHook implements IPlayerVersion {
|
||||
|
||||
@Override
|
||||
public int getProtocolVersion(Player p) {
|
||||
return Version.getVersion().MAX_VER;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package me.dadus33.chatitem.playerversion.hooks;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.dadus33.chatitem.playerversion.IPlayerVersion;
|
||||
import protocolsupport.api.ProtocolSupportAPI;
|
||||
|
||||
public class ProtocolSupportHook implements IPlayerVersion {
|
||||
|
||||
@Override
|
||||
public int getProtocolVersion(Player p) {
|
||||
return ProtocolSupportAPI.getProtocolVersion(p).getId();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package me.dadus33.chatitem.playerversion.hooks;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
|
||||
import me.dadus33.chatitem.playerversion.IPlayerVersion;
|
||||
|
||||
public class ViaVersionHook implements IPlayerVersion {
|
||||
|
||||
@Override
|
||||
public int getProtocolVersion(Player p) {
|
||||
return Via.getAPI().getPlayerVersion(p.getUniqueId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package me.dadus33.chatitem.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
|
||||
public class ColorManager {
|
||||
|
||||
public static final List<String> COLORS = Arrays.asList("4", "c", "6", "e", "2", "a", "b", "3", "1", "9", "d", "5", "f", "7", "8", "0");
|
||||
|
||||
public static boolean isHexColor(ChatColor c) {
|
||||
return Version.getVersion().isNewerOrEquals(Version.V1_16) && c.getName().startsWith("#");
|
||||
}
|
||||
|
||||
public static boolean isHexColor(String c) {
|
||||
return Version.getVersion().isNewerOrEquals(Version.V1_16) && c.startsWith("x");
|
||||
}
|
||||
|
||||
public static String removeColorAtBegin(String s) {
|
||||
if(s == null || s.isEmpty())
|
||||
return "";
|
||||
boolean wasColorChar = s.startsWith(Character.toString(ChatColor.COLOR_CHAR));
|
||||
if(!wasColorChar)
|
||||
return s;
|
||||
String next = "";
|
||||
for(int i = 1; i < s.length(); i++) {
|
||||
char c = s.charAt(i);
|
||||
if(wasColorChar) {
|
||||
if(!COLORS.contains(Character.toString(c)))
|
||||
next = next + ChatColor.COLOR_CHAR + "" + c;
|
||||
wasColorChar = false;
|
||||
} else {
|
||||
wasColorChar = c == ChatColor.COLOR_CHAR;
|
||||
if(!wasColorChar) { // something other than color code
|
||||
next += s.substring(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(next.isEmpty())
|
||||
next = s;
|
||||
return next;
|
||||
}
|
||||
|
||||
public static String getColorString(String input) {
|
||||
if (input == null || input.isEmpty())
|
||||
return "";
|
||||
StringBuilder str = new StringBuilder();
|
||||
if (isHexColor(input)) { // x mean it's an hex
|
||||
input = input.substring(1);
|
||||
if (input.length() >= 6) { // at least hex
|
||||
str.append(ChatColor.of("#" + input.substring(0, 6))); // get first hex color code
|
||||
ChatItem.debug("Str with hex: " + str);
|
||||
if (input.length() > 6) // if as another color code
|
||||
str.append(getColorString(input.substring(6))); // get color for after
|
||||
return str.toString();
|
||||
} else
|
||||
ChatItem.debug("Low len: " + input.length());
|
||||
}
|
||||
// not hex
|
||||
for (char c : input.toCharArray())
|
||||
str.append(ChatColor.getByChar(c));
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
public static ChatColor getColor(String input) {
|
||||
if (input == null || input.isEmpty())
|
||||
return ChatColor.RESET;
|
||||
if (isHexColor(input)) { // x mean it's an hex
|
||||
if (input.length() >= 7) { // at least hex, and 7 because we count the "x"
|
||||
return ChatColor.of("#" + input.substring(1, 7)); // get first hex color code
|
||||
} else
|
||||
ChatItem.debug("Low len: " + input.length());
|
||||
}
|
||||
// not hex
|
||||
return ChatColor.getByChar(input.charAt(0));
|
||||
}
|
||||
|
||||
public static String fixColor(String message) {
|
||||
String colorCode = "", text = "";
|
||||
boolean waiting = false;
|
||||
for (char args : message.toCharArray()) {
|
||||
if (args == '§') { // begin of color
|
||||
waiting = true; // waiting for color code
|
||||
} else if (waiting) { // if waiting for code and valid str
|
||||
// if it's hexademical value and with enough space for full color
|
||||
waiting = false;
|
||||
if (args == 'r' && colorCode.isEmpty()) {
|
||||
text += ChatColor.RESET;
|
||||
continue;
|
||||
}
|
||||
if (args == 'x' && !colorCode.isEmpty()) {
|
||||
text += ColorManager.getColorString(colorCode);
|
||||
colorCode = "x";
|
||||
} else if(Character.digit(Character.toLowerCase(args), 16) != -1)
|
||||
colorCode += args; // a color by itself
|
||||
} else {
|
||||
waiting = false;
|
||||
if (!colorCode.isEmpty()) {
|
||||
if (isHexColor(colorCode) && colorCode.length() >= 7) {
|
||||
if (colorCode.length() == 7)
|
||||
text += ColorManager.getColor(colorCode);
|
||||
else {
|
||||
text += ColorManager.getColor(colorCode.substring(0, 7)); // only the hex code
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package me.dadus33.chatitem.utils;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class General {
|
||||
|
||||
private static Storage c;
|
||||
|
||||
public static void checkConfigVersion() {
|
||||
int latestVersion = ChatItem.CFG_VER;
|
||||
if (latestVersion != c.CONFIG_VERSION) {
|
||||
Bukkit.getLogger().log(Level.WARNING, ChatColor.RED + "ChatItem detected an older or invalid configuration file. Replacing it with the default config...");
|
||||
c.performOverwrite();
|
||||
Bukkit.getLogger().log(Level.WARNING, ChatColor.RED + "Replacement complete!");
|
||||
}
|
||||
}
|
||||
|
||||
public static void init(Storage st) {
|
||||
c = st;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package me.dadus33.chatitem.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
public class ItemUtils {
|
||||
|
||||
public static final Material MATERIAL_CLOSE = getMaterialWithCompatibility("BARRIER", "REDSTONE_BLOCK");
|
||||
|
||||
// items
|
||||
public static final Material EMPTY_MAP = getMaterialWithCompatibility("EMPTY_MAP", "MAP");
|
||||
public static final Material BOOK_AND_QUILL = getMaterialWithCompatibility("BOOK_AND_QUILL", "WRITTEN_BOOK");
|
||||
public static final Material WEB = getMaterialWithCompatibility("WEB", "COBWEB");
|
||||
public static final Material FIREBALL = getMaterialWithCompatibility("FIREBALL", "FIRE_CHARGE");
|
||||
public static final Material INK_SAC = getMaterialWithCompatibility("INK_SAC", "INK_SACK", "DYE", "GRAY_DYE");
|
||||
public static final Material FIREWORK_CHARGE = getMaterialWithCompatibility("FIREWORK_CHARGE", "FIRE_CHARGE");
|
||||
|
||||
public static final Material BIRCH_WOOD_STAIRS = getMaterialWithCompatibility("BIRCH_WOOD_STAIRS", "BIRCH_STAIRS");
|
||||
|
||||
// colored items
|
||||
public static final Material GRAY_STAINED_GLASS_PANE = getMaterialWithCompatibility("STAINED_GLASS_PANE", "GRAY_STAINED_GLASS_PANE");
|
||||
public static final Material WHITE_STAINED_GLASS = getMaterialWithCompatibility("STAINED_GLASS_PANE", "WHITE_STAINED_GLASS_PANE");
|
||||
|
||||
public static Material getMaterialWithCompatibility(String... tempMat) {
|
||||
for(String s : tempMat) {
|
||||
try {
|
||||
Material m = (Material) Material.class.getField(s).get(Material.class);
|
||||
if(m != null)
|
||||
return m;
|
||||
} catch (IllegalArgumentException | IllegalAccessException | SecurityException e2) {
|
||||
e2.printStackTrace();
|
||||
} catch (NoSuchFieldException e) {}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ItemStack createItem(Material m, String name, String... lore) {
|
||||
return createItem(m, name, 1, lore);
|
||||
}
|
||||
|
||||
public static ItemStack createItem(Material m, String name, int quantite, String... lore) {
|
||||
ItemStack item = new ItemStack(m, quantite);
|
||||
ItemMeta meta = (ItemMeta) item.getItemMeta();
|
||||
meta.setDisplayName(ChatColor.RESET + name);
|
||||
meta.setLore(Arrays.asList(lore));
|
||||
item.setItemMeta(meta);
|
||||
return item;
|
||||
}
|
||||
|
||||
public static ItemStack createItem(Material m, String name, List<String> lore) {
|
||||
return createItem(m, name, 1, lore);
|
||||
}
|
||||
|
||||
public static ItemStack createItem(Material m, String name, int quantite, List<String> lore) {
|
||||
ItemStack item = new ItemStack(m, quantite);
|
||||
ItemMeta meta = (ItemMeta) item.getItemMeta();
|
||||
meta.setDisplayName(ChatColor.RESET + name);
|
||||
meta.setLore(lore);
|
||||
item.setItemMeta(meta);
|
||||
return item;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static ItemStack createItem(Material m, String name, int amount, byte b, String... lore) {
|
||||
ItemStack item = new ItemStack(m, amount, b);
|
||||
ItemMeta meta = (ItemMeta) item.getItemMeta();
|
||||
meta.setDisplayName(ChatColor.RESET + name);
|
||||
meta.setLore(Arrays.asList(lore));
|
||||
item.setItemMeta(meta);
|
||||
return item;
|
||||
}
|
||||
|
||||
public static ItemStack hideAttributes(ItemStack stack) {
|
||||
if (Version.getVersion().isNewerThan(Version.V1_7)) {
|
||||
ItemMeta meta = stack.getItemMeta();
|
||||
// All ItemFlags are used to hide attributes, their javadoc says so too.
|
||||
meta.addItemFlags(ItemFlag.values());
|
||||
stack.setItemMeta(meta);
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
public static ItemStack copyIfExist(ItemStack item) {
|
||||
return isEmpty(item) ? null : item.clone();
|
||||
}
|
||||
|
||||
public static boolean isEmpty(ItemStack item) {
|
||||
return item == null || item.getType().equals(Material.AIR);
|
||||
}
|
||||
|
||||
public static void stripData(ItemStack i) {
|
||||
if (i == null) {
|
||||
return;
|
||||
}
|
||||
if (i.getType().equals(Material.AIR)) {
|
||||
return;
|
||||
}
|
||||
if (!i.hasItemMeta()) {
|
||||
return;
|
||||
}
|
||||
ItemMeta im = Bukkit.getItemFactory().getItemMeta(i.getType());
|
||||
ItemMeta original = i.getItemMeta();
|
||||
if (original.hasDisplayName()) {
|
||||
im.setDisplayName(original.getDisplayName());
|
||||
}
|
||||
i.setItemMeta(im);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package me.dadus33.chatitem.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.Storage;
|
||||
|
||||
public class Messages {
|
||||
|
||||
public static void sendMessage(CommandSender p, String key, Object... placeholders) {
|
||||
getMessageList(key, placeholders).forEach(p::sendMessage);
|
||||
}
|
||||
|
||||
public static String getMessage(String key, Object... placeholders) {
|
||||
return colorAndPlaceholders(ChatItem.getInstance().getConfig().getString("messages." + key, key), placeholders);
|
||||
}
|
||||
|
||||
public static List<String> getMessageList(String key, Object... placeholders) {
|
||||
Object obj = ChatItem.getInstance().getConfig().get("messages." + key);
|
||||
if(obj == null)
|
||||
return Arrays.asList(key);
|
||||
if(obj instanceof List) {
|
||||
return ((List<String>) obj).stream().map((s) -> colorAndPlaceholders(s, placeholders)).collect(Collectors.toList());
|
||||
} else if(obj instanceof String)
|
||||
return Arrays.asList(colorAndPlaceholders((String) obj, placeholders));
|
||||
else
|
||||
return Arrays.asList(colorAndPlaceholders(obj.toString(), placeholders));
|
||||
}
|
||||
|
||||
private static String colorAndPlaceholders(String msg, Object... placeholders) {
|
||||
if(msg == null)
|
||||
return "";
|
||||
for (int index = 0; index <= placeholders.length - 1; index += 2) {
|
||||
msg = msg.replace(String.valueOf(placeholders[index]), String.valueOf(placeholders[index + 1]));
|
||||
}
|
||||
return Storage.color(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
package me.dadus33.chatitem.utils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulator;
|
||||
|
||||
public class PacketUtils {
|
||||
|
||||
public static final String VERSION = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
|
||||
public static final String NMS_PREFIX;
|
||||
public static final String OBC_PREFIX;
|
||||
public static final boolean IS_THERMOS;
|
||||
public static final Class<?> CHAT_SERIALIZER, COMPONENT_CLASS;
|
||||
public static final Method ICB_FROM_JSON;
|
||||
|
||||
/**
|
||||
* 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 + ".";
|
||||
OBC_PREFIX = "org.bukkit.craftbukkit." + VERSION + ".";
|
||||
CHAT_SERIALIZER = getNmsClass("IChatBaseComponent$ChatSerializer", "network.chat.", "ChatSerializer");
|
||||
COMPONENT_CLASS = getNmsClass("IChatBaseComponent", "network.chat.");
|
||||
ICB_FROM_JSON = getMethod("a", CHAT_SERIALIZER, String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
* @return clazz the searched class
|
||||
*/
|
||||
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 : "");
|
||||
try {
|
||||
Class<?> clazz = Class.forName(fullPrefix + name);
|
||||
if (clazz != null)
|
||||
return clazz;
|
||||
} catch (ClassNotFoundException e) {
|
||||
if (alias.length == 0)
|
||||
e.printStackTrace(); // no alias, print error
|
||||
// else ignore and go check for alias
|
||||
}
|
||||
|
||||
for (String className : alias) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName(fullPrefix + className);
|
||||
if (clazz != null)
|
||||
return clazz;
|
||||
} catch (ClassNotFoundException e) {
|
||||
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)
|
||||
* @return clazz the searched class
|
||||
*/
|
||||
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)
|
||||
return clazz;
|
||||
} catch (ClassNotFoundException e) {
|
||||
if (alias.length == 0)
|
||||
e.printStackTrace(); // no alias, print error
|
||||
// else ignore and go check for alias
|
||||
}
|
||||
|
||||
for (String className : alias) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName(OBC_PREFIX + className);
|
||||
if (clazz != null)
|
||||
return clazz;
|
||||
} catch (ClassNotFoundException e) {
|
||||
if (className == alias[alias.length - 1]) // if it's last alias, print error
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get NMS entity player of specified one
|
||||
*
|
||||
* @param p the player that we want the NMS entity player
|
||||
* @return the entity player
|
||||
*/
|
||||
public static Object getEntityPlayer(Player p) {
|
||||
try {
|
||||
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);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get NMS player connection of specified player
|
||||
*
|
||||
* @param p Player of which we want to get the player connection
|
||||
* @return the NMS player connection
|
||||
*/
|
||||
public static Object getPlayerConnection(Player p) {
|
||||
try {
|
||||
Object entityPlayer = getEntityPlayer(p);
|
||||
return ReflectionUtils.getFirstWith(entityPlayer, entityPlayer.getClass(), getNmsClass("PlayerConnection", "server.network."));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get NMS entity player of specified one
|
||||
*
|
||||
* @param p the player that we want the NMS entity player
|
||||
* @return the entity player
|
||||
*/
|
||||
public static Object getCraftServer() {
|
||||
try {
|
||||
return getObcClass("CraftServer").getMethod("getHandle").invoke(Bukkit.getServer());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the packet to the specified player
|
||||
*
|
||||
* @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);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getNbtMethod;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
if (getNbtMethod == null) {
|
||||
Class<?> itemClass = getNmsClass("ItemStack", "world.item.");
|
||||
Version v = Version.getVersion();
|
||||
if (v.isNewerOrEquals(Version.V1_20))
|
||||
getNbtMethod = itemClass.getDeclaredMethod("w");
|
||||
else if (v.equals(Version.V1_19))
|
||||
getNbtMethod = itemClass.getDeclaredMethod("u");
|
||||
else if (v.equals(Version.V1_18))
|
||||
getNbtMethod = itemClass.getDeclaredMethod("t");
|
||||
else
|
||||
getNbtMethod = itemClass.getDeclaredMethod("getTag");
|
||||
|
||||
getNbtMethod.setAccessible(true);
|
||||
}
|
||||
Object tag = getNbtMethod.invoke(JSONManipulator.AS_NMS_COPY.invoke(null, item));
|
||||
return tag == null ? "{}" : tag.toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "{}";
|
||||
}
|
||||
|
||||
private static Method getMethod(String name, Class<?> clazz, Class<?>... params) {
|
||||
try {
|
||||
return clazz.getDeclaredMethod(name, params);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void printPacketToDebug(Object packet) {
|
||||
if(!ChatItem.hasDebug())
|
||||
return;
|
||||
if(packet == null) {
|
||||
ChatItem.debug("Packet is null");
|
||||
return;
|
||||
}
|
||||
ChatItem.debug("Packet with Class: " + packet.getClass().getSimpleName());
|
||||
for (Field f : packet.getClass().getDeclaredFields()) {
|
||||
f.setAccessible(true);
|
||||
try {
|
||||
ChatItem.debug(f.getName() + ": " + f.get(packet));
|
||||
} catch (Exception exc) {
|
||||
exc.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package me.dadus33.chatitem.utils;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class Reflect {
|
||||
|
||||
|
||||
private static String versionString;
|
||||
|
||||
|
||||
private static String getVersion() {
|
||||
if (versionString == null) {
|
||||
String name = Bukkit.getServer().getClass().getPackage().getName();
|
||||
versionString = name.substring(name.lastIndexOf('.') + 1) + ".";
|
||||
}
|
||||
|
||||
return versionString;
|
||||
}
|
||||
|
||||
public static Class<?> getNMSClass(String nmsClassName) {
|
||||
|
||||
String clazzName = "net.minecraft.server." + getVersion() + nmsClassName;
|
||||
Class<?> clazz;
|
||||
|
||||
try {
|
||||
clazz = Class.forName(clazzName);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
return clazz;
|
||||
}
|
||||
|
||||
|
||||
public static Class<?> getOBCClass(String obcClassName) {
|
||||
|
||||
String clazzName = "org.bukkit.craftbukkit." + getVersion() + obcClassName;
|
||||
Class<?> clazz;
|
||||
|
||||
try {
|
||||
clazz = Class.forName(clazzName);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
return clazz;
|
||||
}
|
||||
|
||||
|
||||
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... params) {
|
||||
try {
|
||||
return clazz.getMethod(methodName, params);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
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 {
|
||||
Field objectField = object.getClass().getDeclaredField(field);
|
||||
objectField.setAccessible(true);
|
||||
return objectField.get(object);
|
||||
}
|
||||
|
||||
public static void setField(Object src, String fieldName, Object value) {
|
||||
try {
|
||||
Field field = src.getClass().getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
field.set(src, value);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified field name in the object source
|
||||
*
|
||||
* @param source where we will find the field
|
||||
* @param field the name of the field
|
||||
* @return the requested object of the field
|
||||
*/
|
||||
public static Object getObject(Object source, String... field) {
|
||||
try {
|
||||
for(String fieldName : field) {
|
||||
try {
|
||||
Field f = source.getClass().getDeclaredField(fieldName);
|
||||
f.setAccessible(true);
|
||||
return f.get(source);
|
||||
} catch (NoSuchFieldException e) {
|
||||
// ignore because going to next item
|
||||
}
|
||||
}
|
||||
ChatItem.getInstance().getLogger().severe("Failed to find fields: " + String.join(", ", field) + " in " + source.getClass().getSimpleName());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified field name in the object source
|
||||
*
|
||||
* @param source where we will find the field
|
||||
* @param field the name of the field
|
||||
* @return the requested field
|
||||
*/
|
||||
public static Field getField(Object source, String field) {
|
||||
try {
|
||||
Field f = source.getClass().getDeclaredField(field);
|
||||
f.setAccessible(true);
|
||||
return f;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call method. Return the method return.
|
||||
*
|
||||
* @param source the object where we want to run the method
|
||||
* @param method the name of the method to call
|
||||
* @return the return of the method called
|
||||
*/
|
||||
public static Object callMethod(Object source, String method) {
|
||||
try {
|
||||
return source.getClass().getDeclaredMethod(method).invoke(source);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param searchingFor the class of the required field
|
||||
* @return the field (or null if not found)
|
||||
* @throws Exception if something gone wrong
|
||||
*/
|
||||
public static <T> T getFirstWith(Object from, Class<T> searchingFor) throws Exception {
|
||||
return getFirstWith(from, from.getClass(), searchingFor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param searchingFor the class of the required field
|
||||
* @return the field (or null if not found)
|
||||
* @throws Exception if something gone wrong
|
||||
*/
|
||||
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())) {
|
||||
f.setAccessible(true);
|
||||
return (T) f.get(from);
|
||||
}
|
||||
}
|
||||
if(!clazz.getSuperclass().equals(Object.class))
|
||||
return getFirstWith(from, clazz.getSuperclass(), searchingFor);
|
||||
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;
|
||||
}
|
||||
|
||||
public static boolean isClassExist(String name) {
|
||||
try {
|
||||
Class.forName(name);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
package me.dadus33.chatitem.utils;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Represents the simplified SemVer schema Negativity uses for its plugin versions.
|
||||
*/
|
||||
public final class SemVer implements Comparable<SemVer> {
|
||||
|
||||
private final int major;
|
||||
private final int minor;
|
||||
private final int patch;
|
||||
|
||||
private final @Nullable Suffix suffix;
|
||||
|
||||
public SemVer(int major, int minor, int patch, @Nullable Suffix suffix) {
|
||||
this.major = major;
|
||||
this.minor = minor;
|
||||
this.patch = patch;
|
||||
this.suffix = suffix;
|
||||
}
|
||||
|
||||
public boolean isNewerThan(SemVer other) {
|
||||
return this.compareTo(other) > 0;
|
||||
}
|
||||
|
||||
public boolean isOlderThan(SemVer other) {
|
||||
return this.compareTo(other) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Slightly different from {@link #equals} in that this method will return
|
||||
* true if the suffix has the same {@link Suffix#getWeight() weight}
|
||||
* but not the same {@link Suffix#getText()} text
|
||||
*/
|
||||
public boolean isEquivalentTo(SemVer other) {
|
||||
return this.compareTo(other) == 0;
|
||||
}
|
||||
|
||||
public int getMajor() {
|
||||
return major;
|
||||
}
|
||||
|
||||
public int getMinor() {
|
||||
return minor;
|
||||
}
|
||||
|
||||
public int getPatch() {
|
||||
return patch;
|
||||
}
|
||||
|
||||
public @Nullable Suffix getSuffix() {
|
||||
return suffix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(SemVer o) {
|
||||
int majorDelta = Integer.compare(this.major, o.major);
|
||||
if (majorDelta != 0) {
|
||||
return majorDelta;
|
||||
}
|
||||
int minorDelta = Integer.compare(this.minor, o.minor);
|
||||
if (minorDelta != 0) {
|
||||
return minorDelta;
|
||||
}
|
||||
int patchDelta = Integer.compare(this.patch, o.patch);
|
||||
if (patchDelta != 0) {
|
||||
return patchDelta;
|
||||
}
|
||||
if (this.suffix != null) {
|
||||
return o.suffix != null ? this.suffix.compareTo(o.suffix) : -1;
|
||||
}
|
||||
if (o.suffix != null) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
SemVer semVer = (SemVer) o;
|
||||
return major == semVer.major && minor == semVer.minor && patch == semVer.patch && Objects.equals(suffix, semVer.suffix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(major, minor, patch, suffix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SemVer{major=" + major + ", minor=" + minor + ", patch=" + patch + ", suffix=" + suffix + '}';
|
||||
}
|
||||
|
||||
public String toFormattedString() {
|
||||
if (suffix == null) {
|
||||
if(patch > 0)
|
||||
return major + "." + minor + (patch > 0 ? "." + patch : "");
|
||||
}
|
||||
return major + "." + minor + (patch > 0 ? "." + patch : "") + (suffix == null ? "" : "-" + suffix.getText());
|
||||
}
|
||||
|
||||
public static @Nullable SemVer parse(String text) {
|
||||
if (text == null || text.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] suffixSplit = text.split("-", 2);
|
||||
Suffix suffix = null;
|
||||
if (suffixSplit.length > 1) {
|
||||
suffix = Suffix.of(suffixSplit[1]);
|
||||
}
|
||||
|
||||
String[] parts = suffixSplit[0].split("\\.");
|
||||
int major;
|
||||
try {
|
||||
major = Integer.parseInt(parts[0]);
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
int minor = 0;
|
||||
if (parts.length > 1) {
|
||||
try {
|
||||
minor = Integer.parseInt(parts[1]);
|
||||
} catch (NumberFormatException ignore) {
|
||||
}
|
||||
}
|
||||
int patch = 0;
|
||||
if (parts.length > 2) {
|
||||
try {
|
||||
patch = Integer.parseInt(parts[2]);
|
||||
} catch (NumberFormatException ignore) {
|
||||
}
|
||||
}
|
||||
return new SemVer(major, minor, patch, suffix);
|
||||
}
|
||||
|
||||
public static final class Suffix implements Comparable<Suffix> {
|
||||
|
||||
public static final Suffix SNAPSHOT = new Suffix(0, "SNAPSHOT");
|
||||
public static final Suffix ALPHA = new Suffix(1, "ALPHA");
|
||||
public static final Suffix BETA = new Suffix(2, "BETA");
|
||||
public static final Suffix GAMMA = new Suffix(3, "GAMMA");
|
||||
public static final Suffix DELTA = new Suffix(4, "DELTA");
|
||||
|
||||
private final int weight;
|
||||
private final String text;
|
||||
|
||||
public Suffix(int weight, String text) {
|
||||
this.weight = weight;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public int getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Suffix o) {
|
||||
return Integer.compare(this.weight, o.weight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Suffix suffix = (Suffix) o;
|
||||
return weight == suffix.weight && text.equals(suffix.text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(weight, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Suffix{weight=" + weight + ", text='" + text + "'}";
|
||||
}
|
||||
|
||||
public static Suffix of(String text) {
|
||||
String uppercaseText = text.toUpperCase(Locale.ROOT);
|
||||
switch (uppercaseText) {
|
||||
case "SNAPSHOT":
|
||||
return SNAPSHOT;
|
||||
case "ALPHA":
|
||||
return ALPHA;
|
||||
case "BETA":
|
||||
return BETA;
|
||||
case "GAMMA":
|
||||
return GAMMA;
|
||||
case "DELTA":
|
||||
return DELTA;
|
||||
default:
|
||||
return new Suffix(-1, uppercaseText);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
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.logging.Level;
|
||||
|
||||
|
||||
public class Storage {
|
||||
|
||||
public final HashMap<String, HashMap<Short, String>> TRANSLATIONS = new HashMap<>();
|
||||
public final List<String> PLACEHOLDERS;
|
||||
public final String NAME_FORMAT;
|
||||
public final String AMOUNT_FORMAT;
|
||||
public final Boolean COLOR_IF_ALREADY_COLORED;
|
||||
public final Boolean FORCE_ADD_AMOUNT;
|
||||
public final Boolean DENY_IF_NO_ITEM;
|
||||
public final String DENY_MESSAGE;
|
||||
public final String LIMIT_MESSAGE;
|
||||
public final String RELOAD_MESSAGE;
|
||||
final Integer CONFIG_VERSION;
|
||||
public final Integer LIMIT;
|
||||
public final List<Command> ALLOWED_COMMANDS = new ArrayList<>();
|
||||
|
||||
public Storage(FileConfiguration conf) {
|
||||
Set<String> keys = conf.getConfigurationSection("Translations").getKeys(false);
|
||||
for (String key : keys) {
|
||||
HashMap<Short, String> entry = new HashMap<>();
|
||||
Set<String> subKeys = conf.getConfigurationSection("Translations.".concat(key)).getKeys(false);
|
||||
for (String subKey : subKeys) {
|
||||
entry.put(Short.parseShort(subKey), color(conf.getString("Translations.".concat(key).concat(".")
|
||||
.concat(subKey))));
|
||||
}
|
||||
|
||||
TRANSLATIONS.put(key, entry);
|
||||
}
|
||||
CONFIG_VERSION = conf.getInt("config-version");
|
||||
LIMIT = conf.getInt("limit");
|
||||
List<String> added = conf.getStringList("placeholders");
|
||||
PLACEHOLDERS = ImmutableList.copyOf(added);
|
||||
NAME_FORMAT = color(conf.getString("name-format"));
|
||||
AMOUNT_FORMAT = color(conf.getString("amount-format"));
|
||||
COLOR_IF_ALREADY_COLORED = conf.getBoolean("color-if-already-colored");
|
||||
FORCE_ADD_AMOUNT = conf.getBoolean("force-add-amount");
|
||||
DENY_IF_NO_ITEM = conf.getBoolean("deny-if-no-item");
|
||||
DENY_MESSAGE = color(conf.getString("deny-message"));
|
||||
LIMIT_MESSAGE = color(conf.getString("limit-message"));
|
||||
RELOAD_MESSAGE = color(conf.getString("reload-success"));
|
||||
final List<String> cmds = conf.getStringList("commands");
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(ChatItem.getInstance(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for(String s : cmds){
|
||||
Command c = Bukkit.getPluginCommand(s);
|
||||
if(c!=null) {
|
||||
ALLOWED_COMMANDS.add(Bukkit.getPluginCommand(s));
|
||||
}
|
||||
else
|
||||
ChatItem.getInstance().getLogger().log(Level.WARNING, ChatColor.RED.toString().concat("Unknown command ")
|
||||
.concat(s).concat(" found in config! Ignoring occurrence..."));
|
||||
}
|
||||
}
|
||||
}, 100L);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static String color(String s) {
|
||||
return ChatColor.translateAlternateColorCodes('&', s);
|
||||
}
|
||||
|
||||
|
||||
void performOverwrite() {
|
||||
ChatItem.getInstance().saveResource("config.yml", true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
package me.dadus33.chatitem.utils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.ConnectException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.TreeMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
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.ChatManager;
|
||||
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulator;
|
||||
import me.dadus33.chatitem.playerversion.PlayerVersionManager;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
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.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 static final Pattern UUID_PATTERN = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$");
|
||||
private static final TreeMap<Integer, String> ROMAN_KEYS = new TreeMap<>();
|
||||
private static final HashMap<String, String> ENCHANTS_NAMES = new HashMap<>();
|
||||
|
||||
static {
|
||||
ROMAN_KEYS.put(1000, "M");
|
||||
ROMAN_KEYS.put(900, "CM");
|
||||
ROMAN_KEYS.put(500, "D");
|
||||
ROMAN_KEYS.put(400, "CD");
|
||||
ROMAN_KEYS.put(100, "C");
|
||||
ROMAN_KEYS.put(90, "XC");
|
||||
ROMAN_KEYS.put(50, "L");
|
||||
ROMAN_KEYS.put(40, "XL");
|
||||
ROMAN_KEYS.put(10, "X");
|
||||
ROMAN_KEYS.put(9, "IX");
|
||||
ROMAN_KEYS.put(5, "V");
|
||||
ROMAN_KEYS.put(4, "IV");
|
||||
ROMAN_KEYS.put(1, "I");
|
||||
|
||||
ENCHANTS_NAMES.put("ARROW_DAMAGE", "Power");
|
||||
ENCHANTS_NAMES.put("ARROW_FIRE", "Flame");
|
||||
ENCHANTS_NAMES.put("ARROW_INFINITE", "Infinity");
|
||||
ENCHANTS_NAMES.put("ARROW_KNOCKBACK", "Punch");
|
||||
ENCHANTS_NAMES.put("BINDING_CURSE", "Curse of Binding");
|
||||
ENCHANTS_NAMES.put("DAMAGE_ALL", "Sharpness");
|
||||
ENCHANTS_NAMES.put("DAMAGE_ARTHROPODS", "Bane of Arthropods");
|
||||
ENCHANTS_NAMES.put("DAMAGE_UNDEAD", "Smite");
|
||||
ENCHANTS_NAMES.put("DEPTH_STRIDER", "Depth Strider");
|
||||
ENCHANTS_NAMES.put("DIG_SPEED", "Efficiency");
|
||||
ENCHANTS_NAMES.put("DURABILITY", "Unbreaking");
|
||||
ENCHANTS_NAMES.put("FIRE_ASPECT", "Fire Aspect");
|
||||
ENCHANTS_NAMES.put("FROST_WALKER", "Frost Walker");
|
||||
ENCHANTS_NAMES.put("KNOCKBACK", "Knockback");
|
||||
ENCHANTS_NAMES.put("LOOT_BONUS_BLOCKS", "Fortune");
|
||||
ENCHANTS_NAMES.put("LOOT_BONUS_MOBS", "Looting");
|
||||
ENCHANTS_NAMES.put("LUCK", "Luck of the Sea");
|
||||
ENCHANTS_NAMES.put("LURE", "Lure");
|
||||
ENCHANTS_NAMES.put("MENDING", "Mending");
|
||||
ENCHANTS_NAMES.put("OXYGEN", "Respiration");
|
||||
ENCHANTS_NAMES.put("PROTECTION_ENVIRONMENTAL", "Protection");
|
||||
ENCHANTS_NAMES.put("PROTECTION_EXPLOSIONS", "Blast Protection");
|
||||
ENCHANTS_NAMES.put("PROTECTION_FALL", "Feather Falling");
|
||||
ENCHANTS_NAMES.put("PROTECTION_FIRE", "Fire Protection");
|
||||
ENCHANTS_NAMES.put("PROTECTION_PROJECTILE", "Projectile Protection");
|
||||
ENCHANTS_NAMES.put("SILK_TOUCH", "Silk Touch");
|
||||
ENCHANTS_NAMES.put("SWEEPING_EDGE", "Sweeping Edge");
|
||||
ENCHANTS_NAMES.put("THORNS", "Thorns");
|
||||
ENCHANTS_NAMES.put("VANISHING_CURSE", "Cure of Vanishing");
|
||||
ENCHANTS_NAMES.put("WATER_WORKER", "Aqua Affinity");
|
||||
}
|
||||
|
||||
public static List<Player> getOnlinePlayers() {
|
||||
return new ArrayList<>(Bukkit.getOnlinePlayers());
|
||||
}
|
||||
|
||||
public static String toRoman(int number) {
|
||||
int l = ROMAN_KEYS.floorKey(number);
|
||||
if (number == l) {
|
||||
return ROMAN_KEYS.get(number);
|
||||
}
|
||||
return ROMAN_KEYS.get(l) + toRoman(number - l);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static String getEnchantName(Enchantment enchant) {
|
||||
String name = ENCHANTS_NAMES.get(enchant.getName());
|
||||
if (name == null) {
|
||||
ChatItem.getInstance().getLogger()
|
||||
.warning("Unknown enchant " + enchant.getName() + ". Please report this to Elikill58.");
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public static String getFromURL(String urlName) {
|
||||
ChatItem pl = ChatItem.getInstance();
|
||||
try {
|
||||
URL url = new URL(urlName);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setUseCaches(true);
|
||||
connection.setConnectTimeout(5000);
|
||||
connection.setReadTimeout(5000);
|
||||
connection.setRequestProperty("User-Agent", "ChatItem " + pl.getDescription().getVersion());
|
||||
connection.setDoOutput(true);
|
||||
connection.setRequestMethod("GET");
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
StringBuilder content = new StringBuilder();
|
||||
String input;
|
||||
while ((input = br.readLine()) != null)
|
||||
content.append(input);
|
||||
br.close();
|
||||
return content.toString();
|
||||
} catch (SocketTimeoutException e) {
|
||||
pl.getLogger().info("Failed to access to " + urlName + " (Reason: timed out).");
|
||||
} catch (UnknownHostException | MalformedURLException e) {
|
||||
pl.getLogger().info("Could not use the internet connection to check for update or send stats");
|
||||
} catch (ConnectException e) {
|
||||
pl.getLogger().warning("Cannot connect to " + urlName + " (Reason: " + e.getMessage() + ").");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int indexOf(CharSequence s, CharSequence searched, int i) {
|
||||
return s.toString().indexOf(searched.toString(), i);
|
||||
}
|
||||
|
||||
public static boolean isEmpty(CharSequence s) {
|
||||
return (s == null || s.length() == 0);
|
||||
}
|
||||
|
||||
public static int countMatches(CharSequence str, CharSequence searched) {
|
||||
if (isEmpty(str) || isEmpty(searched))
|
||||
return 0;
|
||||
byte b = 0;
|
||||
int i = 0;
|
||||
while ((i = indexOf(str, searched, i)) != -1) {
|
||||
b++;
|
||||
i += searched.length();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
public static boolean isBeforeChatJson(Player p) {
|
||||
return !PlayerVersionManager.getPlayerVersionAdapter().getPlayerVersion(p).isNewerOrEquals(Version.V1_16) && Version.getVersion().isNewerOrEquals(Version.V1_16);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static HoverEvent createItemHover(ItemStack item, Player to) {
|
||||
if(isBeforeChatJson(to)) {
|
||||
ComponentBuilder comp = new ComponentBuilder("");
|
||||
for(String line : ChatManager.getMaxLinesFromItem(to, item))
|
||||
comp.append(line + "\n");
|
||||
return createTextHover(comp.create());
|
||||
}
|
||||
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 ClickEvent createRunCommand(String command) {
|
||||
return new ClickEvent(ClickEvent.Action.RUN_COMMAND, command);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isUUID(String s) {
|
||||
return s != null && UUID_PATTERN.matcher(s.toLowerCase()).matches();
|
||||
}
|
||||
|
||||
public static YamlConfiguration copyLoadFile(File folder, String filename, String baseFile) {
|
||||
File legacyConfig = new File(folder, filename);
|
||||
if(!legacyConfig.exists())
|
||||
copyFile(baseFile, legacyConfig);
|
||||
return YamlConfiguration.loadConfiguration(legacyConfig);
|
||||
}
|
||||
|
||||
public static void copyFile(String fileName, File dir) {
|
||||
try (InputStream stream = ChatItem.getInstance().getResource(fileName)) {
|
||||
Files.copy(stream, dir.toPath());
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static String arrayToString(Object[] a) {
|
||||
StringJoiner sj = new StringJoiner(", ");
|
||||
for(Object o : a)
|
||||
sj.add(o == null ? "null" : o.toString());
|
||||
return sj.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package me.dadus33.chatitem.utils;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import me.dadus33.chatitem.ChatItem;
|
||||
|
||||
public enum Version {
|
||||
|
||||
// http://wiki.vg/Protocol_version_numbers
|
||||
V1_7(0, 5, 7),
|
||||
V1_8(6, 47, 8),
|
||||
V1_9(49, 110, 9), // 1.9.X - Starts with 49 as 48 was an april fools update
|
||||
V1_10(201, 210, 10), // 1.10.X - Starts with 201 because why not.
|
||||
V1_11(301, 316, 11),
|
||||
V1_12(317, 340, 12),
|
||||
V1_13(341, 440, 13),
|
||||
V1_14(441, 500, 14),
|
||||
V1_15(550, 578, 15),
|
||||
V1_16(700, 754, 16),
|
||||
V1_17(755, 756, 17),
|
||||
V1_18(757, 758, 18),
|
||||
V1_19(759, 762, 19),
|
||||
V1_20(763, 1000, 20),
|
||||
HIGHER(Integer.MAX_VALUE, -1, Integer.MAX_VALUE);
|
||||
|
||||
// Latest version should always have the upper limit set to Integer.MAX_VALUE so
|
||||
// I don't have to update the plugin for every minor protocol change
|
||||
|
||||
public final int MIN_VER;
|
||||
public final int MAX_VER;
|
||||
public final int index; // Represents how new the version is (0 - extremely old)
|
||||
|
||||
private static final Version SERVER_VERSION;
|
||||
public static final String BUKKIT_VERSION;
|
||||
|
||||
static {
|
||||
BUKKIT_VERSION = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
|
||||
SERVER_VERSION = getVersionByName(BUKKIT_VERSION);
|
||||
}
|
||||
|
||||
Version(int min, int max, int index) {
|
||||
this.MIN_VER = min;
|
||||
this.MAX_VER = max;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public boolean isNewerOrEquals(Version other) {
|
||||
return index >= other.index;
|
||||
}
|
||||
|
||||
public boolean isNewerThan(Version other) {
|
||||
return index > other.index;
|
||||
}
|
||||
|
||||
public static Version getVersionByName(String name) {
|
||||
for (Version v : Version.values())
|
||||
if (name.toLowerCase().startsWith(v.name().toLowerCase()))
|
||||
return v;
|
||||
return HIGHER;
|
||||
}
|
||||
|
||||
public static Version getVersion(int protocolVersion) {
|
||||
for (Version ver : Version.values()) {
|
||||
if (protocolVersion >= ver.MIN_VER && protocolVersion <= ver.MAX_VER) {
|
||||
return ver;
|
||||
}
|
||||
}
|
||||
return HIGHER;
|
||||
}
|
||||
|
||||
public static Version getVersion(int protocolVersion, Version def) {
|
||||
for (Version ver : Version.values()) {
|
||||
if (protocolVersion >= ver.MIN_VER && protocolVersion <= ver.MAX_VER) {
|
||||
return ver;
|
||||
}
|
||||
}
|
||||
ChatItem.debug("Failed to find version for protocol " + protocolVersion);
|
||||
return def;
|
||||
}
|
||||
|
||||
public static Version getVersion() {
|
||||
return SERVER_VERSION;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
+274
-79
@@ -1,83 +1,278 @@
|
||||
#Config for ChatItem
|
||||
#For info visit
|
||||
#https://www.spigotmc.org/resources/chatitem.19064/
|
||||
# Config for ChatItem
|
||||
# For info visit
|
||||
# Spigotmc: https://www.spigotmc.org/resources/19064/
|
||||
# Discord: https://discord.gg/yng5PPf62h
|
||||
|
||||
# Version info, DON'T TOUCH
|
||||
config-version: 13
|
||||
|
||||
# By default, it's in "both" mode.
|
||||
#
|
||||
# Available mode :
|
||||
# - "both" : Prevent chat editing with multiple plugins by using all ways possible to edit the chat.
|
||||
# - "auto" : Choose automatically between all available according to actual plugins.
|
||||
# - "packet" : The working system for 1.4's ChatItem version (and older)
|
||||
# It was working with lot of others chat plugin, specially those who made hover text.
|
||||
# - "chat" : New system which works without other chat plugin, which is simpler and with lower
|
||||
# amount of possible issues.
|
||||
# You can replace 'both' by another mode that should correspond to what you want.
|
||||
# If you don't know which one use, come on discord (link at begin of config or in spigotmc)
|
||||
manager: "both"
|
||||
|
||||
#Version info, DON'T TOUCH
|
||||
config-version: 6
|
||||
#General configuration
|
||||
general:
|
||||
# The placeholders to display an item in chat.
|
||||
placeholders:
|
||||
- "[i]"
|
||||
- "{i}"
|
||||
- "[item]"
|
||||
- "{item}"
|
||||
other-placeholders:
|
||||
# Show what is in the head
|
||||
helmet:
|
||||
# Enable it or not
|
||||
enabled: true
|
||||
# Disallow showing empty item
|
||||
deny-if-no-item: true
|
||||
# Placeholders to use in chat
|
||||
keys:
|
||||
- "[head]"
|
||||
- "{head}"
|
||||
# Show the CHESTPLATE not the enderchest or whatever
|
||||
chestplate:
|
||||
enabled: true
|
||||
deny-if-no-item: true
|
||||
keys:
|
||||
- "[chest]"
|
||||
- "{chest}"
|
||||
# Show leggings
|
||||
leggings:
|
||||
enabled: true
|
||||
deny-if-no-item: true
|
||||
keys:
|
||||
- "[legs]"
|
||||
- "{legs}"
|
||||
# Show what is their feets
|
||||
boots:
|
||||
enabled: false
|
||||
deny-if-no-item: true
|
||||
keys:
|
||||
- "[feet]"
|
||||
- "{feet}"
|
||||
inventory:
|
||||
enabled: true
|
||||
deny-if-no-item: true
|
||||
# Time in minute before the placeholder expire
|
||||
time-expire: 1800
|
||||
keys:
|
||||
- "[inv]"
|
||||
- "{inv}"
|
||||
enderchest:
|
||||
enabled: true
|
||||
deny-if-no-item: true
|
||||
# Time in minute before the placeholder expire
|
||||
time-expire: 1800
|
||||
keys:
|
||||
- "[ec]"
|
||||
- "{ec}"
|
||||
|
||||
# The format of the item placeholders.
|
||||
name-format: "&b&l&o{name}{amount}&r"
|
||||
# The format of the {amount} placeholder.
|
||||
# {times} correspond to amount of item
|
||||
amount-format: " x{times}"
|
||||
# Should we use the translated item name or the custom name of an item
|
||||
color-if-already-colored: true
|
||||
# Should we always show the amount, even if it's just one
|
||||
force-add-amount: true
|
||||
# Should we let the message through, as-is (with the placeholder not replaced)
|
||||
# if the user doesn't have permission or if the user is on cooldown?
|
||||
let-message-through: true
|
||||
# Should we allow users to show their hands off
|
||||
deny-if-no-item: false
|
||||
# If the above (deny-if-no-item) is set to false, what should the placeholder be replaced with?
|
||||
# Bellow you can configure that behaviour.
|
||||
hand:
|
||||
# Should we completely disable users being able to show their hands off
|
||||
disabled: false
|
||||
# The name of the hand chat message.
|
||||
name: "&b&l&o{display-name}&b&l&o's hand"
|
||||
# The lore of the hand chat message.
|
||||
tooltip:
|
||||
- "&7Nothing to see here"
|
||||
- "&7Just the empty hand of {display-name}."
|
||||
# Manage what is showed for bugged client.
|
||||
# Specially lunar client with old version (1.7)
|
||||
bugged_client:
|
||||
# You can try to show the most informations as possible:
|
||||
# item name & lore. You will not see specific item meta-data
|
||||
# Or just show the bugged tooltip.
|
||||
#
|
||||
# Action available:
|
||||
# nothing: no hover
|
||||
# item: only try to get values from item
|
||||
# tooltip: only show tooltip
|
||||
# show_both: show item & tooltip below
|
||||
action: "show_both"
|
||||
tooltip:
|
||||
- "&7Failed to parse item for your client"
|
||||
|
||||
# Format used with using /chatitem show
|
||||
command-format: "&6%name%'s item is %item%"
|
||||
|
||||
#The placeholders you want to use for the item. You can add as many as you want.
|
||||
placeholders:
|
||||
- "[i]"
|
||||
- "{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.
|
||||
show-no-permission-message:
|
||||
normal: true
|
||||
command: false
|
||||
# Manage permission to use placeholders
|
||||
permission:
|
||||
enabled: false
|
||||
name: "chatitem.use"
|
||||
# Here you can set the limit on how many placeholders a user is allowed to use inside a message.
|
||||
# Allowing too many placeholders can result in client crashes.
|
||||
limit: 8
|
||||
# The cooldown, in seconds, between allowing players to send messages with items. Setting this to 0
|
||||
# will remove the cooldown entirely.
|
||||
cooldown: 60
|
||||
# All items that are not allowed to be showed
|
||||
ignored_items:
|
||||
- "SOME_ITEM"
|
||||
# Check if the plugin have update
|
||||
check-update: true
|
||||
language: "en_gb"
|
||||
sub-commands:
|
||||
broadcast: true
|
||||
show: true
|
||||
|
||||
|
||||
# Messages section. You can disable any of them by simply leaving them empty, like this: ""
|
||||
messages:
|
||||
# The message sent if showing off hands is disabled and the user isn't holding an item.
|
||||
# Only works if 'General.deny-if-no-item' is set to true!
|
||||
deny-message: "&c&lYou have no item in hand!"
|
||||
# The message sent after the configuration file is successfully reloaded.
|
||||
reload-success: "&b&lSuccessful reload!"
|
||||
# The message sent if the player is on cooldown from sending a placeholder.
|
||||
cooldown-message: "&c&lYou can only use items in chat once a minute! You have {remaining} left!"
|
||||
# The message sent if the no permission messages are enabled and the user doesn't have permission to send an item placeholder.
|
||||
no-permission: "&c&lI'm sorry, but you are not allowed to use the placeholder in chat!"
|
||||
# The message sent if the player uses more placeholders than configured in one message.
|
||||
limit-message: "&c&lYou can only add 8 item placeholders per message!"
|
||||
# When trying to show item that is ignored
|
||||
ignored-item: "&cThis item is not allowed to be showed."
|
||||
# All message about the update of the plugin
|
||||
join-update:
|
||||
message: "&cA new version of ChatItem is available. &aClick here to download."
|
||||
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:
|
||||
- "&6/chatitem admin : &7Manage some options"
|
||||
- "&6/chatitem links : &7See all links which are usefull"
|
||||
links:
|
||||
begin: "&aAll usefull links: "
|
||||
list:
|
||||
1:
|
||||
message: "\n&7- &eSpigotmc updates"
|
||||
hover: "&6Click to go to spigot page !"
|
||||
link: "https://www.spigotmc.org/resources/19064/"
|
||||
2:
|
||||
message: " "
|
||||
3:
|
||||
message: "&7(Original author: &aDadus33"
|
||||
hover: "&6See &aDadus33&6's profile"
|
||||
link: "https://www.spigotmc.org/members/10224/"
|
||||
4:
|
||||
message: "&7, "
|
||||
5:
|
||||
message: "&7Maintainer: &aElikill58&7)"
|
||||
hover: "&6See &aElikill58&6's profile"
|
||||
link: "https://www.spigotmc.org/members/310762/"
|
||||
6:
|
||||
message: "\n&7- &6Support on discord"
|
||||
hover: "&6Click to open discord !"
|
||||
link: "https://discord.gg/yng5PPf62h"
|
||||
# All messages in admin inventory
|
||||
admin-inv:
|
||||
name: "ChatItem - Admin"
|
||||
close: "Close"
|
||||
# Generic lores for options items
|
||||
amount-lore:
|
||||
- "&aLeft-click: &6+1"
|
||||
- "&aRight-click: &6-1"
|
||||
bool-lore:
|
||||
- "&7Click to enable/disable"
|
||||
# Name of options items
|
||||
color-if-already-colored: "&6Color if already colored: %state%"
|
||||
deny-no-item: "&6Deny without item: %state%"
|
||||
hand-disabled: "&6Hand disabled: %state%"
|
||||
limit-per-message: "&6Limit per message: &a%state%"
|
||||
cooldown: "&6Cooldown: &a%state%"
|
||||
debug: "&6Debug: &a%state%"
|
||||
check-update: "&6Check updates: &a%state%"
|
||||
language:
|
||||
name: "&6Change language"
|
||||
lore: "&7Actual: &e%name%"
|
||||
# Change name and lore of all managers
|
||||
manager:
|
||||
both:
|
||||
name: "&6Use both manager&7: &aPacket & Chat"
|
||||
lore:
|
||||
- "&aTry both manager. Very usefull when you have lot of plugins"
|
||||
- "&eIt enable to use ChatItem for all type of messages"
|
||||
- ""
|
||||
- "&7Since ChatItem v2.1"
|
||||
auto:
|
||||
name: "&6Choose automatically"
|
||||
lore:
|
||||
- "&aChoose automatically between managers available"
|
||||
- "&aaccording to actuals plugins."
|
||||
- "&eThis is better when you are not using own plugin."
|
||||
- ""
|
||||
- "&7Since ChatItem v2.1"
|
||||
packet:
|
||||
name: "&6Intercept packets"
|
||||
lore:
|
||||
- "&aChange message sent directly by intercepting packet"
|
||||
- "&aCan use &6ProtocolLib &aif present."
|
||||
- "&cCan have error with &e/cir &c!"
|
||||
- ""
|
||||
- "&7Originally made until ChatItem v1.4"
|
||||
chat:
|
||||
name: "&6Change basic message"
|
||||
lore:
|
||||
- "&aVery quick and usefull for server without plugin message !"
|
||||
- "&aIt enable to use ChatItem without packet reading."
|
||||
- "&eIt's more optimized than others manager"
|
||||
- ""
|
||||
- "&7Since ChatItem v2.0"
|
||||
# The item that show the actual manager
|
||||
actual:
|
||||
name: '&6Actual manager: %manager%'
|
||||
lore: []
|
||||
# All the fields bellow shold be translated in your own language. Those will be used in the {remaining} format of the cooldown message.
|
||||
# You should leave a space as a PREFIX as we will add a number in front of them
|
||||
seconds: " seconds"
|
||||
minutes: " minutes"
|
||||
hours: " hours"
|
||||
enabled: "&aEnabled"
|
||||
disabled: "&cDisabled"
|
||||
seeinv_not_found: "&cImpossible to find this inventory. Are you coming too late ?"
|
||||
inventory:
|
||||
name: "%cible%'s inventory"
|
||||
chat: "%cible%'s inventory"
|
||||
hover: "&7Click to see inventory"
|
||||
enderchest:
|
||||
name: "%cible%'s enderchest"
|
||||
chat: "%cible%'s enderchest"
|
||||
hover: "&7Click to see enderchest"
|
||||
|
||||
# How will the item be displayed in chat? {name} represents the display name of
|
||||
# the item, or material name (ex. DIAMOND_SWORD) if it doesn't have a customized
|
||||
# display name, and {amount} will be replaced by the amount-format configured bellow.
|
||||
# You can use color codes.
|
||||
name-format: "&f<&b&l&o{name} {amount}&f>&r"
|
||||
|
||||
# The amount format that will replace the {amount} placeholder in the 'name-format'
|
||||
# field above. The {times} placeholder represents the number of times the item is
|
||||
# presented in the itemstack, in other words, the actual item amount in the stack
|
||||
# the player holds. You can use color codes too.
|
||||
amount-format: "x{times}"
|
||||
|
||||
# Should we apply the color and formatting defined in the name-format field even if
|
||||
# the item is already colored/formated (ex. From anvils or other plugins that change
|
||||
# the display name of an item). I recommend leaving this to true as not applying color
|
||||
# codes or formatting at all can lead to an unexpected output compared to what you
|
||||
# actually want, but feel free to experiment with it ;)
|
||||
color-if-already-colored: true
|
||||
|
||||
# Should we add the item amount even if there's only one item in the stack?
|
||||
force-add-amount: true
|
||||
|
||||
# Should we cancel the user message if the item in his (main) hand is air or null? (No item in hand, that is)
|
||||
deny-if-no-item: true
|
||||
|
||||
# If so, what message should the user get upon attempting to send such a message? Set to "" to disable.
|
||||
deny-message: "&c&lYou have no item in hand!"
|
||||
|
||||
# The message you will get after reloading the plugin using /cireload.
|
||||
reload-success: "&b&lSuccessful reload!"
|
||||
|
||||
# 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.
|
||||
# Care should be taken with vanilla commands as those are not supported!
|
||||
commands:
|
||||
- "msg"
|
||||
|
||||
# Here you can set the limit on how many placeholders a user is allowed to use inside a message.
|
||||
# Allowing too many placeholders can result in client crashes.
|
||||
limit: 5
|
||||
|
||||
# The message a player will get when attempting to send a message with more placeholders then the allowed limit.
|
||||
limit-message: "&c&lYou can only add 5 item placeholders per message!"
|
||||
|
||||
|
||||
|
||||
# Translations
|
||||
Translations:
|
||||
STONE:
|
||||
1: "Granite"
|
||||
# The above field is a little more complicated, but I'll explain you:
|
||||
# You may have noticed that (until now) if using the placeholder
|
||||
# with an item such as Granite in hand, (unless it's display name
|
||||
# is changed) the item will display in chat as (for granite) Stone.
|
||||
# That happens because the plugin is set to use the material
|
||||
# name of the item if no custom displayname is found on it.
|
||||
# The material name for both stone and granite is STONE, the
|
||||
# only difference being the data value, stone being STONE:0
|
||||
# and granite being STONE:1. In order to make things more user
|
||||
# friendly, I implemented this translation feature. Here's how it works:
|
||||
# If you want to display STONE:1 as GRANITE in chat, you should
|
||||
# add the following line under translations:
|
||||
# STONE:
|
||||
# 1: "Granite"
|
||||
# STONE represents the material name of the item, while it's sub-section
|
||||
# '1' represents the data value of the item. The thing that comes next is
|
||||
# what should actually be displayed in chat.
|
||||
# You can find a list of item materials and data values
|
||||
# here: http://www.minecraftinfo.com/idlist.html
|
||||
# If ChatItem send message using DiscordSRV
|
||||
# This option will be ignored if you don't have it
|
||||
discord-srv-send-our: true
|
||||
@@ -0,0 +1 @@
|
||||
{"block.minecraft.brown_terracotta":"Bruin Terracotta","block.minecraft.lapis_ore":"Lasuurerts","item.minecraft.gray_dye":"Grys Kleurstof","block.minecraft.banner.base.yellow":"Ten volle geel veld","block.minecraft.terracotta":"Terracotta","item.minecraft.stray_spawn_egg":"Nagelaate Kuit Eier","block.minecraft.banner.base.pink":"Ten volle pienk veld","item.minecraft.potion.effect.weakness":"Swakheid Doepa","block.minecraft.dark_prismarine_slab":"Donker Prismaryn blad","item.minecraft.splash_potion.effect.thick":"Dik Spatdoepa","item.minecraft.cooked_cod":"Gaar Kabeljou","block.minecraft.red_nether_brick_slab":"Rooi Laer Baksteen Blad","block.minecraft.yellow_terracotta":"Geel Terracotta","block.minecraft.observer":"Waarnemer","block.minecraft.banner.stripe_bottom.cyan":"Siaan Basis","block.minecraft.banner.creeper.purple":"Pers Creeper Gelaai","block.minecraft.banner.straight_cross.cyan":"Siaan Kruis","block.minecraft.banner.half_horizontal_bottom.brown":"Omgekeerde Bruin Dwarsstreep","item.minecraft.firework_star.shape.large_ball":"Groot Bal","block.minecraft.prismarine_brick_slab":"Prismaryn Baksteen Blad","block.minecraft.jungle_trapdoor":"Oerwoudhout Valdeur","block.minecraft.sculk_sensor":"Sculk Sensor","block.minecraft.banner.creeper.orange":"Oranje Creeper Gelaai","block.minecraft.banner.triangles_top.lime":"Lemmetjie Groen Ingekeepde Hoof","item.minecraft.charcoal":"Houtskool","item.minecraft.tipped_arrow.effect.night_vision":"Pyl van Nagsig","block.minecraft.stone_brick_slab":"Klipsteenblad","block.minecraft.banner.mojang.cyan":"Siaan Ding","block.minecraft.white_stained_glass":"Wit Glas","item.minecraft.bowl":"Hout Bak","block.minecraft.banner.diagonal_up_left.magenta":"Magenta Per draai omgekeerde","block.minecraft.banner.square_top_right.light_gray":"Ligte Grys Hoof Sinistere Kanton","block.minecraft.dead_brain_coral_fan":"Dooie Gespreide Breinkoraal","block.minecraft.banner.flower.white":"Wit Blom Lading","item.minecraft.bone_meal":"Beenmeel","block.minecraft.banner.triangle_bottom.red":"Rooi Chevron","block.minecraft.cyan_carpet":"Siaan Mat","block.minecraft.oak_door":"Eikehout Deur","block.minecraft.flowering_azalea_leaves":"Blomdraende Azalea Blare","item.minecraft.prismarine_crystals":"Prismaryn Kristalle","block.minecraft.banner.diagonal_left.cyan":"Siaan Per draai Sinister","block.minecraft.banner.stripe_bottom.light_blue":"Ligte Blou Basis","item.minecraft.tipped_arrow.effect.slow_falling":"Pyl van Stadig Val","block.minecraft.end_stone":"Endsteen","block.minecraft.potted_white_tulip":"Gopotte Wit Tulp","block.minecraft.warped_door":"Vreemde Deur","block.minecraft.banner.square_top_left.light_gray":"Ligte Grys Hoof Dexter Kanton","item.minecraft.splash_potion.effect.fire_resistance":"Brandbestandheid Spatdoepa","block.minecraft.banner.half_vertical_right.pink":"Omgekeerde Paars Per Bleek","item.minecraft.furnace_minecart":"Koekepan Enjin","block.minecraft.banner.triangles_bottom.light_gray":"Ligte Grys Ingekeepde Basis","item.minecraft.shield.red":"Rooi Skild","block.minecraft.quartz_pillar":"Kwarts Pilaar","block.minecraft.prismarine_slab":"Prismaryn Blad","block.minecraft.nether_portal":"Laer Ingang","item.minecraft.diamond_sword":"Diamant Swaard","block.minecraft.oak_planks":"Eikehout Planke","item.minecraft.amethyst_shard":"Ametis Skerf","block.minecraft.purple_banner":"Pers Vlag","block.minecraft.structure_void":"Struktuur Leemte","block.minecraft.purple_shulker_box":"Pers Shulker Boks","block.minecraft.potatoes":"Aartappels","block.minecraft.light_blue_bed":"Ligte blou Bed","block.minecraft.yellow_banner":"Geel Banier","item.modifiers.head":"Wanneer dit op die kop is:","item.minecraft.potion.effect.swiftness":"Snelheid Doepa","block.minecraft.glass_pane":"Glaspaneel","block.minecraft.clay":"Klei","block.minecraft.banner.diagonal_right.cyan":"Cyan Per draai","block.minecraft.cut_copper_slab":"Gesnyde Koper Blad","block.minecraft.polished_diorite_slab":"Gepoleerde Dioriet Blad","block.minecraft.banner.piglin.green":"Groen Snoet","item.minecraft.splash_potion.effect.slow_falling":"Spat Doepa van Stadig Val","item.minecraft.book":"Boek","block.minecraft.banner.gradient.brown":"Bruin Gradiënt","block.minecraft.banner.cross.magenta":"Magenta Skuinskruis","block.minecraft.cobblestone_slab":"Steengruisblad","block.minecraft.banner.diagonal_right.purple":"Pers Per draai","block.minecraft.banner.curly_border.gray":"Grys Ingekeepde Borduur","block.minecraft.big_dripleaf":"Groot Drupblaar","block.minecraft.black_shulker_box":"Swart Shulker Boks","block.minecraft.banner.straight_cross.purple":"Pers Kruis","block.minecraft.blackstone_stairs":"Swartsteentrappe","block.minecraft.banner.triangles_top.blue":"Blou Ingekeepde Hoof","block.minecraft.deepslate_tile_slab":"Leisteenteëlblad","block.minecraft.banner.square_top_left.blue":"Blou Hoof Dexter Kanton","block.minecraft.banner.stripe_center.yellow":"Geen Paal","item.minecraft.piglin_banner_pattern.desc":"Snoet","item.minecraft.firework_star.cyLine truncated
|
||||
@@ -0,0 +1 @@
|
||||
{"block.minecraft.brown_terracotta":"طين النضيج البني","block.minecraft.lapis_ore":"خام اللازورد","item.minecraft.gray_dye":"صبغة رمادية","block.minecraft.banner.base.yellow":"حقل أصفر كامل","block.minecraft.terracotta":"طين النضيج","item.minecraft.stray_spawn_egg":"بيضة الضال","block.minecraft.banner.base.pink":"حقل وردي كامل","item.minecraft.potion.effect.weakness":"جرعة الضعف","block.minecraft.dark_prismarine_slab":"بلاطة البريسمارين الداكن","item.minecraft.splash_potion.effect.thick":"رشة الجرعة الكثيفة","item.minecraft.cooked_cod":"سمك قد مطبوخ","block.minecraft.red_nether_brick_slab":"بلاطة طوب النذر الأحمر","block.minecraft.yellow_terracotta":"طين النضيج الأصفر","block.minecraft.observer":"المراقب","block.minecraft.banner.stripe_bottom.cyan":"شريط سفلي سماوي","block.minecraft.banner.creeper.purple":"شعار كريبر بنفسجي","block.minecraft.banner.straight_cross.cyan":"صليب سماوي","block.minecraft.banner.half_horizontal_bottom.brown":"النصف الأسفل ملون بني","item.minecraft.firework_star.shape.large_ball":"كرة كبيرة","block.minecraft.prismarine_brick_slab":"بلاطة طوب البريسمارين","block.minecraft.jungle_trapdoor":"باب أرضي من خشب الأدغال","block.minecraft.sculk_sensor":"مستشعر السكالك","block.minecraft.banner.creeper.orange":"شعار كريبر برتقالي","block.minecraft.banner.triangles_top.lime":"مثلثات علوية ليمونية","item.minecraft.charcoal":"فحم نباتي","item.minecraft.tipped_arrow.effect.night_vision":"سهم الرؤية الليلية","block.minecraft.stone_brick_slab":"بلاطة طوب حجري","block.minecraft.banner.mojang.cyan":"شيء سماوي","block.minecraft.white_stained_glass":"زجاج ابيض","item.minecraft.bowl":"زبدية","block.minecraft.banner.diagonal_up_left.magenta":"النصف السفلي الأيسر أرجواني","block.minecraft.banner.square_top_right.light_gray":"مربع رأسي أيمن رمادي فاتح","block.minecraft.dead_brain_coral_fan":"شعاب مرجان عقلي ميت","block.minecraft.banner.flower.white":"شعار زهرة أبيض","item.minecraft.bone_meal":"مسحوق العظام","block.minecraft.banner.triangle_bottom.red":"مثلث أحمر","block.minecraft.cyan_carpet":"سجاد سماوي","block.minecraft.oak_door":"باب البلوط","block.minecraft.flowering_azalea_leaves":"أوراق الأزاليا المزهرة","item.minecraft.prismarine_crystals":"بلورات البرسمارين","block.minecraft.banner.diagonal_left.cyan":"النصف العلوي الأيسر سماوي","block.minecraft.banner.stripe_bottom.light_blue":"شريط سفلي أزرق فاتح","item.minecraft.tipped_arrow.effect.slow_falling":"سهم السقوط البطيء","block.minecraft.end_stone":"حجر الاند","block.minecraft.potted_white_tulip":"توليب أبيض في وعاء","block.minecraft.warped_door":"باب عجيب","block.minecraft.banner.square_top_left.light_gray":"مربع رأسي أيسر رمادي فاتح","item.minecraft.splash_potion.effect.fire_resistance":"رشة جرعة مقاومة النار","block.minecraft.banner.half_vertical_right.pink":"النصف اليميني ملون وردي","item.minecraft.furnace_minecart":"عربة منجم بفرن","block.minecraft.banner.triangles_bottom.light_gray":"مثلثات سفلية رمادية فاتحة","item.minecraft.shield.red":"درس أحمر","block.minecraft.quartz_pillar":"عمود كوارتز","block.minecraft.prismarine_slab":"بلاطة بريسمارين","block.minecraft.nether_portal":"بوابة النذر","item.minecraft.diamond_sword":"سيف ألماسي","block.minecraft.oak_planks":"ألواح خشب البلوط","item.minecraft.amethyst_shard":"شظية جمشت","block.minecraft.purple_banner":"راية بنفسجية","block.minecraft.structure_void":"فراغ الهيكل","block.minecraft.purple_shulker_box":"صندوق شلكر بنفسجي","block.minecraft.potatoes":"بطاطا","block.minecraft.light_blue_bed":"سرير أزرق فاتح","block.minecraft.yellow_banner":"راية صفراء","item.modifiers.head":"عندما يكون على الرأس:","item.minecraft.potion.effect.swiftness":"جرعة السرعة","block.minecraft.glass_pane":"لوح زجاجي","block.minecraft.clay":"صلصال","block.minecraft.banner.diagonal_right.cyan":"النصف العلوي الأيمن سماوي","block.minecraft.cut_copper_slab":"بلاطة نحاس مقطع","block.minecraft.polished_diorite_slab":"بلاطة ديوريت مصقول","block.minecraft.banner.piglin.green":"أنف أخضر","item.minecraft.splash_potion.effect.slow_falling":"رشة جرعة السقوط البطيء","item.minecraft.book":"كتاب","blockLine truncated
|
||||
Loaded 100 of 224 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user