Compare commits

...
475 Commits
Author SHA1 Message Date
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
Elikill58 2d97d5fd45 Upgrade to 2.4.7 2023-05-09 18:53:00 +02:00
Elikill58 32e71bc683 Fix chatitem select 2023-05-09 18:51:59 +02:00
Elikill58 31c08cbb37 Add select of manager 2023-05-06 12:49:11 +02:00
Elikill58 084cc40f88 Fix second message 2023-05-06 11:19:43 +02:00
Elikill58 c322fb2eec Fix double item in chat 2023-05-06 10:30:05 +02:00
Elikill58 4e90d96f48 Fix v1 issue #74 2023-04-30 22:42:14 +02:00
Elikill58 828a8e3824 Add chatmanager support 2023-04-30 22:24:29 +02:00
Elikill58 7da5adf264 Update gitignore 2023-04-30 22:12:01 +02:00
Elikill58 513185de26 Fix unknow version 2023-04-10 11:25:25 +02:00
Elikill58 2f17aa897a Prevent obj can't be created 2023-04-10 11:10:18 +02:00
Elikill58 dd2359f96d Change for TAB 2023-04-10 10:54:43 +02:00
Elikill58 8799aa6fc0 Fix storage 2023-04-10 10:50:18 +02:00
Elikill58 4dfe50038b Fix failed to find lang 2023-04-10 10:46:29 +02:00
Elikill58 51c4311233 Fix for item/block and for chatitem links 2023-04-07 09:30:24 +02:00
Elikill58 72557594eb Fix for not found constructor 2023-04-07 09:24:10 +02:00
Elikill58 708e995ac7 Add items in langs 2023-04-05 22:17:24 +02:00
Elikill58 589318ea8d Re-add EcoEnchant support for v8 2023-04-05 21:55:55 +02:00
Elikill58 17e9edbd53 Add translation into inventory 2023-04-04 22:49:22 +02:00
Elikill58 f5124f749f Add complete translation system 2023-04-04 22:10:01 +02:00
Elikill58 fe10f7ca5b Change readme 2023-04-03 22:24:23 +02:00
dependabot[bot] d590b66630 Bump discordsrv from 1.26.0 to 1.26.2 (#71)
Bumps discordsrv from 1.26.0 to 1.26.2.

---
updated-dependencies:
- dependency-name: com.discordsrv:discordsrv
  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-04-03 22:13:17 +02:00
dependabot[bot] e68b843f73 Bump viaversion-api from 4.6.1 to 4.6.2 (#72)
Bumps viaversion-api from 4.6.1 to 4.6.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>
2023-04-03 22:12:56 +02:00
Elikill58 2cf594f9ed Fix PCM 2023-04-02 17:15:21 +02:00
Elikill58 1b33b42e94 Fix error 2023-04-01 14:37:12 +02:00
Elikill58 77ba7e65ce Re-add some managers 2023-04-01 14:31:42 +02:00
Elikill58 7375f970af Fix error while changing packet 2023-03-30 22:46:35 +02:00
Elikill58 870d9052a0 Fix double item 2023-03-28 19:13:33 +02:00
Elikill58 4ea4aa43bf Upgrade kyori's adventure thing 2023-03-26 15:30:45 +02:00
Elikill58 39ffa60e7a Prevent the error 2023-03-21 17:44:39 +01:00
dependabot[bot] fc1c9b0019 Bump EcoEnchants from 9.17.5 to 9.17.7 (#68)
Bumps [EcoEnchants](https://github.com/Auxilor/EcoEnchants) from 9.17.5 to 9.17.7.
- [Release notes](https://github.com/Auxilor/EcoEnchants/releases)
- [Commits](https://github.com/Auxilor/EcoEnchants/compare/9.17.5...9.17.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-20 22:35:04 +01:00
dependabot[bot] ed3ad9db85 Bump viaversion-api from 4.5.1 to 4.6.1 (#69)
Bumps viaversion-api from 4.5.1 to 4.6.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-03-20 22:34:44 +01:00
dependabot[bot] c38d68d081 Bump ChatControl-Free from master-SNAPSHOT to 5.9.5 (#70)
Bumps [ChatControl-Free](https://github.com/kangarko/ChatControl-Free) from master-SNAPSHOT to 5.9.5.
- [Release notes](https://github.com/kangarko/ChatControl-Free/releases)
- [Commits](https://github.com/kangarko/ChatControl-Free/commits/5.9.5)

---
updated-dependencies:
- dependency-name: com.github.kangarko:ChatControl-Free
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-20 22:34:33 +01:00
Elikill58 352dcb82b7 Add ChatContorl into plugin dep 2023-03-16 21:42:20 +01:00
Elikill58 7981ccaa1e Fix cooldown for v1 and chatcontrol support 2023-03-16 21:41:56 +01:00
Elikill58 e5444216ce Merge branch 'v2' of https://github.com/dadus33-plugins/ChatItem into v2 2023-03-15 23:55:02 +01:00
dependabot[bot] 207159bb17 Bump EcoEnchants from 9.17.3 to 9.17.5 (#67)
Bumps [EcoEnchants](https://github.com/Auxilor/EcoEnchants) from 9.17.3 to 9.17.5.
- [Release notes](https://github.com/Auxilor/EcoEnchants/releases)
- [Commits](https://github.com/Auxilor/EcoEnchants/compare/9.17.3...9.17.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-15 13:55:04 +01:00
dependabot[bot] 32d4d3556d Bump opennbt from 1.4 to 1.5 (#66)
Bumps [opennbt](https://github.com/Steveice10/OpenNBT) from 1.4 to 1.5.
- [Release notes](https://github.com/Steveice10/OpenNBT/releases)
- [Commits](https://github.com/Steveice10/OpenNBT/compare/1.4...1.5)

---
updated-dependencies:
- dependency-name: com.github.GeyserMC:opennbt
  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-03-15 13:54:56 +01:00
Elikill58 9102b6a11f Change default config 2023-03-10 19:00:11 +01:00
Elikill58 587d6bbb93 Fix #16 2023-03-10 18:57:19 +01:00
Elikill58 9ea5d6ffb7 Quick change for SCM 2023-03-10 18:25:14 +01:00
Elikill58 7ac7369a7f Update how bugged clients are managed 2023-03-09 21:18:36 +01:00
Elikill58 d548b68c8a Prevent error for 1.12- version 2023-03-07 21:17:52 +01:00
dependabot[bot] 92f4118015 Bump EcoEnchants from 9.17.1 to 9.17.3 (#64)
Bumps [EcoEnchants](https://github.com/Auxilor/EcoEnchants) from 9.17.1 to 9.17.3.
- [Release notes](https://github.com/Auxilor/EcoEnchants/releases)
- [Commits](https://github.com/Auxilor/EcoEnchants/compare/9.17.1...9.17.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-07 20:17:00 +01:00
Elikill58 3cae31998e Remove one logger 2023-03-07 18:10:50 +01:00
Elikill58 396b8ccc05 Possible way to remove coloring 2023-03-07 18:10:16 +01:00
Elikill58 70fece6c4f Prevent re-adding content 2023-03-07 17:42:26 +01:00
Elikill58 7ad2f1923e Fix end of message removed 2023-03-05 13:47:10 +01:00
Elikill58 f1796cee43 Add new filter 2023-03-05 10:38:27 +01:00
Elikill58 e460940fcd Fx something not filtered 2023-03-04 20:39:36 +01:00
Elikill58 26b71376b1 Upgrade to 2.4.6 2023-02-27 22:59:58 +01:00
Elikill58 9b25f2e0ae Fix control 2023-02-27 17:39:50 +01:00
dependabot[bot] cd40bc0894 Bump EcoEnchants from 9.17.0 to 9.17.1 (#63)
Bumps [EcoEnchants](https://github.com/Auxilor/EcoEnchants) from 9.17.0 to 9.17.1.
- [Release notes](https://github.com/Auxilor/EcoEnchants/releases)
- [Commits](https://github.com/Auxilor/EcoEnchants/compare/9.17.0...9.17.1)

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

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

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

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

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

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

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

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

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

* Rename config variables

* Fix searching chat id

* Remove some debug lines

* Change default config

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* re-add export_dir
2022-02-15 19:42:33 +01:00
Elikill58 95bcd6ceff Upgrade to v2.2 2022-02-14 21:20:24 +01:00
Elikill58 b596873300 Prevent too many char in color code 2022-02-08 18:37:47 +01:00
Elikill58 0425336f67 Prevent concurrent modifications 2022-02-02 12:17:56 +01:00
Elikill58 1a27bcbec2 Fix hex support with chat manager 2022-01-31 15:19:46 +01:00
Elikill58 17761fb649 Fix enchants issue with json 2022-01-31 14:37:58 +01:00
Elikill58 9b287c5f83 Add option to disable permission and change it 2022-01-31 13:54:36 +01:00
Elikill58 ce44cd7297 Fix for 1.12 only 2022-01-27 19:59:22 +01:00
Elikill58 4ee5a69a28 Edit auto manager 2022-01-26 23:43:09 +01:00
Elikill58 e7f19acc7f Prevent bell not found because of \ 2022-01-26 23:35:48 +01:00
Elikill58 9d557260ae Prevent bell not set 2022-01-26 23:20:53 +01:00
Elikill58 6bbf12182a Add some debugging message 2022-01-26 22:27:37 +01:00
Elikill58 54a582d3eb Prevent issue that show own item 2022-01-26 22:19:18 +01:00
Elikill58 0cbf4edbd1 Prevent ink sack not supported 2022-01-26 22:16:30 +01:00
Elikill58 0d4d8a7bf1 Merge branch 'v2' of https://github.com/dadus33-plugins/ChatItem into v2 2022-01-20 16:33:45 +01:00
Elikill58 332bed1bcb Fix for snapshot new ver message 2022-01-20 16:32:42 +01:00
Elikill58 ecbcbbab12 Go to snapshot 2022-01-20 15:49:23 +01:00
Elikill58 e143dd14bf Make link secret (and invalidate old one) 2022-01-20 15:42:45 +01:00
Elikill58 5234812a49 Change uploaded fild 2022-01-20 01:55:20 +01:00
Elikill58 ec770ddd15 Publish on discord 2022-01-20 01:50:23 +01:00
Elikill58 fbe0538a71 Make auto-run show artifact (#35 from averyanalex/v2)
Make auto-run show artifact
2022-01-11 21:59:02 +01:00
Alex Averyanov fb1027f4a8 Update build workflow 2022-01-11 18:37:58 +03:00
Elikill58 97e6ad4245 Add auto-upload of artifact 2022-01-11 16:11:11 +01:00
Elikill58 2ef74e9166 Upgrade to JDK 16 2022-01-11 12:54:58 +01:00
Elikill58 05ce1fb059 Upgrade to 2.1 2022-01-11 12:30:30 +01:00
Elikill58 3dcd31807f Fix #15 2022-01-11 12:15:31 +01:00
Elikill58 d026aeea41 Make v2 show tooltip for hand 2022-01-11 12:07:35 +01:00
Elikill58 5ab5ce9e95 Fix error for 1.18 2022-01-11 11:56:47 +01:00
Elikill58 cf5b5feb9c Edit action's config 2022-01-11 10:20:53 +01:00
Elikill58 d579eb8e4a Fix amount items 2022-01-11 10:12:12 +01:00
Elikill58 fec31fe4bb Fix possible reload issue 2022-01-11 10:09:13 +01:00
Elikill58 b6d25866c1 Add tab 2022-01-11 09:59:24 +01:00
Elikill58 58fe4a2aeb Add item in inventory 2022-01-11 09:56:33 +01:00
Elikill58 37e9359b1f Introduce message system 2022-01-10 16:52:53 +01:00
Elikill58 78adf1c9d0 Create inventory 2022-01-10 15:54:17 +01:00
Elikill58 19ad0c362c Introduce /chatitem command 2022-01-10 15:45:38 +01:00
Elikill58 3785534b0e Re-add warn message 2022-01-10 15:11:51 +01:00
Elikill58 8e8fa85ec3 Fix some plugin compatibility with 1.18 2022-01-10 14:52:16 +01:00
Elikill58 ad340f239e Make changes for 1.16+ 2022-01-09 23:17:21 +01:00
Elikill58 3e53c370ec Remove unused code 2022-01-09 21:56:36 +01:00
Elikill58 dff6d30e78 Fix 1.18 support 2022-01-09 21:03:15 +01:00
Elikill58 275a7bb773 Fix error while reloading with packets 2022-01-08 22:43:20 +01:00
Elikill58 26ec7ec819 Allow reload for manager and begin of 'both' manager 2022-01-08 22:28:02 +01:00
Elikill58 592981a678 Fix error with bungee serializer 2022-01-08 21:37:52 +01:00
Elikill58 fbe286ded5 Update chat v2 2022-01-08 19:12:46 +01:00
Elikill58 7780e8a406 Prevent translated item without space 2022-01-08 19:05:25 +01:00
Elikill58 b70bc7ee51 Remove unecessary mvn config 2022-01-08 18:53:37 +01:00
Elikill58 57baf6675a Use HexNicks for chat manager 2022-01-08 18:51:41 +01:00
Elikill58 8998498383 Make possible to change for API 2022-01-08 18:38:01 +01:00
Elikill58 94a7c549d7 add PlayerNamer 2022-01-08 18:37:25 +01:00
Elikill58 988b0e8080 Add HexNicks to dep 2022-01-08 18:06:53 +01:00
Elikill58 22e51bf668 Merge branch 'v2' of https://github.com/dadus33-plugins/ChatItem into v2 2021-12-31 13:10:06 +01:00
Elikill58 1f70b0048e Fix https repo 2021-12-30 11:13:49 +01:00
Elikill58 e18ef8a927 Fix chat spam 2021-12-30 08:31:08 +01:00
Elikill58 86078e7869 Add config for maven 2021-12-27 14:59:32 +01:00
Elikill58 212bf7174e Merge branch 'v2' of https://github.com/dadus33-plugins/ChatItem into v2 2021-12-27 14:39:16 +01:00
Elikill58 284396ea28 Use own repo 2021-12-27 14:39:07 +01:00
Elikill58 0bd697cbd4 Add workflow 2021-12-27 14:04:34 +01:00
Elikill58 72be8e243e Update starting messages 2021-12-27 14:00:45 +01:00
Elikill58 445fb84a40 Fix own packet system 2021-12-27 13:54:41 +01:00
Elikill58 1ebf5b4edb Add soft depend 2021-12-27 13:47:52 +01:00
Elikill58 8869bc88d1 Rename chat packet validator 2021-12-27 13:18:25 +01:00
Elikill58 aae9708647 Make protocol version general 2021-12-27 11:56:46 +01:00
Elikill58 e9736c4031 Rename packet listener 2021-12-26 23:56:17 +01:00
Elikill58 28199b5e0b Fix limit 2021-12-26 23:54:14 +01:00
Elikill58 fe743d8302 Add chat event for v1 2021-12-26 23:52:03 +01:00
Elikill58 2f08ea9509 Fix log 2021-12-26 23:30:44 +01:00
Elikill58 854dcca6ee Update config keys 2021-12-26 23:25:17 +01:00
Elikill58 9072db7c1b Add auto mode 2021-12-26 23:19:06 +01:00
Elikill58 2b0ca413b4 Add both manager 2021-12-26 23:11:50 +01:00
Elikill58 0f1ce81a31 Update dependencies 2021-12-26 20:31:12 +01:00
Elikill58 1b714f25b8 Upgrading to v13 for config 2021-12-26 20:20:29 +01:00
Elikill58 c03b8b4810 Remove some useless comments 2021-12-26 20:15:29 +01:00
Elikill58 5f0744dd0e Use recipients 2021-12-26 20:11:49 +01:00
Elikill58 fe1676620f Fix multiple message type 2021-11-25 17:06:39 +01:00
Elikill58 ec5b2fe509 Fix event not working 2021-11-25 16:12:49 +01:00
Elikill58 3efe63bb49 Add default values for config 2021-11-25 15:30:36 +01:00
Elikill58 48a1dfbc26 Fix messages not well parsed 2021-11-25 15:17:43 +01:00
Elikill58 0a604cf83d Upgrade to 2.0 2021-11-24 19:56:18 +01:00
Elikill58 4bc657ab63 Don't include LangUtils's code 2021-11-24 19:55:44 +01:00
Elikill58 165e8f4474 Clean dependencies 2021-11-24 19:54:23 +01:00
Elikill58 a4ca8611f4 Remove unused code 2021-11-24 19:46:58 +01:00
Elikill58 0f354e2dd9 Fix class not found for 1.17 2021-11-24 19:43:25 +01:00
Elikill58 c9bd62dc47 Add LanguageUtils support #27 2021-11-24 19:25:18 +01:00
Elikill58 f8304aeb28 Add namer feature 2021-11-24 18:48:37 +01:00
Elikill58 1fdf1312a0 Remove unused class event 2021-11-24 15:56:12 +01:00
Elikill58 295a7c406c Merge pull request #28 from dadus33-plugins/v2-without-packet
Removing all packet system and fix for thermos
2021-11-24 15:54:03 +01:00
Elikill58 78fbeed7d2 Fix for all versions 2021-11-24 15:52:14 +01:00
Elikill58 446127f7bb Fix for thermos 2021-11-23 18:59:41 +01:00
Elikill58 9dd172447c Clean code 2021-11-23 18:22:17 +01:00
Elikill58 38cb530993 Fix possible issue with 1.17 2021-11-20 23:11:14 +01:00
Elikill58 6bfd45727f Prevent cancellation when not using ChatItem 2021-11-09 18:03:29 +01:00
Elikill58 9f69f078fc Use hand disabled and amount management from config 2021-11-09 15:00:52 +01:00
Elikill58 2050c6c044 Make config reloadable 2021-11-09 00:16:04 +01:00
Elikill58 26d57460d5 Use new system 2021-11-08 22:33:33 +01:00
Elikill58 a36c8ef09b Prevent multiple sent 2021-11-08 19:57:56 +01:00
Elikill58 45ee278b61 Prevent issue when don't have 1.8 2021-10-29 15:36:10 +02:00
Elikill58 0470810eb8 Prevent NPE 2021-10-07 19:56:35 +02:00
Elikill58 2c01b03982 Prefer use v2 listeners 2021-10-07 14:08:35 +02:00
Elikill58 f285a7ceee Fix #22 2021-10-07 14:06:44 +02:00
Elikill58 b25e229e17 Begin of 1.17 support 2021-10-06 23:38:37 +02:00
Elikill58 e8869dfcdf Edit default config and upgrade to 1.4. 2021-10-06 22:20:11 +02:00
Elikill58 b9cc5ad202 Upgrade log4j and maven-shade-plugin to prevent security isssue 2021-10-05 17:52:43 +02:00
Elikill58 4c9efd5d39 Merge branch 'master' of https://github.com/dadus33-plugins/ChatItem 2021-10-05 17:03:46 +02:00
Elikill58 b75325998d Remove unused code 2021-10-05 16:52:13 +02:00
Elikill58 c23de3969c End of ProtocolLib dependency ! (Which fix #18) 2021-10-05 16:45:29 +02:00
Elikill58 f1c9511c50 Use PL when there isn't ViaVersion or PS 2021-10-05 13:27:53 +02:00
Elikill58 bd2b4df822 Update version support 2021-10-05 13:06:10 +02:00
dadus33 f33e0c8ad4 Merge pull request #21 from Elikill58/master
Fix compilation, ProtocolLib support and other quick issues
2021-09-28 14:56:48 +03:00
Elikill58 eeb1e40c11 Fix https://github.com/dadus33/ChatItem/issues/20 2021-09-26 14:54:06 +02:00
Elikill58 7c84b3a85e Fix https://github.com/dadus33/ChatItem/issues/19 2021-09-26 14:45:54 +02:00
Elikill58 146fc3abe5 Remove few warnings 2021-09-25 23:34:27 +02:00
Elikill58 e9aa99ad82 Remove projects files 2021-09-25 23:27:42 +02:00
Elikill58 89d6a60235 Fix dependencies 2021-09-25 23:19:28 +02:00
dadus33 d69c0e02f3 Add proper spacing in authors array 2019-03-06 11:07:44 +02:00
dadus33 7f337c0f49 Merge pull request #11 from WOLFI3654/master
1.13 Update
2019-03-06 11:06:12 +02:00
Thomas Windt a403b35602 Merge branch '1.13' of github.com:WOLFI3654/ChatItem into 1.13 2019-02-13 20:15:27 +01:00
Thomas Windt 0cdb2eccda Add 1.13 protocols
Signed-off-by: Thomas Windt <thomas@architekt-windt.de>
2019-02-13 20:14:36 +01:00
Thomas Windt a5cfb6216a Update version 2019-02-13 20:01:29 +01:00
Thomas Windt a219e7c61e Dirty 1.13 port
Signed-off-by: Thomas Windt <thomas@architekt-windt.de>
2019-02-13 19:56:29 +01:00
dadus33 f932d56bf1 Fix color-if-already-colored config option bug 2018-01-06 18:56:21 +02:00
dadus33 d925b2d922 Update to 1.12.X (accepts any protocol number higher than the one for 1.12).
Implement minor performance improvements.
Fix permission and JSON styling related issues.
Add config setting for 'normal' and 'command' no permission message.
2018-01-01 19:52:12 +02:00
dadus33 4b4de6426c Fix support for situations when the server version is greater than the client version. 2017-09-15 19:46:07 +03:00
dadus33 0e75d355c6 Remove app.deveo.com support. 2017-08-26 12:51:59 +03:00
dadus33 523d13f9c5 Add API and Maven repository, update to Java 8, fix numerous bugs and add support for 1.12.1 2017-08-26 12:47:55 +03:00
dadus33 cd6b79d946 First commit of dev branch. 2017-07-25 23:47:55 +03:00
dadus33 5ecbffacbd Add 1.12 to the ProtocolVersion enum. Rewrite the remapping system. Use client version instead of server version when deciding on the NBTTagList format. 2017-06-25 21:26:52 +03:00
dadus33 2c84f0c60e Remove deubg messages. 2017-06-24 15:29:42 +03:00
dadus33 9a77c68685 Ignore null addresses in the HandShakeListener (player couldn't join the server for some reason or was kicked in the meantime) 2017-06-24 00:21:16 +03:00
dadus33 a597d86710 Only use the proper user (the one which is != null) 2017-06-18 22:25:23 +03:00
dadus33 8f3ed60b8c Properly load client addresses on servers connected to bungee by loading the address from an updated player (instead of temporary player) 2017-06-18 01:13:57 +03:00
dadus33 37e08ffb40 Add discord badge 2017-06-12 23:49:49 +03:00
dadus33 e400de8cc4 Remove ProtocolSupport as maven dependency (required manually installed file to local repo) and use reflection instead.
Fix OpenNBT imports.
2017-06-12 23:17:12 +03:00
dadus33 bfd78444e3 Use proper details for OpenNBT (change from spacehq repo) 2017-06-12 22:34:43 +03:00
dadus33 ed1934be36 Add 1.12 support. 2017-06-12 22:27:46 +03:00
dadus33 99a980476b Properly handle messages sent by different client versions. Update version to 1.3.5 2017-02-23 18:30:26 +02:00
dadus33 f581ccad1c Update version to 1.3.4. Remove "debug" from config.yml 2017-02-13 20:09:29 +02:00
dadus33 2c29af8a6a Use new method to replace NMS NBTTagCompound#toString(). Add a caching system for sent items. 2017-02-13 20:08:19 +02:00
dadus33 306cae8bcb Add alternative method (better than the default NMS one) to stringify items and NBTTagCompounds. 2017-02-12 20:53:57 +02:00
dadus33 781d0b3a70 Remove debug mode. 2017-02-12 18:22:04 +02:00
dadus33 355ff63318 Fix Translator class. 2017-01-24 00:25:01 +02:00
dadus33 243e117538 Properly use asynchronous tasks. Allow lists of strings in empty hand tooltips. 2017-01-23 13:11:00 +02:00
dadus33 f1a1f795d2 Add debug mode. 2017-01-13 22:49:32 +02:00
dadus33 bcb092f29f Fix bugs in the previous version. Add support for empty hand messages. 2017-01-08 21:42:01 +02:00
dadus33 4500161341 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	src/main/java/me/dadus33/chatitem/listeners/ChatPacketValidator.java
2017-01-08 20:00:44 +02:00
dadus33 79e1cd3951 Fix issues with order of simultaneous messages. 2017-01-08 20:00:15 +02:00
dadus33 77c8abf457 Fix issues with order of simultaneous messages. 2017-01-08 19:59:32 +02:00
dadus33 847b6ddc92 Add fltering for Shulker Boxes. 2017-01-08 14:30:13 +02:00
dadus33 d234858ec5 Fix permissions. Add cooldown placeholder. Reformat config. 2016-12-27 20:25:58 +02:00
dadus33 e7a3cf69fd Fix the integration with plugins that use Spigot's ChatComponent API. 2016-12-22 10:09:06 +02:00
dadus33 ee41588a91 Fix the "Invalid Item!" issue. 2016-12-17 15:33:17 +02:00
dadus33 1b160bdd28 Fix handling of empty arrays in JSON messages, fixing integration with some plugins like VentureChat. 2016-12-08 14:29:26 +02:00
dadus33 c33fe83030 Add cooldown system and new default config with translations. 2016-12-07 19:35:58 +02:00
dadus33 eaeba41c53 Fix null message handling in the Log4J filter and update it to match new separator system. 2016-12-04 13:35:53 +02:00
dadus33 34905cbfeb Revert travis changes. 2016-11-29 23:28:06 +02:00
dadus33 78e8b7f8a7 Add .travis.yml to .gitignore 2016-11-29 23:17:38 +02:00
224 changed files with 9133 additions and 1255 deletions

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "maven"
directory: "/"
schedule:
interval: "weekly"
+30
View File
@@ -0,0 +1,30 @@
name: Build v2 for PR
on:
pull_request:
branches: [ v2 ]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
name: Checkout repo
- name: Set up JDK 17 (LTS)
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
cache: maven
- name: Build with Maven
run: mvn install --file pom.xml
- uses: actions/upload-artifact@v3
name: Upload Artifact
with:
name: ChatItem.jar
path: target/ChatItem-*.jar
+36
View File
@@ -0,0 +1,36 @@
name: Build v2
on:
push:
branches: [ v2 ]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
name: Checkout repo
- name: Set up JDK 17 (LTS)
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
cache: maven
- name: Build with Maven
run: mvn install --file pom.xml
- uses: actions/upload-artifact@v3
name: Upload Artifact
with:
name: ChatItem.jar
path: target/ChatItem-*.jar
- name: Send file README.md to discord channel
uses: sinshutu/upload-to-discord@master
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
with:
args: target/ChatItem-*.jar
+6
View File
@@ -1,5 +1,11 @@
.idea/
src/test/
bin/
target/
*.iml
dependency-reduced-pom.xml
.classpath
.project
.settings/
/.apt_generated/
/.apt_generated_tests/
-1
View File
@@ -1 +0,0 @@
language: java
+25 -1
View File
@@ -1,5 +1,29 @@
# ChatItem [![Build Status](https://travis-ci.org/dadus33/ChatItem.svg?branch=master)](https://travis-ci.org/dadus33/ChatItem)
# ChatItem
The official repository of the ChatItem Spigot/Bukkit plugin.
You can:
- [Download latest dev build](https://nightly.link/dadus33-plugins/ChatItem/workflows/build/v2/ChatItem.jar.zip)
- [ ![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
You can try to do `/chatitem admin` then select different paper item. It will change how the plugin try to add item in chat.
**If you already have issue, please do**:
1) Do `/chatitem admin` then select on "Debug" item at top right
2) Try to use ChatItem in chat
3) Come on discord [here](https://discord.gg/yng5PPf62h) or in private message: `Elikill58#0743`
4) Send the **full file `logs/latest.log`**
PS: Yes you can disable the debug behavior after.
# Building
Building this is simple as we use Maven.
To build it, simply clone this repository and then run `mvn clean install`.
You can add the parameter `export_dir` to set the URL where the JAR will be exported.
+162 -49
View File
@@ -6,106 +6,192 @@
<groupId>me.dadus33</groupId>
<artifactId>ChatItem</artifactId>
<version>1.2.5</version>
<version>2.5.1</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
<id>Bungeecord</id>
<url>https://repo.md-5.net/content/groups/public/</url>
</repository>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>dmulloy2-repo</id>
<url>http://repo.dmulloy2.net/content/groups/public/</url>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
<repository>
<id>Plugin Metrics</id>
<url>http://repo.mcstats.org/content/repositories/public</url>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<repository>
<id>lang-utils-repo</id>
<url>https://raw.github.com/MascusJeoraly/LanguageUtils/mvn-repo/</url>
</repository>
<repository>
<id>protocollib-repo</id>
<url>https://repo.dmulloy2.net/nexus/repository/public/</url>
</repository>
<repository>
<id>viaversion-repo</id>
<url>https://repo.viaversion.com</url>
</repository>
<repository>
<id>elikill-repo</id>
<url>https://repo.eliapp.fr:8081/repository/internal/</url>
</repository>
<repository>
<id>dv8tion</id>
<url>https://m2.dv8tion.net/releases</url>
</repository>
<repository>
<id>Scarsz-Nexus</id>
<url>https://nexus.scarsz.me/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.10-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.10-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>3.6.5</version>
<version>1.17-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>minecraft-server</artifactId>
<version>1.7.10</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.7</version>
<version>2.9.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.meowj</groupId>
<artifactId>LangUtils</artifactId>
<version>1.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>5.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.viaversion</groupId>
<artifactId>viaversion-api</artifactId>
<version>4.9.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.shevchik</groupId>
<artifactId>ProtocolSupport</artifactId>
<version>1.18.2-1-dev</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.58.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.GeyserMC</groupId>
<artifactId>opennbt</artifactId>
<version>1.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.mcstats.bukkit</groupId>
<artifactId>metrics-lite</artifactId>
<version>R8-SNAPSHOT</version>
<scope>compile</scope>
<groupId>dev.majek</groupId>
<artifactId>HexNicks</artifactId>
<version>2.2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.0</version>
<groupId>com.github.MajekDev</groupId>
<artifactId>HexNicks</artifactId>
<version>3.1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.0</version>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.14.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bukkit</artifactId>
<version>4.3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.discordsrv</groupId>
<artifactId>discordsrv</artifactId>
<version>1.26.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.willfp</groupId>
<artifactId>EcoEnchants</artifactId>
<version>8.57.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.Auxilor</groupId>
<artifactId>EcoEnchants</artifactId>
<version>12.2.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.ryderbelserion</groupId>
<artifactId>ChatManager</artifactId>
<version>3.7.7</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.willfp</groupId>
<artifactId>eco</artifactId>
<version>6.66.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>ChatItem-${project.version}</finalName>
<directory>./target</directory>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>plugin.yml</include>
<include>config.yml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<version>3.10.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<outputDirectory>${dir}</outputDirectory>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
@@ -113,17 +199,44 @@
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<relocations>
<relocation>
<pattern>com.google.gson</pattern>
<shadedPattern>me.dadus33.gson</shadedPattern>
<shadedPattern>me.dadus33.libs.gson</shadedPattern>
</relocation>
<relocation>
<pattern>com.github.steveice10.opennbt</pattern>
<shadedPattern>me.dadus33.libs.opennbt</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*</artifact>
<excludes>
<exclude>net.kyori:examination-api:**</exclude>
<exclude>net.kyori:examination-string:**</exclude>
<exclude>net.kyori:adventure-platform-api:**</exclude>
<exclude>net.kyori:adventure-text-serializer-legacy:**</exclude>
<exclude>net.kyori:adventure-text-serializer-gson:**</exclude>
<exclude>net.kyori:adventure-platform-facet:**</exclude>
<exclude>net.kyori:adventure-nbt:**</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<outputDirectory>${export_dir}</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>
</project>
+210 -98
View File
@@ -1,117 +1,229 @@
package me.dadus33.chatitem;
import com.comphenix.protocol.AsynchronousManager;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.async.AsyncListenerHandler;
import com.comphenix.protocol.events.ListenerPriority;
import me.dadus33.chatitem.commands.CIReload;
import me.dadus33.chatitem.filters.Log4jFilter;
import me.dadus33.chatitem.json.JSONManipulator;
import me.dadus33.chatitem.json.JSONManipulatorCurrent;
import me.dadus33.chatitem.listeners.ChatEventListener;
import me.dadus33.chatitem.listeners.ChatPacketListener;
import me.dadus33.chatitem.utils.General;
import me.dadus33.chatitem.utils.Storage;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Server;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
import org.mcstats.MetricsLite;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.concurrent.CompletableFuture;
import java.io.IOException;
import java.util.logging.Level;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabCompleter;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import com.google.common.base.Strings;
import me.dadus33.chatitem.chatmanager.ChatEventListener;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.chatmanager.v2.ChatListenerChatManager;
import me.dadus33.chatitem.commands.CIReloadCommand;
import me.dadus33.chatitem.commands.ChatItemCommand;
import me.dadus33.chatitem.hook.ChatControlSupport;
import me.dadus33.chatitem.hook.ChatManagerSupport;
import me.dadus33.chatitem.hook.ecoenchants.EcoEnchantsSupport;
import me.dadus33.chatitem.invsee.InvShower;
import me.dadus33.chatitem.itemnamer.NamerManager;
import me.dadus33.chatitem.listeners.InventoryListener;
import me.dadus33.chatitem.listeners.JoinListener;
import me.dadus33.chatitem.listeners.TranslationInventoryListener;
import me.dadus33.chatitem.playernamer.PlayerNamerManager;
import me.dadus33.chatitem.utils.ReflectionUtils;
import me.dadus33.chatitem.utils.SemVer;
import me.dadus33.chatitem.utils.Utils;
import me.dadus33.chatitem.utils.Version;
public class ChatItem extends JavaPlugin {
public final static int CFG_VER = 6;
private static ChatItem instance;
private ChatEventListener chatEventListener;
private Log4jFilter filter;
private Storage storage;
private ProtocolManager pm;
private ChatPacketListener listener;
private static JSONManipulator manip;
public static boolean post17 = false;
public final static int CFG_VER = 13;
public static boolean discordSrvSupport = false, hasNewVersion = false;
private static ChatItem instance;
private final String brandChannelName = Version.getVersion().isNewerOrEquals(Version.V1_13) ? "minecraft:brand" : "MC|Brand";
private final List<ChatManager> chatManager = new ArrayList<>();
private Storage storage;
public static void reload(CommandSender sender) {
ChatItem obj = getInstance();
obj.pm = ProtocolLibrary.getProtocolManager();
obj.saveDefaultConfig();
obj.reloadConfig();
obj.storage = new Storage(obj.getConfig());
General.init(obj.storage);
General.checkConfigVersion();
obj.listener.setStorage(obj.storage);
obj.chatEventListener.setStorage(obj.storage);
obj.filter.setStorage(obj.storage);
if (!obj.storage.RELOAD_MESSAGE.isEmpty())
sender.sendMessage(obj.storage.RELOAD_MESSAGE);
}
public static void reload(CommandSender sender) {
ChatItem pl = getInstance();
if (pl.getConfig().getKeys(false).isEmpty())
pl.saveDefaultConfig();
pl.reloadConfig();
String oldChatManager = pl.storage.manager;
pl.storage = new Storage(pl.getConfig());
pl.chooseManagers();
Translation.load(pl);
InvShower.getInvShower().clear();
if(sender != null) {
if (!pl.storage.messageReload.isEmpty())
sender.sendMessage(pl.storage.messageReload);
if (!oldChatManager.equalsIgnoreCase(pl.storage.manager))
sender.sendMessage(ChatColor.GOLD + "Changing the manager with command reloading CAN produce issue. It's mostly suggested to restart after finding the better manager for you.");
}
}
public static ChatItem getInstance() {
return instance;
}
public static ChatItem getInstance() {
return instance;
}
public void onEnable() {
instance = this;
pm = ProtocolLibrary.getProtocolManager();
saveDefaultConfig();
storage = new Storage(getConfig());
General.init(storage);
General.checkConfigVersion();
listener = new ChatPacketListener(this, ListenerPriority.HIGHEST, storage, PacketType.Play.Server.CHAT);
AsynchronousManager am = pm.getAsynchronousManager();
AsyncListenerHandler packetListenerAsyncThread = am.registerAsyncHandler(listener);
packetListenerAsyncThread.start();
CIReload rld = new CIReload();
Bukkit.getPluginCommand("cireload").setExecutor(rld);
chatEventListener = new ChatEventListener(storage);
Bukkit.getPluginManager().registerEvents(chatEventListener, this);
if(isMc18OrLater()) {
post17 = true;
}
manip = new JSONManipulatorCurrent();
public static void debug(String msg) {
if (getInstance().getStorage().debug)
getInstance().getLogger().info("[Debug] " + msg.replace(ChatManager.SEPARATOR, 'S').replace(ChatManager.SEPARATOR_END, 'E'));
}
public static boolean hasDebug() {
return getInstance().getStorage().debug;
}
try {
MetricsLite metrics = new MetricsLite(this);
metrics.start();
} catch (IOException e) {
getLogger().log(Level.WARNING, ChatColor.RED + "Couldn't start metrics!");
}
filter = new Log4jFilter(storage);
}
private void chooseManagers() {
this.chatManager.forEach((cm) -> cm.unload(this));
this.chatManager.clear();
PluginManager pm = getServer().getPluginManager();
String managerName = getStorage().manager;
switch (managerName.toLowerCase(Locale.ROOT)) {
case "both":
this.chatManager.add(new PacketEditingChatManager(this));
this.chatManager.add(new ChatListenerChatManager(this));
getLogger().info("Manager automatically chosen: " + getVisualChatManagers());
break;
case "auto":
if (getPluginThatRequirePacket().stream().map(pm::getPlugin).anyMatch(Objects::nonNull) && Version.getVersion().isNewerThan(Version.V1_7))
this.chatManager.add(new PacketEditingChatManager(this));
else
this.chatManager.add(new ChatListenerChatManager(this));
getLogger().info("Manager automatically chosen: " + getVisualChatManagers());
break;
case "packet":
this.chatManager.add(new PacketEditingChatManager(this));
getLogger().info("Manager chosen: " + getVisualChatManagers());
break;
case "chat":
this.chatManager.add(new ChatListenerChatManager(this));
getLogger().info("Manager chosen: " + getVisualChatManagers());
break;
default:
getLogger().severe("----- WARN -----");
getLogger().severe("Failed to find manager: " + managerName + ".");
getLogger().severe("Please reset your config and/or check wiki for more information");
getLogger().severe("Using default manager: chat.");
getLogger().severe("----- WARN -----");
this.chatManager.add(new ChatListenerChatManager(this));
break;
}
public void onDisable() {
instance = null;
post17 = false;
}
this.chatManager.forEach((cm) -> cm.load(this, getStorage()));
private boolean isMc18OrLater(){
switch(getVersion(Bukkit.getServer())){
case "v1_8_R1": return true;
case "v1_8_R2": return true;
case "v1_8_R3": return true;
case "v1_9_R1": return true;
case "v1_9_R2": return true;
case "v1_10_R1": return true;
case "v1_10_R2": return true;
default: return false;
}
}
NamerManager.load(this);
PlayerNamerManager.load(this);
}
private List<String> getPluginThatRequirePacket() {
return Arrays.asList("DeluxeChat", "HexNicks", "VentureChat", "ItemsAdder");
}
private static String getVersion(Server server) {
final String packageName = server.getClass().getPackage().getName();
@Override
public void onEnable() {
// Save the instance (we're basically a singleton)
instance = this;
getLogger().info("Detected server version: " + Version.getVersion().name().toLowerCase());
return packageName.substring(packageName.lastIndexOf('.') + 1);
}
// Load config
if (!new File(getDataFolder(), "config.yml").exists()) {
getLogger().info("--------------");
getLogger().info("");
getLogger().info("Welcome on ChatItem !");
getLogger().info("If you need help for setup, USE: /chatitem select");
getLogger().info("Then follow steps.");
getLogger().info("");
getLogger().info("--------------");
saveDefaultConfig();
}
storage = new Storage(getConfig());
// Commands
loadCommand(getCommand("cireload"), new CIReloadCommand());
loadCommand(getCommand("chatitem"), new ChatItemCommand());
public static JSONManipulator getManipulator(){
return manip;
}
// events
PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new JoinListener(), this);
pm.registerEvents(new InventoryListener(), this);
pm.registerEvents(new TranslationInventoryListener(), this);
pm.registerEvents(new ChatEventListener(), this);
chooseManagers();
StringJoiner plugins = new StringJoiner(", ");
if (pm.isPluginEnabled("DiscordSRV")) {
discordSrvSupport = true;
plugins.add("DiscordSRV");
}
if (pm.isPluginEnabled("ChatControl") && ReflectionUtils.isClassExist("org.mineacademy.chatcontrol.settings.Settings")) {
ChatControlSupport.init(this);
plugins.add("ChatControl");
}
if (pm.isPluginEnabled("ChatManager") && ReflectionUtils.isClassExist("me.h1dd3nxn1nja.chatmanager.Main")) {
ChatManagerSupport.init(this);
plugins.add("ChatManager");
}
if (pm.isPluginEnabled("EcoEnchants") && EcoEnchantsSupport.load()) {
plugins.add("EcoEnchants");
}
if (plugins.length() > 0)
getLogger().info("Load " + plugins.toString() + " support.");
Translation.load(this);
getServer().getMessenger().registerIncomingPluginChannel(this, brandChannelName, (chan, p, msg) -> ItemPlayer.getPlayer(p).setClientName(new String(msg).substring(1)));
if (storage.checkUpdate) {
CompletableFuture.runAsync(() -> {
String urlName = "https://api.spigotmc.org/legacy/update.php?resource=19064";
String content = Utils.getFromURL(urlName);
if (Strings.isNullOrEmpty(content))
return;
SemVer currentVersion = SemVer.parse(getDescription().getVersion());
if (currentVersion == null)
return;
SemVer latestVersion = SemVer.parse(content);
if (latestVersion != null && latestVersion.isNewerThan(currentVersion)) {
hasNewVersion = !content.equalsIgnoreCase(getDescription().getVersion());
if (hasNewVersion)
getLogger().info(storage.updateMessage);
}
});
}
}
public void loadCommand(PluginCommand cmd, Object obj) {
if (obj instanceof CommandExecutor)
cmd.setExecutor((CommandExecutor) obj);
if (obj instanceof TabCompleter)
cmd.setTabCompleter((TabCompleter) obj);
}
public Storage getStorage() {
return storage;
}
public List<ChatManager> getChatManager() {
return chatManager;
}
public String getVisualChatManagers() {
StringJoiner sj = new StringJoiner(", ");
for (ChatManager cm : chatManager) {
sj.add(cm.getName() + " (" + cm.getId() + ")");
}
return sj.toString();
}
public boolean isHasNewVersion() {
return hasNewVersion;
}
}
@@ -0,0 +1,83 @@
package me.dadus33.chatitem;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.playerversion.PlayerVersionManager;
import me.dadus33.chatitem.utils.Version;
public class ItemPlayer {
private static final ConcurrentHashMap<UUID, ItemPlayer> PLAYERS = new ConcurrentHashMap<>();
public static ItemPlayer getPlayer(Player p) {
return PLAYERS.computeIfAbsent(p.getUniqueId(), ItemPlayer::new);
}
public static ItemPlayer getPlayer(UUID uuid) {
return PLAYERS.computeIfAbsent(uuid, ItemPlayer::new);
}
private final UUID uuid;
private int protocolVersion = 0;
private Version version = null;
private String clientName = "unknow";
public ItemPlayer(UUID uuid) {
this.uuid = uuid;
Player p = Bukkit.getPlayer(uuid);
if(p != null)
setVersion(PlayerVersionManager.getPlayerVersionAdapter().getPlayerVersion(p));
}
public UUID getUUID() {
return uuid;
}
public Player getPlayer() {
return Bukkit.getPlayer(uuid);
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public int getProtocolVersion() {
if(protocolVersion == 0)
setProtocolVersion(PlayerVersionManager.getPlayerVersionAdapter().getProtocolVersion(getPlayer()));
return protocolVersion;
}
public void setProtocolVersion(int protocolVersion) {
this.protocolVersion = protocolVersion;
if(version == Version.getVersion()) {// if is default
version = Version.getVersion(protocolVersion);
ChatItem.debug("Detected version " + version.name() + " (protocol: " + protocolVersion + ")");
}
}
public Version getVersion() {
if(version == null)
setVersion(PlayerVersionManager.getPlayerVersionAdapter().getPlayerVersion(getPlayer()));
return version;
}
public void setVersion(Version version) {
this.version = version;
if(protocolVersion == 0)
this.protocolVersion = version.MAX_VER;
}
public boolean isBuggedClient() {
return (getVersion().equals(Version.V1_7) && getClientName().toLowerCase().contains("lunarclient")) || (!getVersion().isNewerOrEquals(Version.V1_15) && Version.getVersion().isNewerOrEquals(Version.V1_16));
}
@Override
public String toString() {
return "ItemPlayer[uuid=" + uuid + ",name=" + (getPlayer() != null ? getPlayer().getName() : "-") + ",version=" + version.name() + ",protocol=" + protocolVersion + ",client=" + clientName + "]";
}
}
@@ -0,0 +1,69 @@
package me.dadus33.chatitem;
import java.util.List;
import me.dadus33.chatitem.chatmanager.ChatManager;
public enum ItemSlot {
HAND(true, "", false),
HELMET(false, "helmet", false),
CHESTPLATE(false, "chestplate", false),
LEGGINGS(false, "leggings", false),
BOOTS(false, "boots", false),
INVENTORY(false, "inventory", true),
ENDERCHEST(false, "enderchest", true);
private final boolean basic, command;
private final String key;
private ItemSlot(boolean basic, String key, boolean command) {
this.basic = basic;
this.command = command;
this.key = key;
}
public boolean isBasic() {
return basic;
}
public boolean isCommand() {
return command;
}
public List<String> getPlaceholders() {
return ChatItem.getInstance().getConfig().getStringList(basic ? "general.placeholders" : "general.other-placeholders." + key + ".keys");
}
public boolean isEnabled() {
return basic || ChatItem.getInstance().getConfig().getBoolean("general.other-placeholders." + key + ".enabled", true);
}
public boolean isDenyIfNoItem() {
return ChatItem.getInstance().getConfig().getBoolean("general" + (basic ? "" : ".other-placeholders." + key) + ".deny-if-no-item", true);
}
public boolean hasPlaceholders(String message) {
for (String rep : getPlaceholders()) {
if (message.contains(rep)) {
return true;
}
}
return false;
}
public String replacePlaceholdersToSeparator(String message) {
for(String rep : getPlaceholders())
message = message.replace(rep, Character.toString(ChatManager.SEPARATOR));
return message;
}
public static ItemSlot getItemSlotFromMessage(String message) {
for(ItemSlot slot : ItemSlot.values()) {
if(slot.isEnabled() && slot.hasPlaceholders(message)) {
return slot;
}
}
return null;
}
}
@@ -0,0 +1,88 @@
package me.dadus33.chatitem;
import java.util.List;
import java.util.stream.Collectors;
import org.bukkit.ChatColor;
import org.bukkit.configuration.file.FileConfiguration;
public class Storage {
public String handName, nameFormat, amountFormat, commandFormat, manager, permissionName, buggedClientAction, language;
public final String messageNoPermission, messageDeny, messageReload, messageCooldown, messageLimit, messageIgnoredItem;
public final String SECONDS, minutes, hours;
public final String updateMessage, updateHover;
public final List<String> tooltipHand, tooltipBuggedClient, ignoredItems;
public boolean colorIfColored, addAmountForced, letMessageThrough, debug, handDisabled, showNoPermissionMessage, checkUpdate, permissionEnabled, cmdBroadcast, cmdShow, discordSrvSendMsg;
public int configVersion, limit, cooldown;
private FileConfiguration conf;
public Storage(FileConfiguration cnf) {
this.conf = cnf;
configVersion = conf.getInt("config-version", 13);
checkConfigVersion();
this.manager = conf.getString("manager", "auto");
language = conf.getString("general.language", "en_gb");
debug = conf.getBoolean("debug", false);
nameFormat = color(conf.getString("general.name-format", "&b&l&o{name} {amount}&r"));
amountFormat = color(conf.getString("general.amount-format", "x{times}"));
commandFormat = color(conf.getString("general.command-format", "&6%name%'s item is %item%"));
colorIfColored = conf.getBoolean("general.color-if-already-colored", true);
letMessageThrough = conf.getBoolean("general.let-message-through", true);
addAmountForced = conf.getBoolean("general.force-add-amount", true);
limit = conf.getInt("general.limit", 8);
cooldown = conf.getInt("general.cooldown", 60);
showNoPermissionMessage = conf.getBoolean("general.show-no-permission-message.normal", true);
permissionEnabled = conf.getBoolean("general.permission.enabled", false);
permissionName = conf.getString("general.permission.name", "chatitem.use");
handDisabled = conf.getBoolean("general.hand.disabled", false);
handName = color(conf.getString("general.hand.name", "&b&l&o{display-name}&b&l&o's hand"));
tooltipHand = conf.getStringList("general.hand.tooltip").stream().map(Storage::color).collect(Collectors.toList());
buggedClientAction = conf.getString("general.bugged_client.action", "show_both");
tooltipBuggedClient = conf.getStringList("general.bugged_client.tooltip").stream().map(Storage::color).collect(Collectors.toList());
ignoredItems = conf.getStringList("general.ignored_items");
checkUpdate = conf.getBoolean("general.check-update", true);
cmdShow = conf.getBoolean("general.sub-commands.broadcast", true);
cmdBroadcast = conf.getBoolean("general.sub-commands.show", true);
messageDeny = color(conf.getString("messages.deny-message", "&c&lYou have no item in hand!"));
messageReload = color(conf.getString("messages.reload-success", "&b&lSuccessful reload!"));
messageNoPermission = color(conf.getString("messages.no-permission", "&c&lI'm sorry, but you are not allowed to use the placeholder in chat!"));
messageCooldown = color(conf.getString("messages.cooldown-message", "&c&lYou can only use items in chat once a minute! You have {remaining} left!"));
updateMessage = color(conf.getString("messages.join-update.message", "&cA new version of ChatItem is available. &aClick here to download."));
updateHover = color(conf.getString("messages.join-update.hover", "&6Click to go to spigot page !"));
messageLimit = color(conf.getString("messages.limit-message", "&c&lYou can only add 8 item placeholders per message!"));
messageIgnoredItem = color(conf.getString("messages.ignored-item", "&cThis item is not allowed to be showed."));
discordSrvSendMsg = conf.getBoolean("discord-srv-send-our", true);
SECONDS = color(conf.getString("messages.seconds", " seconds"));
minutes = color(conf.getString("messages.minutes", " minutes"));
hours = color(conf.getString("messages.hours", " hours"));
colorStringList(tooltipHand);
}
public static String color(String s) {
return s == null || s.isEmpty() ? s : ChatColor.translateAlternateColorCodes('&', s);
}
private static void colorStringList(List<String> input) {
for (int i = 0; i < input.size(); ++i) {
input.set(i, color(input.get(i)));
}
}
private void checkConfigVersion() {
int latestVersion = ChatItem.CFG_VER;
if (latestVersion != configVersion) {
ChatItem pl = ChatItem.getInstance();
pl.getLogger().warning(ChatColor.RED + "ChatItem detected an older or invalid configuration file. Replacing it with the default config...");
performOverwrite();
conf = pl.getConfig();
pl.getLogger().warning(ChatColor.RED + "Replacement complete!");
}
}
private void performOverwrite() {
ChatItem.getInstance().saveResource("config.yml", true);
}
}
@@ -0,0 +1,109 @@
package me.dadus33.chatitem;
import java.io.File;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.inventory.ItemStack;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.dadus33.chatitem.utils.Utils;
public class Translation {
private static File folder;
private static YamlConfiguration legacy, allLangsConfig;
private static JsonObject messages;
private static HashMap<String, String> allLangs = new HashMap<>();
public static void load(ChatItem pl) {
folder = new File(pl.getDataFolder(), "lang");
if (!folder.exists())
folder.mkdir();
legacy = Utils.copyLoadFile(folder, "legacy.yml", "lang/legacy.yml");
allLangsConfig = Utils.copyLoadFile(pl.getDataFolder(), "langs.yml", "langs.yml");
allLangsConfig.getStringList("all").forEach(langKey -> {
try {
JsonObject content = JsonParser.parseReader(new InputStreamReader(pl.getResource("lang/" + langKey + ".json"))).getAsJsonObject();
allLangs.put(langKey, content.get("language.name").getAsString() + " (" + content.get("language.region").getAsString() + ")");
} catch (Exception e) {
pl.getLogger().severe("Failed to load lang with key " + langKey + " : " + e.getMessage() + " (" + e.getStackTrace()[0].toString() + ")");
}
});
allLangs = allLangs.entrySet().stream().sorted(Entry.comparingByValue()).collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
loadLang(pl.getStorage().language);
}
public static HashMap<String, String> getAllLangs() {
return allLangs;
}
public static JsonObject getMessages() {
return messages;
}
public static void loadLang(String lang) {
ChatItem pl = ChatItem.getInstance();
File langFile = new File(folder, lang + ".json");
if (!langFile.exists()) {
if (pl.getResource("lang/" + lang + ".json") != null) {
Utils.copyFile("lang/" + lang + ".json", langFile);
} else {
pl.getLogger().severe("Failed to find lang file for " + lang);
if(lang != "en_gb")
loadLang("en_gb");
return;
}
}
try {
messages = JsonParser.parseReader(new FileReader(langFile)).getAsJsonObject();
} catch (Exception e) {
e.printStackTrace();
}
pl.getLogger().info("Loaded translation for " + lang + ".");
}
@SuppressWarnings("deprecation")
public static String get(ItemStack item) {
String key = (item.getType().isBlock() ? "block" : "item") + ".minecraft." + item.getType().name().toLowerCase();
if (messages != null && messages.has(key)) {
return messages.get(key).getAsString();
} else
ChatItem.debug("Failed to find translation for " + key);
return legacy.getString(item.getType().name() + "." + item.getDurability(), item.getType().name().toLowerCase().replace("_", " "));
}
protected void thisMethodShouldNotBeUsed_InsteadToUpdateLangFileFromLocalInstall() throws Exception {
File dir = new File("dir/to/result");
File folder = new File("C:\\Dir\\To\\AppData\\Roaming\\.minecraft\\assets");// here we are looking for 1.19
JsonObject json = JsonParser.parseReader(new FileReader(new File(folder, "indexes/1.19.json"))).getAsJsonObject().get("objects").getAsJsonObject();
for (String key : json.keySet()) {
if (key.startsWith("minecraft/lang")) { // only lang files
String lang = key.toString().replace("minecraft/lang/", "");
String hash = json.get(key).getAsJsonObject().get("hash").getAsString();
File langFile = new File(folder, "objects/" + hash.substring(0, 2) + "/" + hash);
JsonObject langs = JsonParser.parseReader(new FileReader(langFile)).getAsJsonObject();
for (String langKey : new ArrayList<>(langs.keySet())) {
if (!(langKey.startsWith("block.") || langKey.startsWith("language"))) { // only what we want
langs.remove(langKey); // removing not needed
}
}
File langDir = new File(dir, lang);
Files.write(langDir.toPath(), Arrays.asList(langs.toString()));
System.out.println("Copied " + lang); // using sysout as it's made for basic java, not mc
}
}
}
}
@@ -0,0 +1,97 @@
package me.dadus33.chatitem.chatmanager;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.ItemPlayer;
import me.dadus33.chatitem.ItemSlot;
import me.dadus33.chatitem.utils.Utils;
public class Chat {
private static int actualId = 0;
private static final List<Chat> CHAT = new ArrayList<>();
public static Optional<Chat> getChat(int id) {
synchronized (CHAT) {
CHAT.removeIf(Chat::isOld);
return CHAT.stream().filter(o -> o.getId() == id).findFirst();
}
}
public static Chat create(Player p, String message, ChatAction action) {
return new Chat(actualId++, p, message, action);
}
public static Chat getFrom(String message) {
boolean found = false;
String id = "";
for(char c : ChatManager.fixSeparator(message).toCharArray()) {
if(c == ChatManager.SEPARATOR)
found = true;
else if(c == ChatManager.SEPARATOR_END)
break;
else if(found)
id += c;
}
ChatItem.debug("Search in " + message + ", id found: " + id);
return (id != "" && Utils.isInteger(id)) ? Chat.getChat(Integer.parseInt(id)).orElse(null) : null;
}
private final long time;
private final int id;
private final Player p;
private final String message;
private final ChatAction action;
public Chat(int id, Player p, String message, ChatAction action) {
this.time = System.currentTimeMillis();
this.id = id;
this.p = p;
this.message = message;
this.action = action;
CHAT.add(this);
}
public long getTime() {
return time;
}
public int getId() {
return id;
}
public Player getPlayer() {
return p;
}
public String getMessage() {
return message;
}
public ItemSlot getSlot() {
return action.getSlot();
}
public ChatAction getAction() {
return action;
}
public ItemPlayer getItemPlayer() {
return ItemPlayer.getPlayer(getPlayer());
}
private boolean isOld() {
return System.currentTimeMillis() > time + 10000;
}
public void remove() {
CHAT.remove(this);
}
@Override
public String toString() {
return "Chat{id=" + id + ",message=" + message + ",time=" + time + "}";
}
}
@@ -0,0 +1,41 @@
package me.dadus33.chatitem.chatmanager;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ItemSlot;
public class ChatAction {
private boolean isItem;
private ItemSlot slot;
private String command;
private ItemStack item;
public ChatAction(ItemSlot slot, ItemStack item) {
this.slot = slot;
this.item = item;
this.isItem = true;
}
public ChatAction(ItemSlot slot, String command) {
this.slot = slot;
this.command = command;
this.isItem = false;
}
public ItemSlot getSlot() {
return slot;
}
public boolean isItem() {
return isItem;
}
public String getCommand() {
return command;
}
public ItemStack getItem() {
return item;
}
}
@@ -0,0 +1,53 @@
package me.dadus33.chatitem.chatmanager;
import static me.dadus33.chatitem.chatmanager.ChatManager.SEPARATOR;
import static me.dadus33.chatitem.chatmanager.ChatManager.SEPARATOR_END;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.ItemSlot;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.utils.Utils;
public class ChatEventListener implements Listener {
private Storage getStorage() {
return ChatItem.getInstance().getStorage();
}
@EventHandler(priority = EventPriority.LOWEST)
public void onChat(AsyncPlayerChatEvent e) {
if (ChatManager.isTestingEnabled() && !ChatManager.isTesting("packet"))
return;
if (ChatManager.containsSeparator(e.getMessage())) { // If the BELL character is found, we have to remove it
e.setMessage(ChatManager.removeSeparator(e.getMessage()));
}
Player p = e.getPlayer();
String oldMsg = e.getMessage();
ItemSlot slot = ItemSlot.getItemSlotFromMessage(e.getMessage());
if (slot == null) {
ChatItem.debug("(v1) not found placeholders in: " + e.getMessage());
return;
}
ChatAction action = ChatManager.getChatAction(slot, p);
if(action.isItem() && !ChatManager.canShowItem(p, action.getItem(), slot, e))
return;
String s = slot.replacePlaceholdersToSeparator(e.getMessage());
if (Utils.countMatches(s, Character.toString(ChatManager.SEPARATOR)) > getStorage().limit) {
e.setCancelled(true);
if (!getStorage().messageLimit.isEmpty())
p.sendMessage(getStorage().messageLimit);
return;
}
Chat c = Chat.create(p, oldMsg, action);
ChatItem.debug("(v1) Set placeholder to message " + c);
e.setMessage(s.replace(Character.toString(ChatManager.SEPARATOR), SEPARATOR + Integer.toString(c.getId()) + SEPARATOR_END));
e.setFormat(e.getFormat().replace(oldMsg, e.getMessage())); // set own message for plugin that already put the message into the format
}
}
@@ -0,0 +1,345 @@
package me.dadus33.chatitem.chatmanager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import javax.annotation.Nullable;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.ItemMeta;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.ItemSlot;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.hook.ecoenchants.EcoEnchantsSupport;
import me.dadus33.chatitem.invsee.InvShower;
import me.dadus33.chatitem.invsee.hook.EnderChestShower;
import me.dadus33.chatitem.invsee.hook.PlayerInventoryShower;
import me.dadus33.chatitem.itemnamer.NamerManager;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.Utils;
import me.dadus33.chatitem.utils.Version;
public abstract class ChatManager {
public static String inTest = null;
private final static HashMap<UUID, Long> COOLDOWNS = new HashMap<>();
private final static HashMap<UUID, Long> LAST_INFO_MESSAGE = new HashMap<>();
private final static String NAME = "{name}";
private final static String AMOUNT = "{amount}";
private final static String TIMES = "{times}";
private final static String LEFT = "{remaining}";
public final static char SEPARATOR = ((char) 0x0007);
public final static String SEPARATOR_STR = "\\u0007";
public final static char SEPARATOR_END = ((char) 0x0003);
public final static String SEPARATOR_END_STR = "\\u0003";
public static String removeSeparator(String message) {
return fixSeparator(message).replace(Character.toString(SEPARATOR), "").replace(Character.toString(SEPARATOR_END), "");
}
public static String replaceSeparator(Chat chat, String message, String replacement) {
return fixSeparator(message).replace(Character.toString(SEPARATOR) + (chat != null ? chat.getId() : "") + Character.toString(SEPARATOR_END), replacement);
}
public static String fixSeparator(String s) {
return s == null ? "" : s.replace(SEPARATOR_STR, Character.toString(SEPARATOR)).replace(SEPARATOR_END_STR, Character.toString(SEPARATOR_END));
}
public static boolean equalsSeparator(String s) {
return s != null && (s.equalsIgnoreCase(SEPARATOR_STR) || s.equalsIgnoreCase(Character.toString(SEPARATOR)));
}
public static boolean containsSeparator(String s) {
return s != null && (s.contains(SEPARATOR_STR) || s.contains(Character.toString(SEPARATOR)));
}
public static boolean equalsSeparatorEnd(String s) {
return s != null && (s.equalsIgnoreCase(SEPARATOR_END_STR) || s.equalsIgnoreCase(Character.toString(SEPARATOR_END)));
}
public static boolean containsSeparatorEnd(String s) {
return s != null && (s.contains(SEPARATOR_END_STR) || s.contains(Character.toString(SEPARATOR_END)));
}
protected Storage s;
public ChatManager() {
}
public abstract String getName();
public abstract String getId();
public Storage getStorage() {
return s;
}
public void load(ChatItem pl, Storage s) {
this.s = s;
}
public abstract void unload(ChatItem pl);
/**
* Get the item in hand as usable one.<br>
* Will include, in lore, all informations from other plugins.
*
* @param p the player
* @return the usable item
*/
public static ItemStack getUsableItem(Player p, ItemSlot slot) {
if(slot == null)
return null;
ItemStack betterItem = HandItem.getBetterItem(p, slot);
if(betterItem == null)
return null;
ItemStack item = betterItem.clone();
if(slot.isDenyIfNoItem() && ItemUtils.isEmpty(item))
return null;
if (EcoEnchantsSupport.hasSupport()) {
item = EcoEnchantsSupport.manageItem(item);
} else if (item.hasItemMeta()) {
ItemMeta meta = item.getItemMeta();
if (meta instanceof BookMeta) { // filtering written books
BookMeta bm = (BookMeta) item.getItemMeta();
bm.setPages(Collections.emptyList());
item.setItemMeta(bm);
} else if (meta instanceof BlockStateMeta && Version.getVersion().isNewerOrEquals(Version.V1_9)) { // if it's a block
BlockStateMeta bsm = (BlockStateMeta) item.getItemMeta();
if (bsm.hasBlockState() && bsm.getBlockState() instanceof ShulkerBox) {
ShulkerBox sb = (ShulkerBox) bsm.getBlockState();
for (ItemStack itemInv : sb.getInventory()) {
ItemUtils.stripData(itemInv);
}
bsm.setBlockState(sb);
}
item.setItemMeta(bsm);
}
}
return item;
}
public static ChatAction getChatAction(ItemSlot slot, Player p) {
if(slot.isCommand()) {
UUID uuid = UUID.randomUUID();
InvShower.add(uuid.toString(), slot == ItemSlot.INVENTORY ? new PlayerInventoryShower(p) : new EnderChestShower(p));
return new ChatAction(slot, "/chatitem seeinv " + uuid.toString());
}
return new ChatAction(slot, getUsableItem(p, slot));
}
/**
* Get all lores lines of an item, to replace the show_item action which is not
* working with ViaBackwards
*
* @param item the item to get lines from
* @return all lores
*/
public static List<String> getMaxLinesFromItem(Player p, ItemStack item) {
List<String> lines = new ArrayList<>();
if (item.hasItemMeta()) {
ItemMeta meta = item.getItemMeta();
lines.add(meta.hasDisplayName() ? meta.getDisplayName() : NamerManager.getName(p, item, ChatItem.getInstance().getStorage()));
if (meta.hasEnchants()) {
meta.getEnchants().forEach((enchant, lvl) -> {
lines.add(ChatColor.RESET + Utils.getEnchantName(enchant) + " " + Utils.toRoman(lvl));
});
}
if (meta.hasLore())
lines.addAll(meta.getLore());
} else {
lines.add(NamerManager.getName(p, item, ChatItem.getInstance().getStorage()));
}
return lines;
}
/**
* Get the name of item according to player & config<br>
* Prefer use {@link #getNameOfItem(Player, ItemStack, Storage)} if you want
* take in count the empty item
*
* @param p the player
* @param item the item
* @param c the config
* @return the name of item
*/
public static String styleItem(Player p, ItemStack item, Storage c) {
String replacer = c.nameFormat;
String amount = c.amountFormat;
if (item.getAmount() == 1) {
if (c.addAmountForced) {
amount = amount.replace(TIMES, "1");
replacer = replacer.replace(AMOUNT, amount);
} else {
replacer = replacer.replace(AMOUNT, "");
}
} else {
amount = amount.replace(TIMES, String.valueOf(item.getAmount()));
replacer = replacer.replace(AMOUNT, amount);
}
return replacer.replace(NAME, NamerManager.getName(p, item, c));
}
/**
* Get the name of item according to player & config
*
* @param p the player that is owner of item
* @param item the item
* @param c the config
* @return the name of item or hand
*/
public static String getNameOfItem(Player p, ItemStack item, Storage c) {
if (ItemUtils.isEmpty(item)) {
if (c.handDisabled)
return ItemSlot.HAND.getPlaceholders().get(0);
else
return c.handName;
}
return styleItem(p, item, c);
}
public static String getNameForChatAction(Player p, ChatAction action, Storage c) {
if(action.isItem()) {
ItemStack item = action.getItem();
if (ItemUtils.isEmpty(item)) {
if (c.handDisabled)
return ItemSlot.HAND.getPlaceholders().get(0);
else
return c.handName;
}
return styleItem(p, item, c);
}
return "";
}
public static String calculateTime(long seconds) {
Storage c = ChatItem.getInstance().getStorage();
if (seconds < 60) {
return seconds + c.SECONDS;
}
if (seconds < 3600) {
StringBuilder builder = new StringBuilder();
int minutes = (int) seconds / 60;
builder.append(minutes).append(c.minutes);
int secs = (int) seconds - minutes * 60;
if (secs != 0) {
builder.append(" ").append(secs).append(c.SECONDS);
}
return builder.toString();
}
StringBuilder builder = new StringBuilder();
int hours = (int) seconds / 3600;
builder.append(hours).append(c.hours);
int minutes = (int) (seconds / 60) - (hours * 60);
if (minutes != 0) {
builder.append(" ").append(minutes).append(c.minutes);
}
int secs = (int) (seconds - ((seconds / 60) * 60));
if (secs != 0) {
builder.append(" ").append(secs).append(c.SECONDS);
}
return builder.toString();
}
public static boolean canShowItem(Player p, ItemStack item, ItemSlot slot, @Nullable Cancellable e) {
if(item == null)
return false;
Storage c = ChatItem.getInstance().getStorage();
if (c.permissionEnabled && !p.hasPermission(c.permissionName)) {
if (!c.letMessageThrough) {
if (e != null)
e.setCancelled(true);
}
if (!c.messageNoPermission.isEmpty() && c.showNoPermissionMessage) {
sendIfNeed(p, c.messageNoPermission);
}
return false;
}
if (item.getType().equals(Material.AIR)) {
if (slot.isDenyIfNoItem()) {
if (e != null)
e.setCancelled(true);
if (!c.messageDeny.isEmpty())
sendIfNeed(p, c.messageDeny);
return false;
}
if (c.handDisabled) {
return false;
}
}
if (c.cooldown > 0 && !p.hasPermission("chatitem.ignore-cooldown")) {
if (COOLDOWNS.containsKey(p.getUniqueId())) {
long start = COOLDOWNS.get(p.getUniqueId());
long current = System.currentTimeMillis() / 1000;
long elapsed = current - start;
if (elapsed >= c.cooldown) {
COOLDOWNS.remove(p.getUniqueId());
} else {
if (!c.letMessageThrough) {
if (e != null)
e.setCancelled(true);
}
if (!c.messageCooldown.isEmpty()) {
long left = (start + c.cooldown) - current;
sendIfNeed(p, c.messageCooldown.replace(LEFT, ChatManager.calculateTime(left)));
}
ChatItem.debug("Cooldown");
return false;
}
}
}
for (String ignored : c.ignoredItems) {
if (item.getType().name().toLowerCase().contains(ignored.toLowerCase())) {
return false;
}
}
LAST_INFO_MESSAGE.put(p.getUniqueId(), System.currentTimeMillis()); // prevent showing item then send cooldown error message
return true;
}
private static void sendIfNeed(Player p, String msg) {
Long time = LAST_INFO_MESSAGE.remove(p.getUniqueId());
if (time != null) {
long diff = System.currentTimeMillis() - time;
if (diff < 100)
return; // don't show message
}
p.sendMessage(msg);
LAST_INFO_MESSAGE.put(p.getUniqueId(), System.currentTimeMillis());
}
public static void clear(Player p) {
COOLDOWNS.remove(p.getUniqueId());
LAST_INFO_MESSAGE.remove(p.getUniqueId());
}
public static void applyCooldown(Player p) {
COOLDOWNS.put(p.getUniqueId(), System.currentTimeMillis() / 1000);
}
public static boolean isTestingEnabled() {
return inTest != null;
}
public static boolean isTesting(String actual) {
return inTest != null && (inTest == "both" || inTest.equalsIgnoreCase(actual));
}
public static void setTesting(String actual) {
inTest = actual;
}
}
@@ -0,0 +1,38 @@
package me.dadus33.chatitem.chatmanager;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ItemSlot;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.Version;
public class HandItem {
@SuppressWarnings("deprecation")
public static ItemStack getBetterItem(Player p, ItemSlot slot) {
switch (slot) {
case HAND:
if(Version.getVersion().isNewerOrEquals(Version.V1_9)) {
ItemStack main = p.getInventory().getItemInMainHand();
if(!ItemUtils.isEmpty(main))
return main;
return p.getInventory().getItemInOffHand();
}
return p.getItemInHand();
case HELMET:
return p.getInventory().getHelmet();
case CHESTPLATE:
return p.getInventory().getChestplate();
case LEGGINGS:
return p.getInventory().getLeggings();
case BOOTS:
return p.getInventory().getBoots();
case ENDERCHEST:
break;
case INVENTORY:
break;
}
return null; // should never happen
}
}
@@ -0,0 +1,151 @@
package me.dadus33.chatitem.chatmanager.v1;
import java.lang.reflect.Constructor;
import org.bukkit.Bukkit;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.listeners.ChatPacketManager;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacketManager;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketManager;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
import me.dadus33.chatitem.utils.Utils;
public class PacketEditingChatManager extends ChatManager {
private boolean baseComponentAvailable = true;
private final ChatItemPacketManager packetManager;
private final ChatPacketManager chatPacketManager;
public PacketEditingChatManager(ChatItem pl) {
packetManager = new ChatItemPacketManager(pl);
chatPacketManager = new ChatPacketManager(this);
// Check for existence of BaseComponent class (only on spigot)
try {
Class.forName("net.md_5.bungee.api.chat.BaseComponent");
} catch (ClassNotFoundException e) {
baseComponentAvailable = false;
}
}
@Override
public String getName() {
return "PacketEditing";
}
@Override
public String getId() {
return "packet";
}
@Override
public void load(ChatItem pl, Storage s) {
super.load(pl, s);
PacketManager pm = packetManager.getPacketManager();
pm.addHandler(chatPacketManager);
Bukkit.getOnlinePlayers().forEach(pm::addPlayer); // add actual online players
}
@Override
public void unload(ChatItem pl) {
PacketManager pm = packetManager.getPacketManager();
pm.removeHandler(chatPacketManager);
pm.stop();
}
public boolean supportsChatComponentApi() {
return baseComponentAvailable;
}
private static String checkPacketSize(String packet, int maxSize) {
int size = packet.getBytes().length;
while(size > maxSize) {
packet = packet.replaceFirst(" ", " ");
if(size == packet.getBytes().length)
break; // could not fix myself
size = packet.getBytes().length;
}
return packet;
}
public static Object createSystemChatPacket(String json) throws Exception {
json = checkPacketSize(json, 150000);
Object packet = internalCreateSystemChatPacket(json);
if(packet != null)
return packet;
packet = internalCreateSystemChatPacket(PacketUtils.ICB_FROM_JSON.invoke(null, json));
if(packet != null)
return packet;
ChatItem.getInstance().getLogger().warning("Can't create a new packet for json " + json);
return null;
}
private static Object internalCreateSystemChatPacket(Object obj) throws Exception {
Class<?> packetClass = PacketUtils.getNmsClass("ClientboundPlayerChatPacket", "network.protocol.game.", "ClientboundSystemChatPacket", "PacketPlayOutChat");
Class<?> chatMessageTypeClass = PacketUtils.isClassExist("net.minecraft.network.chat.ChatMessageType") ? PacketUtils.getNmsClass("ChatMessageType", "network.chat.") : null;
Constructor<?> betterOne = null;
Object[] betterParam = null;
for (Constructor<?> cons : packetClass.getDeclaredConstructors()) {
if (!cons.isAccessible())
cons.setAccessible(true);
// check for basic method
if(obj instanceof String) {
if (cons.getParameterCount() == 2 && cons.getParameterTypes()[0].equals(String.class) && cons.getParameterTypes()[1].equals(int.class)) { // "string, int"
return cons.newInstance(obj, 1);
} else if (cons.getParameterCount() == 2 && cons.getParameterTypes()[0].equals(String.class) && cons.getParameterTypes()[1].equals(boolean.class)) { // "string, boolean"
return cons.newInstance(obj, false); // false for no overlay
} else if (cons.getParameterCount() == 3 && cons.getParameterTypes()[1].equals(String.class)) { // "component", "string", <something not checked>
Class<?> secondParam = cons.getParameterTypes()[2];
if (secondParam.equals(int.class)) // "component", "string", "int"
return cons.newInstance(null, obj, 1);
else if (secondParam.equals(boolean.class)) // "component", "string", "boolean"
return cons.newInstance(null, obj, false);
}
}
int nbPut = 0;
Object[] params = new Object[cons.getParameterCount()];
for(int i = 0; i < params.length; i++) {
if(cons.getParameterTypes()[i].isAssignableFrom(obj.getClass())) {
params[i] = obj;
nbPut++;
} else if(chatMessageTypeClass != null && cons.getParameterTypes()[i].isAssignableFrom(chatMessageTypeClass)) {
params[i] = getChatMessageType();
} else if(cons.getParameterTypes()[i].isAssignableFrom(boolean.class)) // need to set primitives
params[i] = false;
else if(cons.getParameterTypes()[i].isAssignableFrom(int.class)) // need to set primitives
params[i] = 0;
}
if(nbPut == 1) {
if((betterOne == null && betterParam == null) || betterParam.length > params.length) {
betterOne = cons;
betterParam = params;
if(params.length == 1) // only what we need
break;
continue; // check for something better?
}
} else if(nbPut > 1)
ChatItem.getInstance().getLogger().warning("Some constructor seems to have too many " + obj.getClass().getSimpleName() + ". Class: " + packetClass.getSimpleName());
}
if(betterOne != null && betterParam != null) {
try {
return betterOne.newInstance(betterParam);
} catch (IllegalArgumentException e) {
ChatItem.getInstance().getLogger().warning("Failed to create a new packet to send. " + betterOne.getParameterCount() + " (" + Utils.arrayToString(betterOne.getParameterTypes()) + "). Params: " + Utils.arrayToString(betterParam));
return null;
}
}
return null;
}
private static Object getChatMessageType() throws Exception {
Class<?> c = PacketUtils.getNmsClass("ChatMessageType", "network.chat.");
return ReflectionUtils.getMethod(c, c, byte.class).invoke(null, (byte) 0);
}
}
@@ -0,0 +1,130 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp;
import javax.annotation.Nullable;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.chatmanager.Chat;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulator;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.utils.Utils;
public interface IComponentManager {
default boolean hasConditions() {
return true;
}
String getBaseComponentAsJSON(ChatItemPacket packet);
void writeJson(ChatItemPacket packet, String json);
default @Nullable Chat getChat(String json) {
json = ChatManager.fixSeparator(json);
try {
Chat possibleChat = Chat.getFrom(json);
if (possibleChat != null) // found something with basic search
return possibleChat;
Chat chat = new Searching(json).search();
if (chat == null)
ChatItem.debug("Failed to find chat for JSON " + json);
return chat;
} catch (Exception e) {
e.printStackTrace();
} // not JSON
return null;
}
default Object manageItem(Player p, Chat chat, ChatItemPacket packet, ItemStack item, String json, Storage c) throws Exception {
String message;
if (Utils.isBeforeChatJson(p))
message = JSONManipulator.getInstance().parseEmpty(json, ChatManager.styleItem(chat.getPlayer(), item, c), ChatManager.getMaxLinesFromItem(p, item), chat.getPlayer());
else
message = JSONManipulator.getInstance().parse(chat, json, chat.getAction(), ChatManager.styleItem(chat.getPlayer(), item, c));
if (message != null) {
ChatItem.debug("(v1) Writing message: " + message);
writeJson(packet, message);
}
return packet.getPacket();
}
default Object manageEmpty(Player p, Chat chat, ChatItemPacket packet, String json, Storage c) {
String message = JSONManipulator.getInstance().parseEmpty(json, c.handName, c.tooltipHand, chat.getPlayer());
if (message != null) {
ChatItem.debug("(v1) Writing empty message: " + message);
writeJson(packet, message);
}
return packet.getPacket();
}
public static class Searching {
private boolean found = false;
private String id = "", json;
public Searching(String json) {
this.json = json;
}
private Chat search() {
JsonObject jsonObj = JsonParser.parseString(json).getAsJsonObject();
if (jsonObj.has("extra")) {
if (searchInExtra(jsonObj.getAsJsonArray("extra"))) {
return getWithId();
}
}
if (jsonObj.has("text")) {
JsonElement text = jsonObj.get("text");
if (text.isJsonObject() && searchInObject(text.getAsJsonObject()))
return getWithId();
else if (text.isJsonArray() && searchInExtra(text.getAsJsonArray()))
return getWithId();
else if (text.isJsonPrimitive() && searchInString(text.getAsString()))
return getWithId();
}
return null;
}
private Chat getWithId() {
return id != "" && Utils.isInteger(id) ? Chat.getChat(Integer.parseInt(id)).orElse(null) : null;
}
private boolean searchInExtra(JsonArray json) {
for (JsonElement element : json) {
if (element.isJsonObject()) {
JsonObject withObj = element.getAsJsonObject();
if (withObj.has("extra") && searchInExtra(withObj.getAsJsonArray("extra")))
return true;
else if (withObj.has("text") && searchInObject(withObj))
return true;
}
}
return false;
}
private boolean searchInObject(JsonObject json) {
return json.has("text") && json.get("text").isJsonPrimitive() && searchInString(json.get("text").getAsString());
}
private boolean searchInString(String s) {
for (char c : ChatManager.fixSeparator(s).toCharArray()) {
if (c == ChatManager.SEPARATOR)
found = true;
else if (c == ChatManager.SEPARATOR_END)
return true;
else if (found)
id += c;
}
return id != "" && Utils.isInteger(id) && Chat.getChat(Integer.parseInt(id)).isPresent();
}
}
}
@@ -0,0 +1,147 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.chatmanager.Chat;
import me.dadus33.chatitem.chatmanager.ChatAction;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IComponentManager;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent.ContentModifier;
import me.dadus33.chatitem.hook.DiscordSrvSupport;
import me.dadus33.chatitem.utils.Messages;
import me.dadus33.chatitem.utils.PacketUtils;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.nbt.api.BinaryTagHolder;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TranslatableComponent;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
public class AdventureComponentManager implements IComponentManager {
@Override
public boolean hasConditions() {
try {
for (String cl : Arrays.asList("net.kyori.adventure.text.Component", "net.kyori.adventure.text.serializer.gson.GsonComponentSerializer"))
Class.forName(cl);
} catch (Throwable e) { // can't support this, adventure comp not found
ChatItem.debug("Can't load AdventureComponentManager : " + e.getMessage());
return false;
}
return true;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Component comp = packet.getContent().getSpecificModifier(Component.class).readSafely(0);
if (comp == null)
return null;
try {
String json = GsonComponentSerializer.gson().serialize(comp);
JsonObject jsonObj = JsonParser.parseString(json).getAsJsonObject();
ChatItem.debug("AdventureJSON : " + json);
if (jsonObj.has("with")) {
JsonObject next = new JsonObject();
next.add("extra", jsonObj.get("with"));
return next.toString();
}
return json;
} catch (JsonParseException e) { // ignore this and just let skip this
return null;
}
}
@Override
public Object manageItem(Player p, Chat chat, ChatItemPacket packet, ItemStack item, String json, Storage c) throws Exception {
ChatAction action = chat.getAction();
if (action.isItem()) {
String itemName = ChatManager.getNameOfItem(chat.getPlayer(), item, c);
ChatItem.debug("NBT tag: " + PacketUtils.getNbtTag(item));
return manage(p, chat, packet, itemName, HoverEvent.showItem(Key.key(item.getType().getKey().getKey()), item.getAmount(), BinaryTagHolder.of(PacketUtils.getNbtTag(item))), null);
}
return manage(p, chat, packet, Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat", "%cible%", chat.getPlayer().getName()),
HoverEvent.showText(Component.text(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", chat.getPlayer().getName()))),
ClickEvent.runCommand(action.getCommand()));
}
@Override
public Object manageEmpty(Player p, Chat chat, ChatItemPacket packet, String json, Storage c) {
Component builder = Component.text("");
c.tooltipHand.forEach(s -> builder.append(Component.text(s)));
Player sender = chat.getPlayer();
ChatAction action = chat.getAction();
if (action.isItem()) {
String handName = c.handName.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName());
return manage(p, chat, packet, handName, HoverEvent.showText(builder), null);
}
return manage(p, chat, packet, Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat", "%cible%", chat.getPlayer().getName()),
HoverEvent.showText(Component.text(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", chat.getPlayer().getName()))),
ClickEvent.runCommand(action.getCommand()));
}
private Object manage(Player p, Chat chat, ChatItemPacket packet, String replacement, HoverEvent<?> hover, ClickEvent click) {
ContentModifier<Component> modifier = packet.getContent().getSpecificModifier(Component.class);
Component comp = modifier.readSafely(0);
if (comp == null) {
ChatItem.debug("The component is null.");
return null;
}
comp = checkComponent(comp, hover, click, replacement, chat);
if(ChatItem.discordSrvSupport && DiscordSrvSupport.isSendingMessage())
DiscordSrvSupport.sendChatMessage(p, comp, null);
try {
((Audience) Audience.class.getDeclaredMethod("audience", Audience.class).invoke(null, p)).sendMessage(comp);
} catch (Exception e) {
e.printStackTrace();
}
return null; // send by manager
}
private Component checkComponent(Component comp, HoverEvent<?> hover, ClickEvent click, String itemName, Chat chat) {
if (comp instanceof TextComponent) {
TextComponent tc = (TextComponent) comp;
if (ChatManager.containsSeparator(tc.content())) {
ChatItem.debug("Changing text " + tc.content() + " to " + itemName);
TextColor color = tc.color();
comp = tc.content(ChatManager.replaceSeparator(chat, tc.content(), itemName)).hoverEvent(hover);
if (click != null)
comp.clickEvent(click);
comp.append(Component.text("").color(color)); // reset color
} else
ChatItem.debug("No insert of text without separator: " + tc.content());
} else if (comp instanceof TranslatableComponent) {
TranslatableComponent tc = (TranslatableComponent) comp;
List<Component> next = new ArrayList<>();
for (Component extra : tc.args()) {
next.add(checkComponent(extra, hover, click, itemName, chat));
}
comp = tc.args(next);
} else
ChatItem.debug("Not valid comp class " + comp.getClass().getSimpleName() + " : " + comp);
List<Component> next = new ArrayList<>();
for (Component extra : comp.children()) {
next.add(checkComponent(extra, hover, click, itemName, chat));
}
return comp.children(next);
}
}
@@ -0,0 +1,47 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import com.google.gson.JsonParser;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IComponentManager;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.hook.DiscordSrvSupport;
import me.dadus33.chatitem.utils.PacketUtils;
public class ComponentNMSManager implements IComponentManager {
@Override
public boolean hasConditions() {
return PacketUtils.COMPONENT_CLASS != null;
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Object chatBaseComp = packet.getContent().getChatComponents().readSafely(0);
if (chatBaseComp != null) {
try {
Object o = PacketUtils.CHAT_SERIALIZER.getMethod("a", PacketUtils.COMPONENT_CLASS).invoke(null, chatBaseComp);
if(o != null && o instanceof String && JsonParser.parseString((String) o).isJsonObject()) {
return (String) o;
}
} catch (Exception exc) {
exc.printStackTrace();
}
}
return null;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
// Not compatible with that for now
if(ChatItem.discordSrvSupport && DiscordSrvSupport.isSendingMessage())
ChatItem.debug("(v1 ComponentNMS) Can't send message to discord");
// DiscordSrvSupport.sendChatMessage(p, comp, null);
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,56 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import java.lang.reflect.Method;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IComponentManager;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.utils.PacketUtils;
public class IChatBaseComponentManager implements IComponentManager {
private Method serializerGetJson;
public IChatBaseComponentManager() {
try {
Class<?> chatSerializer = PacketUtils.CHAT_SERIALIZER;
//fromJson = chatSerializer.getMethod("a", String.class);
for (Method m : chatSerializer.getDeclaredMethods()) {
if (m.getParameterCount() == 1 && m.getParameterTypes()[0].equals(PacketUtils.COMPONENT_CLASS) && m.getReturnType().equals(String.class)) {
serializerGetJson = m;
break;
}
}
if (serializerGetJson == null)
ChatItem.getInstance().getLogger().warning("Failed to find JSON serializer in class: " + chatSerializer.getCanonicalName());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public boolean hasConditions() {
return serializerGetJson != null;
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
try {
Object obj = packet.getContent().getChatComponents().readSafely(0);
return obj == null ? null : (String) serializerGetJson.invoke(null, obj);
} catch (Exception exc) {
exc.printStackTrace();
}
return null;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,68 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IComponentManager;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent.ContentModifier;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
public class PCMComponentManager implements IComponentManager {
@Override
public boolean hasConditions() {
try {
for (String cl : Arrays.asList("net.minecraft.network.chat.PlayerChatMessage"))
Class.forName(cl);
} catch (Exception e) { // can't support this
ChatItem.debug("Can't load PCMComponentManager : " + e.getMessage());
return false;
}
return true;
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Class<?> pcmClass = PacketUtils.getNmsClass("PlayerChatMessage", "network.chat.");
Object pcm = packet.getContent().getSpecificModifier(pcmClass).readSafely(0);
if (pcm != null) {
try {
Object chatBaseComp = ReflectionUtils.getMethod(pcmClass, PacketUtils.COMPONENT_CLASS).invoke(pcm);
if(chatBaseComp != null)
ChatItem.debug("[PCMManager] Founded " + chatBaseComp.getClass().getSimpleName());
return chatBaseComp == null ? null : PacketUtils.CHAT_SERIALIZER.getMethod("a", PacketUtils.COMPONENT_CLASS).invoke(null, chatBaseComp).toString();
} catch (Exception exc) {
exc.printStackTrace();
}
}
return null;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
Object chatComp = PacketUtils.CHAT_SERIALIZER.getMethod("a", String.class).invoke(null, json);
Class<?> pcmClass = PacketUtils.getNmsClass("PlayerChatMessage", "network.chat.");
ContentModifier<Object> pcmModifier = packet.getContent().getSpecificModifier((Class<Object>) pcmClass);
Object pcm = ReflectionUtils.getMethod(pcmClass, pcmClass, PacketUtils.COMPONENT_CLASS).invoke(pcmModifier.readSafely(0), chatComp);
for(Constructor<?> cons : packet.getPacket().getClass().getConstructors()) {
if(cons.getParameterCount() <= 1)
continue;
Object[] params = new Object[cons.getParameterCount()];
for(int i = 0; i < params.length; i++) {
Class<?> cls = cons.getParameterTypes()[i];
if(cls.equals(pcmClass)) {
params[i] = pcm;
} else
params[i] = packet.getContent().getSpecificModifier(cls).readSafely(0);
}
packet.setPacket(cons.newInstance(params));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,157 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import java.util.Arrays;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.chatmanager.Chat;
import me.dadus33.chatitem.chatmanager.ChatAction;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IComponentManager;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.hook.DiscordSrvSupport;
import me.dadus33.chatitem.utils.Messages;
import me.dadus33.chatitem.utils.Utils;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.chat.ComponentSerializer;
public class StringComponentManager implements IComponentManager {
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
String json = packet.getContent().getStrings().readSafely(0);
if (json != null && json.startsWith("[") && json.endsWith("]")) { // if used as array instead of json obj
JsonArray extra = new JsonArray();
for (JsonElement element : JsonParser.parseString(json).getAsJsonArray()) {
if (element.isJsonObject()) { // ignore this
extra.add(element);
} else {
ChatItem.debug("Ignoring element " + element);
}
}
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("text", "");
jsonObject.add("extra", extra);
json = jsonObject.toString();
} else if (json == null) {
BaseComponent[] comp = packet.getContent().getSpecificModifier(BaseComponent[].class).readSafely(0);
if (comp != null)
return ComponentSerializer.toString(comp);
}
return json;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json));
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Object manageItem(Player p, Chat chat, ChatItemPacket packet, ItemStack item, String json, Storage c) throws Exception {
ChatAction action = chat.getAction();
if (action.isItem())
return manage(p, chat, packet, ChatManager.getNameOfItem(chat.getPlayer(), item, c), Utils.createItemHover(item, p), null);
else
return manage(p, chat, packet, ChatManager.getNameOfItem(chat.getPlayer(), item, c),
Utils.createTextHover(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", chat.getPlayer().getName())),
Utils.createRunCommand(action.getCommand()));
}
@Override
public Object manageEmpty(Player p, Chat chat, ChatItemPacket packet, String json, Storage c) {
ComponentBuilder builder = new ComponentBuilder("");
c.tooltipHand.forEach(s -> builder.append(s));
Player sender = chat.getPlayer();
HoverEvent hover;
ClickEvent click;
String rep;
ChatAction action = chat.getAction();
if (action.isItem()) {
hover = Utils.createTextHover(builder.create());
rep = c.handName.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName());
click = null;
} else {
hover = Utils.createTextHover(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", chat.getPlayer().getName()));
rep = Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat", "%cible%", chat.getPlayer().getName());
click = Utils.createRunCommand(action.getCommand());
}
return manage(p, chat, packet, rep, hover, click);
}
private Object manage(Player p, Chat chat, ChatItemPacket packet, String replacement, HoverEvent hover, ClickEvent click) {
BaseComponent[] components = packet.getContent().getSpecificModifier(BaseComponent[].class).readSafely(0);
if (components == null) {
String json = packet.getContent().getStrings().readSafely(0);
if (json != null && json.startsWith("[") && json.endsWith("]")) { // if used as array instead of json obj
JsonArray extra = new JsonArray();
for (JsonElement element : JsonParser.parseString(json).getAsJsonArray()) {
if (element.isJsonObject()) { // ignore this
extra.add(element);
} else {
ChatItem.debug("Ignoring element " + element);
}
}
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("text", "");
jsonObject.add("extra", extra);
json = jsonObject.toString();
}
ChatItem.debug("[StringComponentManager] Using JSON " + json);
try {
components = ComponentSerializer.parse(json);
} catch (Exception e) {
ChatItem.getInstance().getLogger().severe("Failed to parse JSON: " + json + ". Error:");
e.printStackTrace();
return packet.getPacket();
}
}
ChatItem.debug("Checking for " + components.length + " components");
Arrays.asList(components).forEach(comp -> checkComponent(comp, hover, click, replacement, chat));
if(ChatItem.discordSrvSupport && DiscordSrvSupport.isSendingMessage())
DiscordSrvSupport.sendChatMessage(p, TextComponent.toLegacyText(components), null);
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(ComponentSerializer.toString(components)));
} catch (Exception e) {
e.printStackTrace();
}
return packet.getPacket();
}
private void checkComponent(BaseComponent comp, HoverEvent hover, ClickEvent click, String itemName, Chat chat) {
if (comp instanceof TextComponent) {
TextComponent tc = (TextComponent) comp;
if (ChatManager.containsSeparator(tc.getText())) {
String oldText = tc.getText();
ChatItem.debug("Changing text " + oldText + " to " + itemName + ", extra: " + (tc.getExtra() == null ? "-" : tc.getExtra().size()));
tc.setText(ChatManager.replaceSeparator(chat, oldText, itemName));
tc.setHoverEvent(hover);
if (click != null)
tc.setClickEvent(click);
} else
ChatItem.debug("No insert of text without separator: " + tc.getText() + " (legacy: " + tc.toLegacyText() + ")");
}
if (comp.getExtra() != null) {
for (BaseComponent extra : comp.getExtra()) {
checkComponent(extra, hover, click, itemName, chat);
}
}
}
}
@@ -0,0 +1,296 @@
package me.dadus33.chatitem.chatmanager.v1.json;
import static me.dadus33.chatitem.utils.PacketUtils.getNmsClass;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.Chat;
import me.dadus33.chatitem.chatmanager.ChatAction;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.utils.Messages;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
public class JSONManipulator {
private static JSONManipulator instance = new JSONManipulator();
public static JSONManipulator getInstance() {
return instance;
}
private static final List<String> SKIPPED = Arrays.asList("HSTRY_ENCHANTS");
public static final Class<?> CRAFT_ITEM_STACK_CLASS = PacketUtils.getObcClass("inventory.CraftItemStack");
public static final Class<?> NMS_ITEM_STACK_CLASS = getNmsClass("ItemStack", "world.item.");
public static final Method AS_NMS_COPY = ReflectionUtils.getMethod(CRAFT_ITEM_STACK_CLASS, "asNMSCopy", ItemStack.class);
public static final Class<?> NBT_TAG_COMPOUND = getNmsClass("NBTTagCompound", "nbt.");
public static final Method SAVE_NMS_ITEM_STACK_METHOD = ReflectionUtils.getMethod(NMS_ITEM_STACK_CLASS, NBT_TAG_COMPOUND, NBT_TAG_COMPOUND);
public static final Field MAP = ReflectionUtils.getField(NBT_TAG_COMPOUND, "map", "x");
private JsonArray classicTooltip;
public String parse(Chat chat, String json, ChatAction action, String replacement) throws Exception {
JsonObject obj = JsonParser.parseString(json).getAsJsonObject();
JsonObject wrapper = new JsonObject(); // Create a wrapper object for the whole array
JsonArray use = Translator.toJson(replacement); // We get the json representation of the old color
// formatting method
ChatItem.debug("Remplacement: " + replacement + " use: " + use.toString());
// There's no public clone method for JSONObjects so we need to parse them every
// time
JsonObject hover = new JsonObject();
if (action.isItem()) {
hover.addProperty("action", "show_item");
// Get the JSON representation of the item (well, not really JSON, but rather a
// string representation of NBT data)
hover.addProperty("value", stringifyItem(action.getItem()));
} else {
hover.addProperty("action", "show_text");
// Get the JSON representation of the item (well, not really JSON, but rather a
// string representation of NBT data)
hover.addProperty("value", parseEmpty(json, replacement, Arrays.asList(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", chat.getItemPlayer().getPlayer().getName())), chat.getPlayer()));
JsonObject click = new JsonObject();
click.addProperty("action", "run_command");
click.addProperty("value", action.getCommand());
wrapper.add("clickEvent", click);
}
if (use.size() == 1) {
JsonElement extraElement = use.get(0);
if (extraElement.isJsonPrimitive())
wrapper.addProperty("text", extraElement.getAsString());
else if (extraElement.isJsonObject())
wrapper.addProperty("text", extraElement.getAsJsonObject().get("text").getAsString());
else
wrapper.add("extra", use); // add it only if
} else if (!use.isEmpty())
wrapper.add("extra", use); // add it only if
if (!wrapper.has("text"))
wrapper.addProperty("text", ""); // The text field is compulsory, even if it's empty
wrapper.add("hoverEvent", hover);
if (obj.size() == 1 && obj.has("text")) {
wrapper.add("text", obj.get("text"));
ChatItem.debug("[JsonManipulator] Parsed quick: " + obj.toString() + ", wrapper: " + wrapper);
return ChatManager.replaceSeparator(chat, wrapper.toString(), replacement);
}
obj.add("extra", parseArray(obj.has("extra") ? obj.getAsJsonArray("extra") : new JsonArray(), wrapper));
if (!obj.has("text")) {
obj.addProperty("text", "");
}
ChatItem.debug("Parsed array for item: " + obj.toString() + ", wrapper: " + wrapper);
return obj.toString();
}
public String parseEmpty(String json, String repl, List<String> tooltip, Player sender) {
JsonObject obj = JsonParser.parseString(json).getAsJsonObject();
JsonArray array = obj.has("extra") ? obj.getAsJsonArray("extra") : new JsonArray();
JsonArray use = Translator.toJson(repl.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName()));
JsonObject hover = JsonParser.parseString("{\"action\":\"show_text\", \"value\": \"\"}").getAsJsonObject();
StringBuilder oneLineTooltip = new StringBuilder("");
int index = 0;
for (String m : tooltip) {
oneLineTooltip.append(m.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName()));
++index;
if (index != tooltip.size()) {
oneLineTooltip.append('\n');
}
}
hover.add("value", new JsonPrimitive(oneLineTooltip.toString()));
if (!tooltip.isEmpty()) {
for (JsonElement ob : use)
ob.getAsJsonObject().add("hoverEvent", hover);
classicTooltip = use;
}
obj.add("extra", parseArray(array, classicTooltip));
if (!obj.has("text")) {
obj.addProperty("text", "");
}
return obj.toString();
}
private JsonArray parseArray(JsonArray arr, JsonElement tooltip) {
JsonArray replacer = new JsonArray();
boolean isComplex = false;
for (int i = 0; i < arr.size(); ++i) {
JsonElement element = arr.get(i);
if (element.isJsonNull()) {
continue;
} else if (element.isJsonObject()) {
isComplex = true;
addParsedJsonObjectToArray(element.getAsJsonObject(), replacer, tooltip);
} else if (element.isJsonArray()) {
isComplex = true;
JsonArray jar = element.getAsJsonArray();
if (jar.size() != 0) {
jar = parseArray(element.getAsJsonArray(), tooltip);
replacer.set(i, jar);
}
} else if (element.isJsonPrimitive() && isComplex) {
if(ChatManager.containsSeparator(element.getAsString())) {
addParsedStringToArray(element.getAsString(), replacer, element, tooltip);
} else
ChatItem.debug("[JSONManipulator] Put " + element + " to trash as it's primitive with complex things");
// ignore
} else {
addParsedStringToArray(element.getAsString(), replacer, element, tooltip);
}
}
return replacer;
}
private void addParsedJsonObjectToArray(JsonObject o, JsonArray rep, JsonElement tooltip) {
JsonElement text = o.get("text");
if (text == null) {
JsonElement el = o.get("extra");
if (el != null) {
JsonArray jar = el.getAsJsonArray();
if (jar.size() != 0) {
JsonArray tmpArray = parseArray(jar, tooltip);
if (!tmpArray.isEmpty())
o.add("extra", tmpArray);
else
o.remove("extra");
} else {
o.remove("extra");
}
}
return;
} else {
if (text.getAsString().isEmpty()) {
JsonElement el = o.get("extra");
if (el != null) {
JsonArray jar = el.getAsJsonArray();
if (!jar.isEmpty()) {
JsonArray tmpArray = parseArray(jar, tooltip);
if (!tmpArray.isEmpty())
o.add("extra", tmpArray);
else
o.remove("extra");
} else {
o.remove("extra");
}
}
}
}
addParsedStringToArray(text.getAsString(), rep, o, tooltip);
}
private void addParsedStringToArray(String msg, JsonArray rep, JsonElement o, JsonElement tooltip) {
ChatItem.debug("Checking " + msg + " > " + rep + ", o: " + o);
if (!ChatManager.containsSeparator(msg)) {
rep.add(o);
return;
}
String current = "";
boolean wasSep = false;
for (String parts : msg.split("")) {
if (ChatManager.equalsSeparator(parts)) {
if (!current.isEmpty()) {
rep.add(current);
current = "";
}
rep.add(tooltip);
wasSep = true;
} else if (wasSep) {
if (ChatManager.equalsSeparatorEnd(parts)) // sep finished
wasSep = false;
} else {
current += parts;
}
}
if (!current.isEmpty())
rep.add(current);
}
public static String stringifyItem(ItemStack is) {
try {
return stringifyItemInternal(is);
} catch (Exception e) {
e.printStackTrace();
return "{}";
}
}
@SuppressWarnings({ "deprecation" })
public static String stringifyItemInternal(ItemStack is) throws Exception {
Object nmsStack = JSONManipulator.AS_NMS_COPY.invoke(null, is);
Object nmsTag = JSONManipulator.NBT_TAG_COMPOUND.newInstance();
JSONManipulator.SAVE_NMS_ITEM_STACK_METHOD.invoke(nmsStack, nmsTag);
HashMap<String, String> tagMap = new HashMap<>();
Map<String, Object> nmsMap = (Map<String, Object>) JSONManipulator.MAP.get(nmsTag);
String id = nmsMap.get("id").toString().replace("\"", "");
Object realTag = nmsMap.get("tag");
if (JSONManipulator.NBT_TAG_COMPOUND.isInstance(realTag)) { // We need to make sure this is indeed an
// NBTTagCompound
Map<String, Object> realMap = (Map<String, Object>) JSONManipulator.MAP.get(realTag);
Set<Map.Entry<String, Object>> entrySet = realMap.entrySet();
for (Map.Entry<String, Object> entry : entrySet) {
tagMap.put(entry.getKey(), entry.getValue().toString());
}
}
// TODO check for ID remapping
// ItemRewriter.remapIds(Version.getVersion().MAX_VER, protocolVersion.MAX_VER,
// is);
StringBuilder sb = new StringBuilder("{id:");
sb.append("\"").append(id).append("\"").append(","); // Append the id
sb.append("Count:").append(is.getAmount()).append("b"); // Append the amount
if (!tagMap.containsKey("Damage")) { // for new versions
sb.append(",Damage:").append(is.getDurability()).append("s"); // Append the durability data
}
if (tagMap.isEmpty()) {
sb.append("}");
return sb.toString();
}
Set<Map.Entry<String, String>> entrySet = tagMap.entrySet();
boolean first = true;
sb.append(",tag:{"); // Start of the tag
for (Map.Entry<String, String> entry : entrySet) {
if (SKIPPED.contains(entry.getKey()))
continue;
if (!first)
sb.append(",");
first = false;
if (!entry.getKey().isEmpty()) {
if (entry.getKey().contains(";"))
sb.append("\"" + entry.getKey() + "\"");
else
sb.append(entry.getKey());
sb.append(":");
}
ChatItem.debug("Cleaning " + entry.getKey() + ": " + entry.getValue() + " > " + cleanStr(entry.getValue()));
sb.append(cleanStr(entry.getValue()));
}
sb.append("}}"); // End of tag and end of item
return sb.toString();
}
private static String cleanStr(String s) {
return s.startsWith("'") && s.endsWith("'") ? s.substring(1, s.length() - 1) : s;
}
}
@@ -0,0 +1,203 @@
package me.dadus33.chatitem.chatmanager.v1.json;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.utils.ColorManager;
import net.md_5.bungee.api.ChatColor;
//Based on DarkSeraphim's system, but using Gson and supporting some more edge cases
public class Translator {
private static final String STYLES = "klmnor"; //All style codes
public static JsonArray toJson(String old){
if(old.lastIndexOf(ChatColor.COLOR_CHAR) == -1){
JsonArray arr = new JsonArray();
JsonObject obj = new JsonObject();
obj.addProperty("text", old);
arr.add(obj);
return arr;
}
JsonArray message = new JsonArray();
JsonObject next = new JsonObject();
String colorCode = "", text = "";
boolean waiting = false;
for (char args : old.toCharArray()) {
if (args == '§') { // begin of color
if(!text.isEmpty()) {
next.addProperty("text", text);
message.add(next);
next = new JsonObject();
text = "";
}
waiting = true; // waiting for color code
} else if (waiting) { // if waiting for code and valid str
// if it's hexademical value and with enough space for full color
waiting = false;
if(isStyle(args)) { // is style and not making rich color code
next.addProperty(getStyleName(args), true);
continue;
}
if(args == 'x' && !colorCode.isEmpty()) {
if(!text.isEmpty()) // ignore this if no text before
text += ColorManager.getColorString(colorCode);
colorCode = "x";
} else
colorCode += args; // a color by itself
} else {
waiting = false;
if(!colorCode.isEmpty()) { // manage color
if(colorCode.startsWith("x") && colorCode.length() == 7) { // hex color code
next.addProperty("color", ColorManager.getColor(colorCode).getName());
} else if(colorCode.length() == 1) { // if only one color code
if(next.has("color"))
text += ColorManager.getColor(colorCode);
else
next.addProperty("color", ColorManager.getColor(colorCode).getName());
} else if(!text.isEmpty())// no text before -> color will be used as "color"
text += ColorManager.getColorString(colorCode);
ChatItem.debug("Add " + colorCode + " to " + text + ", msg: " + message);
colorCode = "";
}
// basic text, not waiting for code after '§'
text += args;
}
}
if(!text.isEmpty() || message.isEmpty()) {
next.addProperty("text", text);
if(!next.has("color"))
next.addProperty("color", "white");
message.add(next);
}
return message;
}
public static JsonArray toJsonOld(String old){
if(old.lastIndexOf(ChatColor.COLOR_CHAR) == -1){
JsonArray arr = new JsonArray();
JsonObject obj = new JsonObject();
obj.addProperty("text", old);
arr.add(obj);
return arr;
}
boolean startsWithCode = old.startsWith(Character.toString(ChatColor.COLOR_CHAR));
JsonArray message = new JsonArray();
String[] parts = old.split(Character.toString(ChatColor.COLOR_CHAR));
JsonObject next = null; //refers to the object we created before (in time) but next in the message, as we're going from end to start
for(int i = parts.length-1; i >= 0; --i){ //We go in reverse order
String part = parts[i];
if(part.isEmpty()){
continue;
}
if(i == 0 && !startsWithCode){
JsonObject toAdd = new JsonObject();
toAdd.addProperty("text", part);
message.add(toAdd);
break;
}
char code = Character.toLowerCase(part.charAt(0));
if(!isColorOrStyle(code)){
if(next != null){
String text = next.get("text").getAsString();
text = ChatColor.COLOR_CHAR + part + text;
next.addProperty("text", text);
}else{
JsonObject added = new JsonObject();
added.addProperty("text", ChatColor.COLOR_CHAR + part);
message.add(added);
next = added;
}
continue;
}
if(part.length() == 1){ //If it's just format and no text, we try to format the next element, if it wasn't formatted already (and it's not null)
if(next == null){
continue;
}
if(isStyle(code)){
next.addProperty(getStyleName(code), true);
}else{ //it's a color
if(isAlreadyColored(next)){
continue;
}
next.addProperty("color", getColorName(code));
}
continue;
}
//Last possibility that remains is that we have a normal color/format + text situation
JsonObject added = new JsonObject();
added.addProperty("text", part.substring(1));
if(isStyle(code)){
added.addProperty(getStyleName(code), true);
message.add(added);
next = added;
continue;
}
//else it can only be a color
added.addProperty("color", getColorName(code));
//also try to color the next element if not colored already
if(next != null){
if(!isAlreadyColored(next)){
next.addProperty("color", getColorName(code));
}
}
message.add(added);
next = added;
}
int i = message.size()-1;
JsonArray orderedMessage = new JsonArray();//This is where we'll store the reverted message (in proper order for being sent to the client)
//First we have to copy all elements
for(JsonElement el : message){
orderedMessage.add(el);
}
for(JsonElement element : message){
JsonObject obj = (JsonObject) element;
orderedMessage.set(i, obj); //And then we add the object to the properly ordered array
--i;
}
return orderedMessage;
}
private static String getColorName(char code){
return ChatColor.getByChar(code).getName().toLowerCase();
}
private static String getStyleName(char code){
switch(code){
case 'k': return "obfuscated";
case 'l': return "bold";
case 'm': return "strikethrough";
case 'n': return "underlined";
case 'o': return "italic";
case 'r': return "reset";
default:
ChatItem.getInstance().getLogger().severe("Can't find code for style " + code);
return null; //Should never happen. Made it return null to throw errors if a new format pops up and it really happens
}
}
private static boolean isColorOrStyle(char code){
return ChatColor.getByChar(code) != null;
}
private static boolean isStyle(char c){
return STYLES.indexOf(c) != -1;
}
private static boolean isAlreadyColored(JsonObject obj){
return obj.has("color");
}
}
@@ -0,0 +1,201 @@
package me.dadus33.chatitem.chatmanager.v1.listeners;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import org.bukkit.block.ShulkerBox;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.ItemMeta;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.ItemPlayer;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.chatmanager.Chat;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IComponentManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.AdventureComponentManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.ComponentNMSManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.PCMComponentManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.StringComponentManager;
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulator;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketHandler;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.Version;
public class ChatPacketManager extends PacketHandler {
private Object lastSentPacket = null;
private Method serializerGetJson;
private PacketEditingChatManager manager;
private final List<IComponentManager> componentManager = new ArrayList<>();
public ChatPacketManager(PacketEditingChatManager manager) {
this.manager = manager;
try {
for (Method m : PacketUtils.CHAT_SERIALIZER.getDeclaredMethods()) {
if (m.getParameterCount() == 1 && m.getParameterTypes()[0].equals(PacketUtils.COMPONENT_CLASS) && m.getReturnType().equals(String.class)) {
serializerGetJson = m;
break;
}
}
if (serializerGetJson == null)
ChatItem.getInstance().getLogger().warning("Failed to find JSON serializer in class: " + PacketUtils.CHAT_SERIALIZER.getCanonicalName());
} catch (Exception e) {
e.printStackTrace();
}
for (IComponentManager getter : Arrays.asList(new StringComponentManager(), new ComponentNMSManager(), new PCMComponentManager())) {
tryRegister(getter);
}
try {
Class.forName("net.kyori.adventure.text.Component");
tryRegister(new AdventureComponentManager());
} catch (Exception e) {}
ChatItem.getInstance().getLogger().info("Loaded " + componentManager.size() + " getter for base components.");
ChatItem.debug("ComponentManager: " + String.join(", ", componentManager.stream().map(IComponentManager::getClass).map(Class::getSimpleName).collect(Collectors.toList())));
}
private void tryRegister(IComponentManager getter) {
if (getter.hasConditions())
componentManager.add(getter);
else
ChatItem.debug("Component " + getter.getClass().getSimpleName() + " doesn't answer conditions");
}
@Override
public void onSend(ChatItemPacket e) {
if (!e.hasPlayer() || !e.getPacketType().equals(PacketType.Server.CHAT))
return;
if(ChatManager.isTestingEnabled() && !ChatManager.isTesting("packet"))
return;
if (lastSentPacket != null && lastSentPacket == e.getPacket())
return; // prevent infinite loop
ChatItem.debug("Checking: " + e.getPacket().getClass().getSimpleName() + " to " + e.getPlayername());
PacketContent packet = e.getContent();
Version version = Version.getVersion();
String json = "{}";
IComponentManager choosedGetter = null;
if (version.isNewerOrEquals(Version.V1_19)) {
/*if (packet.getIntegers().readSafely(0, 0) > 1) { // not parsed chat message type
ChatItem.debug("Invalid int: " + packet.getIntegers().read(0));
return;
}*/
choosedGetter = new StringComponentManager();
json = choosedGetter.getBaseComponentAsJSON(e); // if null, will be re-checked so anyway
} else if (version.isNewerOrEquals(Version.V1_12)) {
// only if action bar messages are supported
if (((Enum<?>) packet.getSpecificModifier(PacketUtils.getNmsClass("ChatMessageType", "network.chat.")).read(0)).name().equals("GAME_INFO"))
return; // It's an actionbar message, ignoring
} else if (version.isNewerOrEquals(Version.V1_8) && packet.getBytes().readSafely(0) == (byte) 2)
return; // It's an actionbar message, ignoring
if (json == null || choosedGetter == null) {
for (IComponentManager getters : componentManager) {
String tmpJson = getters.getBaseComponentAsJSON(e);
if (tmpJson != null) {
json = ChatManager.fixSeparator(tmpJson);
choosedGetter = getters;
if (ChatManager.containsSeparator(json))
break; // be sure it's valid one
} else
ChatItem.debug("Null JSON for manager " + getters.getClass().getSimpleName());
}
}
if (json == null || choosedGetter == null) {
ChatItem.debug("Can't find valid json getter or json itself");
ChatItem.debug("String: " + packet.getStrings().getContent());
PacketUtils.printPacketToDebug(e.getPacket());
return; // can't find something
}
if (!ChatManager.containsSeparator(json)) // if the message doesn't contain the BELL separator
return;
ChatItem.debug("Found with " + choosedGetter.getClass().getName());
Chat chat = choosedGetter.getChat(json);
if (chat == null) { // something went really bad, so we run away and hide (AKA the player left or is
// on another server)
ChatItem.debug("Chat null for " + json);
return;
}
Player itemPlayer = chat.getPlayer();
if (getStorage().cooldown > 0 && !itemPlayer.hasPermission("chatitem.ignore-cooldown"))
ChatManager.applyCooldown(itemPlayer);
IComponentManager getter = choosedGetter;
String fjson = json;
ChatItem.debug("Final json used: " + fjson);
e.setCancelled(true); // We cancel the packet as we're going to resends it anyways
CompletableFuture.runAsync(() -> {
Player p = e.getPlayer();
String message = null;
try {
ItemStack item = ChatManager.getUsableItem(itemPlayer, chat.getSlot());
if (!ItemUtils.isEmpty(item)) {
ItemStack copy = item.clone();
if (ItemPlayer.getPlayer(p).isBuggedClient()) { // if the guy that will receive it is bugged
String act = getStorage().buggedClientAction;
List<String> tooltip;
if (act.equalsIgnoreCase("tooltip"))
tooltip = getStorage().tooltipBuggedClient;
else if (act.equalsIgnoreCase("item"))
tooltip = ChatManager.getMaxLinesFromItem(p, copy);
else if (act.equalsIgnoreCase("show_both")) {
tooltip = ChatManager.getMaxLinesFromItem(p, copy);
tooltip.addAll(getStorage().tooltipBuggedClient);
} else
tooltip = new ArrayList<>();
message = JSONManipulator.getInstance().parseEmpty(getter.getBaseComponentAsJSON(e), ChatManager.styleItem(p, copy, getStorage()), tooltip, chat.getPlayer());
if(message != null) {
getter.writeJson(e, message);
}
lastSentPacket = e.getPacket();
}
if (copy.hasItemMeta()) {
ItemMeta meta = copy.getItemMeta();
if (meta instanceof BookMeta) { // filtering written books
BookMeta bm = (BookMeta) copy.getItemMeta();
bm.setPages(Collections.emptyList());
copy.setItemMeta(bm);
} else if (meta instanceof BlockStateMeta && Version.getVersion().isNewerOrEquals(Version.V1_9)) { // if it's a block
BlockStateMeta bsm = (BlockStateMeta) copy.getItemMeta();
if (bsm.hasBlockState() && bsm.getBlockState() instanceof ShulkerBox) {
ShulkerBox sb = (ShulkerBox) bsm.getBlockState();
for (ItemStack itemInv : sb.getInventory()) {
ItemUtils.stripData(itemInv);
}
bsm.setBlockState(sb);
}
copy.setItemMeta(bsm);
}
}
lastSentPacket = getter.manageItem(p, chat, e, item, fjson, getStorage());
} else {
if (!getStorage().handDisabled) {
lastSentPacket = getter.manageEmpty(p, chat, e, fjson, getStorage());
}
}
if (lastSentPacket == null) // maybe sent by the manager directly
ChatItem.debug("(v1) No packet to sent with manager " + getter.getClass().getName());
else
PacketUtils.sendPacket(p, lastSentPacket);
} catch (Exception e1) {
e1.printStackTrace();
}
});
}
public Storage getStorage() {
return manager.getStorage();
}
}
@@ -0,0 +1,57 @@
package me.dadus33.chatitem.chatmanager.v1.packets;
import org.bukkit.entity.Player;
public class ChatItemPacket {
protected final Player player;
protected Object packet;
protected PacketType type;
protected boolean cancel = false;
public ChatItemPacket(PacketType type, Object packet, Player player) {
this.player = player;
this.packet = packet;
this.type = type;
}
public Player getPlayer() {
return player;
}
public boolean hasPlayer() {
return player != null;
}
public String getPlayername() {
return getPlayer().getName();
}
public Object getPacket() {
return packet;
}
public void setPacket(Object packet) {
this.packet = packet;
}
public String getPacketName() {
return packet.getClass().getSimpleName();
}
public PacketType getPacketType() {
return type;
}
public boolean isCancelled() {
return cancel;
}
public void setCancelled(boolean cancel) {
this.cancel = cancel;
}
public PacketContent getContent() {
return new PacketContent(this);
}
}
@@ -0,0 +1,46 @@
package me.dadus33.chatitem.chatmanager.v1.packets;
import java.util.Arrays;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
import me.dadus33.chatitem.chatmanager.v1.packets.protocollib.ProtocollibPacketManager;
public class ChatItemPacketManager {
private PacketManager packetManager;
public ChatItemPacketManager(ChatItem pl) {
Plugin protocolLibPlugin = Bukkit.getPluginManager().getPlugin("ProtocolLib");
if (protocolLibPlugin != null) {
if(checkProtocollibConditions()) {
pl.getLogger().info("The plugin ProtocolLib has been detected. Loading Protocollib support ...");
packetManager = new ProtocollibPacketManager(pl);
} else {
pl.getLogger().warning("The plugin ProtocolLib has been detected but you have an old or too new version, so we cannot use it.");
pl.getLogger().warning("Fallback to default Packet system ...");
packetManager = new CustomPacketManager(pl);
}
} else {
pl.getLogger().info("Loading own packet system.");
packetManager = new CustomPacketManager(pl);
}
}
public PacketManager getPacketManager() {
return packetManager;
}
private boolean checkProtocollibConditions() {
for(String searchedClass : Arrays.asList("com.comphenix.protocol.injector.server.TemporaryPlayer", "com.comphenix.protocol.injector.temporary.TemporaryPlayer")) { // class since 4.4.0 until 4.8.0, then the new one
try {
Class.forName(searchedClass);
return true; // class found
} catch (ClassNotFoundException e) {}
}
return false;
}
}
@@ -0,0 +1,210 @@
package me.dadus33.chatitem.chatmanager.v1.packets;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.stream.Collectors;
import me.dadus33.chatitem.utils.PacketUtils;
public class PacketContent {
private final ChatItemPacket packet;
private final Object obj;
/**
* Create a PacketContent to easily read and write value in it
*
* @param packet the Negativity's packet
*/
public PacketContent(ChatItemPacket packet) {
this.packet = packet;
this.obj = packet.getPacket();
}
/**
* Create a PacketContent to easily read and write to the specified object
*
* @param obj the object that will be read or edit
*/
public PacketContent(Object obj) {
this.packet = null;
this.obj = obj;
}
public ChatItemPacket getPacket() {
return packet;
}
public <T> ContentModifier<T> getSpecificModifier(T type){
return new ContentModifier<T>(obj, type.getClass());
}
public <T> ContentModifier<T> getSpecificModifier(Class<T> clazz){
return new ContentModifier<T>(obj, clazz);
}
public ContentModifier<String> getStrings(){
return new ContentModifier<String>(obj, String.class);
}
public ContentModifier<Byte> getBytes(){
return new ContentModifier<Byte>(obj, byte.class);
}
public ContentModifier<Boolean> getBooleans(){
return new ContentModifier<Boolean>(obj, boolean.class);
}
public ContentModifier<Integer> getIntegers(){
return new ContentModifier<Integer>(obj, int.class);
}
public ContentModifier<byte[]> getByteArrays(){
return new ContentModifier<byte[]>(obj, byte[].class);
}
public ContentModifier<Object> getChatComponents() {
return (ContentModifier<Object>) getSpecificModifier(PacketUtils.COMPONENT_CLASS);
}
public static class ContentModifier<T> {
private Object obj;
private HashMap<Field, T> content = new HashMap<>();
public ContentModifier(Object obj, Class<?> clazz) {
this.obj = obj;
for(Field f : obj.getClass().getDeclaredFields()) {
try {
if(f.getType().isAssignableFrom(clazz)) {
f.setAccessible(true);
content.put(f, (T) f.get(obj));
}
} catch (Exception e) {
e.printStackTrace();
}
}
if(!obj.getClass().getSuperclass().equals(Object.class)) {
for(Field f : obj.getClass().getSuperclass().getDeclaredFields()) {
try {
if(f.getType().isAssignableFrom(clazz)) {
f.setAccessible(true);
content.put(f, (T) f.get(obj));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public Object getObj() {
return obj;
}
/**
* Get the size of the Map of content
*
* @return the number of content
*/
public int size() {
return content.size();
}
/**
* Get the value of the field which is named by the given one
*
* @param fieldName the name of the needed field
* @return the value of the field
*/
public T read(String fieldName) {
for(Field field : content.keySet())
if(field.getName().equalsIgnoreCase(fieldName))
return content.get(field);
return null;
}
/**
* Get the value of the field which is named by the given one
*
* @param fieldName the name of the needed field
* @param defaultValue the returned value if there is no value
* @return the value of the field
*/
public T read(String fieldName, T defaultValue) {
for(Field field : content.keySet())
if(field.getName().equalsIgnoreCase(fieldName))
return content.get(field);
return defaultValue;
}
/**
* Read the specified value.
*
* @param i the number of the value to get getted. Start at 0.
* @return the requested value.
*
* @throws NoSuchElementException if the value doesn't exist
*/
public T read(int i) {
return content.values().stream().filter(Objects::nonNull).collect(Collectors.toList()).get(i);
}
/**
* Read the specified value.
*
* @param i the number of the value to get getted. Start at 0.
* @return the requested value, or null if it doesn't exist.
*/
public T readSafely(int i) {
return readSafely(i, null);
}
/**
* Read the specified value.
*
* @param i the number of the value to get getted. Start at 0.
* @param defaultValue the value which is return if the key doesn't exist
* @return the requested value.
*/
public T readSafely(int i, T defaultValue) {
List<T> vals = content.values().stream().filter(Objects::nonNull).collect(Collectors.toList());
return vals.size() <= i ? defaultValue : vals.get(i);
}
/**
* Set the value in the specified object.
*
* @param i the key of the value to set
* @param value the new value which will be set
*/
public void write(int i, T value) {
Field key = content.keySet().toArray(new Field[] {})[i];
if(key == null) {
new NoSuchFieldException("Not enough value in " + obj.getClass() + ".").printStackTrace();
} else {
content.put(key, value);
try {
key.setAccessible(true);
key.set(obj, value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Get field which her value
*
* @return all content
*/
public HashMap<Field, T> getContent(){
return content;
}
}
}
@@ -0,0 +1,7 @@
package me.dadus33.chatitem.chatmanager.v1.packets;
public abstract class PacketHandler {
public void onReceive(ChatItemPacket packet) {}
public void onSend(ChatItemPacket packet) {}
}
@@ -0,0 +1,25 @@
package me.dadus33.chatitem.chatmanager.v1.packets;
import java.util.ArrayList;
import org.bukkit.entity.Player;
public abstract class PacketManager {
public void addPlayer(Player p) {}
public void removePlayer(Player p) {}
public abstract void stop();
private final ArrayList<PacketHandler> handlers = new ArrayList<>();
public boolean addHandler(PacketHandler handler) {
return !handlers.add(handler);
}
public boolean removeHandler(PacketHandler handler) {
return handlers.remove(handler);
}
public void notifyHandlersSent(ChatItemPacket packet) {
handlers.forEach((handler) -> handler.onSend(packet));
}
}
@@ -0,0 +1,106 @@
package me.dadus33.chatitem.chatmanager.v1.packets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public interface PacketType {
String name();
String getPacketName();
String getFullName();
List<String> getAlias();
public static List<PacketType> values() {
List<PacketType> list = new ArrayList<>();
list.addAll(Arrays.asList(Server.values()));
list.addAll(Arrays.asList(Handshake.values()));
return list;
}
static final String SERVER_PREFIX = "PacketPlayOut", HANDSHAKE_PREFIX = "PacketHandshaking";
public static PacketType getType(String packetName) {
if(packetName.startsWith(SERVER_PREFIX)) {
return getPacketTypeFor(packetName, Server.values(), Server.UNSET);
} else if(packetName.startsWith(HANDSHAKE_PREFIX)) {
return getPacketTypeFor(packetName, Handshake.values(), Handshake.UNSET);
} else {
for(PacketType types : values()) {
if(types.getFullName().equalsIgnoreCase(packetName) || types.getAlias().contains(packetName))
return types;
}
return null;
}
}
static PacketType getPacketTypeFor(String packetName, PacketType[] types, PacketType unset) {
for(PacketType packet : types)
if(packet.getFullName().equalsIgnoreCase(packetName) || packet.getPacketName().equalsIgnoreCase(packetName) || packet.getAlias().contains(packetName))
return packet;
return unset;
}
public static enum Server implements PacketType {
CHAT("Chat", "ClientboundPlayerChatPacket", "ClientboundSystemChatPacket"),
UNSET("Unset");
private final String packetName, fullName;
private List<String> alias = new ArrayList<>();
private Server(String packetName, String... alias) {
this.packetName = packetName;
this.fullName = SERVER_PREFIX + packetName;
for(String al : alias)
this.alias.add(al);
}
@Override
public String getPacketName() {
return packetName;
}
@Override
public String getFullName() {
return fullName;
}
@Override
public List<String> getAlias() {
return alias;
}
}
public static enum Handshake implements PacketType {
IS_SET_PROTOCOL("InSetProtocol"),
UNSET("Unset");
private final String packetName, fullName;
private List<String> alias = new ArrayList<>();
private Handshake(String packetName, String... alias) {
this.packetName = packetName;
for(String al : alias)
this.alias.add(HANDSHAKE_PREFIX + al);
this.fullName = HANDSHAKE_PREFIX + packetName;
}
@Override
public String getPacketName() {
return packetName;
}
@Override
public String getFullName() {
return fullName;
}
@Override
public List<String> getAlias() {
return alias;
}
}
}
@@ -0,0 +1,92 @@
package me.dadus33.chatitem.chatmanager.v1.packets.custom;
import java.util.HashMap;
import java.util.concurrent.CompletableFuture;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.Plugin;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketManager;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.channel.ChannelAbstract;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.channel.INC2Channel;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.channel.INCChannel;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.channel.NMUChannel;
import me.dadus33.chatitem.utils.Utils;
import me.dadus33.chatitem.utils.Version;
public class CustomPacketManager extends PacketManager implements Listener {
private ChannelAbstract channel;
private Plugin pl;
public HashMap<Object, Integer> protocolVersionPerChannel = new HashMap<>();
private boolean isStarted = false;
public CustomPacketManager(Plugin pl) {
this.pl = pl;
Version version = Version.getVersion();
if (version.isNewerOrEquals(Version.V1_17))
channel = new INC2Channel(this);
else if (version.equals(Version.V1_7))
channel = new NMUChannel(this);
else
channel = new INCChannel(this);
pl.getServer().getPluginManager().registerEvents(this, pl);
// we wait the start server
CompletableFuture.runAsync(() -> {
isStarted = true;
for(Player p : Utils.getOnlinePlayers())
addPlayer(p);
});
}
public Plugin getPlugin() {
return pl;
}
@EventHandler
public void onJoin(PlayerJoinEvent e) {
addPlayer(e.getPlayer());
}
@EventHandler
public void onQuit(PlayerQuitEvent e) {
removePlayer(e.getPlayer());
}
@Override
public void addPlayer(Player p) {
if(isStarted)
channel.addPlayer(p);
}
@Override
public void removePlayer(Player p) {
channel.removePlayer(p);
}
@Override
public void stop() {
for(Player player : Utils.getOnlinePlayers())
removePlayer(player);
if(channel.getAddChannelExecutor() != null)
channel.getAddChannelExecutor().shutdownNow();
if(channel.getRemoveChannelExecutor() != null)
channel.getRemoveChannelExecutor().shutdownNow();
}
public ChatItemPacket onPacketSent(PacketType type, Player sender, Object packet) {
if(type == null) {
return null;
}
ChatItemPacket customPacket = new ChatItemPacket(type, packet, sender);
notifyHandlersSent(customPacket);
return customPacket;
}
}
@@ -0,0 +1,86 @@
package me.dadus33.chatitem.chatmanager.v1.packets.custom.channel;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.ItemPlayer;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
public abstract class ChannelAbstract {
private ExecutorService addChannelExecutor, removeChannelExecutor;
static final String KEY_HANDSHAKE = "packet_handshake_chatitem", KEY_HANDLER_SERVER = "packet_handler", KEY_SERVER = "packet_server_chatitem";
private CustomPacketManager customPacketManager;
private HashSet<UUID> players = new HashSet<>();
protected ChannelAbstract(CustomPacketManager customPacketManager) {
this.customPacketManager = customPacketManager;
}
public CustomPacketManager getPacketManager() {
return customPacketManager;
}
public ExecutorService getAddChannelExecutor() {
return addChannelExecutor;
}
public ExecutorService getOrCreateAddChannelExecutor() {
if(addChannelExecutor == null || addChannelExecutor.isTerminated())
addChannelExecutor = Executors.newSingleThreadExecutor();
return addChannelExecutor;
}
public ExecutorService getRemoveChannelExecutor() {
return removeChannelExecutor;
}
public ExecutorService getOrCreateRemoveChannelExecutor() {
if(removeChannelExecutor == null || removeChannelExecutor.isTerminated())
removeChannelExecutor = Executors.newSingleThreadExecutor();
return removeChannelExecutor;
}
public void addPlayer(Player p) {
if(players.add(p.getUniqueId())) {
addChannel(p, p.getUniqueId().toString());
try {
Integer protocol = customPacketManager.protocolVersionPerChannel.remove(getChannel(p));
if(protocol != null)
ItemPlayer.getPlayer(p).setProtocolVersion(protocol);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void removePlayer(Player p) {
if(players.remove(p.getUniqueId()))
removeChannel(p, p.getUniqueId().toString());
}
public void removeAllPlayers() {
new ArrayList<>(players).forEach((uuid) -> {
Player p = Bukkit.getPlayer(uuid);
if(p != null) // player don't left
removeChannel(Bukkit.getPlayer(uuid), uuid.toString());
});
players.clear();
}
protected abstract void stopPipelines();
public abstract void addChannel(Player player, String endChannelName);
public abstract void removeChannel(Player player, String endChannelName);
public abstract Object getChannel(Player p) throws Exception;
}
@@ -0,0 +1,92 @@
package me.dadus33.chatitem.chatmanager.v1.packets.custom.channel;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent.ContentModifier;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
public class ChannelInboundHandler extends ChannelInboundHandlerAdapter {
private CustomPacketManager packetManager;
private List<ChannelPipeline> pipelines = new ArrayList<>();
public ChannelInboundHandler(CustomPacketManager packetManager) {
this.packetManager = packetManager;
}
public void clean() {
pipelines.forEach(ChannelPipeline::removeFirst);
pipelines.clear();
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.fireChannelRead(msg);
ChannelPipeline pipe = ((Channel) msg).pipeline();
pipelines.add(pipe);
pipe.addFirst(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) {
try {
channel.eventLoop().submit(() -> {
try {
ChannelHandler interceptor = channel.pipeline().get(ChannelAbstract.KEY_HANDSHAKE);
// Inject our packet interceptor
if (interceptor == null) {
interceptor = new ChannelHandlerHandshakeReceive(channel);
channel.pipeline().addBefore("packet_handler", ChannelAbstract.KEY_HANDSHAKE, interceptor);
}
return interceptor;
} catch (IllegalArgumentException e) {
// Try again
return channel.pipeline().get(ChannelAbstract.KEY_HANDSHAKE);
}
});
} catch (Exception e) {
packetManager.getPlugin().getLogger().log(Level.SEVERE, "Cannot inject incoming channel " + channel, e);
}
}
});
}
public class ChannelHandlerHandshakeReceive extends ChannelInboundHandlerAdapter {
private Channel channel;
public ChannelHandlerHandshakeReceive(Channel channel) {
this.channel = channel;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object packet) {
try {
PacketType packetType = PacketType.getType(packet.getClass().getSimpleName());
if(packetType != null && packetType == PacketType.Handshake.IS_SET_PROTOCOL) {
ContentModifier<Integer> ints = new PacketContent(packet).getIntegers();
int possibleProtocol = ints.readSafely(0, 0);
if(possibleProtocol == Bukkit.getPort())
possibleProtocol = ints.readSafely(1, 0);
if(possibleProtocol == -1 || possibleProtocol == 255)
possibleProtocol = ints.readSafely(2, 0);
packetManager.protocolVersionPerChannel.put(channel, possibleProtocol);
}
super.channelRead(ctx, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@@ -0,0 +1,110 @@
package me.dadus33.chatitem.chatmanager.v1.packets.custom.channel;
import static me.dadus33.chatitem.utils.PacketUtils.getPlayerConnection;
import java.util.List;
import java.util.NoSuchElementException;
import org.bukkit.entity.Player;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
import me.dadus33.chatitem.utils.Version;
public class INC2Channel extends ChannelAbstract {
private final ChannelInboundHandler boundHandler;
private ChannelPipeline pipeline;
public INC2Channel(CustomPacketManager customPacketManager) {
super(customPacketManager);
boundHandler = new ChannelInboundHandler(customPacketManager);
try {
Object mcServer = ReflectionUtils.callMethod(PacketUtils.getCraftServer(), Version.getVersion().equals(Version.V1_17) ? "getServer" : "b");
Object co = ReflectionUtils.getFirstWith(mcServer, PacketUtils.getNmsClass("MinecraftServer", "server."), PacketUtils.getNmsClass("ServerConnection", "server.network."));
((List<ChannelFuture>) ReflectionUtils.getObject(co, "f")).forEach((channelFuture) -> {
pipeline = channelFuture.channel().pipeline();
pipeline.addFirst(boundHandler);
});
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void stopPipelines() {
pipeline.remove(boundHandler);
boundHandler.clean();
}
@Override
public void addChannel(final Player player, String endChannelName) {
getOrCreateAddChannelExecutor().execute(() -> {
if(!player.isOnline())
return;
try {
Channel channel = getChannel(player);
// Managing outgoing packet (to the player)
channel.pipeline().addAfter(KEY_HANDLER_SERVER, KEY_SERVER + endChannelName, new ChannelHandlerSent(player));
} catch (NoSuchElementException e) {
// appear when the player's channel isn't accessible because of reload.
getPacketManager().getPlugin().getLogger().warning("Please, don't use reload, this can produce some problem. Currently, " + player.getName() + " isn't fully checked because of that. More details: " + e.getMessage() + " (NoSuchElementException)");
} catch (IllegalArgumentException e) {
if(e.getMessage().contains("Duplicate handler")) {
removeChannel(player, endChannelName);
addChannel(player, endChannelName);
} else
getPacketManager().getPlugin().getLogger().severe("Error while loading Packet channel. " + e.getMessage() + ". Please, prefer restart than reload.");
} catch (Exception e) {
e.printStackTrace();
}
});
}
@Override
public void removeChannel(Player player, String endChannelName) {
getOrCreateRemoveChannelExecutor().execute(() -> {
try {
final Channel channel = getChannel(player);
if(channel.pipeline().get(KEY_SERVER + endChannelName) != null)
channel.pipeline().remove(KEY_SERVER + endChannelName);
} catch (Exception e) {
ChatItem.getInstance().getLogger().warning("Failed to remove channel for " + player.getName() + ". Reason: " + e.getMessage() + " (" + e.getStackTrace()[0].toString() + ")");
}
});
}
@Override
public Channel getChannel(Player p) throws Exception {
Object playerConnection = getPlayerConnection(p);
Object networkManager = ReflectionUtils.getFirstWith(playerConnection, PacketUtils.getNmsClass("NetworkManager", "network."));
return ReflectionUtils.getFirstWith(networkManager, Channel.class);
}
private class ChannelHandlerSent extends ChannelOutboundHandlerAdapter {
private final Player owner;
public ChannelHandlerSent(Player player) {
this.owner = player;
}
@Override
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
ChatItemPacket nextPacket = getPacketManager().onPacketSent(PacketType.getType(packet.getClass().getSimpleName()), owner, packet);
if(nextPacket != null && nextPacket.isCancelled())
return;
super.write(ctx, nextPacket == null ? packet : nextPacket.getPacket(), promise);
}
}
}
@@ -0,0 +1,122 @@
package me.dadus33.chatitem.chatmanager.v1.packets.custom.channel;
import static me.dadus33.chatitem.utils.PacketUtils.getPlayerConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import org.bukkit.entity.Player;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
public class INCChannel extends ChannelAbstract {
private final ChannelInboundHandler boundHandler;
private ChannelPipeline pipeline;
public INCChannel(CustomPacketManager customPacketManager) {
super(customPacketManager);
boundHandler = new ChannelInboundHandler(customPacketManager);
getFuturChannel().forEach((channelFuture) -> {
pipeline = channelFuture.channel().pipeline();
pipeline.addFirst(boundHandler);
});
}
public List<ChannelFuture> getFuturChannel() {
try {
Object dedicatedSrv = PacketUtils.getCraftServer();
Object mcServer = dedicatedSrv.getClass().getMethod("getServer").invoke(dedicatedSrv);
Object co = ReflectionUtils.getFirstWith(mcServer, PacketUtils.getNmsClass("MinecraftServer", "server."), PacketUtils.getNmsClass("ServerConnection", "network."));
try {
return (List<ChannelFuture>) ReflectionUtils.getPrivateField(co, "g");
} catch (NoSuchFieldException e) {
return (List<ChannelFuture>) ReflectionUtils.getPrivateField(co, "listeningChannels");
}
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<>();
}
}
@Override
protected void stopPipelines() {
pipeline.remove(boundHandler);
boundHandler.clean();
}
@Override
public void addChannel(final Player player, String endChannelName) {
getOrCreateAddChannelExecutor().execute(() -> {
if(!player.isOnline())
return;
try {
Channel channel = getChannel(player);
// Managing outgoing packet (to the player)
channel.pipeline().addAfter(KEY_HANDLER_SERVER, KEY_SERVER + endChannelName, new ChannelHandlerSent(player));
} catch (NoSuchElementException e) {
// appear when the player's channel isn't accessible because of reload.
getPacketManager().getPlugin().getLogger().warning("Please, don't use reload, this can produce some problem. Currently, " + player.getName() + " isn't fully checked because of that. More details: " + e.getMessage() + " (NoSuchElementException)");
} catch (IllegalArgumentException e) {
if(e.getMessage().contains("Duplicate handler")) {
removeChannel(player, endChannelName);
addChannel(player, endChannelName);
} else
getPacketManager().getPlugin().getLogger().severe("Error while loading Packet channel. " + e.getMessage() + ". Please, prefer restart than reload.");
} catch (Exception e) {
e.printStackTrace();
}
});
}
@Override
public void removeChannel(Player player, String endChannelName) {
getOrCreateRemoveChannelExecutor().execute(() -> {
try {
final Channel channel = getChannel(player);
if(channel.pipeline().get(KEY_SERVER + endChannelName) != null)
channel.pipeline().remove(KEY_SERVER + endChannelName);
} catch (Exception e) {
ChatItem.getInstance().getLogger().warning("Failed to remove channel for " + player.getName() + ". Reason: " + e.getMessage() + " (" + e.getStackTrace()[0].toString() + ")");
}
});
}
@Override
public Channel getChannel(Player p) throws Exception {
Object playerConnection = getPlayerConnection(p);
Object networkManager = playerConnection.getClass().getField("networkManager").get(playerConnection);
return new PacketContent(networkManager).getSpecificModifier(Channel.class).readSafely(0);//(Channel) networkManager.getClass().getDeclaredField("channel").get(networkManager);
}
private class ChannelHandlerSent extends ChannelOutboundHandlerAdapter {
private final Player owner;
public ChannelHandlerSent(Player player) {
this.owner = player;
}
@Override
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
ChatItemPacket nextPacket = getPacketManager().onPacketSent(PacketType.getType(packet.getClass().getSimpleName()), owner, packet);
if(nextPacket != null && nextPacket.isCancelled())
return;
super.write(ctx, nextPacket == null ? packet : nextPacket.getPacket(), promise);
}
}
}
@@ -0,0 +1,166 @@
package me.dadus33.chatitem.chatmanager.v1.packets.custom.channel;
import static me.dadus33.chatitem.utils.PacketUtils.getPlayerConnection;
import java.lang.reflect.Field;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.logging.Level;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
import net.minecraft.util.io.netty.channel.Channel;
import net.minecraft.util.io.netty.channel.ChannelFuture;
import net.minecraft.util.io.netty.channel.ChannelHandler;
import net.minecraft.util.io.netty.channel.ChannelHandlerContext;
import net.minecraft.util.io.netty.channel.ChannelInboundHandlerAdapter;
import net.minecraft.util.io.netty.channel.ChannelInitializer;
import net.minecraft.util.io.netty.channel.ChannelOutboundHandlerAdapter;
import net.minecraft.util.io.netty.channel.ChannelPipeline;
import net.minecraft.util.io.netty.channel.ChannelPromise;
public class NMUChannel extends ChannelAbstract {
private ChannelInboundHandlerAdapter boundHandler;
private ChannelPipeline pipeline;
public NMUChannel(CustomPacketManager customPacketManager) {
super(customPacketManager);
try {
Object dedicatedSrv = PacketUtils.getCraftServer();
Object mcServer = dedicatedSrv.getClass().getMethod("getServer").invoke(dedicatedSrv);
Object co = ReflectionUtils.getFirstWith(mcServer, PacketUtils.getNmsClass("MinecraftServer", "server."), PacketUtils.getNmsClass("ServerConnection", "network."));
List<ChannelFuture> g = (List<ChannelFuture>) ReflectionUtils.getObject(co, "g", "e");
g.forEach((channelFuture) -> {
pipeline = channelFuture.channel().pipeline();
pipeline.addFirst(boundHandler = new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
((Channel) msg).pipeline().addFirst(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) {
try {
channel.eventLoop().submit(() -> {
try {
ChannelHandler interceptor = channel.pipeline().get(KEY_HANDSHAKE);
// Inject our packet interceptor
if (interceptor == null) {
interceptor = new ChannelHandlerHandshakeReceive(channel);
channel.pipeline().addBefore("packet_handler", KEY_HANDSHAKE, interceptor);
}
return interceptor;
} catch (IllegalArgumentException e) {
// Try again
return channel.pipeline().get(KEY_HANDSHAKE);
}
});
} catch (Exception e) {
getPacketManager().getPlugin().getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e);
}
}
});
ctx.fireChannelRead(msg);
}
});
});
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void stopPipelines() {
pipeline.remove(boundHandler);
}
@Override
public void addChannel(final Player player, String endChannelName) {
getOrCreateAddChannelExecutor().execute(() -> {
try {
Channel channel = getChannel(player);
// Managing outgoing packet (to the player)
channel.pipeline().addAfter(KEY_HANDLER_SERVER, KEY_SERVER + endChannelName, new ChannelHandlerSent(player));
} catch (NoSuchElementException e) {
// appear when the player's channel isn't accessible because of reload.
getPacketManager().getPlugin().getLogger().warning("Please, don't use reload, this can produce some problem. Currently, " + player.getName() + " isn't fully checked because of that. More details: " + e.getMessage() + " (NoSuchElementException)");
} catch (IllegalArgumentException e) {
if(e.getMessage().contains("Duplicate")) {
removeChannel(player, endChannelName);
addChannel(player, endChannelName);
} else
getPacketManager().getPlugin().getLogger().severe("Error while loading Packet channel. " + e.getMessage() + ". Please, prefer restart than reload.");
} catch (Exception e) {
e.printStackTrace();
}
});
}
@Override
public void removeChannel(Player player, String endChannelName) {
getOrCreateRemoveChannelExecutor().execute(() -> {
try {
final Channel channel = getChannel(player);
if(channel.pipeline().get(KEY_SERVER + endChannelName) != null)
channel.pipeline().remove(KEY_SERVER + endChannelName);
} catch (Exception e) {}
});
}
@Override
public Channel getChannel(Player p) throws Exception {
Object playerConnection = getPlayerConnection(p);
Object networkManager = playerConnection.getClass().getField("networkManager").get(playerConnection);
for (Field field : networkManager.getClass().getDeclaredFields())
if (field.getType().equals(Channel.class)) {
field.setAccessible(true);
return (Channel) field.get(networkManager);
}
return null;
}
private class ChannelHandlerSent extends ChannelOutboundHandlerAdapter {
private final Player owner;
public ChannelHandlerSent(Player player) {
this.owner = player;
}
@Override
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
ChatItemPacket nextPacket = getPacketManager().onPacketSent(PacketType.getType(packet.getClass().getSimpleName()), owner, packet);
if(nextPacket != null && nextPacket.isCancelled())
return;
super.write(ctx, nextPacket == null ? packet : nextPacket.getPacket(), promise);
}
}
private class ChannelHandlerHandshakeReceive extends ChannelInboundHandlerAdapter {
private final Channel channel;
public ChannelHandlerHandshakeReceive(Channel channel) {
this.channel = channel;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object packet) {
try {
PacketType packetType = PacketType.getType(packet.getClass().getSimpleName());
if(packetType != null && packetType == PacketType.Handshake.IS_SET_PROTOCOL) {
getPacketManager().protocolVersionPerChannel.put(channel, new PacketContent(packet).getIntegers().readSafely(1, 0));
}
super.channelRead(ctx, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@@ -0,0 +1,62 @@
package me.dadus33.chatitem.chatmanager.v1.packets.protocollib;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.entity.Player;
import com.comphenix.protocol.PacketType.Play;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketManager;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
public class ProtocollibPacketManager extends PacketManager {
private final ProtocolManager protocolManager;
public ProtocollibPacketManager(ChatItem pl) {
protocolManager = ProtocolLibrary.getProtocolManager();
List<com.comphenix.protocol.PacketType> list = new ArrayList<>();
list.add(Play.Server.CHAT);
try {
list.add((com.comphenix.protocol.PacketType) Play.Server.class.getDeclaredField("SYSTEM_CHAT").get(null));
} catch (Exception e) {
// ignore because using old version
}
protocolManager.addPacketListener(new PacketAdapter(pl, ListenerPriority.LOWEST, list) {
@Override
public void onPacketSending(PacketEvent e) {
Player p = e.getPlayer();
if (p == null || e.isPlayerTemporary())
return;
ChatItemPacket packet = onPacketSent(PacketType.getType(e.getPacket().getHandle().getClass().getSimpleName()), p, e.getPacket().getHandle());
if(packet == null) {
ChatItem.debug("Can't find packet: " + e.getPacket().getHandle().getClass().getName());
return;
}
if(!e.isCancelled())
e.setCancelled(packet.isCancelled());
}
});
}
@Override
public void stop() {
protocolManager.removePacketListeners(ChatItem.getInstance());
}
public ChatItemPacket onPacketSent(PacketType type, Player sender, Object packet) {
if(type == null)
return null;
ChatItemPacket customPacket = new ChatItemPacket(type, packet, sender);
notifyHandlersSent(customPacket);
return customPacket;
}
}
@@ -0,0 +1,44 @@
package me.dadus33.chatitem.chatmanager.v1.utils;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
@Deprecated
public class Item {
private String id;
private byte amount;
private short data;
private CompoundTag tag;
public CompoundTag getTag(){
return tag;
}
public void setTag(CompoundTag newTag){
this.tag = newTag;
}
public void setId(String newId){
this.id = newId;
}
public void setData(short newData){
data = newData;
}
public String getId(){
return id;
}
public short getData(){
return data;
}
public void setAmount(byte newAmount){
this.amount = newAmount;
}
public byte getAmount(){
return amount;
}
}
@@ -0,0 +1,50 @@
package me.dadus33.chatitem.chatmanager.v1.utils;
import static me.dadus33.chatitem.utils.Version.V1_10;
import static me.dadus33.chatitem.utils.Version.V1_11;
import static me.dadus33.chatitem.utils.Version.V1_8;
import static me.dadus33.chatitem.utils.Version.V1_9;
import org.bukkit.inventory.ItemStack;
@Deprecated
public class ItemRewriter {
public static String remapIds(int server, int player, ItemStack is) {
Item item = new Item();
item.setAmount((byte)is.getAmount());
//item.setData(is.getDurability());
//item.setId(id);
//item.setTag(tag);
if (areIdsCompatible(server, player)) {
return item.getId();
}
if ((server >= V1_9.MIN_VER && player <= V1_8.MAX_VER) || (player >= V1_9.MIN_VER && server <= V1_8.MAX_VER)) {
if ((server >= V1_9.MIN_VER && player <= V1_8.MAX_VER)) {
ItemRewriter_1_9_TO_1_8.reversedToClient(item);
} else
ItemRewriter_1_9_TO_1_8.toClient(item);
}
if ((server <= V1_10.MAX_VER && player >= V1_11.MIN_VER)
|| (player <= V1_10.MAX_VER && server >= V1_11.MIN_VER)) {
if (server <= V1_10.MAX_VER && player >= V1_11.MIN_VER) {
ItemRewriter_1_11_TO_1_10.toClient(item);
} else {
ItemRewriter_1_11_TO_1_10.reverseToClient(item);
}
}
return item.getId();
}
public static boolean areIdsCompatible(int version1, int version2) {
if ((version1 >= V1_9.MIN_VER && version2 <= V1_8.MAX_VER)
|| (version2 >= V1_9.MIN_VER && version1 <= V1_8.MAX_VER)) {
return false;
}
if ((version1 <= V1_10.MAX_VER && version2 >= V1_11.MIN_VER)
|| (version1 <= V1_10.MAX_VER && version2 >= V1_11.MIN_VER)) {
return false;
}
return true;
}
}
@@ -0,0 +1,132 @@
package me.dadus33.chatitem.chatmanager.v1.utils;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
/**
* Thanks to the developers of ViaVersion for this!
*/
@Deprecated
public class ItemRewriter_1_11_TO_1_10 {
private static BiMap<String, String> oldToNewNames = HashBiMap.create();
static {
oldToNewNames.put("AreaEffectCloud", "minecraft:area_effect_cloud");
oldToNewNames.put("ArmorStand", "minecraft:armor_stand");
oldToNewNames.put("Arrow", "minecraft:arrow");
oldToNewNames.put("Bat", "minecraft:bat");
oldToNewNames.put("Blaze", "minecraft:blaze");
oldToNewNames.put("Boat", "minecraft:boat");
oldToNewNames.put("CaveSpider", "minecraft:cave_spider");
oldToNewNames.put("Chicken", "minecraft:chicken");
oldToNewNames.put("Cow", "minecraft:cow");
oldToNewNames.put("Creeper", "minecraft:creeper");
oldToNewNames.put("Donkey", "minecraft:donkey");
oldToNewNames.put("DragonFireball", "minecraft:dragon_fireball");
oldToNewNames.put("ElderGuardian", "minecraft:elder_guardian");
oldToNewNames.put("EnderCrystal", "minecraft:ender_crystal");
oldToNewNames.put("EnderDragon", "minecraft:ender_dragon");
oldToNewNames.put("Enderman", "minecraft:enderman");
oldToNewNames.put("Endermite", "minecraft:endermite");
oldToNewNames.put("EntityHorse", "minecraft:horse");
oldToNewNames.put("EyeOfEnderSignal", "minecraft:eye_of_ender_signal");
oldToNewNames.put("FallingSand", "minecraft:falling_block");
oldToNewNames.put("Fireball", "minecraft:fireball");
oldToNewNames.put("FireworksRocketEntity", "minecraft:fireworks_rocket");
oldToNewNames.put("Ghast", "minecraft:ghast");
oldToNewNames.put("Giant", "minecraft:giant");
oldToNewNames.put("Guardian", "minecraft:guardian");
oldToNewNames.put("Husk", "minecraft:husk");
oldToNewNames.put("Item", "minecraft:item");
oldToNewNames.put("ItemFrame", "minecraft:item_frame");
oldToNewNames.put("LavaSlime", "minecraft:magma_cube");
oldToNewNames.put("LeashKnot", "minecraft:leash_knot");
oldToNewNames.put("MinecartChest", "minecraft:chest_minecart");
oldToNewNames.put("MinecartCommandBlock", "minecraft:commandblock_minecart");
oldToNewNames.put("MinecartFurnace", "minecraft:furnace_minecart");
oldToNewNames.put("MinecartHopper", "minecraft:hopper_minecart");
oldToNewNames.put("MinecartRideable", "minecraft:minecart");
oldToNewNames.put("MinecartSpawner", "minecraft:spawner_minecart");
oldToNewNames.put("MinecartTNT", "minecraft:tnt_minecart");
oldToNewNames.put("Mule", "minecraft:mule");
oldToNewNames.put("MushroomCow", "minecraft:mooshroom");
oldToNewNames.put("Ozelot", "minecraft:ocelot");
oldToNewNames.put("Painting", "minecraft:painting");
oldToNewNames.put("Pig", "minecraft:pig");
oldToNewNames.put("PigZombie", "minecraft:zombie_pigman");
oldToNewNames.put("PolarBear", "minecraft:polar_bear");
oldToNewNames.put("PrimedTnt", "minecraft:tnt");
oldToNewNames.put("Rabbit", "minecraft:rabbit");
oldToNewNames.put("Sheep", "minecraft:sheep");
oldToNewNames.put("Shulker", "minecraft:shulker");
oldToNewNames.put("ShulkerBullet", "minecraft:shulker_bullet");
oldToNewNames.put("Silverfish", "minecraft:silverfish");
oldToNewNames.put("Skeleton", "minecraft:skeleton");
oldToNewNames.put("SkeletonHorse", "minecraft:skeleton_horse");
oldToNewNames.put("Slime", "minecraft:slime");
oldToNewNames.put("SmallFireball", "minecraft:small_fireball");
oldToNewNames.put("Snowball", "minecraft:snowball");
oldToNewNames.put("SnowMan", "minecraft:snowman");
oldToNewNames.put("SpectralArrow", "minecraft:spectral_arrow");
oldToNewNames.put("Spider", "minecraft:spider");
oldToNewNames.put("Squid", "minecraft:squid");
oldToNewNames.put("Stray", "minecraft:stray");
oldToNewNames.put("ThrownEgg", "minecraft:egg");
oldToNewNames.put("ThrownEnderpearl", "minecraft:ender_pearl");
oldToNewNames.put("ThrownExpBottle", "minecraft:xp_bottle");
oldToNewNames.put("ThrownPotion", "minecraft:potion");
oldToNewNames.put("Villager", "minecraft:villager");
oldToNewNames.put("VillagerGolem", "minecraft:villager_golem");
oldToNewNames.put("Witch", "minecraft:witch");
oldToNewNames.put("WitherBoss", "minecraft:wither");
oldToNewNames.put("WitherSkeleton", "minecraft:wither_skeleton");
oldToNewNames.put("WitherSkull", "minecraft:wither_skull");
oldToNewNames.put("Wolf", "minecraft:wolf");
oldToNewNames.put("XPOrb", "minecraft:xp_orb");
oldToNewNames.put("Zombie", "minecraft:zombie");
oldToNewNames.put("ZombieHorse", "minecraft:zombie_horse");
oldToNewNames.put("ZombieVillager", "minecraft:zombie_villager");
}
static void toClient(Item item) {
if (hasEntityTag(item)) {
CompoundTag entityTag = item.getTag().get("EntityTag");
if (entityTag.get("id") instanceof StringTag) {
StringTag id = entityTag.get("id");
if (oldToNewNames.containsKey(id.getValue())) {
id.setValue(oldToNewNames.get(id.getValue()));
}
}
}
}
static void reverseToClient(Item item) {
if (hasEntityTag(item)) {
CompoundTag entityTag = item.getTag().get("EntityTag");
if (entityTag.get("id") instanceof StringTag) {
StringTag id = entityTag.get("id");
if (oldToNewNames.containsKey(id.getValue())) {
id.setValue(oldToNewNames.get(id.getValue()));
}
}
}
}
private static boolean hasEntityTag(Item item) {
if (item != null && item.getId().equals("minecraft:spawn_egg")) { // Monster Egg
CompoundTag tag = item.getTag();
if (tag != null && tag.contains("EntityTag") && tag.get("EntityTag") instanceof CompoundTag) {
if (((CompoundTag) tag.get("EntityTag")).get("id") instanceof StringTag) {
return true;
}
}
}
return false;
}
}
@@ -0,0 +1,342 @@
package me.dadus33.chatitem.chatmanager.v1.utils;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import java.util.HashMap;
import java.util.Map;
/**
* Thanks to the developers of ViaVersion for this!
*/
@Deprecated
public class ItemRewriter_1_9_TO_1_8 {
private static final Map<String, Integer> ENTTIY_NAME_TO_ID = new HashMap<>();
private static final Map<Integer, String> ENTTIY_ID_TO_NAME = new HashMap<>();
private static final Map<String, Integer> POTION_NAME_TO_ID = new HashMap<>();
private static final Map<Integer, String> POTION_ID_TO_NAME = new HashMap<>();
private static final Map<Integer, Integer> POTION_INDEX = new HashMap<>();
static {
/* Entities */
registerEntity(1, "Item");
registerEntity(2, "XPOrb");
registerEntity(7, "ThrownEgg");
registerEntity(8, "LeashKnot");
registerEntity(9, "Painting");
registerEntity(10, "Arrow");
registerEntity(11, "Snowball");
registerEntity(12, "Fireball");
registerEntity(13, "SmallFireball");
registerEntity(14, "ThrownEnderpearl");
registerEntity(15, "EyeOfEnderSignal");
registerEntity(16, "ThrownPotion");
registerEntity(17, "ThrownExpBottle");
registerEntity(18, "ItemFrame");
registerEntity(19, "WitherSkull");
registerEntity(20, "PrimedTnt");
registerEntity(21, "FallingSand");
registerEntity(22, "FireworksRocketEntity");
registerEntity(30, "ArmorStand");
registerEntity(40, "MinecartCommandBlock");
registerEntity(41, "Boat");
registerEntity(42, "MinecartRideable");
registerEntity(43, "MinecartChest");
registerEntity(44, "MinecartFurnace");
registerEntity(45, "MinecartTNT");
registerEntity(46, "MinecartHopper");
registerEntity(47, "MinecartSpawner");
registerEntity(48, "Mob");
registerEntity(49, "Monster");
registerEntity(50, "Creeper");
registerEntity(51, "Skeleton");
registerEntity(52, "Spider");
registerEntity(53, "Giant");
registerEntity(54, "Zombie");
registerEntity(55, "Slime");
registerEntity(56, "Ghast");
registerEntity(57, "PigZombie");
registerEntity(58, "Enderman");
registerEntity(59, "CaveSpider");
registerEntity(60, "Silverfish");
registerEntity(61, "Blaze");
registerEntity(62, "LavaSlime");
registerEntity(63, "EnderDragon");
registerEntity(64, "WitherBoss");
registerEntity(65, "Bat");
registerEntity(66, "Witch");
registerEntity(67, "Endermite");
registerEntity(68, "Guardian");
registerEntity(90, "Pig");
registerEntity(91, "Sheep");
registerEntity(92, "Cow");
registerEntity(93, "Chicken");
registerEntity(94, "Squid");
registerEntity(95, "Wolf");
registerEntity(96, "MushroomCow");
registerEntity(97, "SnowMan");
registerEntity(98, "Ozelot");
registerEntity(99, "VillagerGolem");
registerEntity(100, "EntityHorse");
registerEntity(101, "Rabbit");
registerEntity(120, "Villager");
registerEntity(200, "EnderCrystal");
/* Potions */
registerPotion(-1, "empty");
registerPotion(0, "water");
registerPotion(64, "mundane");
registerPotion(32, "thick");
registerPotion(16, "awkward");
registerPotion(8198, "night_vision");
registerPotion(8262, "long_night_vision");
registerPotion(8206, "invisibility");
registerPotion(8270, "long_invisibility");
registerPotion(8203, "leaping");
registerPotion(8267, "long_leaping");
registerPotion(8235, "strong_leaping");
registerPotion(8195, "fire_resistance");
registerPotion(8259, "long_fire_resistance");
registerPotion(8194, "swiftness");
registerPotion(8258, "long_swiftness");
registerPotion(8226, "strong_swiftness");
registerPotion(8202, "slowness");
registerPotion(8266, "long_slowness");
registerPotion(8205, "water_breathing");
registerPotion(8269, "long_water_breathing");
registerPotion(8261, "healing");
registerPotion(8229, "strong_healing");
registerPotion(8204, "harming");
registerPotion(8236, "strong_harming");
registerPotion(8196, "poison");
registerPotion(8260, "long_poison");
registerPotion(8228, "strong_poison");
registerPotion(8193, "regeneration");
registerPotion(8257, "long_regeneration");
registerPotion(8225, "strong_regeneration");
registerPotion(8201, "strength");
registerPotion(8265, "long_strength");
registerPotion(8233, "strong_strength");
registerPotion(8200, "weakness");
registerPotion(8264, "long_weakness");
}
static void toClient(Item item) {
if (item != null) {
if (item.getId().equals("minecraft:spawn_egg") && item.getData() != 0) { // Monster Egg
CompoundTag tag = item.getTag();
if (tag == null) {
tag = new CompoundTag("tag");
}
CompoundTag entityTag = new CompoundTag("EntityTag");
if (ENTTIY_ID_TO_NAME.containsKey((int) item.getData())) {
StringTag id = new StringTag("id", ENTTIY_ID_TO_NAME.get((int) item.getData()));
entityTag.put(id);
tag.put(entityTag);
}
item.setTag(tag);
item.setData((short) 0);
}
if (item.getId().equals("minecraft:potion")) { // Potion
CompoundTag tag = item.getTag();
if (tag == null) {
tag = new CompoundTag("tag");
}
if (item.getData() >= 16384) {
item.setId("minecraft:splash_potion"); // splash id
item.setData((short) (item.getData() - 8192));
}
String name = potionNameFromDamage(item.getData());
StringTag potion = new StringTag("Potion", "minecraft:" + name);
tag.put(potion);
item.setTag(tag);
item.setData((short) 0);
}
}
}
static void reversedToClient(Item item) {
if (item != null) {
if (item.getId().equals("minecraft:spawn_egg") && item.getData() == 0) { // Monster Egg
CompoundTag tag = item.getTag();
int data = 0;
if(tag != null) {
if (tag.get("EntityTag") instanceof CompoundTag) {
CompoundTag entityTag = tag.get("EntityTag");
if (entityTag.get("id") instanceof StringTag) {
StringTag id = entityTag.get("id");
if (ENTTIY_NAME_TO_ID.containsKey(id.getValue()))
data = ENTTIY_NAME_TO_ID.get(id.getValue());
}
tag.remove("EntityTag");
}
}
item.setTag(tag);
item.setData((short) data);
}
if (item.getId().equals("minecraft:potion")) { // Potion
CompoundTag tag = item.getTag();
int data = 0;
if(tag != null) {
if (tag.get("Potion") instanceof StringTag) {
StringTag potion = tag.get("Potion");
String potionName = potion.getValue().replace("minecraft:", "");
if (POTION_NAME_TO_ID.containsKey(potionName)) {
data = POTION_NAME_TO_ID.get(potionName);
}
tag.remove("Potion");
}
}
item.setTag(tag);
item.setData((short) data);
}
// Splash potion
if (item.getId().equals("minecraft:splash_potion")) {
CompoundTag tag = item.getTag();
int data = 0;
item.setId("minecraft:potion"); // Potion
if(tag != null) {
if (tag.get("Potion") instanceof StringTag) {
StringTag potion = tag.get("Potion");
String potionName = potion.getValue().replace("minecraft:", "");
if (POTION_NAME_TO_ID.containsKey(potionName)) {
data = POTION_NAME_TO_ID.get(potionName) + 8192;
}
tag.remove("Potion");
}
}
item.setTag(tag);
item.setData((short) data);
}
}
}
private static String potionNameFromDamage(short damage) {
String cached = POTION_ID_TO_NAME.get((int) damage);
if (cached != null) {
return cached;
}
if (damage == 0) {
return "water";
}
int effect = damage & 0xF;
int name = damage & 0x3F;
boolean enhanced = (damage & 0x20) > 0;
boolean extended = (damage & 0x40) > 0;
boolean canEnhance = true;
boolean canExtend = true;
String id;
switch (effect) {
case 1:
id = "regeneration";
break;
case 2:
id = "swiftness";
break;
case 3:
id = "fire_resistance";
canEnhance = false;
break;
case 4:
id = "poison";
break;
case 5:
id = "healing";
canExtend = false;
break;
case 6:
id = "night_vision";
canEnhance = false;
break;
case 8:
id = "weakness";
canEnhance = false;
break;
case 9:
id = "strength";
break;
case 10:
id = "slowness";
canEnhance = false;
break;
case 11:
id = "leaping";
break;
case 12:
id = "harming";
canExtend = false;
break;
case 13:
id = "water_breathing";
canEnhance = false;
break;
case 14:
id = "invisibility";
canEnhance = false;
break;
default:
canEnhance = false;
canExtend = false;
switch (name) {
case 0:
id = "mundane";
break;
case 16:
id = "awkward";
break;
case 32:
id = "thick";
break;
default:
id = "empty";
}
}
if (effect > 0) {
if (canEnhance && enhanced) {
id = "strong_" + id;
} else if (canExtend && extended) {
id = "long_" + id;
}
}
return id;
}
private static void registerEntity(Integer id, String name) {
ENTTIY_ID_TO_NAME.put(id, name);
ENTTIY_NAME_TO_ID.put(name, id);
}
private static void registerPotion(Integer id, String name) {
POTION_INDEX.put(id, POTION_ID_TO_NAME.size());
POTION_ID_TO_NAME.put(id, name);
POTION_NAME_TO_ID.put(name, id);
}
}
@@ -0,0 +1,336 @@
package me.dadus33.chatitem.chatmanager.v2;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.ItemPlayer;
import me.dadus33.chatitem.ItemSlot;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.chatmanager.Chat;
import me.dadus33.chatitem.chatmanager.ChatAction;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.hook.DiscordSrvSupport;
import me.dadus33.chatitem.playernamer.PlayerNamerManager;
import me.dadus33.chatitem.utils.ColorManager;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.Messages;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
import me.dadus33.chatitem.utils.Utils;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.TextComponent;
public class ChatListener implements Listener {
private static Method saveMethod;
private static boolean shouldUseAppendMethod = false;
static {
try {
Class<?> nbtTag = PacketUtils.getNmsClass("NBTTagCompound", "nbt.");
Class<?> itemClass = PacketUtils.getNmsClass("ItemStack", "world.item.");
for (Method m : itemClass.getDeclaredMethods()) {
if (m.getParameterTypes().length == 1) {
if (m.getParameterTypes()[0].equals(nbtTag) && m.getReturnType().equals(nbtTag)) {
saveMethod = m;
}
}
}
try {
ComponentBuilder.class.getDeclaredMethod("append", BaseComponent[].class);
shouldUseAppendMethod = true;
} catch (Exception e) {
shouldUseAppendMethod = false;
}
} catch (Exception e) {
}
Logger log = ChatItem.getInstance().getLogger();
String appendMethodMsg = shouldUseAppendMethod ? "Use ComponentBuilder's method." : "Use own ComponentBuilder append method.";
if (saveMethod == null)
log.info("Failed to find save method. Using default system. " + appendMethodMsg);
else
log.info("Save method founded: " + saveMethod.getName() + ". " + appendMethodMsg);
}
private ChatListenerChatManager manage;
public ChatListener(ChatListenerChatManager manage) {
this.manage = manage;
}
public Storage getStorage() {
return manage.getStorage();
}
@EventHandler(priority = EventPriority.HIGH)
public void onChat(AsyncPlayerChatEvent e) {
if(ChatManager.isTestingEnabled() && !ChatManager.isTesting("chat"))
return;
Storage c = getStorage();
if (e.isCancelled()) {
if (ChatItem.getInstance().getChatManager().size() == 1) { // only chat
String msg = e.getMessage().toLowerCase();
for(ItemSlot slot : ItemSlot.values()) {
for (String rep : slot.getPlaceholders()) {
if (msg.contains(rep)) {
ChatItem.debug("You choose 'chat' manager but it seems to don't be the good choice. More informations here: https://github.com/dadus33-plugins/ChatItem/wiki");
return;
}
}
}
}
ChatItem.debug("Chat cancelled for " + e.getPlayer().getName());
return;
}
Player p = e.getPlayer();
if(ChatManager.containsSeparator(e.getMessage())) { // fix for v1
Chat chat = Chat.getFrom(e.getMessage());
if(chat != null)
e.setMessage(ChatManager.replaceSeparator(chat, e.getMessage(), chat.getSlot().getPlaceholders().get(0)));
}
ItemSlot slot = ItemSlot.getItemSlotFromMessage(e.getMessage());
if (slot == null) { // if not found
ChatItem.debug("(v2) Can't found placeholder in: " + e.getMessage() + " > " + PlayerNamerManager.getPlayerNamer().getName(p));
return;
}
ChatAction action = ChatManager.getChatAction(slot, p);
if(action.isItem() && !ChatManager.canShowItem(p, action.getItem(), slot, e))
return;
e.setCancelled(true);
String format = e.getFormat();
String defMsg = slot.replacePlaceholdersToSeparator(e.getMessage());
if (Utils.countMatches(defMsg, Character.toString(ChatManager.SEPARATOR)) > getStorage().limit) {
if (!getStorage().messageLimit.isEmpty())
p.sendMessage(getStorage().messageLimit);
return;
}
String msg;
if (format.contains("%1$s") || format.contains("%2$s")) {
msg = (format.contains("%2$s") ? String.format(format, p.getDisplayName(), defMsg) : String.format(format, p.getDisplayName()));
} else {
msg = format.replace(e.getMessage(), defMsg);
}
String itemName = ChatManager.getNameForChatAction(p, action, c);
String loggedMessage = msg.replace(ChatManager.SEPARATOR + "", itemName).replace("{name}", p.getName()).replace("{display-name}", p.getDisplayName());
Bukkit.getConsoleSender().sendMessage(loggedMessage); // show in log
if (ChatItem.discordSrvSupport)
DiscordSrvSupport.sendChatMessage(p, defMsg.replace(ChatManager.SEPARATOR + "", itemName).replace("{name}", p.getName()).replace("{display-name}", p.getDisplayName()), e);
Set<Player> recipients = e.getRecipients().isEmpty() ? new HashSet<>(Bukkit.getOnlinePlayers()) : e.getRecipients();
ChatItem.debug("Msg: " + msg.replace(ChatColor.COLOR_CHAR, '&') + ", format: " + format + " to " + recipients.size() + " players");
recipients.forEach((pl) -> showItem(pl, p, action, msg));
if (c.cooldown > 0 && !p.hasPermission("chatitem.ignore-cooldown"))
ChatManager.applyCooldown(p);
}
public static void showItem(Player to, Player origin, ChatAction action, String msg) {
ComponentBuilder builder = new ComponentBuilder("");
ChatColor color = ChatColor.WHITE;
String colorCode = "", text = "";
boolean waiting = false, removing = false;
for (char args : msg.toCharArray()) {
if (args == '§') { // begin of color
if (colorCode.isEmpty() && !text.isEmpty()) { // text before this char
ChatItem.debug("Append '" + text.replace(ChatColor.COLOR_CHAR, '&') + "' (len: " + text.length() + ")");
if(text.length() > 2 && text.startsWith("§") && text.substring(2) == ChatColor.stripColor(text)
&& color != null && color != ChatColor.WHITE) {
text = text.substring(2); // remove some code which should not be here
}
appendToComponentBuilder(builder, createComponent(to, text, color, action));
text = "";
}
waiting = true; // waiting for color code
} else if (waiting) { // if waiting for code and valid str
// if it's hexademical value and with enough space for full color
waiting = false;
if (args == 'r' && colorCode.isEmpty()) {
color = ChatColor.RESET;
continue;
} else if(args == 'x') {
if(!colorCode.isEmpty()) {
color = ColorManager.getColor(colorCode);
colorCode = ""; // clean for previous things
}
}
colorCode += args;
} else {
waiting = false;
if (!colorCode.isEmpty()) {
if (colorCode.startsWith("x") && colorCode.length() >= 7) {
if (colorCode.length() == 7)
color = ColorManager.getColor(colorCode);
else {
color = ColorManager.getColor(colorCode.substring(0, 7)); // only the hex code
ChatItem.debug("Adding color for " + colorCode.substring(7, colorCode.length()) + " (in " + colorCode + ")");
text += ColorManager.getColorString(colorCode.substring(7, colorCode.length()));
}
} else if (colorCode.length() == 1) // if only one color code
color = ColorManager.getColor(colorCode);
else
text += ColorManager.getColorString(colorCode);
colorCode = "";
}
if (args == ChatManager.SEPARATOR) {
// here put the item
appendToComponentBuilder(builder, fixColorComponent(to, text, color, action));
if(action.isItem())
addItem(builder, to, origin, action.getItem(), action);
else
addCommand(builder, to, origin, action.getCommand(), action);
text = "";
if(ChatManager.containsSeparatorEnd(msg))
removing = true;
} else if(args == ChatManager.SEPARATOR_END) {
removing = false;
} else if(!removing) { // not removing content
// basic text, not waiting for code after '§'
text += args;
}
}
}
if (!text.isEmpty())
appendToComponentBuilder(builder, createComponent(to, text, color, action));
to.spigot().sendMessage(builder.create());
}
public static void addItem(ComponentBuilder builder, Player to, Player origin, ItemStack item, ChatAction action) {
Storage c = ChatItem.getInstance().getStorage();
if (!ItemUtils.isEmpty(item)) {
ComponentBuilder itemComponent = new ComponentBuilder("");
appendToComponentBuilder(itemComponent, fixColorComponent(to, ChatManager.getNameOfItem(to, item, c), ChatColor.WHITE, action));
ChatItem.debug("Item for " + to.getName() + " (ver: " + ItemPlayer.getPlayer(to).getVersion().name() + ") : " + PacketUtils.getNbtTag(item));
// itemComponent.event(new HoverEvent(Action.SHOW_ITEM, itemBaseComponent));
appendToComponentBuilder(builder, itemComponent.create());
} else {
String handName = c.handName;
ComponentBuilder handComp = new ComponentBuilder("");
ComponentBuilder handTooltip = new ComponentBuilder("");
int stay = c.tooltipHand.size();
for (String line : c.tooltipHand) {
stay--;
handTooltip.append(ColorManager.fixColor(line.replace("{name}", origin.getName()).replace("{display-name}", origin.getDisplayName())));
if (stay > 0)
handTooltip.append("\n");
}
handComp.event(Utils.createTextHover(handTooltip.create()));
if (handName.contains("{display-name}")) {
String[] splitted = handName.split("\\{display-name\\}");
for (int i = 0; i < (splitted.length - 1); i++) {
handComp.append(splitted[i]);
appendToComponentBuilder(handComp, PlayerNamerManager.getPlayerNamer().getName(origin));
}
handComp.append(splitted[splitted.length - 1]);
} else
handComp.append(handName.replace("{name}", origin.getName()));
appendToComponentBuilder(builder, handComp.create());
}
}
public static void addCommand(ComponentBuilder builder, Player to, Player origin, String command, ChatAction action) {
ComponentBuilder itemComponent = new ComponentBuilder("");
appendToComponentBuilder(itemComponent, fixColorComponent(to, Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat", "%cible%", origin.getName()), ChatColor.WHITE, action));
appendToComponentBuilder(builder, itemComponent.create());
}
public static void appendToComponentBuilder(ComponentBuilder builder, BaseComponent[] comps) {
if (shouldUseAppendMethod) {
try {
builder.append(comps);
} catch (Exception e) {
ChatItem.getInstance().getLogger().severe("This should NEVER append. The ComponentBuilder#append(BaseComponent[]) was found but it's NOT. Using own next time.");
shouldUseAppendMethod = false;
}
} else {
try {
Field currentField = ReflectionUtils.getField(builder, "current");
List<BaseComponent> parts = (List<BaseComponent>) ReflectionUtils.getObject(builder, "parts");
parts.add(new TextComponent((TextComponent) currentField.get(builder)));
parts.addAll(Arrays.asList(comps));
currentField.set(builder, new TextComponent(""));
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static BaseComponent[] fixColorComponent(Player to, String message, ChatColor color, ChatAction action) {
ComponentBuilder builder = new ComponentBuilder("");
String colorCode = "", text = "";
boolean waiting = false;
for (char args : message.toCharArray()) {
if (args == '§') { // begin of color
if (colorCode.isEmpty() && !text.isEmpty()) { // text before this char
ChatItem.debug("Append while fixing name " + (ColorManager.isHexColor(color) && builder.getParts().isEmpty() ? ColorManager.removeColorAtBegin(text) : text));
appendToComponentBuilder(builder, createComponent(to, ColorManager.isHexColor(color) ? ColorManager.removeColorAtBegin(text) : text, color, action));
text = "";
}
waiting = true; // waiting for color code
} else if (waiting) { // if waiting for code and valid str
// if it's hexademical value and with enough space for full color
waiting = false;
if (args == 'r' && colorCode.isEmpty()) {
color = ChatColor.RESET;
continue;
}
if (args == 'x' && !colorCode.isEmpty()) {
text += ColorManager.getColorString(colorCode);
colorCode = "x";
} else
colorCode += args; // a color by itself
} else {
waiting = false;
if (!colorCode.isEmpty()) {
if (colorCode.startsWith("x") && colorCode.length() >= 7) {
if (colorCode.length() == 7)
color = ColorManager.getColor(colorCode);
else {
color = ColorManager.getColor(colorCode.substring(0, 7)); // only the hex code
ChatItem.debug("Adding color for " + colorCode.substring(7, colorCode.length()) + " (in " + colorCode + ")");
text += ColorManager.getColorString(colorCode.substring(7, colorCode.length()));
}
} else if (colorCode.length() == 1) // if only one color code
color = ColorManager.getColor(colorCode);
else
text += ColorManager.getColorString(colorCode);
ChatItem.debug("Color: " + color + ", text: " + text + ", code: " + colorCode);
colorCode = "";
}
// basic text, not waiting for code after '§'
text += args;
}
}
if (!text.isEmpty()) {
appendToComponentBuilder(builder, createComponent(to, text, color, action));
}
return builder.create();
}
private static BaseComponent[] createComponent(Player to, String text, ChatColor color, ChatAction action) {
ComponentBuilder littleBuilder = new ComponentBuilder(text);
if(color != null && color != ChatColor.RESET) // don't add reset thing
littleBuilder.color(color);
if (action.isItem())
littleBuilder.event(Utils.createItemHover(action.getItem(), to));
else {
littleBuilder.event(Utils.createTextHover(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover")));
littleBuilder.event(Utils.createRunCommand(action.getCommand()));
}
return littleBuilder.create();
}
}
@@ -0,0 +1,51 @@
package me.dadus33.chatitem.chatmanager.v2;
import org.bukkit.Bukkit;
import org.bukkit.event.HandlerList;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.chatmanager.ChatManager;
public class ChatListenerChatManager extends ChatManager {
private final ChatListener chatListener;
private boolean baseComponentAvailable = true;
public ChatListenerChatManager(ChatItem pl) {
chatListener = new ChatListener(this);
//Check for existence of BaseComponent class (only on spigot)
try {
Class.forName("net.md_5.bungee.api.chat.BaseComponent");
} catch (ClassNotFoundException e) {
baseComponentAvailable = false;
}
}
@Override
public String getName() {
return "ChatListener";
}
@Override
public String getId() {
return "chat";
}
@Override
public void load(ChatItem pl, Storage s) {
super.load(pl, s);
Bukkit.getPluginManager().registerEvents(chatListener, pl);
}
@Override
public void unload(ChatItem pl) {
HandlerList.unregisterAll(chatListener);
}
public boolean supportsChatComponentApi(){
return baseComponentAvailable;
}
}
@@ -1,16 +1,16 @@
package me.dadus33.chatitem.commands;
import me.dadus33.chatitem.ChatItem;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import me.dadus33.chatitem.ChatItem;
public class CIReload implements CommandExecutor {
public class CIReloadCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
ChatItem.reload(sender);
ChatItem.reload(sender);
return false;
}
}
@@ -0,0 +1,170 @@
package me.dadus33.chatitem.commands;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.ItemSlot;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.chatmanager.ChatAction;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v2.ChatListener;
import me.dadus33.chatitem.invsee.InvShower;
import me.dadus33.chatitem.listeners.InventoryListener;
import me.dadus33.chatitem.utils.Messages;
import me.dadus33.chatitem.utils.Utils;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.TextComponent;
public class ChatItemCommand implements CommandExecutor, TabExecutor {
private static final List<String> orders = Arrays.asList("packet", "chat", "both");
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (!(sender instanceof Player)) {
Messages.sendMessage(sender, "only-players");
return false;
}
Player p = (Player) sender;
if (args.length == 0) {
Messages.sendMessage(p, "chatitem-cmd.help");
} else if (args[0].equalsIgnoreCase("admin") && p.hasPermission("chatitem.reload")) {
InventoryListener.open(p);
} else if (args[0].equalsIgnoreCase("reload") && p.hasPermission("chatitem.reload")) {
ChatItem.reload(sender);
} else if (args[0].equalsIgnoreCase("show") && ChatItem.getInstance().getStorage().cmdShow) {
Player cible = args.length == 1 ? p : Bukkit.getPlayer(args[1]);
if(cible == null) {
Messages.sendMessage(p, "player-not-found", "%arg%", args[1]);
return false;
}
Storage c = ChatItem.getInstance().getStorage();
ItemStack item = ChatManager.getUsableItem(cible, ItemSlot.HAND);
ChatListener.showItem(p, cible, new ChatAction(ItemSlot.HAND, item), c.commandFormat.replace("%name%", cible.getName()).replace("%item%", ChatManager.SEPARATOR + ""));
} else if (args[0].equalsIgnoreCase("broadcast") && ChatItem.getInstance().getStorage().cmdBroadcast) {
Player cible = args.length == 1 ? p : Bukkit.getPlayer(args[1]);
if(cible == null) {
Messages.sendMessage(p, "player-not-found", "%arg%", args[1]);
return false;
}
Storage c = ChatItem.getInstance().getStorage();
ItemStack item = ChatManager.getUsableItem(cible, ItemSlot.HAND);
for(Player all : Bukkit.getOnlinePlayers())
ChatListener.showItem(all, cible, new ChatAction(ItemSlot.HAND, item), c.commandFormat.replace("%name%", cible.getName()).replace("%item%", ChatManager.SEPARATOR + ""));
} else if (args[0].equalsIgnoreCase("link") || args[0].equalsIgnoreCase("links")) {
ConfigurationSection config = ChatItem.getInstance().getConfig()
.getConfigurationSection("messages.chatitem-cmd.links");
TextComponent text = new TextComponent(Storage.color(config.getString("begin")));
for (String key : config.getConfigurationSection("list").getKeys(false)) {
ConfigurationSection linkConfig = config.getConfigurationSection("list." + key);
TextComponent linkComp = new TextComponent(Storage.color(linkConfig.getString("message")));
String hover = Storage.color(linkConfig.getString("hover"));
if (hover != null)
linkComp.setHoverEvent(Utils.createTextHover(hover));
String link = linkConfig.getString("link");
if (link != null)
linkComp.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, link));
text.addExtra(linkComp);
}
p.spigot().sendMessage(text);
} else if (args[0].equalsIgnoreCase("select") && p.hasPermission("chatitem.reload")) {
if(args.length == 1) {
p.sendMessage(ChatColor.GRAY + "----------" + ChatColor.GOLD + " ChatItem - Setup " + ChatColor.GRAY + "----------");
p.sendMessage(ChatColor.AQUA + "Welcome in the help of setup." + ChatColor.YELLOW + " Please follow step by simply answer to test.");
sendCheckSelectMessage(p, orders.get(0));
} else {
String tested = args[1];
if(!orders.contains(tested)) {
p.sendMessage(ChatColor.RED + "Unknow test for " + tested + ".");
return false;
}
if(args.length == 2) {
p.sendMessage(ChatColor.RED + "Can't find if it works");
return false;
}
if(args[2].equalsIgnoreCase("yes")) {
ChatManager.setTesting(null);
InventoryListener.setInConfig("manager", tested);
p.sendMessage(ChatColor.GREEN + "Perfect ! Updating config ...");
ChatItem.reload(p);
} else if(args[2].equalsIgnoreCase("no")) {
int index = orders.indexOf(tested);
if(orders.size() == (index + 1)) {
p.sendMessage(ChatColor.RED + "Sad. Sorry but nothing is available. I suggest you to come on discord for more help. Do '/chatitem link' for all links.");
ChatManager.setTesting(null);
} else {
p.sendMessage(ChatColor.RED + "Sad. Checking for next manager ...");
sendCheckSelectMessage(p, orders.get(index + 1));
}
} else {
p.sendMessage(ChatColor.RED + "Can't find if it works");
}
}
} else if (args[0].equalsIgnoreCase("seeinv")) {
if(args.length == 2 && Utils.isUUID(args[1])) {
InvShower inv = InvShower.get(args[1]);
if(inv == null) {
Messages.sendMessage(p, "seeinv_not_found");
} else {
inv.open(p);
}
} // else just ignore
} else {
Messages.sendMessage(p, "chatitem-cmd.help");
}
return false;
}
private void sendCheckSelectMessage(Player p, String testing) {
ChatManager.setTesting(testing);
p.chat("Checking for " + testing + ": [i]");
Bukkit.getScheduler().runTaskLater(ChatItem.getInstance(), () -> {
TextComponent text = new TextComponent(ChatColor.GOLD + "Did it worked fine? ");
TextComponent agree = new TextComponent(ChatColor.GREEN + "Yes");
agree.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/chatitem select " + testing + " yes"));
agree.setHoverEvent(Utils.createTextHover(ChatColor.GRAY + "Click to say it worked fine"));
text.addExtra(agree);
text.addExtra(" ");
TextComponent decline = new TextComponent(ChatColor.RED + "No");
decline.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/chatitem select " + testing + " no"));
decline.setHoverEvent(Utils.createTextHover(ChatColor.GRAY + "Click to say it's not working as expected"));
text.addExtra(decline);
p.spigot().sendMessage(text);
}, 2);
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] arg) {
List<String> list = new ArrayList<>();
String prefix = arg[arg.length - 1].toLowerCase(Locale.ROOT);
if(arg.length <= 2) {
if(sender.hasPermission("chatitem.reload")) {
for (String s : Arrays.asList("admin", "reload", "select"))
if (prefix.isEmpty() || s.startsWith(prefix))
list.add(s);
}
if (ChatItem.getInstance().getStorage().cmdShow && (prefix.isEmpty() || "show".startsWith(prefix)))
list.add("show");
if (ChatItem.getInstance().getStorage().cmdBroadcast && (prefix.isEmpty() || "broadcast".startsWith(prefix)))
list.add("broadcast");
for (String s : Arrays.asList("help", "link"))
if (prefix.isEmpty() || s.startsWith(prefix))
list.add(s);
}
return list;
}
}
@@ -1,102 +0,0 @@
package me.dadus33.chatitem.filters;
import me.dadus33.chatitem.utils.Storage;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.Logger;
import org.apache.logging.log4j.message.Message;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.concurrent.CopyOnWriteArrayList;
import static org.apache.logging.log4j.core.Filter.Result.NEUTRAL;
public class Log4jFilter implements Filter {
private boolean stopped;
private final static CopyOnWriteArrayList<String> ls = new CopyOnWriteArrayList<>();
public Storage c;
public Log4jFilter(Storage st){
c = st;
((Logger) LogManager.getRootLogger()).addFilter(this);
}
@Override
public Result getOnMismatch() {
return NEUTRAL;
}
@Override
public Result getOnMatch() {
return NEUTRAL;
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String s, Object... objects) {
return checkMessage(s);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, Object o, Throwable throwable) {
return checkMessage(((Message)o).getFormattedMessage());
}
@Override
public Result filter(Logger logger, Level level, Marker marker, Message message, Throwable throwable) {
return checkMessage(message.getFormattedMessage());
}
@Override
public Result filter(LogEvent logEvent) {
return checkMessage(logEvent.getMessage().getFormattedMessage());
}
@Override
public void start() {
stopped = false;
}
@Override
public void stop() {
stopped = true;
}
@Override
public boolean isStarted() {
return !this.stopped;
}
@Override
public boolean isStopped() {
return this.stopped;
}
private Result checkMessage(String msg){
for(String placeholder : c.PLACEHOLDERS){
if(msg.contains(placeholder)){
ls.add(msg);
for(Player p : Bukkit.getOnlinePlayers()){
msg = msg.replaceAll("\\p{C}", "");
if(msg.endsWith(p.getName()) || msg.lastIndexOf(p.getName())+2+p.getName().length()>=msg.length()){
return Result.DENY;
}
}
}
}
return Result.NEUTRAL;
}
public void setStorage(Storage nst){
this.c = nst;
}
}
@@ -0,0 +1,18 @@
package me.dadus33.chatitem.hook;
import me.dadus33.chatitem.ChatItem;
public class ChatControlSupport {
public static void init(ChatItem pl) {
try {
Class<?> clz = Class.forName("org.mineacademy.chatcontrol.settings.Settings$Chat$Grammar");
clz.getField("CAPITALIZE").setBoolean(null, false);
clz.getField("INSERT_DOT").setBoolean(null, false);
pl.getLogger().info("Loaded ChatControl support by disabling 2 options in 'Chat.Grammar' config.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,16 @@
package me.dadus33.chatitem.hook;
import java.util.List;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.h1dd3nxn1nja.chatmanager.Main;
public class ChatManagerSupport {
public static void init(ChatItem pl) {
List<String> whitelist = Main.settings.getConfig().getStringList("Anti_Unicode.Whitelist");
whitelist.add(ChatManager.SEPARATOR_STR);
whitelist.add(ChatManager.SEPARATOR_END_STR);
}
}
@@ -0,0 +1,31 @@
package me.dadus33.chatitem.hook;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import github.scarsz.discordsrv.DiscordSRV;
import me.dadus33.chatitem.ChatItem;
import net.kyori.adventure.text.Component;
public class DiscordSrvSupport {
public static boolean isSendingMessage() {
return ChatItem.getInstance().getStorage().discordSrvSendMsg;
}
public static void sendChatMessage(Player p, String message, Event e) {
DiscordSRV pl = DiscordSRV.getPlugin();
if (DiscordSRV.config().getBooleanElse("UseModernPaperChatEvent", false) && pl.isModernChatEventAvailable()) {
return;
}
pl.processChatMessage(p, message, pl.getOptionalChannel("global"), false, e);
}
public static void sendChatMessage(Player p, Component message, Event e) {
DiscordSRV pl = DiscordSRV.getPlugin();
if (DiscordSRV.config().getBooleanElse("UseModernPaperChatEvent", false) && pl.isModernChatEventAvailable()) {
return;
}
pl.processChatMessage(p, message, pl.getOptionalChannel("global"), false, e);
}
}
@@ -0,0 +1,56 @@
package me.dadus33.chatitem.hook.ecoenchants;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import me.dadus33.chatitem.ChatItem;
public class EcoEnchantsSupport {
private static int supportedVersion = 0;
public static boolean hasSupport() {
return supportedVersion > 0;
}
public static boolean load() {
String ver = Bukkit.getPluginManager().getPlugin("EcoEnchants").getDescription().getVersion();
if(ver.startsWith("8."))
supportedVersion = 8;
else if(ver.startsWith("10."))
supportedVersion = 10;
else if(ver.startsWith("11."))
supportedVersion = 11;
else if(ver.startsWith("12."))
supportedVersion = 12;
else {
ChatItem.getInstance().getLogger().warning("Failed to find support version for EcoEnchants " + ver);
return false;
}
return true;
}
public static ItemStack manageItem(ItemStack item) {
if(supportedVersion == 8) {
List<String> addLore = EcoEnchantsV8Support.getLores(item);
if (!addLore.isEmpty()) {
ItemMeta meta = item.getItemMeta();
List<String> lores = meta.hasLore() ? meta.getLore() : new ArrayList<>();
for (int i = 0; i < addLore.size(); i++)
lores.add(i, addLore.get(i));
meta.setLore(lores);
item.setItemMeta(meta);
ChatItem.debug("Added " + addLore.size() + " lores from EcoEnchants");
} else
ChatItem.debug("No lore to add from EcoEnchants");
} else if(supportedVersion >= 10) {
EcoEnchantsV10Support.display(item);
}
return item;
}
}
@@ -0,0 +1,35 @@
package me.dadus33.chatitem.hook.ecoenchants;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.willfp.eco.core.display.DisplayProperties;
import com.willfp.ecoenchants.EcoEnchantsPlugin;
import com.willfp.ecoenchants.display.EnchantDisplay;
public class EcoEnchantsV10Support {
private static EnchantDisplay enchantDisplay;
public static EnchantDisplay getEnchantDisplay() {
if (enchantDisplay == null) {
try {
enchantDisplay = EnchantDisplay.class.getConstructor(EcoEnchantsPlugin.class).newInstance(Bukkit.getPluginManager().getPlugin("EcoEnchants"));
} catch (Exception e) {
e.printStackTrace();
}
}
return enchantDisplay;
}
public static void display(ItemStack item) {
try {
DisplayProperties display = DisplayProperties.class.getDeclaredConstructor(boolean.class, boolean.class, ItemStack.class).newInstance(false, false, item);
getEnchantDisplay().display(item, (Player) null, display, new Object[] { false });
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,21 @@
package me.dadus33.chatitem.hook.ecoenchants;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.inventory.ItemStack;
import com.willfp.ecoenchants.display.EnchantmentCache;
import com.willfp.ecoenchants.enchantments.util.EnchantChecks;
public class EcoEnchantsV8Support {
public static List<String> getLores(ItemStack item) {
List<String> lores = new ArrayList<>();
EnchantChecks.getEnchantsOnItem(item).forEach((en, lvl) -> {
lores.add(EnchantmentCache.getEntry(en).getNameWithLevel(lvl));
});
return lores;
}
}
@@ -0,0 +1,57 @@
package me.dadus33.chatitem.invsee;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.ChatItem;
public abstract class InvShower {
private static final HashMap<String, InvShower> INV_SHOWER = new HashMap<>();
public static InvShower get(String s) {
return INV_SHOWER.get(s);
}
public static void add(String s, InvShower shower) {
INV_SHOWER.put(s, shower);
}
public static HashMap<String, InvShower> getInvShower() {
return INV_SHOWER;
}
static {
Bukkit.getScheduler().runTaskTimer(ChatItem.getInstance(), () -> {
for(Entry<String, InvShower> entries : new HashMap<>(INV_SHOWER).entrySet())
if(entries.getValue().hasExpired())
INV_SHOWER.remove(entries.getKey());
}, 200, 200);
}
protected final long time;
protected final UUID uuid;
protected final String name;
public InvShower(String id, Player cible) {
this.time = System.currentTimeMillis() + ChatItem.getInstance().getConfig().getInt("general.other-placeholders." + id + ".time-expire", 1800) * 1000;
this.uuid = cible.getUniqueId();
this.name = cible.getName();
}
public UUID getUuid() {
return uuid;
}
public long getTimeExpire() {
return time;
}
public boolean hasExpired() {
return System.currentTimeMillis() > time || Bukkit.getPlayer(uuid) == null || !Bukkit.getPlayer(uuid).isOnline();
}
public abstract void open(Player p);
}
@@ -0,0 +1,36 @@
package me.dadus33.chatitem.invsee.hook;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.invsee.InvShower;
import me.dadus33.chatitem.listeners.holder.CustomInventoryHolder;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.Messages;
public class EnderChestShower extends InvShower {
private final ItemStack[] items;
public EnderChestShower(Player cible) {
super("enderchest", cible);
Inventory ec = cible.getEnderChest();
ItemStack[] tmp = ec.getContents();
items = new ItemStack[tmp.length];
for(int i = 0; i < ec.getSize(); i++)
items[i] = ItemUtils.copyIfExist(tmp[i]);
}
@Override
public void open(Player p) {
Inventory inv = Bukkit.createInventory(new CustomInventoryHolder(), items.length, Messages.getMessage("enderchest.name", "%cible%", name));
for(int i = 0; i < items.length; i++)
inv.setItem(i, items[i]);
p.openInventory(inv);
}
}
@@ -0,0 +1,49 @@
package me.dadus33.chatitem.invsee.hook;
import java.util.HashMap;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import me.dadus33.chatitem.invsee.InvShower;
import me.dadus33.chatitem.listeners.holder.CustomInventoryHolder;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.Messages;
public class PlayerInventoryShower extends InvShower {
private final HashMap<Integer, ItemStack> items = new HashMap<>();
private final int level;
public PlayerInventoryShower(Player cible) {
super("inventory", cible);
this.level = cible.getLevel();
PlayerInventory pi = cible.getInventory();
items.put(4, ItemUtils.copyIfExist(pi.getHelmet()));
items.put(5, ItemUtils.copyIfExist(pi.getChestplate()));
items.put(6, ItemUtils.copyIfExist(pi.getLeggings()));
items.put(7, ItemUtils.copyIfExist(pi.getBoots()));
for(int i = 0; i < pi.getContents().length && i < (54 - 18); i++)
items.put(i + 18, ItemUtils.copyIfExist(pi.getContents()[i]));
}
@Override
public void open(Player p) {
Inventory inv = Bukkit.createInventory(new CustomInventoryHolder(), 54, Messages.getMessage("inventory.name", "%cible%", name));
for(int i = 0; i < 18; i++)
inv.setItem(i, ItemUtils.createItem(ItemUtils.getMaterialWithCompatibility("BROWN_STAINED_GLASS_PANE", "STAINED_GLASS_PANE"), ""));
inv.setItem(2, new ItemStack(ItemUtils.getMaterialWithCompatibility("EXPERIENCE_BOTTLE", "EXP_BOTTLE"), level == 0 ? 1 : (level >= 64 ? 64 : level)));
items.forEach(inv::setItem);
p.openInventory(inv);
}
}
@@ -0,0 +1,54 @@
package me.dadus33.chatitem.itemnamer;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.Storage;
public interface INamer {
/**
* Get priority of this namer.<br>
* Get first name that is not null, with this order:
* - MAJOR
*
*
* @return priority
*/
Priority getPriority();
/**
* Get the name of the item thanks to this namer.
*
* @param item the item to get the name
* @param storage the actual config
* @return the name or null if can't find a name
*/
String getName(Player p, ItemStack item, Storage storage);
public enum Priority {
MAJOR(4),
IMPORTANT(3),
MEDIUM(2),
SMALL(1),
MINOR(0);
private final int priority;
Priority(int priority) {
this.priority = priority;
}
public int getPriority() {
return priority;
}
public static List<Priority> getOrderedPriorities() {
return Arrays.stream(values()).sorted((p1, p2) -> p2.getPriority() - p1.getPriority()).collect(Collectors.toList());
}
}
}
@@ -0,0 +1,77 @@
package me.dadus33.chatitem.itemnamer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.StringJoiner;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.PluginManager;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.itemnamer.INamer.Priority;
import me.dadus33.chatitem.itemnamer.hook.ChatItemTranslationNamer;
import me.dadus33.chatitem.itemnamer.hook.DefaultNamer;
import me.dadus33.chatitem.itemnamer.hook.ItemDisplayNamer;
import me.dadus33.chatitem.itemnamer.hook.LangUtilsNamer;
public class NamerManager {
private static final HashMap<Priority, List<INamer>> NAMER_PER_PRIORITY = new HashMap<>();
public static void load(ChatItem pl) {
NAMER_PER_PRIORITY.clear();
StringJoiner sj = new StringJoiner(", ");
PluginManager pm = Bukkit.getPluginManager();
if(pm.getPlugin("LangUtils") != null) {
addNamer(new LangUtilsNamer());
sj.add("LangUtils");
}
if(sj.length() > 0)
pl.getLogger().info("Loaded namer for plugin " + sj.toString() + ".");
addNamer(new ChatItemTranslationNamer());
addNamer(new ItemDisplayNamer());
addNamer(new DefaultNamer());
}
/**
* Add namer according to his {@link INamer#getPriority()}'s value
*
* @param namer the namer to add
*/
public static void addNamer(INamer namer) {
List<INamer> namers = getOrCreate(namer.getPriority());
namers.add(namer);
}
private static List<INamer> getOrCreate(Priority p){
return NAMER_PER_PRIORITY.computeIfAbsent(p, (a) -> new ArrayList<>());
}
/**
* Get the name of this item, according to this storage.
*
* @param p the player that will see the name
* @param item the item to show
* @param storage the storage
* @return the name (should NOT return null)
*/
public static String getName(Player p, ItemStack item, Storage storage) {
for(Priority pr : Priority.getOrderedPriorities()) {
List<INamer> allNamers = NAMER_PER_PRIORITY.get(pr);
if(allNamers == null || allNamers.isEmpty())
continue;
for(INamer namer : allNamers) {
String tmpName = namer.getName(p, item, storage);
if(tmpName != null)
return tmpName;
}
}
return null; // this should NEVER append
}
}
@@ -0,0 +1,22 @@
package me.dadus33.chatitem.itemnamer.hook;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.Translation;
import me.dadus33.chatitem.itemnamer.INamer;
public class ChatItemTranslationNamer implements INamer {
@Override
public Priority getPriority() {
return Priority.SMALL;
}
@Override
public String getName(Player p, ItemStack item, Storage storage) {
return Translation.get(item);
}
}
@@ -0,0 +1,23 @@
package me.dadus33.chatitem.itemnamer.hook;
import org.apache.commons.lang.WordUtils;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.itemnamer.INamer;
public class DefaultNamer implements INamer {
@Override
public Priority getPriority() {
return Priority.MINOR;
}
@Override
public String getName(Player p, ItemStack item, Storage storage) {
Material m = item.getType();
return m.equals(Material.TNT) ? "TNT" : WordUtils.capitalize(m.name().replaceAll("_", " ").toLowerCase());
}
}
@@ -0,0 +1,26 @@
package me.dadus33.chatitem.itemnamer.hook;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.itemnamer.INamer;
public class ItemDisplayNamer implements INamer {
@Override
public Priority getPriority() {
return Priority.MEDIUM;
}
@Override
public String getName(Player p, ItemStack item, Storage storage) {
if(item.hasItemMeta() && item.getItemMeta().hasDisplayName()) {
String name = item.getItemMeta().getDisplayName();
return storage.colorIfColored ? ChatColor.stripColor(name) : name;
}
return null;
}
}
@@ -0,0 +1,23 @@
package me.dadus33.chatitem.itemnamer.hook;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.meowj.langutils.lang.LanguageHelper;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.itemnamer.INamer;
public class LangUtilsNamer implements INamer {
@Override
public Priority getPriority() {
return Priority.IMPORTANT;
}
@Override
public String getName(Player p, ItemStack item, Storage storage) {
return LanguageHelper.getItemName(item, p);
}
}
@@ -1,10 +0,0 @@
package me.dadus33.chatitem.json;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.InvocationTargetException;
public interface JSONManipulator {
String parse(String json, String[] replacements, ItemStack item, String repl) throws InvocationTargetException, IllegalAccessException, InstantiationException;
}
@@ -1,298 +0,0 @@
package me.dadus33.chatitem.json;
import com.google.gson.*;
import me.dadus33.chatitem.utils.Reflect;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.regex.Pattern;
public class JSONManipulatorCurrent implements JSONManipulator{
private static Class<?> craftItemStackClass = Reflect.getOBCClass("inventory.CraftItemStack");
private static Class<?> nmsItemStackClass = Reflect.getNMSClass("ItemStack");
private static Method asNMSCopy = Reflect.getMethod(craftItemStackClass, "asNMSCopy", ItemStack.class);
private static Class<?> nbtTagCompoundClass = Reflect.getNMSClass("NBTTagCompound");
private static Method saveNmsItemStackMethod = Reflect.getMethod(nmsItemStackClass, "save", nbtTagCompoundClass);
private static String[] replaces;
private static String rgx;
private static JsonArray toUse;
private static JsonParser parser = new JsonParser();
public String parse(String json, String[] replacements, ItemStack item, String repl) throws InvocationTargetException, IllegalAccessException, InstantiationException {
JsonObject obj = parser.parse(json).getAsJsonObject();
JsonArray array = obj.getAsJsonArray("extra");
replaces = replacements;
String regex = "";
for (int i = 0; i < replacements.length; ++i) {
if (replacements.length == 1) {
regex = Pattern.quote(replacements[0]);
break;
}
if (i == 0 || i + 1 == replacements.length) {
if (i == 0) {
regex = "(" + Pattern.quote(replacements[i]);
} else {
regex = regex.concat("|").concat(Pattern.quote(replacements[i])).concat(")");
}
continue;
}
regex = regex.concat("|").concat(Pattern.quote(replacements[i]));
}
rgx = regex;
JsonArray rep = new JsonArray();
repl = escapeBackslash(repl);
JsonArray use = parser.parse(Translator.toJSON(repl)).getAsJsonArray();
JsonObject hover = parser.parse("{\"action\":\"show_item\", \"value\": \"\"}").getAsJsonObject();
Object nmsStack = asNMSCopy.invoke(null, item);
Object tag = nbtTagCompoundClass.newInstance();
tag = saveNmsItemStackMethod.invoke(nmsStack, tag);
String jsonRep = escapeBackslash(tag.toString());
hover.addProperty("value", jsonRep);
for (JsonElement ob : use)
ob.getAsJsonObject().add("hoverEvent", hover);
toUse = use;
for (int i = 0; i < array.size(); ++i) {
if (array.get(i).isJsonObject()){
JsonObject o = array.get(i).getAsJsonObject();
boolean inside = false;
for (String replacement : replacements)
if (o.toString().contains(replacement)) {
if (inside) {
break;
}
inside = true;
}
JsonElement text = o.get("text");
if (text == null) {
JsonElement el = o.get("extra");
if (el != null) {
JsonArray jar = el.getAsJsonArray();
jar = parseArray(jar);
o.add("extra", jar);
}
continue;
} else {
if (text.getAsString().isEmpty()) {
JsonElement el = o.get("extra");
if (el != null) {
JsonArray jar = el.getAsJsonArray();
jar = parseArray(jar);
o.add("extra", jar);
}
}
}
String msg = text.getAsString();
boolean isLast = false;
boolean done = false;
boolean fnd;
String[] splits;
for (String repls : replacements) {
if (done) {
break;
}
isLast = msg.endsWith(repls);
if (isLast) {
done = true;
msg = msg.concat(".");
}
}
splits = msg.split(regex);
fnd = splits.length != 1;
if (fnd)
for (int j = 0; j < splits.length; ++j) {
boolean endDot = (j == splits.length - 1) && isLast;
if (!splits[j].isEmpty() && !endDot) {
String st = o.toString();
JsonObject fix = parser.parse(st).getAsJsonObject();
fix.addProperty("text", splits[j]);
rep.add(fix);
}
if (j != splits.length - 1) {
rep.addAll(use);
}
}
if (!fnd) {
rep.add(o);
}
}else{
if(array.get(i).isJsonNull()){
continue;
}else{
if(array.get(i).isJsonArray()){
JsonArray jar = parseArray(array.get(i).getAsJsonArray());
rep.set(i, jar);
}else{
String msg = array.get(i).getAsString();
boolean isLast = false;
boolean done = false;
boolean fnd;
String[] splits;
for (String repls : replacements) {
if (done) {
break;
}
isLast = msg.endsWith(repls);
if (isLast) {
done = true;
msg = msg.concat(".");
}
}
splits = msg.split(regex);
fnd = splits.length != 1;
if (fnd)
for (int j = 0; j < splits.length; ++j) {
boolean endDot = (j == splits.length - 1) && isLast;
if (!splits[j].isEmpty() && !endDot) {
JsonElement fix = new JsonPrimitive(splits[j]);
rep.add(fix);
}
if (j != splits.length - 1) {
rep.addAll(use);
}
}
if (!fnd) {
rep.add(array.get(i));
}
}
}
}
}
obj.add("extra", rep);
return obj.toString();
}
private static JsonArray parseArray(JsonArray arr) {
JsonArray replacer = new JsonArray();
for (int i = 0; i < arr.size(); ++i) {
if (arr.get(i).isJsonObject()){
JsonObject o = arr.get(i).getAsJsonObject();
boolean inside = false;
for (String replacement : replaces)
if (o.toString().contains(replacement)) {
if (inside) {
break;
}
inside = true;
}
if (!inside) { //the placeholder we're looking for is not inside this element, so we continue searching
continue;
}
JsonElement text = o.get("text");
if (text == null) {
continue;
}
if (text.getAsString().isEmpty()) {
JsonElement el = o.get("extra");
if (el == null) {
continue;
}
JsonArray jar = el.getAsJsonArray();
jar = parseArray(jar);
o.add("extra", jar);
}
String msg = text.getAsString();
boolean isLast = false;
boolean done = false;
boolean fnd;
String[] splits;
for (String repls : replaces) {
if (done) {
break;
}
isLast = msg.endsWith(repls);
if (isLast) {
done = true;
msg = msg.concat(".");
}
}
splits = msg.split(rgx);
fnd = splits.length != 1;
if (fnd)
for (int j = 0; j < splits.length; ++j) {
boolean endDot = (j == splits.length - 1) && isLast;
if (!splits[j].isEmpty() && !endDot) {
String st = o.toString();
JsonObject fix = parser.parse(st).getAsJsonObject();
fix.addProperty("text", splits[j]);
replacer.add(fix);
}
if (j != splits.length - 1) {
replacer.addAll(toUse);
}
}
if (!fnd) {
replacer.add(o);
}
}else{
if(arr.get(i).isJsonNull()){
continue;
}else{
if(arr.get(i).isJsonArray()){
JsonArray jar = parseArray(arr.get(i).getAsJsonArray());
replacer.set(i, jar);
}else{
String msg = arr.get(i).getAsString();
boolean isLast = false;
boolean done = false;
boolean fnd;
String[] splits;
for (String repls : replaces) {
if (done) {
break;
}
isLast = msg.endsWith(repls);
if (isLast) {
done = true;
msg = msg.concat(".");
}
}
splits = msg.split(rgx);
fnd = splits.length != 1;
if (fnd)
for (int j = 0; j < splits.length; ++j) {
boolean endDot = (j == splits.length - 1) && isLast;
if (!splits[j].isEmpty() && !endDot) {
JsonElement fix = new JsonPrimitive(splits[j]);
replacer.add(fix);
}
if (j != splits.length - 1) {
replacer.addAll(toUse);
}
}
if (!fnd) {
replacer.add(arr.get(i));
}
}
}
}
}
return replacer;
}
private static String escapeBackslash(String json){
json = json.replace("\\", "\\\\");
return json;
}
}
@@ -1,91 +0,0 @@
package me.dadus33.chatitem.json;
import org.bukkit.ChatColor;
/*
Many thanks to @DarkSeraphim for this!
I only modified his work to make it compatible with what I was building.
*/
public class Translator {
private static final StringBuilder BUILDER = new StringBuilder("");
private static final StringBuilder STYLE = new StringBuilder();
static String toJSON(String message) {
if (message == null || message.isEmpty())
return null;
String[] parts = message.split(Character.toString(ChatColor.COLOR_CHAR));
boolean first = true;
String colour = null;
String format = null;
BUILDER.setLength(0);
BUILDER.append("[");
boolean ignoreFirst = !parts[0].isEmpty() && ChatColor.getByChar(parts[0].charAt(0)) != null;
for (String part : parts) {
if (part.isEmpty()) {
continue;
}
String newStyle = null;
if (!ignoreFirst) {
newStyle = getStyle(part.charAt(0));
} else {
ignoreFirst = false;
}
if (newStyle != null) {
part = part.substring(1);
if (newStyle.startsWith("\"c"))
colour = newStyle;
else
format = newStyle;
}
if (!part.isEmpty()) {
if (first)
first = false;
else {
BUILDER.append(", ");
}
BUILDER.append("{");
if (colour != null) {
BUILDER.append(colour);
colour = null;
}
if (format != null) {
BUILDER.append(format);
format = null;
}
BUILDER.append(String.format("\"text\":\"%s\"", part));
BUILDER.append("}");
}
}
BUILDER.append("]");
return BUILDER.toString();
}
private static String getStyle(char colour) {
if (STYLE.length() > 0)
STYLE.delete(0, STYLE.length());
switch (colour) {
case 'k':
return "\"obfuscated\": true,";
case 'l':
return "\"bold\": true,";
case 'm':
return "\"strikethrough\": true,";
case 'n':
return "\"underlined\": true,";
case 'o':
return "\"italic\": true,";
case 'r':
return "\"reset\": true,";
default:
break;
}
ChatColor cc = ChatColor.getByChar(colour);
if (cc == null)
return null;
return STYLE.append("\"color\":\"").append(cc.name().toLowerCase()).append("\", ").toString();
}
}
@@ -1,159 +0,0 @@
package me.dadus33.chatitem.listeners;
import me.dadus33.chatitem.utils.Storage;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
public class ChatEventListener implements Listener {
private Storage c;
private final static char SEPARATOR = ((char)0x0007);
public ChatEventListener(Storage storage) {
c = storage;
}
private int countOccurrences(String findStr, String str){
int lastIndex = 0;
int count = 0;
while(lastIndex != -1){
lastIndex = str.indexOf(findStr,lastIndex);
if(lastIndex != -1){
count ++;
lastIndex += findStr.length();
}
}
return count;
}
@SuppressWarnings("deprecation")
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onChat(AsyncPlayerChatEvent e) {
if(e.getMessage().indexOf(SEPARATOR)!=-1){ //If the BELL character is found, we have to remove it
String msg = e.getMessage().replace(Character.toString(SEPARATOR), "");
e.setMessage(msg);
}
boolean found = false;
for (String rep : c.PLACEHOLDERS)
if (e.getMessage().contains(rep)) {
found = true;
break;
}
if (!found) {
return;
}
if (!e.getPlayer().hasPermission("chatitem.use")) {
e.setCancelled(true);
return;
}
if (e.getPlayer().getItemInHand().getType().equals(Material.AIR)) {
if (c.DENY_IF_NO_ITEM) {
e.setCancelled(true);
if (!c.DENY_MESSAGE.isEmpty())
e.getPlayer().sendMessage(c.DENY_MESSAGE);
return;
}
return;
}
String s = e.getMessage();
for(String placeholder : c.PLACEHOLDERS){
s = s.replace(placeholder, c.PLACEHOLDERS.get(0));
}
int occurrences = countOccurrences(c.PLACEHOLDERS.get(0), s);
if(occurrences>c.LIMIT){
e.setCancelled(true);
if(c.LIMIT_MESSAGE.isEmpty()){
return;
}
e.getPlayer().sendMessage(c.LIMIT_MESSAGE);
return;
}
String oldmsg = e.getMessage();
StringBuilder sb = new StringBuilder(oldmsg);
sb.append(SEPARATOR).append(e.getPlayer().getName());
e.setMessage(sb.toString());
Bukkit.getConsoleSender().sendMessage(String.format(e.getFormat(), e.getPlayer().getDisplayName(), oldmsg));
}
@SuppressWarnings("deprecation")
@EventHandler(priority = EventPriority.NORMAL)
public void onCommand(PlayerCommandPreprocessEvent e){
if(e.getMessage().indexOf(SEPARATOR)!=-1){ //If the BELL character is found, we have to remove it
String msg = e.getMessage().replace(Character.toString(SEPARATOR), "");
e.setMessage(msg);
}
Command cmd = Bukkit.getPluginCommand(e.getMessage().split(" ")[0].substring(1));
if(cmd==null){ //not a plugin command
return;
}
if(!c.ALLOWED_COMMANDS.contains(cmd)){
return;
}
boolean found = false;
for (String rep : c.PLACEHOLDERS) {
if (e.getMessage().contains(rep)) {
found = true;
break;
}
}
if (!found) {
return;
}
if (!e.getPlayer().hasPermission("chatitem.use")) {
e.setCancelled(true);
return;
}
if (e.getPlayer().getItemInHand().getType().equals(Material.AIR)) {
if (c.DENY_IF_NO_ITEM) {
e.setCancelled(true);
if (!c.DENY_MESSAGE.isEmpty())
e.getPlayer().sendMessage(c.DENY_MESSAGE);
}
return;
}
String s = e.getMessage();
for(String placeholder : c.PLACEHOLDERS){
s = s.replace(placeholder, c.PLACEHOLDERS.get(0));
}
int occurrences = countOccurrences(c.PLACEHOLDERS.get(0), s);
if(occurrences>c.LIMIT){
e.setCancelled(true);
if(c.LIMIT_MESSAGE.isEmpty()){
return;
}
e.getPlayer().sendMessage(c.LIMIT_MESSAGE);
return;
}
StringBuilder sb = new StringBuilder(e.getMessage());
sb.append(SEPARATOR).append(e.getPlayer().getName());
e.setMessage(sb.toString());
}
public void setStorage(Storage st) {
c = st;
}
}
@@ -1,188 +0,0 @@
package me.dadus33.chatitem.listeners;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.utils.Storage;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
public class ChatPacketListener extends PacketAdapter {
private final static String NAME = "{name}";
private final static String AMOUNT = "{amount}";
private final static String TIMES = "{times}";
private ChatItem instance;
private Storage c;
public ChatPacketListener(Plugin plugin, ListenerPriority listenerPriority, Storage s, PacketType... types) {
super(plugin, listenerPriority, types);
this.instance = (ChatItem) plugin;
c = s;
}
private static String materialToName(Material m) {
if (m.equals(Material.TNT)) {
return "TNT";
}
String orig = m.toString().toLowerCase();
String[] splits = orig.split("_");
StringBuilder sb = new StringBuilder(orig.length());
int pos = 0;
for (String split : splits) {
sb.append(split);
int loc = sb.lastIndexOf(split);
char charLoc = sb.charAt(loc);
if (!(split.equalsIgnoreCase("of") || split.equalsIgnoreCase("and") ||
split.equalsIgnoreCase("with") || split.equalsIgnoreCase("on")))
sb.setCharAt(loc, Character.toUpperCase(charLoc));
if (pos != splits.length - 1)
sb.append(' ');
++pos;
}
return sb.toString();
}
@SuppressWarnings("deprecation")
@Override
public void onPacketSending(PacketEvent e) {
if(ChatItem.post17) //actionbar messages are only available after 1.7
if (e.getPacket().getBytes().readSafely(0) == (byte) 2) {
return; //It means it's an actionbar message, and we ain't intercepting those
}
PacketContainer packet = e.getPacket();
if(packet.getChatComponents().readSafely(0)==null){ // null check for some cases of messages from other plugins
return;
}
String json = packet.getChatComponents().readSafely(0).getJson();
boolean found = false;
for (String rep : c.PLACEHOLDERS)
if (json.contains(rep)) {
found = true;
break;
}
if (!found) {
return; //then it's just a normal message without placeholders, so we leave it alone
}
if(json.lastIndexOf("\\u0007")==-1){ //if the message doesn't contain the BEL separator, then it's certainly NOT a message we want to parse
return;
}
//here we find the last player name in the string
int topIndex = -1;
String name = null;
for(Player p : Bukkit.getOnlinePlayers()){
String pname = p.getName();
if(!json.contains(pname)){
continue;
}
int index = json.lastIndexOf(pname)+pname.length();
if(index>topIndex){
topIndex = index;
name = pname;
}
}
if(name==null){ //something went really bad, so we run away and hide
return;
}
//then we make sure the name is after the BEL separator.
if(json.lastIndexOf(name)!=json.lastIndexOf("\\u0007")+6){
return; //then it means somehow the message just contained a BEL character not inserted by our plugin
}
Player p = Bukkit.getPlayer(name);
StringBuilder buff = new StringBuilder(json);
buff.replace(topIndex-(name.length()+6), topIndex, ""); //we remove both the name and the separator from the json string
json = buff.toString();
//Item Styling
//STYLE BEGIN
ItemStack inHand = p.getItemInHand();
String replacer = c.NAME_FORMAT;
String amount = c.AMOUNT_FORMAT;
boolean dname = false;
if (!c.COLOR_IF_ALREADY_COLORED && inHand.hasItemMeta()) {
if (inHand.getItemMeta().hasDisplayName()) {
replacer = ChatColor.stripColor(replacer);
dname = true;
}
} else {
if (inHand.hasItemMeta()) {
if (inHand.getItemMeta().hasDisplayName()) {
dname = true;
}
}
}
if (inHand.getAmount() == 1) {
if (c.FORCE_ADD_AMOUNT) {
amount = amount.replace(TIMES, "1");
replacer = replacer.replace(AMOUNT, amount);
} else {
replacer = replacer.replace(AMOUNT, "");
}
} else {
amount = amount.replace(TIMES, String.valueOf(inHand.getAmount()));
replacer = replacer.replace(AMOUNT, amount);
}
if (dname) {
String trp = inHand.getItemMeta().getDisplayName();
replacer = replacer.replace(NAME, trp);
} else {
HashMap<Short, String> translationSection = c.TRANSLATIONS.get(inHand.getType().name());
if(translationSection==null){
String trp = materialToName(inHand.getType());
replacer = replacer.replace(NAME, trp);
}else {
String translated = translationSection.get(inHand.getDurability());
if (translated != null) {
replacer = replacer.replace(NAME, translated);
} else {
replacer = replacer.replace(NAME, materialToName(inHand.getType()));
}
}
}
//STYLE END
String[] reps = new String[c.PLACEHOLDERS.size()];
c.PLACEHOLDERS.toArray(reps);
String message = null;
try {
if(!p.getItemInHand().getType().equals(Material.AIR))
message = ChatItem.getManipulator().parse(json, reps, p.getItemInHand(), replacer);
} catch (InvocationTargetException | IllegalAccessException | InstantiationException e1) {
e1.printStackTrace();
}
if(message!=null)
packet.getChatComponents().writeSafely(0, WrappedChatComponent.fromJson(message));
else
e.setCancelled(true);
}
public void setStorage(Storage st) {
c = st;
}
}
@@ -0,0 +1,143 @@
package me.dadus33.chatitem.listeners;
import static me.dadus33.chatitem.utils.ItemUtils.createItem;
import java.util.Arrays;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.Storage;
import me.dadus33.chatitem.Translation;
import me.dadus33.chatitem.listeners.holder.AdminHolder;
import me.dadus33.chatitem.listeners.holder.ChatItemHolder;
import me.dadus33.chatitem.listeners.holder.CustomInventoryHolder;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.Messages;
public class InventoryListener implements Listener {
@EventHandler
public void onClick(InventoryClickEvent e) {
Player p = (Player) e.getWhoClicked();
if(e.getClickedInventory() == null || !(e.getWhoClicked() instanceof Player))
return;
InventoryHolder holder = e.getClickedInventory().getHolder();
if(holder == null || !(holder instanceof ChatItemHolder)) {
if(e.getClick().equals(ClickType.DOUBLE_CLICK) && p.getOpenInventory() != null && p.getOpenInventory().getTopInventory() != null) {
Inventory top = p.getOpenInventory().getTopInventory();
if(top.getHolder() != null && top.getHolder() instanceof ChatItemHolder) {
e.setCancelled(true);
}
}
return;
}
if(holder instanceof CustomInventoryHolder) {
e.setCancelled(true);
return;
}
if(!(holder instanceof AdminHolder))
return;
e.setCancelled(true);
if(e.getCurrentItem() == null)
return;
ItemStack item = e.getCurrentItem();
Material type = item.getType();
Storage c = ChatItem.getInstance().getStorage();
if(type.equals(ItemUtils.MATERIAL_CLOSE)) {
p.closeInventory();
} else if(type.equals(Material.BOOK)) {
TranslationInventoryListener.open(p, 0);
} else if(type.equals(Material.PAPER)) {
String key = ((AdminHolder) holder).keyBySlot.get(e.getSlot());
if(key != null) {
setInConfig("manager", key);
p.closeInventory();
ChatItem.reload(p);
}
} else if(type.equals(ItemUtils.INK_SAC)) {
setInConfig("general.color-if-already-colored", c.colorIfColored = !c.colorIfColored);
open(p);
} else if(type.equals(Material.STICK)) {
setInConfig("general.hand.disabled", c.handDisabled = !c.handDisabled);
open(p);
} else if(type.equals(Material.BLAZE_ROD)) {
setInConfig("general.check-update", c.checkUpdate = !c.checkUpdate);
open(p);
} else if(type.equals(ItemUtils.FIREWORK_CHARGE)) {
setInConfig("debug", c.debug = !c.debug);
open(p);
} else if(type.equals(Material.IRON_DOOR)) {
if(e.getClick().equals(ClickType.RIGHT))
c.limit--;
else if(e.getClick().equals(ClickType.LEFT))
c.limit++;
setInConfig("general.limit-per-message", c.limit);
open(p);
} else if(type.equals(Material.APPLE)) {
if(e.getClick().equals(ClickType.RIGHT))
c.cooldown--;
else if(e.getClick().equals(ClickType.LEFT))
c.cooldown++;
setInConfig("general.cooldown", c.cooldown);
open(p);
}
}
public static void setInConfig(String key, Object val) {
ChatItem pl = ChatItem.getInstance();
pl.getConfig().set(key, val);
pl.saveConfig();
}
public static void open(Player p) {
AdminHolder holder = new AdminHolder();
Storage c = ChatItem.getInstance().getStorage();
Inventory inv = Bukkit.createInventory(holder, 27, Messages.getMessage("admin-inv.name"));
for(int i = 0; i < inv.getSize(); i ++)
inv.setItem(i, createItem(ItemUtils.WHITE_STAINED_GLASS, "-"));
int slot = 0;
for(String manager : Arrays.asList("both", "auto", "packet", "chat")) {
holder.keyBySlot.put(slot, manager);
inv.setItem(slot++, getManagerItem(manager));
}
inv.setItem(slot + 1, getManagerItem("actual", "%manager%", Messages.getMessage("admin-inv.manager." + c.manager + ".name")));
inv.setItem(8, getBoolChangeItem(ItemUtils.FIREWORK_CHARGE, "debug", c.debug));
inv.setItem(18, getBoolChangeItem(ItemUtils.INK_SAC, "color-if-already-colored", c.colorIfColored));
inv.setItem(20, getBoolChangeItem(Material.STICK, "hand-disabled", c.handDisabled));
inv.setItem(21, getAmountChangeItem(Material.IRON_DOOR, "limit-per-message", c.limit));
inv.setItem(22, getAmountChangeItem(Material.APPLE, "cooldown", c.cooldown));
inv.setItem(23, getBoolChangeItem(Material.BLAZE_ROD, "check-update", c.checkUpdate));
inv.setItem(24, createItem(Material.BOOK, Messages.getMessage("admin-inv.language.name"),
Messages.getMessage("admin-inv.language.lore", "%name%", Translation.getMessages().get("language.name").getAsString())));
inv.setItem(26, createItem(ItemUtils.MATERIAL_CLOSE, Messages.getMessage("admin-inv.close")));
p.openInventory(inv);
}
private static ItemStack getBoolChangeItem(Material type, String key, boolean b) {
return createItem(type, Messages.getMessage("admin-inv." + key, "%state%", Messages.getMessage(b ? "enabled" : "disabled")), Messages.getMessageList("admin-inv.bool-lore"));
}
private static ItemStack getAmountChangeItem(Material type, String key, int amount) {
return createItem(type, Messages.getMessage("admin-inv." + key, "%state%", amount), Messages.getMessageList("admin-inv.amount-lore"));
}
private static ItemStack getManagerItem(String manager, Object... placeholders) {
return createItem(Material.PAPER, Messages.getMessage("admin-inv.manager." + manager + ".name", placeholders),
Messages.getMessageList("admin-inv.manager." + manager + ".lore", placeholders));
}
}
@@ -0,0 +1,35 @@
package me.dadus33.chatitem.listeners;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.utils.Utils;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.TextComponent;
public class JoinListener implements Listener {
@EventHandler
public void onJoin(PlayerJoinEvent e) {
Player p = e.getPlayer();
if(!p.isOp())
return;
ChatItem pl = ChatItem.getInstance();
if(pl.isHasNewVersion()) {
TextComponent text = new TextComponent(pl.getStorage().updateMessage);
text.setHoverEvent(Utils.createTextHover(pl.getStorage().updateHover));
text.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.spigotmc.org/resources/19064/"));
p.spigot().sendMessage(text);
}
}
@EventHandler
public void onLeft(PlayerQuitEvent e) {
ChatManager.clear(e.getPlayer());
}
}
@@ -0,0 +1,95 @@
package me.dadus33.chatitem.listeners;
import static me.dadus33.chatitem.utils.ItemUtils.createItem;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.Translation;
import me.dadus33.chatitem.listeners.holder.TranslationHolder;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.Messages;
public class TranslationInventoryListener implements Listener {
@EventHandler
public void onClick(InventoryClickEvent e) {
if(e.getClickedInventory() == null || !(e.getWhoClicked() instanceof Player) || e.getCurrentItem() == null
|| !(e.getClickedInventory().getHolder() instanceof TranslationHolder))
return;
e.setCancelled(true);
Player p = (Player) e.getWhoClicked();
ItemStack item = e.getCurrentItem();
Material type = item.getType();
TranslationHolder holder = (TranslationHolder) e.getClickedInventory().getHolder();
if(type.equals(Material.ARROW)) {
if(e.getSlot() == 0)
InventoryListener.open(p);
else if(e.getSlot() == 3)
open(p, holder.getPage() - 1);
else if(e.getSlot() == 5)
open(p, holder.getPage() + 1);
} else if(type.equals(ItemUtils.MATERIAL_CLOSE))
p.closeInventory();
else if(type.equals(Material.PAPER)) {
String lang = holder.langBySlot.get(e.getSlot());
if(lang == null)
return;
p.closeInventory();
ChatItem pl = ChatItem.getInstance();
pl.getStorage().language = lang;
pl.getConfig().set("general.language", lang);
pl.saveConfig();
Translation.loadLang(lang);
p.sendMessage(ChatColor.GREEN + "Language changed to " + Translation.getMessages().get("language.name").getAsString());
}
}
public static void open(Player p, int page) {
int perPage = 45;
List<String> langs = new ArrayList<>(Translation.getAllLangs().keySet());
TranslationHolder holder = new TranslationHolder(page);
Inventory inv = Bukkit.createInventory(holder, 54, "Change language - " + ChatColor.GOLD + " Page " + (page + 1) + " / " + ((langs.size() / perPage) + 1));
for(int i = 0; i < 9; i ++)
inv.setItem(i, new ItemStack(ItemUtils.GRAY_STAINED_GLASS_PANE));
inv.setItem(0, createItem(Material.ARROW, ChatColor.GRAY + "Back"));
if(page > 0)
inv.setItem(3, createItem(Material.ARROW, ChatColor.RED + "Previous page"));
if(langs.size() > (perPage * (page + 1)))
inv.setItem(5, createItem(Material.ARROW, ChatColor.GREEN + "Next page"));
inv.setItem(8, createItem(ItemUtils.MATERIAL_CLOSE, Messages.getMessage("admin-inv.close")));
int slot = 9;
for(int i = (page * perPage); i < langs.size() && (i < ((page + 1) * perPage)); i++) {
String lang = langs.get(i);
holder.langBySlot.put(slot, lang);
ItemStack item = createItem(Material.PAPER, ChatColor.GOLD + Translation.getAllLangs().get(lang), ChatColor.GRAY + "Clic to select this language");
if(lang.equalsIgnoreCase(ChatItem.getInstance().getStorage().language)) {
item.addUnsafeEnchantment(Enchantment.DURABILITY, 1);
ItemMeta meta = item.getItemMeta();
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
item.setItemMeta(meta);
}
inv.setItem(slot++, item);
}
p.openInventory(inv);
}
}
@@ -0,0 +1,9 @@
package me.dadus33.chatitem.listeners.holder;
import java.util.HashMap;
public class AdminHolder extends ChatItemHolder {
public final HashMap<Integer, String> keyBySlot = new HashMap<>();
}
@@ -0,0 +1,12 @@
package me.dadus33.chatitem.listeners.holder;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
public abstract class ChatItemHolder implements InventoryHolder {
@Override
public Inventory getInventory() {
return null;
}
}
@@ -0,0 +1,5 @@
package me.dadus33.chatitem.listeners.holder;
public class CustomInventoryHolder extends ChatItemHolder {
}
@@ -0,0 +1,17 @@
package me.dadus33.chatitem.listeners.holder;
import java.util.HashMap;
public class TranslationHolder extends ChatItemHolder {
public final HashMap<Integer, String> langBySlot = new HashMap<>();
private final int page;
public TranslationHolder(int page) {
this.page = page;
}
public int getPage() {
return page;
}
}
@@ -0,0 +1,11 @@
package me.dadus33.chatitem.playernamer;
import org.bukkit.entity.Player;
import net.md_5.bungee.api.chat.BaseComponent;
public interface IPlayerNamer {
public BaseComponent[] getName(Player p);
}
@@ -0,0 +1,42 @@
package me.dadus33.chatitem.playernamer;
import me.dadus33.chatitem.playernamer.hook.HexNicksV3PlayerNamer;
import org.bukkit.Bukkit;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.playernamer.hook.DefaultPlayerNamer;
import me.dadus33.chatitem.playernamer.hook.HexNicksV2PlayerNamer;
import org.bukkit.plugin.Plugin;
public class PlayerNamerManager {
private static IPlayerNamer playerNamer;
public static IPlayerNamer getPlayerNamer() {
return playerNamer;
}
public static void setPlayerNamer(IPlayerNamer playerNamer) {
PlayerNamerManager.playerNamer = playerNamer;
}
public static void load(ChatItem pl) {
Plugin plugin = Bukkit.getPluginManager().getPlugin("HexNicks");
if (plugin != null) {
char majorVersion = plugin.getDescription().getVersion().charAt(0);
if (majorVersion == '3')
setPlayerNamer(new HexNicksV3PlayerNamer());
else
setPlayerNamer(new HexNicksV2PlayerNamer());
pl.getLogger().info("Enable support for HexNicks plugin v" + majorVersion);
return;
}
setPlayerNamer(new DefaultPlayerNamer());
}
}
@@ -0,0 +1,15 @@
package me.dadus33.chatitem.playernamer.hook;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.playernamer.IPlayerNamer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ComponentBuilder;
public class DefaultPlayerNamer implements IPlayerNamer {
@Override
public BaseComponent[] getName(Player p) {
return new ComponentBuilder(p.getName()).create();
}
}
@@ -0,0 +1,17 @@
package me.dadus33.chatitem.playernamer.hook;
import org.bukkit.entity.Player;
import dev.majek.hexnicks.Nicks;
import me.dadus33.chatitem.playernamer.IPlayerNamer;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.chat.BaseComponent;
public class HexNicksV2PlayerNamer implements IPlayerNamer {
@Override
public BaseComponent[] getName(Player p) {
return BungeeComponentSerializer.get().serialize(Nicks.api().getStoredNick(p).join());
}
}
@@ -0,0 +1,17 @@
package me.dadus33.chatitem.playernamer.hook;
import dev.majek.hexnicks.HexNicks;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.playernamer.IPlayerNamer;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.chat.BaseComponent;
public class HexNicksV3PlayerNamer implements IPlayerNamer {
@Override
public BaseComponent[] getName(Player p) {
return BungeeComponentSerializer.get().serialize(HexNicks.api().getStoredNick(p).join());
}
}
@@ -0,0 +1,14 @@
package me.dadus33.chatitem.playerversion;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.utils.Version;
public interface IPlayerVersion {
public int getProtocolVersion(Player p);
default Version getPlayerVersion(Player p) {
return Version.getVersion(getProtocolVersion(p), Version.getVersion());
}
}
@@ -0,0 +1,29 @@
package me.dadus33.chatitem.playerversion;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.playerversion.hooks.DefaultVersionHook;
import me.dadus33.chatitem.playerversion.hooks.ProtocolSupportHook;
import me.dadus33.chatitem.playerversion.hooks.ViaVersionHook;
import org.bukkit.Bukkit;
public class PlayerVersionManager {
private static final IPlayerVersion playerVersionAdapter;
static {
ChatItem pl = ChatItem.getInstance();
if (Bukkit.getPluginManager().getPlugin("ProtocolSupport") != null) {
playerVersionAdapter = new ProtocolSupportHook();
pl.getLogger().info("Loading ProtocolSupport support ...");
} else if (Bukkit.getPluginManager().getPlugin("ViaVersion") != null) {
playerVersionAdapter = new ViaVersionHook();
pl.getLogger().info("Loading ViaVersion support ...");
} else {
playerVersionAdapter = new DefaultVersionHook();
}
}
public static IPlayerVersion getPlayerVersionAdapter() {
return playerVersionAdapter;
}
}
@@ -0,0 +1,14 @@
package me.dadus33.chatitem.playerversion.hooks;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.playerversion.IPlayerVersion;
import me.dadus33.chatitem.utils.Version;
public class DefaultVersionHook implements IPlayerVersion {
@Override
public int getProtocolVersion(Player p) {
return Version.getVersion().MAX_VER;
}
}
@@ -0,0 +1,15 @@
package me.dadus33.chatitem.playerversion.hooks;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.playerversion.IPlayerVersion;
import protocolsupport.api.ProtocolSupportAPI;
public class ProtocolSupportHook implements IPlayerVersion {
@Override
public int getProtocolVersion(Player p) {
return ProtocolSupportAPI.getProtocolVersion(p).getId();
}
}
@@ -0,0 +1,15 @@
package me.dadus33.chatitem.playerversion.hooks;
import org.bukkit.entity.Player;
import com.viaversion.viaversion.api.Via;
import me.dadus33.chatitem.playerversion.IPlayerVersion;
public class ViaVersionHook implements IPlayerVersion {
@Override
public int getProtocolVersion(Player p) {
return Via.getAPI().getPlayerVersion(p.getUniqueId());
}
}
@@ -0,0 +1,121 @@
package me.dadus33.chatitem.utils;
import java.util.Arrays;
import java.util.List;
import me.dadus33.chatitem.ChatItem;
import net.md_5.bungee.api.ChatColor;
public class ColorManager {
public static final List<String> COLORS = Arrays.asList("4", "c", "6", "e", "2", "a", "b", "3", "1", "9", "d", "5", "f", "7", "8", "0");
public static boolean isHexColor(ChatColor c) {
return Version.getVersion().isNewerOrEquals(Version.V1_16) && c.getName().startsWith("#");
}
public static boolean isHexColor(String c) {
return Version.getVersion().isNewerOrEquals(Version.V1_16) && c.startsWith("x");
}
public static String removeColorAtBegin(String s) {
if(s == null || s.isEmpty())
return "";
boolean wasColorChar = s.startsWith(Character.toString(ChatColor.COLOR_CHAR));
if(!wasColorChar)
return s;
String next = "";
for(int i = 1; i < s.length(); i++) {
char c = s.charAt(i);
if(wasColorChar) {
if(!COLORS.contains(Character.toString(c)))
next = next + ChatColor.COLOR_CHAR + "" + c;
wasColorChar = false;
} else {
wasColorChar = c == ChatColor.COLOR_CHAR;
if(!wasColorChar) { // something other than color code
next += s.substring(i);
break;
}
}
}
if(next.isEmpty())
next = s;
return next;
}
public static String getColorString(String input) {
if (input == null || input.isEmpty())
return "";
StringBuilder str = new StringBuilder();
if (isHexColor(input)) { // x mean it's an hex
input = input.substring(1);
if (input.length() >= 6) { // at least hex
str.append(ChatColor.of("#" + input.substring(0, 6))); // get first hex color code
ChatItem.debug("Str with hex: " + str);
if (input.length() > 6) // if as another color code
str.append(getColorString(input.substring(6))); // get color for after
return str.toString();
} else
ChatItem.debug("Low len: " + input.length());
}
// not hex
for (char c : input.toCharArray())
str.append(ChatColor.getByChar(c));
return str.toString();
}
public static ChatColor getColor(String input) {
if (input == null || input.isEmpty())
return ChatColor.RESET;
if (isHexColor(input)) { // x mean it's an hex
if (input.length() >= 7) { // at least hex, and 7 because we count the "x"
return ChatColor.of("#" + input.substring(1, 7)); // get first hex color code
} else
ChatItem.debug("Low len: " + input.length());
}
// not hex
return ChatColor.getByChar(input.charAt(0));
}
public static String fixColor(String message) {
String colorCode = "", text = "";
boolean waiting = false;
for (char args : message.toCharArray()) {
if (args == '§') { // begin of color
waiting = true; // waiting for color code
} else if (waiting) { // if waiting for code and valid str
// if it's hexademical value and with enough space for full color
waiting = false;
if (args == 'r' && colorCode.isEmpty()) {
text += ChatColor.RESET;
continue;
}
if (args == 'x' && !colorCode.isEmpty()) {
text += ColorManager.getColorString(colorCode);
colorCode = "x";
} else if(Character.digit(Character.toLowerCase(args), 16) != -1)
colorCode += args; // a color by itself
} else {
waiting = false;
if (!colorCode.isEmpty()) {
if (isHexColor(colorCode) && colorCode.length() >= 7) {
if (colorCode.length() == 7)
text += ColorManager.getColor(colorCode);
else {
text += ColorManager.getColor(colorCode.substring(0, 7)); // only the hex code
text += ColorManager.getColorString(colorCode.substring(7, colorCode.length()));
}
} else if (colorCode.length() == 1) // if only one color code
text += ColorManager.getColor(colorCode);
else
text += ColorManager.getColorString(colorCode);
colorCode = "";
}
// basic text, not waiting for code after '§'
text += args;
}
}
return text;
}
}
@@ -1,25 +0,0 @@
package me.dadus33.chatitem.utils;
import me.dadus33.chatitem.ChatItem;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import java.util.logging.Level;
public class General {
private static Storage c;
public static void checkConfigVersion() {
int latestVersion = ChatItem.CFG_VER;
if (latestVersion != c.CONFIG_VERSION) {
Bukkit.getLogger().log(Level.WARNING, ChatColor.RED + "ChatItem detected an older or invalid configuration file. Replacing it with the default config...");
c.performOverwrite();
Bukkit.getLogger().log(Level.WARNING, ChatColor.RED + "Replacement complete!");
}
}
public static void init(Storage st) {
c = st;
}
}
@@ -0,0 +1,115 @@
package me.dadus33.chatitem.utils;
import java.util.Arrays;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
public class ItemUtils {
public static final Material MATERIAL_CLOSE = getMaterialWithCompatibility("BARRIER", "REDSTONE_BLOCK");
// items
public static final Material EMPTY_MAP = getMaterialWithCompatibility("EMPTY_MAP", "MAP");
public static final Material BOOK_AND_QUILL = getMaterialWithCompatibility("BOOK_AND_QUILL", "WRITTEN_BOOK");
public static final Material WEB = getMaterialWithCompatibility("WEB", "COBWEB");
public static final Material FIREBALL = getMaterialWithCompatibility("FIREBALL", "FIRE_CHARGE");
public static final Material INK_SAC = getMaterialWithCompatibility("INK_SAC", "INK_SACK", "DYE", "GRAY_DYE");
public static final Material FIREWORK_CHARGE = getMaterialWithCompatibility("FIREWORK_CHARGE", "FIRE_CHARGE");
public static final Material BIRCH_WOOD_STAIRS = getMaterialWithCompatibility("BIRCH_WOOD_STAIRS", "BIRCH_STAIRS");
// colored items
public static final Material GRAY_STAINED_GLASS_PANE = getMaterialWithCompatibility("STAINED_GLASS_PANE", "GRAY_STAINED_GLASS_PANE");
public static final Material WHITE_STAINED_GLASS = getMaterialWithCompatibility("STAINED_GLASS_PANE", "WHITE_STAINED_GLASS_PANE");
public static Material getMaterialWithCompatibility(String... tempMat) {
for(String s : tempMat) {
try {
Material m = (Material) Material.class.getField(s).get(Material.class);
if(m != null)
return m;
} catch (IllegalArgumentException | IllegalAccessException | SecurityException e2) {
e2.printStackTrace();
} catch (NoSuchFieldException e) {}
}
return null;
}
public static ItemStack createItem(Material m, String name, String... lore) {
return createItem(m, name, 1, lore);
}
public static ItemStack createItem(Material m, String name, int quantite, String... lore) {
ItemStack item = new ItemStack(m, quantite);
ItemMeta meta = (ItemMeta) item.getItemMeta();
meta.setDisplayName(ChatColor.RESET + name);
meta.setLore(Arrays.asList(lore));
item.setItemMeta(meta);
return item;
}
public static ItemStack createItem(Material m, String name, List<String> lore) {
return createItem(m, name, 1, lore);
}
public static ItemStack createItem(Material m, String name, int quantite, List<String> lore) {
ItemStack item = new ItemStack(m, quantite);
ItemMeta meta = (ItemMeta) item.getItemMeta();
meta.setDisplayName(ChatColor.RESET + name);
meta.setLore(lore);
item.setItemMeta(meta);
return item;
}
@SuppressWarnings("deprecation")
public static ItemStack createItem(Material m, String name, int amount, byte b, String... lore) {
ItemStack item = new ItemStack(m, amount, b);
ItemMeta meta = (ItemMeta) item.getItemMeta();
meta.setDisplayName(ChatColor.RESET + name);
meta.setLore(Arrays.asList(lore));
item.setItemMeta(meta);
return item;
}
public static ItemStack hideAttributes(ItemStack stack) {
if (Version.getVersion().isNewerThan(Version.V1_7)) {
ItemMeta meta = stack.getItemMeta();
// All ItemFlags are used to hide attributes, their javadoc says so too.
meta.addItemFlags(ItemFlag.values());
stack.setItemMeta(meta);
}
return stack;
}
public static ItemStack copyIfExist(ItemStack item) {
return isEmpty(item) ? null : item.clone();
}
public static boolean isEmpty(ItemStack item) {
return item == null || item.getType().equals(Material.AIR);
}
public static void stripData(ItemStack i) {
if (i == null) {
return;
}
if (i.getType().equals(Material.AIR)) {
return;
}
if (!i.hasItemMeta()) {
return;
}
ItemMeta im = Bukkit.getItemFactory().getItemMeta(i.getType());
ItemMeta original = i.getItemMeta();
if (original.hasDisplayName()) {
im.setDisplayName(original.getDisplayName());
}
i.setItemMeta(im);
}
}
@@ -0,0 +1,42 @@
package me.dadus33.chatitem.utils;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.bukkit.command.CommandSender;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.Storage;
public class Messages {
public static void sendMessage(CommandSender p, String key, Object... placeholders) {
getMessageList(key, placeholders).forEach(p::sendMessage);
}
public static String getMessage(String key, Object... placeholders) {
return colorAndPlaceholders(ChatItem.getInstance().getConfig().getString("messages." + key, key), placeholders);
}
public static List<String> getMessageList(String key, Object... placeholders) {
Object obj = ChatItem.getInstance().getConfig().get("messages." + key);
if(obj == null)
return Arrays.asList(key);
if(obj instanceof List) {
return ((List<String>) obj).stream().map((s) -> colorAndPlaceholders(s, placeholders)).collect(Collectors.toList());
} else if(obj instanceof String)
return Arrays.asList(colorAndPlaceholders((String) obj, placeholders));
else
return Arrays.asList(colorAndPlaceholders(obj.toString(), placeholders));
}
private static String colorAndPlaceholders(String msg, Object... placeholders) {
if(msg == null)
return "";
for (int index = 0; index <= placeholders.length - 1; index += 2) {
msg = msg.replace(String.valueOf(placeholders[index]), String.valueOf(placeholders[index + 1]));
}
return Storage.color(msg);
}
}
@@ -0,0 +1,236 @@
package me.dadus33.chatitem.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulator;
public class PacketUtils {
public static final String VERSION = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
public static final String NMS_PREFIX;
public static final String OBC_PREFIX;
public static final boolean IS_THERMOS;
public static final Class<?> CHAT_SERIALIZER, COMPONENT_CLASS;
public static final Method ICB_FROM_JSON;
/**
* This Map is to reduce Reflection action which take more resources than just
* RAM action
*/
private static final Map<String, Class<?>> ALL_CLASS = Collections.synchronizedMap(new HashMap<String, Class<?>>());
static {
IS_THERMOS = isClassExist("thermos.Thermos");
NMS_PREFIX = Version.getVersion().isNewerOrEquals(Version.V1_17) || IS_THERMOS ? "net.minecraft." : "net.minecraft.server." + VERSION + ".";
OBC_PREFIX = "org.bukkit.craftbukkit." + VERSION + ".";
CHAT_SERIALIZER = getNmsClass("IChatBaseComponent$ChatSerializer", "network.chat.", "ChatSerializer");
COMPONENT_CLASS = getNmsClass("IChatBaseComponent", "network.chat.");
ICB_FROM_JSON = getMethod("a", CHAT_SERIALIZER, String.class);
}
/**
* Get the Class in NMS, with a processing reducer
*
* @param name of the NMS class (in net.minecraft.server package ONLY, because it's NMS)
* @return clazz the searched class
*/
public static Class<?> getNmsClass(String name, String packagePrefix, String... alias) {
return ALL_CLASS.computeIfAbsent(name, (a) -> {
String fullPrefix = NMS_PREFIX + (Version.getVersion().isNewerOrEquals(Version.V1_17) || IS_THERMOS ? packagePrefix : "");
try {
Class<?> clazz = Class.forName(fullPrefix + name);
if (clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
if (alias.length == 0)
e.printStackTrace(); // no alias, print error
// else ignore and go check for alias
}
for (String className : alias) {
try {
Class<?> clazz = Class.forName(fullPrefix + className);
if (clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
if (className == alias[alias.length - 1]) // if it's last alias, print error
e.printStackTrace();
}
}
return null;
});
}
/**
* Get the Class in NMS, with a processing reducer
*
* @param name of the NMS class (in net.minecraft.server package ONLY, because
* it's NMS)
* @return clazz the searched class
*/
public static Class<?> getObcClass(String name, String... alias) {
return ALL_CLASS.computeIfAbsent(name, (a) -> {
try {
Class<?> clazz = Class.forName(OBC_PREFIX + name);
if (clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
if (alias.length == 0)
e.printStackTrace(); // no alias, print error
// else ignore and go check for alias
}
for (String className : alias) {
try {
Class<?> clazz = Class.forName(OBC_PREFIX + className);
if (clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
if (className == alias[alias.length - 1]) // if it's last alias, print error
e.printStackTrace();
}
}
return null;
});
}
/**
* Get NMS entity player of specified one
*
* @param p the player that we want the NMS entity player
* @return the entity player
*/
public static Object getEntityPlayer(Player p) {
try {
return getObcClass("entity.CraftPlayer").getMethod("getHandle").invoke(p);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static boolean isClassExist(String name) {
try {
Class.forName(name);
return true;
} catch (Exception e) {
return false;
}
}
/**
* Get NMS player connection of specified player
*
* @param p Player of which we want to get the player connection
* @return the NMS player connection
*/
public static Object getPlayerConnection(Player p) {
try {
Object entityPlayer = getEntityPlayer(p);
return ReflectionUtils.getFirstWith(entityPlayer, entityPlayer.getClass(), getNmsClass("PlayerConnection", "server.network."));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Get NMS entity player of specified one
*
* @param p the player that we want the NMS entity player
* @return the entity player
*/
public static Object getCraftServer() {
try {
return getObcClass("CraftServer").getMethod("getHandle").invoke(Bukkit.getServer());
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Send the packet to the specified player
*
* @param p which will receive the packet
* @param packet the packet to sent
*/
public static void sendPacket(Player p, Object packet) {
try {
Object playerConnection = getPlayerConnection(p);
playerConnection.getClass().getMethod(Version.getVersion().isNewerOrEquals(Version.V1_18) ? "a" : "sendPacket", getNmsClass("Packet", "network.protocol."))
.invoke(playerConnection, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
private static Method getNbtMethod;
/**
* Converts an {@link org.bukkit.inventory.ItemStack} to a Json string for
* sending with {@link net.md_5.bungee.api.chat.BaseComponent}'s.
*
* @param item the item to convert
* @return the Json string representation of the item
*/
public static String getNbtTag(ItemStack item) {
try {
if (getNbtMethod == null) {
Class<?> itemClass = getNmsClass("ItemStack", "world.item.");
Version v = Version.getVersion();
if (v.isNewerOrEquals(Version.V1_20))
getNbtMethod = itemClass.getDeclaredMethod("w");
else if (v.equals(Version.V1_19))
getNbtMethod = itemClass.getDeclaredMethod("u");
else if (v.equals(Version.V1_18))
getNbtMethod = itemClass.getDeclaredMethod("t");
else
getNbtMethod = itemClass.getDeclaredMethod("getTag");
getNbtMethod.setAccessible(true);
}
Object tag = getNbtMethod.invoke(JSONManipulator.AS_NMS_COPY.invoke(null, item));
return tag == null ? "{}" : tag.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "{}";
}
private static Method getMethod(String name, Class<?> clazz, Class<?>... params) {
try {
return clazz.getDeclaredMethod(name, params);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void printPacketToDebug(Object packet) {
if(!ChatItem.hasDebug())
return;
if(packet == null) {
ChatItem.debug("Packet is null");
return;
}
ChatItem.debug("Packet with Class: " + packet.getClass().getSimpleName());
for (Field f : packet.getClass().getDeclaredFields()) {
f.setAccessible(true);
try {
ChatItem.debug(f.getName() + ": " + f.get(packet));
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
}
@@ -1,63 +0,0 @@
package me.dadus33.chatitem.utils;
import org.bukkit.Bukkit;
import java.lang.reflect.Method;
public class Reflect {
private static String versionString;
private static String getVersion() {
if (versionString == null) {
String name = Bukkit.getServer().getClass().getPackage().getName();
versionString = name.substring(name.lastIndexOf('.') + 1) + ".";
}
return versionString;
}
public static Class<?> getNMSClass(String nmsClassName) {
String clazzName = "net.minecraft.server." + getVersion() + nmsClassName;
Class<?> clazz;
try {
clazz = Class.forName(clazzName);
} catch (Throwable t) {
t.printStackTrace();
return null;
}
return clazz;
}
public static Class<?> getOBCClass(String obcClassName) {
String clazzName = "org.bukkit.craftbukkit." + getVersion() + obcClassName;
Class<?> clazz;
try {
clazz = Class.forName(clazzName);
} catch (Throwable t) {
t.printStackTrace();
return null;
}
return clazz;
}
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... params) {
try {
return clazz.getMethod(methodName, params);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
@@ -0,0 +1,194 @@
package me.dadus33.chatitem.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import me.dadus33.chatitem.ChatItem;
public class ReflectionUtils {
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... params) {
try {
return clazz.getMethod(methodName, params);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static Method getMethod(Class<?> clazz, Class<?> returned, Class<?>... params) {
try {
for(Method m : clazz.getDeclaredMethods()) {
if(returned.equals(m.getReturnType()) && areParamsEquals(m.getParameterTypes(), params))
return m;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static boolean areParamsEquals(Class<?>[] p1, Class<?>[] p2) {
if(p1.length != p2.length)
return false;
for(int i = 0; i < p1.length; i++) {
if(!p1[i].equals(p2[i]))
return false;
}
return true;
}
public static Field getField(Class<?> clazz, String... fieldNames){
for(String field : fieldNames) {
try{
Field f = clazz.getDeclaredField(field);
f.setAccessible(true);
return f;
} catch (NoSuchFieldException e) {
// go to next
}
}
ChatItem.getInstance().getLogger().severe("Failed to find field: " + Arrays.asList(fieldNames) + " in class: " + clazz.getCanonicalName());
return null;
}
public static Object getPrivateField(Object object, String field)
throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field objectField = object.getClass().getDeclaredField(field);
objectField.setAccessible(true);
return objectField.get(object);
}
public static void setField(Object src, String fieldName, Object value) {
try {
Field field = src.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(src, value);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Get the specified field name in the object source
*
* @param source where we will find the field
* @param field the name of the field
* @return the requested object of the field
*/
public static Object getObject(Object source, String... field) {
try {
for(String fieldName : field) {
try {
Field f = source.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
return f.get(source);
} catch (NoSuchFieldException e) {
// ignore because going to next item
}
}
ChatItem.getInstance().getLogger().severe("Failed to find fields: " + String.join(", ", field) + " in " + source.getClass().getSimpleName());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Get the specified field name in the object source
*
* @param source where we will find the field
* @param field the name of the field
* @return the requested field
*/
public static Field getField(Object source, String field) {
try {
Field f = source.getClass().getDeclaredField(field);
f.setAccessible(true);
return f;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Call method. Return the method return.
*
* @param source the object where we want to run the method
* @param method the name of the method to call
* @return the return of the method called
*/
public static Object callMethod(Object source, String method) {
try {
return source.getClass().getDeclaredMethod(method).invoke(source);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Get the first object which have the searching for class type
*
* @param from the object where we will try to find the field
* @param clazz the class that have to define the field
* @param searchingFor the class of the required field
* @return the field (or null if not found)
* @throws Exception if something gone wrong
*/
public static <T> T getFirstWith(Object from, Class<T> searchingFor) throws Exception {
return getFirstWith(from, from.getClass(), searchingFor);
}
/**
* Get the first object which have the searching for class type
*
* @param from the object where we will try to find the field
* @param clazz the class that have to define the field
* @param searchingFor the class of the required field
* @return the field (or null if not found)
* @throws Exception if something gone wrong
*/
public static <T> T getFirstWith(Object from, Class<?> clazz, Class<T> searchingFor) throws Exception {
for (Field f : clazz.getDeclaredFields()) {
if (f.getType().equals(searchingFor) && !Modifier.isStatic(f.getModifiers())) {
f.setAccessible(true);
return (T) f.get(from);
}
}
if(!clazz.getSuperclass().equals(Object.class))
return getFirstWith(from, clazz.getSuperclass(), searchingFor);
return null;
}
/**
* Get the first field which have the searching for class type
*
* @param from the object where we will try to find the field
* @param clazz the class that have to define the field
* @param searchingFor the class of the required field
* @return the field (or null if not found)
* @throws Exception if something gone wrong
*/
public static Field getFirstFieldWith(Class<?> clazz, Class<?> searchingFor) throws Exception {
for (Field f : clazz.getDeclaredFields()) {
if (f.getType().equals(searchingFor) && !Modifier.isStatic(f.getModifiers())) {
f.setAccessible(true);
return f;
}
}
return null;
}
public static boolean isClassExist(String name) {
try {
Class.forName(name);
return true;
} catch (Exception e) {
return false;
}
}
}
@@ -0,0 +1,208 @@
package me.dadus33.chatitem.utils;
import java.util.Locale;
import java.util.Objects;
import javax.annotation.Nullable;
/**
* Represents the simplified SemVer schema Negativity uses for its plugin versions.
*/
public final class SemVer implements Comparable<SemVer> {
private final int major;
private final int minor;
private final int patch;
private final @Nullable Suffix suffix;
public SemVer(int major, int minor, int patch, @Nullable Suffix suffix) {
this.major = major;
this.minor = minor;
this.patch = patch;
this.suffix = suffix;
}
public boolean isNewerThan(SemVer other) {
return this.compareTo(other) > 0;
}
public boolean isOlderThan(SemVer other) {
return this.compareTo(other) < 0;
}
/**
* Slightly different from {@link #equals} in that this method will return
* true if the suffix has the same {@link Suffix#getWeight() weight}
* but not the same {@link Suffix#getText()} text
*/
public boolean isEquivalentTo(SemVer other) {
return this.compareTo(other) == 0;
}
public int getMajor() {
return major;
}
public int getMinor() {
return minor;
}
public int getPatch() {
return patch;
}
public @Nullable Suffix getSuffix() {
return suffix;
}
@Override
public int compareTo(SemVer o) {
int majorDelta = Integer.compare(this.major, o.major);
if (majorDelta != 0) {
return majorDelta;
}
int minorDelta = Integer.compare(this.minor, o.minor);
if (minorDelta != 0) {
return minorDelta;
}
int patchDelta = Integer.compare(this.patch, o.patch);
if (patchDelta != 0) {
return patchDelta;
}
if (this.suffix != null) {
return o.suffix != null ? this.suffix.compareTo(o.suffix) : -1;
}
if (o.suffix != null) {
return 1;
}
return 0;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SemVer semVer = (SemVer) o;
return major == semVer.major && minor == semVer.minor && patch == semVer.patch && Objects.equals(suffix, semVer.suffix);
}
@Override
public int hashCode() {
return Objects.hash(major, minor, patch, suffix);
}
@Override
public String toString() {
return "SemVer{major=" + major + ", minor=" + minor + ", patch=" + patch + ", suffix=" + suffix + '}';
}
public String toFormattedString() {
if (suffix == null) {
if(patch > 0)
return major + "." + minor + (patch > 0 ? "." + patch : "");
}
return major + "." + minor + (patch > 0 ? "." + patch : "") + (suffix == null ? "" : "-" + suffix.getText());
}
public static @Nullable SemVer parse(String text) {
if (text == null || text.isEmpty()) {
return null;
}
String[] suffixSplit = text.split("-", 2);
Suffix suffix = null;
if (suffixSplit.length > 1) {
suffix = Suffix.of(suffixSplit[1]);
}
String[] parts = suffixSplit[0].split("\\.");
int major;
try {
major = Integer.parseInt(parts[0]);
} catch (NumberFormatException e) {
return null;
}
int minor = 0;
if (parts.length > 1) {
try {
minor = Integer.parseInt(parts[1]);
} catch (NumberFormatException ignore) {
}
}
int patch = 0;
if (parts.length > 2) {
try {
patch = Integer.parseInt(parts[2]);
} catch (NumberFormatException ignore) {
}
}
return new SemVer(major, minor, patch, suffix);
}
public static final class Suffix implements Comparable<Suffix> {
public static final Suffix SNAPSHOT = new Suffix(0, "SNAPSHOT");
public static final Suffix ALPHA = new Suffix(1, "ALPHA");
public static final Suffix BETA = new Suffix(2, "BETA");
public static final Suffix GAMMA = new Suffix(3, "GAMMA");
public static final Suffix DELTA = new Suffix(4, "DELTA");
private final int weight;
private final String text;
public Suffix(int weight, String text) {
this.weight = weight;
this.text = text;
}
public int getWeight() {
return weight;
}
public String getText() {
return text;
}
@Override
public int compareTo(Suffix o) {
return Integer.compare(this.weight, o.weight);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Suffix suffix = (Suffix) o;
return weight == suffix.weight && text.equals(suffix.text);
}
@Override
public int hashCode() {
return Objects.hash(weight, text);
}
@Override
public String toString() {
return "Suffix{weight=" + weight + ", text='" + text + "'}";
}
public static Suffix of(String text) {
String uppercaseText = text.toUpperCase(Locale.ROOT);
switch (uppercaseText) {
case "SNAPSHOT":
return SNAPSHOT;
case "ALPHA":
return ALPHA;
case "BETA":
return BETA;
case "GAMMA":
return GAMMA;
case "DELTA":
return DELTA;
default:
return new Suffix(-1, uppercaseText);
}
}
}
}
@@ -1,85 +0,0 @@
package me.dadus33.chatitem.utils;
import com.google.common.collect.ImmutableList;
import me.dadus33.chatitem.ChatItem;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.configuration.file.FileConfiguration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
public class Storage {
public final HashMap<String, HashMap<Short, String>> TRANSLATIONS = new HashMap<>();
public final List<String> PLACEHOLDERS;
public final String NAME_FORMAT;
public final String AMOUNT_FORMAT;
public final Boolean COLOR_IF_ALREADY_COLORED;
public final Boolean FORCE_ADD_AMOUNT;
public final Boolean DENY_IF_NO_ITEM;
public final String DENY_MESSAGE;
public final String LIMIT_MESSAGE;
public final String RELOAD_MESSAGE;
final Integer CONFIG_VERSION;
public final Integer LIMIT;
public final List<Command> ALLOWED_COMMANDS = new ArrayList<>();
public Storage(FileConfiguration conf) {
Set<String> keys = conf.getConfigurationSection("Translations").getKeys(false);
for (String key : keys) {
HashMap<Short, String> entry = new HashMap<>();
Set<String> subKeys = conf.getConfigurationSection("Translations.".concat(key)).getKeys(false);
for (String subKey : subKeys) {
entry.put(Short.parseShort(subKey), color(conf.getString("Translations.".concat(key).concat(".")
.concat(subKey))));
}
TRANSLATIONS.put(key, entry);
}
CONFIG_VERSION = conf.getInt("config-version");
LIMIT = conf.getInt("limit");
List<String> added = conf.getStringList("placeholders");
PLACEHOLDERS = ImmutableList.copyOf(added);
NAME_FORMAT = color(conf.getString("name-format"));
AMOUNT_FORMAT = color(conf.getString("amount-format"));
COLOR_IF_ALREADY_COLORED = conf.getBoolean("color-if-already-colored");
FORCE_ADD_AMOUNT = conf.getBoolean("force-add-amount");
DENY_IF_NO_ITEM = conf.getBoolean("deny-if-no-item");
DENY_MESSAGE = color(conf.getString("deny-message"));
LIMIT_MESSAGE = color(conf.getString("limit-message"));
RELOAD_MESSAGE = color(conf.getString("reload-success"));
final List<String> cmds = conf.getStringList("commands");
Bukkit.getScheduler().runTaskLaterAsynchronously(ChatItem.getInstance(), new Runnable() {
@Override
public void run() {
for(String s : cmds){
Command c = Bukkit.getPluginCommand(s);
if(c!=null) {
ALLOWED_COMMANDS.add(Bukkit.getPluginCommand(s));
}
else
ChatItem.getInstance().getLogger().log(Level.WARNING, ChatColor.RED.toString().concat("Unknown command ")
.concat(s).concat(" found in config! Ignoring occurrence..."));
}
}
}, 100L);
}
private static String color(String s) {
return ChatColor.translateAlternateColorCodes('&', s);
}
void performOverwrite() {
ChatItem.getInstance().saveResource("config.yml", true);
}
}
@@ -0,0 +1,262 @@
package me.dadus33.chatitem.utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.StringJoiner;
import java.util.TreeMap;
import java.util.regex.Pattern;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulator;
import me.dadus33.chatitem.playerversion.PlayerVersionManager;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.ItemTag;
import net.md_5.bungee.api.chat.hover.content.Item;
import net.md_5.bungee.api.chat.hover.content.Text;
public class Utils {
private static final Pattern UUID_PATTERN = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$");
private static final TreeMap<Integer, String> ROMAN_KEYS = new TreeMap<>();
private static final HashMap<String, String> ENCHANTS_NAMES = new HashMap<>();
static {
ROMAN_KEYS.put(1000, "M");
ROMAN_KEYS.put(900, "CM");
ROMAN_KEYS.put(500, "D");
ROMAN_KEYS.put(400, "CD");
ROMAN_KEYS.put(100, "C");
ROMAN_KEYS.put(90, "XC");
ROMAN_KEYS.put(50, "L");
ROMAN_KEYS.put(40, "XL");
ROMAN_KEYS.put(10, "X");
ROMAN_KEYS.put(9, "IX");
ROMAN_KEYS.put(5, "V");
ROMAN_KEYS.put(4, "IV");
ROMAN_KEYS.put(1, "I");
ENCHANTS_NAMES.put("ARROW_DAMAGE", "Power");
ENCHANTS_NAMES.put("ARROW_FIRE", "Flame");
ENCHANTS_NAMES.put("ARROW_INFINITE", "Infinity");
ENCHANTS_NAMES.put("ARROW_KNOCKBACK", "Punch");
ENCHANTS_NAMES.put("BINDING_CURSE", "Curse of Binding");
ENCHANTS_NAMES.put("DAMAGE_ALL", "Sharpness");
ENCHANTS_NAMES.put("DAMAGE_ARTHROPODS", "Bane of Arthropods");
ENCHANTS_NAMES.put("DAMAGE_UNDEAD", "Smite");
ENCHANTS_NAMES.put("DEPTH_STRIDER", "Depth Strider");
ENCHANTS_NAMES.put("DIG_SPEED", "Efficiency");
ENCHANTS_NAMES.put("DURABILITY", "Unbreaking");
ENCHANTS_NAMES.put("FIRE_ASPECT", "Fire Aspect");
ENCHANTS_NAMES.put("FROST_WALKER", "Frost Walker");
ENCHANTS_NAMES.put("KNOCKBACK", "Knockback");
ENCHANTS_NAMES.put("LOOT_BONUS_BLOCKS", "Fortune");
ENCHANTS_NAMES.put("LOOT_BONUS_MOBS", "Looting");
ENCHANTS_NAMES.put("LUCK", "Luck of the Sea");
ENCHANTS_NAMES.put("LURE", "Lure");
ENCHANTS_NAMES.put("MENDING", "Mending");
ENCHANTS_NAMES.put("OXYGEN", "Respiration");
ENCHANTS_NAMES.put("PROTECTION_ENVIRONMENTAL", "Protection");
ENCHANTS_NAMES.put("PROTECTION_EXPLOSIONS", "Blast Protection");
ENCHANTS_NAMES.put("PROTECTION_FALL", "Feather Falling");
ENCHANTS_NAMES.put("PROTECTION_FIRE", "Fire Protection");
ENCHANTS_NAMES.put("PROTECTION_PROJECTILE", "Projectile Protection");
ENCHANTS_NAMES.put("SILK_TOUCH", "Silk Touch");
ENCHANTS_NAMES.put("SWEEPING_EDGE", "Sweeping Edge");
ENCHANTS_NAMES.put("THORNS", "Thorns");
ENCHANTS_NAMES.put("VANISHING_CURSE", "Cure of Vanishing");
ENCHANTS_NAMES.put("WATER_WORKER", "Aqua Affinity");
}
public static List<Player> getOnlinePlayers() {
return new ArrayList<>(Bukkit.getOnlinePlayers());
}
public static String toRoman(int number) {
int l = ROMAN_KEYS.floorKey(number);
if (number == l) {
return ROMAN_KEYS.get(number);
}
return ROMAN_KEYS.get(l) + toRoman(number - l);
}
@SuppressWarnings("deprecation")
public static String getEnchantName(Enchantment enchant) {
String name = ENCHANTS_NAMES.get(enchant.getName());
if (name == null) {
ChatItem.getInstance().getLogger()
.warning("Unknown enchant " + enchant.getName() + ". Please report this to Elikill58.");
}
return name;
}
public static String getFromURL(String urlName) {
ChatItem pl = ChatItem.getInstance();
try {
URL url = new URL(urlName);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setUseCaches(true);
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.setRequestProperty("User-Agent", "ChatItem " + pl.getDescription().getVersion());
connection.setDoOutput(true);
connection.setRequestMethod("GET");
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder content = new StringBuilder();
String input;
while ((input = br.readLine()) != null)
content.append(input);
br.close();
return content.toString();
} catch (SocketTimeoutException e) {
pl.getLogger().info("Failed to access to " + urlName + " (Reason: timed out).");
} catch (UnknownHostException | MalformedURLException e) {
pl.getLogger().info("Could not use the internet connection to check for update or send stats");
} catch (ConnectException e) {
pl.getLogger().warning("Cannot connect to " + urlName + " (Reason: " + e.getMessage() + ").");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static int indexOf(CharSequence s, CharSequence searched, int i) {
return s.toString().indexOf(searched.toString(), i);
}
public static boolean isEmpty(CharSequence s) {
return (s == null || s.length() == 0);
}
public static int countMatches(CharSequence str, CharSequence searched) {
if (isEmpty(str) || isEmpty(searched))
return 0;
byte b = 0;
int i = 0;
while ((i = indexOf(str, searched, i)) != -1) {
b++;
i += searched.length();
}
return b;
}
public static boolean isBeforeChatJson(Player p) {
return !PlayerVersionManager.getPlayerVersionAdapter().getPlayerVersion(p).isNewerOrEquals(Version.V1_16) && Version.getVersion().isNewerOrEquals(Version.V1_16);
}
@SuppressWarnings("deprecation")
public static HoverEvent createItemHover(ItemStack item, Player to) {
if(isBeforeChatJson(to)) {
ComponentBuilder comp = new ComponentBuilder("");
for(String line : ChatManager.getMaxLinesFromItem(to, item))
comp.append(line + "\n");
return createTextHover(comp.create());
}
if(Version.getVersion().isNewerOrEquals(Version.V1_13)) {
return new HoverEvent(HoverEvent.Action.SHOW_ITEM, new Item(item.getType().getKey().getKey(), item.getAmount(), ItemTag.ofNbt(PacketUtils.getNbtTag(item))));
} else {
return new HoverEvent(HoverEvent.Action.SHOW_ITEM, new ComponentBuilder(JSONManipulator.stringifyItem(item)).create());
}
}
public static HoverEvent createTextHover(String text) {
return createTextHover(new ComponentBuilder(text).create());
}
@SuppressWarnings("deprecation")
public static HoverEvent createTextHover(BaseComponent[] comps) {
if(Version.getVersion().isNewerOrEquals(Version.V1_13)) {
return new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(comps));
} else {
return new HoverEvent(HoverEvent.Action.SHOW_TEXT, comps);
}
}
public static ClickEvent createRunCommand(String command) {
return new ClickEvent(ClickEvent.Action.RUN_COMMAND, command);
}
public static boolean isInteger(String s) {
try {
Integer.parseInt(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isByte(String s) {
try {
Byte.parseByte(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isShort(String s) {
try {
Short.parseShort(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isLong(String s) {
try {
Long.parseLong(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isUUID(String s) {
return s != null && UUID_PATTERN.matcher(s.toLowerCase()).matches();
}
public static YamlConfiguration copyLoadFile(File folder, String filename, String baseFile) {
File legacyConfig = new File(folder, filename);
if(!legacyConfig.exists())
copyFile(baseFile, legacyConfig);
return YamlConfiguration.loadConfiguration(legacyConfig);
}
public static void copyFile(String fileName, File dir) {
try (InputStream stream = ChatItem.getInstance().getResource(fileName)) {
Files.copy(stream, dir.toPath());
} catch(Exception e) {
e.printStackTrace();
}
}
public static String arrayToString(Object[] a) {
StringJoiner sj = new StringJoiner(", ");
for(Object o : a)
sj.add(o == null ? "null" : o.toString());
return sj.toString();
}
}
@@ -0,0 +1,94 @@
package me.dadus33.chatitem.utils;
import java.net.InetSocketAddress;
import org.bukkit.Bukkit;
import me.dadus33.chatitem.ChatItem;
public enum Version {
// http://wiki.vg/Protocol_version_numbers
V1_7(0, 5, 7),
V1_8(6, 47, 8),
V1_9(49, 110, 9), // 1.9.X - Starts with 49 as 48 was an april fools update
V1_10(201, 210, 10), // 1.10.X - Starts with 201 because why not.
V1_11(301, 316, 11),
V1_12(317, 340, 12),
V1_13(341, 440, 13),
V1_14(441, 500, 14),
V1_15(550, 578, 15),
V1_16(700, 754, 16),
V1_17(755, 756, 17),
V1_18(757, 758, 18),
V1_19(759, 762, 19),
V1_20(763, 1000, 20),
HIGHER(Integer.MAX_VALUE, -1, Integer.MAX_VALUE);
// Latest version should always have the upper limit set to Integer.MAX_VALUE so
// I don't have to update the plugin for every minor protocol change
public final int MIN_VER;
public final int MAX_VER;
public final int index; // Represents how new the version is (0 - extremely old)
private static final Version SERVER_VERSION;
public static final String BUKKIT_VERSION;
static {
BUKKIT_VERSION = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
SERVER_VERSION = getVersionByName(BUKKIT_VERSION);
}
Version(int min, int max, int index) {
this.MIN_VER = min;
this.MAX_VER = max;
this.index = index;
}
public boolean isNewerOrEquals(Version other) {
return index >= other.index;
}
public boolean isNewerThan(Version other) {
return index > other.index;
}
public static Version getVersionByName(String name) {
for (Version v : Version.values())
if (name.toLowerCase().startsWith(v.name().toLowerCase()))
return v;
return HIGHER;
}
public static Version getVersion(int protocolVersion) {
for (Version ver : Version.values()) {
if (protocolVersion >= ver.MIN_VER && protocolVersion <= ver.MAX_VER) {
return ver;
}
}
return HIGHER;
}
public static Version getVersion(int protocolVersion, Version def) {
for (Version ver : Version.values()) {
if (protocolVersion >= ver.MIN_VER && protocolVersion <= ver.MAX_VER) {
return ver;
}
}
ChatItem.debug("Failed to find version for protocol " + protocolVersion);
return def;
}
public static Version getVersion() {
return SERVER_VERSION;
}
public static String stringifyAdress(InetSocketAddress address) {
if(address == null)
return "0.0.0.0:0";
String port = String.valueOf(address.getPort());
String ip = address.getAddress().getHostAddress();
return ip + ":" + port;
}
}
+274 -79
View File
@@ -1,83 +1,278 @@
#Config for ChatItem
#For info visit
#https://www.spigotmc.org/resources/chatitem.19064/
# Config for ChatItem
# For info visit
# Spigotmc: https://www.spigotmc.org/resources/19064/
# Discord: https://discord.gg/yng5PPf62h
# Version info, DON'T TOUCH
config-version: 13
# By default, it's in "both" mode.
#
# Available mode :
# - "both" : Prevent chat editing with multiple plugins by using all ways possible to edit the chat.
# - "auto" : Choose automatically between all available according to actual plugins.
# - "packet" : The working system for 1.4's ChatItem version (and older)
# It was working with lot of others chat plugin, specially those who made hover text.
# - "chat" : New system which works without other chat plugin, which is simpler and with lower
# amount of possible issues.
# You can replace 'both' by another mode that should correspond to what you want.
# If you don't know which one use, come on discord (link at begin of config or in spigotmc)
manager: "both"
#Version info, DON'T TOUCH
config-version: 6
#General configuration
general:
# The placeholders to display an item in chat.
placeholders:
- "[i]"
- "{i}"
- "[item]"
- "{item}"
other-placeholders:
# Show what is in the head
helmet:
# Enable it or not
enabled: true
# Disallow showing empty item
deny-if-no-item: true
# Placeholders to use in chat
keys:
- "[head]"
- "{head}"
# Show the CHESTPLATE not the enderchest or whatever
chestplate:
enabled: true
deny-if-no-item: true
keys:
- "[chest]"
- "{chest}"
# Show leggings
leggings:
enabled: true
deny-if-no-item: true
keys:
- "[legs]"
- "{legs}"
# Show what is their feets
boots:
enabled: false
deny-if-no-item: true
keys:
- "[feet]"
- "{feet}"
inventory:
enabled: true
deny-if-no-item: true
# Time in minute before the placeholder expire
time-expire: 1800
keys:
- "[inv]"
- "{inv}"
enderchest:
enabled: true
deny-if-no-item: true
# Time in minute before the placeholder expire
time-expire: 1800
keys:
- "[ec]"
- "{ec}"
# The format of the item placeholders.
name-format: "&b&l&o{name}{amount}&r"
# The format of the {amount} placeholder.
# {times} correspond to amount of item
amount-format: " x{times}"
# Should we use the translated item name or the custom name of an item
color-if-already-colored: true
# Should we always show the amount, even if it's just one
force-add-amount: true
# Should we let the message through, as-is (with the placeholder not replaced)
# if the user doesn't have permission or if the user is on cooldown?
let-message-through: true
# Should we allow users to show their hands off
deny-if-no-item: false
# If the above (deny-if-no-item) is set to false, what should the placeholder be replaced with?
# Bellow you can configure that behaviour.
hand:
# Should we completely disable users being able to show their hands off
disabled: false
# The name of the hand chat message.
name: "&b&l&o{display-name}&b&l&o's hand"
# The lore of the hand chat message.
tooltip:
- "&7Nothing to see here"
- "&7Just the empty hand of {display-name}."
# Manage what is showed for bugged client.
# Specially lunar client with old version (1.7)
bugged_client:
# You can try to show the most informations as possible:
# item name & lore. You will not see specific item meta-data
# Or just show the bugged tooltip.
#
# Action available:
# nothing: no hover
# item: only try to get values from item
# tooltip: only show tooltip
# show_both: show item & tooltip below
action: "show_both"
tooltip:
- "&7Failed to parse item for your client"
# Format used with using /chatitem show
command-format: "&6%name%'s item is %item%"
#The placeholders you want to use for the item. You can add as many as you want.
placeholders:
- "[i]"
- "{item}"
# Here you can set when the players should see the no-permission message (defined in the 'Messages' section bellow).
# 'normal' dictates whether the user should see the message when using the placeholder in normal chat, and 'command'
# sets whether the user should see it when using the placeholder in a command.
show-no-permission-message:
normal: true
command: false
# Manage permission to use placeholders
permission:
enabled: false
name: "chatitem.use"
# Here you can set the limit on how many placeholders a user is allowed to use inside a message.
# Allowing too many placeholders can result in client crashes.
limit: 8
# The cooldown, in seconds, between allowing players to send messages with items. Setting this to 0
# will remove the cooldown entirely.
cooldown: 60
# All items that are not allowed to be showed
ignored_items:
- "SOME_ITEM"
# Check if the plugin have update
check-update: true
language: "en_gb"
sub-commands:
broadcast: true
show: true
# Messages section. You can disable any of them by simply leaving them empty, like this: ""
messages:
# The message sent if showing off hands is disabled and the user isn't holding an item.
# Only works if 'General.deny-if-no-item' is set to true!
deny-message: "&c&lYou have no item in hand!"
# The message sent after the configuration file is successfully reloaded.
reload-success: "&b&lSuccessful reload!"
# The message sent if the player is on cooldown from sending a placeholder.
cooldown-message: "&c&lYou can only use items in chat once a minute! You have {remaining} left!"
# The message sent if the no permission messages are enabled and the user doesn't have permission to send an item placeholder.
no-permission: "&c&lI'm sorry, but you are not allowed to use the placeholder in chat!"
# The message sent if the player uses more placeholders than configured in one message.
limit-message: "&c&lYou can only add 8 item placeholders per message!"
# When trying to show item that is ignored
ignored-item: "&cThis item is not allowed to be showed."
# All message about the update of the plugin
join-update:
message: "&cA new version of ChatItem is available. &aClick here to download."
hover: "&6Click to go to spigot page !"
# For all commands ran by console by reserved to player
only-players: "&cOnly players can run this command"
# The player is not found
player-not-found: "&cThe player %arg% can't be founded."
# All messages for the /chatitem command
chatitem-cmd:
help:
- "&6/chatitem admin : &7Manage some options"
- "&6/chatitem links : &7See all links which are usefull"
links:
begin: "&aAll usefull links: "
list:
1:
message: "\n&7- &eSpigotmc updates"
hover: "&6Click to go to spigot page !"
link: "https://www.spigotmc.org/resources/19064/"
2:
message: " "
3:
message: "&7(Original author: &aDadus33"
hover: "&6See &aDadus33&6's profile"
link: "https://www.spigotmc.org/members/10224/"
4:
message: "&7, "
5:
message: "&7Maintainer: &aElikill58&7)"
hover: "&6See &aElikill58&6's profile"
link: "https://www.spigotmc.org/members/310762/"
6:
message: "\n&7- &6Support on discord"
hover: "&6Click to open discord !"
link: "https://discord.gg/yng5PPf62h"
# All messages in admin inventory
admin-inv:
name: "ChatItem - Admin"
close: "Close"
# Generic lores for options items
amount-lore:
- "&aLeft-click: &6+1"
- "&aRight-click: &6-1"
bool-lore:
- "&7Click to enable/disable"
# Name of options items
color-if-already-colored: "&6Color if already colored: %state%"
deny-no-item: "&6Deny without item: %state%"
hand-disabled: "&6Hand disabled: %state%"
limit-per-message: "&6Limit per message: &a%state%"
cooldown: "&6Cooldown: &a%state%"
debug: "&6Debug: &a%state%"
check-update: "&6Check updates: &a%state%"
language:
name: "&6Change language"
lore: "&7Actual: &e%name%"
# Change name and lore of all managers
manager:
both:
name: "&6Use both manager&7: &aPacket & Chat"
lore:
- "&aTry both manager. Very usefull when you have lot of plugins"
- "&eIt enable to use ChatItem for all type of messages"
- ""
- "&7Since ChatItem v2.1"
auto:
name: "&6Choose automatically"
lore:
- "&aChoose automatically between managers available"
- "&aaccording to actuals plugins."
- "&eThis is better when you are not using own plugin."
- ""
- "&7Since ChatItem v2.1"
packet:
name: "&6Intercept packets"
lore:
- "&aChange message sent directly by intercepting packet"
- "&aCan use &6ProtocolLib &aif present."
- "&cCan have error with &e/cir &c!"
- ""
- "&7Originally made until ChatItem v1.4"
chat:
name: "&6Change basic message"
lore:
- "&aVery quick and usefull for server without plugin message !"
- "&aIt enable to use ChatItem without packet reading."
- "&eIt's more optimized than others manager"
- ""
- "&7Since ChatItem v2.0"
# The item that show the actual manager
actual:
name: '&6Actual manager: %manager%'
lore: []
# All the fields bellow shold be translated in your own language. Those will be used in the {remaining} format of the cooldown message.
# You should leave a space as a PREFIX as we will add a number in front of them
seconds: " seconds"
minutes: " minutes"
hours: " hours"
enabled: "&aEnabled"
disabled: "&cDisabled"
seeinv_not_found: "&cImpossible to find this inventory. Are you coming too late ?"
inventory:
name: "%cible%'s inventory"
chat: "%cible%'s inventory"
hover: "&7Click to see inventory"
enderchest:
name: "%cible%'s enderchest"
chat: "%cible%'s enderchest"
hover: "&7Click to see enderchest"
# How will the item be displayed in chat? {name} represents the display name of
# the item, or material name (ex. DIAMOND_SWORD) if it doesn't have a customized
# display name, and {amount} will be replaced by the amount-format configured bellow.
# You can use color codes.
name-format: "&f<&b&l&o{name} {amount}&f>&r"
# The amount format that will replace the {amount} placeholder in the 'name-format'
# field above. The {times} placeholder represents the number of times the item is
# presented in the itemstack, in other words, the actual item amount in the stack
# the player holds. You can use color codes too.
amount-format: "x{times}"
# Should we apply the color and formatting defined in the name-format field even if
# the item is already colored/formated (ex. From anvils or other plugins that change
# the display name of an item). I recommend leaving this to true as not applying color
# codes or formatting at all can lead to an unexpected output compared to what you
# actually want, but feel free to experiment with it ;)
color-if-already-colored: true
# Should we add the item amount even if there's only one item in the stack?
force-add-amount: true
# Should we cancel the user message if the item in his (main) hand is air or null? (No item in hand, that is)
deny-if-no-item: true
# If so, what message should the user get upon attempting to send such a message? Set to "" to disable.
deny-message: "&c&lYou have no item in hand!"
# The message you will get after reloading the plugin using /cireload.
reload-success: "&b&lSuccessful reload!"
# Here you can choose which commands will the plugin attempt to parse. Console commands will all be ignored,
# however player commands will be taken into consideration. To add a command, simply add an element to the list
# bellow containing an alias (or name) for that command.
# Care should be taken with vanilla commands as those are not supported!
commands:
- "msg"
# Here you can set the limit on how many placeholders a user is allowed to use inside a message.
# Allowing too many placeholders can result in client crashes.
limit: 5
# The message a player will get when attempting to send a message with more placeholders then the allowed limit.
limit-message: "&c&lYou can only add 5 item placeholders per message!"
# Translations
Translations:
STONE:
1: "Granite"
# The above field is a little more complicated, but I'll explain you:
# You may have noticed that (until now) if using the placeholder
# with an item such as Granite in hand, (unless it's display name
# is changed) the item will display in chat as (for granite) Stone.
# That happens because the plugin is set to use the material
# name of the item if no custom displayname is found on it.
# The material name for both stone and granite is STONE, the
# only difference being the data value, stone being STONE:0
# and granite being STONE:1. In order to make things more user
# friendly, I implemented this translation feature. Here's how it works:
# If you want to display STONE:1 as GRANITE in chat, you should
# add the following line under translations:
# STONE:
# 1: "Granite"
# STONE represents the material name of the item, while it's sub-section
# '1' represents the data value of the item. The thing that comes next is
# what should actually be displayed in chat.
# You can find a list of item materials and data values
# here: http://www.minecraftinfo.com/idlist.html
# If ChatItem send message using DiscordSRV
# This option will be ignored if you don't have it
discord-srv-send-our: true
+1
View File
@@ -0,0 +1 @@
{"block.minecraft.brown_terracotta":"Bruin Terracotta","block.minecraft.lapis_ore":"Lasuurerts","item.minecraft.gray_dye":"Grys Kleurstof","block.minecraft.banner.base.yellow":"Ten volle geel veld","block.minecraft.terracotta":"Terracotta","item.minecraft.stray_spawn_egg":"Nagelaate Kuit Eier","block.minecraft.banner.base.pink":"Ten volle pienk veld","item.minecraft.potion.effect.weakness":"Swakheid Doepa","block.minecraft.dark_prismarine_slab":"Donker Prismaryn blad","item.minecraft.splash_potion.effect.thick":"Dik Spatdoepa","item.minecraft.cooked_cod":"Gaar Kabeljou","block.minecraft.red_nether_brick_slab":"Rooi Laer Baksteen Blad","block.minecraft.yellow_terracotta":"Geel Terracotta","block.minecraft.observer":"Waarnemer","block.minecraft.banner.stripe_bottom.cyan":"Siaan Basis","block.minecraft.banner.creeper.purple":"Pers Creeper Gelaai","block.minecraft.banner.straight_cross.cyan":"Siaan Kruis","block.minecraft.banner.half_horizontal_bottom.brown":"Omgekeerde Bruin Dwarsstreep","item.minecraft.firework_star.shape.large_ball":"Groot Bal","block.minecraft.prismarine_brick_slab":"Prismaryn Baksteen Blad","block.minecraft.jungle_trapdoor":"Oerwoudhout Valdeur","block.minecraft.sculk_sensor":"Sculk Sensor","block.minecraft.banner.creeper.orange":"Oranje Creeper Gelaai","block.minecraft.banner.triangles_top.lime":"Lemmetjie Groen Ingekeepde Hoof","item.minecraft.charcoal":"Houtskool","item.minecraft.tipped_arrow.effect.night_vision":"Pyl van Nagsig","block.minecraft.stone_brick_slab":"Klipsteenblad","block.minecraft.banner.mojang.cyan":"Siaan Ding","block.minecraft.white_stained_glass":"Wit Glas","item.minecraft.bowl":"Hout Bak","block.minecraft.banner.diagonal_up_left.magenta":"Magenta Per draai omgekeerde","block.minecraft.banner.square_top_right.light_gray":"Ligte Grys Hoof Sinistere Kanton","block.minecraft.dead_brain_coral_fan":"Dooie Gespreide Breinkoraal","block.minecraft.banner.flower.white":"Wit Blom Lading","item.minecraft.bone_meal":"Beenmeel","block.minecraft.banner.triangle_bottom.red":"Rooi Chevron","block.minecraft.cyan_carpet":"Siaan Mat","block.minecraft.oak_door":"Eikehout Deur","block.minecraft.flowering_azalea_leaves":"Blomdraende Azalea Blare","item.minecraft.prismarine_crystals":"Prismaryn Kristalle","block.minecraft.banner.diagonal_left.cyan":"Siaan Per draai Sinister","block.minecraft.banner.stripe_bottom.light_blue":"Ligte Blou Basis","item.minecraft.tipped_arrow.effect.slow_falling":"Pyl van Stadig Val","block.minecraft.end_stone":"Endsteen","block.minecraft.potted_white_tulip":"Gopotte Wit Tulp","block.minecraft.warped_door":"Vreemde Deur","block.minecraft.banner.square_top_left.light_gray":"Ligte Grys Hoof Dexter Kanton","item.minecraft.splash_potion.effect.fire_resistance":"Brandbestandheid Spatdoepa","block.minecraft.banner.half_vertical_right.pink":"Omgekeerde Paars Per Bleek","item.minecraft.furnace_minecart":"Koekepan Enjin","block.minecraft.banner.triangles_bottom.light_gray":"Ligte Grys Ingekeepde Basis","item.minecraft.shield.red":"Rooi Skild","block.minecraft.quartz_pillar":"Kwarts Pilaar","block.minecraft.prismarine_slab":"Prismaryn Blad","block.minecraft.nether_portal":"Laer Ingang","item.minecraft.diamond_sword":"Diamant Swaard","block.minecraft.oak_planks":"Eikehout Planke","item.minecraft.amethyst_shard":"Ametis Skerf","block.minecraft.purple_banner":"Pers Vlag","block.minecraft.structure_void":"Struktuur Leemte","block.minecraft.purple_shulker_box":"Pers Shulker Boks","block.minecraft.potatoes":"Aartappels","block.minecraft.light_blue_bed":"Ligte blou Bed","block.minecraft.yellow_banner":"Geel Banier","item.modifiers.head":"Wanneer dit op die kop is:","item.minecraft.potion.effect.swiftness":"Snelheid Doepa","block.minecraft.glass_pane":"Glaspaneel","block.minecraft.clay":"Klei","block.minecraft.banner.diagonal_right.cyan":"Cyan Per draai","block.minecraft.cut_copper_slab":"Gesnyde Koper Blad","block.minecraft.polished_diorite_slab":"Gepoleerde Dioriet Blad","block.minecraft.banner.piglin.green":"Groen Snoet","item.minecraft.splash_potion.effect.slow_falling":"Spat Doepa van Stadig Val","item.minecraft.book":"Boek","block.minecraft.banner.gradient.brown":"Bruin Gradiënt","block.minecraft.banner.cross.magenta":"Magenta Skuinskruis","block.minecraft.cobblestone_slab":"Steengruisblad","block.minecraft.banner.diagonal_right.purple":"Pers Per draai","block.minecraft.banner.curly_border.gray":"Grys Ingekeepde Borduur","block.minecraft.big_dripleaf":"Groot Drupblaar","block.minecraft.black_shulker_box":"Swart Shulker Boks","block.minecraft.banner.straight_cross.purple":"Pers Kruis","block.minecraft.blackstone_stairs":"Swartsteentrappe","block.minecraft.banner.triangles_top.blue":"Blou Ingekeepde Hoof","block.minecraft.deepslate_tile_slab":"Leisteenteëlblad","block.minecraft.banner.square_top_left.blue":"Blou Hoof Dexter Kanton","block.minecraft.banner.stripe_center.yellow":"Geen Paal","item.minecraft.piglin_banner_pattern.desc":"Snoet","item.minecraft.firework_star.cyLine truncated
+1
View File
@@ -0,0 +1 @@
{"block.minecraft.brown_terracotta":"طين النضيج البني","block.minecraft.lapis_ore":"خام اللازورد","item.minecraft.gray_dye":"صبغة رمادية","block.minecraft.banner.base.yellow":"حقل أصفر كامل","block.minecraft.terracotta":"طين النضيج","item.minecraft.stray_spawn_egg":"بيضة الضال","block.minecraft.banner.base.pink":"حقل وردي كامل","item.minecraft.potion.effect.weakness":"جرعة الضعف","block.minecraft.dark_prismarine_slab":"بلاطة البريسمارين الداكن","item.minecraft.splash_potion.effect.thick":"رشة الجرعة الكثيفة","item.minecraft.cooked_cod":"سمك قد مطبوخ","block.minecraft.red_nether_brick_slab":"بلاطة طوب النذر الأحمر","block.minecraft.yellow_terracotta":"طين النضيج الأصفر","block.minecraft.observer":"المراقب","block.minecraft.banner.stripe_bottom.cyan":"شريط سفلي سماوي","block.minecraft.banner.creeper.purple":"شعار كريبر بنفسجي","block.minecraft.banner.straight_cross.cyan":"صليب سماوي","block.minecraft.banner.half_horizontal_bottom.brown":"النصف الأسفل ملون بني","item.minecraft.firework_star.shape.large_ball":"كرة كبيرة","block.minecraft.prismarine_brick_slab":"بلاطة طوب البريسمارين","block.minecraft.jungle_trapdoor":"باب أرضي من خشب الأدغال","block.minecraft.sculk_sensor":"مستشعر السكالك","block.minecraft.banner.creeper.orange":"شعار كريبر برتقالي","block.minecraft.banner.triangles_top.lime":"مثلثات علوية ليمونية","item.minecraft.charcoal":"فحم نباتي","item.minecraft.tipped_arrow.effect.night_vision":"سهم الرؤية الليلية","block.minecraft.stone_brick_slab":"بلاطة طوب حجري","block.minecraft.banner.mojang.cyan":"شيء سماوي","block.minecraft.white_stained_glass":"زجاج ابيض","item.minecraft.bowl":"زبدية","block.minecraft.banner.diagonal_up_left.magenta":"النصف السفلي الأيسر أرجواني","block.minecraft.banner.square_top_right.light_gray":"مربع رأسي أيمن رمادي فاتح","block.minecraft.dead_brain_coral_fan":"شعاب مرجان عقلي ميت","block.minecraft.banner.flower.white":"شعار زهرة أبيض","item.minecraft.bone_meal":"مسحوق العظام","block.minecraft.banner.triangle_bottom.red":"مثلث أحمر","block.minecraft.cyan_carpet":"سجاد سماوي","block.minecraft.oak_door":"باب البلوط","block.minecraft.flowering_azalea_leaves":"أوراق الأزاليا المزهرة","item.minecraft.prismarine_crystals":"بلورات البرسمارين","block.minecraft.banner.diagonal_left.cyan":"النصف العلوي الأيسر سماوي","block.minecraft.banner.stripe_bottom.light_blue":"شريط سفلي أزرق فاتح","item.minecraft.tipped_arrow.effect.slow_falling":"سهم السقوط البطيء","block.minecraft.end_stone":"حجر الاند","block.minecraft.potted_white_tulip":"توليب أبيض في وعاء","block.minecraft.warped_door":"باب عجيب","block.minecraft.banner.square_top_left.light_gray":"مربع رأسي أيسر رمادي فاتح","item.minecraft.splash_potion.effect.fire_resistance":"رشة جرعة مقاومة النار","block.minecraft.banner.half_vertical_right.pink":"النصف اليميني ملون وردي","item.minecraft.furnace_minecart":"عربة منجم بفرن","block.minecraft.banner.triangles_bottom.light_gray":"مثلثات سفلية رمادية فاتحة","item.minecraft.shield.red":"درس أحمر","block.minecraft.quartz_pillar":"عمود كوارتز","block.minecraft.prismarine_slab":"بلاطة بريسمارين","block.minecraft.nether_portal":"بوابة النذر","item.minecraft.diamond_sword":"سيف ألماسي","block.minecraft.oak_planks":"ألواح خشب البلوط","item.minecraft.amethyst_shard":"شظية جمشت","block.minecraft.purple_banner":"راية بنفسجية","block.minecraft.structure_void":"فراغ الهيكل","block.minecraft.purple_shulker_box":"صندوق شلكر بنفسجي","block.minecraft.potatoes":"بطاطا","block.minecraft.light_blue_bed":"سرير أزرق فاتح","block.minecraft.yellow_banner":"راية صفراء","item.modifiers.head":"عندما يكون على الرأس:","item.minecraft.potion.effect.swiftness":"جرعة السرعة","block.minecraft.glass_pane":"لوح زجاجي","block.minecraft.clay":"صلصال","block.minecraft.banner.diagonal_right.cyan":"النصف العلوي الأيمن سماوي","block.minecraft.cut_copper_slab":"بلاطة نحاس مقطع","block.minecraft.polished_diorite_slab":"بلاطة ديوريت مصقول","block.minecraft.banner.piglin.green":"أنف أخضر","item.minecraft.splash_potion.effect.slow_falling":"رشة جرعة السقوط البطيء","item.minecraft.book":"كتاب","blockLine truncated
Loaded 100 of 224 files, more files were not shown because too many files have changed in this diff. Show more