44import ch .njol .skript .aliases .ItemType ;
55import ch .njol .skript .classes .Changer .ChangeMode ;
66import ch .njol .skript .classes .Changer .ChangerUtils ;
7- import ch .njol .skript .doc .Description ;
8- import ch .njol .skript .doc .Examples ;
9- import ch .njol .skript .doc .Name ;
10- import ch .njol .skript .doc .Since ;
7+ import ch .njol .skript .doc .*;
118import ch .njol .skript .lang .Effect ;
129import ch .njol .skript .lang .Expression ;
1310import ch .njol .skript .lang .SkriptParser .ParseResult ;
1411import ch .njol .skript .util .EnchantmentType ;
12+ import ch .njol .skript .util .Patterns ;
1513import ch .njol .util .Kleenean ;
14+ import org .bukkit .Bukkit ;
1615import org .bukkit .event .Event ;
16+ import org .bukkit .inventory .ItemFactory ;
1717import org .bukkit .inventory .ItemStack ;
1818import org .jetbrains .annotations .Nullable ;
1919
20+ import java .util .concurrent .ThreadLocalRandom ;
2021import java .util .function .Function ;
2122
22- /**
23- * @author Peter Güttinger
24- */
2523@ Name ("Enchant/Disenchant" )
26- @ Description ("Enchant or disenchant an existing item." )
27- @ Examples ({"enchant the player's tool with sharpness 5" ,
28- "disenchant the player's tool" })
29- @ Since ("2.0" )
24+ @ Description ("Enchant or disenchant an existing item. Enchanting at a specific level will act as if an enchanting table " +
25+ "was used, and will apply the enchantments randomly chosen at that level. Treasure enchantments, like mending, can " +
26+ "optionally be allowed. Note that enchanting a book at a specific level will turn it into an enchanted book, rather " +
27+ "than a book with enchantments." )
28+ @ Example ("enchant the player's tool with sharpness 5" )
29+ @ Example ("enchant the player's tool at level 30 " )
30+ @ Example ("disenchant the player's tool" )
31+ @ Since ("2.0, INSERT VERSION (at level)" )
3032public class EffEnchant extends Effect {
33+
34+ private enum Operation {
35+ ENCHANT ,
36+ ENCHANT_AT_LEVEL ,
37+ DISENCHANT
38+ }
39+
40+ private static final Patterns <Operation > patterns ;
41+
3142 static {
32- Skript .registerEffect (EffEnchant .class ,
33- "enchant %~itemtypes% with %enchantmenttypes%" ,
34- "disenchant %~itemtypes%" );
43+ patterns = new Patterns <>(new Object [][]{
44+ {"enchant %~itemtypes% with %enchantmenttypes%" , Operation .ENCHANT },
45+ {"[naturally|randomly] enchant %~itemtypes% at level %number%[treasure:[,] allowing treasure enchant[ment]s]" ,
46+ Operation .ENCHANT_AT_LEVEL },
47+ {"disenchant %~itemtypes%" , Operation .DISENCHANT }
48+ });
49+ Skript .registerEffect (EffEnchant .class , patterns .getPatterns ());
3550 }
36-
37- @ SuppressWarnings ("null" )
51+
3852 private Expression <ItemType > items ;
39- @ Nullable
4053 private Expression <EnchantmentType > enchantments ;
54+ private Expression <Number > level ;
55+ private boolean treasure ;
56+ private Operation operation ;
4157
4258 @ Override
4359 @ SuppressWarnings ("unchecked" )
@@ -47,36 +63,63 @@ public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelaye
4763 Skript .error (items + " cannot be changed, thus it cannot be (dis)enchanted" );
4864 return false ;
4965 }
50- if (matchedPattern == 0 )
66+ if (matchedPattern == 0 ) {
5167 enchantments = (Expression <EnchantmentType >) exprs [1 ];
68+ } else if (matchedPattern == 1 ) {
69+ level = (Expression <Number >) exprs [1 ];
70+ treasure = parseResult .hasTag ("treasure" );
71+ }
72+ operation = patterns .getInfo (matchedPattern );
5273 return true ;
5374 }
5475
5576 @ Override
5677 protected void execute (Event event ) {
5778 Function <ItemType , ItemType > changeFunction ;
5879
59- if (enchantments != null ) {
60- EnchantmentType [] types = enchantments .getArray (event );
61- if (types .length == 0 )
62- return ;
63- changeFunction = item -> {
64- item .addEnchantments (types );
65- return item ;
66- };
67- } else {
68- changeFunction = item -> {
80+ switch (operation ) {
81+ case ENCHANT -> {
82+ EnchantmentType [] types = enchantments .getArray (event );
83+ if (types .length == 0 )
84+ return ;
85+ changeFunction = item -> {
86+ item .addEnchantments (types );
87+ return item ;
88+ };
89+ }
90+ case ENCHANT_AT_LEVEL -> {
91+ ItemFactory factory = Bukkit .getItemFactory ();
92+ Number levelValue = level .getSingle (event );
93+ if (levelValue == null || levelValue .intValue () < 0 ) {
94+ return ;
95+ }
96+ changeFunction = item -> {
97+ ItemStack itemstack = item .getRandom ();
98+ if (itemstack == null ) {
99+ return item ;
100+ }
101+ itemstack = factory .enchantWithLevels (itemstack , levelValue .intValue (), treasure , ThreadLocalRandom .current ());
102+ return new ItemType (itemstack );
103+ };
104+ }
105+ case DISENCHANT -> changeFunction = item -> {
69106 item .clearEnchantments ();
70107 return item ;
71108 };
109+ default -> throw new IllegalStateException ("Unexpected operation: " + operation );
72110 }
73111
74112 this .items .changeInPlace (event , changeFunction );
75113 }
76114
77115 @ Override
78116 public String toString (@ Nullable Event event , boolean debug ) {
79- return enchantments == null ? "disenchant " + items .toString (event , debug ) : "enchant " + items .toString (event , debug ) + " with " + enchantments ;
117+ return switch (operation ) {
118+ case ENCHANT -> "enchant " + items .toString (event , debug ) + " with " + enchantments .toString (event , debug );
119+ case ENCHANT_AT_LEVEL -> "enchant " + items .toString (event , debug ) + " at level " + level .toString (event , debug )
120+ + (treasure ? " allowing treasure enchantments" : "" );
121+ case DISENCHANT -> "disenchant " + items .toString (event , debug );
122+ };
80123 }
81124
82125}
0 commit comments