Compare commits

..

345 commits

Author SHA1 Message Date
8447233b1e
Merge remote-tracking branch 'origin/v1.x.x' into v1.x.x 2026-06-22 03:12:11 +02:00
eb2e7b3abb
allow enchanted book for super enchant 2026-06-22 03:12:04 +02:00
7f7f049b7b
Update COMPATIBILITY.md 2026-06-22 01:01:45 +02:00
37e8ca7da9
update excellentenchants 2026-06-20 23:49:03 +02:00
95d3cf3228
update nightexpress 2026-06-20 23:43:01 +02:00
178b372255
paper mns use getter/setter no property access [ci skip] 2026-06-20 14:57:12 +02:00
106cd53b02
mark 26.2.x as supported on modrinth & hangar [ci skip] 2026-06-20 03:28:07 +02:00
950bad2168
versions bump 2026-06-19 20:31:43 +02:00
bc9cbe0b44
fix and simplify xp handling
- Fix xp limit not being respected
- Fix player xp not being check causing error
2026-06-19 20:29:10 +02:00
9d616d2fd0
remove use of legacy currentMinecraftVersionArray 2026-06-17 02:15:34 +02:00
f82ccfa07e
make Version work with experimental 26.1 paper build 2026-06-17 02:15:04 +02:00
cff94a2c5a
better thanks and put names in compatibility note [ci skip] 2026-06-16 04:05:17 +02:00
4b5133c872
markdown issue² 2026-06-16 03:49:32 +02:00
98d359f59f
markdown issue [skip ci] 2026-06-16 03:49:16 +02:00
96754fd260
better readme [skip ci] 2026-06-16 03:48:47 +02:00
b92b762551
overdid \ [skip ci] 2026-06-16 03:33:03 +02:00
c064e4b1e1
forgot \ [skip ci] 2026-06-16 03:32:46 +02:00
fc33b6fbd5
Update README.md 2026-06-16 03:27:10 +02:00
29e08fe29b
fix double space issue [ci skip] 2026-06-16 03:17:53 +02:00
151666fd21
better excellent enchant fake event [skip ci] 2026-06-16 03:10:34 +02:00
593527241a
fix bugged unit repair & version bump 2026-06-16 02:57:41 +02:00
3578322686
Update README.md 2026-06-13 15:22:39 +02:00
12ec4e1f54
update faststats
fix a potential plugin issue with disabling faststat in a certain way and fix potential submission on first run
2026-06-13 15:14:33 +02:00
b0f32fdba2
do not load metrics in test 2026-06-10 17:18:43 +02:00
d82bd9b22c
do not packet manager on test 2026-06-10 17:07:52 +02:00
380b0de92f
Lot of internal change and monetary cost (#116)
Internal changes this big was not intentional but had to do it for
monetary cost

excluding that: 
- add monetary cost, with dependency on rename
dialogue
- also change some a bit rename dialog
2026-06-10 15:35:41 +02:00
d91576b0de
update faststat [skip ci] 2026-06-10 15:30:57 +02:00
2f9d25bfe9
fix fake prepare anvil on modern versions 2026-06-10 15:19:56 +02:00
49b0054eca
move anvil cost to its own class 2026-06-10 14:59:28 +02:00
2efb6e55e2
new treat anvil event 2026-06-10 14:54:13 +02:00
d679cd73f9
remove rename pdc on paper lore append 2026-06-09 14:08:17 +02:00
9f06f708f5
fix superenchant price 2026-06-08 10:28:03 +02:00
31fa3d38b7
minimum version of datapack tester upped to unsure minimum java version 2026-06-06 12:46:32 +02:00
bf4395ba3f
fix multiples issues 2026-06-03 03:21:45 +02:00
2768c0a0dc
custom craft monetary cost fixed 2026-06-03 03:21:44 +02:00
f0d53a6ffa
Rename Dialog (#113)
Add a rename dialog for longer possible rename text
Also has a rename fix
2026-06-02 17:16:28 +02:00
d0078e528d
fix creative price and other small fixes 2026-06-02 16:50:14 +02:00
edceba879f
custom craft logic deduplication 2026-06-02 16:18:16 +02:00
106bc724a1
deduplicate lore edit logic 2026-06-02 14:36:09 +02:00
e6293be1c6
deduplicate unit repair logic 2026-06-02 14:01:49 +02:00
7a705f3bfc
move a lot of function to AnvilMergeLogic.kt 2026-06-02 13:29:26 +02:00
df92b4bf91
update faststat to 0.24.0 2026-06-01 13:49:15 +02:00
bf8144ad06
result work for unity repair and custom craft 2026-05-30 03:53:31 +02:00
2d31a7f5a8
seems to work better 2026-05-29 13:21:43 +02:00
3992ce1662
no price on no result 2026-05-29 02:48:16 +02:00
7aac325c70
hell 2026-05-29 00:39:12 +02:00
171a8cad6d
monetary cost require dialog rename 2026-05-28 20:33:20 +02:00
fb27ad2e55
avoid looping on same name 2026-05-28 20:11:02 +02:00
1b3447d041
monetary cost display 2026-05-28 17:26:57 +02:00
ac9f492125
monetary minimum version & rename impl 2026-05-28 17:26:56 +02:00
1660250ee1
monetary dependency functions 2026-05-28 17:26:56 +02:00
856c1e08bd
add monetary config and generic progress 2026-05-28 17:26:56 +02:00
2c3e43cb84
moved to vault unlocked 2026-05-28 17:26:56 +02:00
d67380da1a
per type xp cost 2026-05-28 17:26:50 +02:00
b18cf1fd59
hook to vault economy api 2026-05-28 17:26:22 +02:00
bf926fb159
add forgoten default 2026-05-23 17:03:17 +02:00
21087b89e0
force exist when fail to load non default config [skip ci] 2026-05-23 16:55:56 +02:00
a392702df2
negative max dialog size as infinity 2026-05-22 23:57:56 +02:00
5265d81176
add pcd keept rename name 2026-05-22 23:57:56 +02:00
91d2cce8cc
dialog max size range 2026-05-22 23:57:56 +02:00
31f9e7e281
dialog rename working good enough 2026-05-22 23:57:53 +02:00
05951d0ace
don't consider content equal if same name as type. don't cover all case sadly 2026-05-22 23:57:14 +02:00
65bf82a239
add rename dialog options 2026-05-22 23:57:09 +02:00
90cc758e88
Per color code permission (#114)
Add ability to have color code restricted by a specific permission for
each color code
2026-05-22 23:48:33 +02:00
d926b5001e
per color code permission 2026-05-22 23:44:20 +02:00
809dc3488b
fix broken isInTag logic 2026-05-21 23:16:12 +02:00
3594cf72af
try catch other plugin's listeners 2026-05-21 23:15:53 +02:00
2070f8fd68
do not track error
faststats update
2026-05-21 22:53:34 +02:00
68f63a8ec7
fix max damage not being checked 2026-05-21 22:32:04 +02:00
c703dc68f9
add compatibility notice 2026-05-17 17:49:09 +02:00
36030c598b
Add compatibility with Item Adder (#112) 2026-05-17 17:35:59 +02:00
a6cdd79750
check the same way as item adder for eco items 2026-05-17 17:33:51 +02:00
440b2b2741
create negative material set for iterator 2026-05-17 17:30:16 +02:00
41a62d810a
get "all material" info from other plugins 2026-05-17 17:30:16 +02:00
459e3351fd
item adder namespace considered for unit merge 2026-05-17 17:30:16 +02:00
e00c5e8b47
clone use item adder on custom items adder item 2026-05-17 17:30:16 +02:00
638df714fd
Rename .java to .kt 2026-05-17 17:30:16 +02:00
190f334656
prepare to use item adder dependency for clone 2026-05-17 17:30:16 +02:00
8141232c46
add superenchant bulk operation 2026-05-17 17:25:39 +02:00
a1984ad5b9
Superenchant compatibility (#111)
Superenchant compatibility & update kotlin to 2.3
2026-05-17 17:15:38 +02:00
f5343440e4
add super enchant compatibility 2026-05-14 06:30:46 +02:00
55f6b94ba9
add super enchant as dep and update kotlin 2026-05-14 06:29:18 +02:00
24db259435
add super enchant as lib 2026-05-14 06:28:50 +02:00
d867ca6c85
forgot paper version 2026-04-23 14:16:48 +02:00
1b86996317
add 26.1 ver to modrinth versions 2026-04-23 12:32:41 +02:00
bce43649bc
fix build error 2026-04-23 12:28:30 +02:00
12bfcb75ce
add more spigot warnings 2026-04-21 15:19:06 +02:00
e30f09120d
Work with eco item (#106)
Use material key instead of material enum

This is made with the goal of making eco item work as independant item.
so item type key now depend on eco item's id 

Known issue: EcoEnchant target group still do not has the eco item id inside it and cannot be handled properly by custom anvil
2026-04-21 15:18:37 +02:00
b42fb42d83
fix weird isAir error ? 2026-04-21 14:20:17 +02:00
daa1c6171f
check section exist for group & conflict 2026-04-12 20:39:31 +02:00
d4e94872d8
fix recipe error 2026-04-10 12:12:11 +02:00
7612eac765
progress on using namespaced key instead of material 2026-04-10 12:12:06 +02:00
TrashyPixl
1a71086327 ci: use native github actions features for environment variables 2026-03-26 11:41:22 +01:00
45fe037a92
[ci skip] version bump 2026-03-25 11:07:39 +01:00
d061bfc6f4
Revert "[ci skip] try better changelog"
This reverts commit f520d5e3db.
2026-03-25 03:52:18 +01:00
889d452466
Merge remote-tracking branch 'origin/v1.x.x' into v1.x.x 2026-03-25 03:31:11 +01:00
7fbf68dff3
[ci skip] add deprecation warning 2026-03-25 03:30:50 +01:00
f520d5e3db
[ci skip] try better changelog 2026-03-25 02:25:47 +01:00
e5167971f4
[ci skip] faststat ver up 2026-03-24 02:47:06 +01:00
3d50e0ec82
bruh 2026-03-24 01:40:46 +01:00
60ebdbf107
fix bad copy paste 2026-03-24 01:40:22 +01:00
f3c6526967
add excellent enchant limit 2026-03-23 23:54:38 +01:00
8ded2ae9c6
Better enchant limit & remove protocolib (#109)
Simplify item level limit code by deleting "default level" and using
enchantment's default level instead
allow max level 0 for "can't use it" and -1 for "default maximum"
made the enchantment limit gui reflect the above change

Also removed force protocolib in config as hopefully should be
unnecessary. It is still in the plugin in case something go wrong, which
seems unlikely as never been necessary as far as I remember
2026-03-23 20:40:52 +01:00
f0d2f07703
int item display better 2026-03-23 20:06:58 +01:00
26469982b2
indicate alias 2026-03-23 18:26:20 +01:00
882e50e449
remove force protocolib in config 2026-03-23 18:04:14 +01:00
c96dd7d308 simplify and extend enchant limit 2026-03-23 17:57:47 +01:00
f59071f504
prioritize paper nms on paper servers 2026-03-09 22:43:57 +01:00
6afe51acca
reduce faststat java major version 2026-03-09 22:16:35 +01:00
6a4c861eab
update faststat 2026-03-09 21:22:49 +01:00
ab3e4a32ba
[ci skip] version bump 2026-03-03 16:19:59 +01:00
b532ce7dc6
avoid error on java < 21 2026-03-03 16:19:59 +01:00
e08a02a84a
fix class error on java 17 2026-03-03 16:19:59 +01:00
9b8a2d0f32
[ci skip] update permissions in readme 2026-03-03 15:21:40 +01:00
7bb0c1523d
lowercase .md 2026-03-03 15:07:54 +01:00
5caa56be59
lowercase .md 2026-03-03 15:07:38 +01:00
77c8494166
Add last detected error in diag optional 2026-03-03 04:23:07 +01:00
0440835013
Help Command 2026-03-03 04:15:15 +01:00
bc7ed5af85
add permission on tab completer and pre execute 2026-03-03 03:59:58 +01:00
2dd48a8041
Add faststats Telemetry (#108)
also add telemetry option in config.yml
2026-03-03 03:44:59 +01:00
621222fc01
better telemetry disclosure 2026-03-03 03:43:04 +01:00
7044860267
some fix and add disable error telemetry config 2026-03-03 03:12:35 +01:00
48f0cab15d
error logging and bstats simple pie 2026-03-03 00:39:10 +01:00
3e68af06ea
progress on new metrics 2026-03-02 21:58:09 +01:00
d037263e3f
add fast stats as a dependency 2026-03-02 20:42:50 +01:00
5ff096190f code cleanup 2026-03-02 20:27:21 +01:00
39db70d7ad some more logs 2026-03-02 20:27:21 +01:00
ec2384bc7f fix minor feature explaination issue on config 2026-03-02 20:27:21 +01:00
4e15aab024 fix minor error 2026-03-02 20:27:21 +01:00
a66206a52c add conflict before level 2026-03-02 20:27:21 +01:00
2cff7bd83c made combine with logic work 2026-03-02 20:27:21 +01:00
33a86cd3bc version bump 2026-03-02 20:27:21 +01:00
fbc862a5a3 try add conflict after level 2026-03-02 20:27:21 +01:00
20509faed4 add enchantment data 2026-03-02 19:48:34 +01:00
63f2f16b9f add anvil simulation test for diag 2026-03-02 19:48:34 +01:00
63353c6205 progress on diagnostic command 2026-03-02 19:48:34 +01:00
5f707c7397 progress 2026-03-02 19:48:34 +01:00
3eb07a8c09 prepare generic command 2026-03-02 19:48:34 +01:00
196392e206
workflow invert & simplify logic to put not "" first 2026-02-28 15:20:22 +01:00
f13503f873
Feature/better start (#107) 2026-02-28 15:17:02 +01:00
49abca2ccf update checker 2026-02-27 19:46:36 +01:00
d801d85242 better formating 2026-02-22 04:21:14 +01:00
9cf06fbb93 add bstat in credit 2026-02-22 04:15:30 +01:00
c57de03442 add credits move compatibility list & remove spigot link
spigot is not recomended anymore as do not have auto upload
2026-02-22 04:02:20 +01:00
ae8167faec safer start 2026-02-22 01:10:38 +01:00
7aeb776ce0 add run dir for myself 2026-02-22 00:42:33 +01:00
2c30446bc1
don't use eco's pre anvil event player 2026-02-10 12:39:00 +01:00
9ed43f3def
fix eco enchant conflict with everything 2026-02-10 12:14:35 +01:00
8e3f190bb3
version bump 2026-02-10 12:14:04 +01:00
c8f1aa65a2
change message a bit 2026-02-04 17:41:36 +01:00
4dd7d6361b
fix custom anvil not checking enchantment key name
version bump
2026-02-04 17:38:23 +01:00
58b2910350
Fix incompatibility with excellent enchant 5.4 (#105)
Fix #104
2026-01-27 22:09:10 +01:00
76e5059632
use reflection for enchantment definition 2026-01-27 21:28:33 +01:00
b7e19355a8
version bump 2026-01-27 21:05:14 +01:00
377bc4c1d8
use correct anvil combine method 2026-01-27 21:05:03 +01:00
ea6c5724fa
no changelog for build [skip ci] 2026-01-16 21:43:34 +01:00
f14fe20faf
change message a bit again 2026-01-13 02:20:51 +01:00
675a16c9b4
make modrinth publish run every time 2026-01-13 02:09:15 +01:00
18a0f58e68
fix modrinth release 2026-01-13 02:01:24 +01:00
dc7f3f5e20
add modrinth release and fix discord message 2026-01-13 01:24:43 +01:00
73fd79b9da
add release discord webhook 2026-01-12 03:13:49 +01:00
5c32e819fd
pre release specific suffix 2026-01-12 01:45:16 +01:00
4a2a9c5b3a
try multiline 2026-01-12 01:33:51 +01:00
203713385a
invert bad logic 2026-01-12 01:27:45 +01:00
35c67e4207
set env variable early 2026-01-12 01:17:34 +01:00
e1c794403c
print log on build for release debug 2026-01-12 01:05:15 +01:00
69f0e2936e
forgot paper version 2026-01-12 00:57:19 +01:00
be3a98078f
add hangar publish logic 2026-01-12 00:43:06 +01:00
5fe65799c8
cache paperweight 2026-01-10 21:32:13 +01:00
9e0e546367
why did I used path and not name lol 2026-01-10 19:51:45 +01:00
d4165df61a
try add "on release" workflow 2026-01-10 19:40:55 +01:00
4ed9de3d3c
FINALLY offline build SHOULD work 2026-01-10 19:09:03 +01:00
474ad0f1b2
version up 2026-01-01 19:01:56 +01:00
a373cd76f7
has to add adventure as libary for spigot
sadly
2026-01-01 19:01:13 +01:00
a350b7fa69
finally ! smaller jar is smaller 2026-01-01 18:59:48 +01:00
fe2196626a
bring back old gui tester 2026-01-01 17:32:56 +01:00
161ef6ba91
fix forgot 2025-12-30 02:18:11 +01:00
a6cee2d591
check air 2025-12-30 02:03:58 +01:00
be7f4d0bcb
fix big issue extern gui wrongly tested 2025-12-29 15:20:28 +01:00
89eec84a66
update README.md 2025-12-26 01:34:47 +01:00
59d3c9a85c
update doc 2025-12-26 01:04:41 +01:00
6975f29d9d
Better old versions support (#102) 2025-12-26 00:55:59 +01:00
1544cd315b
fix older version issue 2025-12-26 00:51:14 +01:00
01d7d91d4f
Merge remote-tracking branch 'origin/v1.x.x' into feature/genericnms
# Conflicts:
#	build.gradle.kts
#	settings.gradle.kts
2025-12-25 23:54:00 +01:00
87f7ed6538
fix spigot and refactor some gradlew things (#101) 2025-12-25 23:51:18 +01:00
87c9971626
fix spigot and refactor some gradlew things 2025-12-25 23:49:40 +01:00
fc94dbe169
Generic gui tester and generic paper nms 2025-12-25 22:33:37 +01:00
f5a89fea7c
Merge remote-tracking branch 'refs/remotes/origin/v1.x.x' into feature/genericnms
# Conflicts:
#	src/main/kotlin/xyz/alexcrea/cuanvil/dependency/gui/GuiTesterSelector.kt
2025-12-25 22:09:24 +01:00
ee4936ecf5
reobf for spigot 2025-12-25 21:55:48 +01:00
b8da163e77
Feature/1.21.11 (#100) 2025-12-13 15:12:14 +01:00
c166d2a78a start of nms generalization 2025-12-07 15:34:30 +01:00
9e7a1a963d
fix default rename text issue 2025-12-06 04:11:41 +01:00
35fb136a40
default config for 1.21.11 2025-12-01 19:30:50 +01:00
d096ee7f35
less vebose about minecraft config update 2025-12-01 19:26:33 +01:00
8582038c71
add unit repair for spears 2025-12-01 19:23:32 +01:00
eb24fb4be8
fix copper unit repair not being present 2025-12-01 19:23:32 +01:00
0aad19166f
prepare 1.21.11 nms 2025-12-01 19:23:32 +01:00
905646cdee
prepare config update for 1.21.11 2025-12-01 19:23:32 +01:00
9c3c2cfd2c
version bump 2025-12-01 18:06:44 +01:00
c94c85a3cf
fix forgetting luck of the sea for the longest time (#98) 2025-11-10 23:46:43 +01:00
ade94bdfca
fix forgetting luck of the sea for the longest time 2025-11-10 23:43:16 +01:00
bc8107ca44
Custom anvil only work on nms menu (#97)
Meaning compatibility with most plugin using anvil menu and not only
some selected should be restored !
still need some manual testing
2025-11-10 21:51:24 +01:00
8afd54c94d
Custom anvil only work on nms menu 2025-11-07 00:02:17 +01:00
0993b007a0
fix Excellent enchant compatibility (#96)
fix #93
2025-11-06 23:08:53 +01:00
9e772c7c19
fix Excellent enchant compatibility
fix #93
2025-11-06 23:00:16 +01:00
0b1e3bc12c
add minimessage for color and decoration only (#92)
no test so I don't like it but can't really work more on it currently
2025-11-06 10:46:09 +01:00
b7f98b20fa
version up 2025-11-03 17:25:53 +01:00
fe09a1b2c6
disable lore edit test 2025-11-03 17:06:44 +01:00
e9a2890cfb
tag detection 2025-11-03 16:24:12 +01:00
b9aae9e799
update doc 2025-10-23 15:48:05 +02:00
517fcf3430
disallow use of hex code and minimessage on append 2025-10-23 15:36:14 +02:00
11f7bf8602
progress on using pure component in paper 2025-10-23 15:36:14 +02:00
2967d500eb
use correct condition
Co-authored-by: Illyrius <28700752+illyrius666@users.noreply.github.com>
2025-10-23 08:32:33 +02:00
c9e41aceb6
some refractor 2025-10-20 11:25:43 +02:00
8411b21d1c
forgot some config 2025-10-19 17:01:30 +02:00
9912da869c
add minimessage for color and decoration only 2025-10-19 16:45:45 +02:00
c63482c9df
prepare nms for 1.21.10 2025-10-07 04:41:47 +02:00
7d9b0f05cd
Feature/1.21.9 (#90) 2025-10-07 04:11:13 +02:00
8615ec82e2
Prepare for release 2025-09-27 19:03:04 +02:00
f907a4b6c4
prepare release 2025-09-27 19:01:36 +02:00
07f6da525d Revert "drop 1.17.x to 1.18.x nms"
This reverts commit 3ab6dbc155.
2025-09-27 13:19:21 +02:00
e508f3fdf5
Merge branch 'v1.x.x' into feature/1.21.9 2025-09-25 20:39:11 +02:00
49845f8d6b
prepare version bumb 2025-09-25 20:34:00 +02:00
8b7be2dd1f
add default 1.21.9 configurations 2025-09-25 20:32:05 +02:00
4da017c9be
more pretty log 2025-09-25 20:30:03 +02:00
dd2f3204c3
logic issue fix 2025-09-25 20:24:22 +02:00
5bdd2f9b4c
add copper items 2025-09-25 20:15:41 +02:00
3ab6dbc155
drop 1.17.x to 1.18.x nms
paper bundle are broken
2025-09-25 19:39:10 +02:00
870f56debf
add nms for mc 1.21.9 2025-09-25 19:07:00 +02:00
283a65b74a temporarly disable all ItemsAdder pre anvil event to fix an issue 2025-09-09 08:56:17 +02:00
092daa9306
fix me being stupid
used wrong class
2025-08-18 17:48:43 +02:00
e6ff0a5e5f
fix/disenchantment-gui (#87)
fix disenchantment gui not working
2025-08-16 14:38:39 +02:00
502364e7be
version up 2025-08-16 14:36:48 +02:00
aa86030f01
fix disenchantment gui being broken 2025-08-16 14:32:27 +02:00
54801a07e6
update protocolib to use maven central 2025-08-07 10:40:30 +02:00
600149c237
try fix old ee definition issue (#84) 2025-08-06 14:44:58 +02:00
b1fd64351a
use reflection to support pre v5 2025-07-28 10:42:41 +02:00
d92a97781c
try fix definition issue 2025-07-28 09:49:13 +02:00
179b8db090
use item max stack size and not material's (#83) 2025-07-27 06:46:08 +02:00
444e6354c0
fix enchant limit logic issue 2025-07-27 06:42:04 +02:00
b8f46365a1
use item max stack size and not material's 2025-07-27 04:13:24 +02:00
e4176404ac
fix AxPlayersWarps incompatibility (#82) 2025-07-25 05:42:16 +02:00
f4aaeddb25
fix AxPlayersWarps incompatibility 2025-07-25 05:33:53 +02:00
78ce6a8f42
add enchant limit (#80) 2025-07-24 04:46:19 +02:00
6e02798459
version up 2025-07-24 04:34:17 +02:00
3b8a8fa590
update default config 2025-07-24 04:33:55 +02:00
d03d2a0444
fix small issue 2025-07-24 04:30:52 +02:00
65d6af7672
add per item enchant count limit 2025-07-24 04:29:29 +02:00
b095cd5316
add config value for per item enchantment limit 2025-07-24 04:29:29 +02:00
a8177c9aba
why am I this stupid 2025-07-24 04:29:28 +02:00
00adf05d2b
use eco enchant enchant limit 2025-07-24 04:29:19 +02:00
dea86ab9ce
mc 1.21.8 (#81) 2025-07-24 04:28:43 +02:00
3d58bb2565
1.21.8 2025-07-19 21:05:59 +02:00
2436a84272
do not allow certain dependencies in published pom 2025-07-17 17:00:45 +02:00
d347d7b766
remove use of specific key 2025-07-16 17:25:41 +02:00
2c70e41a38
version 1.13.1 up 2025-07-16 17:02:00 +02:00
a5ccd6f8db
fix a small unexpected behavior with NeoEnchant+ (#76) 2025-07-16 16:55:42 +02:00
56ce36eddf
fix item group update issue (#77) 2025-07-16 16:55:25 +02:00
494f48b9fc
better merge item change check (#78)
try to fix a weird issue with an user
2025-07-16 16:54:59 +02:00
c72372200e
better merge item change check 2025-07-16 15:30:00 +02:00
05f54a5408
fix item group update issue 2025-07-13 23:07:10 +02:00
5b03156965
fix a small unexpected behavior with NeoEnchant+ 2025-07-10 16:51:30 +02:00
4c0c7a8c3b
Revert "add flags for the api"
This reverts commit cea6d51470.

Did not liked the idea after some thinking
2025-07-10 16:27:17 +02:00
cea6d51470
add flags for the api 2025-07-09 23:04:46 +02:00
7ee6ab0376
how was it working 2025-07-09 02:04:34 +02:00
6c470e9fa8
version bump (v1.13.0) 2025-07-08 23:20:06 +02:00
f740248a85
add listener api events (#73) 2025-07-08 23:18:35 +02:00
db6bd4a998
dugeon and taverns support (#75) 2025-07-08 23:17:51 +02:00
c7787676ac
fix enchant conflict file having the wrong name 2025-07-08 22:58:32 +02:00
52c5773118
forgot flint group 2025-07-08 22:04:44 +02:00
a2c0037666
add support for dungeon and taverns datapack 2025-07-08 21:55:37 +02:00
4d956baa56
unit test for config phase events 2025-07-07 04:14:46 +02:00
87e837a4b1
Added javadoc to event
also remove extra Event in one of the event
2025-07-07 03:34:00 +02:00
6029193f6e
append Event to the name of new events 2025-07-06 22:40:33 +02:00
45c5649ee4
fix stupidity 2025-07-06 22:40:33 +02:00
2964bbd998
force set price if bypassed 2025-07-06 22:40:33 +02:00
12d37e1f59
add listener events 2025-07-06 22:40:32 +02:00
6930867e74
EEE item not checked fix (#74)
fix not checking excellent enchant enchantments primary and supported
items
2025-07-06 22:40:13 +02:00
a40fd14b05
Feature/linear recipe cost (#72) 2025-07-06 22:37:04 +02:00
2eed730341
fix not checking excellent enchant enchantments primary and supported items 2025-07-06 22:33:35 +02:00
e93c2cc121
add unit test for new features 2025-07-05 23:04:42 +02:00
a0fa1e3fe2
manually set level and exp % 2025-07-05 23:03:28 +02:00
6078136a80
change api recipe default cost
also update api recipe builder unit test
2025-07-05 04:05:17 +02:00
b6f5c7b7a1
linear xp cost pre anvil unit test 2025-07-05 04:03:11 +02:00
7f19783beb
fix gui logic issue 2025-07-04 23:13:14 +02:00
87ec40a7ab
handle recipe list gui creation and lore 2025-07-04 22:58:40 +02:00
b3cc234ef3
add api for recipe changes 2025-07-04 22:52:18 +02:00
8914369d38
linear cost first gui iteration 2025-07-04 16:19:42 +02:00
8f3c721820
linear cost logic 2025-07-04 15:50:57 +02:00
ec4351e70d
custom craft linear cost config values 2025-07-04 15:50:35 +02:00
0baa1b8b28
linear cost util functions 2025-07-04 15:49:53 +02:00
b2947ff5f7
forgot to update readme again 2025-07-04 14:39:18 +02:00
507e8aa8df
forgot to update readme 2025-07-04 14:38:00 +02:00
7cb7d05cb4
change for 1.21.7 (#70) 2025-07-04 14:34:08 +02:00
600ae9ac1f
version up 2025-07-04 14:33:49 +02:00
d2599492a3
Feature/neo enchant+ (#71)
support neo enchant + datapack
2025-07-04 14:33:06 +02:00
3bb109c31b
forgot elytra group 2025-07-04 14:32:18 +02:00
1076e60bf1 use actual file name 2025-07-04 14:07:46 +02:00
af2d2c45b6 small fix 2025-07-04 13:44:47 +02:00
bd17d55346 small utility I forgot 2025-07-04 13:38:22 +02:00
a8ac725ce1 first attempt for compatibility 2025-07-04 13:04:25 +02:00
4f27744885 change for 1.21.7 2025-07-02 15:34:19 +02:00
97beb3ebe0
update to only need java 21 and no older version 2025-06-25 13:37:17 +02:00
2a36ad945d
fix me being stupid 2025-06-23 22:04:20 +02:00
f24d2e227e
support mc 1.21.6 (#69) 2025-06-21 14:26:28 +02:00
6e2cc20c9e
spigot reobf 2025-06-21 04:05:35 +02:00
344b52bc14 do not reofb 1.21.6 jar
spigot mapping not yet present
2025-06-17 21:59:00 +02:00
119f722494 update readme 2025-06-17 17:38:49 +02:00
3d664b9fbd version up 2025-06-17 17:26:04 +02:00
a0c243f2dd update for 1.21.6 2025-06-17 17:22:23 +02:00
3df4f4bab7 update gradlew & paperweight 2025-06-17 17:15:08 +02:00
fd1267456c
gave up 2025-06-15 04:42:56 +02:00
cb00ba3978
again ? 2025-06-15 04:37:22 +02:00
fa5edbf0d6
this time for sure 2025-06-15 04:28:00 +02:00
e4ddab0a56
try once again.... 2025-06-15 04:20:26 +02:00
b95a906808
try again use path 2025-06-15 04:03:58 +02:00
70c767b366
rename again this time for good 2025-06-15 03:50:10 +02:00
4d9f4ff1f2
forgot to update branch name on action 2025-06-15 03:47:30 +02:00
deaaa9b513
update some dependencies 2025-06-15 03:23:01 +02:00
ce64e0c77e
oopsd 2025-06-14 16:41:13 +02:00
6480c6b4f8
use generic name for artefact that will get zipped anyway 2025-06-14 16:26:25 +02:00
80c6250cc2
version up 2025-06-14 15:59:00 +02:00
ff27180e82
fix null error on toolstat detected (#68) 2025-06-14 15:57:56 +02:00
4ec8597ca2
check nullability of item before getting its token
(toolstat)
2025-06-14 15:57:30 +02:00
b4089fa3a3
Compatibility with Excellent Enchants V5 (#66) 2025-06-14 15:55:29 +02:00
5a2c493b59
Better gradlew workflow (#67)
Upload build artifacts with commit small hash inside the name
2025-06-14 15:54:50 +02:00
d27419ef40
make dependency graph push only 2025-06-14 15:51:14 +02:00
6347db9167
add small hash to actions name 2025-06-14 15:45:56 +02:00
71e0761476
fix not getting environment variable 2025-06-14 14:05:14 +02:00
36a2bd23a6
use small hash for effective plugin version 2025-06-14 13:47:20 +02:00
d4bb82dc87
small commit hash as a gradlew environment variable 2025-06-14 13:35:17 +02:00
3e7b44102c
add write permission because of dependency submission 2025-06-14 12:45:24 +02:00
18b3a0421b
oops 2025-06-14 12:39:33 +02:00
b0d3f25347
move dependency submission & correct upload of jars 2025-06-14 12:33:29 +02:00
1cd2d27814
move back dependency workflow 2025-06-14 12:11:20 +02:00
a44827c2a6
should upload the jars individually now 2025-06-14 12:06:23 +02:00
4ab55b70b4
avoid concurent action 2025-06-14 11:47:01 +02:00
b53b462151
add temporary pull request for test of dependency task 2025-06-14 11:44:16 +02:00
6b470aa635
upload build per individual files 2025-06-14 11:22:56 +02:00
4f8d4d6b77
remove unused note 2025-06-14 11:18:30 +02:00
b3bccb4d1f
move dependency submission out of build 2025-06-14 11:09:39 +02:00
acc9f1fb1b
make workflow run on 2.0 branch 2025-06-14 11:08:45 +02:00
23adf3b1a4
upload build artifacts 2025-06-14 10:45:11 +02:00
7e655281cc
Hellish code for compatibility with Excellent enchant V5
The Hellish part is keeping compatiblity with older versions too
2025-06-04 16:16:49 +02:00
4bb0cb9a89
add excellent enchant v5 jar as lib 2025-06-04 14:34:40 +02:00
222 changed files with 11016 additions and 2604 deletions

View file

@ -9,16 +9,25 @@ name: Java CI with Gradle
on: on:
push: push:
branches: [ "master" ] branches: [ "v1.x.x", "v2.x.x" ]
pull_request: pull_request:
branches: [ "master" ] branches: [ "v1.x.x", "v2.x.x" ]
release:
types: [published]
concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: true
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read contents: write
env:
MODRINTH_VERSIONS: '["1.18.x", "1.19.x", "1.20.x", "1.21.x", "26.1.x", "26.2.x"]'
MODRINTH_PLATFORMS: '["spigot", "paper", "purpur", "folia"]'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -26,57 +35,129 @@ jobs:
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
java-version: | java-version: |
16
17
20
21 21
distribution: 'temurin' distribution: 'temurin'
cache: 'gradle' cache: gradle
- name: Cache Gradle root and wrapper
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-root-${{ runner.os }}-${{ hashFiles('build.gradle*') }}
restore-keys: gradle-root-${{ runner.os }}-
# Setup paperweight cache
- name: Cache paperweight
uses: actions/cache@v3
with:
path: |
./nms/*/.gradle/caches/paperweight
key: paperweight-submodules-${{ runner.os }}-${{ hashFiles('nms/*/build.gradle*') }}
restore-keys: |
paperweight-submodules-${{ runner.os }}-
# Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies. # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
# See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
- name: Setup Gradle - name: Setup Gradle
uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 uses: gradle/actions/setup-gradle@v5
- name: Make gradlew executable - name: Make gradlew executable
run: chmod +x ./gradlew run: chmod +x ./gradlew
- name: Get small commit hash
if: ${{ github.event_name != 'release' && success() }}
run: echo "SMALL_COMMIT_HASH=$(git rev-parse --short ${{ github.sha }})" >> $GITHUB_ENV
- name: Build with Gradle Wrapper - name: Build with Gradle Wrapper
run: ./gradlew build --parallel run: ./gradlew build --parallel --stacktrace
# only submit dependency on push
- name: Generate and submit dependency graph
uses: gradle/actions/dependency-submission@v4
if: ${{ github.event_name == 'push' && success() }}
continue-on-error: true
# Get the names of the online and offline jars
# grep -v "offline" to exclude offline jar as the regex would catch it otherwise
- name: Get file name for jars
run: |
ONLINE_JAR_PATH=$(ls build/libs/CustomAnvil-*.jar | grep -v "offline")
OFFLINE_JAR_PATH=$(ls build/libs/CustomAnvil-*-offline.jar)
echo "ONLINE_JAR_NAME=$(basename $ONLINE_JAR_PATH)" >> $GITHUB_ENV
echo "OFFLINE_JAR_NAME=$(basename $OFFLINE_JAR_PATH)" >> $GITHUB_ENV
# upload the named jars as artifact
- name: Upload online JAR artifact
uses: actions/upload-artifact@v4
with:
name: CustomAnvil.jar
path: build/libs/${{ env.ONLINE_JAR_NAME }}
- name: Upload offline JAR file
uses: actions/upload-artifact@v4
with:
name: CustomAnvil-offline.jar
path: build/libs/${{ env.OFFLINE_JAR_NAME }}
- name: Summarize tests results - name: Summarize tests results
uses: jeantessier/test-summary-action@v1 uses: jeantessier/test-summary-action@v1
if: ${{ always() }} if: ${{ always() }}
# NOTE: The Gradle Wrapper is the default and recommended way to run Gradle (https://docs.gradle.org/current/userguide/gradle_wrapper.html). # upload the jar to release
# If your project does not have the Gradle Wrapper configured, you can use the following configuration to run Gradle with a specified version. - name: Upload jar to release
# if: ${{ github.event_name == 'release' && success() }}
# - name: Setup Gradle uses: softprops/action-gh-release@v2
# uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
# with:
# gradle-version: '8.9'
#
# - name: Build with Gradle 8.9
# run: gradle build
dependency-submission:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Set up JDKs
uses: actions/setup-java@v4
with: with:
distribution: 'temurin' files: |
java-version: | build/libs/${{ env.ONLINE_JAR_NAME }}
16 build/libs/${{ env.OFFLINE_JAR_NAME }}
17
20
21
# Generates and submits a dependency graph, enabling Dependabot Alerts for all project dependencies. - name: Hangar release
# See: https://github.com/gradle/actions/blob/main/dependency-submission/README.md if: ${{ (github.event_name != 'release' || github.event_name != 'push') && github.repository_owner == 'alexcrea' && success() }}
- name: Generate and submit dependency graph env:
uses: gradle/actions/dependency-submission@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 HANGAR_API_TOKEN: ${{ secrets.HANGAR_API_TOKEN }}
RELEASE_CHANGELOG: ${{ github.event.release.body }}
run: ./gradlew publishAllPublicationsToHangar --stacktrace
- name: Modrinth publish alpha
if: ${{ github.event_name == 'push' && github.repository_owner == 'alexcrea' && success() }}
uses: cloudnode-pro/modrinth-publish@v2
with:
token: ${{ secrets.MODRINTH_TOKEN }}
project: S75Ueiq9
name: dev-${{ env.SMALL_COMMIT_HASH }}
version: dev-${{ env.SMALL_COMMIT_HASH }}
loaders: ${{ env.MODRINTH_PLATFORMS }}
game-versions: ${{ env.MODRINTH_VERSIONS }}
channel: alpha
files: build/libs/${{ env.ONLINE_JAR_NAME }}
changelog: ${{ github.event.head_commit.message }}
- name: Modrinth publish release
if: ${{ github.event_name == 'release' && github.repository_owner == 'alexcrea' && success() }}
uses: cloudnode-pro/modrinth-publish@v2
with:
token: ${{ secrets.MODRINTH_TOKEN }}
project: S75Ueiq9
name: ${{ github.event.release.name }}
version: ${{ github.event.release.tag_name }}${{ github.event.release.prerelease && '-pre' || '' }}
loaders: ${{ env.MODRINTH_PLATFORMS }}
game-versions: ${{ env.MODRINTH_VERSIONS }}
channel: ${{ github.event.release.prerelease == false && 'release' || 'beta' }}
files: build/libs/${{ env.ONLINE_JAR_NAME }}
changelog: ${{ github.event.release.body }}
- name: Send release note to discord
if: ${{ github.event_name == 'release' && github.repository_owner == 'alexcrea' && success() }}
uses: tsickert/discord-webhook@v7.0.0
with:
webhook-url: ${{ secrets.RELEASE_WEBHOOK_URL }}
content: |
${{ github.event.release.prerelease == false && '<@&1338546156325568642>' || '<@&1352296092989001768>' }}
# New ${{ github.event.release.prerelease && 'beta ' || '' }}version of custom anvil ! <:CustomAnvil:1262550667986342001>([Modrinth](https://modrinth.com/plugin/customanvil), [Hangar](https://hangar.papermc.io/alexcrea/CustomAnvil) and [GitHub](${{ github.event.release.html_url }}) links)
-# note: automated release. spigot is not uploaded yet.
${{ github.event.release.body }}

3
.gitignore vendored
View file

@ -14,6 +14,9 @@
/impl/*/build /impl/*/build
/impl/*/.gradle /impl/*/.gradle
# run folder
/run/
# other random folders # other random folders
/htmlReport /htmlReport
/.kotlin/errors /.kotlin/errors

9
.run/Server.run.xml Normal file
View file

@ -0,0 +1,9 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Server" type="JarApplication">
<option name="JAR_PATH" value="$PROJECT_DIR$/run/server.jar" />
<option name="PROGRAM_PARAMETERS" value="-nogui" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/run" />
<option name="ALTERNATIVE_JRE_PATH" />
<method v="2" />
</configuration>
</component>

63
COMPATIBILITY.md Normal file
View file

@ -0,0 +1,63 @@
### Bedrock issue
For server using geyser, bedrock player cannot use custom "recipes" in the anvil.
This is cannot be fixed on geyser or my side.
### Plugin Compatibility
Here is various plugins that had issues with CustomAnvil
where efforts was made for compatibility and should be working right:
some if not all of them are cool ! I recommend checking them out !
## Supported By CustomAnvil
These plugins have compatibility handled by custom anvil. seek help on custom anvil and do not bother these developers
#### Enchantment Plugins
- [ExcellentEnchants](https://www.spigotmc.org/resources/excellentenchants-%E2%AD%90-75-vanilla-like-enchantments.61693/) by NightExpress:
Use ExcellentEnchants item type \
Also use ExcellentEnchant max enchant limit
- [EcoEnchant](https://www.spigotmc.org/resources/ecoenchants-%E2%AD%95-250-enchantments-%E2%9C%85-create-custom-enchants-%E2%9C%A8-essentials-cmi-support.79573/) by Auxilor:
Need to use /anvilconfigreload or a server restart to add newly added enchantment.
Use EcoEnchant restriction system but new restriction can be added in custom anvil
- [Enchantment²](https://www.spigotmc.org/resources/enchants-squared-the-enchantsplus-rewrite-custom-enchantments-that-act-like-vanilla-ones.86747/) by Athlaeos:
Support by Custom Anvil but still experimental. Automatic configuration. Plugin is not actively developed anymore
- [SuperEnchants](https://modrinth.com/plugin/superenchants) by Aznos:
Use SuperEnchant restrictions system but new restriction can be added in custom anvil
#### Custom Items Plugins
Custom Items support is considered unstable. If you find issue please report it !
- [EcoItem](https://www.spigotmc.org/resources/30-sale%E2%8F%B3-ecoitems-%E2%AD%95-create-custom-items-%E2%9C%85-weapons-armors-tools-charms-%E2%9C%A8-item-levels-rarities.94601/) by Exanthiax:
May have some issue. but should partially work I hope
- [ItemAdder](https://www.spigotmc.org/resources/%E2%9C%A8itemsadder%E2%AD%90emotes-mobs-items-armors-hud-gui-emojis-blocks-wings-hats-liquids.73355/) by LoneDev:
Need to fix unit item not working completly correctly as in can't have twice same base item
#### Anvil Mechanics Plugins
- [Disenchantment](https://www.spigotmc.org/resources/disenchantment-1-21-1-1-20-6-new-book-splitting-mechanics.110741/) by H7KZ
Partially use Custom Anvil maximum XP settings (>= 6.1.5)
- [HavenBags](https://www.spigotmc.org/resources/havenbags-shulker-like-player-bound-bags-1-17-1-21-4.110420/) by hyperdefined
For bag upgrade and skin via anvil. (version >= 1.31.0)
- [AxPlayerWarp](https://modrinth.com/project/QDJHDKvi) by ArtillexStudios
For its anvil inventory usage
- [ToolsStats](https://modrinth.com/project/oBZj9E15) by Valorless
For token application using anvil
### Known Partially Incompatible
- [UberEnchant](https://modrinth.com/plugin/uberenchant) by coltonj96
Anvil handling as they are doing something similar to CustomAnvil.
It is by no mean there faults and I recommend checking them out especially if custom anvil do not work for your use case !
- [AdvencedEnchantments](https://ae.advancedplugins.net/) by Advanced Plugins
Paid plugin I do not own as I did not get commissioned for support.
may be able to use api but cannot test on my side
If you like Custom Anvil to support a specific plugin (custom enchant or anvil mechanic).
You can ask, but please note implementing compatibility will be considered
as low priority as I work for the plugin as an hobby on my free time for free.

34
CREDITS.md Normal file
View file

@ -0,0 +1,34 @@
Thanks **DelilahEve** for making [Unsafe Enchants](https://github.com/DelilahEve/UnsafeEnchants). \
CustomAnvil was initially a fork of Unsafe Enchants where I wanted to add more and more and here we are now !
Thanks for all the contributors of bukkit, spigot, the paper team and the adventure API developers \
Thanks JetBrain for making IntelliJ
### Dependencies
These dependencies (or a modified version of) are used by custom anvil
- [IF](https://github.com/stefvanschie/IF) an inventory framework by stefvanschie
- [Mockbukkit](https://github.com/MockBukkit/MockBukkit) for unit testing
- [CentralPortalPlus](https://github.com/lalakii/central-portal-plus) by lalakii
- [test-summary-action](https://github.com/jeantessier/test-summary-action) by jeantessier
- [modrinth-publish](https://github.com/cloudnode-pro/modrinth-publish) by Zefir
- [discord-webhook](https://github.com/tsickert/discord-webhook) by tsickert
- Thanks [bstats](https://bstats.org/) for keeping me motivated
- And [FastStats](https://faststats.dev/) alternative to bstats in beta test
- [ModrinthUpdateChecker](https://github.com/Clickism/ModrinthUpdateChecker) by Clickism and thanks to the modrinth team
### Compatibility
Thanks to all the cool creator making the minecraft plugin's ecosystem works ! \
See [Compatibility list](https://github.com/alexcrea/CustomAnvil/blob/v1.x.x/COMPATIBILITY.md) for details
but especially, Big Thanks for H7KZ maker of [Disenchantment](https://github.com/H7KZ/Disenchantment)
### Special Thanks
Thanks for all the users trying my plugin for these niche use cases
, reporting issues and giving ideas !
Thanks coltonj96 for [UberEnchant](https://modrinth.com/plugin/uberenchant).
we may be incompatible with the anvil, but I do think it is a good alternative ! \
I wish one day to work on cross compatibiltiy \
* If custom anvil do not work well for you or your use case give it a try ! *

109
README.md
View file

@ -1,18 +1,11 @@
# Custom Anvil # Custom Anvil
**Custom Anvil** is a plugin that allows server administrators to customize every aspect of the anvil's mechanics. **Custom Anvil** is a plugin that allows server administrators to customize every aspect of the anvil's mechanics.
It is expected to work on 1.18 to 1.21.5 minecraft servers running spigot or paper.
(the plugin support of 1.16.5 to 1.17.1 is experimental and may encounter issues)
**Custom Anvil** was previously named **Unsafe Enchants+**.
It was renamed because it now affects every anvil aspect and not only unsafe enchants\
**Custom Anvil** is based on [Unsafe Enchants](https://github.com/DelilahEve/UnsafeEnchants) by DelilahEve.
### Download Locations: ### Download Locations:
the plugin can be downloaded on the plugin can be downloaded on
[Spigot](https://www.spigotmc.org/resources/custom-anvil.114884), [Modrinth](https://modrinth.com/plugin/customanvil),
[modrinth](https://modrinth.com/plugin/customanvil),
[Hangar](https://hangar.papermc.io/alexcrea/CustomAnvil) [Hangar](https://hangar.papermc.io/alexcrea/CustomAnvil)
or here [on GitHub](https://github.com/alexcrea/CustomAnvil/releases/latest) or here [on GitHub](https://github.com/alexcrea/CustomAnvil/releases/latest)
@ -21,94 +14,98 @@ the plugin can be downloaded on
- Vanilla like default configuration. - Vanilla like default configuration.
- Custom enchantment level limit. - Custom enchantment level limit.
- Custom anvil recipes. - Custom anvil recipes.
- Custom enchant restrictions (allow unsafe enchantment only for a group of item or create new restriction). - Custom enchant restrictions (allows unsafe enchantment only for a group of item or create new restriction).
- Custom items of unit repairs (repair damaged with unit of "material", for example the repair of diamond sword by diamonds). - Custom items of unit repairs (repair damaged with unit of "material", for example the repair of diamond sword by diamonds).
- Custom XP cost for every aspect of the anvil. - Custom XP cost for every aspect of the anvil.
- Permissions to bypass level limit or enchantment restriction. - Permissions to bypass level limit or enchantment restriction.
- Display XP cost instead of "too expensive" when above level 40. (see below for more information) - Display XP cost instead of "too expensive" when above level 40. (see below for more information)
- Can handle some custom enchantment plugins (see below for more information) - Can handle some custom enchantment plugins (see below for more information)
- Gui to configure the plugin in game. - Gui to configure the plugin in game.
- Support of color code and hexadecimal color - Support use of color code, hexadecimal color and minimessage for color/decoration
- (Experimental) Folia support (gui do not work) - (Experimental) Folia support (gui do not work)
- (Experimental) Dialog rename (allows longer rename)
- (Experimental) Anvil with monetary cost (using vault) (require dialog rename)
And more !
--- ---
### Permissions: ### Permissions:
Note that for most of them you also need to enable feature and in most case enable use of permission for the specfic feature (indicated with `(toggleable)`)
```yml ```yml
# Generic and bypass permissions
ca.affected: Player with this permission will be affected by the plugin ca.affected: Player with this permission will be affected by the plugin
ca.bypass.fuse: Allow player to combine every enchantments to every item (no custom limit) ca.bypass.fuse: Allow player to combine every enchantments to every item (no custom limit)
ca.bypass.level: Allow player to bypass every level limit (no custom limit) ca.bypass.level: Allow player to bypass every level limit (no custom limit)
ca.command.reload: Allow administrator to reload the plugin's configs
ca.config.edit: Allow administrator to edit the plugin's config in game
# Bellow permissions also require some config change to allow usage of features
# usage of these permission is toggleable in basic config gui or config.yml
# Permissions related to use of color # Command permissions
ca.color.code: Allow player to use color code if enabled (toggleable) ca.command.reload: Allow administrator to reload the plugin's configs
ca.color.hex: Allow player to use hexadecimal color if enabled (toggleable) ca.command.diagnostic: Allow adminastator to diagnistic some simple problem with the plugin
ca.config.edit: Allow administrator to edit the plugin's config in game
# -----------------------------------------------------------------------------
# Bellow permissions also require some config change to allow usage of features
# Usage of these permission is toggleable in basic config gui or config.yml
# -----------------------------------------------------------------------------
# Permissions related to use of color and minimessage
ca.color.code: Allow player to use color code on rename if enabled (toggleable)
ca.color.code.[thecode] (for example ca.color.code.a): Allows usage of only certain color code (toggleable)
ca.color.hex: Allow player to use hexadecimal color on rename if enabled (toggleable)
ca.rename.minimessage: Allow player to use minimessage formating on rename if enabled (toggleable)
# Permissions related to edition of the lore # Permissions related to edition of the lore
ca.lore_edit.book: Allow player to edit lore via book and quil if enabled (toggleable) ca.lore_edit.book: Allow player to edit lore via book and quil if enabled (toggleable)
ca.lore_edit.paper: Allow player to edit lore via paper if enabled (toggleable) ca.lore_edit.paper: Allow player to edit lore via paper if enabled (toggleable)
# Others
ca.rename.dialog: Allow player to use the rename dialog (toggleable)
``` ```
### Commands ### Commands
```yml
anvilconfigreload or carl: Reload every config of this plugin run `/customanvil help` to get information about available commands \
customanvilconfig or configanvil: open a menu for administrator to edit plugin's config in game this only show subcommands you have permission for
```
### Supported Plugins ### Supported Plugins
Custom Anvil can be compatible with some custom enchantments and anvil mechanics plugins. See the [Compatibility list](https://github.com/alexcrea/CustomAnvil/blob/v1.x.x/COMPATIBILITY.md)
Here is a list of supported custom enchantment plugins with support status:
- [Enchantment²](https://www.spigotmc.org/resources/enchants-squared-the-enchantsplus-rewrite-custom-enchantments-that-act-like-vanilla-ones.86747/):
Support by Custom Anvil but still experimental. Automatic configuration.
- [EcoEnchant](https://www.spigotmc.org/resources/ecoenchants-%E2%AD%95-250-enchantments-%E2%9C%85-create-custom-enchants-%E2%9C%A8-essentials-cmi-support.79573/):
Support by Custom Anvil but still experimental. Need to use /anvilconfigreload or a server restart to add newly added enchantment.
Use EcoEnchant restriction system by default.
- [ExcellentEnchants](https://www.spigotmc.org/resources/excellentenchants-%E2%AD%90-75-vanilla-like-enchantments.61693/):
Support by Custom Anvil but still experimental. Use ExcellentEnchants item type.
- [Superenchants](https://modrinth.com/plugin/superenchants)
support by Superenchants. Use CustomAnvil to combine enchantment in anvil in survival.
Here is a list of supported anvil mechanic plugins with support status:
- [Disenchantment](https://www.spigotmc.org/resources/disenchantment-1-21-1-1-20-6-new-book-splitting-mechanics.110741/)
support by Custom Anvil but still experimental. Mostly use Custom Anvil basic XP settings. (version >= 6.1.5)
- [HavenBags](https://www.spigotmc.org/resources/havenbags-shulker-like-player-bound-bags-1-17-1-21-4.110420/)
support by Custom Anvil. Not really enchantment related but CustomAnvil should not impact bag upgrade and skin via anvil. (version >= 1.31.0)
If you like Custom Anvil to support a specific plugin (custom enchant or anvil mechanic).
You can ask, but please note implementing compatibility will be considered
as low priority as I work for the plugin on my free time for free.
### Overriding Too Expensive ### Overriding Too Expensive
One of the configurations allow displaying price about 40 and removing Too Expensive. \ One of the configurations allow displaying price about 40 and removing Too Expensive. \
By how the minecraft client work: price above 40 can only be displayed green, even if the player does not own enough experience level. By how the minecraft client work: price above 40 can only be displayed green, even if the player does not own enough experience level.
Minecraft version 1.17 to 1.21.5 do not need any dependency. Other version need ProtocoLib enabled on your server for this feature. \ spigot version 1.18 to 1.21.11 do not need any ProtocoLib dependency. (26.1.0 or above requires it) \
You can also wait for an update of the plugin to support a newer version. Any recent paper version also are supported for this feature.
But you should wait for update for new version containing new enchantable item or new enchantments if any of this got added.
Please note that 1.16.5 to 1.17.1 are not officially supported. Run at your own risk. Else it is, likely, fine to use the current version you are ussing on a new paper version
### For custom enchantment plugin developers ### For custom enchantment plugin developers
For information about the API, please refer to [the Wiki](https://github.com/alexcrea/CustomAnvil/wiki) \ For information about the API, please refer to [the Wiki](https://github.com/alexcrea/CustomAnvil/wiki) \
(Please note that the wiki is currently incomplete) (Please note that the wiki is currently incomplete)
--- ---
### Default Plugin's Configurations ### Default Plugin's Configurations
For 1.18 to 1.20.6 use the [1.18 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.18)\ see [Here](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs)
For 1.21 to 1.21.5 use the [1.21 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21)
--- ---
Custom anvil [use bstat](https://bstats.org/plugin/bukkit/Unsafe%20Enchants%20Plus/20923) for metric. You can [disable it](https://bstats.org/getting-started) if you like. ### Metric And Telemetry
Custom anvil [use bstat](https://bstats.org/plugin/bukkit/Unsafe%20Enchants%20Plus/20923)
and [faststats](https://faststats.dev/project/customanvil/minecraft-plugin) for metric and error reporting.
You can select specific telemetry or disable all in config.yml. \
You can also [disable bstat](https://bstats.org/getting-started) and [faststats](https://faststats.dev/info) in their /plugin folder if you like too.
faststats is in beta testing please report me or them any error you encounter
### Credits and Thanks
Credits and thanks can be seen [here](https://github.com/alexcrea/CustomAnvil/blob/v1.x.x/CREDITS.md)
### Planned: ### Planned:
- Better Folia support (make gui work. fix some dirty handled parts) - Better Folia support (make gui work. fix some dirty handled parts)
- Get restriction on unknown enchantments - Get restriction on unknown enchantments (planned for V2)
- More features for custom anvil craft - More features for custom anvil craft
### Known issue: ### Known issue:
Most unknown registered enchantments (by unsupported custom enchantment plugin & datapacks) will not have restriction by default. Planned but no eta. Most unknown registered enchantments (by unsupported custom enchantment plugin & datapacks) will not have restriction by default. Planned but no eta.
### Do you need help with the plugin, or have any issue or suggestion?
You can ask on the discussion page, create a [GitHub issue](https://github.com/alexcrea/CustomAnvil/issues) or join my [discord](https://discord.gg/KHUNsUfRYJ)

View file

@ -1,33 +1,68 @@
import cn.lalaki.pub.BaseCentralPortalPlusExtension import cn.lalaki.pub.BaseCentralPortalPlusExtension
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import groovy.util.Node
import groovy.util.NodeList
import io.papermc.hangarpublishplugin.model.HangarPublication
import io.papermc.hangarpublishplugin.model.Platforms
import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import java.io.ByteArrayOutputStream
plugins { plugins {
kotlin("jvm") version "2.1.0" kotlin("jvm") version "2.3.0"
java java
id("org.jetbrains.dokka").version("1.9.20") id("org.jetbrains.dokka").version("1.9.20")
id("com.gradleup.shadow").version("8.3.5") id("com.gradleup.shadow").version("9.3.0")
// Maven publish // Maven publish
`maven-publish` `maven-publish`
signing signing
id("cn.lalaki.central").version("1.2.5") id("cn.lalaki.central").version("1.2.8")
// Paper // Paper
id("io.papermc.paperweight.userdev") version "2.0.0-beta.16" apply false id("io.papermc.paperweight.userdev") version "2.0.0-beta.17" apply false
id("io.papermc.hangar-publish-plugin") version "0.1.2"
} }
group = "xyz.alexcrea" group = "xyz.alexcrea"
version = "1.11.3" version = "1.17.5"
val isDevBuild = System.getenv("SMALL_COMMIT_HASH") != null
val isPreRelease = System.getenv("IS_GITHUB_PRERELEASE") == "true"
val effectiveVersion = "$version" +
(if (isDevBuild) "-dev-${System.getenv("SMALL_COMMIT_HASH")!!}" else "")
repositories { repositories {
// EcoEnchants // EcoEnchants
maven(url = "https://repo.auxilor.io/repository/maven-public/") maven(url = "https://repo.auxilor.io/repository/maven-public/")
// ExcellentEnchants
maven(url = "https://repo.nightexpressdev.com/releases")
// ItemsAdder
maven(url = "https://maven.devs.beer/")
// For fast stats
maven {
name = "thenextlvlReleases"
url = uri("https://repo.thenextlvl.net/releases")
} }
// For vault unlocked
maven { url = uri("https://repo.codemc.io/repository/creatorfromhell/") }
}
val reobfNMS = providers.gradleProperty("subprojects.reobfnms")
.get().split(",")
dependencies { dependencies {
// Spigot api // Spigot api
compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT") compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT")
// fast stats
implementation("dev.faststats.metrics:bukkit:0.27.0")
// minimessage
implementation("net.kyori:adventure-text-minimessage:4.25.0")
// Gui library // Gui library
val inventoryFramework = "xyz.alexcrea.cuanvil.inventoryframework:IF-CustomAnvil:0.10.18.2" val inventoryFramework = "xyz.alexcrea.cuanvil.inventoryframework:IF-CustomAnvil:0.10.18.2"
implementation(inventoryFramework) implementation(inventoryFramework)
@ -36,15 +71,22 @@ dependencies {
// EnchantsSquaredRewritten // EnchantsSquaredRewritten
compileOnly(files("libs/EnchantsSquared.jar")) compileOnly(files("libs/EnchantsSquared.jar"))
// EcoEnchants // EcoEnchants & item
compileOnly("com.willfp:EcoEnchants:12.11.1") compileOnly("com.willfp:libreforge:4.79.0:all")
compileOnly("com.willfp:eco:6.74.5") compileOnly("com.willfp:eco:6.74.5")
compileOnly("com.willfp:EcoEnchants:12.11.1")
compileOnly(project(":impl:LegacyEcoEnchant")) compileOnly(project(":impl:LegacyEcoEnchant"))
compileOnly("com.willfp:EcoItems:5.66.0")
// ExcellentEnchants // ExcellentEnchants
compileOnly(files("libs/nightcore-2.7.3.jar")) implementation(project(":impl:ExcellentEnchant5_4"))
compileOnly(files("libs/ExcellentEnchants-4.3.1.jar")) compileOnly("su.nightexpress.excellentenchants:Core:5.1.0") {
compileOnly(files("libs/ExcellentEnchants 4.1.0-striped.jar")) // For legacy excellent enchants exclude("org.spigotmc")
}
compileOnly(files("libs/ExcellentEnchants-4.3.3-striped.jar")) // For pre v5 excellent enchants
compileOnly(files("libs/ExcellentEnchants-4.1.0-striped.jar")) // For legacy excellent enchants
// Disenchantment // Disenchantment
compileOnly(files("libs/Disenchantment-6.1.5.jar")) compileOnly(files("libs/Disenchantment-6.1.5.jar"))
@ -55,22 +97,24 @@ dependencies {
// ToolStats // ToolStats
compileOnly(files("libs/toolstats-1.9.6-stripped.jar")) compileOnly(files("libs/toolstats-1.9.6-stripped.jar"))
// AxPlayerWarps
compileOnly(files("libs/AxPlayerWarps-1.10.3.jar"))
// SuperEnchants
compileOnly(files("libs/SuperEnchants-4.6.2-all.jar"))
// ItemsAdder API
compileOnly("dev.lone:api-itemsadder:4.0.10")
// Vault api
compileOnly("net.milkbowl.vault:VaultUnlockedAPI:2.16")
// Include nms // Include nms
implementation(project(":nms:nms-common")) implementation(project(":nms:nms-common"))
implementation(project(":nms:v1_17R1", configuration = "reobf")) implementation(project(":nms:nms-paper"))
implementation(project(":nms:v1_18R1", configuration = "reobf")) for (nmsPart in reobfNMS) {
implementation(project(":nms:v1_18R2", configuration = "reobf")) implementation(project(":nms:$nmsPart", configuration = "reobf"))
implementation(project(":nms:v1_19R1", configuration = "reobf")) }
implementation(project(":nms:v1_19R2", configuration = "reobf"))
implementation(project(":nms:v1_19R3", configuration = "reobf"))
implementation(project(":nms:v1_20R1", configuration = "reobf"))
implementation(project(":nms:v1_20R2", configuration = "reobf"))
implementation(project(":nms:v1_20R3", configuration = "reobf"))
implementation(project(":nms:v1_20R4", configuration = "reobf"))
implementation(project(":nms:v1_21R1", configuration = "reobf"))
implementation(project(":nms:v1_21R2", configuration = "reobf"))
implementation(project(":nms:v1_21R3", configuration = "reobf"))
implementation(project(":nms:v1_21R4", configuration = "reobf"))
// include kotlin for the offline jar // include kotlin for the offline jar
implementation(kotlin("stdlib")) implementation(kotlin("stdlib"))
@ -115,7 +159,8 @@ allprojects {
// Set target version // Set target version
tasks.withType<JavaCompile>().configureEach { tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "16" // We aim for java 16 for minecraft 1.16.5. even if it not really suported by custom anvil. sourceCompatibility =
"16" // We aim for java 16 for minecraft 1.16.5. even if it not really supported by custom anvil.
targetCompatibility = "16" targetCompatibility = "16"
options.encoding = "UTF-8" options.encoding = "UTF-8"
@ -123,43 +168,29 @@ allprojects {
kotlin { kotlin {
compilerOptions { compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_16) jvmTarget.set(JvmTarget.JVM_16)
} }
} }
} }
// Fat-jar builder
val fatJar = tasks.register<Jar>("fatJar") {
manifest {
attributes.apply { put("Main-Class", "io.delilaheve.CustomAnvil") }
}
archiveFileName.set("${rootProject.name}-${project.version}.jar")
exclude("META-INF/*.RSA", "META-INF/*.SF", "META-INF/*.DSA")
duplicatesStrategy = DuplicatesStrategy.WARN
from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) })
with(tasks.jar.get() as CopySpec)
}
tasks { tasks {
// Online jar (use of libraries)
shadowJar {
// No suffix for this jar
archiveClassifier.set("")
// Exclude kotlin std and its annotation fun ShadowJar.configureBaseShadow(suffix: String, libraries: Array<String>) {
exclude("**/kotlin-stdlib*.jar") val processedSuffix = if(suffix.isEmpty()) "" else "-$suffix"
exclude("**/annotations*.jar") val name = "${rootProject.name}-${effectiveVersion}${processedSuffix}.jar"
archiveFileName.set(name)
// Shadow necessary dependency // Shadow necessary dependency
relocate("com.github.stefvanschie.inventoryframework", "xyz.alexcrea.inventoryframework") relocate("com.github.stefvanschie.inventoryframework", "xyz.alexcrea.cuanvil.inventoryframework")
relocate("dev.faststats", "xyz.alexcrea.cuanvil.faststats")
// Replace version and example fields in plugin.yml
filesMatching("plugin.yml") { filesMatching("plugin.yml") {
expand( expand(
"version" to project.version, "version" to effectiveVersion + processedSuffix,
"libraries" to " \"org.jetbrains.kotlin:kotlin-stdlib:2.1.0\" " "libraries" to libraries.joinToString(transform = { "\"$it\"" }),
) )
} }
@ -167,35 +198,28 @@ tasks {
dependsOn(processResources) dependsOn(processResources)
} }
// Offline jar (include kotlin std in the final jar fine) // Online jar (use of libraries)
val offlineJar by // Shadow necessary dependency shadowJar {
registering( configureBaseShadow("",
arrayOf(
"org.jetbrains.kotlin:kotlin-stdlib:2.3.0",
"net.kyori:adventure-text-minimessage:4.25.0",
"net.kyori:adventure-text-serializer-plain:4.25.0",
"net.kyori:adventure-text-serializer-legacy:4.25.0",
))
// Include all project other dependencies // Exclude kotlin std, annotations and adventure api
ShadowJar exclude("*kotlin/**")
exclude("**/annotations/**")
// Add custom anvil compiled exclude("net/kyori/**")
::class, fun ShadowJar.() {
archiveClassifier.set("offline")
// Shadow necessary dependency
relocate("com.github.stefvanschie.inventoryframework", "xyz.alexcrea.inventoryframework")
filesMatching("plugin.yml") {
expand(
"version" to "${project.version}-offline",
"libraries" to ""
)
} }
// Include all project other dependencies val offlineJar by registering(ShadowJar::class) {
from(project.configurations.runtimeClasspath) configureBaseShadow("offline", emptyArray())
// Add custom anvil compiled
from(sourceSets.main.get().output) from(sourceSets.main.get().output)
configurations = listOf(project.configurations.runtimeClasspath.get())
dependsOn(processResources) }
})
// Make the online and offline jar on build // Make the online and offline jar on build
named("build") { named("build") {
@ -248,6 +272,10 @@ object Meta {
const val snapshot = "https://s01.oss.sonatype.org/content/repositories/snapshots/" const val snapshot = "https://s01.oss.sonatype.org/content/repositories/snapshots/"
} }
val disallowedDependency = HashSet<String>()
disallowedDependency.addAll(reobfNMS)
disallowedDependency.addAll(listOf("nms-common", "nms-paper", "kotlin-stdlib"))
publishing { publishing {
repositories { repositories {
maven { maven {
@ -263,6 +291,16 @@ publishing {
from(components["kotlin"]) from(components["kotlin"])
artifact(tasks["sourcesJar"]) artifact(tasks["sourcesJar"])
artifact(tasks["javadocJar"]) artifact(tasks["javadocJar"])
versionMapping {
usage("java-api") {
fromResolutionOf("runtimeClasspath")
}
usage("java-runtime") {
fromResolutionResult()
}
}
pom { pom {
name.set(project.name) name.set(project.name)
description.set(Meta.desc) description.set(Meta.desc)
@ -295,7 +333,123 @@ publishing {
issueManagement { issueManagement {
url.set("https://github.com/${Meta.githubRepo}/issues") url.set("https://github.com/${Meta.githubRepo}/issues")
} }
withXml {
val dependenciesNode = (asNode().get("dependencies") as NodeList)[0] as Node
val toRemove = ArrayList<Node>()
for (child in dependenciesNode.children()) {
val artifactNode = ((child as Node).get("artifactId") as NodeList)[0] as Node
val artifactID = artifactNode.value() as String
if(disallowedDependency.contains(artifactID)) {
toRemove.add(child)
}
}
for (node in toRemove) {
dependenciesNode.remove(node)
} }
} }
} }
} }
}
}
// hangar publish
fun executeGitCommand(vararg command: String): String {
val byteOut = ByteArrayOutputStream()
exec {
commandLine = listOf("git", *command)
standardOutput = byteOut
}
return byteOut.toString(Charsets.UTF_8.name()).trim()
}
fun latestCommitMessage(): String {
return executeGitCommand("log", "-1", "--pretty=%B")
}
fun changelog(isOnline: Boolean): String {
var changelog = if(isDevBuild) latestCommitMessage()
else System.getenv("RELEASE_CHANGELOG")
if(!isOnline) {
changelog = "This is an offline version of the plugin. \\\n" +
"This mean that this plugin libraries are shaded into this plugin \\\n" +
"You likely want to use the normal version of this plugin\n\n" + changelog
}
if(changelog == null || changelog.isEmpty()) {
changelog = "empty changelog"
}
return changelog
}
hangarPublish {
fun HangarPublication.configure(isOnline: Boolean, devChannel: String, releaseChannel: String) {
var versionName = effectiveVersion
if(isPreRelease) versionName+= "-pre"
if(!isOnline) versionName+= "-offline"
version.set(versionName)
channel.set(if (isDevBuild || isPreRelease) devChannel else releaseChannel)
changelog.set(changelog(isOnline))
id.set("CustomAnvil")
apiKey.set(System.getenv("HANGAR_API_TOKEN"))
platforms {
register(Platforms.PAPER) {
// Set the JAR file to upload
var task = if(isOnline) tasks.shadowJar
else tasks.named<ShadowJar>("offlineJar")
jar.set(task.flatMap { it.archiveFile })
// Set platform versions from gradle.properties file
val versions: List<String> = (property("paperVersion") as String)
.split(",")
.map { it.trim() }
platformVersions.set(versions)
dependencies {
hangar("ProtocolLib") {
required.set(false)
}
url("Disenchantment", "https://modrinth.com/plugin/disenchantment") {
required.set(false)
}
url("ToolStats", "https://modrinth.com/plugin/toolstats") {
required.set(false)
}
url("HavenBags", "https://www.spigotmc.org/resources/havenbags-shulker-like-player-bound-bags-1-17-1-21-4.110420/") {
required.set(false)
}
url("EcoEnchants", "https://www.spigotmc.org/resources/ecoenchants-%E2%AD%95-250-enchantments-%E2%9C%85-create-custom-enchants-%E2%9C%A8-essentials-cmi-support.79573/") {
required.set(false)
}
hangar("EnchantsSquared") {
required.set(false)
}
url("ExcellentEnchants", "https://www.spigotmc.org/resources/excellentenchants-%E2%AD%90-75-vanilla-like-enchantments.61693/") {
required.set(false)
}
}
}
}
}
publications.register("plugin") {
configure(true, "DevSnapshot", "Release")
}
publications.register("offline") {
configure(false, "OfflineSnapshot", "OfflineRelease")
}
}

View file

@ -3,6 +3,19 @@
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
# #
# What service of metric should custom anvil use
# Custom anvil collect generic information like server minecraft version, type, etc...
# It can also collect error information if error is happening (currently faststats only)
# It can also be disabled
# Please refer to README for public metric link
# Possible options: auto, bstat, faststats, disabled (auto by default)
metric_type: auto
# Allow to report errors made caused by this plugin (only for faststats)
# This allows me to fix potentials issue that I'm not aware of
# Accept true or false (true by default)
metric_collect_errors: true
# All anvil cost will be capped to limit_repair_value if enabled. # All anvil cost will be capped to limit_repair_value if enabled.
# #
# In other words: # In other words:
@ -59,8 +72,22 @@ sacrifice_illegal_enchant_cost: 1
# #
# Color code are prefixed by "&" and hexadecimal color by "#". # Color code are prefixed by "&" and hexadecimal color by "#".
# Color code will not be applied if it colors nothing. "&&" can be used to write "&". # Color code will not be applied if it colors nothing. "&&" can be used to write "&".
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
allow_color_code: false allow_color_code: false
allow_hexadecimal_color: false allow_hexadecimal_color: false
allow_minimessage: false
# This enables restricting color code for player having specific permission
# It requires allow_color_code enabled for... obvious reasons
#
# For example: if player want to use "&aHello" it will be required that the player has
# the permission "ca.color.code.a" as he used the color code "a"
# In general permission to give to the player is "ca.color.code.[code]"
# where [code] is the color code you wish to allow the player
#
# It is kinda of useless when minimessage is supported as players would be able to bypass
# that using the equivalent minimessage tag
per_color_code_permission: false
# Toggle if color should only be applicable if the player a certain permission. # Toggle if color should only be applicable if the player a certain permission.
# #
@ -72,10 +99,23 @@ permission_needed_for_color: true
# Valid values include 0 to 1000. # Valid values include 0 to 1000.
use_of_color_cost: 0 use_of_color_cost: 0
# Default limit to apply to any enchants missing from enchant_limits # Dialogue rename menu make use of dialog menu to allow bigger rename
# You can also change the maximum size and set it to -1 or less for maximum
# #
# Valid values include 1 to 1000 # This feature only work on paper 1.21.7 or later
default_limit: 5 #
# At the moment only english is available for this menu... sorry !
#
# CustomAnvil use "ca.rename.dialog" when permission
enable_dialog_rename: false
dialog_rename_max_size: 256
permission_needed_for_dialog_rename: false
# This allows custom anvil to not "guess" the text used for rename but store it in the item
# It will make item stackable only and only if it had used the same rename text
#
# For practical reason. this only work when dialog rename is enabled
dialog_rename_keep_user_text: true
# Override limits for specific enchants # Override limits for specific enchants
# #
@ -83,7 +123,8 @@ default_limit: 5
# #
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels # Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
# #
# Valid range of 1 - 255 for each enchantment # Valid range of 0 - 255 for each enchantment
# -1 mean keep default
enchant_limits: enchant_limits:
minecraft:aqua_affinity: 1 minecraft:aqua_affinity: 1
minecraft:binding_curse: 1 minecraft:binding_curse: 1
@ -265,11 +306,20 @@ enchant_values:
# Even if disable-merge-over of unbreaking is set to 2 # Even if disable-merge-over of unbreaking is set to 2
# -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent. # -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent.
disable-merge-over: disable-merge-over:
# Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla) # Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla on default configuration)
minecraft:sharpness: -1 minecraft:sharpness: -1
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied # If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
#minecraft:unbreaking: 2 #minecraft:unbreaking: 2
# The maximum number of enchantment an item can get. -1 for infinity
# Use eco enchant enchant_limit if present by default unless "default" is not equal to -1
enchantment_count_limit:
default: -1
# Limit for specific items. example bellow is an example with stick
# Per item enchantment limit override eco enchant enchant_limit and default limit
items:
stick: -1
# Settings for lore modification # Settings for lore modification
lore_edit: lore_edit:
book_and_quil: book_and_quil:
@ -292,9 +342,12 @@ lore_edit:
# #
# Color code are prefixed by "&" and hexadecimal color by "#" # Color code are prefixed by "&" and hexadecimal color by "#"
# Color code will not be applied if it colors nothing. "&&" can be used to write "&" # Color code will not be applied if it colors nothing. "&&" can be used to write "&"
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
#
# Note that currently minimessage would disable hex code when adding color
allow_color_code: true allow_color_code: true
allow_hexadecimal_color: true allow_hexadecimal_color: false
use_cost: 0 allow_minimessage: true
remove: remove:
# If removing lore using book & quil is enabled # If removing lore using book & quil is enabled
@ -309,16 +362,25 @@ lore_edit:
shared_additive: false shared_additive: false
# If removing the lore consume the book & quil # If removing the lore consume the book & quil
do_consume: false do_consume: false
# If the color should get back to color code or hex format
remove_color_on_remove: true
# Cost of replacing colors # Cost of replacing colors
remove_color_cost: 0 remove_color_cost: 0
# Allowed some color and tags to be reverted to plain text
# Custom anvil will prioritise format that result is a smaller resulting text
# Note that not allowing certain format will lead to some lost of color or tags.
# If configuration are exact as append appending this book should result in the exact same color
#
# Color code will be prefixed by "&" and hexadecimal color by "#".
# If color code is allowed, "&" in the text will get converted to "&&"
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
paper: paper:
# Permission is ca.lore_edit.paper # Permission is ca.lore_edit.paper
use_permission: true use_permission: true
# what order should the lines should get added/removed (start/end, if invalid or not present will be end) # what order should the lines should get added/removed (start/end, if invalid or not present will be end)
order: "end" order: end
append_line: append_line:
# If adding lore line using paper is enabled # If adding lore line using paper is enabled
@ -335,8 +397,12 @@ lore_edit:
# #
# Color code are prefixed by "&" and hexadecimal color by "#" # Color code are prefixed by "&" and hexadecimal color by "#"
# Color code will not be applied if it colors nothing. "&&" can be used to write "&" # Color code will not be applied if it colors nothing. "&&" can be used to write "&"
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
#
# Note that currently minimessage would disable hex code when adding color
allow_color_code: true allow_color_code: true
allow_hexadecimal_color: true allow_hexadecimal_color: false
allow_minimessage: true
color_use_cost: 0 color_use_cost: 0
remove_line: remove_line:
@ -350,10 +416,46 @@ lore_edit:
shared_additive: false shared_additive: false
# If removing the lore line consume the paper # If removing the lore line consume the paper
do_consume: false do_consume: false
# If the color should get back to color code or hex format
remove_color_on_remove: true
# Cost of replacing colors # Cost of replacing colors
remove_color_cost: 0 remove_color_cost: 0
# Allowed some color and tags to be reverted to plain text
# Custom anvil will prioritise format that result is a smaller resulting text
# Note that not allowing certain format will lead to some lost of color or tags.
# If configuration are exact as append appending this paper should result in the exact same color
#
# Color code will be prefixed by "&" and hexadecimal color by "#".
# If color code is allowed, "&" in the text will get converted to "&&"
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
# Allow to replace the xp cost by a monetary cost
# If enabled it will not be bound to the experience level limits
#
# It also requires to enable dialog rename (set "enable_dialog_rename: false" a bit higher)
# If dialog rename permission is enabled and player do not have the permission merge will fall back to vanilla xp cost
#
# If you are using custom craft I recommend using Linear Xp Cost with Exact Linear Xp as normal Xp Cost will act "weird"
# But Linear Xp will act as 1$ time global multiplier. In other word: like you expect
#
# As this feature require dialog rename, it can only be enabled starting with paper 1.21.6 and later
monetary_cost:
enabled: false
# If using vault unlocked this allow to specify what currency should be used for anvil usage
# default being the default currency
currency: default
# multiply the anvil cost by a value to allow to have price a big bigger than like 40
multipliers:
# global multipliers. all usage type will be multiplied by this value
global: 1.0
# usage specific type. it will only apply for specific xp "reason"
enchantment: 1.0 # related to enchantments level
repair: 1.0 # for repairing via unit repair (per unit)
rename: 1.0 # for renaming the item
lore_edit: 1.0 # for changing the lore of the item (only if lore edit is enabled)
work_penalty: 1.0 # for work penalty (aka use penalty)
recipe: 1.0 # for custom anvil recipe cost
# Whether to show debug logging # Whether to show debug logging
debug_log: false debug_log: false
@ -361,10 +463,4 @@ debug_log: false
# Whether to show verbose debug logging # Whether to show verbose debug logging
debug_log_verbose: false debug_log_verbose: false
# In case something when wrong with CustomAnvil packet manager. configVersion: 1.11.0
# If you see "missing class exception" or similar you may test this.
# If enabled and Protocolib absent or disabled "Replace to expensive" will not work.
# ProtocoLib may also be used if the server is in an "unsupported" version even if this option is disabled.
force_protocolib: false
configVersion: 1.8.0

View file

@ -92,6 +92,10 @@ restriction_loyalty:
enchantments: [ minecraft:loyalty ] enchantments: [ minecraft:loyalty ]
notAffectedGroups: [ enchanted_book, trident ] notAffectedGroups: [ enchanted_book, trident ]
restriction_luck_of_the_sea:
enchantments: [ minecraft:luck_of_the_sea ]
notAffectedGroups: [ enchanted_book, fishing_rod ]
restriction_lure: restriction_lure:
enchantments: [ minecraft:lure ] enchantments: [ minecraft:lure ]
notAffectedGroups: [ enchanted_book, fishing_rod ] notAffectedGroups: [ enchanted_book, fishing_rod ]

View file

@ -0,0 +1,6 @@
### Default Plugin's Configurations For 1.21.11
- [config.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.11/config.yml)
- [enchant_conflict.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.11/enchant_conflict.yml)
- [item_groups.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.11/item_groups.yml)
- [unit_repair_item.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.11/unit_repair_item.yml)
- [custom_recipes.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.11/custom_recipes.yml)

View file

@ -0,0 +1,487 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# What service of metric should custom anvil use
# Custom anvil collect generic information like server minecraft version, type, etc...
# It can also collect error information if error is happening (currently faststats only)
# It can also be disabled
# Please refer to README for public metric link
# Possible options: auto, bstat, faststats, disabled (auto by default)
metric_type: auto
# Allow to report errors made caused by this plugin (only for faststats)
# This allows me to fix potentials issue that I'm not aware of
# Accept true or false (true by default)
metric_collect_errors: true
# All anvil cost will be capped to limit_repair_value if enabled.
#
# In other words:
# For any anvil cost greater than limit_repair_value, Cost will be set to limit_repair_value.
limit_repair_cost: false
# Max cost value the Anvil can get to.
#
# Valid values include 0 to 1000.
# Cost will be displayed as "Too Expensive":
# - If Cost is above 39
# - And replace_too_expensive is disabled (false)
limit_repair_value: 39
# Whether the anvil's cost limit should be removed entirely.
#
# The anvil will still visually display "Too Expensive" if "replace_too_expensive" is disabled
# However, the action will be completable if xp requirement is meet.
remove_repair_limit: false
# Whenever anvil cost is above 39 should display the true price and not "Too Expensive".
#
# However, when bypassing "Too Expensive", anvil price will be displayed as Green.
# If the action is not completable, the cost will still be displayed as "Too expensive".
# That mean you also need to change other settings like remove_repair_limit or limit_repair_cost.
#
# Require ProtocoLib.
replace_too_expensive: false
# XP Level amount added to the anvil when the item is repaired by another item of the same type
#
# Valid values include 0 to 1000
item_repair_cost: 2
# XP Level amount added to the anvil when the item is renamed
#
# Valid values include 0 to 1000
item_rename_cost: 1
# XP Level amount added to the anvil when the item is repaired by an "unit"
# For example: a Diamond on a Diamond Sword
# What's considered unit for what can be edited on the unit repair configuration.
#
# Valid values include 0 to 1000
unit_repair_cost: 1
# XP Level amount added to the anvil when a sacrifice enchantment
# conflict with one of the left item enchantment
#
# Valid values include 0 to 1000
sacrifice_illegal_enchant_cost: 1
# Allow using color code and hexadecimal color.
#
# Color code are prefixed by "&" and hexadecimal color by "#".
# Color code will not be applied if it colors nothing. "&&" can be used to write "&".
# For minimessage search for minimessage formating https://docs.papermc.io/adventure/minimessage/format/
# Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin
# but any global tag will be allowed later when v2 release
allow_color_code: false
allow_hexadecimal_color: false
allow_minimessage: false
# This enables restricting color code for player having specific permission
# It requires allow_color_code enabled for... obvious reasons
#
# For example: if player want to use "&aHello" it will be required that the player has
# the permission "ca.color.code.a" as he used the color code "a"
# In general permission to give to the player is "ca.color.code.[code]"
# where [code] is the color code you wish to allow the player
#
# It is kinda of useless when minimessage is supported as players would be able to bypass
# that using the equivalent minimessage tag
per_color_code_permission: false
# Toggle if color should only be applicable if the player a certain permission.
#
# permission are "ca.color.code" for use of color code and "ca.color.hex" for use of hexadecimal color.
permission_needed_for_color: true
# Xp cost if the player use color in the items name on rename.
#
# Valid values include 0 to 1000.
use_of_color_cost: 0
# Dialogue rename menu make use of dialog menu to allow bigger rename
# You can also change the maximum size and set it to -1 or less for maximum
#
# This feature only work on paper 1.21.7 or later
#
# At the moment only english is available for this menu... sorry !
#
# CustomAnvil use "ca.rename.dialog" when permission
enable_dialog_rename: false
dialog_rename_max_size: 256
permission_needed_for_dialog_rename: false
# This allows custom anvil to not "guess" the text used for rename but store it in the item
# It will make item stackable only and only if it had used the same rename text
#
# For practical reason. this only work when dialog rename is enabled
dialog_rename_keep_user_text: true
# Override limits for specific enchants
#
# Enchantments not listed here will use the value of default_limit
#
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
#
# Valid range of 0 - 255 for each enchantment
# -1 mean keep default
enchant_limits:
minecraft:aqua_affinity: 1
minecraft:binding_curse: 1
minecraft:channeling: 1
minecraft:flame: 1
minecraft:infinity: 1
minecraft:mending: 1
minecraft:multishot: 1
minecraft:silk_touch: 1
minecraft:vanishing_curse: 1
minecraft:depth_strider: 3 # anything more than 3 is treated as 3 by the game
minecraft:protection: 4
minecraft:fire_protection: 4
minecraft:blast_protection: 4
minecraft:projectile_protection: 4
minecraft:feather_falling: 4
minecraft:thorns: 3
minecraft:respiration: 3
minecraft:sharpness: 5
minecraft:smite: 5
minecraft:bane_of_arthropods: 5
minecraft:knockback: 2
minecraft:fire_aspect: 2
minecraft:looting: 3
minecraft:sweeping: 3
minecraft:sweeping_edge: 3
minecraft:efficiency: 5
minecraft:unbreaking: 3
minecraft:fortune: 3
minecraft:power: 5
minecraft:punch: 2
minecraft:luck_of_the_sea: 3
minecraft:lure: 3
minecraft:frost_walker: 2
minecraft:impaling: 5
minecraft:riptide: 3
minecraft:loyalty: 3
minecraft:piercing: 4
minecraft:quick_charge: 3
minecraft:soul_speed: 3
minecraft:swift_sneak: 3
minecraft:density: 5
minecraft:breach: 4
minecraft:wind_burst: 3
minecraft:lunge: 3
# Multipliers used to calculate the enchantment's value in repair/combining
#
# Values here are pulled from the fandom wiki:
# https://minecraft.fandom.com/wiki/Anvil_mechanics#Costs_for_combining_enchantments
#
# If an enchantment is missing values here, or is less than 0, it will default to 0
#
# Calculated as: [Enchantment lvl] * [multiplier]
#
# With default values protection 4 would have a value of 4 when
# coming from either a book (4 * 1) or an item (4 * 1)
enchant_values:
minecraft:aqua_affinity:
item: 4
book: 2
minecraft:bane_of_arthropods:
item: 2
book: 1
minecraft:binding_curse:
item: 8
book: 4
minecraft:blast_protection:
item: 4
book: 2
minecraft:channeling:
item: 8
book: 4
minecraft:depth_strider:
item: 4
book: 2
minecraft:efficiency:
item: 1
book: 1
minecraft:flame:
item: 4
book: 2
minecraft:feather_falling:
item: 2
book: 1
minecraft:fire_aspect:
item: 4
book: 2
minecraft:fire_protection:
item: 2
book: 1
minecraft:fortune:
item: 4
book: 2
minecraft:frost_walker:
item: 4
book: 2
minecraft:impaling:
item: 4
book: 2
minecraft:infinity:
item: 8
book: 4
minecraft:knockback:
item: 2
book: 1
minecraft:looting:
item: 4
book: 2
minecraft:loyalty:
item: 1
book: 1
minecraft:luck_of_the_sea:
item: 4
book: 2
minecraft:lure:
item: 4
book: 2
minecraft:mending:
item: 4
book: 2
minecraft:multishot:
item: 4
book: 2
minecraft:piercing:
item: 1
book: 1
minecraft:power:
item: 1
book: 1
minecraft:projectile_protection:
item: 2
book: 1
minecraft:protection:
item: 1
book: 1
minecraft:punch:
item: 4
book: 2
minecraft:quick_charge:
item: 2
book: 1
minecraft:respiration:
item: 4
book: 2
minecraft:riptide:
item: 4
book: 2
minecraft:silk_touch:
item: 8
book: 4
minecraft:sharpness:
item: 1
book: 1
minecraft:smite:
item: 2
book: 1
minecraft:soul_speed:
item: 8
book: 4
minecraft:swift_sneak:
item: 8
book: 4
minecraft:sweeping:
item: 4
book: 2
minecraft:sweeping_edge:
item: 4
book: 2
minecraft:thorns:
item: 8
book: 4
minecraft:unbreaking:
item: 2
book: 1
minecraft:vanishing_curse:
item: 8
book: 4
minecraft:density:
item: 2
book: 1
minecraft:breach:
item: 4
book: 2
minecraft:wind_burst:
item: 4
book: 2
minecraft:lunge:
item: 2
book: 1
# Disable enchantment merging for level above the set value
# Enchantment merging is when, for example, 2 unbreaking II book combine to give sharpness III
# But Enchantment above this value can still be applied. following the previous example, we could still apply a unbreaking III book to a sword
# Even if disable-merge-over of unbreaking is set to 2
# -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent.
disable-merge-over:
# Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla on default configuration)
minecraft:sharpness: -1
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
# minecraft:unbreaking: 2
# The maximum number of enchantment an item can get. -1 for infinity
# Use eco enchant enchant_limit if present by default unless "default" is not equal to -1
enchantment_count_limit:
default: -1
# Limit for specific items. example bellow is an example with stick
# Per item enchantment limit override eco enchant enchant_limit and default limit
items:
stick: -1
# Settings for lore modification
lore_edit:
book_and_quil:
# Permission is ca.lore_edit.book
use_permission: true
append:
# If adding lore using book & quil is enabled
enabled: false
# Cost used every time
fixed_cost: 1
# Cost used for every lore line added
per_line_cost: 0
# Use left item vanilla cost penalty if any
shared_increase: false
# Increase shared left item cost penalty
shared_additive: false
# If adding the lore consume the book & quil
do_consume: false
# Allow using color code and hexadecimal color when editing lore via book & quil
#
# Color code are prefixed by "&" and hexadecimal color by "#"
# Color code will not be applied if it colors nothing. "&&" can be used to write "&"
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
#
# Note that currently minimessage would disable hex code when adding color
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
use_cost: 0
remove:
# If removing lore using book & quil is enabled
enabled: false
# Cost used every time
fixed_cost: 1
# Cost used for every lore line removed
per_line_cost: 0
# Use left item vanilla cost penalty if any
shared_increase: false
# Increase shared left item cost penalty
shared_additive: false
# If removing the lore consume the book & quil
do_consume: false
# Cost of replacing colors
remove_color_cost: 0
# Allowed some color and tags to be reverted to plain text
# Custom anvil will prioritise format that result is a smaller resulting text
# Note that not allowing certain format will lead to some lost of color or tags.
# If configuration are exact as append appending this book should result in the exact same color
#
# Color code will be prefixed by "&" and hexadecimal color by "#".
# If color code is allowed, "&" in the text will get converted to "&&"
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
paper:
# Permission is ca.lore_edit.paper
use_permission: true
# what order should the lines should get added/removed (start/end, if invalid or not present will be end)
order: end
append_line:
# If adding lore line using paper is enabled
enabled: false
# Cost used every time
fixed_cost: 1
# Use left item vanilla cost penalty if any
shared_increase: false
# Increase shared left item cost penalty
shared_additive: false
# If adding the lore line consume the paper
do_consume: false
# Allow using color code and hexadecimal color when editing lore via book & quil
#
# Color code are prefixed by "&" and hexadecimal color by "#"
# Color code will not be applied if it colors nothing. "&&" can be used to write "&"
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
#
# Note that currently minimessage would disable hex code when adding color
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
color_use_cost: 0
use_cost: 0
remove_line:
# If removing lore line using paper is enabled
enabled: false
# Cost used every time
fixed_cost: 1
# Use left item vanilla cost penalty if any
shared_increase: false
# Increase shared left item cost penalty
shared_additive: false
# If removing the lore line consume the paper
do_consume: false
# Cost of replacing colors
remove_color_cost: 0
# Allowed some color and tags to be reverted to plain text
# Custom anvil will prioritise format that result is a smaller resulting text
# Note that not allowing certain format will lead to some lost of color or tags.
# If configuration are exact as append appending this paper should result in the exact same color
#
# Color code will be prefixed by "&" and hexadecimal color by "#".
# If color code is allowed, "&" in the text will get converted to "&&"
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
# Allow to replace the xp cost by a monetary cost
# If enabled it will not be bound to the experience level limits
#
# It also requires to enable dialog rename (set "enable_dialog_rename: false" a bit higher)
# If dialog rename permission is enabled and player do not have the permission merge will fall back to vanilla xp cost
#
# If you are using custom craft I recommend using Linear Xp Cost with Exact Linear Xp as normal Xp Cost will act "weird"
# But Linear Xp will act as 1$ time global multiplier. In other word: like you expect
#
# As this feature require dialog rename, it can only be enabled starting with paper 1.21.6 and later
monetary_cost:
enabled: false
# If using vault unlocked this allow to specify what currency should be used for anvil usage
# default being the default currency
currency: default
# multiply the anvil cost by a value to allow to have price a big bigger than like 40
multipliers:
# global multipliers. all usage type will be multiplied by this value
global: 1.0
# usage specific type. it will only apply for specific xp "reason"
enchantment: 1.0 # related to enchantments level
repair: 1.0 # for repairing via unit repair (per unit)
rename: 1.0 # for renaming the item
lore_edit: 1.0 # for changing the lore of the item (only if lore edit is enabled)
work_penalty: 1.0 # for work penalty (aka use penalty)
recipe: 1.0 # for custom anvil recipe cost
# Whether to show debug logging
debug_log: false
# Whether to show verbose debug logging
debug_log_verbose: false
configVersion: 1.15.5
lowMinecraftVersion: 1.21.11

View file

@ -0,0 +1,5 @@
# ----------------------------------------------------
# This config file is to store custom craft
# It is recommended to use the in game config editor for this configuration.
# /customanvilconfig With ca.config.edit permission
# ----------------------------------------------------

View file

@ -0,0 +1,398 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# material conflicts
#
# If you want to edit this file:
# - A conflict will apply to every item except if in one of the notAffectedGroups group
# - the conflict will count only if the user try to combine at least as
# many conflicting enchantment as "maxEnchantmentBeforeConflict"
#
#
# ----------------------------------------------------
# These restriction are about not allowing enchantment
# on illegal items
# ----------------------------------------------------
restriction_aqua_affinity:
enchantments:
- minecraft:aqua_affinity
notAffectedGroups:
- enchanted_book
- helmets
restriction_bane_of_arthropods:
enchantments:
- minecraft:bane_of_arthropods
notAffectedGroups:
- enchanted_book
- melee_weapons
- mace
restriction_blast_protection:
enchantments:
- minecraft:blast_protection
notAffectedGroups:
- enchanted_book
- armors
restriction_channeling:
enchantments:
- minecraft:channeling
notAffectedGroups:
- enchanted_book
- trident
restriction_binding_curse:
enchantments:
- minecraft:binding_curse
notAffectedGroups:
- enchanted_book
- wearable
restriction_vanishing_curse:
enchantments:
- minecraft:vanishing_curse
notAffectedGroups:
- enchanted_book
- can_vanish
restriction_depth_strider:
enchantments:
- minecraft:depth_strider
notAffectedGroups:
- enchanted_book
- boots
restriction_efficiency:
enchantments:
- minecraft:efficiency
notAffectedGroups:
- enchanted_book
- tools
- shears
restriction_feather_falling:
enchantments:
- minecraft:feather_falling
notAffectedGroups:
- enchanted_book
- boots
restriction_fire_aspect:
enchantments:
- minecraft:fire_aspect
notAffectedGroups:
- enchanted_book
- swords
- mace
- spears
restriction_fire_protection:
enchantments:
- minecraft:fire_protection
notAffectedGroups:
- enchanted_book
- armors
restriction_flame:
enchantments:
- minecraft:flame
notAffectedGroups:
- enchanted_book
- bow
restriction_fortune:
enchantments:
- minecraft:fortune
notAffectedGroups:
- enchanted_book
- tools
restriction_frost_walker:
enchantments:
- minecraft:frost_walker
notAffectedGroups:
- enchanted_book
- boots
restriction_impaling:
enchantments:
- minecraft:impaling
notAffectedGroups:
- enchanted_book
- trident
restriction_infinity:
enchantments:
- minecraft:infinity
notAffectedGroups:
- enchanted_book
- bow
restriction_knockback:
enchantments:
- minecraft:knockback
notAffectedGroups:
- enchanted_book
- swords
- spears
restriction_looting:
enchantments:
- minecraft:looting
notAffectedGroups:
- enchanted_book
- swords
- spears
restriction_loyalty:
enchantments:
- minecraft:loyalty
notAffectedGroups:
- enchanted_book
- trident
restriction_luck_of_the_sea:
enchantments:
- minecraft:luck_of_the_sea
notAffectedGroups:
- enchanted_book
- fishing_rod
restriction_lure:
enchantments:
- minecraft:lure
notAffectedGroups:
- enchanted_book
- fishing_rod
restriction_mending:
enchantments:
- minecraft:mending
notAffectedGroups:
- enchanted_book
- can_unbreak
restriction_minecraft_multishot:
enchantments:
- minecraft:multishot
notAffectedGroups:
- enchanted_book
- crossbow
restriction_piercing:
enchantments:
- minecraft:piercing
notAffectedGroups:
- enchanted_book
- crossbow
restriction_power:
enchantments:
- minecraft:power
notAffectedGroups:
- enchanted_book
- bow
restriction_projectile_protection:
enchantments:
- minecraft:projectile_protection
notAffectedGroups:
- enchanted_book
- armors
restriction_protection:
enchantments:
- minecraft:protection
notAffectedGroups:
- enchanted_book
- armors
restriction_punch:
enchantments:
- minecraft:punch
notAffectedGroups:
- enchanted_book
- bow
restriction_quick_charge:
enchantments:
- minecraft:quick_charge
notAffectedGroups:
- enchanted_book
- crossbow
restriction_respiration:
enchantments:
- minecraft:respiration
notAffectedGroups:
- enchanted_book
- helmets
restriction_riptide:
enchantments:
- minecraft:riptide
notAffectedGroups:
- enchanted_book
- trident
restriction_sharpness:
enchantments:
- minecraft:sharpness
notAffectedGroups:
- enchanted_book
- melee_weapons
restriction__silk_touch:
enchantments:
- minecraft:silk_touch
notAffectedGroups:
- enchanted_book
- tools
restriction_smite:
enchantments:
- minecraft:smite
notAffectedGroups:
- enchanted_book
- melee_weapons
- mace
restriction_soul_speed:
enchantments:
- minecraft:soul_speed
notAffectedGroups:
- enchanted_book
- boots
restriction_sweeping_edge:
enchantments:
- minecraft:sweeping
- minecraft:sweeping_edge
notAffectedGroups:
- enchanted_book
- swords
# Do not exist in 1.18, that mean useInFuture will be set to true
# useInFuture set to true also mean it will not warn if there is an issue
restriction_swift_sneak:
useInFuture: true
enchantments:
- minecraft:swift_sneak
notAffectedGroups:
- enchanted_book
- leggings
restriction_thorns:
enchantments:
- minecraft:thorns
notAffectedGroups:
- enchanted_book
- armors
restriction__unbreaking:
enchantments:
- minecraft:unbreaking
notAffectedGroups:
- enchanted_book
- can_unbreak
# ----------------------------------------------------
# Now we have conflicts about enchantment Incompatibility
# We just filtered what item enchantments can be applied
# notAffectedGroups is empty as we don't want anything to not respect theses rules
# maxEnchantmentBeforeConflict is set to 1 to only have 1 on those enchantment available
# ----------------------------------------------------
sword_enchant_conflict:
enchantments:
- minecraft:bane_of_arthropods
- minecraft:smite
- minecraft:sharpness
- minecraft:density
- minecraft:breach
notAffectedGroups: []
maxEnchantmentBeforeConflict: 1
protection_enchant_conflict:
enchantments:
- minecraft:blast_protection
- minecraft:fire_protection
- minecraft:projectile_protection
- minecraft:protection
notAffectedGroups: []
maxEnchantmentBeforeConflict: 1
trident_conflict1:
enchantments:
- minecraft:channeling
- minecraft:riptide
notAffectedGroups: []
maxEnchantmentBeforeConflict: 1
trident_conflict2:
enchantments:
- minecraft:loyalty
- minecraft:riptide
notAffectedGroups: []
maxEnchantmentBeforeConflict: 1
boot_conflict:
enchantments:
- minecraft:depth_strider
- minecraft:frost_walker
notAffectedGroups: []
maxEnchantmentBeforeConflict: 1
tool_conflict:
enchantments:
- minecraft:fortune
- minecraft:silk_touch
notAffectedGroups: []
maxEnchantmentBeforeConflict: 1
bow_conflict:
enchantments:
- minecraft:mending
- minecraft:infinity
notAffectedGroups: []
maxEnchantmentBeforeConflict: 1
crossbow_conflict:
enchantments:
- minecraft:multishot
- minecraft:piercing
notAffectedGroups: []
maxEnchantmentBeforeConflict: 1
restriction_density:
enchantments:
- minecraft:density
notAffectedGroups:
- mace
- enchanted_book
restriction_breach:
enchantments:
- minecraft:breach
notAffectedGroups:
- mace
- enchanted_book
restriction_wind_burst:
enchantments:
- minecraft:wind_burst
notAffectedGroups:
- mace
- enchanted_book
restriction_lunge:
enchantments:
- minecraft:lunge
notAffectedGroups:
- spears
- enchanted_book
# ----------------------------------------------------
# Bellow is for custom conflicts.
# This is also where conflict create from the gui will be placed.
# ----------------------------------------------------

View file

@ -0,0 +1,247 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# Please note this config use spigot material names.
# It should match minecraft name in most case, maybe every case, but I can't be sure
# In case there an issue with material name, you can found them here:
# https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html
# An empty Exclude group exclude nothing, so it contain everything
everything:
type: exclude
# An empty include group will include nothing
nothing:
type: include
# This group is an example of a group including only stone and polished granite
example_include:
type: include
items:
- stone
- polished_granite
# This group contain everything except polished granite and elements of example_include
example_exclude:
type: exclude
items:
- polished_granite
groups:
- example_include
# Default configuration should be vanilla enchantment conflict group
# there may have error, if you find one you can fix it !
# https://minecraft.fandom.com/wiki/Enchanting
swords:
type: include
items:
- wooden_sword
- stone_sword
- iron_sword
- diamond_sword
- golden_sword
- netherite_sword
- copper_sword
axes:
type: include
items:
- wooden_axe
- stone_axe
- iron_axe
- diamond_axe
- golden_axe
- netherite_axe
- copper_axe
melee_weapons:
type: include
groups:
- swords
- axes
- spears
helmets:
type: include
items:
- leather_helmet
- chainmail_helmet
- iron_helmet
- diamond_helmet
- golden_helmet
- netherite_helmet
- turtle_helmet
- copper_helmet
chestplate:
type: include
items:
- leather_chestplate
- chainmail_chestplate
- iron_chestplate
- diamond_chestplate
- golden_chestplate
- netherite_chestplate
- copper_chestplate
leggings:
type: include
items:
- leather_leggings
- chainmail_leggings
- iron_leggings
- diamond_leggings
- golden_leggings
- netherite_leggings
- copper_leggings
boots:
type: include
items:
- leather_boots
- chainmail_boots
- iron_boots
- diamond_boots
- golden_boots
- netherite_boots
- copper_boots
armors:
type: include
groups:
- helmets
- chestplate
- leggings
- boots
wearable:
type: include
items:
- elytra
- carved_pumpkin
- skeleton_skull
- wither_skeleton_skull
- zombie_head
- player_head
- creeper_head
- dragon_head
- piglin_head
groups:
- armors
pickaxes:
type: include
items:
- wooden_pickaxe
- stone_pickaxe
- iron_pickaxe
- diamond_pickaxe
- golden_pickaxe
- netherite_pickaxe
- copper_pickaxe
shovels:
type: include
items:
- wooden_shovel
- stone_shovel
- iron_shovel
- diamond_shovel
- golden_shovel
- netherite_shovel
- copper_shovel
hoes:
type: include
items:
- wooden_hoe
- stone_hoe
- iron_hoe
- diamond_hoe
- golden_hoe
- netherite_hoe
- copper_hoe
tools:
type: include
groups:
- pickaxes
- shovels
- hoes
- axes
enchanted_book:
type: include
items:
- enchanted_book
trident:
type: include
items:
- trident
bow:
type: include
items:
- bow
crossbow:
type: include
items:
- crossbow
fishing_rod:
type: include
items:
- fishing_rod
shears:
type: include
items:
- shears
can_unbreak:
type: include
items:
- elytra
- flint_and_steel
- shield
- carrot_on_a_stick
- warped_fungus_on_a_stick
- brush
groups:
- melee_weapons
- tools
- armors
- trident
- bow
- crossbow
- fishing_rod
- shears
- mace
can_vanish:
type: include
items:
- compass
groups:
- wearable
- can_unbreak
mace:
type: include
items:
- mace
spears:
type: include
items:
- wooden_spear
- golden_spear
- stone_spear
- copper_spear
- iron_spear
- diamond_spear
- netherite_spear

View file

@ -0,0 +1,220 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# Unit repair configuration
#
# This configuration is to make custom unit repair
# A unit repair is, for example, a diamond to repair a diamond sword
# In vanilla, a unit repair 25% of object durability
# you can make a custom value here
#
# Item name should NOT combine caps and no caps (example: Stone)
# Default value if the config is an invalid value (value <= 0 )
# If value > 1 it will be treated as being = 1
default_repair_amount: 0.25
# You can add custom unit repair
# The example bellow make a shield repaired by 10% by sticks
# stick:
# shield: 0.10
# Vanilla unit repair group is bellow
diamond:
diamond_helmet: 0.25
diamond_chestplate: 0.25
diamond_leggings: 0.25
diamond_boots: 0.25
diamond_sword: 0.25
diamond_pickaxe: 0.25
diamond_axe: 0.25
diamond_shovel: 0.25
diamond_hoe: 0.25
diamond_spear: 0.25
netherite_ingot:
netherite_helmet: 0.25
netherite_chestplate: 0.25
netherite_leggings: 0.25
netherite_boots: 0.25
netherite_sword: 0.25
netherite_pickaxe: 0.25
netherite_axe: 0.25
netherite_shovel: 0.25
netherite_hoe: 0.25
netherite_spear: 0.25
gold_ingot:
golden_helmet: 0.25
golden_chestplate: 0.25
golden_leggings: 0.25
golden_boots: 0.25
golden_sword: 0.25
golden_pickaxe: 0.25
golden_axe: 0.25
golden_shovel: 0.25
golden_hoe: 0.25
golden_spear: 0.25
iron_ingot:
iron_helmet: 0.25
iron_chestplate: 0.25
iron_leggings: 0.25
iron_boots: 0.25
iron_sword: 0.25
iron_pickaxe: 0.25
iron_axe: 0.25
iron_shovel: 0.25
iron_hoe: 0.25
iron_spear: 0.25
cobblestone:
stone_sword: 0.25
stone_pickaxe: 0.25
stone_axe: 0.25
stone_shovel: 0.25
stone_hoe: 0.25
stone_spear: 0.25
cobbled_deepslate:
stone_sword: 0.25
stone_pickaxe: 0.25
stone_axe: 0.25
stone_shovel: 0.25
stone_hoe: 0.25
stone_spear: 0.25
blackstone:
stone_sword: 0.25
stone_pickaxe: 0.25
stone_axe: 0.25
stone_shovel: 0.25
stone_hoe: 0.25
leather:
leather_helmet: 0.25
leather_chestplate: 0.25
leather_leggings: 0.25
leather_boots: 0.25
phantom_membrane:
elytra: 0.25
scute:
turtle_helmet: 0.25
oak_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
wooden_spear: 0.25
spruce_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
wooden_spear: 0.25
birch_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
wooden_spear: 0.25
jungle_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
wooden_spear: 0.25
acacia_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
wooden_spear: 0.25
dark_oak_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
wooden_spear: 0.25
mangrove_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
wooden_spear: 0.25
cherry_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
wooden_spear: 0.25
bamboo_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
wooden_spear: 0.25
crimson_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
wooden_spear: 0.25
warped_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
wooden_spear: 0.25
breeze_rod:
mace: 0.25
copper_ingot:
copper_helmet: 0.25
copper_chestplate: 0.25
copper_leggings: 0.25
copper_boots: 0.25
copper_pickaxe: 0.25
copper_shovel: 0.25
copper_hoe: 0.25
copper_axe: 0.25
copper_sword: 0.25
copper_spear: 0.25

View file

@ -0,0 +1,6 @@
### Default Plugin's Configurations For 1.21.9
- [config.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.9/config.yml)
- [enchant_conflict.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.9/enchant_conflict.yml)
- [item_groups.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.9/item_groups.yml)
- [unit_repair_item.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.9/unit_repair_item.yml)
- [custom_recipes.yml](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.9/custom_recipes.yml)

View file

@ -0,0 +1,479 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# What service of metric should custom anvil use
# Custom anvil collect generic information like server minecraft version, type, etc...
# It can also collect error information if error is happening (currently faststats only)
# It can also be disabled
# Please refer to README for public metric link
# Possible options: auto, bstat, faststats, disabled (auto by default)
metric_type: auto
# Allow to report errors made caused by this plugin (only for faststats)
# This allows me to fix potentials issue that I'm not aware of
# Accept true or false (true by default)
metric_collect_errors: true
# All anvil cost will be capped to limit_repair_value if enabled.
#
# In other words:
# For any anvil cost greater than limit_repair_value, Cost will be set to limit_repair_value.
limit_repair_cost: false
# Max cost value the Anvil can get to.
#
# Valid values include 0 to 1000.
# Cost will be displayed as "Too Expensive":
# - If Cost is above 39
# - And replace_too_expensive is disabled (false)
limit_repair_value: 39
# Whether the anvil's cost limit should be removed entirely.
#
# The anvil will still visually display "Too Expensive" if "replace_too_expensive" is disabled
# However, the action will be completable if xp requirement is meet.
remove_repair_limit: false
# Whenever anvil cost is above 39 should display the true price and not "Too Expensive".
#
# However, when bypassing "Too Expensive", anvil price will be displayed as Green.
# If the action is not completable, the cost will still be displayed as "Too expensive".
# That mean you also need to change other settings like remove_repair_limit or limit_repair_cost.
#
# Require ProtocoLib.
replace_too_expensive: false
# XP Level amount added to the anvil when the item is repaired by another item of the same type
#
# Valid values include 0 to 1000
item_repair_cost: 2
# XP Level amount added to the anvil when the item is renamed
#
# Valid values include 0 to 1000
item_rename_cost: 1
# XP Level amount added to the anvil when the item is repaired by an "unit"
# For example: a Diamond on a Diamond Sword
# What's considered unit for what can be edited on the unit repair configuration.
#
# Valid values include 0 to 1000
unit_repair_cost: 1
# XP Level amount added to the anvil when a sacrifice enchantment
# conflict with one of the left item enchantment
#
# Valid values include 0 to 1000
sacrifice_illegal_enchant_cost: 1
# Allow using color code and hexadecimal color.
#
# Color code are prefixed by "&" and hexadecimal color by "#".
# Color code will not be applied if it colors nothing. "&&" can be used to write "&".
# For minimessage search for minimessage formating https://docs.papermc.io/adventure/minimessage/format/
allow_color_code: false
allow_hexadecimal_color: false
allow_minimessage: false
# This enables restricting color code for player having specific permission
# It requires allow_color_code enabled for... obvious reasons
#
# For example: if player want to use "&aHello" it will be required that the player has
# the permission "ca.color.code.a" as he used the color code "a"
# In general permission to give to the player is "ca.color.code.[code]"
# where [code] is the color code you wish to allow the player
#
# It is kinda of useless when minimessage is supported as players would be able to bypass
# that using the equivalent minimessage tag
per_color_code_permission: false
# Toggle if color should only be applicable if the player a certain permission.
#
# permission are "ca.color.code" for use of color code and "ca.color.hex" for use of hexadecimal color.
permission_needed_for_color: true
# Xp cost if the player use color in the items name on rename.
#
# Valid values include 0 to 1000.
use_of_color_cost: 0
# Dialogue rename menu make use of dialog menu to allow bigger rename
# You can also change the maximum size and set it to -1 or less for maximum
#
# This feature only work on paper 1.21.7 or later
#
# At the moment only english is available for this menu... sorry !
#
# CustomAnvil use "ca.rename.dialog" when permission
enable_dialog_rename: false
dialog_rename_max_size: 256
permission_needed_for_dialog_rename: false
# This allows custom anvil to not "guess" the text used for rename but store it in the item
# It will make item stackable only and only if it had used the same rename text
#
# For practical reason. this only work when dialog rename is enabled
dialog_rename_keep_user_text: true
# Override limits for specific enchants
#
# Enchantments not listed here will use the value of default_limit
#
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
#
# Valid range of 0 - 255 for each enchantment
# -1 mean keep default
enchant_limits:
minecraft:aqua_affinity: 1
minecraft:binding_curse: 1
minecraft:channeling: 1
minecraft:flame: 1
minecraft:infinity: 1
minecraft:mending: 1
minecraft:multishot: 1
minecraft:silk_touch: 1
minecraft:vanishing_curse: 1
minecraft:depth_strider: 3 # anything more than 3 is treated as 3 by the game
minecraft:protection: 4
minecraft:fire_protection: 4
minecraft:blast_protection: 4
minecraft:projectile_protection: 4
minecraft:feather_falling: 4
minecraft:thorns: 3
minecraft:respiration: 3
minecraft:sharpness: 5
minecraft:smite: 5
minecraft:bane_of_arthropods: 5
minecraft:knockback: 2
minecraft:fire_aspect: 2
minecraft:looting: 3
minecraft:sweeping: 3
minecraft:sweeping_edge: 3
minecraft:efficiency: 5
minecraft:unbreaking: 3
minecraft:fortune: 3
minecraft:power: 5
minecraft:punch: 2
minecraft:luck_of_the_sea: 3
minecraft:lure: 3
minecraft:frost_walker: 2
minecraft:impaling: 5
minecraft:riptide: 3
minecraft:loyalty: 3
minecraft:piercing: 4
minecraft:quick_charge: 3
minecraft:soul_speed: 3
minecraft:swift_sneak: 3
minecraft:density: 5
minecraft:breach: 4
minecraft:wind_burst: 3
# Multipliers used to calculate the enchantment's value in repair/combining
#
# Values here are pulled from the fandom wiki:
# https://minecraft.fandom.com/wiki/Anvil_mechanics#Costs_for_combining_enchantments
#
# If an enchantment is missing values here, or is less than 0, it will default to 0
#
# Calculated as: [Enchantment lvl] * [multiplier]
#
# With default values protection 4 would have a value of 4 when
# coming from either a book (4 * 1) or an item (4 * 1)
enchant_values:
minecraft:aqua_affinity:
item: 4
book: 2
minecraft:bane_of_arthropods:
item: 2
book: 1
minecraft:binding_curse:
item: 8
book: 4
minecraft:blast_protection:
item: 4
book: 2
minecraft:channeling:
item: 8
book: 4
minecraft:depth_strider:
item: 4
book: 2
minecraft:efficiency:
item: 1
book: 1
minecraft:flame:
item: 4
book: 2
minecraft:feather_falling:
item: 2
book: 1
minecraft:fire_aspect:
item: 4
book: 2
minecraft:fire_protection:
item: 2
book: 1
minecraft:fortune:
item: 4
book: 2
minecraft:frost_walker:
item: 4
book: 2
minecraft:impaling:
item: 4
book: 2
minecraft:infinity:
item: 8
book: 4
minecraft:knockback:
item: 2
book: 1
minecraft:looting:
item: 4
book: 2
minecraft:loyalty:
item: 1
book: 1
minecraft:luck_of_the_sea:
item: 4
book: 2
minecraft:lure:
item: 4
book: 2
minecraft:mending:
item: 4
book: 2
minecraft:multishot:
item: 4
book: 2
minecraft:piercing:
item: 1
book: 1
minecraft:power:
item: 1
book: 1
minecraft:projectile_protection:
item: 2
book: 1
minecraft:protection:
item: 1
book: 1
minecraft:punch:
item: 4
book: 2
minecraft:quick_charge:
item: 2
book: 1
minecraft:respiration:
item: 4
book: 2
minecraft:riptide:
item: 4
book: 2
minecraft:silk_touch:
item: 8
book: 4
minecraft:sharpness:
item: 1
book: 1
minecraft:smite:
item: 2
book: 1
minecraft:soul_speed:
item: 8
book: 4
minecraft:swift_sneak:
item: 8
book: 4
minecraft:sweeping:
item: 4
book: 2
minecraft:sweeping_edge:
item: 4
book: 2
minecraft:thorns:
item: 8
book: 4
minecraft:unbreaking:
item: 2
book: 1
minecraft:vanishing_curse:
item: 8
book: 4
minecraft:density:
item: 2
book: 1
minecraft:breach:
item: 4
book: 2
minecraft:wind_burst:
item: 4
book: 2
# Disable enchantment merging for level above the set value
# Enchantment merging is when, for example, 2 unbreaking II book combine to give sharpness III
# But Enchantment above this value can still be applied. following the previous example, we could still apply a unbreaking III book to a sword
# Even if disable-merge-over of unbreaking is set to 2
# -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent.
disable-merge-over:
# Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla on default configuration)
minecraft:sharpness: -1
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
# minecraft:unbreaking: 2
# The maximum number of enchantment an item can get. -1 for infinity
# Use eco enchant enchant_limit if present by default unless "default" is not equal to -1
enchantment_count_limit:
default: -1
# Limit for specific items. example bellow is an example with stick
# Per item enchantment limit override eco enchant enchant_limit and default limit
items:
stick: -1
# Settings for lore modification
lore_edit:
book_and_quil:
# Permission is ca.lore_edit.book
use_permission: true
append:
# If adding lore using book & quil is enabled
enabled: false
# Cost used every time
fixed_cost: 1
# Cost used for every lore line added
per_line_cost: 0
# Use left item vanilla cost penalty if any
shared_increase: false
# Increase shared left item cost penalty
shared_additive: false
# If adding the lore consume the book & quil
do_consume: false
# Allow using color code and hexadecimal color when editing lore via book & quil
#
# Color code are prefixed by "&" and hexadecimal color by "#"
# Color code will not be applied if it colors nothing. "&&" can be used to write "&"
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
#
# Note that currently minimessage would disable hex code when adding color
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
remove:
# If removing lore using book & quil is enabled
enabled: false
# Cost used every time
fixed_cost: 1
# Cost used for every lore line removed
per_line_cost: 0
# Use left item vanilla cost penalty if any
shared_increase: false
# Increase shared left item cost penalty
shared_additive: false
# If removing the lore consume the book & quil
do_consume: false
# Cost of replacing colors
remove_color_cost: 0
# Allowed some color and tags to be reverted to plain text
# Custom anvil will prioritise format that result is a smaller resulting text
# Note that not allowing certain format will lead to some lost of color or tags.
# If configuration are exact as append appending this book should result in the exact same color
#
# Color code will be prefixed by "&" and hexadecimal color by "#".
# If color code is allowed, "&" in the text will get converted to "&&"
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
paper:
# Permission is ca.lore_edit.paper
use_permission: true
# what order should the lines should get added/removed (start/end, if invalid or not present will be end)
order: end
append_line:
# If adding lore line using paper is enabled
enabled: false
# Cost used every time
fixed_cost: 1
# Use left item vanilla cost penalty if any
shared_increase: false
# Increase shared left item cost penalty
shared_additive: false
# If adding the lore line consume the paper
do_consume: false
# Allow using color code and hexadecimal color when editing lore via book & quil
#
# Color code are prefixed by "&" and hexadecimal color by "#"
# Color code will not be applied if it colors nothing. "&&" can be used to write "&"
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
#
# Note that currently minimessage would disable hex code when adding color
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
color_use_cost: 0
remove_line:
# If removing lore line using paper is enabled
enabled: false
# Cost used every time
fixed_cost: 1
# Use left item vanilla cost penalty if any
shared_increase: false
# Increase shared left item cost penalty
shared_additive: false
# If removing the lore line consume the paper
do_consume: false
# Cost of replacing colors
remove_color_cost: 0
# Allowed some color and tags to be reverted to plain text
# Custom anvil will prioritise format that result is a smaller resulting text
# Note that not allowing certain format will lead to some lost of color or tags.
# If configuration are exact as append appending this paper should result in the exact same color
#
# Color code will be prefixed by "&" and hexadecimal color by "#".
# If color code is allowed, "&" in the text will get converted to "&&"
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
# Allow to replace the xp cost by a monetary cost
# If enabled it will not be bound to the experience level limits
#
# It also requires to enable dialog rename (set "enable_dialog_rename: false" a bit higher)
# If dialog rename permission is enabled and player do not have the permission merge will fall back to vanilla xp cost
#
# If you are using custom craft I recommend using Linear Xp Cost with Exact Linear Xp as normal Xp Cost will act "weird"
# But Linear Xp will act as 1$ time global multiplier. In other word: like you expect
#
# As this feature require dialog rename, it can only be enabled starting with paper 1.21.6 and later
monetary_cost:
enabled: false
# If using vault unlocked this allow to specify what currency should be used for anvil usage
# default being the default currency
currency: default
# multiply the anvil cost by a value to allow to have price a big bigger than like 40
multipliers:
# global multipliers. all usage type will be multiplied by this value
global: 1.0
# usage specific type. it will only apply for specific xp "reason"
enchantment: 1.0 # related to enchantments level
repair: 1.0 # for repairing via unit repair (per unit)
rename: 1.0 # for renaming the item
lore_edit: 1.0 # for changing the lore of the item (only if lore edit is enabled)
work_penalty: 1.0 # for work penalty (aka use penalty)
recipe: 1.0 # for custom anvil recipe cost
# Whether to show debug logging
debug_log: false
# Whether to show verbose debug logging
debug_log_verbose: false
configVersion: 1.11.0
lowMinecraftVersion: 1.21.9

View file

@ -0,0 +1,5 @@
# ----------------------------------------------------
# This config file is to store custom craft
# It is recommended to use the in game config editor for this configuration.
# /customanvilconfig With ca.config.edit permission
# ----------------------------------------------------

View file

@ -0,0 +1,389 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# material conflicts
#
# If you want to edit this file:
# - A conflict will apply to every item except if in one of the notAffectedGroups group
# - the conflict will count only if the user try to combine at least as
# many conflicting enchantment as "maxEnchantmentBeforeConflict"
#
#
# ----------------------------------------------------
# These restriction are about not allowing enchantment
# on illegal items
# ----------------------------------------------------
restriction_aqua_affinity:
enchantments:
- minecraft:aqua_affinity
notAffectedGroups:
- enchanted_book
- helmets
restriction_bane_of_arthropods:
enchantments:
- minecraft:bane_of_arthropods
notAffectedGroups:
- enchanted_book
- melee_weapons
- mace
restriction_blast_protection:
enchantments:
- minecraft:blast_protection
notAffectedGroups:
- enchanted_book
- armors
restriction_channeling:
enchantments:
- minecraft:channeling
notAffectedGroups:
- enchanted_book
- trident
restriction_binding_curse:
enchantments:
- minecraft:binding_curse
notAffectedGroups:
- enchanted_book
- wearable
restriction_vanishing_curse:
enchantments:
- minecraft:vanishing_curse
notAffectedGroups:
- enchanted_book
- can_vanish
restriction_depth_strider:
enchantments:
- minecraft:depth_strider
notAffectedGroups:
- enchanted_book
- boots
restriction_efficiency:
enchantments:
- minecraft:efficiency
notAffectedGroups:
- enchanted_book
- tools
- shears
restriction_feather_falling:
enchantments:
- minecraft:feather_falling
notAffectedGroups:
- enchanted_book
- boots
restriction_fire_aspect:
enchantments:
- minecraft:fire_aspect
notAffectedGroups:
- enchanted_book
- swords
- mace
restriction_fire_protection:
enchantments:
- minecraft:fire_protection
notAffectedGroups:
- enchanted_book
- armors
restriction_flame:
enchantments:
- minecraft:flame
notAffectedGroups:
- enchanted_book
- bow
restriction_fortune:
enchantments:
- minecraft:fortune
notAffectedGroups:
- enchanted_book
- tools
restriction_frost_walker:
enchantments:
- minecraft:frost_walker
notAffectedGroups:
- enchanted_book
- boots
restriction_impaling:
enchantments:
- minecraft:impaling
notAffectedGroups:
- enchanted_book
- trident
restriction_infinity:
enchantments:
- minecraft:infinity
notAffectedGroups:
- enchanted_book
- bow
restriction_knockback:
enchantments:
- minecraft:knockback
notAffectedGroups:
- enchanted_book
- swords
restriction_looting:
enchantments:
- minecraft:looting
notAffectedGroups:
- enchanted_book
- swords
restriction_loyalty:
enchantments:
- minecraft:loyalty
notAffectedGroups:
- enchanted_book
- trident
restriction_luck_of_the_sea:
enchantments:
- minecraft:luck_of_the_sea
notAffectedGroups:
- enchanted_book
- fishing_rod
restriction_lure:
enchantments:
- minecraft:lure
notAffectedGroups:
- enchanted_book
- fishing_rod
restriction_mending:
enchantments:
- minecraft:mending
notAffectedGroups:
- enchanted_book
- can_unbreak
restriction_minecraft_multishot:
enchantments:
- minecraft:multishot
notAffectedGroups:
- enchanted_book
- crossbow
restriction_piercing:
enchantments:
- minecraft:piercing
notAffectedGroups:
- enchanted_book
- crossbow
restriction_power:
enchantments:
- minecraft:power
notAffectedGroups:
- enchanted_book
- bow
restriction_projectile_protection:
enchantments:
- minecraft:projectile_protection
notAffectedGroups:
- enchanted_book
- armors
restriction_protection:
enchantments:
- minecraft:protection
notAffectedGroups:
- enchanted_book
- armors
restriction_punch:
enchantments:
- minecraft:punch
notAffectedGroups:
- enchanted_book
- bow
restriction_quick_charge:
enchantments:
- minecraft:quick_charge
notAffectedGroups:
- enchanted_book
- crossbow
restriction_respiration:
enchantments:
- minecraft:respiration
notAffectedGroups:
- enchanted_book
- helmets
restriction_riptide:
enchantments:
- minecraft:riptide
notAffectedGroups:
- enchanted_book
- trident
restriction_sharpness:
enchantments:
- minecraft:sharpness
notAffectedGroups:
- enchanted_book
- melee_weapons
restriction__silk_touch:
enchantments:
- minecraft:silk_touch
notAffectedGroups:
- enchanted_book
- tools
restriction_smite:
enchantments:
- minecraft:smite
notAffectedGroups:
- enchanted_book
- melee_weapons
- mace
restriction_soul_speed:
enchantments:
- minecraft:soul_speed
notAffectedGroups:
- enchanted_book
- boots
restriction_sweeping_edge:
enchantments:
- minecraft:sweeping
- minecraft:sweeping_edge
notAffectedGroups:
- enchanted_book
- swords
# Do not exist in 1.18, that mean useInFuture will be set to true
# useInFuture set to true also mean it will not warn if there is an issue
restriction_swift_sneak:
useInFuture: true
enchantments:
- minecraft:swift_sneak
notAffectedGroups:
- enchanted_book
- leggings
restriction_thorns:
enchantments:
- minecraft:thorns
notAffectedGroups:
- enchanted_book
- armors
restriction__unbreaking:
enchantments:
- minecraft:unbreaking
notAffectedGroups:
- enchanted_book
- can_unbreak
# ----------------------------------------------------
# Now we have conflicts about enchantment Incompatibility
# We just filtered what item enchantments can be applied
# notAffectedGroups is empty as we don't want anything to not respect theses rules
# maxEnchantmentBeforeConflict is set to 1 to only have 1 on those enchantment available
# ----------------------------------------------------
sword_enchant_conflict:
enchantments:
- minecraft:bane_of_arthropods
- minecraft:smite
- minecraft:sharpness
- minecraft:density
- minecraft:breach
notAffectedGroups: []
maxEnchantmentBeforeConflict: 1
protection_enchant_conflict:
enchantments:
- minecraft:blast_protection
- minecraft:fire_protection
- minecraft:projectile_protection
- minecraft:protection
notAffectedGroups: []
maxEnchantmentBeforeConflict: 1
trident_conflict1:
enchantments:
- minecraft:channeling
- minecraft:riptide
notAffectedGroups: []
maxEnchantmentBeforeConflict: 1
trident_conflict2:
enchantments:
- minecraft:loyalty
- minecraft:riptide
notAffectedGroups: []
maxEnchantmentBeforeConflict: 1
boot_conflict:
enchantments:
- minecraft:depth_strider
- minecraft:frost_walker
notAffectedGroups: []
maxEnchantmentBeforeConflict: 1
tool_conflict:
enchantments:
- minecraft:fortune
- minecraft:silk_touch
notAffectedGroups: []
maxEnchantmentBeforeConflict: 1
bow_conflict:
enchantments:
- minecraft:mending
- minecraft:infinity
notAffectedGroups: []
maxEnchantmentBeforeConflict: 1
crossbow_conflict:
enchantments:
- minecraft:multishot
- minecraft:piercing
notAffectedGroups: []
maxEnchantmentBeforeConflict: 1
restriction_density:
enchantments:
- minecraft:density
notAffectedGroups:
- mace
- enchanted_book
restriction_breach:
enchantments:
- minecraft:breach
notAffectedGroups:
- mace
- enchanted_book
restriction_wind_burst:
enchantments:
- minecraft:wind_burst
notAffectedGroups:
- mace
- enchanted_book
# ----------------------------------------------------
# Bellow is for custom conflicts.
# This is also where conflict create from the gui will be placed.
# ----------------------------------------------------

View file

@ -0,0 +1,236 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# Please note this config use spigot material names.
# It should match minecraft name in most case, maybe every case, but I can't be sure
# In case there an issue with material name, you can found them here:
# https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html
# An empty Exclude group exclude nothing, so it contain everything
everything:
type: exclude
# An empty include group will include nothing
nothing:
type: include
# This group is an example of a group including only stone and polished granite
example_include:
type: include
items:
- stone
- polished_granite
# This group contain everything except polished granite and elements of example_include
example_exclude:
type: exclude
items:
- polished_granite
groups:
- example_include
# Default configuration should be vanilla enchantment conflict group
# there may have error, if you find one you can fix it !
# https://minecraft.fandom.com/wiki/Enchanting
swords:
type: include
items:
- wooden_sword
- stone_sword
- iron_sword
- diamond_sword
- golden_sword
- netherite_sword
- copper_sword
axes:
type: include
items:
- wooden_axe
- stone_axe
- iron_axe
- diamond_axe
- golden_axe
- netherite_axe
- copper_axe
melee_weapons:
type: include
groups:
- swords
- axes
helmets:
type: include
items:
- leather_helmet
- chainmail_helmet
- iron_helmet
- diamond_helmet
- golden_helmet
- netherite_helmet
- turtle_helmet
- copper_helmet
chestplate:
type: include
items:
- leather_chestplate
- chainmail_chestplate
- iron_chestplate
- diamond_chestplate
- golden_chestplate
- netherite_chestplate
- copper_chestplate
leggings:
type: include
items:
- leather_leggings
- chainmail_leggings
- iron_leggings
- diamond_leggings
- golden_leggings
- netherite_leggings
- copper_leggings
boots:
type: include
items:
- leather_boots
- chainmail_boots
- iron_boots
- diamond_boots
- golden_boots
- netherite_boots
- copper_boots
armors:
type: include
groups:
- helmets
- chestplate
- leggings
- boots
wearable:
type: include
items:
- elytra
- carved_pumpkin
- skeleton_skull
- wither_skeleton_skull
- zombie_head
- player_head
- creeper_head
- dragon_head
- piglin_head
groups:
- armors
pickaxes:
type: include
items:
- wooden_pickaxe
- stone_pickaxe
- iron_pickaxe
- diamond_pickaxe
- golden_pickaxe
- netherite_pickaxe
- copper_pickaxe
shovels:
type: include
items:
- wooden_shovel
- stone_shovel
- iron_shovel
- diamond_shovel
- golden_shovel
- netherite_shovel
- copper_shovel
hoes:
type: include
items:
- wooden_hoe
- stone_hoe
- iron_hoe
- diamond_hoe
- golden_hoe
- netherite_hoe
- copper_hoe
tools:
type: include
groups:
- pickaxes
- shovels
- hoes
- axes
enchanted_book:
type: include
items:
- enchanted_book
trident:
type: include
items:
- trident
bow:
type: include
items:
- bow
crossbow:
type: include
items:
- crossbow
fishing_rod:
type: include
items:
- fishing_rod
shears:
type: include
items:
- shears
can_unbreak:
type: include
items:
- elytra
- flint_and_steel
- shield
- carrot_on_a_stick
- warped_fungus_on_a_stick
- brush
groups:
- melee_weapons
- tools
- armors
- trident
- bow
- crossbow
- fishing_rod
- shears
- mace
can_vanish:
type: include
items:
- compass
groups:
- wearable
- can_unbreak
mace:
type: include
items:
- mace

View file

@ -0,0 +1,192 @@
#
# It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
#
# Unit repair configuration
#
# This configuration is to make custom unit repair
# A unit repair is, for example, a diamond to repair a diamond sword
# In vanilla, a unit repair 25% of object durability
# you can make a custom value here
#
# Item name should NOT combine caps and no caps (example: Stone)
# Default value if the config is an invalid value (value <= 0 )
# If value > 1 it will be treated as being = 1
default_repair_amount: 0.25
# You can add custom unit repair
# The example bellow make a shield repaired by 10% by sticks
# stick:
# shield: 0.10
# Vanilla unit repair group is bellow
diamond:
diamond_helmet: 0.25
diamond_chestplate: 0.25
diamond_leggings: 0.25
diamond_boots: 0.25
diamond_sword: 0.25
diamond_pickaxe: 0.25
diamond_axe: 0.25
diamond_shovel: 0.25
diamond_hoe: 0.25
netherite_ingot:
netherite_helmet: 0.25
netherite_chestplate: 0.25
netherite_leggings: 0.25
netherite_boots: 0.25
netherite_sword: 0.25
netherite_pickaxe: 0.25
netherite_axe: 0.25
netherite_shovel: 0.25
netherite_hoe: 0.25
gold_ingot:
golden_helmet: 0.25
golden_chestplate: 0.25
golden_leggings: 0.25
golden_boots: 0.25
golden_sword: 0.25
golden_pickaxe: 0.25
golden_axe: 0.25
golden_shovel: 0.25
golden_hoe: 0.25
iron_ingot:
iron_helmet: 0.25
iron_chestplate: 0.25
iron_leggings: 0.25
iron_boots: 0.25
iron_sword: 0.25
iron_pickaxe: 0.25
iron_axe: 0.25
iron_shovel: 0.25
iron_hoe: 0.25
cobblestone:
stone_sword: 0.25
stone_pickaxe: 0.25
stone_axe: 0.25
stone_shovel: 0.25
stone_hoe: 0.25
cobbled_deepslate:
stone_sword: 0.25
stone_pickaxe: 0.25
stone_axe: 0.25
stone_shovel: 0.25
stone_hoe: 0.25
blackstone:
stone_sword: 0.25
stone_pickaxe: 0.25
stone_axe: 0.25
stone_shovel: 0.25
stone_hoe: 0.25
leather:
leather_helmet: 0.25
leather_chestplate: 0.25
leather_leggings: 0.25
leather_boots: 0.25
phantom_membrane:
elytra: 0.25
scute:
turtle_helmet: 0.25
oak_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
spruce_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
birch_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
jungle_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
acacia_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
dark_oak_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
mangrove_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
cherry_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
bamboo_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
crimson_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
warped_planks:
wooden_sword: 0.25
wooden_pickaxe: 0.25
wooden_axe: 0.25
wooden_shovel: 0.25
wooden_hoe: 0.25
shield: 0.25
breeze_rod:
mace: 0.25

View file

@ -3,6 +3,19 @@
# You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /anvilconfigreload after you changes !
# #
# What service of metric should custom anvil use
# Custom anvil collect generic information like server minecraft version, type, etc...
# It can also collect error information if error is happening (currently faststats only)
# It can also be disabled
# Please refer to README for public metric link
# Possible options: auto, bstat, faststats, disabled (auto by default)
metric_type: auto
# Allow to report errors made caused by this plugin (only for faststats)
# This allows me to fix potentials issue that I'm not aware of
# Accept true or false (true by default)
metric_collect_errors: true
# All anvil cost will be capped to limit_repair_value if enabled. # All anvil cost will be capped to limit_repair_value if enabled.
# #
# In other words: # In other words:
@ -59,8 +72,22 @@ sacrifice_illegal_enchant_cost: 1
# #
# Color code are prefixed by "&" and hexadecimal color by "#". # Color code are prefixed by "&" and hexadecimal color by "#".
# Color code will not be applied if it colors nothing. "&&" can be used to write "&". # Color code will not be applied if it colors nothing. "&&" can be used to write "&".
# For minimessage search for minimessage formating https://docs.papermc.io/adventure/minimessage/format/
allow_color_code: false allow_color_code: false
allow_hexadecimal_color: false allow_hexadecimal_color: false
allow_minimessage: false
# This enables restricting color code for player having specific permission
# It requires allow_color_code enabled for... obvious reasons
#
# For example: if player want to use "&aHello" it will be required that the player has
# the permission "ca.color.code.a" as he used the color code "a"
# In general permission to give to the player is "ca.color.code.[code]"
# where [code] is the color code you wish to allow the player
#
# It is kinda of useless when minimessage is supported as players would be able to bypass
# that using the equivalent minimessage tag
per_color_code_permission: false
# Toggle if color should only be applicable if the player a certain permission. # Toggle if color should only be applicable if the player a certain permission.
# #
@ -72,10 +99,23 @@ permission_needed_for_color: true
# Valid values include 0 to 1000. # Valid values include 0 to 1000.
use_of_color_cost: 0 use_of_color_cost: 0
# Default limit to apply to any enchants missing from enchant_limits # Dialogue rename menu make use of dialog menu to allow bigger rename
# You can also change the maximum size and set it to -1 or less for maximum
# #
# Valid values include 1 to 1000 # This feature only work on paper 1.21.7 or later
default_limit: 5 #
# At the moment only english is available for this menu... sorry !
#
# CustomAnvil use "ca.rename.dialog" when permission
enable_dialog_rename: false
dialog_rename_max_size: 256
permission_needed_for_dialog_rename: false
# This allows custom anvil to not "guess" the text used for rename but store it in the item
# It will make item stackable only and only if it had used the same rename text
#
# For practical reason. this only work when dialog rename is enabled
dialog_rename_keep_user_text: true
# Override limits for specific enchants # Override limits for specific enchants
# #
@ -83,7 +123,8 @@ default_limit: 5
# #
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels # Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
# #
# Valid range of 1 - 255 for each enchantment # Valid range of 0 - 255 for each enchantment
# -1 mean keep default
enchant_limits: enchant_limits:
minecraft:aqua_affinity: 1 minecraft:aqua_affinity: 1
minecraft:binding_curse: 1 minecraft:binding_curse: 1
@ -265,11 +306,20 @@ enchant_values:
# Even if disable-merge-over of unbreaking is set to 2 # Even if disable-merge-over of unbreaking is set to 2
# -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent. # -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent.
disable-merge-over: disable-merge-over:
# Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla) # Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla on default configuration)
minecraft:sharpness: -1 minecraft:sharpness: -1
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied # If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
# minecraft:unbreaking: 2 # minecraft:unbreaking: 2
# The maximum number of enchantment an item can get. -1 for infinity
# Use eco enchant enchant_limit if present by default unless "default" is not equal to -1
enchantment_count_limit:
default: -1
# Limit for specific items. example bellow is an example with stick
# Per item enchantment limit override eco enchant enchant_limit and default limit
items:
stick: -1
# Settings for lore modification # Settings for lore modification
lore_edit: lore_edit:
book_and_quil: book_and_quil:
@ -292,9 +342,12 @@ lore_edit:
# #
# Color code are prefixed by "&" and hexadecimal color by "#" # Color code are prefixed by "&" and hexadecimal color by "#"
# Color code will not be applied if it colors nothing. "&&" can be used to write "&" # Color code will not be applied if it colors nothing. "&&" can be used to write "&"
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
#
# Note that currently minimessage would disable hex code when adding color
allow_color_code: true allow_color_code: true
allow_hexadecimal_color: true allow_hexadecimal_color: false
use_cost: 0 allow_minimessage: true
remove: remove:
# If removing lore using book & quil is enabled # If removing lore using book & quil is enabled
@ -309,16 +362,25 @@ lore_edit:
shared_additive: false shared_additive: false
# If removing the lore consume the book & quil # If removing the lore consume the book & quil
do_consume: false do_consume: false
# If the color should get back to color code or hex format
remove_color_on_remove: true
# Cost of replacing colors # Cost of replacing colors
remove_color_cost: 0 remove_color_cost: 0
# Allowed some color and tags to be reverted to plain text
# Custom anvil will prioritise format that result is a smaller resulting text
# Note that not allowing certain format will lead to some lost of color or tags.
# If configuration are exact as append appending this book should result in the exact same color
#
# Color code will be prefixed by "&" and hexadecimal color by "#".
# If color code is allowed, "&" in the text will get converted to "&&"
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
paper: paper:
# Permission is ca.lore_edit.paper # Permission is ca.lore_edit.paper
use_permission: true use_permission: true
# what order should the lines should get added/removed (start/end, if invalid or not present will be end) # what order should the lines should get added/removed (start/end, if invalid or not present will be end)
order: "end" order: end
append_line: append_line:
# If adding lore line using paper is enabled # If adding lore line using paper is enabled
@ -335,8 +397,12 @@ lore_edit:
# #
# Color code are prefixed by "&" and hexadecimal color by "#" # Color code are prefixed by "&" and hexadecimal color by "#"
# Color code will not be applied if it colors nothing. "&&" can be used to write "&" # Color code will not be applied if it colors nothing. "&&" can be used to write "&"
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
#
# Note that currently minimessage would disable hex code when adding color
allow_color_code: true allow_color_code: true
allow_hexadecimal_color: true allow_hexadecimal_color: false
allow_minimessage: true
color_use_cost: 0 color_use_cost: 0
remove_line: remove_line:
@ -350,10 +416,46 @@ lore_edit:
shared_additive: false shared_additive: false
# If removing the lore line consume the paper # If removing the lore line consume the paper
do_consume: false do_consume: false
# If the color should get back to color code or hex format
remove_color_on_remove: true
# Cost of replacing colors # Cost of replacing colors
remove_color_cost: 0 remove_color_cost: 0
# Allowed some color and tags to be reverted to plain text
# Custom anvil will prioritise format that result is a smaller resulting text
# Note that not allowing certain format will lead to some lost of color or tags.
# If configuration are exact as append appending this paper should result in the exact same color
#
# Color code will be prefixed by "&" and hexadecimal color by "#".
# If color code is allowed, "&" in the text will get converted to "&&"
# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
# Allow to replace the xp cost by a monetary cost
# If enabled it will not be bound to the experience level limits
#
# It also requires to enable dialog rename (set "enable_dialog_rename: false" a bit higher)
# If dialog rename permission is enabled and player do not have the permission merge will fall back to vanilla xp cost
#
# If you are using custom craft I recommend using Linear Xp Cost with Exact Linear Xp as normal Xp Cost will act "weird"
# But Linear Xp will act as 1$ time global multiplier. In other word: like you expect
#
# As this feature require dialog rename, it can only be enabled starting with paper 1.21.6 and later
monetary_cost:
enabled: false
# If using vault unlocked this allow to specify what currency should be used for anvil usage
# default being the default currency
currency: default
# multiply the anvil cost by a value to allow to have price a big bigger than like 40
multipliers:
# global multipliers. all usage type will be multiplied by this value
global: 1.0
# usage specific type. it will only apply for specific xp "reason"
enchantment: 1.0 # related to enchantments level
repair: 1.0 # for repairing via unit repair (per unit)
rename: 1.0 # for renaming the item
lore_edit: 1.0 # for changing the lore of the item (only if lore edit is enabled)
work_penalty: 1.0 # for work penalty (aka use penalty)
recipe: 1.0 # for custom anvil recipe cost
# Whether to show debug logging # Whether to show debug logging
debug_log: false debug_log: false
@ -361,10 +463,4 @@ debug_log: false
# Whether to show verbose debug logging # Whether to show verbose debug logging
debug_log_verbose: false debug_log_verbose: false
# In case something when wrong with CustomAnvil packet manager. configVersion: 1.11.0
# If you see "missing class exception" or similar you may test this.
# If enabled and Protocolib absent or disabled "Replace to expensive" will not work.
# ProtocoLib may also be used if the server is in an "unsupported" version even if this option is disabled.
force_protocolib: false
configVersion: 1.8.0

View file

@ -92,6 +92,10 @@ restriction_loyalty:
enchantments: [ minecraft:loyalty ] enchantments: [ minecraft:loyalty ]
notAffectedGroups: [ enchanted_book, trident ] notAffectedGroups: [ enchanted_book, trident ]
restriction_luck_of_the_sea:
enchantments: [ minecraft:luck_of_the_sea ]
notAffectedGroups: [ enchanted_book, fishing_rod ]
restriction_lure: restriction_lure:
enchantments: [ minecraft:lure ] enchantments: [ minecraft:lure ]
notAffectedGroups: [ enchanted_book, fishing_rod ] notAffectedGroups: [ enchanted_book, fishing_rod ]

View file

@ -1,3 +1,5 @@
### Default Plugin's Configurations ### Default Plugin's Configurations
For 1.18 to 1.20.6 use [1.18 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.18) \ From 1.18 to 1.20.6 use [1.18 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.18) \
For 1.21 use [1.21 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21) From 1.21 to 1.21.8 use [1.21 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21) \
From 1.21.9 to 1.21.10 use [1.21.9 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.9) \
From 1.21.11 use [1.21.11 configurations](https://github.com/alexcrea/CustomAnvil/tree/master/defaultconfigs/1.21.11)

View file

@ -1,8 +1,13 @@
kotlin.code.style=official kotlin.code.style=official
# Signing # Signing
signing.gnupg.executable=gpg signing.secretKeyRingFile=~/.gnupg/secring.gpg
signing.gnupg.useLegacyGpg=true
signing.gnupg.keyName=2D3280C5
kotlin.daemon.jvmargs=-Xmx8G kotlin.daemon.jvmargs=-Xmx8G
# list of nms
subprojects.reobfnms=v1_17R1,v1_18R1,v1_18R2,v1_19R1,v1_19R2,v1_19R3,v1_20R1,v1_20R2,v1_20R3,v1_20R4,v1_21R1,v1_21R2,v1_21R3,v1_21R4,v1_21R5,v1_21R6,v1_21R7
# list of version for hangar release
paperVersion=1.18-26.2

View file

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

0
gradlew vendored Normal file → Executable file
View file

View file

@ -0,0 +1,17 @@
group = rootProject.group
version = rootProject.version
plugins {
kotlin("jvm") version "2.3.0"
}
repositories {
// ExcellentEnchants
maven(url = "https://repo.nightexpressdev.com/releases")
}
dependencies {
// Excellent Enchant
compileOnly("su.nightexpress.excellentenchants:Core:5.4.3")
compileOnly("su.nightexpress.nightcore:main:2.16.2")
}

View file

@ -0,0 +1,16 @@
package xyz.alexcrea.cuanvil.dependency.plugins;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.api.enchantment.CustomEnchantment;
import su.nightexpress.excellentenchants.enchantment.EnchantRegistry;
import java.util.Set;
public class ExcellentEnchant5_3Registry {
public static @NotNull Set<CustomEnchantment> getRegistered(){
return EnchantRegistry.getRegistered();
}
}

View file

@ -0,0 +1,12 @@
package xyz.alexcrea.cuanvil.dependency.plugins;
import su.nightexpress.excellentenchants.EnchantsAPI;
public class ExcellentEnchant5_4EnchantSettings {
public static int anvilLimit() {
return EnchantsAPI.getEnchantManager().getSettings().getAnvilEnchantsLimit();
}
}

View file

@ -2,7 +2,7 @@ group = rootProject.group
version = rootProject.version version = rootProject.version
plugins { plugins {
kotlin("jvm") version "2.1.0" kotlin("jvm") version "2.3.0"
} }
// Imitate needed class and method to support legacy version of EcoEnchant // Imitate needed class and method to support legacy version of EcoEnchant
@ -10,6 +10,4 @@ dependencies {
// Spigot api // Spigot api
compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT") compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT")
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,16 +1,35 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
group = rootProject.group group = rootProject.group
version = rootProject.version version = rootProject.version
repositories { plugins {
// ProtocoLib id("io.papermc.paperweight.userdev")
maven (url = "https://repo.dmulloy2.net/repository/public/" )
} }
dependencies { dependencies {
// Spigot api // Used for nms
compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT") paperweight.paperDevBundle("1.21.10-R0.1-SNAPSHOT")
// Protocolib // Protocolib
compileOnly("com.comphenix.protocol:ProtocolLib:5.1.0") compileOnly("net.dmulloy2:ProtocolLib:5.4.0")
}
repositories {
maven("https://repo.papermc.io/repository/maven-public/")
}
// Set target version
tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "16"
targetCompatibility = "16"
options.encoding = "UTF-8"
}
kotlin {
compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_16)
}
} }

View file

@ -1,49 +0,0 @@
package xyz.alexcrea.cuanvil.dependency.gui
import org.bukkit.inventory.InventoryView
interface ExternGuiTester {
val wesjdAnvilGuiName: String?
fun getContainerClass(inventory: InventoryView): Class<Any>?
fun testIfGui(inventory: InventoryView): Boolean {
// this mean we are on test
//TODO review why needed knowing previous mitigations should works
if(inventory.javaClass.name.endsWith("AnvilViewMock")) return false
val clazz = getContainerClass(inventory) ?: return false
val clazzName = clazz.name
//TODO maybe instead of testing non default, better to be testing we are default ?
if (expectWesjd(clazzName)) return true
if (expectXenondevUI(clazzName)) return true
if (expectVanePortal(clazzName)) return true
return false
}
fun expectWesjd(name: String): Boolean {
val expectedWesjdGuiPath = "anvilgui.version.$wesjdAnvilGuiName"
return name.contains(expectedWesjdGuiPath)
}
private val XenondevUIPrefix: String
get() = "xyz.xenondevs.inventoryaccess."
private val XenondevUISufix: String
get() = ".AnvilInventoryImpl"
fun expectXenondevUI(name: String): Boolean {
return name.startsWith(XenondevUIPrefix)
&& name.endsWith(XenondevUISufix)
}
fun expectVanePortal(name: String): Boolean {
val expected = "org.oddlama.vane.core.menu.AnvilMenu\$AnvilContainer"
return name == expected
}
}

View file

@ -0,0 +1,102 @@
package xyz.alexcrea.cuanvil.dependency.util
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ItemMeta
// Mostly made for paper, spigot and folia support
@Suppress("DEPRECATION")
object PlatformUtil {
private fun hasClass(className: String): Boolean {
try {
Class.forName(className)
return true
} catch (_: ClassNotFoundException) {
return false
}
}
private fun hasMethod(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>): Boolean {
try {
clazz.getDeclaredMethod(name, *parameterTypes)
return true
} catch (_: NoSuchMethodException) {
return false
}
}
val isPaper = hasClass("com.destroystokyo.paper.PaperConfig") ||
hasClass("io.papermc.paper.configuration.Configuration")
val isFolia = hasClass("io.papermc.paper.threadedregions.RegionizedServer")
private val legacy_mm = LegacyComponentSerializer.legacySection()
// Lore
fun ItemMeta.componentLore(): MutableList<Component> {
val lore: List<Component>?
if(isPaper){
lore = this.lore()
} else {
val legacyLores = this.lore ?: return ArrayList()
lore = ArrayList(legacyLores.size)
for (legacyLore in legacyLores) {
lore.add(legacy_mm.deserialize(legacyLore))
}
}
return lore ?: ArrayList()
}
fun ItemMeta.setComponentLore(lore: List<Component?>) {
if(isPaper){
this.lore(lore)
} else {
val legacyLore = ArrayList<String?>(lore.size)
for (component in lore) {
legacyLore.add(if(component == null) null
else legacy_mm.serialize(component))
}
this.lore = legacyLore
}
}
// Display name
private val useCustomName = hasMethod(ItemStack::class.java, "customName")
fun ItemMeta.componentDisplayName(): Component? {
if(useCustomName){
if(!this.hasCustomName()) return null
return this.customName()
}else if(isPaper){
if(!this.hasDisplayName()) return null
return this.displayName()
} else {
if(!this.hasDisplayName()) return null
val legacy = this.displayName
return legacy_mm.deserialize(legacy)
}
}
fun ItemMeta.setComponentDisplayName(component: Component?) {
if(useCustomName){
this.customName(component)
}else if(isPaper){
this.displayName(component)
} else {
if(component == null){
this.setDisplayName(null)
return
}
val legacy = legacy_mm.serialize(component)
this.setDisplayName(legacy)
}
}
}

View file

@ -0,0 +1,23 @@
package xyz.alexcrea.cuanvil.dialog
import org.bukkit.NamespacedKey
import org.bukkit.entity.HumanEntity
import org.bukkit.event.inventory.PrepareAnvilEvent
interface AnvilRenameDialog {
companion object {
val PCD_KEEP_RENAME_TEXT_KEY = NamespacedKey.fromString("customanvil:last_rename_text")!!
}
fun canSendDialog(): Boolean
fun tryShowDialog(player: HumanEntity, event: PrepareAnvilEvent)
fun closeInventory(player: HumanEntity)
fun currentText(player: HumanEntity): String?
fun isOpenFor(player: HumanEntity): Boolean
}

1
nms/nms-paper/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.lastDeploymentsId

View file

@ -0,0 +1,35 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
group = rootProject.group
version = rootProject.version
plugins {
id("io.papermc.paperweight.userdev")
}
dependencies {
implementation(project(":nms:nms-common"))
// Used for nms
paperweight.paperDevBundle("1.21.7-R0.1-SNAPSHOT")
}
repositories {
maven("https://repo.papermc.io/repository/maven-public/")
}
// Set target version
tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "18"
targetCompatibility = "18"
options.encoding = "UTF-8"
}
kotlin {
compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_18)
}
}

View file

@ -2,6 +2,7 @@ package xyz.alexcrea.cuanvil.dependency.datapack
import io.papermc.paper.datapack.Datapack import io.papermc.paper.datapack.Datapack
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.packs.DataPack
import java.util.* import java.util.*
object DataPackTester { object DataPackTester {
@ -21,6 +22,13 @@ object DataPackTester {
.stream().map { obj: Datapack -> obj.name } .stream().map { obj: Datapack -> obj.name }
.toList() .toList()
} catch (e: NoSuchMethodException) { } catch (e: NoSuchMethodException) {
try {
DataPack::class.java.getDeclaredMethod("getKey")
} catch (e: NoSuchMethodException) {
System.err.println("Could not find compatible datapack manager")
System.err.println("If you are using a datapack that should be compatible with CustomAnvil. It will not get detected...")
return emptyList()
}
return legacyNames return legacyNames
} catch (e: Exception){ } catch (e: Exception){
// Assume cause UnimplementedOperationException on mock server // Assume cause UnimplementedOperationException on mock server

View file

@ -0,0 +1,33 @@
package xyz.alexcrea.cuanvil.dependency.packet.versions
import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket
import net.minecraft.world.entity.player.Abilities
import org.bukkit.craftbukkit.entity.CraftPlayer
import org.bukkit.entity.Player
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager
import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase
class PaperPacketManager : PacketManagerBase(), PacketManager {
override val canSetInstantBuild: Boolean
get() = true
override fun setInstantBuild(player: Player, instantBuild: Boolean) {
val nmsPlayer = (player as CraftPlayer).handle
val playerAbilities = nmsPlayer.abilities
val sendedAbilities: Abilities
if (playerAbilities.instabuild == instantBuild) {
sendedAbilities = playerAbilities
} else {
sendedAbilities = Abilities()
sendedAbilities.invulnerable = playerAbilities.invulnerable
sendedAbilities.flying = playerAbilities.flying
sendedAbilities.mayfly = playerAbilities.mayfly
sendedAbilities.instabuild = instantBuild
sendedAbilities.mayBuild = playerAbilities.mayBuild
sendedAbilities.setFlyingSpeed(playerAbilities.getFlyingSpeed())
sendedAbilities.setWalkingSpeed(playerAbilities.getWalkingSpeed())
}
val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities)
nmsPlayer.connection.send(packet)
}
}

View file

@ -0,0 +1,236 @@
package xyz.alexcrea.cuanvil.dialog
import io.papermc.paper.dialog.Dialog
import io.papermc.paper.registry.data.dialog.ActionButton
import io.papermc.paper.registry.data.dialog.DialogBase
import io.papermc.paper.registry.data.dialog.action.DialogAction
import io.papermc.paper.registry.data.dialog.body.DialogBody
import io.papermc.paper.registry.data.dialog.input.DialogInput
import io.papermc.paper.registry.data.dialog.type.DialogType
import io.papermc.paper.threadedregions.scheduler.ScheduledTask
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.event.ClickCallback
import net.kyori.adventure.text.format.TextColor
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer
import net.minecraft.world.inventory.AnvilMenu
import org.bukkit.craftbukkit.event.CraftEventFactory
import org.bukkit.craftbukkit.inventory.CraftInventoryView
import org.bukkit.craftbukkit.inventory.view.CraftAnvilView
import org.bukkit.entity.HumanEntity
import org.bukkit.event.inventory.PrepareAnvilEvent
import org.bukkit.inventory.InventoryView
import org.bukkit.inventory.ItemStack
import org.bukkit.persistence.PersistentDataType
import org.bukkit.plugin.Plugin
import java.util.*
import java.util.function.BiFunction
import java.util.function.Consumer
import java.util.function.Supplier
@Suppress("UnstableApiUsage")
class AnvilRenameDialogImpl(
val fromFormated: BiFunction<HumanEntity, Component?, String?>,
val keepUserPreviousDialog: Supplier<Boolean>,
val maxLength: Supplier<Int>,
val plugin: Plugin,
) : AnvilRenameDialog {
companion object {
private const val RENAME_TEXT_KEY = "rename"
private const val MAX_WIDTH = 512
private val PLAIN_TEXT_SERIALIZER = PlainTextComponentSerializer.plainText()
// Need to be able to translate it later !
private val USER_FACING_RENAME_TITLE = Component.text("Rename Your Item")
private val USER_FACING_WARNING = Component.text(
"Note that the repair text will appear blank after Confirm\n" +
"But the name will be correctly applied"
)
private val USER_FACING_CONFIRM = Component.text("Confirm").color(TextColor.fromHexString("#40FF40"))
private val USER_FACING_CANCEL = Component.text("Cancel").color(TextColor.fromHexString("#FF4040"))
fun itemDefaultName(item: ItemStack?): String? {
return PLAIN_TEXT_SERIALIZER.serializeOrNull(item?.effectiveName())
}
}
private val lastNames = HashMap<UUID, String>()
private val lastRenames = HashMap<UUID, String>()
private val lastLeftItem = HashMap<UUID, String>()
private val runTaskMap = HashMap<UUID, ScheduledTask>()
// For monetary cost
val hasUiOpen = HashSet<UUID>()
private val containerField = CraftInventoryView::class.java.getDeclaredField("container")
init {
containerField.setAccessible(true)
}
override fun canSendDialog(): Boolean {
return true
}
fun makeDialog(playerID: UUID, initial: String?, callback: Consumer<String?>): Dialog {
val maxLength = this.maxLength.get()
val initialFinal = initial?.take(maxLength)
val baseBuilder = DialogBase.builder(USER_FACING_RENAME_TITLE)
.canCloseWithEscape(true)
.afterAction(DialogBase.DialogAfterAction.CLOSE)
.inputs(
listOf(
DialogInput.text(RENAME_TEXT_KEY, Component.text("Rename text"))
.maxLength(maxLength)
.initial(initialFinal ?: "")
.labelVisible(false)
.width(MAX_WIDTH)
.build(),
),
)
baseBuilder.body(
listOf(
DialogBody.plainMessage(USER_FACING_WARNING, MAX_WIDTH)
)
)
return Dialog.create { builder ->
builder.empty()
.base(baseBuilder.build())
.type(
DialogType.confirmation(
ActionButton.builder(USER_FACING_CONFIRM)
.action(DialogAction.customClick({ response, _ ->
hasUiOpen.remove(playerID)
val text = response.getText(RENAME_TEXT_KEY)!!
callback.accept(text)
}, ClickCallback.Options.builder().build()))
.build(),
ActionButton.builder(USER_FACING_CANCEL)
.action(DialogAction.customClick({ response, _ ->
hasUiOpen.remove(playerID)
}, ClickCallback.Options.builder().build()))
.build(),
)
)
}
}
private fun setResult(player: HumanEntity, view: InventoryView, result: String?) {
val defaultName = itemDefaultName(view.getItem(0))
if (defaultName == result) {
setName(player, view, "", null)
if (defaultName != null) lastNames[player.uniqueId] = defaultName
} else setName(player, view, result, result)
}
private fun setName(player: HumanEntity, view: InventoryView, name: String?, rename: String?) {
val menu = (containerField.get(view) as AnvilMenu)
val isSameName = menu.itemName == name
menu.itemName = rename
if (name == null)
lastNames.remove(player.uniqueId)
else
lastNames[player.uniqueId] = name
if (rename == null)
lastRenames.remove(player.uniqueId)
else
lastRenames[player.uniqueId] = rename
if (!isSameName)
CraftEventFactory.callPrepareResultEvent(menu, 2);
}
private fun nameFromItem(player: HumanEntity, item: ItemStack?): String? {
// Already has text
if (item?.hasItemMeta() != true || !item.itemMeta.hasCustomName())
return PLAIN_TEXT_SERIALIZER.serializeOrNull(item?.effectiveName())
if (keepUserPreviousDialog.get() && item.hasItemMeta()) {
val lastName = item.itemMeta.persistentDataContainer.get(
AnvilRenameDialog.PCD_KEEP_RENAME_TEXT_KEY,
PersistentDataType.STRING
)
if (lastName != null) return lastName
}
return fromFormated.apply(player, item.effectiveName())
}
private fun tryShowDialogScheduled(player: HumanEntity, event: PrepareAnvilEvent) {
val view = event.view
if (view !is CraftAnvilView) return
val renameText = view.renameText
val leftItem = view.getItem(0)
val leftItemStr = leftItem?.toString()
val lastName = lastNames.getOrDefault(player.uniqueId, null)
val lastRename = lastRenames.getOrDefault(player.uniqueId, null)
if (lastLeftItem.getOrDefault(player.uniqueId, null) != leftItemStr) {
if (leftItemStr == null)
lastLeftItem.remove(player.uniqueId)
else lastLeftItem[player.uniqueId] = leftItemStr
setName(player, view, renameText, nameFromItem(player, leftItem))
return
}
if (lastName == renameText || lastRename == renameText)
return
if (renameText?.isBlank() == true || renameText == itemDefaultName(leftItem)) {
setName(player, view, lastName, lastRename)
return
}
val dialog = makeDialog(player.uniqueId, lastRename)
{ result -> setResult(player, view, result) }
player.showDialog(dialog)
hasUiOpen.add(player.uniqueId)
}
// We need to wait for a short time as changing item will change the name BEFORE the item change
// no guaranty both of them came in the same tick too so let's wait 2 tick....
override fun tryShowDialog(player: HumanEntity, event: PrepareAnvilEvent) {
runTaskMap.remove(player.uniqueId)?.cancel()
val task = player.scheduler.runDelayed(
plugin,
{ _ ->
run { tryShowDialogScheduled(player, event) }
},
{},
2
)
if (task == null) return
runTaskMap[player.uniqueId] = task
}
override fun closeInventory(player: HumanEntity) {
lastNames.remove(player.uniqueId)
lastRenames.remove(player.uniqueId)
lastLeftItem.remove(player.uniqueId)
runTaskMap.remove(player.uniqueId)?.cancel()
}
override fun currentText(player: HumanEntity): String? {
return lastNames[player.uniqueId]
}
override fun isOpenFor(player: HumanEntity): Boolean {
return hasUiOpen.contains(player.uniqueId)
}
}

View file

@ -0,0 +1,45 @@
package xyz.alexcrea.cuanvil.util
import io.papermc.paper.threadedregions.scheduler.ScheduledTask
import org.bukkit.entity.HumanEntity
import org.bukkit.inventory.InventoryView
import org.bukkit.plugin.Plugin
import xyz.alexcrea.cuanvil.dialog.AnvilRenameDialog
import java.util.HashMap
import java.util.UUID
object AnvilTitleUtil {
private val runTaskMap = HashMap<UUID, ScheduledTask>()
private fun actualRename(view: InventoryView, name: String, player: HumanEntity, anvilDialog: AnvilRenameDialog) {
runTaskMap.remove(player.uniqueId)
if (view.title == name) return
// We assume rename impl is used
if (anvilDialog.isOpenFor(player)) return
view.title = name
}
// We don't want to rename instantly it is causing issue with rename text
// especially as it can "override" current ui when it is rename ui time but rename ui also need some delay
fun rename(view: InventoryView, name: String, player: HumanEntity, anvilDialog: AnvilRenameDialog, plugin: Plugin) {
runTaskMap.remove(player.uniqueId)?.cancel()
val task = player.scheduler.runDelayed(
plugin,
{ _ ->
run { actualRename(view, name, player, anvilDialog) }
},
{
runTaskMap.remove(player.uniqueId)
},
2
)
if (task == null) return
runTaskMap[player.uniqueId] = task
}
}

View file

@ -19,14 +19,6 @@ repositories {
} }
// As minecraft 1.17 recommended java version is 1.16. we set language version to 1.16
// Configure used version of kotlin and java
java {
disableAutoTargetJvm()
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}
// Set target version // Set target version
tasks.withType<JavaCompile>().configureEach { tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "16" sourceCompatibility = "16"
@ -37,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
kotlin { kotlin {
compilerOptions { compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_16) jvmTarget.set(JvmTarget.JVM_16)
} }
} }

View file

@ -1,16 +0,0 @@
package xyz.alexcrea.cuanvil.dependency.gui.version
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftInventoryView
import org.bukkit.inventory.InventoryView
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
class v1_17R1_ExternGuiTester: ExternGuiTester {
override val wesjdAnvilGuiName = "Wrapper1_17_R1"
override fun getContainerClass(view: InventoryView): Class<Any>? {
if (view !is CraftInventoryView) return null
val container = view.handle
return container.javaClass
}
}

View file

@ -19,14 +19,6 @@ repositories {
} }
// As minecraft 1.18 work with java 1.17 or above. we set language version to 1.17
// Configure used version of kotlin and java
java {
disableAutoTargetJvm()
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}
// Set target version // Set target version
tasks.withType<JavaCompile>().configureEach { tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "17" sourceCompatibility = "17"
@ -37,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
kotlin { kotlin {
compilerOptions { compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_17) jvmTarget.set(JvmTarget.JVM_17)
} }
} }

View file

@ -1,16 +0,0 @@
package xyz.alexcrea.cuanvil.dependency.gui.version
import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftInventoryView
import org.bukkit.inventory.InventoryView
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
class v1_18R1_ExternGuiTester: ExternGuiTester {
override val wesjdAnvilGuiName = "Wrapper1_18_R1"
override fun getContainerClass(view: InventoryView): Class<Any>? {
if (view !is CraftInventoryView) return null
val container = view.handle
return container.javaClass
}
}

View file

@ -19,14 +19,6 @@ repositories {
} }
// As minecraft 1.18 work with java 1.17 or above. we set language version to 1.17
// Configure used version of kotlin and java
java {
disableAutoTargetJvm()
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}
// Set target version // Set target version
tasks.withType<JavaCompile>().configureEach { tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "17" sourceCompatibility = "17"
@ -37,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
kotlin { kotlin {
compilerOptions { compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_17) jvmTarget.set(JvmTarget.JVM_17)
} }
} }

View file

@ -1,16 +0,0 @@
package xyz.alexcrea.cuanvil.dependency.gui.version
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftInventoryView
import org.bukkit.inventory.InventoryView
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
class v1_18R2_ExternGuiTester: ExternGuiTester {
override val wesjdAnvilGuiName = "Wrapper1_18_R2"
override fun getContainerClass(view: InventoryView): Class<Any>? {
if (view !is CraftInventoryView) return null
val container = view.handle
return container.javaClass
}
}

View file

@ -19,14 +19,6 @@ repositories {
} }
// I do not know minecraft 1.19 recommended java version. assumed 17 is good enough
// Configure used version of kotlin and java
java {
disableAutoTargetJvm()
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}
// Set target version // Set target version
tasks.withType<JavaCompile>().configureEach { tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "17" sourceCompatibility = "17"
@ -37,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
kotlin { kotlin {
compilerOptions { compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_17) jvmTarget.set(JvmTarget.JVM_17)
} }
} }

View file

@ -1,16 +0,0 @@
package xyz.alexcrea.cuanvil.dependency.gui.version
import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftInventoryView
import org.bukkit.inventory.InventoryView
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
class v1_19R1_ExternGuiTester: ExternGuiTester {
override val wesjdAnvilGuiName = "Wrapper1_19_R1"
override fun getContainerClass(view: InventoryView): Class<Any>? {
if (view !is CraftInventoryView) return null
val container = view.handle
return container.javaClass
}
}

View file

@ -19,14 +19,6 @@ repositories {
} }
// I do not know minecraft 1.19 recommended java version. assumed 17 is good enough
// Configure used version of kotlin and java
java {
disableAutoTargetJvm()
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}
// Set target version // Set target version
tasks.withType<JavaCompile>().configureEach { tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "17" sourceCompatibility = "17"
@ -37,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
kotlin { kotlin {
compilerOptions { compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_17) jvmTarget.set(JvmTarget.JVM_17)
} }
} }

View file

@ -1,16 +0,0 @@
package xyz.alexcrea.cuanvil.dependency.gui.version
import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftInventoryView
import org.bukkit.inventory.InventoryView
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
class v1_19R2_ExternGuiTester: ExternGuiTester {
override val wesjdAnvilGuiName = "Wrapper1_19_R2"
override fun getContainerClass(view: InventoryView): Class<Any>? {
if (view !is CraftInventoryView) return null
val container = view.handle
return container.javaClass
}
}

View file

@ -19,14 +19,6 @@ repositories {
} }
// I do not know minecraft 1.19 recommended java version. assumed 17 is good enough
// Configure used version of kotlin and java
java {
disableAutoTargetJvm()
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}
// Set target version // Set target version
tasks.withType<JavaCompile>().configureEach { tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "17" sourceCompatibility = "17"
@ -37,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
kotlin { kotlin {
compilerOptions { compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_17) jvmTarget.set(JvmTarget.JVM_17)
} }
} }

View file

@ -1,16 +0,0 @@
package xyz.alexcrea.cuanvil.dependency.gui.version
import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftInventoryView
import org.bukkit.inventory.InventoryView
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
class v1_19R3_ExternGuiTester: ExternGuiTester {
override val wesjdAnvilGuiName = "Wrapper1_19_R3"
override fun getContainerClass(view: InventoryView): Class<Any>? {
if (view !is CraftInventoryView) return null
val container = view.handle
return container.javaClass
}
}

View file

@ -19,25 +19,17 @@ repositories {
} }
// minecraft 1.20 recommended java version is 18. but we assume 17 is good enough as lts
// Configure used version of kotlin and java
java {
disableAutoTargetJvm()
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}
// Set target version // Set target version
tasks.withType<JavaCompile>().configureEach { tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "17" sourceCompatibility = "18"
targetCompatibility = "17" targetCompatibility = "18"
options.encoding = "UTF-8" options.encoding = "UTF-8"
} }
kotlin { kotlin {
compilerOptions { compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_17) jvmTarget.set(JvmTarget.JVM_18)
} }
} }

View file

@ -1,16 +0,0 @@
package xyz.alexcrea.cuanvil.dependency.gui.version
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftInventoryView
import org.bukkit.inventory.InventoryView
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
class v1_20R1_ExternGuiTester: ExternGuiTester {
override val wesjdAnvilGuiName = "Wrapper1_20_R1"
override fun getContainerClass(view: InventoryView): Class<Any>? {
if (view !is CraftInventoryView) return null
val container = view.handle
return container.javaClass
}
}

View file

@ -19,25 +19,17 @@ repositories {
} }
// minecraft 1.20 recommended java version is 18. but we assume 17 is good enough as lts
// Configure used version of kotlin and java
java {
disableAutoTargetJvm()
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}
// Set target version // Set target version
tasks.withType<JavaCompile>().configureEach { tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "17" sourceCompatibility = "18"
targetCompatibility = "17" targetCompatibility = "18"
options.encoding = "UTF-8" options.encoding = "UTF-8"
} }
kotlin { kotlin {
compilerOptions { compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_17) jvmTarget.set(JvmTarget.JVM_18)
} }
} }

View file

@ -1,17 +0,0 @@
package xyz.alexcrea.cuanvil.dependency.gui.version
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftInventoryView
import org.bukkit.inventory.InventoryView
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
import kotlin.jvm.javaClass
class v1_20R2_ExternGuiTester: ExternGuiTester {
override val wesjdAnvilGuiName = "Wrapper1_20_R2"
override fun getContainerClass(view: InventoryView): Class<Any>? {
if (view !is CraftInventoryView) return null
val container = view.handle
return container.javaClass
}
}

View file

@ -19,25 +19,17 @@ repositories {
} }
// minecraft 1.20 recommended java version is 18. but we assume 17 is good enough as lts
// Configure used version of kotlin and java
java {
disableAutoTargetJvm()
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}
// Set target version // Set target version
tasks.withType<JavaCompile>().configureEach { tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "17" sourceCompatibility = "18"
targetCompatibility = "17" targetCompatibility = "18"
options.encoding = "UTF-8" options.encoding = "UTF-8"
} }
kotlin { kotlin {
compilerOptions { compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_17) jvmTarget.set(JvmTarget.JVM_18)
} }
} }

View file

@ -1,17 +0,0 @@
package xyz.alexcrea.cuanvil.dependency.gui.version
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftInventoryView
import org.bukkit.inventory.InventoryView
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
import kotlin.jvm.javaClass
class v1_20R3_ExternGuiTester: ExternGuiTester {
override val wesjdAnvilGuiName = "Wrapper1_20_R3"
override fun getContainerClass(view: InventoryView): Class<Any>? {
if (view !is CraftInventoryView) return null
val container = view.handle
return container.javaClass
}
}

View file

@ -19,18 +19,10 @@ repositories {
} }
// minecraft 1.20 recommended java version is 18. but we assume 17 is good enough as lts
// Configure used version of kotlin and java
java {
disableAutoTargetJvm()
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}
// Set target version // Set target version
tasks.withType<JavaCompile>().configureEach { tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "17" sourceCompatibility = "18"
targetCompatibility = "17" targetCompatibility = "18"
options.encoding = "UTF-8" options.encoding = "UTF-8"
} }
@ -38,6 +30,6 @@ tasks.withType<JavaCompile>().configureEach {
kotlin { kotlin {
compilerOptions { compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0)
jvmTarget.set(JvmTarget.JVM_17) jvmTarget.set(JvmTarget.JVM_18)
} }
} }

View file

@ -1,17 +0,0 @@
package xyz.alexcrea.cuanvil.dependency.gui.version
import org.bukkit.craftbukkit.inventory.CraftInventoryView
import org.bukkit.inventory.InventoryView
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
import kotlin.jvm.javaClass
class v1_20R4_ExternGuiTester: ExternGuiTester {
override val wesjdAnvilGuiName = "Wrapper1_20_R4"
override fun getContainerClass(view: InventoryView): Class<Any>? {
if (view !is CraftInventoryView) return null
val container = view.handle
return container.javaClass
}
}

View file

@ -0,0 +1,18 @@
package xyz.alexcrea.cuanvil.util
import org.bukkit.inventory.meta.Damageable
// I LOVE support of old versions and needing to do modules like that
// That truly is my favorite activity
// TODO clean this one of legacy removal branch
object MaxDamageCheckerUtil {
/**
* @return max damage or int max if not set
*/
fun getMaxDamage(meta: Damageable): Int {
if(!meta.hasMaxDamage()) return Integer.MAX_VALUE
return meta.maxDamage
}
}

View file

@ -19,14 +19,6 @@ repositories {
} }
// minecraft 1.21 java version is 21.
// Configure used version of kotlin and java
java {
disableAutoTargetJvm()
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
}
// Set target version // Set target version
tasks.withType<JavaCompile>().configureEach { tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "21" sourceCompatibility = "21"
@ -37,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
kotlin { kotlin {
compilerOptions { compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_21) jvmTarget.set(JvmTarget.JVM_21)
} }
} }

View file

@ -1,17 +0,0 @@
package xyz.alexcrea.cuanvil.dependency.gui.version
import org.bukkit.craftbukkit.inventory.CraftInventoryView
import org.bukkit.inventory.InventoryView
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
class v1_21R1_ExternGuiTester: ExternGuiTester {
override val wesjdAnvilGuiName = "Wrapper1_21_R1"
override fun getContainerClass(view: InventoryView): Class<Any>? {
if(view !is CraftInventoryView<*, *>) return null
val container = view.handle
return container.javaClass
}
}

View file

@ -19,14 +19,6 @@ repositories {
} }
// minecraft 1.21 java version is 21.
// Configure used version of kotlin and java
java {
disableAutoTargetJvm()
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
}
// Set target version // Set target version
tasks.withType<JavaCompile>().configureEach { tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "21" sourceCompatibility = "21"
@ -37,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
kotlin { kotlin {
compilerOptions { compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_21) jvmTarget.set(JvmTarget.JVM_21)
} }
} }

View file

@ -1,34 +0,0 @@
package xyz.alexcrea.cuanvil.dependency.gui.version
import org.bukkit.craftbukkit.inventory.CraftInventoryView
import org.bukkit.inventory.InventoryView
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
class v1_21R2_ExternGuiTester: ExternGuiTester {
override val wesjdAnvilGuiName = "Wrapper1_21_R2"
var tested = false;
var possible = false;
override fun getContainerClass(view: InventoryView): Class<Any>? {
// In case we are in a test environment
if(!tested) testClassExist()
if(!possible) return null
if(view !is CraftInventoryView<*, *>) return null
val container = view.handle
return container.javaClass
}
fun testClassExist(){
tested = true;
try {
Class.forName("org.bukkit.craftbukkit.inventory.CraftInventoryView")
possible = true
} catch (e: ClassNotFoundException){
possible = false
}
}
}

View file

@ -19,14 +19,6 @@ repositories {
} }
// minecraft 1.21 java version is 21.
// Configure used version of kotlin and java
java {
disableAutoTargetJvm()
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
}
// Set target version // Set target version
tasks.withType<JavaCompile>().configureEach { tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "21" sourceCompatibility = "21"
@ -37,7 +29,7 @@ tasks.withType<JavaCompile>().configureEach {
kotlin { kotlin {
compilerOptions { compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_21) jvmTarget.set(JvmTarget.JVM_21)
} }
} }

View file

@ -1,17 +0,0 @@
package xyz.alexcrea.cuanvil.dependency.gui.version
import org.bukkit.craftbukkit.inventory.CraftInventoryView
import org.bukkit.inventory.InventoryView
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
class v1_21R3_ExternGuiTester: ExternGuiTester {
override val wesjdAnvilGuiName = "Wrapper1_21_R3"
override fun getContainerClass(view: InventoryView): Class<Any>? {
if(view !is CraftInventoryView<*, *>) return null
val container = view.handle
return container.javaClass
}
}

View file

@ -11,21 +11,11 @@ dependencies {
implementation(project(":nms:nms-common")) implementation(project(":nms:nms-common"))
// Used for nms // Used for nms
paperweight.paperDevBundle("1.21.5-no-moonrise-SNAPSHOT") paperweight.paperDevBundle("1.21.5-R0.1-SNAPSHOT")
} }
repositories { repositories {
maven("https://repo.papermc.io/repository/maven-public/") maven("https://repo.papermc.io/repository/maven-public/")
mavenLocal()//TODO remove when paperDevBundle 1.21.5 release
}
// minecraft 1.21 java version is 21.
// Configure used version of kotlin and java
java {
disableAutoTargetJvm()
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
} }
// Set target version // Set target version
@ -38,7 +28,7 @@ tasks.withType<JavaCompile>().configureEach {
kotlin { kotlin {
compilerOptions { compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_21) jvmTarget.set(JvmTarget.JVM_21)
} }
} }

View file

@ -1,34 +0,0 @@
package xyz.alexcrea.cuanvil.dependency.gui.version
import org.bukkit.craftbukkit.inventory.CraftInventoryView
import org.bukkit.inventory.InventoryView
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
class v1_21R4_ExternGuiTester: ExternGuiTester {
override val wesjdAnvilGuiName = "Wrapper1_21_R4"
var tested = false;
var possible = false;
override fun getContainerClass(view: InventoryView): Class<Any>? {
// In case we are in a test environment
if(!tested) testClassExist()
if(!possible) return null
if(view !is CraftInventoryView<*, *>) return null
val container = view.handle
return container.javaClass
}
fun testClassExist(){
tested = true;
try {
Class.forName("org.bukkit.craftbukkit.inventory.CraftInventoryView")
possible = true
} catch (e: ClassNotFoundException){
possible = false
}
}
}

1
nms/v1_21R5/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.lastDeploymentsId

View file

@ -0,0 +1,34 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
group = rootProject.group
version = rootProject.version
plugins {
id("io.papermc.paperweight.userdev")
}
dependencies {
implementation(project(":nms:nms-common"))
// Used for nms
paperweight.paperDevBundle("1.21.6-R0.1-SNAPSHOT")
}
repositories {
maven("https://repo.papermc.io/repository/maven-public/")
}
// Set target version
tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "21"
targetCompatibility = "21"
options.encoding = "UTF-8"
}
kotlin {
compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_21)
}
}

View file

@ -0,0 +1,33 @@
package xyz.alexcrea.cuanvil.dependency.packet.versions
import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket
import net.minecraft.world.entity.player.Abilities
import org.bukkit.craftbukkit.entity.CraftPlayer
import org.bukkit.entity.Player
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager
import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase
class V1_21R5_PacketManager : PacketManagerBase(), PacketManager {
override val canSetInstantBuild: Boolean
get() = true
override fun setInstantBuild(player: Player, instantBuild: Boolean) {
val nmsPlayer = (player as CraftPlayer).handle
val playerAbilities = nmsPlayer.abilities
val sendedAbilities: Abilities
if (playerAbilities.instabuild == instantBuild) {
sendedAbilities = playerAbilities
} else {
sendedAbilities = Abilities()
sendedAbilities.invulnerable = playerAbilities.invulnerable
sendedAbilities.flying = playerAbilities.flying
sendedAbilities.mayfly = playerAbilities.mayfly
sendedAbilities.instabuild = instantBuild
sendedAbilities.mayBuild = playerAbilities.mayBuild
sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed
sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed
}
val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities)
nmsPlayer.connection.send(packet)
}
}

1
nms/v1_21R6/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.lastDeploymentsId

View file

@ -0,0 +1,34 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
group = rootProject.group
version = rootProject.version
plugins {
id("io.papermc.paperweight.userdev")
}
dependencies {
implementation(project(":nms:nms-common"))
// Used for nms
paperweight.paperDevBundle("1.21.10-R0.1-SNAPSHOT")
}
repositories {
maven("https://repo.papermc.io/repository/maven-public/")
}
// Set target version
tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "21"
targetCompatibility = "21"
options.encoding = "UTF-8"
}
kotlin {
compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_21)
}
}

View file

@ -0,0 +1,33 @@
package xyz.alexcrea.cuanvil.dependency.packet.versions
import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket
import net.minecraft.world.entity.player.Abilities
import org.bukkit.craftbukkit.entity.CraftPlayer
import org.bukkit.entity.Player
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager
import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase
class V1_21R6_PacketManager : PacketManagerBase(), PacketManager {
override val canSetInstantBuild: Boolean
get() = true
override fun setInstantBuild(player: Player, instantBuild: Boolean) {
val nmsPlayer = (player as CraftPlayer).handle
val playerAbilities = nmsPlayer.abilities
val sendedAbilities: Abilities
if (playerAbilities.instabuild == instantBuild) {
sendedAbilities = playerAbilities
} else {
sendedAbilities = Abilities()
sendedAbilities.invulnerable = playerAbilities.invulnerable
sendedAbilities.flying = playerAbilities.flying
sendedAbilities.mayfly = playerAbilities.mayfly
sendedAbilities.instabuild = instantBuild
sendedAbilities.mayBuild = playerAbilities.mayBuild
sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed
sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed
}
val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities)
nmsPlayer.connection.send(packet)
}
}

1
nms/v1_21R7/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.lastDeploymentsId

View file

@ -0,0 +1,34 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
group = rootProject.group
version = rootProject.version
plugins {
id("io.papermc.paperweight.userdev")
}
dependencies {
implementation(project(":nms:nms-common"))
// Used for nms
paperweight.paperDevBundle("1.21.11-R0.1-SNAPSHOT")
}
repositories {
maven("https://repo.papermc.io/repository/maven-public/")
}
// Set target version
tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = "21"
targetCompatibility = "21"
options.encoding = "UTF-8"
}
kotlin {
compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2)
jvmTarget.set(JvmTarget.JVM_21)
}
}

View file

@ -0,0 +1,33 @@
package xyz.alexcrea.cuanvil.dependency.packet.versions
import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket
import net.minecraft.world.entity.player.Abilities
import org.bukkit.craftbukkit.entity.CraftPlayer
import org.bukkit.entity.Player
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager
import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerBase
class V1_21R7_PacketManager : PacketManagerBase(), PacketManager {
override val canSetInstantBuild: Boolean
get() = true
override fun setInstantBuild(player: Player, instantBuild: Boolean) {
val nmsPlayer = (player as CraftPlayer).handle
val playerAbilities = nmsPlayer.abilities
val sendedAbilities: Abilities
if (playerAbilities.instabuild == instantBuild) {
sendedAbilities = playerAbilities
} else {
sendedAbilities = Abilities()
sendedAbilities.invulnerable = playerAbilities.invulnerable
sendedAbilities.flying = playerAbilities.flying
sendedAbilities.mayfly = playerAbilities.mayfly
sendedAbilities.instabuild = instantBuild
sendedAbilities.mayBuild = playerAbilities.mayBuild
sendedAbilities.flyingSpeed = playerAbilities.flyingSpeed
sendedAbilities.walkingSpeed = playerAbilities.walkingSpeed
}
val packet = ClientboundPlayerAbilitiesPacket(sendedAbilities)
nmsPlayer.connection.send(packet)
}
}

View file

@ -3,34 +3,20 @@ rootProject.name = "CustomAnvil"
// NMS subproject // NMS subproject
include("nms:nms-common") include("nms:nms-common")
findProject(":nms:nms-common")?.name = "nms-common" findProject(":nms:nms-common")?.name = "nms-common"
include("nms:v1_17R1") include("nms:nms-paper")
findProject(":nms:v1_17R1")?.name = "v1_17R1" findProject(":nms:nms-paper")?.name = "nms-paper"
include("nms:v1_18R1")
findProject(":nms:v1_18R1")?.name = "v1_18R1"
include("nms:v1_18R2")
findProject(":nms:v1_18R2")?.name = "v1_18R2"
include("nms:v1_19R1")
findProject(":nms:v1_19R1")?.name = "v1_19R1"
include("nms:v1_19R2")
findProject(":nms:v1_19R2")?.name = "v1_19R2"
include("nms:v1_19R3")
findProject(":nms:v1_19R3")?.name = "v1_19R3"
include("nms:v1_20R1")
findProject(":nms:v1_20R1")?.name = "v1_20R1"
include("nms:v1_20R2")
findProject(":nms:v1_20R2")?.name = "v1_20R2"
include("nms:v1_20R3")
findProject(":nms:v1_20R3")?.name = "v1_20R3"
include("nms:v1_20R4")
findProject(":nms:v1_20R4")?.name = "v1_20R4"
include("nms:v1_21R1")
findProject(":nms:v1_21R1")?.name = "v1_21R1"
include("nms:v1_21R2")
findProject(":nms:v1_21R2")?.name = "v1_21R2"
include("nms:v1_21R3")
findProject(":nms:v1_21R3")?.name = "v1_21R3"
include("nms:v1_21R4")
findProject(":nms:v1_21R4")?.name = "v1_21R4"
val reobfNMS = providers.gradleProperty("subprojects.reobfnms")
.get().split(",")
for (nmsPart in reobfNMS) {
include("nms:$nmsPart")
findProject(":nms:$nmsPart")?.name = nmsPart
}
// compatibility subprojects
include(":impl:LegacyEcoEnchant") include(":impl:LegacyEcoEnchant")
findProject(":impl:LegacyEcoEnchant")?.name = "LegacyEcoEnchant" findProject(":impl:LegacyEcoEnchant")?.name = "LegacyEcoEnchant"
include("impl:ExcellentEnchant5_4")
findProject(":impl:ExcellentEnchant5_4")?.name = "ExcellentEnchant5_4"

View file

@ -14,7 +14,10 @@ public class AnvilRecipeBuilder {
private @NotNull String name; private @NotNull String name;
private boolean exactCount; private boolean exactCount;
private int xpCostPerCraft; private int levelCostPerCraft;
private int linearXpCostPerCraft;
private boolean removeExactLinearXp;
private @Nullable ItemStack leftItem; private @Nullable ItemStack leftItem;
private @Nullable ItemStack rightItem; private @Nullable ItemStack rightItem;
@ -23,7 +26,7 @@ public class AnvilRecipeBuilder {
/** /**
* Instantiates a new Anvil recipe builder. * Instantiates a new Anvil recipe builder.
* exact count default to true. * exact count default to true.
* xp cost per craft default to 1. * xp level and linear cost per craft default to 0.
* *
* @param name The recipe name * @param name The recipe name
*/ */
@ -31,7 +34,9 @@ public class AnvilRecipeBuilder {
this.name = name; this.name = name;
this.exactCount = true; this.exactCount = true;
this.xpCostPerCraft = 1; this.levelCostPerCraft = 0;
this.linearXpCostPerCraft = 0;
this.removeExactLinearXp = false;
this.leftItem = null; this.leftItem = null;
this.rightItem = null; this.rightItem = null;
@ -60,7 +65,7 @@ public class AnvilRecipeBuilder {
} }
/** /**
* Get if the recipe is exact count. * Get if the recipe is exact count. (default 0)
* <p> * <p>
* Exact count mean the recipe can only be crafted 1 by 1. * Exact count mean the recipe can only be crafted 1 by 1.
* If set to false, then it will craft as much as possible in 1 go and will keep unused material onto the anvil inventory. * If set to false, then it will craft as much as possible in 1 go and will keep unused material onto the anvil inventory.
@ -86,12 +91,14 @@ public class AnvilRecipeBuilder {
} }
/** /**
* Get the xp level cost per craft. * Get the xp level cost per craft. (default 0)
* *
* @return The xp level cost per craft * @return The xp level cost per craft
* @deprecated use {@link #getLevelCostPerCraft() getLevelCostPerCraft} instead
*/ */
@Deprecated(since = "1.13.0")
public int getXpCostPerCraft() { public int getXpCostPerCraft() {
return xpCostPerCraft; return getLevelCostPerCraft();
} }
/** /**
@ -99,9 +106,78 @@ public class AnvilRecipeBuilder {
* *
* @param xpCostPerCraft The xp level cost per craft * @param xpCostPerCraft The xp level cost per craft
* @return This recipe builder instance. * @return This recipe builder instance.
* @deprecated use {@link #setLevelCostPerCraft(int) setLevelCostPerCraft} instead
*/ */
@Deprecated(since = "1.13.0")
public AnvilRecipeBuilder setXpCostPerCraft(int xpCostPerCraft) { public AnvilRecipeBuilder setXpCostPerCraft(int xpCostPerCraft) {
this.xpCostPerCraft = xpCostPerCraft; return setLevelCostPerCraft(xpCostPerCraft);
}
/**
* Get the xp level cost per craft. (default 0)
*
* @return The xp level cost per craft
*/
public int getLevelCostPerCraft() {
return levelCostPerCraft;
}
/**
* Sets the xp level cost per craft.
*
* @param levelCostPerCraft The xp level cost per craft
* @return This recipe builder instance.
*/
public AnvilRecipeBuilder setLevelCostPerCraft(int levelCostPerCraft) {
this.levelCostPerCraft = levelCostPerCraft;
return this;
}
/**
* Get the linear xp cost (not xp level cost) per craft.
*
* @return The xp level cost per craft
*/
public int getLinearXpCostPerCraft() {
return linearXpCostPerCraft;
}
/**
* Sets the linear xp cost (not xp level cost) per craft.
*
* @param linearXpCostPerCraft The linear xp cost per craft
* @return This recipe builder instance.
*/
public AnvilRecipeBuilder setLinearXpCostPerCraft(int linearXpCostPerCraft) {
this.linearXpCostPerCraft = linearXpCostPerCraft;
return this;
}
/**
* Get if the linear xp should get removed by an exact amount.
* <p>
* If false (default) level cost will be the level that would be reached by a player with this amount of xp.
* If true will require the level that has at least the specified level of xp then on click remove only the necessary xp
* <p>
* linear xp cost are applied after level cost
* @return if we should remove the exact amount of linear xp
*/
public boolean isRemoveExactLinearXp() {
return removeExactLinearXp;
}
/**
* Set if the linear xp should get removed by an exact amount.
* <p>
* If false (default) level cost will be the level that would be reached by a player with this amount of xp.
* If true will require the level that has at least the specified level of xp then on click remove only the necessary xp
* <p>
* linear xp cost are applied after level cost
* @param removeExactLinearXp if we should remove the exact amount of linear xp
* @return This recipe builder instance.
*/
public AnvilRecipeBuilder setRemoveExactLinearXp(boolean removeExactLinearXp) {
this.removeExactLinearXp = removeExactLinearXp;
return this; return this;
} }
@ -187,7 +263,9 @@ public class AnvilRecipeBuilder {
return new AnvilCustomRecipe( return new AnvilCustomRecipe(
this.name, this.name,
this.exactCount, this.exactCount,
this.xpCostPerCraft, this.levelCostPerCraft,
this.linearXpCostPerCraft,
this.removeExactLinearXp,
this.leftItem, this.rightItem, this.resultItem this.leftItem, this.rightItem, this.resultItem
); );
} }

View file

@ -13,6 +13,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
//TODO add conflict after level
/** /**
* A Builder for material conflict. * A Builder for material conflict.
*/ */

View file

@ -1,6 +1,7 @@
package xyz.alexcrea.cuanvil.api; package xyz.alexcrea.cuanvil.api;
import io.delilaheve.CustomAnvil; import io.delilaheve.CustomAnvil;
import io.delilaheve.util.ConfigOptions;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
@ -180,13 +181,13 @@ public class EnchantmentApi {
private static boolean tryWriteDefaultConfig(FileConfiguration defaultConfig, CAEnchantment enchantment, boolean override) { private static boolean tryWriteDefaultConfig(FileConfiguration defaultConfig, CAEnchantment enchantment, boolean override) {
boolean hasChange = false; boolean hasChange = false;
String levelPath = "enchant_limits." + enchantment.getKey(); String levelPath = ConfigOptions.ENCHANT_LIMIT_ROOT + "." + enchantment.getKey();
if(override || !defaultConfig.isSet(levelPath)){ if(override || !defaultConfig.isSet(levelPath)){
defaultConfig.set(levelPath, enchantment.defaultMaxLevel()); defaultConfig.set(levelPath, enchantment.defaultMaxLevel());
hasChange = true; hasChange = true;
} }
String basePath = "enchant_values." + enchantment.getKey(); String basePath = ConfigOptions.ENCHANT_VALUES_ROOT + "." + enchantment.getKey();
EnchantmentRarity rarity = enchantment.defaultRarity(); EnchantmentRarity rarity = enchantment.defaultRarity();
String itemPath = basePath + ".item"; String itemPath = basePath + ".item";

View file

@ -3,6 +3,7 @@ package xyz.alexcrea.cuanvil.api;
import io.delilaheve.CustomAnvil; import io.delilaheve.CustomAnvil;
import io.delilaheve.util.ConfigOptions; import io.delilaheve.util.ConfigOptions;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -123,7 +124,7 @@ public class MaterialGroupApi {
FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig(); FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig();
String basePath = group.getName() + "."; String basePath = group.getName() + ".";
Set<Material> materialSet = group.getNonGroupInheritedMaterials(); Set<NamespacedKey> materialSet = group.getNonGroupInheritedMaterials();
Set<AbstractMaterialGroup> groupSet = group.getGroups(); Set<AbstractMaterialGroup> groupSet = group.getGroups();
boolean empty = true; boolean empty = true;
@ -153,7 +154,7 @@ public class MaterialGroupApi {
FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig(); FileConfiguration config = ConfigHolder.ITEM_GROUP_HOLDER.getConfig();
String basePath = group.getName() + "."; String basePath = group.getName() + ".";
EnumSet<Material> materials = group.getMaterials(); Set<NamespacedKey> materials = group.getMaterials();
if (materials.isEmpty()) return false; if (materials.isEmpty()) return false;
@ -163,8 +164,8 @@ public class MaterialGroupApi {
return true; return true;
} }
public static List<String> materialSetToStringList(@NotNull Set<Material> materials) { public static List<String> materialSetToStringList(@NotNull Set<NamespacedKey> materials) {
return materials.stream().map(material -> material.getKey().getKey().toLowerCase()).toList(); return materials.stream().map(NamespacedKey::toString).toList();
} }
public static List<String> materialGroupSetToStringList(@NotNull Set<AbstractMaterialGroup> groups) { public static List<String> materialGroupSetToStringList(@NotNull Set<AbstractMaterialGroup> groups) {

View file

@ -3,6 +3,23 @@ package xyz.alexcrea.cuanvil.api.event;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
/**
* Called when the configuration of CustomAnvil is ready.
* It is called either on the plugin startup or on the plugin config reload.
* <p>
* If you want to listen to the first trigger of this event (first configuration load. aka plugin load)
* you will need to register the listener on your plugin onEnable or earlier
* <p>
* This event indicate that can start to register your recipes, item groups and conflicts.
* The vanilla and custom enchantments should already have been provided to CustomAnvil.
* Configuration can be changed any time after this event is triggered but never before.
* <p>
* use {@link xyz.alexcrea.cuanvil.api.ConflictAPI ConflictApi},
* {@link xyz.alexcrea.cuanvil.gui.config.global.CustomRecipeConfigGui CustomRecipeConfigGui},
* {@link xyz.alexcrea.cuanvil.api.MaterialGroupApi MaterialGroupApi}
* and {@link xyz.alexcrea.cuanvil.api.UnitRepairApi UnitRepairApi}
* to add/remove/edit configurations
*/
public class CAConfigReadyEvent extends Event { public class CAConfigReadyEvent extends Event {
private static final HandlerList HANDLERS = new HandlerList(); private static final HandlerList HANDLERS = new HandlerList();

View file

@ -3,6 +3,17 @@ package xyz.alexcrea.cuanvil.api.event;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
/**
* Called when custom anvil is ready to accept registration on custom enchantment.
* <p>
* If you want to listen this event
* you will need to register the listener on your plugin onEnable or earlier
* <p>
* Custom enchantments may be registered later but may cause issue if registered too later
* (after configuration loading phase. see {@link CAConfigReadyEvent})
* <p>
* use {@link xyz.alexcrea.cuanvil.api.EnchantmentApi EnchantmentApi} to register and unregister your custom enchantments
*/
public class CAEnchantRegistryReadyEvent extends Event { public class CAEnchantRegistryReadyEvent extends Event {
private static final HandlerList HANDLERS = new HandlerList(); private static final HandlerList HANDLERS = new HandlerList();

View file

@ -0,0 +1,63 @@
package xyz.alexcrea.cuanvil.api.event.listener;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull;
/**
* Called before custom anvil process the click on the result on the anvil inventory.
* <p>
* This event is called after checking that the inventory is an anvil inventory and that the click is on the result slot
* but before checking if the player has the custom anvil affected permission.
* <p>
* This event being cancelled will make CustomAnvil abort the click on result process.
* <p>
* Most of the time you would likely need {@link CAPreAnvilBypassEvent} or {@link CAEarlyPreAnvilBypassEvent}
* for this event to be useful.
* <p>
* There is also {@link CATreatAnvilResult2Event} that may be better for some use case.
*/
public class CAClickResultBypassEvent extends Event implements Cancellable {
private static final HandlerList HANDLERS = new HandlerList();
public static HandlerList getHandlerList() {
return HANDLERS;
}
@Override
public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
private boolean cancelled = false;
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
@NotNull
private final InventoryClickEvent event;
/**
* Get the bukkit inventory click event causing to this event
*
* @return The click event causing to this event
*/
@NotNull
public InventoryClickEvent getEvent() {
return event;
}
public CAClickResultBypassEvent(@NotNull InventoryClickEvent event) {
this.event = event;
}
}

View file

@ -0,0 +1,63 @@
package xyz.alexcrea.cuanvil.api.event.listener;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.inventory.PrepareAnvilEvent;
import org.jetbrains.annotations.NotNull;
/**
* Called before custom anvil process the prepare anvil event.
* <p>
* This event will always get called when CustomAnvil need to handle
* <p>
* This event being cancelled will make CustomAnvil abort the anvil process.
* <p>
* You should also use {@link CAClickResultBypassEvent} if you want to use this event for something useful.
* <p>
* It is also recommended that you read about {@link CAPreAnvilBypassEvent} and {@link CATreatAnvilResult2Event}
* as your use case may be more prone to use theses.
*/
public class CAEarlyPreAnvilBypassEvent extends Event implements Cancellable {
private static final HandlerList HANDLERS = new HandlerList();
public static HandlerList getHandlerList() {
return HANDLERS;
}
@Override
public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
private boolean cancelled = false;
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
@NotNull
private final PrepareAnvilEvent event;
/**
* Get the bukkit pre anvil event causing this event
*
* @return The pre anvil event causing to this event
*/
@NotNull
public PrepareAnvilEvent getEvent() {
return event;
}
public CAEarlyPreAnvilBypassEvent(@NotNull PrepareAnvilEvent event) {
this.event = event;
}
}

View file

@ -0,0 +1,66 @@
package xyz.alexcrea.cuanvil.api.event.listener;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.inventory.PrepareAnvilEvent;
import org.jetbrains.annotations.NotNull;
/**
* Called before custom anvil process the prepare anvil event.
* <p>
* This event is called after {@link CAEarlyPreAnvilBypassEvent},
* after checking that there is at least an item on the left slot
* and after checking if any of the 2 item is marked as immutable
* but before checking if the player has the custom anvil affected permission.
* <p>
* This event being cancelled will make CustomAnvil abort the anvil process.
* <p>
* You should also use {@link CAClickResultBypassEvent} if you want to use this event for something useful.
* <p>
* It is also recommended that you read about {@link CAEarlyPreAnvilBypassEvent} and {@link CATreatAnvilResult2Event}
* as your use case may be more prone to use theses.
*/
public class CAPreAnvilBypassEvent extends Event implements Cancellable {
private static final HandlerList HANDLERS = new HandlerList();
public static HandlerList getHandlerList() {
return HANDLERS;
}
@Override
public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
private boolean cancelled = false;
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
@NotNull
private final PrepareAnvilEvent event;
/**
* Get the bukkit pre anvil event causing this event
*
* @return The pre anvil event causing this event
*/
@NotNull
public PrepareAnvilEvent getEvent() {
return event;
}
public CAPreAnvilBypassEvent(@NotNull PrepareAnvilEvent event) {
this.event = event;
}
}

View file

@ -0,0 +1,196 @@
package xyz.alexcrea.cuanvil.api.event.listener;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.anvil.AnvilCost;
import xyz.alexcrea.cuanvil.anvil.AnvilUseType;
/**
* Called after custom anvil processed the click on the result on the anvil inventory.
* This event should be used to modify the result of an anvil use.
* <p>
* You may also want to check {@link CAClickResultBypassEvent},
* {@link CAPreAnvilBypassEvent}
* and {@link CAEarlyPreAnvilBypassEvent} for your use case
* <p>
* A null result will cancel this event
*/
@SuppressWarnings("unused")
public class CATreatAnvilResult2Event extends Event {
private static final HandlerList HANDLERS = new HandlerList();
public static HandlerList getHandlerList() {
return HANDLERS;
}
@Override
public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
@NotNull
private final InventoryView view;
private final AnvilUseType useType;
@Nullable
private final ItemStack left;
@Nullable
private final ItemStack right;
@Nullable
private ItemStack result;
private final AnvilCost cost;
@ApiStatus.Internal
public CATreatAnvilResult2Event(
@NotNull InventoryView view,
Inventory inv,
AnvilUseType useType,
@Nullable ItemStack result,
AnvilCost cost) {
this.view = view;
this.useType = useType;
this.left = inv.getItem(0); // TODO use view here
this.right = inv.getItem(1);
this.result = result;
this.cost = cost;
}
/**
* Get the bukkit inventory view.
* <p>
* Temporarily marked as internal as it will get changed to anvil view on legacy removal
* so signature will change
*
* @return The inventory view of this event.
*/
@ApiStatus.Internal
public @NotNull InventoryView getView() {
return view;
}
/**
* Get the type of use source of the result.
*
* @return The craft use type.
*/
public AnvilUseType getUseType() {
return useType;
}
/**
* Get the left item of the anvil use
*
* @return the left item
*/
public @Nullable ItemStack getLeftItem() {
return left;
}
/**
* Get the right item of the anvil use
*
* @return the right item
*/
public @Nullable ItemStack getRightItem() {
return right;
}
/**
* Get the current result
* <p>
* note that it will not be null unless another listener previously set it to null.
*
* @return The current result.
*/
public @Nullable ItemStack getResult() {
return result;
}
/**
* Set the current result
* <p>
* note that a null result will cancel this anvil use.
*
* @param result The new result
*/
public void setResult(@Nullable ItemStack result) {
this.result = result;
}
/**
* Get the level cost displayed on the anvil.
* <h3>Important note:</h3>
* the final price are re calculated on click for the following use case:
* <ul>
* <li>Custom craft</li>
* <li>Unit repair</li>
* <li>Lore edit</li>
* </ul>
* This value will be used as final price for:
* <li>Item merge</li>
* <li>Item rename</li>
* </ul>
*
* @return The current cost.
* @deprecated use #{@link #getCost()} instead
*/
@Deprecated(forRemoval = true, since = "1.17.0")
public int getLevelCost() {
return cost.asXpCost();
}
/**
* Set the level cost displayed on the anvil.
* <h3>Important note:</h3>
* the final price are re calculated on click for the following use case:
* <ul>
* <li>Custom craft</li>
* <li>Unit repair</li>
* <li>Lore edit</li>
* </ul>
* This value will be used as final price for:
* <li>Item merge</li>
* <li>Item rename</li>
* </ul>
*
* @param levelCost The new cost.
* @deprecated use #{@link #getCost()} and set value on this instead
*/
@Deprecated(forRemoval = true, since = "1.17.0")
public void setLevelCost(int levelCost) {
cost.setGeneric(levelCost - cost.getGeneric() - cost.asXpCost());
}
/**
* Allow access to the current cost of the event
* Note that modifying this object will change the event resulting cost
*
* <h3>Important note:</h3>
* the final price are re calculated on click for the following use case:
* <ul>
* <li>Custom craft</li>
* <li>Unit repair</li>
* <li>Lore edit</li>
* </ul>
* This value will be used as final price for:
* <li>Item merge</li>
* <li>Item rename</li>
*
* @return the current anvil cost
*/
public AnvilCost getCost() {
return cost;
}
}

View file

@ -0,0 +1,162 @@
package xyz.alexcrea.cuanvil.api.event.listener;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.inventory.PrepareAnvilEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.anvil.AnvilCost;
import xyz.alexcrea.cuanvil.anvil.AnvilUseType;
/**
* Called after custom anvil processed the click on the result on the anvil inventory.
* This event should be used to modify the result of an anvil use.
* <p>
* You may also want to check {@link CAClickResultBypassEvent},
* {@link CAPreAnvilBypassEvent}
* and {@link CAEarlyPreAnvilBypassEvent} for your use case
* <p>
* A null result will cancel this pre anvil event
*
* @deprecated Prepare anvil Event cannot be provided as it can be called on result and therefore not have prepared anvil event
* use {@link CATreatAnvilResult2Event} instead
*/
@SuppressWarnings("unused")
@Deprecated(forRemoval = true, since = "1.17.0")
public class CATreatAnvilResultEvent extends Event {
private static final HandlerList HANDLERS = new HandlerList();
public static HandlerList getHandlerList() {
return HANDLERS;
}
@Override
public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
@NotNull
private final PrepareAnvilEvent event;
private final AnvilUseType useType;
@Nullable
private ItemStack result;
private final AnvilCost cost;
public CATreatAnvilResultEvent(@NotNull PrepareAnvilEvent event, AnvilUseType useType, @Nullable ItemStack result, AnvilCost cost) {
this.event = event;
this.useType = useType;
this.result = result;
this.cost = cost;
}
/**
* Get the bukkit inventory click event causing to this event.
*
* @return The click event causing to this event.
*/
public @NotNull PrepareAnvilEvent getEvent() {
return event;
}
/**
* Get the type of use source of the result.
*
* @return The craft use type.
*/
public AnvilUseType getUseType() {
return useType;
}
/**
* Get the current result
* <p>
* note that it will not be null unless another listener previously set it to null.
*
* @return The current result.
*/
public @Nullable ItemStack getResult() {
return result;
}
/**
* Set the current result
* <p>
* note that a null result will cancel this anvil use.
*
* @param result The new result
*/
public void setResult(@Nullable ItemStack result) {
this.result = result;
}
/**
* Get the level cost displayed on the anvil.
* <h3>Important note:</h3>
* the final price are re calculated on click for the following use case:
* <ul>
* <li>Custom craft</li>
* <li>Unit repair</li>
* <li>Lore edit</li>
* </ul>
* This value will be used as final price for:
* <li>Item merge</li>
* <li>Item rename</li>
* </ul>
*
* @return The current cost.
* @deprecated use #{@link #getCost()} instead
*/
@Deprecated(forRemoval = true, since = "1.17.0")
public int getLevelCost() {
return cost.asXpCost();
}
/**
* Set the level cost displayed on the anvil.
* <h3>Important note:</h3>
* the final price are re calculated on click for the following use case:
* <ul>
* <li>Custom craft</li>
* <li>Unit repair</li>
* <li>Lore edit</li>
* </ul>
* This value will be used as final price for:
* <li>Item merge</li>
* <li>Item rename</li>
* </ul>
*
* @param levelCost The new cost.
* @deprecated use #{@link #getCost()} and set value on this instead
*/
@Deprecated(forRemoval = true, since = "1.17.0")
public void setLevelCost(int levelCost) {
cost.setGeneric(levelCost - cost.getGeneric() - cost.asXpCost());
}
/**
* Allow access to the current cost of the event
* Note that modifying this object will change the event resulting cost
*
* <h3>Important note:</h3>
* the final price are re calculated on click for the following use case:
* <ul>
* <li>Custom craft</li>
* <li>Unit repair</li>
* <li>Lore edit</li>
* </ul>
* This value will be used as final price for:
* <li>Item merge</li>
* <li>Item rename</li>
*
* @return the current anvil cost
*/
public AnvilCost getCost() {
return cost;
}
}

View file

@ -9,6 +9,7 @@ import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.group.EnchantConflictManager; import xyz.alexcrea.cuanvil.group.EnchantConflictManager;
import xyz.alexcrea.cuanvil.group.ItemGroupManager; import xyz.alexcrea.cuanvil.group.ItemGroupManager;
import xyz.alexcrea.cuanvil.recipe.CustomAnvilRecipeManager; import xyz.alexcrea.cuanvil.recipe.CustomAnvilRecipeManager;
import xyz.alexcrea.cuanvil.util.MetricsUtil;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -145,6 +146,7 @@ public abstract class ConfigHolder {
sufficientSuccess = true; sufficientSuccess = true;
} catch (IOException e) { } catch (IOException e) {
CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not copy backup saving config " + base.getName(), e); CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not copy backup saving config " + base.getName(), e);
MetricsUtil.INSTANCE.trackError(e);
} }
} }
// save last backup // save last backup
@ -275,6 +277,7 @@ public abstract class ConfigHolder {
this.deletedConfigFile.createNewFile(); this.deletedConfigFile.createNewFile();
} catch (IOException e) { } catch (IOException e) {
CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not create " + this.deletedConfigFile.getPath(), e); CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not create " + this.deletedConfigFile.getPath(), e);
MetricsUtil.INSTANCE.trackError(e);
} }
loadDeletedListFile(false); loadDeletedListFile(false);
@ -312,6 +315,7 @@ public abstract class ConfigHolder {
this.deletedListConfig.save(this.deletedConfigFile); this.deletedListConfig.save(this.deletedConfigFile);
} catch (IOException e) { } catch (IOException e) {
CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not save " + this.deletedConfigFile.getPath(), e); CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not save " + this.deletedConfigFile.getPath(), e);
MetricsUtil.INSTANCE.trackError(e);
return false; return false;
} }

View file

@ -2,7 +2,7 @@ package xyz.alexcrea.cuanvil.config;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.util.AnvilUseType; import xyz.alexcrea.cuanvil.anvil.AnvilUseType;
import java.util.EnumMap; import java.util.EnumMap;

View file

@ -1,6 +1,7 @@
package xyz.alexcrea.cuanvil.enchant; package xyz.alexcrea.cuanvil.enchant;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -11,24 +12,23 @@ public interface AdditionalTestEnchantment {
/** /**
* Test if the provided enchantments can be compatible with this enchantment. only non-Custom Anvil conflict. * Test if the provided enchantments can be compatible with this enchantment. only non-Custom Anvil conflict.
* @param enchantments Immutable map of validated enchantments for the item. * @param enchantments Immutable map of validated enchantments for the item.
* @param itemMat Material of the tested item. * @param itemType Material namespaced key of the tested item.
* @return If there is a conflict with the enchantments. * @return If there is a conflict with the enchantments.
*/ */
boolean isEnchantConflict( boolean isEnchantConflict(
@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Map<CAEnchantment, Integer> enchantments,
@NotNull Material itemMat); @NotNull NamespacedKey itemType);
/** /**
* Test if the provided item can be compatible with this enchantment. only non-Custom Anvil conflict. * Test if the provided item can be compatible with this enchantment. only non-Custom Anvil conflict.
* @param enchantments Immutable map of validated enchantments for the item. * @param enchantments Immutable map of validated enchantments for the item.
* @param itemMat Material of the tested item. * @param itemType Material namespaced key of the tested item.
* @param item Provide a new instance of the used item stack with the partial enchantment applied. * @param item Provide a new instance of the used item stack with the partial enchantment applied.
* @return If there is a conflict with the enchantment and the item. * @return If there is a conflict with the enchantment and the item.
*/ */
boolean isItemConflict( boolean isItemConflict(
@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Map<CAEnchantment, Integer> enchantments,
@NotNull Material itemMat, @NotNull NamespacedKey itemType,
@NotNull ItemStack item); @NotNull ItemStack item);
} }

Some files were not shown because too many files have changed in this diff Show more