Compare commits

...
196 Commits
Author SHA1 Message Date
NotAlexNoyle 03eb683d4d Exclude CODEOWNERS from language statistics 2026-10-29 16:18:54 -04:00
NotAlexNoyle b455478be6 Add CODEOWNERS (one staff approval) 2026-10-29 16:18:54 -04:00
NotAlexNoyle 794c341abb Chat-OG compatibility 2026-07-16 18:00:13 -04:00
NotAlexNoyle 21a5fce702 Use live TrueOG Network config file 2026-06-17 08:21:50 -04:00
NotAlexNoyle 02d5f89431 Vault -> LuckPerms 2026-04-25 08:08:04 -04:00
NotAlexNoyle 6ce16a755c Remove ProtocolSupport hook 2026-04-17 15:43:41 -04:00
NotAlexNoyle e0c7b5a725 Merge 1.21.11 client support 2026-03-25 03:06:11 -04:00
Elikill58 b0096e1375 Update default config 2025-12-12 08:58:16 +01:00
Elikill58 ea41f218ae Add support for MC 1.21.11 2025-12-12 08:57:30 +01:00
Elikill58 63542afad4 Prevent NPE 2025-12-08 10:32:29 +01:00
NotAlexNoyle c5d69fa717 Align jar name with project name 2025-08-27 17:21:15 -04:00
NotAlexNoyle e7c4cfe662 Add formatting 2025-08-27 17:19:37 -04:00
NotAlexNoyle 77ca73cef6 Fix build, update gradle to 8.14.3 2025-08-20 09:48:07 -04:00
Elikill58 0927f33506 Fix packet in some cases 2025-04-19 12:18:10 +02:00
Elikill58 f2573439b6 Add clic action 2025-03-29 09:25:38 +01:00
Elikill58 21e9c645d7 Fix packet manager for essentials 2025-03-27 00:02:52 +01:00
Elikill58 cc891bce78 Fix for essentials and maybe some others plugins 2025-03-19 14:16:58 +01:00
Elikill58 7eee07baa3 Add option to see placeholder in console 2025-02-19 08:51:06 +01:00
Elikill58 46a40b2f18 Prevent error 2025-02-11 22:14:26 +01:00
Elikill58 ddcd8bd3e8 FINALLY a fix for 1.20.4 purpur error 2025-01-08 23:55:10 +01:00
Elikill58 2b88a4f3b8 Add parsing for very strange things 2025-01-08 20:29:38 +01:00
Elikill58 3c2d092200 Change order for translation and for content behavior 2024-11-27 19:17:06 +01:00
Elikill58 b1dac86e96 Added messages to config files 2024-11-24 12:49:11 +01:00
Elikill58 4b0c8ef6ff Changes for show commands 2024-11-22 14:25:42 +01:00
Elikill58 02e53a9dd6 Upgrade to snapshot 2024-11-22 13:31:47 +01:00
Elikill58 37f6051794 Fix inventory log error 2024-11-21 20:05:45 +01:00
Elikill58 6280cb211b Drop 1.7 support 2024-11-21 19:58:34 +01:00
Elikill58 6e7554e0a4 Change for inventory listener 2024-11-21 18:25:17 +01:00
Elikill58 6435ea0dad Upgrade to 2.6.2 2024-11-07 22:08:05 +01:00
Elikill58 4e7b14e618 Fix for spigot versions 2024-11-07 21:55:43 +01:00
Elikill58 c9ea8061c8 Fix auto selection 2024-11-07 20:16:18 +01:00
Elikill58 4b966f056e Begin of own formatter 2024-11-07 19:28:23 +01:00
Elikill58 3a2d0ee44d Add placeholders 2024-09-09 11:15:12 +02:00
Elikill58 5ee9cca3d7 Duplicated variable name... 2024-09-04 10:12:16 +02:00
Elikill58 e21f236a09 Prevent IncompatibleClassChangeError error 2024-09-04 10:09:12 +02:00
Elikill58 554dd8ad39 Change for actions 2024-09-03 19:48:05 +02:00
Elikill58 b7a60f1352 Use JDK 21 2024-08-27 23:36:15 +02:00
Elikill58 b8e5e213ae Upgrade github action for pull request 2024-08-27 23:23:07 +02:00
Elikill58 08101a8d18 Upgrade github actions 2024-08-27 23:22:32 +02:00
Elikill58 4ccb543869 Make pull 2024-08-27 22:43:21 +02:00
Elikill58 153667135b Prevent some error on 1.20.6 and 1.21 2024-08-27 22:43:14 +02:00
Elikill58 00ca8ac11b Prevent error 2024-08-23 14:03:47 +02:00
Elikill58 44867e86d8 Merge branch 'v2' of https://github.com/dadus33-plugins/ChatItem into v2 2024-08-20 21:14:51 +02:00
Elikill58 36148b5969 Prevent error with items 2024-08-20 21:14:42 +02:00
Elikill58 103ef2a4f2 Prevent error with unsignedContent 2024-08-20 18:07:01 +02:00
Elikill58 40f67cc41f Upgrade to snapshot 2024-08-20 18:06:32 +02:00
dependabot[bot] df555f7151 Bump com.discordsrv:discordsrv from 1.27.0 to 1.28.1 (#139)
Bumps com.discordsrv:discordsrv from 1.27.0 to 1.28.1.

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-12 10:27:03 +02:00
dependabot[bot] c76c35974c Bump com.viaversion:viaversion-api from 5.0.2 to 5.0.3 (#140)
Bumps com.viaversion:viaversion-api from 5.0.2 to 5.0.3.

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-12 10:23:27 +02:00
Elikill58 81f9711019 Fix typo on config 2024-08-04 21:19:48 +02:00
dependabot[bot] 4edccde81c Bump com.github.MilkBowl:VaultAPI from 1.7 to 1.7.1 (#137)
Bumps [com.github.MilkBowl:VaultAPI](https://github.com/MilkBowl/VaultAPI) from 1.7 to 1.7.1.
- [Release notes](https://github.com/MilkBowl/VaultAPI/releases)
- [Commits](https://github.com/MilkBowl/VaultAPI/compare/1.7...1.7.1)

---
updated-dependencies:
- dependency-name: com.github.MilkBowl:VaultAPI
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-04 21:15:17 +02:00
dependabot[bot] eac6d1c68a Bump com.viaversion:viaversion-api from 4.10.2 to 5.0.2 (#138)
Bumps com.viaversion:viaversion-api from 4.10.2 to 5.0.2.

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-04 21:15:09 +02:00
Elikill58 1914174e42 Upgrade to 2.6.1 2024-08-04 21:12:56 +02:00
Elikill58 4a7f37451a Fix click not included 2024-08-04 11:07:52 +02:00
Elikill58 4d90a80788 Change for paper management 2024-08-04 11:03:57 +02:00
Elikill58 3713ad41af Fix Paper wrong hvoer/click 2024-08-01 23:11:40 +02:00
Elikill58 b8ba6eac69 Changes for adventure 2024-08-01 23:08:15 +02:00
Elikill58 25f8b585b0 Clean imports 2024-07-31 10:27:41 +02:00
Elikill58 746b3b58a0 Fix for some color codes and issues 2024-07-31 10:27:29 +02:00
Elikill58 89f61e0178 Fix wrong paper behavior and end seperator 2024-07-28 01:30:17 +02:00
Elikill58 9d7de56889 Changes for colors 2024-07-28 00:39:16 +02:00
Elikill58 5fb210e841 Add Essentials support 2024-07-26 22:10:35 +02:00
Elikill58 0a9af0d430 Changes for translation 2024-07-26 00:04:29 +02:00
Elikill58 37681d8b27 Add warn 2024-07-25 23:38:23 +02:00
Elikill58 79e03e97bd Fix placeholders not fully removed 2024-07-25 23:35:22 +02:00
Elikill58 db08be3fa8 Fix cmd reload 2024-07-25 22:52:38 +02:00
Elikill58 4133f30701 Prevent init issue with older versions 2024-07-22 23:32:23 +02:00
Elikill58 08434a5df2 Remove auto from inv 2024-07-22 23:25:57 +02:00
Elikill58 ae825569cf Fix Adventure component for newer versions 2024-07-22 23:23:09 +02:00
Elikill58 1a4f95cd80 Fix color issues 2024-07-22 21:05:21 +02:00
Elikill58 4edc061969 Upgrade to snapshot 2024-07-15 23:10:03 +02:00
Elikill58 e508790d9f Upgrade to 2.6 2024-07-13 23:28:20 +02:00
Elikill58 c26259f5e7 Fix error with not json things 2024-07-10 21:23:48 +02:00
Elikill58 62bf8b07fb Fix wrong action 2024-07-08 21:14:51 +02:00
Elikill58 bd93d3e610 Fix wrong key 2024-07-06 10:24:44 +02:00
Elikill58 c0a37084ce Fix ec and inv for packet manager 2024-07-06 01:05:07 +02:00
Elikill58 0f42e22da9 Fix coloring 2024-07-05 20:23:50 +02:00
Elikill58 5e10bb4450 Fix #135 (Wrong spelling of useful) 2024-07-04 16:43:35 +02:00
Elikill58 b88a1ca83e Change for leaded managers 2024-07-03 22:48:04 +02:00
Elikill58 05ae520cf1 Remake of AdventureComponentManager 2024-07-03 22:13:15 +02:00
Elikill58 76123c895d Add vault support and changes for papermc things 2024-06-25 10:33:40 +02:00
Elikill58 4284497bf5 Add more replacers 2024-06-22 11:40:41 +02:00
Elikill58 62a7b10142 Change how the message is send on paper 2024-06-22 11:35:45 +02:00
Elikill58 cd341109de Try to fix for new versions 2024-06-20 20:43:57 +02:00
Elikill58 68fb201855 Changing debug messages 2024-06-16 14:34:23 +02:00
Elikill58 baa4eab53f Fix 1.20.6 detection for spigot 2024-06-16 11:26:16 +02:00
Elikill58 20c5fc3e45 Change for pufferfish and some paper versions 2024-06-16 11:14:37 +02:00
Elikill58 818cd535bb Update EcoEnchants deps 2024-06-15 16:06:19 +02:00
Elikill58 1107b7fe90 Add MVdWPlaceholders 2024-06-15 15:47:00 +02:00
Elikill58 bed3a87c09 Add placeholders 2024-06-15 15:31:42 +02:00
Elikill58 499d0eb93c Possible fix for wrong versions 2024-06-12 19:47:49 +02:00
Elikill58 913d04b96a Don't add formatting as color 2024-05-24 09:31:47 +02:00
Elikill58 497c317d3f Add paper namer 2024-05-24 09:28:28 +02:00
Elikill58 c9d8d52406 Fix NPE for paper 2024-05-24 09:23:13 +02:00
Elikill58 38f8e47b92 Fix for empty items 2024-05-20 22:57:59 +02:00
Elikill58 6fb80712be Fix #133 2024-05-20 22:52:16 +02:00
Elikill58 00ef83bd67 Change for things 2024-05-20 20:49:10 +02:00
Elikill58 1615bdf739 Merge branch 'v2' of https://github.com/Dadus33-plugins/ChatItem into v2 2024-05-16 13:59:13 +02:00
Elikill58 09854352a1 Make cooldown available for everyone 2024-05-16 13:59:07 +02:00
dependabot[bot] c6585bb94a Bump com.viaversion:viaversion-api from 4.10.0 to 4.10.2 (#132)
Bumps com.viaversion:viaversion-api from 4.10.0 to 4.10.2.

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-13 23:26:49 +02:00
Elikill58 1e359523fa Merge branch 'v2' of https://github.com/Dadus33-plugins/ChatItem into v2 2024-05-13 23:26:15 +02:00
Elikill58 885f6b9d7a Fix format code not interpreted 2024-05-13 23:26:09 +02:00
dependabot[bot] f2a49e2f3a Bump com.viaversion:viaversion-api from 4.9.3 to 4.10.0 (#130)
Bumps com.viaversion:viaversion-api from 4.9.3 to 4.10.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-29 09:28:43 +02:00
Elikill58 7c8b61c6eb Fix paper item not fully showed 2024-04-26 19:05:18 +02:00
Elikill58 f502cfa548 Remove warning for paper 2024-04-25 21:44:22 +02:00
Elikill58 fcef1245d6 Upgrade to snapshot 2024-04-25 20:10:42 +02:00
Elikill58 b6c4ad0170 Better support for 'all' new manager 2024-04-25 20:10:23 +02:00
Elikill58 a97710b2c4 Fix conflict with v1 2024-04-25 20:03:49 +02:00
Elikill58 64642cdc58 Added text 2024-04-25 19:20:20 +02:00
Elikill58 9ac6e7abbc Added new paper manager, fix #125 2024-04-25 18:43:34 +02:00
Elikill58 fddf389169 Fix building 2024-04-24 20:38:51 +02:00
Kevin D 3006a7857c [docs] fix wording in readme (#129)
* Fix wording in readme

* Fix a small issue with my changes!
2024-04-24 14:46:16 +02:00
dependabot[bot] e370723a82 Bump com.viaversion:viaversion-api from 4.9.2 to 4.9.3 (#124)
Bumps com.viaversion:viaversion-api from 4.9.2 to 4.9.3.

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-22 09:01:17 +02:00
dependabot[bot] 2a496b9a1a Bump com.discordsrv:discordsrv from 1.26.2 to 1.27.0 (#115)
Bumps com.discordsrv:discordsrv from 1.26.2 to 1.27.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-22 09:00:25 +02:00
daniel-skopek 655304bd52 Fixed putting items from inventory to the GUI (again) (#128)
* Fixed putting items from inventory to the GUI
2024-04-22 08:59:56 +02:00
Elikill58 0081c616d3 [Included in release] Fix #127 2024-04-17 00:00:02 +02:00
Elikill58 824cf62e4c Upgrade to 2.5.1 2024-04-16 22:40:12 +02:00
Elikill58 8f5c90557f Put expire time in config 2024-04-16 22:37:54 +02:00
Elikill58 7e6cb9910c Hide inventory cmd with uuid 2024-04-16 22:30:30 +02:00
Elikill58 0e6f35804d Fix shulker with too many items 2024-04-16 21:53:06 +02:00
Elikill58 fbcfbceaa4 Fix #126 2024-04-09 19:41:37 +02:00
Elikill58 4a6d46d1da Prevent plugin with same name 2024-03-26 20:44:49 +01:00
Elikill58 8779653211 Fix packet size 2024-03-26 20:42:33 +01:00
Elikill58 c4c511315a Change how adventure is 2024-03-06 21:23:18 +01:00
Elikill58 bcc0bbdd2a Upgrade to snapshot 2024-02-09 22:01:14 +01:00
Elikill58 ffe1bb8b44 Add missing placeholder 2024-02-09 20:04:13 +01:00
Elikill58 64cdccc2d1 Add debug 2024-02-09 19:59:34 +01:00
Elikill58 920a055f02 Change how adventure send msg 2024-02-09 19:58:56 +01:00
Elikill58 4d524244d6 Prevent NPE when getting item 2024-02-04 14:35:15 +01:00
daniel-skopek 429e4a597c Fixed putting items from inventory to the GUI (#121) 2024-02-04 14:31:20 +01:00
Elikill58 5a310e3f60 Upgrade to 2.5 2024-01-30 22:50:31 +01:00
Elikill58 58c5f4607f Merge branch 'v2' of https://github.com/dadus33-plugins/ChatItem into v2 2024-01-27 18:34:53 +01:00
Elikill58 b436c73f47 Fix ecoenchants support 2024-01-27 18:34:46 +01:00
Elikill58 806ceea250 Change for adventure 2024-01-25 22:24:27 +01:00
Elikill58 9a4ef0fe5b Fix some issue with primitive 2024-01-23 20:21:51 +01:00
Elikill58 241f80ca3c Fix strange EC 2024-01-22 19:27:01 +01:00
Elikill58 710bbf3163 Prevent inventory click 2024-01-14 12:11:18 +01:00
Elikill58 4ee561c18f Try to send message using discord srv 2024-01-13 11:34:00 +01:00
Elikill58 17754f2dfe Inv and ec for others managers 2024-01-11 22:25:28 +01:00
Elikill58 6a683508d4 Prevent & Fix #114 2024-01-11 22:05:02 +01:00
Elikill58 bcc8ac08f2 Begin of #31 2024-01-11 22:02:35 +01:00
dependabot[bot] 429a664e81 Bump com.willfp:eco from 6.65.5 to 6.66.1 (#109)
Bumps [com.willfp:eco](https://github.com/Auxilor/eco) from 6.65.5 to 6.66.1.
- [Release notes](https://github.com/Auxilor/eco/releases)
- [Commits](https://github.com/Auxilor/eco/compare/6.65.5...6.66.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-11 08:32:27 +01:00
dependabot[bot] 49dadb897a Bump com.viaversion:viaversion-api from 4.8.1 to 4.9.2 (#113)
Bumps com.viaversion:viaversion-api from 4.8.1 to 4.9.2.

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-11 08:31:55 +01:00
Elikill58 3cf54d39a1 Fix #111 2023-12-10 17:33:15 +01:00
Elikill58 187d1212f5 Upgrade to snapshot 2023-12-10 17:27:55 +01:00
Elikill58 d3776e161f Fix #112 2023-12-10 17:27:30 +01:00
Elikill58 010ea46ff2 Add reset color 2023-12-10 11:27:31 +01:00
Elikill58 db8119affd Do not listen on useless thing 2023-11-16 19:28:57 +01:00
Elikill58 484a6b46a0 Merge branch 'v2' of https://github.com/dadus33-plugins/ChatItem into v2 2023-11-06 00:43:33 +01:00
Elikill58 a48f259b99 Fix for 1.20.2 2023-11-06 00:43:27 +01:00
Elikill58 2b9ae264fd Little internal changes 2023-11-05 23:52:00 +01:00
dependabot[bot] 207b066ecb Bump com.github.Auxilor:EcoEnchants from 10.36.1 to 10.39.1 (#105)
Bumps [com.github.Auxilor:EcoEnchants](https://github.com/Auxilor/EcoEnchants) from 10.36.1 to 10.39.1.
- [Release notes](https://github.com/Auxilor/EcoEnchants/releases)
- [Commits](https://github.com/Auxilor/EcoEnchants/compare/10.36.1...10.39.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 11:08:13 +01:00
Elikill58 587432269a Upgrade to 2.4.9 2023-10-09 23:36:05 +02:00
dependabot[bot] a080e18571 Bump EcoEnchants 10.36.1 (#99)
Bumps [com.github.Auxilor:EcoEnchants](https://github.com/Auxilor/EcoEnchants) from 10.35.3 to 10.36.1.
- [Release notes](https://github.com/Auxilor/EcoEnchants/releases)
- [Commits](https://github.com/Auxilor/EcoEnchants/compare/10.35.3...10.36.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-09 13:57:20 +02:00
dependabot[bot] 7b758882be Bump ProtocolLib to 5.1.0 (#90)
Bumps com.comphenix.protocol:ProtocolLib from 5.0.0 to 5.1.0.

---
updated-dependencies:
- dependency-name: com.comphenix.protocol:ProtocolLib
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-09 13:57:09 +02:00
dependabot[bot] beafc6a635 Bump com.viaversion:viaversion-api from 4.7.0 to 4.8.1 (#102)
Bumps com.viaversion:viaversion-api from 4.7.0 to 4.8.1.

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-09 13:54:52 +02:00
dependabot[bot] 0da4039b70 Bump com.willfp:eco from 6.65.4 to 6.65.5 (#95)
Bumps [com.willfp:eco](https://github.com/Auxilor/eco) from 6.65.4 to 6.65.5.
- [Release notes](https://github.com/Auxilor/eco/releases)
- [Commits](https://github.com/Auxilor/eco/compare/6.65.4...6.65.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 08:16:24 +02:00
dependabot[bot] b89e18b149 Bump com.github.Auxilor:EcoEnchants from 10.35.2 to 10.35.3 (#94)
Bumps [com.github.Auxilor:EcoEnchants](https://github.com/Auxilor/EcoEnchants) from 10.35.2 to 10.35.3.
- [Release notes](https://github.com/Auxilor/EcoEnchants/releases)
- [Commits](https://github.com/Auxilor/EcoEnchants/compare/10.35.2...10.35.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-18 08:15:43 +02:00
Elikill58 07243fbf91 Fix wrong key 2023-09-17 21:59:43 +02:00
Elikill58 4b90aaa070 Prevent no end in message 2023-09-17 11:32:53 +02:00
Elikill58 9d74eb067a Fix #93 2023-09-14 15:56:58 +02:00
dependabot[bot] c51f62a9fb Bump com.github.Auxilor:EcoEnchants from 10.26.5 to 10.35.2 (#92)
Bumps [com.github.Auxilor:EcoEnchants](https://github.com/Auxilor/EcoEnchants) from 10.26.5 to 10.35.2.
- [Release notes](https://github.com/Auxilor/EcoEnchants/releases)
- [Commits](https://github.com/Auxilor/EcoEnchants/compare/10.26.5...10.35.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-14 15:51:07 +02:00
Elikill58 badddd29ed Prevent NPE 2023-08-07 13:01:56 +02:00
Elikill58 d188289e84 Add option for broadcast and show, and change for tab 2023-08-07 11:27:11 +02:00
dependabot[bot] 1b9fd3bf90 Bump com.willfp:eco from 6.65.3 to 6.65.4 (#85)
Bumps com.willfp:eco from 6.65.3 to 6.65.4.

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-07 08:34:36 +02:00
dependabot[bot] 0d98b4408e Bump com.github.Auxilor:EcoEnchants from 10.26.2 to 10.26.5 (#87)
Bumps com.github.Auxilor:EcoEnchants from 10.26.2 to 10.26.5.

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-07 08:34:27 +02:00
dependabot[bot] 769abab65c Bump com.github.Auxilor:EcoEnchants from 10.25.1 to 10.26.2 (#84)
Bumps com.github.Auxilor:EcoEnchants from 10.25.1 to 10.26.2.

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-31 08:14:07 +02:00
Elikill58 78311f60b4 upgrade to snapshot 2023-07-26 19:44:51 +02:00
Elikill58 bd31b5791c Fix for 1.15- players 2023-07-26 19:44:24 +02:00
Elikill58 cd5cfa47ec Fix error with json 2023-07-26 19:27:37 +02:00
Elikill58 d31bdbef68 Remove one import 2023-07-26 19:01:12 +02:00
Elikill58 a82b50b1d0 Fix #78 2023-07-24 11:34:04 +02:00
dependabot[bot] 912bbcf371 Bump com.willfp:eco from 6.65.2 to 6.65.3 (#83)
Bumps com.willfp:eco from 6.65.2 to 6.65.3.

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-24 11:27:03 +02:00
dependabot[bot] af5d63ea93 Bump com.github.Auxilor:EcoEnchants from 10.23.1 to 10.25.1 (#82)
Bumps [com.github.Auxilor:EcoEnchants](https://github.com/Auxilor/EcoEnchants) from 10.23.1 to 10.25.1.
- [Release notes](https://github.com/Auxilor/EcoEnchants/releases)
- [Commits](https://github.com/Auxilor/EcoEnchants/compare/10.23.1...10.25.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-24 11:26:56 +02:00
Elikill58 69681553c8 Fix 1.18 issue 2023-07-20 20:05:58 +02:00
Elikill58 3f6856ddab Fix invocation error 2023-07-20 19:22:39 +02:00
Elikill58 9d55208563 Change ChatControl support 2023-07-19 20:27:14 +02:00
Elikill58 2b8ce53553 Upgrade to 2.4.8 2023-07-17 21:22:52 +02:00
dependabot[bot] 6b157320c4 Bump eco from 6.65.1 to 6.65.2 (#80)
Bumps [eco](https://github.com/Auxilor/eco) from 6.65.1 to 6.65.2.
- [Release notes](https://github.com/Auxilor/eco/releases)
- [Commits](https://github.com/Auxilor/eco/compare/6.65.1...6.65.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-17 07:53:03 +02:00
dependabot[bot] ba3da92061 Bump HexNicks from 3.1.0 to 3.1.1 (#81)
Bumps [HexNicks](https://github.com/MajekDev/HexNicks) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/MajekDev/HexNicks/releases)
- [Changelog](https://github.com/MajekDev/HexNicks/blob/main/CHANGELOG.md)
- [Commits](https://github.com/MajekDev/HexNicks/compare/v3.1.0...v3.1.1)

---
updated-dependencies:
- dependency-name: com.github.MajekDev:HexNicks
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-17 07:52:44 +02:00
Elikill58 dc6ce9c260 Change dep 2023-07-15 20:42:07 +02:00
Elikill58 cf45b8e436 Fix EcoEnchants v10 support 2023-07-15 12:05:00 +02:00
Elikill58 fc8966dab0 Change permissions 2023-06-17 18:18:49 +02:00
Elikill58 c537e72a27 Update versions 2023-06-16 10:26:32 +02:00
Elikill58 dee359a37d Upgrade to snapshot 2023-06-16 09:36:05 +02:00
Elikill58 34f67345e2 Add support for 1.20 2023-06-16 09:35:37 +02:00
Elikill58 d937f5d89e Change discord link in config 2023-06-16 09:09:53 +02:00
Elikill58 856a5f182f Fix error with 1.20 2023-06-16 09:08:52 +02:00
dependabot[bot] 6653b9c057 Bump viaversion-api from 4.6.2 to 4.7.0 (#77)
Bumps viaversion-api from 4.6.2 to 4.7.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-12 17:43:35 +02:00
Elikill58 0b60780fe2 Merge branch 'v2' of https://github.com/dadus33-plugins/ChatItem into v2 2023-06-05 19:59:17 +02:00
Elikill58 a16b2ea462 Don't use one componentManager 2023-06-05 19:59:10 +02:00
Magnetite 05771d975c Add support for hexnicks 3 (#76)
* Add support for hexnicks 3

* Remove empty line
2023-05-31 13:48:25 +02:00
Elikill58 417b63e86d [Include in release] Change default config 2023-05-23 08:12:33 +02:00
Elikill58 01da231510 [Include in release] Quick fix typo for lang 2023-05-23 07:37:17 +02:00
dependabot[bot] 5e2559c1ee Bump ProtocolLib from 5.0.0-SNAPSHOT to 5.0.0 (#75)
Bumps ProtocolLib from 5.0.0-SNAPSHOT to 5.0.0.

---
updated-dependencies:
- dependency-name: com.comphenix.protocol:ProtocolLib
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-15 18:34:59 +02:00
Elikill58 0bb784f7f2 Fix for v2 colors 2023-05-15 18:33:48 +02:00
Elikill58 eef3bf80c8 Fix wrong version check 2023-05-14 21:04:56 +02:00
119 changed files with 10684 additions and 5037 deletions

No files matched your search

+1
View File
@@ -0,0 +1 @@
.gitea/CODEOWNERS linguist-detectable=false
+3
View File
@@ -0,0 +1,3 @@
# Pull requests request review from the eligible staff team(s).
# One approval from either an Admin or Developer satisfies branch protection.
* @trueog/Admins @trueog/Developers
+6 -6
View File
@@ -10,14 +10,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
name: Checkout repo
- name: Set up JDK 17 (LTS)
uses: actions/setup-java@v3
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'adopt'
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Build with Maven
@@ -27,4 +27,4 @@ jobs:
name: Upload Artifact
with:
name: ChatItem.jar
path: target/ChatItem-*.jar
path: target/ChatItem-*.jar
+6 -6
View File
@@ -10,20 +10,20 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
name: Checkout repo
- name: Set up JDK 17 (LTS)
uses: actions/setup-java@v3
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'adopt'
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Build with Maven
run: mvn install --file pom.xml
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
name: Upload Artifact
with:
name: ChatItem.jar
+3 -1
View File
@@ -1,7 +1,9 @@
.idea/
.gitignore
src/test/
build/
bin/
target/
.gradle/
*.iml
dependency-reduced-pom.xml
.classpath
+3 -3
View File
@@ -8,11 +8,11 @@ You can:
- [ ![Come on discord](https://img.shields.io/badge/chat-on_discord-7289da.svg) ](https://discord.gg/yng5PPf62h)
- [Check the wiki](https://github.com/dadus33-plugins/ChatItem/wiki)
# Item not well showed in chat
# Item doesn't show up well 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.
You can do `/chatitem admin` then select one of the other paper items in the menu. It will change how the plugin tries to display items in chat.
**If you already have issue, please do**:
**If you still have an 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`
+149
View File
@@ -0,0 +1,149 @@
/* ------------------------------ Plugins ------------------------------ */
plugins {
id("java") // Import Java plugin.
id("java-library") // Import Java Library plugin.
id("com.diffplug.spotless") version "7.0.4" // Import Spotless plugin.
id("com.gradleup.shadow") version "8.3.9" // Import Shadow plugin.
id("checkstyle") // Import Checkstyle plugin.
eclipse // Import Eclipse plugin.
kotlin("jvm") version "2.1.21" // Import Kotlin JVM plugin.
}
/* --------------------------- JDK / Kotlin ---------------------------- */
java {
sourceCompatibility = JavaVersion.VERSION_17 // Compile with JDK 17 compatibility.
toolchain { // Select Java toolchain.
languageVersion.set(JavaLanguageVersion.of(17)) // Use JDK 17.
vendor.set(JvmVendorSpec.GRAAL_VM) // Use GraalVM CE.
}
}
kotlin { jvmToolchain(17) }
/* ----------------------------- Metadata ------------------------------ */
group = "me.dadus33" // Declare bundle identifier.
version = "2.6.3" // Declare plugin version (will be in .jar).
val apiVersion = "1.19" // Declare minecraft server target version.
/* ----------------------------- Resources ----------------------------- */
tasks.named<ProcessResources>("processResources") {
val props = mapOf("version" to version, "apiVersion" to apiVersion)
inputs.properties(props) // Indicates to rerun if version changes.
filesMatching("plugin.yml") { expand(props) }
from("LICENSE") { into("/") } // Bundle licenses into jarfiles.
}
/* ---------------------------- Repos ---------------------------------- */
repositories {
mavenCentral() // Import the Maven Central Maven Repository.
gradlePluginPortal() // Import the Gradle Plugin Portal Maven Repository.
maven { url = uri("https://repo.purpurmc.org/snapshots") } // Import the PurpurMC Maven Repository.
maven { url = uri("https://repo.md-5.net/content/groups/public/") }
maven { url = uri("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") }
maven { url = uri("https://oss.sonatype.org/content/repositories/snapshots/") }
maven { url = uri("https://jitpack.io") }
maven { url = uri("https://raw.github.com/MascusJeoraly/LanguageUtils/mvn-repo/") }
maven { url = uri("https://repo.dmulloy2.net/nexus/repository/public/") }
maven { url = uri("https://repo.viaversion.com") }
maven { url = uri("https://repo.eliapp.fr:8081/repository/internal/") }
maven { url = uri("https://m2.dv8tion.net/releases") }
maven { url = uri("https://nexus.scarsz.me/content/groups/public/") }
maven { url = uri("https://repo.papermc.io/repository/maven-public/") }
maven { url = uri("https://repo.essentialsx.net/snapshots/") }
System.getProperty("SELF_MAVEN_LOCAL_REPO")?.let { // TrueOG Bootstrap mavenLocal().
val dir = file(it)
if (dir.isDirectory) {
println("Using SELF_MAVEN_LOCAL_REPO at: $it")
maven { url = uri("file://${dir.absolutePath}") }
} else {
mavenLocal()
}
}
}
/* ---------------------- Java project deps ---------------------------- */
dependencies {
compileOnly("org.purpurmc.purpur:purpur-api:1.19.4-R0.1-SNAPSHOT") // Declare Purpur API version to be packaged.
implementation("com.google.code.gson:gson:2.9.0")
implementation("com.github.GeyserMC:opennbt:1.5")
implementation("commons-lang:commons-lang:2.6")
compileOnly(files("libs/ProtocolLib-5.0.jar")) // Import Legacy ProtocolLib API.
compileOnly("com.meowj:LangUtils:1.9")
compileOnly("com.viaversion:viaversion-api:5.0.3")
compileOnly("io.netty:netty-all:4.1.58.Final")
compileOnly("dev.majek:HexNicks:3.1.1")
compileOnly("net.kyori:adventure-api:4.17.0")
compileOnly("net.kyori:adventure-platform-bukkit:4.3.4")
compileOnly("com.discordsrv:discordsrv:1.28.1")
compileOnly("com.willfp:EcoEnchants:8.57.2")
compileOnly("com.github.Auxilor:EcoEnchants:12.5.1")
compileOnly("com.ryderbelserion:ChatManager:3.7.7")
compileOnly("com.willfp:eco:6.66.1")
compileOnly("me.clip:placeholderapi:2.11.6")
compileOnly("be.maximvdw:MVdWPlaceholderAPI:3.1.1-SNAPSHOT")
compileOnly("net.luckperms:api:5.5")
compileOnly("net.essentialsx:EssentialsX:2.21.0-SNAPSHOT")
}
/* ---------------------- Reproducible jars ---------------------------- */
tasks.withType<AbstractArchiveTask>().configureEach { // Ensure reproducible .jars
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
}
/* ----------------------------- Shadow -------------------------------- */
tasks.shadowJar {
archiveClassifier.set("") // Use empty string instead of null.
exclude("io/github/miniplaceholders/**")
relocate("com.google.gson", "me.dadus33.libs.gson")
relocate("com.github.steveice10.opennbt", "me.dadus33.libs.opennbt")
relocate("org.apache.commons.lang", "me.dadus33.libs.commonslang2")
exclude("net/kyori/examination/**")
exclude("net/kyori/adventure/platform/**")
exclude("net/kyori/adventure/text/serializer/legacy/**")
exclude("net/kyori/adventure/text/serializer/gson/**")
exclude("net/kyori/adventure/nbt/**")
minimize()
}
tasks.jar { archiveClassifier.set("part") } // Applies to root jarfile only.
tasks.build { dependsOn(tasks.spotlessApply, tasks.shadowJar) } // Build depends on spotless and shadow.
/* --------------------------- Javac opts ------------------------------- */
tasks.withType<JavaCompile>().configureEach {
options.compilerArgs.add("-parameters") // Enable reflection for java code.
options.isFork = true // Run javac in its own process.
options.compilerArgs.add("-Xlint:deprecation") // Trigger deprecation warning messages.
options.encoding = "UTF-8" // Use UTF-8 file encoding.
}
/* ----------------------------- Auto Formatting ------------------------ */
spotless {
java {
eclipse().configFile("config/formatter/eclipse-java-formatter.xml") // Eclipse java formatting.
leadingTabsToSpaces() // Convert leftover leading tabs to spaces.
removeUnusedImports() // Remove imports that aren't being called.
}
kotlinGradle {
ktfmt().kotlinlangStyle().configure { it.setMaxWidth(120) } // JetBrains Kotlin formatting.
target("build.gradle.kts", "settings.gradle.kts") // Gradle files to format.
}
}
checkstyle {
toolVersion = "10.18.1" // Declare checkstyle version to use.
configFile = file("config/checkstyle/checkstyle.xml") // Point checkstyle to config file.
isIgnoreFailures = true // Don't fail the build if checkstyle does not pass.
isShowViolations = true // Show the violations in any IDE with the checkstyle plugin.
}
tasks.named("compileJava") {
dependsOn("spotlessApply") // Run spotless before compiling with the JDK.
}
tasks.named("spotlessCheck") {
dependsOn("spotlessApply") // Run spotless before checking if spotless ran.
}
+34
View File
@@ -0,0 +1,34 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
<property name="severity" value="error"/>
</module>
<module name="TreeWalker">
<module name="FinalLocalVariable"/>
<module name="AvoidStarImport"/>
<module name="Indentation">
<property name="severity" value="ignore"/>
</module>
</module>
<module name="RegexpSingleline">
<property name="format" value="\borg\.junit\.jupiter\.api\.Assertions\.fail\s*\(\s*&quot;Not yet implemented&quot;\s*\)\s*;"/>
<property name="message" value="Remove placeholder fail() and implement the test."/>
<property name="ignoreCase" value="true"/>
<property name="severity" value="warning"/>
</module>
<module name="RegexpSingleline">
<property name="format" value="(?&lt;!\w)fail\s*\(\s*&quot;Not yet implemented&quot;\s*\)\s*;"/>
<property name="message" value="Remove placeholder fail() and implement the test."/>
<property name="severity" value="warning"/>
</module>
</module>
+404
View File
@@ -0,0 +1,404 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="23">
<profile kind="CodeFormatterProfile" name="TrueOG Network Formatting" version="23">
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_switch_case_arrow_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_permitted_types" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_permitted_types_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.javadoc_do_not_separate_block_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case_after_arrow" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.keep_switch_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_arrow" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.align_arrows_in_switch_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_switch_case_with_arrow_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_colon" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_switch_case_with_arrow" value="20"/>
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_permitted_types" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
</profile>
</profiles>
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored Executable
+251
View File
@@ -0,0 +1,251 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH="\\\"\\\""
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
Vendored
+94
View File
@@ -0,0 +1,94 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
+339
View File
@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
Binary file not shown.
-230
View File
@@ -1,230 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>me.dadus33</groupId>
<artifactId>chatitem</artifactId>
<version>2.4.7</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>
</repository>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
<repository>
<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.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.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.0.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.viaversion</groupId>
<artifactId>viaversion-api</artifactId>
<version>4.6.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>dev.majek</groupId>
<artifactId>HexNicks</artifactId>
<version>2.2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.13.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bukkit</artifactId>
<version>4.3.0</version>
<scope>compile</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.kangarko</groupId>
<artifactId>ChatControl-Free</artifactId>
<version>5.9.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.ryderbelserion</groupId>
<artifactId>ChatManager</artifactId>
<version>3.7.7</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>ChatItem-${project.version}</finalName>
<directory>./target</directory>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<relocations>
<relocation>
<pattern>com.google.gson</pattern>
<shadedPattern>me.dadus33.libs.gson</shadedPattern>
</relocation>
<relocation>
<pattern>net.kyori.adventure.text.serializer.bungeecord</pattern>
<shadedPattern>me.dadus33.libs.kyori.serializer.bungeecord</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*</artifact>
<excludes>
<exclude>net.kyori:examination-api:**</exclude>
<exclude>net.kyori:examination-string:**</exclude>
<exclude>net.kyori:adventure-platform-api:**</exclude>
<exclude>net.kyori:adventure-text-serializer-legacy:**</exclude>
<exclude>net.kyori:adventure-text-serializer-gson:**</exclude>
<exclude>net.kyori:adventure-platform-facet:**</exclude>
<exclude>net.kyori:adventure-nbt:**</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</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>
+1
View File
@@ -0,0 +1 @@
rootProject.name = "ChatItem"
+21
View File
@@ -0,0 +1,21 @@
package me.dadus33.chatitem;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
public class C {
public static TextComponent text(String s) {
return LegacyComponentSerializer.legacySection().deserialize(s);
}
public static String string(Component c) {
return LegacyComponentSerializer.legacySection().serialize(c);
}
}
+301 -160
View File
@@ -5,216 +5,357 @@ 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 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.entity.Player;
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.chatmanager.v3.PaperChatManager;
import me.dadus33.chatitem.chatmanager.v4.OwnManager;
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.hook.placeholders.EssentialsPlaceholdersHook;
import me.dadus33.chatitem.hook.placeholders.IPlaceholders;
import me.dadus33.chatitem.hook.placeholders.MVdWPlaceholderAPIHook;
import me.dadus33.chatitem.hook.placeholders.OwnPlaceholder;
import me.dadus33.chatitem.hook.placeholders.PlaceholderAPIHook;
import me.dadus33.chatitem.hook.placeholders.LuckPermsPlaceholderHook;
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.platform.IPlatform;
import me.dadus33.chatitem.platform.hook.PaperPlatform;
import me.dadus33.chatitem.platform.hook.SpigotPlatform;
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 = 13;
public static boolean discordSrvSupport = false, ecoEnchantsSupport = false, hasNewVersion = false;
private static ChatItem instance;
private final String brandChannelName = Version.getVersion().isNewerOrEquals(Version.V1_13) ? "minecraft:brand" : "MC|Brand";
private final List<ChatManager> chatManager = new ArrayList<>();
private Storage storage;
private static final List<IPlaceholders> PLACEHOLDERS = new ArrayList<>();
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);
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 List<IPlaceholders> getPlaceholders() {
public static ChatItem getInstance() {
return instance;
}
return PLACEHOLDERS;
public static void debug(String msg) {
if (getInstance().getStorage().debug)
getInstance().getLogger().info("[Debug] " + msg.replace(ChatManager.SEPARATOR, 'S').replace(ChatManager.SEPARATOR_END, 'E'));
}
}
private void chooseManagers() {
this.chatManager.forEach((cm) -> cm.unload(this));
this.chatManager.clear();
PluginManager pm = getServer().getPluginManager();
String managerName = getStorage().manager;
public static String replace(Player p, String text) {
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;
}
for (IPlaceholders ip : getPlaceholders())
text = ip.replace(p, text);
return text;
this.chatManager.forEach((cm) -> cm.load(this, getStorage()));
}
NamerManager.load(this);
PlayerNamerManager.load(this);
}
private static final IPlatform platform = Utils.IS_PAPER ? new PaperPlatform() : new SpigotPlatform();
private List<String> getPluginThatRequirePacket() {
return Arrays.asList("DeluxeChat", "HexNicks", "VentureChat", "ItemsAdder");
}
public static IPlatform getPlatform() {
@Override
public void onEnable() {
// Save the instance (we're basically a singleton)
instance = this;
getLogger().info("Detected server version: " + Version.getVersion().name().toLowerCase());
return platform;
// 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 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;
// events
PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new JoinListener(), this);
pm.registerEvents(new InventoryListener(), this);
pm.registerEvents(new TranslationInventoryListener(), this);
public static void reload(CommandSender sender) {
chooseManagers();
ChatItem pl = getInstance();
if (pl.getConfig().getKeys(false).isEmpty())
pl.saveDefaultConfig();
pl.reloadConfig();
pl.storage = new Storage(pl.getConfig());
// pl.chooseManagers();
Translation.load(pl);
InvShower.getInvShower().clear();
if (sender != null) {
StringJoiner plugins = new StringJoiner(", ");
if (pm.isPluginEnabled("DiscordSRV")) {
discordSrvSupport = true;
plugins.add("DiscordSRV");
}
if (pm.isPluginEnabled("ChatControl")) {
ChatControlSupport.init(this);
plugins.add("ChatControl");
}
if (pm.isPluginEnabled("ChatManager")) {
ChatManagerSupport.init(this);
plugins.add("ChatManager");
}
if (pm.isPluginEnabled("EcoEnchants") && pm.getPlugin("EcoEnchants").getDescription().getVersion().startsWith("8.")) {
ecoEnchantsSupport = true;
plugins.add("EcoEnchants");
}
if (!pl.storage.messageReload.isEmpty())
sender.sendMessage(pl.storage.messageReload);
if (plugins.length() > 0)
getLogger().info("Load " + plugins.toString() + " support.");
}
Translation.load(this);
ChatManager.setTesting(null);
getServer().getMessenger().registerIncomingPluginChannel(this, brandChannelName, (chan, p, msg) -> ItemPlayer.getPlayer(p).setClientName(new String(msg).substring(1)));
}
if (storage.checkUpdate) {
getServer().getScheduler().runTaskAsynchronously(this, () -> {
String urlName = "https://api.spigotmc.org/legacy/update.php?resource=19064";
String content = Utils.getFromURL(urlName);
if (Strings.isNullOrEmpty(content))
return;
SemVer currentVersion = SemVer.parse(getDescription().getVersion());
if (currentVersion == null)
return;
SemVer latestVersion = SemVer.parse(content);
if (latestVersion != null && latestVersion.isNewerThan(currentVersion)) {
hasNewVersion = !content.equalsIgnoreCase(getDescription().getVersion());
if (hasNewVersion)
getLogger().info(storage.updateMessage);
}
});
}
}
public static ChatItem getInstance() {
public void loadCommand(PluginCommand cmd, Object obj) {
if (obj instanceof CommandExecutor)
cmd.setExecutor((CommandExecutor) obj);
if (obj instanceof TabCompleter)
cmd.setTabCompleter((TabCompleter) obj);
}
return instance;
public Storage getStorage() {
return storage;
}
}
public List<ChatManager> getChatManager() {
return chatManager;
}
public static void debug(String msg) {
public String getVisualChatManagers() {
StringJoiner sj = new StringJoiner(", ");
for (ChatManager cm : chatManager) {
sj.add(cm.getName() + " (" + cm.getId() + ")");
}
return sj.toString();
}
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;
}
private void chooseManagers() {
this.chatManager.forEach((cm) -> cm.unload(this));
this.chatManager.clear();
this.chatManager.add(new PacketEditingChatManager(this));
this.chatManager.add(new ChatListenerChatManager(this));
if (Utils.IS_PAPER) {
this.chatManager.add(new PaperChatManager(this));
this.chatManager.add(new OwnManager());
}
String managerName = getStorage().manager;
switch (managerName.toLowerCase(Locale.ROOT)) {
case "both":
case "all":
case "auto":
getLogger().info("Manager automatically chosen: " + getVisualChatManagers());
break;
case "paper":
case "packet":
case "chat":
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 -----");
break;
}
this.chatManager.forEach((cm) -> cm.load(this, getStorage()));
NamerManager.load(this);
PlayerNamerManager.load(this);
}
public static List<String> getPluginThatRequirePacket() {
return Arrays.asList("DeluxeChat", "HexNicks", "VentureChat", "ItemsAdder");
}
@Override
public void onEnable() {
// Save the instance (we're basically a singleton)
instance = this;
getLogger().info("Detected server version: " + Version.getVersion().name().toLowerCase() + " (Platform: "
+ getPlatform().getName() + ")");
// 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());
// 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 (pm.isPluginEnabled("PlaceholderAPI")) {
plugins.add("PlaceholderAPI");
PLACEHOLDERS.add(new PlaceholderAPIHook());
}
if (pm.isPluginEnabled("Essentials")) {
plugins.add("Essentials");
PLACEHOLDERS.add(new EssentialsPlaceholdersHook());
}
if (pm.isPluginEnabled("MVdWPlaceholderAPI")) {
plugins.add("MVdWPlaceholderAPI");
PLACEHOLDERS.add(new MVdWPlaceholderAPIHook());
}
if (pm.isPluginEnabled("LuckPerms")) {
plugins.add("LuckPerms");
PLACEHOLDERS.add(new LuckPermsPlaceholderHook());
}
if (plugins.length() > 0)
getLogger().info("Load " + plugins.toString() + " support.");
PLACEHOLDERS.add(new OwnPlaceholder());
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(getPlatform().getPluginVersion(this));
if (currentVersion == null)
return;
SemVer latestVersion = SemVer.parse(content);
if (latestVersion != null && latestVersion.isNewerThan(currentVersion)) {
hasNewVersion = !content.equalsIgnoreCase(getPlatform().getPluginVersion(this));
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 boolean isManagerEnabled(String id) {
for (ChatManager cm : chatManager) {
if (cm.getId().equalsIgnoreCase(id))
return true;
}
return false;
}
public String getVisualChatManagers() {
StringJoiner sj = new StringJoiner(", ");
for (ChatManager cm : chatManager) {
sj.add(cm.getName() + " (" + cm.getId() + ")");
}
return sj.toString();
}
public boolean isHasNewVersion() {
return hasNewVersion;
}
public boolean isHasNewVersion() {
return hasNewVersion;
}
}
+102 -69
View File
@@ -11,73 +11,106 @@ 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 + "]";
}
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().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,125 @@
package me.dadus33.chatitem;
import java.util.List;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.utils.Colors;
public enum ItemSlot {
HAND("", false), HELMET("helmet", false), CHESTPLATE("chestplate", false), LEGGINGS("leggings", false),
BOOTS("boots", false), INVENTORY("inventory", true), ENDERCHEST("enderchest", true);
private final boolean command;
private final String key;
private ItemSlot(String key, boolean command) {
this.command = command;
this.key = key;
}
public String getKey() {
return key;
}
public boolean isBasic() {
return key.equalsIgnoreCase("");
}
public boolean isCommand() {
return command;
}
public List<String> getPlaceholders() {
return ChatItem.getInstance().getConfig()
.getStringList(isBasic() ? "general.placeholders" : "general.other-placeholders." + key + ".keys");
}
public boolean isEnabled() {
return isBasic() || ChatItem.getInstance().getConfig()
.getBoolean("general.other-placeholders." + key + ".enabled", true);
}
public boolean isDenyIfNoItem() {
return ChatItem.getInstance().getConfig()
.getBoolean("general" + (isBasic() ? "" : ".other-placeholders." + key) + ".deny-if-no-item", true);
}
public String getShowMessage() {
return Colors.color(ChatItem.getInstance().getConfig()
.getString("general" + (isBasic() ? "" : ".other-placeholders." + key) + ".show", ""));
}
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;
}
public static ItemSlot getItemSlotByKey(String key) {
for (ItemSlot slot : ItemSlot.values()) {
if (slot.isEnabled() && slot.getKey().equalsIgnoreCase(key)) {
return slot;
}
}
return null;
}
}
+97 -71
View File
@@ -3,88 +3,114 @@ package me.dadus33.chatitem;
import java.util.List;
import java.util.stream.Collectors;
import org.bukkit.ChatColor;
import org.bukkit.configuration.file.FileConfiguration;
import com.google.common.collect.ImmutableList;
import me.dadus33.chatitem.utils.Colors;
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> placeholders, tooltipHand, tooltipBuggedClient, ignoredItems;
public boolean colorIfColored, addAmountForced, letMessageThrough, denyIfNoItem, debug, handDisabled, showNoPermissionMessage, checkUpdate, permissionEnabled;
public int configVersion, limit, cooldown;
private FileConfiguration conf;
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, replaceInConsole;
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);
placeholders = ImmutableList.copyOf(conf.getStringList("general.placeholders"));
nameFormat = color(conf.getString("general.name-format", "&b&l&o{name} {amount}&r"));
amountFormat = color(conf.getString("general.amount-format", "x{times}"));
commandFormat = color(conf.getString("general.command-format", "&6%name%'s item is %item%"));
colorIfColored = conf.getBoolean("general.color-if-already-colored", true);
letMessageThrough = conf.getBoolean("general.let-message-through", true);
addAmountForced = conf.getBoolean("general.force-add-amount", true);
denyIfNoItem = conf.getBoolean("general.deny-if-no-item", false);
limit = conf.getInt("general.limit", 8);
cooldown = conf.getInt("general.cooldown", 60);
showNoPermissionMessage = conf.getBoolean("general.show-no-permission-message.normal", true);
permissionEnabled = conf.getBoolean("general.permission.enabled", false);
permissionName = conf.getString("general.permission.name", "chatitem.use");
handDisabled = conf.getBoolean("general.hand.disabled", false);
handName = color(conf.getString("general.hand.name", "&b&l&o{display-name}&b&l&o's hand"));
tooltipHand = conf.getStringList("general.hand.tooltip").stream().map(Storage::color).collect(Collectors.toList());
buggedClientAction = conf.getString("general.bugged_client.action", "show_both");
tooltipBuggedClient = conf.getStringList("general.bugged_client.tooltip").stream().map(Storage::color).collect(Collectors.toList());
ignoredItems = conf.getStringList("general.ignored_items");
checkUpdate = conf.getBoolean("general.check-update", true);
messageDeny = color(conf.getString("messages.deny-message", "&c&lYou have no item in hand!"));
messageReload = color(conf.getString("messages.reload-success", "&b&lSuccessful reload!"));
messageNoPermission = color(conf.getString("messages.no-permission", "&c&lI'm sorry, but you are not allowed to use the placeholder in chat!"));
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."));
public Storage(FileConfiguration cnf) {
SECONDS = color(conf.getString("messages.seconds", " seconds"));
minutes = color(conf.getString("messages.minutes", " minutes"));
hours = color(conf.getString("messages.hours", " hours"));
colorStringList(tooltipHand);
this.conf = cnf;
configVersion = conf.getInt("config-version", 13);
checkConfigVersion();
this.manager = conf.getString("manager", "auto");
if (manager == "both")
manager = "all";
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);
replaceInConsole = conf.getBoolean("general.replace-in-console", 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)));
}
}
public static String color(String s) {
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!");
}
}
return s == null || s.isEmpty() ? s : Colors.translateAlternateColorCodes('&', s);
private void performOverwrite() {
ChatItem.getInstance().saveResource("config.yml", true);
}
}
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(
"ChatItem detected an older or invalid configuration file. Replacing it with the default config...");
performOverwrite();
conf = pl.getConfig();
pl.getLogger().warning("Replacement complete!");
}
}
private void performOverwrite() {
ChatItem.getInstance().saveResource("config.yml", true);
}
}
@@ -14,92 +14,169 @@ import java.util.stream.Collectors;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.inventory.ItemStack;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.dadus33.chatitem.utils.Utils;
@SuppressWarnings("deprecation")
public class Translation {
private static File folder;
private static YamlConfiguration legacy, allLangsConfig;
private static JsonObject messages;
private static HashMap<String, String> allLangs = new HashMap<>();
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");
public static void load(ChatItem pl) {
allLangsConfig.getStringList("all").forEach(langKey -> {
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() + ")");
});
allLangs = allLangs.entrySet().stream().sorted(Entry.comparingByValue()).collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
loadLang(pl.getStorage().language);
}
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");
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;
}
}
allLangsConfig.getStringList("all").forEach(langKey -> {
try {
messages = JsonParser.parseReader(new FileReader(langFile)).getAsJsonObject();
} catch (Exception e) {
e.printStackTrace();
}
pl.getLogger().info("Loaded translation for " + lang + ".");
}
try {
@SuppressWarnings("deprecation")
public static String get(ItemStack item) {
String key = (item.getType().isBlock() ? "block" : "item") + ".minecraft." + item.getType().name().toLowerCase().replace("_", ".");
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("_", " "));
}
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 String getMessage(String key) {
JsonElement result = messages.get(key);
return result == null ? "" : result.getAsString();
}
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 + ".");
}
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("_", " "));
}
public static String getOr(ItemStack item, String def) {
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(), def);
}
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
}
}
}
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
}
}
}
}
@@ -8,79 +8,127 @@ 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) {
return new Chat(actualId++, p, message);
}
public static Chat getFrom(String message) {
boolean found = false;
String id = "";
for(char c : ChatManager.fixSeparator(message).toCharArray()) {
if(c == ChatManager.SEPARATOR)
found = true;
else if(c == ChatManager.SEPARATOR_END)
break;
else if(found)
id += c;
}
ChatItem.debug("Search in " + message + ", id found: " + id);
return (id != "" && Utils.isInteger(id)) ? Chat.getChat(Integer.parseInt(id)).orElse(null) : null;
}
private final long time;
private final int id;
private final Player p;
private final String message;
public Chat(int id, Player p, String message) {
this.time = System.currentTimeMillis();
this.id = id;
this.p = p;
this.message = message;
CHAT.add(this);
}
public long getTime() {
return time;
}
public int getId() {
return id;
}
public Player getPlayer() {
return p;
}
public String getMessage() {
return message;
}
public ItemPlayer getItemPlayer() {
return ItemPlayer.getPlayer(getPlayer());
}
private boolean isOld() {
return System.currentTimeMillis() > time + 10000;
}
public void remove() {
CHAT.remove(this);
}
@Override
public String toString() {
return "Chat{id=" + id + ",message=" + message + ",time=" + time + "}";
}
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,79 @@
package me.dadus33.chatitem.chatmanager;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ItemSlot;
public class ChatAction {
private boolean hasItem;
private ItemSlot slot;
private String command;
private ItemStack item;
private Player origin;
public ChatAction(ItemSlot slot, Player origin, ItemStack item, String command) {
this.slot = slot;
this.item = item == null ? new ItemStack(Material.AIR) : item;
this.command = command;
this.origin = origin;
this.hasItem = true;
}
public ChatAction(ItemSlot slot, Player origin, String command) {
this.slot = slot;
this.command = command;
this.origin = origin;
this.hasItem = false;
}
public Player getOrigin() {
return origin;
}
public ItemSlot getSlot() {
return slot;
}
public boolean hasItem() {
return hasItem;
}
public String getCommand() {
return command;
}
public boolean hasCommand() {
return command != null && command != "";
}
public ItemStack getItem() {
return item == null ? new ItemStack(Material.AIR) : item;
}
@Override
public String toString() {
return "ChatAction[slot=" + slot + ",command=" + command + ",item=" + item + ",origin=" + origin + "]";
}
}
@@ -0,0 +1,67 @@
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;
@SuppressWarnings("deprecation")
public class ChatEventListener implements Listener {
private Storage getStorage() {
return ChatItem.getInstance().getStorage();
}
@EventHandler(priority = EventPriority.LOWEST)
public void onChat(AsyncPlayerChatEvent e) {
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("(general) not found placeholders in: " + e.getMessage());
return;
}
ChatAction action = ChatManager.getChatAction(slot, p);
if (!ChatManager.canUsePlaceholder(p, action, 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("(general) 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
}
}
@@ -1,310 +1,627 @@
package me.dadus33.chatitem.chatmanager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import javax.annotation.Nullable;
import org.bukkit.ChatColor;
import org.bukkit.Bukkit;
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.EcoEnchantsSupport;
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.OneItemShower;
import me.dadus33.chatitem.invsee.hook.PlayerInventoryShower;
import me.dadus33.chatitem.itemnamer.NamerManager;
import me.dadus33.chatitem.utils.Colors;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.Messages;
import me.dadus33.chatitem.utils.Utils;
import me.dadus33.chatitem.utils.Version;
@SuppressWarnings("deprecation")
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 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 addSeparator(int id) {
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);
}
return SEPARATOR + Integer.toString(id) + SEPARATOR_END;
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 String removeSeparator(String message) {
public static boolean containsSeparator(String s) {
return s != null && (s.contains(SEPARATOR_STR) || s.contains(Character.toString(SEPARATOR)));
}
return fixSeparator(message).replace(Character.toString(SEPARATOR), "")
.replace(Character.toString(SEPARATOR_END), "");
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)));
}
public static String replaceSeparator(Chat chat, String message, String replacement) {
protected Storage s;
return fixSeparator(message).replace(
Character.toString(SEPARATOR) + (chat != null ? chat.getId() : "") + Character.toString(SEPARATOR_END),
replacement);
public ChatManager() {
}
}
public static String fixSeparator(String s) {
public abstract String getName();
return s == null ? ""
: s.replace(SEPARATOR_STR, Character.toString(SEPARATOR)).replace(SEPARATOR_END_STR,
Character.toString(SEPARATOR_END));
public abstract String getId();
}
public Storage getStorage() {
return s;
}
public static boolean equalsSeparator(String s) {
public void load(ChatItem pl, Storage s) {
this.s = s;
}
return s != null && (s.equalsIgnoreCase(SEPARATOR_STR) || s.equalsIgnoreCase(Character.toString(SEPARATOR)));
public abstract void unload(ChatItem pl);
}
/**
* Get the item in hand as usable one.<br>
* Will include, in lore, all informations from other plugins.
*
* @param p the player
* @return the usable item
*/
public static ItemStack getUsableItem(Player p) {
ItemStack item = HandItem.getBetterItem(p).clone();
public static boolean containsSeparator(String s) {
if (ChatItem.ecoEnchantsSupport) {
List<String> addLore = EcoEnchantsSupport.getLores(item);
if (!addLore.isEmpty()) {
ItemMeta meta = item.getItemMeta();
List<String> lores = meta.hasLore() ? meta.getLore() : new ArrayList<>();
for (int i = 0; i < addLore.size(); i++)
lores.add(i, addLore.get(i));
return s != null && (s.contains(SEPARATOR_STR) || s.contains(Character.toString(SEPARATOR)));
meta.setLore(lores);
item.setItemMeta(meta);
ChatItem.debug("Added " + addLore.size() + " lores from EcoEnchants");
} else
ChatItem.debug("No lore to add from EcoEnchants");
}
}
return item;
}
public static boolean equalsSeparatorEnd(String s) {
/**
* 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;
}
return s != null
&& (s.equalsIgnoreCase(SEPARATOR_END_STR) || s.equalsIgnoreCase(Character.toString(SEPARATOR_END)));
/**
* 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);
}
if (item.hasItemMeta() && item.getItemMeta().hasDisplayName()) {
String trp = item.getItemMeta().getDisplayName();
ChatItem.debug("trp: " + trp);
if (c.colorIfColored) {
replacer = replacer.replace(NAME, ChatColor.stripColor(trp));
} else {
replacer = replacer.replace(NAME, trp);
}
} else {
replacer = replacer.replace(NAME, NamerManager.getName(p, item, c));
}
return replacer;
}
}
/**
* Get the name of item according to player & config
*
* @param p the player 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 c.placeholders.get(0);
else
return c.handName;
}
return styleItem(p, item, c);
}
public static boolean containsSeparatorEnd(String s) {
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();
}
return s != null && (s.contains(SEPARATOR_END_STR) || s.contains(Character.toString(SEPARATOR_END)));
public static boolean canShowItem(Player p, ItemStack item, @Nullable Cancellable e) {
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 (c.denyIfNoItem) {
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;
}
protected Storage s;
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 ChatManager() {
public static void clear(Player p) {
COOLDOWNS.remove(p.getUniqueId());
LAST_INFO_MESSAGE.remove(p.getUniqueId());
}
}
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, p, "/chatitem seeinv " + uuid.toString());
}
UUID uuid = UUID.randomUUID();
ItemStack item = getUsableItem(p, slot);
InvShower.add(uuid.toString(), new OneItemShower(p, item));
return new ChatAction(slot, p, item, "/chatitem seeinv " + uuid.toString());
}
/**
* 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 viewer, ItemStack item) {
List<String> lines = new ArrayList<>();
if (item.hasItemMeta()) {
ItemMeta meta = item.getItemMeta();
lines.add(NamerManager.getName(viewer, item, ChatItem.getInstance().getStorage()));
if (meta.hasEnchants()) {
meta.getEnchants().forEach((enchant, lvl) -> {
lines.add(Colors.RESET + Utils.getEnchantName(enchant) + " " + Utils.toRoman(lvl));
});
}
if (meta.hasLore())
lines.addAll(meta.getLore());
} else {
lines.add(NamerManager.getName(viewer, 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 viewer the player
* @param item the item
* @param c the config
* @return the name of item
*/
public static String styleItem(Player viewer, 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(viewer, 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, Player viewer, Storage c) {
if (ItemUtils.isEmpty(item)) {
if (c.handDisabled)
return ItemSlot.HAND.getPlaceholders().get(0);
return getHandName(p);
}
return ChatItem.replace(p, styleItem(viewer, item, c));
}
public static String getNameForChatAction(Player viewer, Chat chat, Storage c) {
ChatAction action = chat.getAction();
if (action.hasItem()) {
ItemStack item = action.getItem();
if (ItemUtils.isEmpty(item)) {
if (c.handDisabled)
return chat.getSlot().getPlaceholders().get(0);
return getHandName(chat);
}
return ChatItem.replace(chat.getPlayer(), styleItem(viewer, item, c));
}
return ChatItem.replace(chat.getPlayer(), Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat",
"%cible%", action.getOrigin().getName()));
}
public static String getNameForChatAction(Player viewer, ChatAction action, Storage c) {
if (action.hasItem()) {
ItemStack item = action.getItem();
if (ItemUtils.isEmpty(item)) {
if (c.handDisabled)
return action.getSlot().getPlaceholders().get(0);
else
return getHandName(action.getOrigin());
}
return ChatItem.replace(action.getOrigin(), styleItem(viewer, item, c));
}
return ChatItem.replace(action.getOrigin(), Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat",
"%cible%", action.getOrigin().getName()));
}
public static String replaceItemsWithNames(String message) {
if (message == null || !containsSeparator(message))
return message;
String fixed = fixSeparator(message);
Storage c = ChatItem.getInstance().getStorage();
StringBuilder result = new StringBuilder();
StringBuilder idBuilder = new StringBuilder();
boolean inId = false;
for (int i = 0; i < fixed.length(); i++) {
char ch = fixed.charAt(i);
if (ch == SEPARATOR) {
inId = true;
idBuilder.setLength(0);
} else if (ch == SEPARATOR_END && inId) {
inId = false;
String id = idBuilder.toString();
if (Utils.isInteger(id)) {
Chat chat = Chat.getChat(Integer.parseInt(id)).orElse(null);
if (chat != null)
result.append(getNameForChatAction(chat.getPlayer(), chat, c));
}
} else if (inId) {
idBuilder.append(ch);
} else {
result.append(ch);
}
}
if (inId)
result.append(SEPARATOR).append(idBuilder);
return result.toString();
}
@Deprecated
public static String getHandName(Player p) {
return ChatItem.replace(p, ChatItem.getInstance().getStorage().handName.replace("{name}", p.getName())
.replace("{display-name}", p.getDisplayName()));
}
public static String getHandName(Chat c) {
Player p = c.getPlayer();
return ChatItem.replace(p, ChatItem.getInstance().getStorage().handName.replace("{name}", p.getName())
.replace("{display-name}", p.getDisplayName()));
}
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 canUsePlaceholder(Player p, ChatAction action, ItemSlot slot, @Nullable Cancellable e) {
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 (action.hasItem() && action.getItem().getType().equals(Material.AIR) && slot.isBasic()) {
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;
}
}
}
if (action.hasItem()) {
for (String ignored : c.ignoredItems) {
if (action.getItem().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 == "all" || inTest.equalsIgnoreCase(actual));
}
public static void setTesting(String actual) {
inTest = actual;
}
public static boolean isSelected(String actual) {
if (isTestingEnabled())
return true;
String selected = ChatItem.getInstance().getStorage().manager;
if (selected.equalsIgnoreCase("both") || selected.equalsIgnoreCase("all"))
return true;
if (selected == "auto") {
if (Utils.IS_PAPER && actual == "paper")
return true;
else if (actual == "packet" && ChatItem.getPluginThatRequirePacket().stream()
.map(Bukkit.getPluginManager()::getPlugin).anyMatch(Objects::nonNull))
return true;
else if (actual == "chat")
return true;
}
return selected.equalsIgnoreCase(actual);
}
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;
}
}
@@ -3,20 +3,44 @@ 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) {
if(Version.getVersion().isNewerOrEquals(Version.V1_9)) {
ItemStack main = p.getInventory().getItemInMainHand();
if(!ItemUtils.isEmpty(main))
return main;
ItemStack off = p.getInventory().getItemInOffHand();
return ItemUtils.isEmpty(off) ? main : off;
}
return p.getItemInHand();
}
@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
}
}
@@ -1,125 +1,279 @@
package me.dadus33.chatitem.chatmanager.v1;
import java.lang.reflect.Constructor;
import java.util.Arrays;
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;
import me.dadus33.chatitem.chatmanager.v1.listeners.ChatEventListener;
import me.dadus33.chatitem.chatmanager.v1.listeners.ChatPacketManager;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacketManager;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
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 ChatEventListener chatEventListener;
private final ChatPacketManager chatPacketManager;
private boolean baseComponentAvailable = true;
private final ChatItemPacketManager packetManager;
private final ChatPacketManager chatPacketManager;
public PacketEditingChatManager(ChatItem pl) {
packetManager = new ChatItemPacketManager(pl);
chatEventListener = new ChatEventListener(this);
chatPacketManager = new ChatPacketManager(this);
public PacketEditingChatManager(ChatItem pl) {
// Check for existence of BaseComponent class (only on spigot)
try {
Class.forName("net.md_5.bungee.api.chat.BaseComponent");
} catch (ClassNotFoundException e) {
baseComponentAvailable = false;
}
}
packetManager = new ChatItemPacketManager(pl);
chatPacketManager = new ChatPacketManager(this);
@Override
public String getName() {
return "PacketEditing";
}
// Check for existence of BaseComponent class (only on spigot)
try {
@Override
public String getId() {
return "packet";
}
Class.forName("net.md_5.bungee.api.chat.BaseComponent");
@Override
public void load(ChatItem pl, Storage s) {
super.load(pl, s);
} catch (ClassNotFoundException e) {
Bukkit.getPluginManager().registerEvents(chatEventListener, pl);
PacketManager pm = packetManager.getPacketManager();
pm.addHandler(chatPacketManager);
Bukkit.getOnlinePlayers().forEach(pm::addPlayer); // add actual online players
}
baseComponentAvailable = false;
@Override
public void unload(ChatItem pl) {
HandlerList.unregisterAll(chatEventListener);
PacketManager pm = packetManager.getPacketManager();
pm.removeHandler(chatPacketManager);
pm.stop();
}
}
public boolean supportsChatComponentApi() {
return baseComponentAvailable;
}
}
public static Object createSystemChatPacket(String json) throws Exception {
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("ClientboundSystemChatPacket", "network.protocol.game.", "PacketPlayOutChat");
Constructor<?> betterOne = null;
Object[] betterParam = null;
for (Constructor<?> cons : packetClass.getDeclaredConstructors()) {
if (!cons.isAccessible())
cons.setAccessible(true);
@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, Object old) throws Exception {
json = checkPacketSize(json, 150000);
if (json.contains("tag:{{")) { // this is to fix for MC 1.20.4 (at least on purpur)
ChatItem.debug("Found strange JSON formatting. Cleaning...");
boolean replaced = false;
String next = "";
for (String part : json.split("tag:\\{\\{")) {
if (replaced) {
next += "tag:{";
next += part.replaceFirst("\\}\\}", "}");
} else
next += part;
replaced = true;
}
json = next;
}
Object packet = internalCreateSystemChatPacket(json, old);
if (packet != null)
return packet;
Object icb = ChatItem.getPlatform().jsonToBaseComponent(json);
if (icb != null)
packet = internalCreateSystemChatPacket(icb, old);
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, Object old) throws Exception {
ChatItem.debug("Creating internal chat system packet from " + old + " to " + obj);
Class<?> packetClass = PacketUtils.getNmsClass("ClientboundSystemChatPacket", "network.protocol.game.",
"ClientboundPlayerChatPacket", "PacketPlayOutChat");
Class<?> chatMessageTypeClass = Utils.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);
}
} else if (obj.getClass().isAssignableFrom(PacketUtils.COMPONENT_CLASS)) {
if (cons.getParameterCount() == 2
&& cons.getParameterTypes()[0].isAssignableFrom(PacketUtils.COMPONENT_CLASS)
&& cons.getParameterTypes()[1].equals(boolean.class)) // "string, boolean"
return cons.newInstance(obj, false);
}
int nbPut = 0;
Object[] params = new Object[cons.getParameterCount()];
for (int i = 0; i < params.length; i++) {
Class<?> type = cons.getParameterTypes()[i];
if (type.isAssignableFrom(obj.getClass())) {
params[i] = obj;
nbPut++;
} else if (chatMessageTypeClass != null && type.isAssignableFrom(chatMessageTypeClass)) {
params[i] = getChatMessageType();
} else if (type.isAssignableFrom(boolean.class)) // need to set primitives
params[i] = false;
else if (type.isAssignableFrom(int.class)) // need to set primitives
params[i] = 0;
else {
boolean found = false;
for (Class<?> prim : Arrays.asList(float.class, long.class)) { // if not primitive
if (type.isAssignableFrom(prim)) {
found = true;
}
}
if (!found) {
params[i] = new PacketContent(old).getSpecificModifier(type).readSafely(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);
}
// 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() == 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++;
}
}
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) {
return betterOne.newInstance(betterParam);
}
return null;
}
}
@@ -1,9 +1,10 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp;
import java.util.ArrayList;
import javax.annotation.Nullable;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
@@ -11,7 +12,6 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
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;
@@ -21,108 +21,179 @@ import me.dadus33.chatitem.utils.Utils;
public interface IComponentManager {
default boolean hasConditions() {
return true;
}
default boolean hasConditions() {
String getBaseComponentAsJSON(ChatItemPacket packet);
return true;
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;
}
String getBaseComponentAsJSON(ChatItemPacket packet);
default Object manageItem(Player p, Chat chat, ChatItemPacket packet, ItemStack item, Storage c) throws Exception {
String message = JSONManipulator.getInstance().parse(chat, getBaseComponentAsJSON(packet), item, ChatManager.styleItem(chat.getPlayer(), item, c),
ItemPlayer.getPlayer(p).getProtocolVersion());
if (message != null) {
ChatItem.debug("(v1) Writing message: " + message);
writeJson(packet, message);
}
return packet.getPacket();
}
void writeJson(ChatItemPacket packet, String json);
default Object manageEmpty(Player p, Chat chat, ChatItemPacket packet, Storage c) {
String message = JSONManipulator.getInstance().parseEmpty(getBaseComponentAsJSON(packet), c.handName, c.tooltipHand, chat.getPlayer());
if (message != null) {
ChatItem.debug("(v1) Writing empty message: " + message);
writeJson(packet, message);
}
return packet.getPacket();
}
default @Nullable Chat getChat(String json) {
public static class Searching {
json = ChatManager.fixSeparator(json);
try {
private boolean found = false;
private String id = "", json;
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;
public Searching(String json) {
this.json = json;
}
} catch (Exception e) {
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;
}
e.printStackTrace();
private Chat getWithId() {
return id != "" && Utils.isInteger(id) ? Chat.getChat(Integer.parseInt(id)).orElse(null) : null;
}
} // not JSON
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;
}
return null;
private boolean searchInObject(JsonObject json) {
return json.has("text") && json.get("text").isJsonPrimitive() && searchInString(json.get("text").getAsString());
}
}
default Object manageContent(Player viewer, Chat chat, ChatItemPacket packet, String json, Storage c)
throws Exception
{
String message;
if (Utils.isBeforeChatJson(viewer))
message = JSONManipulator.getInstance().parseEmpty(chat, json,
chat.getAction().hasItem() ? ChatManager.getMaxLinesFromItem(viewer, chat.getAction().getItem())
: new ArrayList<>(),
chat.getPlayer());
else
message = JSONManipulator.getInstance().parse(chat, json, chat.getAction(),
ChatManager.getNameForChatAction(viewer, chat, 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(chat, json, 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;
try {
jsonObj = JsonParser.parseString(json).getAsJsonObject();
} catch (Exception e) {
if (searchInString(json))
return getWithId();
return null;
}
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();
}
}
private boolean searchInString(String s) {
for (char c : ChatManager.fixSeparator(s).toCharArray()) {
if (c == ChatManager.SEPARATOR)
found = true;
else if (c == ChatManager.SEPARATOR_END)
return true;
else if (found)
id += c;
}
return false;
}
}
}
@@ -1,124 +1,197 @@
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.PacketEditingChatManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IComponentManager;
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulator;
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 me.dadus33.chatitem.utils.ReflectionUtils;
import me.dadus33.chatitem.utils.Utils;
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.TextReplacementConfig;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
public class AdventureComponentManager implements IComponentManager {
@Override
public boolean hasConditions() {
try {
for (String cl : Arrays.asList("net.kyori.adventure.text.Component", "net.kyori.adventure.text.serializer.gson.GsonComponentSerializer"))
Class.forName(cl);
} catch (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 boolean hasConditions() {
@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;
}
}
try {
@SuppressWarnings("deprecation")
@Override
public Object manageItem(Player p, Chat chat, ChatItemPacket packet, ItemStack item, Storage c) throws Exception {
String itemName = ChatManager.getNameOfItem(chat.getPlayer(), item, c);
return manage(p, chat, packet, itemName, HoverEvent.showItem(Key.key(item.getType().getKey().getKey()), item.getAmount(), BinaryTagHolder.of(PacketUtils.getNbtTag(item))));
}
for (String cl : Arrays.asList("net.kyori.adventure.text.Component",
"net.kyori.adventure.text.serializer.gson.GsonComponentSerializer"))
Class.forName(cl);
@Override
public Object manageEmpty(Player p, Chat chat, ChatItemPacket packet, Storage c) {
Component builder = Component.text("");
c.tooltipHand.forEach(s -> builder.append(Component.text(s)));
Player sender = chat.getPlayer();
String handName = c.handName.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName());
return manage(p, chat, packet, handName, HoverEvent.showText(builder));
}
} catch (Throwable e) { // can't support this, adventure comp not found
private Object manage(Player p, Chat chat, ChatItemPacket packet, String replacement, HoverEvent<?> hover) {
ContentModifier<Component> modifier = packet.getContent().getSpecificModifier(Component.class);
Component comp = modifier.readSafely(0);
if (comp == null) {
ChatItem.debug("The component is null.");
return null;
}
comp = checkComponent(comp, hover, replacement, chat);
ChatItem.debug("Result: " + GsonComponentSerializer.gson().serialize(comp));
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(GsonComponentSerializer.gson().serialize(comp)));
} catch (Exception e) {
e.printStackTrace();
}
return packet.getPacket();
}
ChatItem.debug("Can't load AdventureComponentManager : " + e.getMessage());
return false;
}
return true;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
}
public void writeComponentToPacket(ChatItemPacket packet, Component next) {
if (packet.getContent().getSpecificModifier(Component.class).readSafely(0) == null
&& ReflectionUtils.hasObject(packet.getPacket(), "unsignedContent"))
{ // hard way
ReflectionUtils.setField(ReflectionUtils.getObject(packet.getPacket(), "unsignedContent"), "adventure",
next);
} else { // easy way
packet.getContent().getSpecificModifier(Component.class).write(0, next);
}
}
public Component getComponentFromPacket(ChatItemPacket packet) {
Component comp = packet.getContent().getSpecificModifier(Component.class).readSafely(0);
if (comp == null && packet.getPacketName().equalsIgnoreCase("ClientboundPlayerChatPacket")
&& ReflectionUtils.hasObject(packet.getPacket(), "unsignedContent"))
{ // if can get one more
comp = (Component) ReflectionUtils
.getObject(ReflectionUtils.getObject(packet.getPacket(), "unsignedContent"), "adventure");
}
return comp;
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Component comp = getComponentFromPacket(packet);
if (comp == null) // if comp stay null
return null;
try {
String json = GsonComponentSerializer.gson().serialize(comp);
ChatItem.debug("AdventureJSON : " + json);
JsonObject jsonObj = JSONManipulator.parseOrGet(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
e.printStackTrace();
return null;
}
}
@SuppressWarnings("deprecation")
@Override
public Object manageContent(Player viewer, Chat chat, ChatItemPacket packet, String json, Storage c)
throws Exception
{
ChatAction action = chat.getAction();
if (action.hasItem()) {
ItemStack item = action.getItem();
String itemName = ChatManager.getNameForChatAction(viewer, chat, c);
ChatItem.debug("NBT tag: " + PacketUtils.getNbtTag(item));
HoverEvent<?> hover;
if (Utils.IS_PAPER)
hover = item.asHoverEvent();
else
hover = HoverEvent.showItem(Key.key(item.getType().getKey().getKey()), item.getAmount(),
BinaryTagHolder.of(PacketUtils.getNbtTag(item)));
return manage(viewer, chat, packet, itemName, hover, null);
}
return manage(viewer, 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 viewer, Chat chat, ChatItemPacket packet, String json, Storage c) {
Component builder = Component.text("");
c.tooltipHand.forEach(s -> builder.append(Component.text(s)));
ChatAction action = chat.getAction();
if (action.hasItem()) {
return manage(viewer, chat, packet, ChatManager.getNameForChatAction(viewer, chat, c),
HoverEvent.showText(builder), null);
}
return manage(viewer, 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 viewer, Chat chat, ChatItemPacket packet, String replacement, HoverEvent<?> hover,
ClickEvent click)
{
Component comp = getComponentFromPacket(packet);
if (comp == null) {
ChatItem.debug("The component is null.");
return null;
}
comp = comp.replaceText(TextReplacementConfig.builder()
.matchLiteral(ChatManager.SEPARATOR + "" + chat.getId() + ChatManager.SEPARATOR_END)
.replacement(Component.text(replacement).hoverEvent(hover).clickEvent(click)).build());
if (ChatItem.discordSrvSupport && DiscordSrvSupport.isSendingMessage() && viewer == chat.getPlayer())
DiscordSrvSupport.sendChatMessage(chat.getPlayer(), comp, null);
viewer.sendMessage(comp);
return null;
}
private Component checkComponent(Component comp, HoverEvent<?> hover, String itemName, Chat chat) {
if (comp instanceof TextComponent) {
TextComponent tc = (TextComponent) comp;
if (ChatManager.containsSeparator(tc.content())) {
ChatItem.debug("Changing text " + tc.content() + " to " + itemName);
comp = tc.content(ChatManager.replaceSeparator(chat, tc.content(), itemName)).hoverEvent(hover);
} else
ChatItem.debug("No insert of text without separator: " + tc.content());
} else if(comp instanceof TranslatableComponent) {
TranslatableComponent tc = (TranslatableComponent) comp;
List<Component> next = new ArrayList<>();
for (Component extra : tc.args()) {
next.add(checkComponent(extra, hover, itemName, chat));
}
comp = tc.args(next);
} else
ChatItem.debug("Not valid comp class " + comp.getClass().getSimpleName() + " : " + comp);
List<Component> next = new ArrayList<>();
for (Component extra : comp.children()) {
next.add(checkComponent(extra, hover, itemName, chat));
}
return comp.children(next);
}
}
@@ -1,36 +1,66 @@
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.utils.PacketUtils;
import me.dadus33.chatitem.hook.DiscordSrvSupport;
public class ComponentNMSManager implements IComponentManager {
@Override
public boolean hasConditions() {
return PacketUtils.COMPONENT_CLASS != null;
}
@Override
public boolean hasConditions() {
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Object chatBaseComp = packet.getContent().getSpecificModifier(PacketUtils.COMPONENT_CLASS).readSafely(0);
if (chatBaseComp != null) {
try {
return PacketUtils.CHAT_SERIALIZER.getMethod("a", PacketUtils.COMPONENT_CLASS).invoke(null, chatBaseComp).toString();
} catch (Exception exc) {
exc.printStackTrace();
}
}
return null;
}
return ChatItem.getPlatform().hasBaseComponentSerializer();
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Object chatBaseComp = packet.getContent().getChatComponents().readSafely(0);
if (chatBaseComp != null) {
try {
Object o = ChatItem.getPlatform().baseComponentToJson(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, packet.getPacket()));
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -1,56 +1,50 @@
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;
@Override
public boolean hasConditions() {
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();
}
}
return ChatItem.getPlatform().hasBaseComponentSerializer();
@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 String getBaseComponentAsJSON(ChatItemPacket packet) {
try {
Object obj = packet.getContent().getChatComponents().readSafely(0);
return obj == null ? null : (String) ChatItem.getPlatform().baseComponentToJson(obj);
} catch (Exception exc) {
exc.printStackTrace();
}
return null;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json, packet.getPacket()));
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -12,57 +12,88 @@ 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 boolean hasConditions() {
@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;
}
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 : ChatItem.getPlatform().baseComponentToJson(chatBaseComp);
} catch (Exception exc) {
exc.printStackTrace();
}
}
return null;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
Object chatComp = ChatItem.getPlatform().jsonToBaseComponent(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();
}
}
@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();
}
}
}
@@ -3,7 +3,6 @@ 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;
@@ -13,12 +12,16 @@ 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;
@@ -26,105 +29,203 @@ 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 String getBaseComponentAsJSON(ChatItemPacket packet) {
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json));
} catch (Exception e) {
e.printStackTrace();
}
}
String json = packet.getContent().getStrings().readSafely(0);
if (json != null && json.startsWith("[") && json.endsWith("]")) { // if used as array instead of json obj
@Override
public Object manageItem(Player p, Chat chat, ChatItemPacket packet, ItemStack item, Storage c) throws Exception {
return manage(p, chat, packet, ChatManager.getNameOfItem(chat.getPlayer(), item, c), Utils.createItemHover(item));
}
JsonArray extra = new JsonArray();
for (JsonElement element : JsonParser.parseString(json).getAsJsonArray()) {
@Override
public Object manageEmpty(Player p, Chat chat, ChatItemPacket packet, Storage c) {
ComponentBuilder builder = new ComponentBuilder("");
c.tooltipHand.forEach(s -> builder.append(s));
Player sender = chat.getPlayer();
String handName = c.handName.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName());
return manage(p, chat, packet, handName, Utils.createTextHover(builder.create()));
}
if (element.isJsonObject()) { // ignore this
private Object manage(Player p, Chat chat, ChatItemPacket packet, String replacement, HoverEvent hover) {
BaseComponent[] components = packet.getContent().getSpecificModifier(BaseComponent[].class).readSafely(0);
if (components == null) {
String json = packet.getContent().getStrings().readSafely(0);
if (json != null && json.startsWith("[") && json.endsWith("]")) { // if used as array instead of json obj
JsonArray extra = new JsonArray();
for (JsonElement element : JsonParser.parseString(json).getAsJsonArray()) {
if (element.isJsonObject()) { // ignore this
extra.add(element);
} else {
ChatItem.debug("Ignoring element " + element);
}
}
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("text", "");
jsonObject.add("extra", extra);
json = jsonObject.toString();
}
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, replacement, chat));
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(ComponentSerializer.toString(components)));
} catch (Exception e) {
e.printStackTrace();
}
return packet.getPacket();
}
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, packet.getPacket()));
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Object manageContent(Player viewer, Chat chat, ChatItemPacket packet, String json, Storage c)
throws Exception
{
ChatAction action = chat.getAction();
if (action.hasItem())
return manage(viewer, chat, packet, ChatManager.getNameForChatAction(viewer, chat, c),
Utils.createItemHover(action.getItem(), viewer), null);
else
return manage(viewer, chat, packet, ChatManager.getNameForChatAction(viewer, chat, c),
Utils.createTextHover(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover",
"%cible%", chat.getPlayer().getName())),
Utils.createRunCommand(action.getCommand()));
}
@Override
public Object manageEmpty(Player viewer, Chat chat, ChatItemPacket packet, String json, Storage c) {
ComponentBuilder builder = new ComponentBuilder("");
c.tooltipHand.forEach(s -> builder.append(s));
HoverEvent hover;
ClickEvent click;
String rep;
ChatAction action = chat.getAction();
if (action.hasItem()) {
hover = Utils.createTextHover(builder.create());
rep = ChatManager.getHandName(chat);
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(viewer, chat, packet, rep, hover, click);
}
private Object manage(Player viewer, 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() && viewer == chat.getPlayer())
DiscordSrvSupport.sendChatMessage(viewer, TextComponent.toLegacyText(components), null);
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(ComponentSerializer.toString(components),
packet.getPacket()));
} 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);
}
}
}
private void checkComponent(BaseComponent comp, HoverEvent hover, 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);
} else
ChatItem.debug("No insert of text without separator: " + tc.getText() + " (legacy: " + tc.toLegacyText() + ")");
}
if (comp.getExtra() != null) {
for (BaseComponent extra : comp.getExtra()) {
checkComponent(extra, hover, itemName, chat);
}
}
}
}
@@ -4,15 +4,8 @@ import static me.dadus33.chatitem.utils.PacketUtils.getNmsClass;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@@ -24,270 +17,313 @@ 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;
import me.dadus33.chatitem.utils.Version;
public class JSONManipulator {
private static JSONManipulator instance = new JSONManipulator();
private static JSONManipulator instance = new JSONManipulator();
public static JSONManipulator getInstance() {
return instance;
}
public static JSONManipulator getInstance() {
private static final List<String> SKIPPED = Arrays.asList("HSTRY_ENCHANTS");
return instance;
public static final Class<?> CRAFT_ITEM_STACK_CLASS = PacketUtils.getObcClass("inventory.CraftItemStack");
public static final Class<?> NMS_ITEM_STACK_CLASS = getNmsClass("ItemStack", "world.item.");
public static final Method AS_NMS_COPY = ReflectionUtils.getMethod(CRAFT_ITEM_STACK_CLASS, "asNMSCopy", ItemStack.class);
public static final Class<?> NBT_TAG_COMPOUND = getNmsClass("NBTTagCompound", "nbt.");
public static final Method SAVE_NMS_ITEM_STACK_METHOD = ReflectionUtils.getMethod(NMS_ITEM_STACK_CLASS, NBT_TAG_COMPOUND, NBT_TAG_COMPOUND);
public static final Field MAP = ReflectionUtils.getField(NBT_TAG_COMPOUND, "map", "x");
}
private static final ConcurrentHashMap<Map.Entry<Version, ItemStack>, JsonObject> STACKS = new ConcurrentHashMap<>();
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.", "CompoundTag");
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 JsonObject itemTooltip;
private JsonArray classicTooltip;
private JsonArray classicTooltip;
public String parse(Chat chat, String json, ItemStack item, String replacement, int protocol) throws Exception {
JsonObject obj = JsonParser.parseString(json).getAsJsonObject();
final AbstractMap.SimpleEntry<Version, ItemStack> p = new AbstractMap.SimpleEntry<>(Version.getVersion(protocol), item);
public static JsonObject parseOrGet(String json) {
JsonObject wrapper = new JsonObject(); // Create a wrapper object for the whole array
if ((itemTooltip = STACKS.get(p)) == null) {
JsonArray use = Translator.toJson(replacement); // We get the json representation of the old color
// formatting method
ChatItem.debug("Remplacement: " + replacement + " use: " + use.toString());
// There's no public clone method for JSONObjects so we need to parse them every
// time
JsonObject hover = new JsonObject();
hover.addProperty("action", "show_item");
if (json.startsWith("\"") && json.endsWith("\"")) {// seems to be simple line
// Get the JSON representation of the item (well, not really JSON, but rather a
// string representation of NBT data)
hover.addProperty("value", stringifyItem(item));
if (json.startsWith("\"{") && json.endsWith("}\"")) // json in string
return JsonParser.parseString(json.substring(1, json.length() - 1).replace("\\\"", "\""))
.getAsJsonObject();
return JsonParser.parseString("{\"text\":" + json + "}").getAsJsonObject();
if (use.size() == 1) {
JsonElement extraElement = use.get(0);
if (extraElement.isJsonPrimitive())
wrapper.addProperty("text", extraElement.getAsString());
else if (extraElement.isJsonObject())
wrapper.addProperty("text", extraElement.getAsJsonObject().get("text").getAsString());
else
wrapper.add("extra", use); // add it only if
} else if (!use.isEmpty())
wrapper.add("extra", use); // add it only if
if (!wrapper.has("text"))
wrapper.addProperty("text", ""); // The text field is compulsory, even if it's empty
wrapper.add("hoverEvent", hover);
}
itemTooltip = wrapper; // Save the tooltip for later use when we encounter a placeholder
STACKS.put(p, itemTooltip); // Save it in the cache too so when parsing other packets with the same item
// (and client version) we no longer have to create it again
// We remove it later when no longer needed to save memory
Bukkit.getScheduler().runTaskLaterAsynchronously(ChatItem.getInstance(), () -> STACKS.remove(p), 100L);
}
if (obj.size() == 1 && obj.has("text")) {
itemTooltip.add("text", obj.get("text"));
ChatItem.debug("[JsonManipulator] Parsed quick: " + obj.toString() + ", wrapper: " + itemTooltip);
return ChatManager.replaceSeparator(chat, itemTooltip.toString(), replacement);
}
obj.add("extra", parseArray(obj.has("extra") ? obj.getAsJsonArray("extra") : new JsonArray(), itemTooltip));
if (!obj.has("text")) {
obj.addProperty("text", "");
}
ChatItem.debug("Parsed array for item: " + obj.toString() + ", wrapper: " + itemTooltip);
return obj.toString();
}
try {
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();
return JsonParser.parseString(json).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');
}
}
} catch (Exception e) {
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();
}
JsonObject obj = new JsonObject();
obj.addProperty("text", json);
return obj;
private JsonArray parseArray(JsonArray arr, JsonElement tooltip) {
JsonArray replacer = new JsonArray();
boolean isComplex = false;
for (int i = 0; i < arr.size(); ++i) {
JsonElement element = arr.get(i);
if (element.isJsonNull()) {
continue;
} else if (element.isJsonObject()) {
isComplex = true;
addParsedJsonObjectToArray(element.getAsJsonObject(), replacer, tooltip);
} else if (element.isJsonArray()) {
isComplex = true;
JsonArray jar = element.getAsJsonArray();
if (jar.size() != 0) {
jar = parseArray(element.getAsJsonArray(), tooltip);
replacer.set(i, jar);
}
} else if (element.isJsonPrimitive() && isComplex) {
ChatItem.debug("[JSONManipulator] Put " + element + " to trash as it's primitive with complex things");
// ignore
} else {
addParsedStringToArray(element.getAsString(), replacer, element, tooltip);
}
}
}
return replacer;
}
}
private void addParsedJsonObjectToArray(JsonObject o, JsonArray rep, JsonElement tooltip) {
JsonElement text = o.get("text");
if (text == null) {
JsonElement el = o.get("extra");
if (el != null) {
JsonArray jar = el.getAsJsonArray();
if (jar.size() != 0) {
JsonArray tmpArray = parseArray(jar, tooltip);
if (!tmpArray.isEmpty())
o.add("extra", tmpArray);
else
o.remove("extra");
} else {
o.remove("extra");
}
}
return;
} else {
if (text.getAsString().isEmpty()) {
JsonElement el = o.get("extra");
if (el != null) {
JsonArray jar = el.getAsJsonArray();
if (!jar.isEmpty()) {
JsonArray tmpArray = parseArray(jar, tooltip);
if (!tmpArray.isEmpty())
o.add("extra", tmpArray);
else
o.remove("extra");
} else {
o.remove("extra");
}
}
}
}
public String parse(Chat chat, String json, ChatAction action, String replacement) throws Exception {
addParsedStringToArray(text.getAsString(), rep, o, tooltip);
}
JsonObject obj = parseOrGet(json);
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);
}
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.hasItem()) {
public static String stringifyItem(ItemStack is) {
try {
return stringifyItemInternal(is);
} catch (Exception e) {
e.printStackTrace();
return "{}";
}
}
hover.addProperty("action", "show_item");
@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
// Get the JSON representation of the item (well, not really JSON, but rather a
// string representation of NBT data)
String item = ChatItem.getPlatform().stringifyItem(action.getItem());
hover.addProperty("value", item);
hover.add("contents", parseOrGet(item));
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();
}
} 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)
JsonArray hoverArray = new JsonArray();
hoverArray.add(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%",
chat.getItemPlayer().getPlayer().getName()));
hover.add("value", hoverArray);
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
ChatItem.debug("Wrapper " + wrapper + " > " + use);
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);
}
if (!obj.has("extra"))
obj.add("extra", new JsonArray());
ChatItem.debug("Parsing array " + obj.getAsJsonArray("extra") + " FROM: " + obj + ". Result: "
+ parseArray(obj.getAsJsonArray("extra"), wrapper));
obj.add("extra", parseArray(obj.getAsJsonArray("extra"), wrapper));
if (!obj.has("text")) {
obj.addProperty("text", "");
}
return obj.toString();
}
@SuppressWarnings("deprecation")
public String parseEmpty(Chat chat, String json, List<String> tooltip, Player sender) {
JsonObject obj = parseOrGet(json);
JsonArray array = obj.has("extra") ? obj.getAsJsonArray("extra") : new JsonArray();
JsonArray use = Translator
.toJson(ChatManager.getNameForChatAction(chat.getPlayer(), chat, ChatItem.getInstance().getStorage())
.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();
for (int i = 0; i < arr.size(); ++i) {
JsonElement element = arr.get(i);
if (element.isJsonNull())
continue;
/*
* if(separator) { if(ChatManager.containsSeparatorEnd(element.toString()))
* separator = false; continue; }
*/
if (element.isJsonObject()) {
JsonObject o = element.getAsJsonObject();
JsonElement text = o.get("text");
ChatItem.debug("adding JsonObject " + o + " (text: " + text + ")");
if (text != null && !text.getAsString().isEmpty()) {
addParsedStringToArray(text.getAsString(), replacer, o, tooltip);
}
if (o.has("extra") && !o.get("extra").getAsJsonArray().isEmpty()) {
JsonArray jar = o.get("extra").getAsJsonArray();
JsonArray tmpArray = parseArray(jar, tooltip);
if (!tmpArray.isEmpty()) {
o.add("extra", tmpArray);
replacer.add(o);
}
ChatItem.debug("[addParsedJsonObjectToArray] " + jar + " parsed " + tmpArray + " into " + replacer);
}
} else if (element.isJsonArray()) {
JsonArray jar = element.getAsJsonArray();
if (!jar.isEmpty()) {
replacer.set(i, parseArray(element.getAsJsonArray(), tooltip));
}
} else if (element.isJsonPrimitive()) {
if (ChatManager.containsSeparator(element.getAsString())) {
addParsedStringToArray(element.getAsString(), replacer, element, tooltip);
} else
replacer.add(element); // add basic element
}
}
return replacer;
}
private void addParsedStringToArray(String msg, JsonArray rep, JsonElement o, JsonElement tooltip) {
if (!ChatManager.containsSeparator(msg)) {
rep.add(o.deepCopy());
return;
}
ChatItem.debug("[JSONManipulator] Parsed string " + msg + ", rep: " + rep);
String current = "";
boolean wasSep = false;
for (String parts : msg.split("")) {
if (ChatManager.equalsSeparator(parts)) {
if (!current.isEmpty()) {
if (o.isJsonObject()) {
JsonObject jsonObj = o.getAsJsonObject().deepCopy();
jsonObj.addProperty("text", current); // edit text
rep.add(jsonObj); // add with all basic coloring things
} else {
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()) {
if (o.isJsonObject()) {
JsonObject jsonObj = o.getAsJsonObject().deepCopy();
jsonObj.addProperty("text", current); // edit text
rep.add(jsonObj); // add with all basic coloring things
} else {
rep.add(current);
}
}
}
private static String cleanStr(String s) {
return s.startsWith("'") && s.endsWith("'") ? s.substring(1, s.length() - 1) : s;
}
}
@@ -11,193 +11,297 @@ 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
private static final String STYLES = "klmnor"; // All style codes
public static JsonArray toJson(String old) {
if (old.lastIndexOf(ChatColor.COLOR_CHAR) == -1) {
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
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);
}
continue;
}
if (args == 'x' && !colorCode.isEmpty()) {
if (!text.isEmpty()) // ignore this if no text before
text += ColorManager.getColorString(colorCode);
colorCode = "x";
} else if (!colorCode.isEmpty() && !colorCode.startsWith("x")) { // already color and not hex
text += ColorManager.COLOR_CHAR + colorCode; // add the color to text
colorCode = args + "";
} else
colorCode += args; // a color by itself
} else {
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(
"[Translator] Add color code " + colorCode + " to " + text + args + ", msg: " + message);
colorCode = "";
}
// basic text, not waiting for code after '§'
text += args;
}
}
if (!next.has("color") || colorCode.length() == 1) // if no color or a color that can override it
next.addProperty("color", (colorCode.length() == 1 ? ColorManager.getColor(colorCode).getName() : "white"));
if (!text.isEmpty() || message.isEmpty() || next.size() > 0) {
next.addProperty("text", text);
ChatItem.debug("[Translator] Added content " + next + " to message" + message);
message.add(next);
}
return message;
}
public static JsonArray toJsonOld(String old){
if(old.lastIndexOf(ChatColor.COLOR_CHAR) == -1){
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
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()){
if (part.isEmpty()) {
continue;
}
if(i == 0 && !startsWithCode){
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){
if (!isColorOrStyle(code)) {
if (next != null) {
String text = next.get("text").getAsString();
text = ChatColor.COLOR_CHAR + part + text;
next.addProperty("text", text);
}else{
} 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){
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)){
if (isStyle(code)) {
next.addProperty(getStyleName(code), true);
}else{ //it's a color
if(isAlreadyColored(next)){
} 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
// 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)){
if (isStyle(code)) {
added.addProperty(getStyleName(code), true);
message.add(added);
next = added;
continue;
}
//else it can only be a color
// 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)){
// 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){
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){
for (JsonElement element : message) {
JsonObject obj = (JsonObject) element;
orderedMessage.set(i, obj); //And then we add the object to the properly ordered array
orderedMessage.set(i, obj); // And then we add the object to the properly ordered array
--i;
}
return orderedMessage;
}
private static String getColorName(char code){
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";
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
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){
private static boolean isColorOrStyle(char code) {
return ChatColor.getByChar(code) != null;
}
private static boolean isStyle(char c){
private static boolean isStyle(char c) {
return STYLES.indexOf(c) != -1;
}
private static boolean isAlreadyColored(JsonObject obj){
private static boolean isAlreadyColored(JsonObject obj) {
return obj.has("color");
}
}
@@ -1,72 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.listeners;
import static me.dadus33.chatitem.chatmanager.ChatManager.SEPARATOR;
import static me.dadus33.chatitem.chatmanager.ChatManager.SEPARATOR_END;
import 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.Storage;
import me.dadus33.chatitem.chatmanager.Chat;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.utils.Utils;
public class ChatEventListener implements Listener {
private final PacketEditingChatManager manage;
public ChatEventListener(PacketEditingChatManager manage) {
this.manage = manage;
}
public Storage getStorage() {
return this.manage.getStorage();
}
@EventHandler(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()));
}
boolean found = false;
final String oldMsg = e.getMessage();
for (String rep : getStorage().placeholders) {
if (oldMsg.contains(rep)) {
found = true;
break;
}
}
if (!found) {
ChatItem.debug("(v1) not found placeholders in: " + e.getMessage());
return;
}
Player p = e.getPlayer();
ItemStack item = ChatManager.getUsableItem(p);
if (!ChatManager.canShowItem(p, item, e))
return;
String s = e.getMessage(), firstPlaceholder = getStorage().placeholders.get(0);
for (String placeholder : getStorage().placeholders) {
s = s.replace(placeholder, firstPlaceholder);
}
if (Utils.countMatches(s, firstPlaceholder) > getStorage().limit) {
e.setCancelled(true);
if (!getStorage().messageLimit.isEmpty())
p.sendMessage(getStorage().messageLimit);
return;
}
Chat c = Chat.create(p, oldMsg);
ChatItem.debug("(v1) Set placeholder to message " + c);
e.setMessage(s.replace(firstPlaceholder, SEPARATOR + Integer.toString(c.getId()) + SEPARATOR_END));
e.setFormat(e.getFormat().replace(oldMsg, e.getMessage())); // set own message for plugin that already put the message into the format
}
}
@@ -1,15 +1,12 @@
package me.dadus33.chatitem.chatmanager.v1.listeners;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@@ -26,7 +23,6 @@ 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.IChatBaseComponentManager;
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;
@@ -40,186 +36,232 @@ 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<>();
private Object lastSentPacket = null;
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();
}
public ChatPacketManager(PacketEditingChatManager manager) {
for (IComponentManager getter : Arrays.asList(new StringComponentManager(), new IChatBaseComponentManager(), new ComponentNMSManager(), new PCMComponentManager())) {
tryRegister(getter);
}
try {
if (Class.forName("net.kyori.adventure.text.Component") != null)
tryRegister(new AdventureComponentManager());
} catch (Exception e) {
}
ChatItem.getInstance().getLogger().info("Loaded " + componentManager.size() + " getter for base components.");
ChatItem.debug("ComponentManager: " + String.join(", ", componentManager.stream().map(IComponentManager::getClass).map(Class::getSimpleName).collect(Collectors.toList())));
}
this.manager = manager;
private void tryRegister(IComponentManager getter) {
if (getter.hasConditions())
componentManager.add(getter);
}
for (IComponentManager getter : Arrays.asList(new StringComponentManager(), new ComponentNMSManager(),
new PCMComponentManager()))
{
@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
}
}
}
if (json == null || choosedGetter == null) {
ChatItem.debug("Can't find valid json getter or json itself");
ChatItem.debug("String: " + packet.getStrings().getContent());
for (Field f : e.getPacket().getClass().getDeclaredFields()) {
f.setAccessible(true);
try {
ChatItem.debug(f.getName() + ": " + f.get(e.getPacket()));
} catch (Exception exc) {
exc.printStackTrace();
}
}
return; // can't find something
}
if (!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;
e.setCancelled(true); // We cancel the packet as we're going to resends it anyways
Bukkit.getScheduler().runTaskAsynchronously(ChatItem.getInstance(), () -> {
Player p = e.getPlayer();
String message = null;
try {
ItemStack item = ChatManager.getUsableItem(itemPlayer);
if (!ItemUtils.isEmpty(item)) {
ItemStack copy = item.clone();
tryRegister(getter);
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()) {
stripData(itemInv);
}
bsm.setBlockState(sb);
}
copy.setItemMeta(bsm);
}
}
lastSentPacket = getter.manageItem(p, chat, e, item, getStorage());
} else {
if (!getStorage().handDisabled) {
lastSentPacket = getter.manageEmpty(p, chat, e, getStorage());
}
}
if (lastSentPacket == null)
ChatItem.debug("(v1) No packet to sent with manager " + getter.getClass().getName());
else
PacketUtils.sendPacket(p, lastSentPacket);
} catch (Exception e1) {
e1.printStackTrace();
}
});
}
}
private void stripData(ItemStack i) {
if (i == null) {
return;
}
if (i.getType().equals(Material.AIR)) {
return;
}
if (!i.hasItemMeta()) {
return;
}
ItemMeta im = Bukkit.getItemFactory().getItemMeta(i.getType());
ItemMeta original = i.getItemMeta();
if (original.hasDisplayName()) {
im.setDisplayName(original.getDisplayName());
}
i.setItemMeta(im);
}
try {
Class.forName("net.kyori.adventure.text.Component");
tryRegister(new AdventureComponentManager());
} catch (Exception e) {
}
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");
}
@SuppressWarnings("deprecation")
@Override
public void onSend(ChatItemPacket e) {
if (!e.hasPlayer() || !e.getPacketType().equals(PacketType.Server.CHAT))
return;
if (ChatManager.isTestingEnabled() && !ChatManager.isTesting("packet"))
return;
if (!ChatManager.isSelected("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)) {
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 || !ChatManager.containsSeparator(json)) {
for (IComponentManager getters : componentManager) {
String tmpJson = getters.getBaseComponentAsJSON(e);
if (tmpJson != null) {
json = ChatManager.fixSeparator(tmpJson);
choosedGetter = getters;
ChatItem.debug("Seems to have one nice manager with " + getters.getClass().getSimpleName()
+ " (json: " + json + ")");
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 {
if (chat.getAction().hasItem()) {
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(chat, fjson, 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.manageContent(p, chat, e, fjson, getStorage());
} else {
if (!getStorage().handDisabled) {
lastSentPacket = getter.manageEmpty(p, chat, e, fjson, getStorage());
}
}
} else
lastSentPacket = getter.manageContent(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();
}
public Storage getStorage() {
return manager.getStorage();
}
}
@@ -1,33 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.listeners;
import org.bukkit.Bukkit;
import com.comphenix.protocol.PacketType;
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.playerversion.hooks.DefaultVersionHook;
import me.dadus33.chatitem.utils.Version;
public class HandshakeListener extends PacketAdapter {
public HandshakeListener(ChatItem pl) {
super(pl, ListenerPriority.MONITOR, PacketType.Handshake.Client.SET_PROTOCOL);
}
@Override
public void onPacketReceiving(final PacketEvent e){
if(e.isPlayerTemporary() || e.getPlayer() == null)
return;
PacketType.Protocol p = e.getPacket().getProtocols().read(0);
if(p == PacketType.Protocol.STATUS || p == PacketType.Protocol.LEGACY){
return;
}
final int version = e.getPacket().getIntegers().readSafely(0);
//Delay the mapping to make sure the true address of the player was received when using bungeecord or other types of proxies
Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(), () ->
DefaultVersionHook.PROTOCOL_PER_ADDRESS.put(Version.stringifyAdress(e.getPlayer().getAddress()), version), 10L);
}
}
@@ -4,54 +4,77 @@ 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;
}
protected final Player player;
protected Object packet;
protected PacketType type;
protected boolean cancel = false;
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 ChatItemPacket(PacketType type, Object packet, Player player) {
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;
}
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);
}
public PacketContent getContent() {
return new PacketContent(this);
}
}
@@ -11,36 +11,61 @@ import me.dadus33.chatitem.chatmanager.v1.packets.protocollib.ProtocollibPacketM
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;
}
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;
}
}
@@ -11,200 +11,270 @@ 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);
}
private final ChatItemPacket packet;
private final Object obj;
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<>();
/**
* Create a PacketContent to easily read and write value in it
*
* @param packet the Negativity's packet
*/
public PacketContent(ChatItemPacket packet) {
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();
}
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;
}
}
/**
* 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;
}
}
}
@@ -2,6 +2,12 @@ package me.dadus33.chatitem.chatmanager.v1.packets;
public abstract class PacketHandler {
public void onReceive(ChatItemPacket packet) {}
public void onSend(ChatItemPacket packet) {}
public void onReceive(ChatItemPacket packet) {
}
public void onSend(ChatItemPacket packet) {
}
}
@@ -6,20 +6,48 @@ import org.bukkit.entity.Player;
public abstract class PacketManager {
public void addPlayer(Player p) {}
public void removePlayer(Player p) {}
public abstract void stop();
public void addPlayer(Player p) {
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 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));
}
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;
}
public void notifyHandlersSent(ChatItemPacket packet) {
handlers.forEach((handler) -> handler.onSend(packet));
}
}
@@ -6,101 +6,133 @@ 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);
}
String name();
String getPacketName();
String getFullName();
List<String> getAlias();
@Override
public String getPacketName() {
return packetName;
}
public static List<PacketType> values() {
@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;
}
List<PacketType> list = new ArrayList<>();
list.addAll(Arrays.asList(Server.values()));
list.addAll(Arrays.asList(Handshake.values()));
return list;
@Override
public String getPacketName() {
return packetName;
}
}
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;
}
}
@Override
public String getFullName() {
return fullName;
}
@Override
public List<String> getAlias() {
return alias;
}
}
}
@@ -1,8 +1,8 @@
package me.dadus33.chatitem.chatmanager.v1.packets.custom;
import java.util.HashMap;
import java.util.concurrent.CompletableFuture;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -10,83 +10,86 @@ 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
Bukkit.getScheduler().runTaskLater(pl, () -> {
isStarted = true;
for(Player p : Utils.getOnlinePlayers())
addPlayer(p);
}, 20);
}
public Plugin getPlugin() {
return pl;
}
private ChannelAbstract channel;
private Plugin pl;
public HashMap<Object, Integer> protocolVersionPerChannel = new HashMap<>();
private boolean isStarted = false;
@EventHandler
public void onJoin(PlayerJoinEvent e) {
addPlayer(e.getPlayer());
}
public CustomPacketManager(Plugin pl) {
@EventHandler
public void onQuit(PlayerQuitEvent e) {
removePlayer(e.getPlayer());
}
this.pl = pl;
Version version = Version.getVersion();
if (version.isNewerOrEquals(Version.V1_17))
channel = new INC2Channel(this);
else
channel = new INCChannel(this);
pl.getServer().getPluginManager().registerEvents(this, pl);
@Override
public void addPlayer(Player p) {
if(isStarted)
channel.addPlayer(p);
}
// we wait the start server
CompletableFuture.runAsync(() -> {
@Override
public void removePlayer(Player p) {
channel.removePlayer(p);
}
isStarted = true;
for (Player p : Utils.getOnlinePlayers())
addPlayer(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 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;
}
}
@@ -14,73 +14,100 @@ 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 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;
}
private CustomPacketManager customPacketManager;
private HashSet<UUID> players = new HashSet<>();
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();
}
}
}
protected ChannelAbstract(CustomPacketManager customPacketManager) {
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);
this.customPacketManager = customPacketManager;
public abstract void removeChannel(Player player, String endChannelName);
public abstract Object getChannel(Player p) throws Exception;
}
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;
}
@@ -19,74 +19,111 @@ 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;
}
private CustomPacketManager packetManager;
private List<ChannelPipeline> pipelines = new ArrayList<>();
@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();
}
}
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 == Bukkit.getPort())
possibleProtocol = ints.readSafely(2, 0);
packetManager.protocolVersionPerChannel.put(channel, possibleProtocol);
}
super.channelRead(ctx, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
@@ -22,89 +22,145 @@ 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();
}
});
}
private final ChannelInboundHandler boundHandler;
private ChannelPipeline pipeline;
@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() + ")");
}
});
}
public INC2Channel(CustomPacketManager customPacketManager) {
@Override
public Channel getChannel(Player p) throws Exception {
Class<?> networkClass = PacketUtils.getNmsClass("NetworkManager", "network.");
Object networkManager = ReflectionUtils.getFirstWith(getPlayerConnection(p), PacketUtils.getNmsClass("PlayerConnection", "server.network."), networkClass);
return ReflectionUtils.getFirstWith(networkManager, networkClass, Channel.class);
}
super(customPacketManager);
boundHandler = new ChannelInboundHandler(customPacketManager);
try {
private class ChannelHandlerSent extends ChannelOutboundHandlerAdapter {
Object mcServer = ReflectionUtils.callMethod(PacketUtils.getCraftServer(),
Version.getVersion().equals(Version.V1_17) || Version.getVersion().equals(Version.V1_21_11)
? "getServer"
: "b");
Object co = ReflectionUtils.getFirstWith(mcServer, PacketUtils.getNmsClass("MinecraftServer", "server."),
PacketUtils.getNmsClass(Version.getVersion().equals(Version.V1_21_11) ? "ServerConnectionListener"
: "ServerConnection", "server.network."));
ChatItem.debug("co: " + co);
((List<ChannelFuture>) ReflectionUtils.getObject(co,
Version.getVersion().equals(Version.V1_21_11) ? "channels" : "f")).forEach((channelFuture) ->
{
private final Player owner;
pipeline = channelFuture.channel().pipeline();
pipeline.addFirst(boundHandler);
public ChannelHandlerSent(Player player) {
this.owner = player;
}
});
} 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(
Version.getVersion().isNewerOrEquals(Version.V1_21_11) ? "Connection" : "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);
}
}
@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);
}
}
}
@@ -23,100 +23,155 @@ 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();
}
private final ChannelInboundHandler boundHandler;
private ChannelPipeline pipeline;
@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();
}
});
}
public INCChannel(CustomPacketManager customPacketManager) {
@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() + ")");
}
});
}
super(customPacketManager);
boundHandler = new ChannelInboundHandler(customPacketManager);
getFuturChannel().forEach((channelFuture) -> {
@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);
}
pipeline = channelFuture.channel().pipeline();
pipeline.addFirst(boundHandler);
private class ChannelHandlerSent extends ChannelOutboundHandlerAdapter {
});
private final Player owner;
}
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);
}
}
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);
}
}
}
@@ -1,166 +0,0 @@
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();
}
}
}
}
@@ -13,52 +13,60 @@ import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.listeners.HandshakeListener;
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());
}
});
protocolManager.addPacketListener(new HandshakeListener(pl));
}
@Override
public void stop() {
protocolManager.removePacketListeners(ChatItem.getInstance());
}
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;
}
}
@@ -1,44 +1,61 @@
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(){
public CompoundTag getTag() {
return tag;
}
public void setTag(CompoundTag newTag){
public void setTag(CompoundTag newTag) {
this.tag = newTag;
}
public void setId(String newId){
public void setId(String newId) {
this.id = newId;
}
public void setData(short newData){
public void setData(short newData) {
data = newData;
}
public String getId(){
public String getId() {
return id;
}
public short getData(){
public short getData() {
return data;
}
public void setAmount(byte newAmount){
public void setAmount(byte newAmount) {
this.amount = newAmount;
}
public byte getAmount(){
public byte getAmount() {
return amount;
}
}
@@ -10,41 +10,70 @@ 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 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;
}
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;
}
}
@@ -1,20 +1,20 @@
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");
@@ -90,43 +90,68 @@ public class ItemRewriter_1_11_TO_1_10 {
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()));
}
}
}
}
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()));
}
}
}
}
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;
}
}
@@ -1,11 +1,11 @@
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!
*/
@@ -20,6 +20,7 @@ public class ItemRewriter_1_9_TO_1_8 {
private static final Map<Integer, Integer> POTION_INDEX = new HashMap<>();
static {
/* Entities */
registerEntity(1, "Item");
registerEntity(2, "XPOrb");
@@ -137,107 +138,166 @@ public class ItemRewriter_1_9_TO_1_8 {
}
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 != 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 != 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 != 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;
@@ -250,6 +310,7 @@ public class ItemRewriter_1_9_TO_1_8 {
String id;
switch (effect) {
case 1:
id = "regeneration";
break;
@@ -299,11 +360,11 @@ public class ItemRewriter_1_9_TO_1_8 {
canEnhance = false;
break;
default:
canEnhance = false;
canExtend = false;
switch (name) {
case 0:
id = "mundane";
break;
@@ -315,28 +376,42 @@ public class ItemRewriter_1_9_TO_1_8 {
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);
}
}
@@ -1,14 +1,7 @@
package me.dadus33.chatitem.chatmanager.v2;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@@ -16,321 +9,135 @@ 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.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;
@SuppressWarnings("deprecation")
public class ChatListener implements Listener {
private static Method saveMethod;
private static boolean shouldUseAppendMethod = false;
private ChatListenerChatManager manage;
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) {
public ChatListener(ChatListenerChatManager manage) {
}
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);
}
this.manage = manage;
private ChatListenerChatManager manage;
}
public ChatListener(ChatListenerChatManager manage) {
this.manage = manage;
}
public Storage getStorage() {
public Storage getStorage() {
return manage.getStorage();
}
return manage.getStorage();
@EventHandler(priority = EventPriority.MONITOR)
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 (String rep : c.placeholders) {
if (msg.contains(rep)) {
ChatItem.debug("You choose 'chat' manager but it seems to don't be the good choice. More informations here: https://github.com/dadus33-plugins/ChatItem/wiki");
return;
}
}
}
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(), c.placeholders.get(0)));
}
String placeholder = null;
for (String rep : c.placeholders) {
if (e.getMessage().contains(rep)) {
placeholder = rep;
break;
}
}
}
if (placeholder == null) { // if not found
ChatItem.debug("(v2) Can't found placeholder in: " + e.getMessage() + " > " + PlayerNamerManager.getPlayerNamer().getName(p));
return;
}
ItemStack item = ChatManager.getUsableItem(p);
if (!ChatManager.canShowItem(p, item, e))
return;
e.setCancelled(true);
String format = e.getFormat();
String msg, defMsg = e.getMessage();
for (String rep : c.placeholders) {
defMsg = defMsg.replace(rep, Character.toString(ChatManager.SEPARATOR));
}
if (Utils.countMatches(defMsg, Character.toString(ChatManager.SEPARATOR)) > getStorage().limit) {
if (!getStorage().messageLimit.isEmpty())
p.sendMessage(getStorage().messageLimit);
return;
}
if (format.contains("%1$s") || format.contains("%2$s")) {
msg = (format.contains("%2$s") ? String.format(format, p.getDisplayName(), defMsg) : String.format(format, p.getDisplayName()));
} else {
msg = format.replace(e.getMessage(), defMsg);
}
String itemName = ChatManager.getNameOfItem(p, item, c);
String loggedMessage = msg.replace(ChatManager.SEPARATOR + "", itemName).replace("{name}", p.getName()).replace("{display-name}", p.getDisplayName());
Bukkit.getConsoleSender().sendMessage(loggedMessage); // show in log
if (ChatItem.discordSrvSupport)
DiscordSrvSupport.sendChatMessage(p, defMsg.replace(ChatManager.SEPARATOR + "", itemName).replace("{name}", p.getName()).replace("{display-name}", p.getDisplayName()));
Set<Player> recipients = e.getRecipients().isEmpty() ? new HashSet<>(Bukkit.getOnlinePlayers()) : e.getRecipients();
ChatItem.debug("Msg: " + msg.replace(ChatColor.COLOR_CHAR, '&') + ", format: " + format + " to " + recipients.size() + " players");
recipients.forEach((pl) -> showItem(pl, p, item, msg));
if (c.cooldown > 0 && !p.hasPermission("chatitem.ignore-cooldown"))
ChatManager.applyCooldown(p);
}
@EventHandler(priority = EventPriority.HIGH)
public void onChat(AsyncPlayerChatEvent e) {
public static void showItem(Player to, Player origin, ItemStack item, String msg) {
ComponentBuilder builder = new ComponentBuilder("");
ChatColor color = ChatColor.WHITE;
String colorCode = "", text = "";
boolean waiting = false, 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(text, color));
text = "";
}
waiting = true; // waiting for color code
} else if (waiting) { // if waiting for code and valid str
// if it's hexademical value and with enough space for full color
waiting = false;
if (args == 'r' && colorCode.isEmpty()) {
color = ChatColor.RESET;
continue;
}
if (args == 'x' && !colorCode.isEmpty()) {
text += ColorManager.getColorString(colorCode);
colorCode = "x";
} else
colorCode += args; // a color by itself
} else {
waiting = false;
if (!colorCode.isEmpty()) {
if (colorCode.startsWith("x") && colorCode.length() >= 7) {
if (colorCode.length() == 7)
color = ColorManager.getColor(colorCode);
else {
color = ColorManager.getColor(colorCode.substring(0, 7)); // only the hex code
ChatItem.debug("Adding color for " + colorCode.substring(7, colorCode.length()) + " (in " + colorCode + ")");
text += ColorManager.getColorString(colorCode.substring(7, colorCode.length()));
}
} else if (colorCode.length() == 1) // if only one color code
color = ColorManager.getColor(colorCode);
else
text += ColorManager.getColorString(colorCode);
colorCode = "";
}
if (args == ChatManager.SEPARATOR) {
// here put the item
appendToComponentBuilder(builder, fixColorComponent(text, color));
addItem(builder, to, origin, item);
text = "";
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(text, color));
to.spigot().sendMessage(builder.create());
}
if (ChatManager.isTestingEnabled() && !ChatManager.isTesting("chat"))
return;
if (!ChatManager.isSelected("chat"))
return;
Storage c = getStorage();
if (e.isCancelled()) {
public static void addItem(ComponentBuilder builder, Player to, Player origin, ItemStack item) {
Storage c = ChatItem.getInstance().getStorage();
if (!ItemUtils.isEmpty(item)) {
ComponentBuilder itemComponent = new ComponentBuilder("");
appendToComponentBuilder(itemComponent, fixColorComponent(ChatManager.getNameOfItem(to, item, c), ChatColor.WHITE, item));
ChatItem.debug("Item for " + to.getName() + " (ver: " + ItemPlayer.getPlayer(to).getVersion().name() + ") : " + PacketUtils.getNbtTag(item));
// itemComponent.event(new HoverEvent(Action.SHOW_ITEM, itemBaseComponent));
appendToComponentBuilder(builder, itemComponent.create());
} else {
String handName = 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());
}
}
if (ChatItem.getInstance().getChatManager().size() == 1) { // only chat
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();
}
}
}
String msg = e.getMessage().toLowerCase();
for (ItemSlot slot : ItemSlot.values()) {
public static BaseComponent[] fixColorComponent(String message, ChatColor color) {
return fixColorComponent(message, color, null);
}
for (String rep : slot.getPlaceholders()) {
public static BaseComponent[] fixColorComponent(String message, ChatColor color, @Nullable ItemStack item) {
ComponentBuilder builder = new ComponentBuilder("");
String colorCode = "", text = "";
boolean waiting = false;
for (char args : message.toCharArray()) {
if (args == '§') { // begin of color
if (colorCode.isEmpty() && !text.isEmpty()) { // text before this char
ChatItem.debug("Append while fixing name " + (ColorManager.isHexColor(color) && builder.getParts().isEmpty() ? ColorManager.removeColorAtBegin(text) : text));
appendToComponentBuilder(builder, createComponent(ColorManager.isHexColor(color) ? ColorManager.removeColorAtBegin(text) : text, color, item));
text = "";
}
waiting = true; // waiting for color code
} else if (waiting) { // if waiting for code and valid str
// if it's hexademical value and with enough space for full color
waiting = false;
if (args == 'r' && colorCode.isEmpty()) {
color = ChatColor.RESET;
continue;
}
if (args == 'x' && !colorCode.isEmpty()) {
text += ColorManager.getColorString(colorCode);
colorCode = "x";
} else
colorCode += args; // a color by itself
} else {
waiting = false;
if (!colorCode.isEmpty()) {
if (colorCode.startsWith("x") && colorCode.length() >= 7) {
if (colorCode.length() == 7)
color = ColorManager.getColor(colorCode);
else {
color = ColorManager.getColor(colorCode.substring(0, 7)); // only the hex code
ChatItem.debug("Adding color for " + colorCode.substring(7, colorCode.length()) + " (in " + colorCode + ")");
text += ColorManager.getColorString(colorCode.substring(7, colorCode.length()));
}
} else if (colorCode.length() == 1) // if only one color code
color = ColorManager.getColor(colorCode);
else
text += ColorManager.getColorString(colorCode);
ChatItem.debug("Color: " + color + ", text: " + text + ", code: " + colorCode);
colorCode = "";
}
// basic text, not waiting for code after '§'
text += args;
}
}
if (!text.isEmpty()) {
appendToComponentBuilder(builder, createComponent(text, color, item));
}
return builder.create();
}
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();
String targetReplace = ChatManager.SEPARATOR + "";
if (ChatManager.containsSeparator(e.getMessage())) { // fix for v1
Chat chat = Chat.getFrom(e.getMessage());
if (chat != null) {
targetReplace = ChatManager.SEPARATOR + "" + chat.getId() + ChatManager.SEPARATOR_END;
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 (!ChatManager.canUsePlaceholder(p, action, slot, e))
return;
e.setCancelled(true);
String format = e.getFormat().replace(targetReplace, slot.getPlaceholders().get(0));
ChatItem.debug("(v2) Using format: " + format + " and message: " + e.getMessage());
String defMsg = slot.replacePlaceholdersToSeparator(e.getMessage());
if (Utils.countMatches(defMsg, Character.toString(ChatManager.SEPARATOR)) > c.limit) {
if (!c.messageLimit.isEmpty())
p.sendMessage(c.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);
Bukkit.getConsoleSender().sendMessage(c.replaceInConsole ? loggedMessage : msg); // show in log
if (ChatItem.discordSrvSupport)
DiscordSrvSupport.sendChatMessage(p, defMsg.replace(ChatManager.SEPARATOR + "", itemName), e);
Set<Player> recipients = e.getRecipients().isEmpty() ? new HashSet<>(Bukkit.getOnlinePlayers())
: e.getRecipients();
ChatItem.debug("(v2) Msg: " + ChatItem.replace(p, msg).replace(ChatColor.COLOR_CHAR, '&') + ", format: "
+ format + " to " + recipients.size() + " players");
recipients.forEach((pl) -> ChatItem.getPlatform().sendMessage(pl, p, action, ChatItem.replace(p, msg)));
if (c.cooldown > 0 && !p.hasPermission("chatitem.ignore-cooldown"))
ChatManager.applyCooldown(p);
}
private static BaseComponent[] createComponent(String text, ChatColor color) {
return createComponent(text, color, null);
}
private static BaseComponent[] createComponent(String text, ChatColor color, ItemStack item) {
ComponentBuilder littleBuilder = new ComponentBuilder(text);
if(color != null && color != ChatColor.RESET) // don't add reset thing
littleBuilder.color(color);
if (item != null) // add to all possible sub parts
littleBuilder.event(Utils.createItemHover(item));
return littleBuilder.create();
}
}
@@ -9,43 +9,60 @@ 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);
private final ChatListener chatListener;
private boolean baseComponentAvailable = true;
//Check for existence of BaseComponent class (only on spigot)
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;
}
@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;
}
}
@@ -0,0 +1,50 @@
package me.dadus33.chatitem.chatmanager.v3;
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 PaperChatManager extends ChatManager {
private PaperListener paperListener;
public PaperChatManager(ChatItem pl) {
paperListener = new PaperListener(this);
}
@Override
public String getName() {
return "Paper";
}
@Override
public String getId() {
return "paper";
}
@Override
public void load(ChatItem pl, Storage s) {
super.load(pl, s);
Bukkit.getPluginManager().registerEvents(paperListener, pl);
}
@Override
public void unload(ChatItem pl) {
HandlerList.unregisterAll(paperListener);
}
}
@@ -0,0 +1,132 @@
package me.dadus33.chatitem.chatmanager.v3;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import io.papermc.paper.event.player.AsyncChatEvent;
import me.dadus33.chatitem.C;
import me.dadus33.chatitem.ChatItem;
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.utils.Messages;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TextReplacementConfig;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.event.HoverEventSource;
public class PaperListener implements Listener {
private PaperChatManager manage;
public PaperListener(PaperChatManager manage) {
this.manage = manage;
}
public Storage getStorage() {
return manage.getStorage();
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onChat(AsyncChatEvent e) {
if (ChatManager.isTestingEnabled() && !ChatManager.isTesting("paper"))
return;
if (!ChatManager.isSelected("paper"))
return;
Player p = e.getPlayer();
Component message = e.message();
String rawMessage = C.string(message);
if (ChatManager.containsSeparator(rawMessage)) { // fix for v1
Chat chat = Chat.getFrom(rawMessage);
if (chat != null) {
message = message.replaceText(
TextReplacementConfig.builder().matchLiteral(ChatManager.addSeparator(chat.getId()))
.replacement(C.text(chat.getSlot().getPlaceholders().get(0))).build());
rawMessage = C.string(message);
}
}
ItemSlot slot = ItemSlot.getItemSlotFromMessage(rawMessage);
ChatItem.debug("(v3) Raw message: " + rawMessage + ", slot: " + slot);
if (slot == null) // if not found
return;
ChatAction action = ChatManager.getChatAction(slot, p);
if (!ChatManager.canUsePlaceholder(p, action, slot, e))
return;
HoverEventSource<?> hoverEvent = null;
if (action.hasItem()) {
if (!action.getItem().getType().equals(Material.AIR))
hoverEvent = action.getItem().asHoverEvent();
else {
Component t = null;
for (String line : Messages.getMessageList("general.hand.tooltip", "%cible%", p.getName())) {
if (t == null) {
t = Component.text("");
} else
t.append(Component.newline());
t.append(C.text(line));
}
hoverEvent = HoverEvent.showText(t);
}
} else
hoverEvent = HoverEvent.showText(C.text(
Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", p.getName())));
TextComponent like = C.text(ChatManager.getNameForChatAction(p, action, getStorage())).hoverEvent(hoverEvent);
if (action.hasCommand())
like.clickEvent(ClickEvent.runCommand(action.getCommand()));
for (String s : slot.getPlaceholders()) {
message = message.replaceText(TextReplacementConfig.builder().matchLiteral(s).replacement(like).build());
}
if (ChatItem.getInstance().getConfig().getBoolean("manager-config.paper.send-ourself", true)) {
for (Audience a : e.viewers().isEmpty() ? Bukkit.getOnlinePlayers() : e.viewers())
a.sendMessage(e.renderer().render(p, p.displayName(), message, a));
e.setCancelled(true);
ChatItem.debug("Sent message by ourself : " + C.string(message));
} else {
e.message(message);
ChatItem.debug("Changed message to " + C.string(message));
}
if (getStorage().cooldown > 0 && !p.hasPermission("chatitem.ignore-cooldown"))
ChatManager.applyCooldown(p);
}
}
@@ -0,0 +1,28 @@
package me.dadus33.chatitem.chatmanager.v4;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import io.papermc.paper.event.player.AsyncChatEvent;
import me.dadus33.chatitem.chatmanager.ChatManager;
public class OwnListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR)
public void onChat(AsyncChatEvent e) {
if (ChatManager.isTestingEnabled() && !ChatManager.isTesting("ownformatter"))
return;
if (!ChatManager.isSelected("ownformatter"))
return;
if (e.isCancelled())
return;
e.setCancelled(true);
/*
* Player p = e.getPlayer(); Component msg = e.message();
*/
}
}
@@ -0,0 +1,27 @@
package me.dadus33.chatitem.chatmanager.v4;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
public class OwnManager extends ChatManager {
@Override
public String getName() {
return "Own Formatter";
}
@Override
public String getId() {
return "ownformatter";
}
@Override
public void unload(ChatItem pl) {
}
}
@@ -10,7 +10,10 @@ 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;
}
}
@@ -2,149 +2,282 @@ package me.dadus33.chatitem.commands;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
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.Colors;
import me.dadus33.chatitem.utils.ItemUtils;
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;
@SuppressWarnings("deprecation")
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")) {
InventoryListener.open(p);
} else if (args[0].equalsIgnoreCase("reload")) {
ChatItem.reload(sender);
} else if (args[0].equalsIgnoreCase("show")) {
Player cible = args.length == 1 ? p : Bukkit.getPlayer(args[1]);
if(cible == null) {
Messages.sendMessage(p, "player-not-found", "%arg%", args[1]);
return false;
}
Storage c = ChatItem.getInstance().getStorage();
ItemStack item = ChatManager.getUsableItem(cible);
ChatListener.showItem(p, cible, item, c.commandFormat.replace("%name%", cible.getName()).replace("%item%", ChatManager.SEPARATOR + ""));
} else if (args[0].equalsIgnoreCase("broadcast")) {
Player cible = args.length == 1 ? p : Bukkit.getPlayer(args[1]);
if(cible == null) {
Messages.sendMessage(p, "player-not-found", "%arg%", args[1]);
return false;
}
Storage c = ChatItem.getInstance().getStorage();
ItemStack item = ChatManager.getUsableItem(cible);
for(Player all : Bukkit.getOnlinePlayers())
ChatListener.showItem(all, cible, item, c.commandFormat.replace("%name%", cible.getName()).replace("%item%", ChatManager.SEPARATOR + ""));
} else if (args[0].equalsIgnoreCase("link") || args[0].equalsIgnoreCase("links")) {
ConfigurationSection config = ChatItem.getInstance().getConfig()
.getConfigurationSection("messages.chatitem-cmd.links");
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")) {
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 {
Messages.sendMessage(p, "chatitem-cmd.help");
}
return false;
}
private void sendCheckSelectMessage(Player p, String testing) {
ChatManager.setTesting(testing);
p.chat("Checking for " + testing + ": [i]");
private static final List<String> ORDERS;
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);
}
static {
if (Utils.IS_PAPER)
ORDERS = Arrays.asList("chat", "paper", "packet", "all");
else
ORDERS = Arrays.asList("chat", "packet", "all");
}
@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("ec") && ChatItem.getInstance().getStorage().cmdShow) {
sendCommandFormatFrom(p, ItemSlot.ENDERCHEST, Bukkit.getOnlinePlayers());
} else if (args[0].equalsIgnoreCase("inv") && ChatItem.getInstance().getStorage().cmdShow) {
sendCommandFormatFrom(p, ItemSlot.INVENTORY, Bukkit.getOnlinePlayers());
} else if (args[0].equalsIgnoreCase("show") && ChatItem.getInstance().getStorage().cmdShow) {
sendCommandFormatFrom(p, ItemSlot.getItemSlotByKey(args.length <= 1 ? "" : args[1]), Arrays.asList(p));
} else if (args[0].equalsIgnoreCase("broadcast") && ChatItem.getInstance().getStorage().cmdBroadcast) {
sendCommandFormatFrom(p, ItemSlot.getItemSlotByKey(args.length <= 1 ? "" : args[1]),
Bukkit.getOnlinePlayers());
} 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(
Colors.GRAY + "----------" + Colors.GOLD + " ChatItem - Setup " + Colors.GRAY + "----------");
p.sendMessage(Colors.AQUA + "Welcome in the help of setup." + Colors.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(Colors.RED + "Unknow test for " + tested + ".");
return false;
}
if (args.length == 2) {
p.sendMessage(Colors.RED + "Can't find if it works");
return false;
}
if (args[2].equalsIgnoreCase("yes")) {
ChatManager.setTesting(null);
InventoryListener.setInConfig("manager", tested);
p.sendMessage(Colors.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(Colors.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(Colors.RED + "Sad. Checking for next manager ...");
sendCheckSelectMessage(p, ORDERS.get(index + 1));
}
} else {
p.sendMessage(Colors.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 sendCommandFormatFrom(Player p, ItemSlot slot, Collection<? extends Player> receivers) {
if (slot == null) {
Messages.sendMessage(p, "chatitem-cmd.help");
return;
}
ChatAction action = ChatManager.getChatAction(slot, p);
ChatItem.debug("Action: " + action);
if (action.hasItem() && ItemUtils.isEmpty(action.getItem())) {
Messages.sendMessage(p, "empty-item");
return;
}
for (Player all : receivers)
ChatItem.getPlatform().sendMessage(all, p, action,
slot.getShowMessage().replace("%name%", p.getName()).replace("%item%", ChatManager.SEPARATOR + ""));
}
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(Colors.GOLD + "Did it worked fine? ");
TextComponent agree = new TextComponent(Colors.GREEN + "Yes");
agree.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/chatitem select " + testing + " yes"));
agree.setHoverEvent(Utils.createTextHover(Colors.GRAY + "Click to say it worked fine"));
text.addExtra(agree);
text.addExtra(", ");
TextComponent decline = new TextComponent(Colors.RED + "No");
decline.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/chatitem select " + testing + " no"));
decline.setHoverEvent(Utils.createTextHover(Colors.GRAY + "Click to say it's not working as expected"));
text.addExtra(decline);
if (testing.equalsIgnoreCase("packet"))
text.addExtra(
" (This manager can have different result between 'chatitem select' and default chat for technical reasons. If nothing works, it's recommended to select it and try again)");
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 <= 1) {
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) {
for (String s : Arrays.asList("show", "ec", "inv"))
if (prefix.isEmpty() || s.startsWith(prefix))
list.add(s);
}
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);
} else if (arg[0].equalsIgnoreCase("show") || arg[0].equalsIgnoreCase("broadcast")) {
for (ItemSlot slot : ItemSlot.values())
if (prefix.isEmpty() || slot.getKey().startsWith(prefix))
list.add(slot.getKey());
}
return list;
}
@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) {
for (String s : Arrays.asList("help", "admin", "reload", "link", "show", "broadcast", "select"))
if (prefix.isEmpty() || s.startsWith(prefix))
list.add(s);
}
return list;
}
}
@@ -1,15 +1,24 @@
package me.dadus33.chatitem.hook;
import org.mineacademy.chatcontrol.settings.Settings;
import me.dadus33.chatitem.ChatItem;
public class ChatControlSupport {
public static void init(ChatItem pl) {
Settings.Chat.Grammar.CAPITALIZE = false;
Settings.Chat.Grammar.INSERT_DOT = false;
pl.getLogger().info("Loaded ChatControl support by disabling 2 options in 'Chat.Grammar' config.");
}
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();
}
}
}
@@ -8,9 +8,12 @@ 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);
}
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);
}
}
@@ -1,17 +1,36 @@
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;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
public class DiscordSrvSupport {
@SuppressWarnings("deprecation")
public static void sendChatMessage(Player p, String message) {
DiscordSRV pl = DiscordSRV.getPlugin();
if (DiscordSRV.config().getBooleanElse("UseModernPaperChatEvent", false) && pl.isModernChatEventAvailable()) {
return;
}
pl.processChatMessage(p, message, pl.getOptionalChannel("global"), false);
}
public static boolean isSendingMessage() {
return ChatItem.getInstance().getStorage().discordSrvSendMsg;
}
public static void sendChatMessage(Player p, String message, Event e) {
DiscordSRV pl = DiscordSRV.getPlugin();
pl.processChatMessage(p, message, pl.getOptionalChannel("global"), false, e);
}
public static void sendChatMessage(Player p, Component message, Event e) {
DiscordSRV pl = DiscordSRV.getPlugin();
pl.processChatMessage(p,
github.scarsz.discordsrv.dependencies.kyori.adventure.text.serializer.gson.GsonComponentSerializer
.gson().deserialize(GsonComponentSerializer.gson().serialize(message)),
pl.getOptionalChannel("global"), false, e);
}
}
@@ -1,21 +0,0 @@
package me.dadus33.chatitem.hook;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.inventory.ItemStack;
import com.willfp.ecoenchants.display.EnchantmentCache;
import com.willfp.ecoenchants.enchantments.util.EnchantChecks;
public class EcoEnchantsSupport {
public static List<String> getLores(ItemStack item) {
List<String> lores = new ArrayList<>();
EnchantChecks.getEnchantsOnItem(item).forEach((en, lvl) -> {
lores.add(EnchantmentCache.getEntry(en).getNameWithLevel(lvl));
});
return lores;
}
}
@@ -0,0 +1,73 @@
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 = ChatItem.getPlatform().getPluginVersion(Bukkit.getPluginManager().getPlugin("EcoEnchants"));
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;
}
@SuppressWarnings("deprecation")
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,53 @@
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,25 @@
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,52 @@
package me.dadus33.chatitem.hook.placeholders;
import java.util.Locale;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scoreboard.Team;
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil;
public class EssentialsPlaceholdersHook implements IPlaceholders {
private Essentials getEssentials() {
return ((Essentials) Bukkit.getPluginManager().getPlugin("Essentials"));
}
@SuppressWarnings("deprecation")
@Override
public String replace(Player p, String text) {
User user = getEssentials().getUser(p);
if (user == null) {
return null;
}
String world = user.getWorld().getName();
String username = user.getName();
String nickname = user.getFormattedNickname();
Player player = user.getBase();
Team team = player.getScoreboard().getPlayerTeam(player);
return text.replace("{GROUP}", user.getGroup())
.replace("{WORLD}", getEssentials().getSettings().getWorldAlias(world)).replace("{WORLDNAME}", world)
.replace("{SHORTWORLDNAME}", world.substring(0, 1).toUpperCase(Locale.ENGLISH))
.replace("{TEAMNAME}", team == null ? "" : team.getDisplayName())
.replace("{TEAMPREFIX}", team == null ? "" : team.getPrefix())
.replace("{TEAMSUFFIX}", team == null ? "" : team.getSuffix())
.replace("{PREFIX}",
FormatUtil.replaceFormat(getEssentials().getPermissionsHandler().getPrefix(player)))
.replace("{SUFFIX}",
FormatUtil.replaceFormat(getEssentials().getPermissionsHandler().getSuffix(player)))
.replace("{USERNAME}", username).replace("{NICKNAME}", nickname == null ? username : nickname);
}
}
@@ -0,0 +1,9 @@
package me.dadus33.chatitem.hook.placeholders;
import org.bukkit.entity.Player;
public interface IPlaceholders {
String replace(Player p, String text);
}
@@ -0,0 +1,57 @@
package me.dadus33.chatitem.hook.placeholders;
import org.bukkit.entity.Player;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.LuckPermsProvider;
import net.luckperms.api.cacheddata.CachedMetaData;
import net.luckperms.api.model.user.User;
public class LuckPermsPlaceholderHook implements IPlaceholders {
private LuckPerms luckPerms = null;
public LuckPerms getLuckPerms() {
if (luckPerms == null) {
try {
luckPerms = LuckPermsProvider.get();
} catch (IllegalStateException ignored) {
// API not yet loaded.
}
}
return luckPerms;
}
@Override
public String replace(Player p, String text) {
LuckPerms api = getLuckPerms();
if (api == null)
return text;
User user = api.getUserManager().getUser(p.getUniqueId());
if (user == null)
return text;
CachedMetaData meta = user.getCachedData().getMetaData();
String prefix = meta.getPrefix();
String suffix = meta.getSuffix();
if (prefix == null)
prefix = "";
if (suffix == null)
suffix = "";
return text.replace("{prefix}", prefix).replace("{suffix}", suffix).replace("%prefix%", prefix)
.replace("%suffix%", suffix);
}
}
@@ -0,0 +1,16 @@
package me.dadus33.chatitem.hook.placeholders;
import org.bukkit.entity.Player;
import be.maximvdw.placeholderapi.PlaceholderAPI;
public class MVdWPlaceholderAPIHook implements IPlaceholders {
@Override
public String replace(Player p, String text) {
return PlaceholderAPI.replacePlaceholders(p, text);
}
}
@@ -0,0 +1,14 @@
package me.dadus33.chatitem.hook.placeholders;
import org.bukkit.entity.Player;
public class OwnPlaceholder implements IPlaceholders {
@Override
public String replace(Player p, String text) {
return text.replace("{name}", p.getName()).replace("%name%", p.getName());
}
}
@@ -0,0 +1,16 @@
package me.dadus33.chatitem.hook.placeholders;
import org.bukkit.entity.Player;
import me.clip.placeholderapi.PlaceholderAPI;
public class PlaceholderAPIHook implements IPlaceholders {
@Override
public String replace(Player p, String text) {
return PlaceholderAPI.setPlaceholders(p, text);
}
}
@@ -0,0 +1,81 @@
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,42 @@
package me.dadus33.chatitem.invsee.hook;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ChatItem;
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 = ChatItem.getPlatform().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,41 @@
package me.dadus33.chatitem.invsee.hook;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ChatItem;
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 OneItemShower extends InvShower {
private final ItemStack item;
public OneItemShower(Player cible, ItemStack item) {
super("one_item", cible);
this.item = item == null ? new ItemStack(Material.AIR) : item.clone();
}
@Override
public void open(Player p) {
Inventory inv = ChatItem.getPlatform().createInventory(new CustomInventoryHolder(), 9,
Messages.getMessage("inventory.name", "%cible%", name));
for (int i = 0; i < 9; i++)
inv.setItem(i, ItemUtils.ITEM_EMPTY_BROWN);
inv.setItem(4, item);
p.openInventory(inv);
}
}
@@ -0,0 +1,55 @@
package me.dadus33.chatitem.invsee.hook;
import java.util.HashMap;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import me.dadus33.chatitem.ChatItem;
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 = ChatItem.getPlatform().createInventory(new CustomInventoryHolder(), 54,
Messages.getMessage("inventory.name", "%cible%", name));
for (int i = 0; i < 18; i++)
inv.setItem(i, ItemUtils.ITEM_EMPTY_BROWN);
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);
}
}
@@ -10,45 +10,50 @@ 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);
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());
}
}
/**
* 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());
}
}
}
@@ -20,58 +20,78 @@ import me.dadus33.chatitem.itemnamer.hook.LangUtilsNamer;
public class NamerManager {
private static final HashMap<Priority, List<INamer>> NAMER_PER_PRIORITY = new HashMap<>();
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) {
getOrCreate(namer.getPriority()).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 && tmpName != "") {
ChatItem.debug("Using namer " + namer.getClass().getSimpleName() + ", value: " + tmpName);
return tmpName;
}
}
}
return null; // this should NEVER append
}
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
}
}
@@ -9,14 +9,18 @@ import me.dadus33.chatitem.itemnamer.INamer;
public class ChatItemTranslationNamer implements INamer {
@Override
public Priority getPriority() {
return Priority.SMALL;
}
@Override
public Priority getPriority() {
@Override
public String getName(Player p, ItemStack item, Storage storage) {
return Translation.get(item);
}
return Priority.SMALL;
}
@Override
public String getName(Player p, ItemStack item, Storage storage) {
return Translation.getOr(item, null);
}
}
@@ -10,14 +10,19 @@ import me.dadus33.chatitem.itemnamer.INamer;
public class DefaultNamer implements INamer {
@Override
public Priority getPriority() {
return Priority.MINOR;
}
@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());
}
@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());
}
}
@@ -4,23 +4,28 @@ import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.itemnamer.INamer;
@SuppressWarnings("deprecation")
public class ItemDisplayNamer implements INamer {
@Override
public Priority getPriority() {
return Priority.MEDIUM;
}
@Override
public Priority getPriority() {
@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;
}
return Priority.MEDIUM;
}
@Override
public String getName(Player p, ItemStack item, Storage storage) {
String name = ChatItem.getPlatform().getItemDisplayName(item);
if (name != null && name != "")
return storage.colorIfColored ? ChatColor.stripColor(name) : name;
return null;
}
}
@@ -10,14 +10,18 @@ import me.dadus33.chatitem.itemnamer.INamer;
public class LangUtilsNamer implements INamer {
@Override
public Priority getPriority() {
return Priority.IMPORTANT;
}
@Override
public Priority getPriority() {
@Override
public String getName(Player p, ItemStack item, Storage storage) {
return LanguageHelper.getItemName(item, p);
}
return Priority.IMPORTANT;
}
@Override
public String getName(Player p, ItemStack item, Storage storage) {
return LanguageHelper.getItemName(item, p);
}
}
@@ -1,10 +1,7 @@
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;
@@ -12,116 +9,199 @@ 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;
import me.dadus33.chatitem.utils.Utils;
public class InventoryListener implements Listener {
@EventHandler
public void onClick(InventoryClickEvent e) {
if(e.getClickedInventory() == null || !(e.getWhoClicked() instanceof Player) || e.getCurrentItem() == null
|| !(e.getClickedInventory().getHolder() instanceof AdminHolder))
return;
e.setCancelled(true);
Player p = (Player) e.getWhoClicked();
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)) {
AdminHolder holder = (AdminHolder) e.getClickedInventory().getHolder();
String key = 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.REDSTONE)) {
setInConfig("general.deny-if-no-item", c.denyIfNoItem = !c.denyIfNoItem);
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));
@EventHandler
public void onClick(InventoryClickEvent e) {
if (!(e.getWhoClicked() instanceof Player))
return;
Player p = (Player) e.getWhoClicked();
Inventory topInventory = Utils.getTopInventory(e);
InventoryHolder openInventoryHolder = topInventory == null ? null : topInventory.getHolder();
if (openInventoryHolder != null && openInventoryHolder instanceof CustomInventoryHolder) {
e.setCancelled(true);
return;
}
if (e.getClickedInventory() == null)
return;
InventoryHolder holder = e.getClickedInventory().getHolder();
if (holder == null || !(holder instanceof ChatItemHolder)) {
if (e.getClick().equals(ClickType.DOUBLE_CLICK) && topInventory != null) {
if (openInventoryHolder != null && openInventoryHolder 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 = ChatItem.getPlatform().createInventory(holder, 27, Messages.getMessage("admin-inv.name"));
for (int i = 0; i < inv.getSize(); i++)
inv.setItem(i, ChatItem.getPlatform().createItemStack(ItemUtils.WHITE_STAINED_GLASS, "-"));
int slot = 0;
for (String manager : Arrays.asList("all", "packet", "chat", "paper")) { // , "ownformatter")) {
if ((manager == "paper" || manager == "ownformatter") && !Utils.IS_PAPER)
continue;
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, ChatItem.getPlatform().createTranslatedItemStack(Material.BOOK, "admin-inv.language", "%name%",
Translation.getMessage("language.name")));
inv.setItem(26, ChatItem.getPlatform().createItemStack(ItemUtils.MATERIAL_CLOSE,
Messages.getMessage("admin-inv.close")));
p.openInventory(inv);
}
private static ItemStack getBoolChangeItem(Material type, String key, boolean b) {
return ChatItem.getPlatform().createItemStack(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 ChatItem.getPlatform().createItemStack(type, Messages.getMessage("admin-inv." + key, "%state%", amount),
Messages.getMessageList("admin-inv.amount-lore"));
}
private static ItemStack getManagerItem(String manager, Object... placeholders) {
return ChatItem.getPlatform().createTranslatedItemStack(Material.PAPER, "admin-inv.manager." + manager,
placeholders);
}
inv.setItem(18, getBoolChangeItem(ItemUtils.INK_SAC, "color-if-already-colored", c.colorIfColored));
inv.setItem(19, getBoolChangeItem(Material.REDSTONE, "deny-no-item", c.denyIfNoItem));
inv.setItem(20, getBoolChangeItem(Material.STICK, "hand-disabled", c.handDisabled));
inv.setItem(21, getAmountChangeItem(Material.IRON_DOOR, "limit-per-message", c.limit));
inv.setItem(22, getAmountChangeItem(Material.APPLE, "cooldown", c.cooldown));
inv.setItem(23, getBoolChangeItem(Material.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));
}
}
@@ -14,22 +14,30 @@ 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());
}
@SuppressWarnings("deprecation")
@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());
}
}
@@ -1,14 +1,9 @@
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;
@@ -21,75 +16,93 @@ 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.Colors;
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());
}
}
@EventHandler
public void onClick(InventoryClickEvent e) {
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 (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(Colors.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 = ChatItem.getPlatform().createInventory(holder, 54,
"Change language - " + Colors.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, ChatItem.getPlatform().createItemStack(Material.ARROW, Colors.GRAY + "Back"));
if (page > 0)
inv.setItem(3, ChatItem.getPlatform().createItemStack(Material.ARROW, Colors.RED + "Previous page"));
if (langs.size() > (perPage * (page + 1)))
inv.setItem(5, ChatItem.getPlatform().createItemStack(Material.ARROW, Colors.GREEN + "Next page"));
inv.setItem(8, ChatItem.getPlatform().createItemStack(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 = ChatItem.getPlatform().createItemStack(Material.PAPER,
Colors.GOLD + Translation.getAllLangs().get(lang), Colors.GRAY + "Clic to select this language");
if (lang.equalsIgnoreCase(ChatItem.getInstance().getStorage().language)) {
item.addUnsafeEnchantment(ItemUtils.getEnchant("DURABILITY", "UNBREAKING"), 1);
ItemMeta meta = item.getItemMeta();
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
item.setItemMeta(meta);
}
inv.setItem(slot++, item);
}
p.openInventory(inv);
}
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);
}
}
@@ -2,16 +2,8 @@ package me.dadus33.chatitem.listeners.holder;
import java.util.HashMap;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
public class AdminHolder extends ChatItemHolder {
public class AdminHolder implements InventoryHolder {
public final HashMap<Integer, String> keyBySlot = new HashMap<>();
@Override
public Inventory getInventory() {
return null;
}
public final HashMap<Integer, String> keyBySlot = new HashMap<>();
}
@@ -0,0 +1,15 @@
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 {
}
@@ -2,24 +2,21 @@ package me.dadus33.chatitem.listeners.holder;
import java.util.HashMap;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
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 class TranslationHolder implements InventoryHolder {
public final HashMap<Integer, String> langBySlot = new HashMap<>();
private final int page;
public TranslationHolder(int page) {
this.page = page;
}
public int getPage() {
return page;
}
@Override
public Inventory getInventory() {
return null;
}
public int getPage() {
return page;
}
}
@@ -0,0 +1,58 @@
package me.dadus33.chatitem.platform;
import java.util.Arrays;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import me.dadus33.chatitem.chatmanager.ChatAction;
import me.dadus33.chatitem.utils.Messages;
import me.dadus33.chatitem.utils.Version;
public interface IPlatform {
String getName();
Inventory createInventory(InventoryHolder holder, int slot, String name);
ItemStack createItemStack(Material type, String name);
default ItemStack createTranslatedItemStack(Material type, String key, Object... placeholders) {
return createItemStack(type, Messages.getMessage(key + ".name", placeholders),
Messages.getMessageList(key + ".lore", placeholders));
}
default ItemStack createItemStack(Material type, String name, String... lore) {
return createItemStack(type, name, Arrays.asList(lore));
}
ItemStack createItemStack(Material type, String name, List<String> lore);
String getItemDisplayName(ItemStack item);
String getPluginVersion(Plugin plugin);
Version getMinecraftVersion();
String getNMSVersion();
boolean hasBaseComponentSerializer();
String baseComponentToJson(Object obj);
Object jsonToBaseComponent(String json);
void sendMessage(Player to, Player origin, ChatAction action, String msg);
String stringifyItem(ItemStack item);
}
@@ -0,0 +1,250 @@
package me.dadus33.chatitem.platform.hook;
import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.Plugin;
import me.dadus33.chatitem.C;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatAction;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.platform.IPlatform;
import me.dadus33.chatitem.utils.Messages;
import me.dadus33.chatitem.utils.ReflectionUtils;
import me.dadus33.chatitem.utils.Version;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TextReplacementConfig;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.event.HoverEvent.ShowItem;
import net.kyori.adventure.text.event.HoverEventSource;
import net.kyori.adventure.text.format.NamedTextColor;
public class PaperPlatform implements IPlatform {
@Override
public String getName() {
return "PaperMC";
}
@Override
public Inventory createInventory(InventoryHolder holder, int slot, String name) {
return Bukkit.createInventory(holder, slot, C.text(name));
}
@Override
public ItemStack createItemStack(Material type, String name) {
ItemStack item = new ItemStack(type);
ItemMeta meta = (ItemMeta) item.getItemMeta();
meta.displayName(C.text(name).color(NamedTextColor.WHITE));
item.setItemMeta(meta);
return item;
}
@Override
public ItemStack createItemStack(Material type, String name, List<String> lore) {
ItemStack item = new ItemStack(type);
ItemMeta meta = (ItemMeta) item.getItemMeta();
meta.displayName(C.text(name).color(NamedTextColor.WHITE));
meta.lore(lore.stream().map(C::text).collect(Collectors.toList()));
item.setItemMeta(meta);
return item;
}
@SuppressWarnings("deprecation")
@Override
public String getItemDisplayName(ItemStack item) {
// actually the get Displayname for better ... See:
// https://github.com/KyoriPowered/adventure-platform/issues/185
// return
// LegacyComponentSerializer.legacySection().serialize(item.displayName());
return item.hasItemMeta() && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : null;
}
@Override
public String getPluginVersion(Plugin plugin) {
return plugin.getPluginMeta().getVersion();
}
@Override
public Version getMinecraftVersion() {
return Version.getVersionByName("v" + Bukkit.getMinecraftVersion().replace(".", "_"));
}
@Override
public String getNMSVersion() {
String[] parts = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",");
return parts.length <= 3 ? "" : parts[3];
}
@Override
public boolean hasBaseComponentSerializer() {
return SpigotPlatform.getBaseComponentToJsonMethod() != null;
}
private Object getRegistry() throws Exception {
Class<?> serverClass = Class.forName("net.minecraft.server.MinecraftServer");
return serverClass.getDeclaredMethod("registryAccess")
.invoke(serverClass.getDeclaredMethod("getServer").invoke(null));
}
@Override
public String baseComponentToJson(Object obj) {
Method m = SpigotPlatform.getBaseComponentToJsonMethod();
if (m == null)
return null;
try {
Object[] args = new Object[m.getParameterCount()];
args[0] = obj;
if (args.length > 1 && ReflectionUtils.isClassExist("net.minecraft.core.HolderLookup$Provider")) {
Class<?> c = Class.forName("net.minecraft.core.HolderLookup$Provider");
if (m.getParameterTypes()[1].isAssignableFrom(c)) {
args[1] = getRegistry();
}
}
return (String) m.invoke(null, args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public Object jsonToBaseComponent(String json) {
Method m = SpigotPlatform.getJsonToBaseComponentMethod();
try {
Object[] args = new Object[m.getParameterCount()];
args[0] = json;
if (args.length > 1 && ReflectionUtils.isClassExist("net.minecraft.core.HolderLookup$Provider")) {
Class<?> c = Class.forName("net.minecraft.core.HolderLookup$Provider");
if (m.getParameterTypes()[1].isAssignableFrom(c)) {
args[1] = getRegistry();
}
}
return m.invoke(null, args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public void sendMessage(Player to, Player origin, ChatAction action, String msg) {
HoverEventSource<?> hoverEvent = null;
if (action.hasItem()) {
if (!action.getItem().getType().equals(Material.AIR))
hoverEvent = action.getItem().asHoverEvent();
else {
Component t = null;
for (String line : Messages.getMessageList("general.hand.tooltip", "%cible%", origin.getName())) {
if (t == null) {
t = Component.text("");
} else
t.append(Component.newline());
t.append(C.text(line));
}
hoverEvent = HoverEvent.showText(t);
}
} else
hoverEvent = HoverEvent.showText(C.text(Messages
.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", origin.getName())));
TextComponent like = Component
.text(ChatManager.getNameForChatAction(origin, action, ChatItem.getInstance().getStorage()))
.hoverEvent(hoverEvent);
if (action.hasCommand())
like = like.clickEvent(ClickEvent.runCommand(action.getCommand()));
to.sendMessage(C.text(msg).replaceText(
TextReplacementConfig.builder().matchLiteral(ChatManager.SEPARATOR + "").replacement(like).build()));
}
@SuppressWarnings("deprecation")
@Override
public String stringifyItem(ItemStack item) {
ShowItem si = item.asHoverEvent().value();
String json = "{id:\"" + si.item().asString() + "\",count:" + item.getAmount();
if (si.nbt() != null) {
json += ",tag:{" + si.nbt().string() + "}";
} else if (Version.getVersion().isNewerOrEquals(Version.V1_20_6)) { // since MC 1.20.5 in fact
json += ",components:" + (item.hasItemMeta() ? item.getItemMeta().getAsString() : "{}");
}
json += "}";
ChatItem.debug("Item stringified: " + json);
return json;
}
}
@@ -0,0 +1,680 @@
package me.dadus33.chatitem.platform.hook;
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.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.Plugin;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.ItemPlayer;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.chatmanager.ChatAction;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulator;
import me.dadus33.chatitem.platform.IPlatform;
import me.dadus33.chatitem.playernamer.PlayerNamerManager;
import me.dadus33.chatitem.utils.ColorManager;
import me.dadus33.chatitem.utils.Colors;
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 me.dadus33.chatitem.utils.Version;
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;
@SuppressWarnings("deprecation")
public class SpigotPlatform implements IPlatform {
private static boolean shouldUseAppendMethod = false;
static {
try {
try {
ComponentBuilder.class.getDeclaredMethod("append", BaseComponent[].class);
shouldUseAppendMethod = true;
} catch (Exception e) {
shouldUseAppendMethod = false;
}
ChatItem.getInstance().getLogger().info(shouldUseAppendMethod ? "Use ComponentBuilder's method."
: "Use own ComponentBuilder append method.");
} catch (Exception e) {
}
}
@Override
public String getName() {
return "Spigot";
}
@Override
public Inventory createInventory(InventoryHolder holder, int slot, String name) {
return Bukkit.createInventory(holder, slot, name);
}
@Override
public ItemStack createItemStack(Material type, String name) {
ItemStack item = new ItemStack(type);
ItemMeta meta = (ItemMeta) item.getItemMeta();
meta.setDisplayName(Colors.RESET + name);
item.setItemMeta(meta);
return item;
}
@Override
public ItemStack createItemStack(Material type, String name, List<String> lore) {
ItemStack item = new ItemStack(type);
ItemMeta meta = (ItemMeta) item.getItemMeta();
meta.setDisplayName(Colors.RESET + name);
meta.setLore(lore);
item.setItemMeta(meta);
return item;
}
@Override
public String getItemDisplayName(ItemStack item) {
return item.hasItemMeta() && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : null;
}
@Override
public String getPluginVersion(Plugin plugin) {
return plugin.getDescription().getVersion();
}
@Override
public Version getMinecraftVersion() {
return Version.getVersionByName(getNMSVersion().replace("_R4", "_6"));
}
@Override
public String getNMSVersion() {
return Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
}
@Override
public boolean hasBaseComponentSerializer() {
return getBaseComponentToJsonMethod() != null;
}
@Override
public String baseComponentToJson(Object obj) {
Method m = getBaseComponentToJsonMethod();
try {
Object[] args = new Object[m.getParameterCount()];
args[0] = obj;
if (args.length > 1 && ReflectionUtils.isClassExist("net.minecraft.core.HolderLookup$a")) {
Class<?> c = Class.forName("net.minecraft.core.HolderLookup$a");
if (m.getParameterTypes()[1].isAssignableFrom(c)) {
args[1] = getRegistry();
}
}
return (String) m.invoke(null, args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public Object jsonToBaseComponent(String json) {
Method m = getJsonToBaseComponentMethod();
try {
Object[] args = new Object[m.getParameterCount()];
args[0] = json;
if (args.length > 1 && ReflectionUtils.isClassExist("net.minecraft.core.HolderLookup$a")) {
Class<?> c = Class.forName("net.minecraft.core.HolderLookup$a");
if (m.getParameterTypes()[1].isAssignableFrom(c)) {
args[1] = getRegistry();
}
}
return m.invoke(null, args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private Object getRegistry() throws Exception {
Class<?> serverClass = Class.forName("net.minecraft.server.MinecraftServer");
return serverClass.getDeclaredMethod("ba").invoke(serverClass.getDeclaredMethod("getServer").invoke(null));
}
public static Method getBaseComponentToJsonMethod() {
Class<?> chatSerializerClass = PacketUtils.getNmsClass("IChatBaseComponent$ChatSerializer", "network.chat.",
"ChatSerializer", "Component$Serializer");
Class<?> chatBaseComponentClass = PacketUtils.getNmsClass("IChatBaseComponent", "network.chat.", "Component");
if (chatSerializerClass == null || chatBaseComponentClass == null)
return null;
try {
for (Method m : chatSerializerClass.getDeclaredMethods()) {
if (m.getParameterTypes().length > 0 && m.getParameterTypes()[0].equals(chatBaseComponentClass)
&& m.getReturnType().equals(String.class))
{
return m;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Method getJsonToBaseComponentMethod() {
Class<?> chatSerializerClass = PacketUtils.getNmsClass("IChatBaseComponent$ChatSerializer", "network.chat.",
"ChatSerializer", "Component$Serializer");
Class<?> chatBaseComponentClass = PacketUtils.getNmsClass("IChatBaseComponent", "network.chat.", "Component");
Class<?> chatMutableComponentClass = PacketUtils.getNmsClass("IChatMutableComponent", "network.chat.");
if (chatSerializerClass == null || chatBaseComponentClass == null)
return null;
try {
for (Method m : chatSerializerClass.getDeclaredMethods()) {
if (m.getParameterCount() == 0)
continue;
if (m.getParameterTypes()[0].equals(String.class) && (m.getReturnType()
.isAssignableFrom(chatBaseComponentClass)
|| (chatMutableComponentClass != null && m.getReturnType().equals(chatMutableComponentClass))))
{
m.setAccessible(true);
return m;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public void sendMessage(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
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
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.hasItem())
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(origin, item, to, 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
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 = "";
}
// 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(ChatItem.replace(action.getOrigin(), text));
if (color != null && !Colors.isFormatting(color)) // don't add reset thing
littleBuilder.color(color);
if (action.hasItem()) {
if (action.getItem().getType().equals(Material.AIR))
littleBuilder.event(
Utils.createTextHover(String.join("\n", ChatItem.getInstance().getStorage().tooltipHand)));
else
littleBuilder.event(Utils.createItemHover(action.getItem(), to));
} else {
littleBuilder.event(
Utils.createTextHover(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover")));
if (action.hasCommand())
littleBuilder.event(Utils.createRunCommand(action.getCommand()));
}
return littleBuilder.create();
}
private static final List<String> SKIPPED = Arrays.asList("HSTRY_ENCHANTS");
@Override
public String stringifyItem(ItemStack item) {
try {
ChatItem.debug("[JSONManipulator] stringifying item");
Object nmsStack = JSONManipulator.AS_NMS_COPY.invoke(null, item);
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(item.getAmount()).append("b"); // Append the amount
if (!tagMap.containsKey("Damage")) { // for new versions
sb.append(",Damage:").append(item.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(":");
}
sb.append(Utils.cleanStr(entry.getValue()));
}
sb.append("}}"); // End of tag and end of item
return sb.toString();
} catch (Exception e) {
return "{}";
}
}
}
@@ -6,6 +6,6 @@ import net.md_5.bungee.api.chat.BaseComponent;
public interface IPlayerNamer {
public BaseComponent[] getName(Player p);
public BaseComponent[] getName(Player p);
}
@@ -1,27 +1,49 @@
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.HexNicksPlayerNamer;
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) {
if(Bukkit.getPluginManager().getPlugin("HexNicks") != null) {
setPlayerNamer(new HexNicksPlayerNamer());
pl.getLogger().info("Enable support for HexNicks plugin !");
} else {
setPlayerNamer(new DefaultPlayerNamer());
}
}
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 = ChatItem.getPlatform().getPluginVersion(plugin).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());
}
}
Loaded 100 of 119 files, more files were not shown because too many files have changed in this diff. Show more