Skip to content

Commit 7b2dcd9

Browse files
Fix compilation/runtime errors due to Bukkit enum changes (SkriptLang#6926)
1 parent ce93263 commit 7b2dcd9

File tree

5 files changed

+94
-32
lines changed

5 files changed

+94
-32
lines changed

src/main/java/ch/njol/skript/classes/data/BukkitClasses.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1412,7 +1412,8 @@ public String toVariableNameString(FireworkEffect effect) {
14121412
if (BukkitUtils.registryExists("CAT_VARIANT")) {
14131413
catTypeClassInfo = new RegistryClassInfo<>(Cat.Type.class, Registry.CAT_VARIANT, "cattype", "cat types");
14141414
} else {
1415-
catTypeClassInfo = new EnumClassInfo<>(Cat.Type.class, "cattype", "cat types");
1415+
//noinspection unchecked, rawtypes - it is an enum on other versions
1416+
catTypeClassInfo = new EnumClassInfo<>((Class) Cat.Type.class, "cattype", "cat types");
14161417
}
14171418
Classes.registerClass(catTypeClassInfo
14181419
.user("cat ?(type|race)s?")

src/main/java/ch/njol/skript/entity/CatData.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
*/
1919
package ch.njol.skript.entity;
2020

21+
import ch.njol.skript.registrations.Classes;
22+
import com.google.common.collect.Iterators;
2123
import org.bukkit.entity.Cat;
2224
import org.eclipse.jdt.annotation.Nullable;
2325

@@ -26,12 +28,19 @@
2628
import ch.njol.skript.lang.SkriptParser.ParseResult;
2729
import ch.njol.util.coll.CollectionUtils;
2830

31+
import java.util.Objects;
32+
2933
public class CatData extends EntityData<Cat> {
3034

3135
static {
32-
if (Skript.classExists("org.bukkit.entity.Cat"))
36+
if (Skript.classExists("org.bukkit.entity.Cat")) {
3337
EntityData.register(CatData.class, "cat", Cat.class, "cat");
38+
types = Iterators.toArray(Classes.getExactClassInfo(Cat.Type.class).getSupplier().get(), Cat.Type.class);
39+
}
3440
}
41+
42+
@SuppressWarnings("NotNullFieldNotInitialized")
43+
private static Cat.Type[] types;
3544

3645
private Cat.@Nullable Type race = null;
3746

@@ -42,7 +51,7 @@ protected boolean init(Literal<?>[] exprs, int matchedPattern, ParseResult parse
4251
race = ((Literal<Cat.Type>) exprs[0]).getSingle();
4352
return true;
4453
}
45-
54+
4655
@Override
4756
protected boolean init(@Nullable Class<? extends Cat> c, @Nullable Cat cat) {
4857
race = (cat == null) ? Cat.Type.TABBY : cat.getCatType();
@@ -51,7 +60,7 @@ protected boolean init(@Nullable Class<? extends Cat> c, @Nullable Cat cat) {
5160

5261
@Override
5362
public void set(Cat entity) {
54-
Cat.Type type = race != null ? race : CollectionUtils.getRandom(Cat.Type.values());
63+
Cat.Type type = race != null ? race : CollectionUtils.getRandom(types);
5564
assert type != null;
5665
entity.setCatType(type);
5766
}
@@ -73,7 +82,7 @@ public EntityData getSuperType() {
7382

7483
@Override
7584
protected int hashCode_i() {
76-
return race != null ? race.hashCode() : 0;
85+
return Objects.hashCode(race);
7786
}
7887

7988
@Override

src/main/java/ch/njol/skript/entity/FrogData.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import org.bukkit.entity.Frog.Variant;
2626
import org.eclipse.jdt.annotation.Nullable;
2727

28+
import java.util.Objects;
29+
2830
public class FrogData extends EntityData<Frog> {
2931

3032
static {
@@ -42,13 +44,28 @@ public FrogData() {
4244

4345
public FrogData(@Nullable Variant variant) {
4446
this.variant = variant;
45-
matchedPattern = variant != null ? variant.ordinal() + 1 : 0;
47+
matchedPattern = 0;
48+
if (variant == Variant.TEMPERATE)
49+
matchedPattern = 1;
50+
if (variant == Variant.WARM)
51+
matchedPattern = 2;
52+
if (variant == Variant.COLD)
53+
matchedPattern = 3;
4654
}
4755

4856
@Override
4957
protected boolean init(Literal<?>[] exprs, int matchedPattern, SkriptParser.ParseResult parseResult) {
50-
if (matchedPattern > 0)
51-
variant = Variant.values()[matchedPattern - 1];
58+
switch (matchedPattern) {
59+
case 1:
60+
variant = Variant.TEMPERATE;
61+
break;
62+
case 2:
63+
variant = Variant.WARM;
64+
break;
65+
case 3:
66+
variant = Variant.COLD;
67+
break;
68+
}
5269
return true;
5370
}
5471

@@ -82,7 +99,7 @@ public EntityData getSuperType() {
8299

83100
@Override
84101
protected int hashCode_i() {
85-
return variant != null ? variant.hashCode() : 0;
102+
return Objects.hashCode(variant);
86103
}
87104

88105
@Override

src/main/java/ch/njol/skript/entity/VillagerData.java

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@
1818
*/
1919
package ch.njol.skript.entity;
2020

21+
import java.lang.invoke.MethodHandles;
22+
import java.lang.invoke.MethodType;
2123
import java.util.ArrayList;
2224
import java.util.Arrays;
2325
import java.util.Collections;
2426
import java.util.List;
27+
import java.util.Objects;
2528

2629
import org.bukkit.entity.Villager;
2730
import org.bukkit.entity.Villager.Profession;
@@ -37,7 +40,7 @@
3740
* @author Peter Güttinger
3841
*/
3942
public class VillagerData extends EntityData<Villager> {
40-
43+
4144
/**
4245
* Professions can be for zombies also. These are the ones which are only
4346
* for villagers.
@@ -49,25 +52,37 @@ public class VillagerData extends EntityData<Villager> {
4952
// NORMAL(-1), FARMER(0), LIBRARIAN(1), PRIEST(2), BLACKSMITH(3), BUTCHER(4), NITWIT(5);
5053

5154
Variables.yggdrasil.registerSingleClass(Profession.class, "Villager.Profession");
52-
55+
56+
professions = new ArrayList<>();
5357
if (Skript.isRunningMinecraft(1, 14)) {
5458
EntityData.register(VillagerData.class, "villager", Villager.class, 0,
5559
"villager", "normal", "armorer", "butcher", "cartographer",
5660
"cleric", "farmer", "fisherman", "fletcher",
5761
"leatherworker", "librarian", "mason", "nitwit",
5862
"shepherd", "toolsmith", "weaponsmith");
59-
professions = Arrays.asList(Profession.values());
63+
// TODO obtain from the registry in the future
64+
// This is not currently done as the ordering of the professions is important
65+
// There is no ordering guarantee from the registry
66+
professions = Arrays.asList(Profession.NONE, Profession.ARMORER, Profession.BUTCHER, Profession.CARTOGRAPHER,
67+
Profession.CLERIC, Profession.FARMER, Profession.FISHERMAN, Profession.FLETCHER, Profession.LEATHERWORKER,
68+
Profession.LIBRARIAN, Profession.MASON, Profession.NITWIT, Profession.SHEPHERD, Profession.TOOLSMITH,
69+
Profession.WEAPONSMITH);
6070
} else { // Post 1.10: Not all professions go for villagers
6171
EntityData.register(VillagerData.class, "villager", Villager.class, 0,
6272
"normal", "villager", "farmer", "librarian",
6373
"priest", "blacksmith", "butcher", "nitwit");
6474
// Normal is for zombie villagers, but needs to be here, since someone thought changing first element in enum was good idea :(
6575

66-
professions = new ArrayList<>();
67-
for (Profession prof : Profession.values()) {
68-
// We're better off doing stringfying the constants since these don't exist in 1.14
69-
if (!prof.toString().equals("NORMAL") && !prof.toString().equals("HUSK"))
70-
professions.add(prof);
76+
try {
77+
for (Profession prof : (Profession[]) MethodHandles.lookup().findStatic(Profession.class, "values", MethodType.methodType(Profession[].class)).invoke()) {
78+
// We're better off doing stringfying the constants since these don't exist in 1.14
79+
// Using String#valueOf to prevent IncompatibleClassChangeError due to Enum->Interface change
80+
String profString = String.valueOf(prof);
81+
if (!profString.equals("NORMAL") && !profString.equals("HUSK"))
82+
professions.add(prof);
83+
}
84+
} catch (Throwable e) {
85+
throw new RuntimeException("Failed to load legacy villager profession support", e);
7186
}
7287
}
7388
}
@@ -116,7 +131,7 @@ public Class<? extends Villager> getType() {
116131

117132
@Override
118133
protected int hashCode_i() {
119-
return profession != null ? profession.hashCode() : 0;
134+
return Objects.hashCode(profession);
120135
}
121136

122137
@Override
@@ -133,7 +148,8 @@ protected boolean deserialize(final String s) {
133148
if (s.isEmpty())
134149
return true;
135150
try {
136-
profession = Profession.valueOf(s);
151+
//noinspection unchecked, rawtypes - prevent IncompatibleClassChangeError due to Enum->Interface change
152+
profession = (Profession) Enum.valueOf((Class) Profession.class, s);
137153
return true;
138154
} catch (final IllegalArgumentException e) {
139155
return false;
@@ -143,7 +159,7 @@ protected boolean deserialize(final String s) {
143159
@Override
144160
public boolean isSupertypeOf(final EntityData<?> e) {
145161
if (e instanceof VillagerData)
146-
return profession == null || ((VillagerData) e).profession == profession;
162+
return profession == null || Objects.equals(((VillagerData) e).profession, profession);
147163
return false;
148164
}
149165

src/main/java/ch/njol/skript/entity/ZombieVillagerData.java

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,34 +28,53 @@
2828
import ch.njol.skript.lang.Literal;
2929
import ch.njol.skript.lang.SkriptParser.ParseResult;
3030

31+
import java.lang.invoke.MethodHandles;
32+
import java.lang.invoke.MethodType;
33+
import java.util.Arrays;
34+
import java.util.List;
35+
import java.util.Objects;
36+
3137
public class ZombieVillagerData extends EntityData<ZombieVillager> {
3238

33-
private final static boolean PROFESSION_UPDATE = Skript.isRunningMinecraft(1, 14);
34-
private final static Villager.Profession[] professions = Villager.Profession.values();
39+
private static final boolean PROFESSION_UPDATE = Skript.isRunningMinecraft(1, 14);
40+
private static final List<Profession> professions;
3541

3642
static {
37-
if (PROFESSION_UPDATE)
43+
if (PROFESSION_UPDATE) {
3844
EntityData.register(ZombieVillagerData.class, "zombie villager", ZombieVillager.class, 0,
3945
"zombie villager", "zombie armorer", "zombie butcher", "zombie cartographer", "zombie cleric", "zombie farmer", "zombie fisherman",
4046
"zombie fletcher", "zombie leatherworker", "zombie librarian", "zombie mason", "zombie nitwit", "zombie shepherd", "zombie toolsmith", "zombie weaponsmith");
41-
else
47+
professions = Arrays.asList(Profession.NONE, Profession.ARMORER, Profession.BUTCHER, Profession.CARTOGRAPHER,
48+
Profession.CLERIC, Profession.FARMER, Profession.FISHERMAN, Profession.FLETCHER, Profession.LEATHERWORKER,
49+
Profession.LIBRARIAN, Profession.MASON, Profession.NITWIT, Profession.SHEPHERD, Profession.TOOLSMITH,
50+
Profession.WEAPONSMITH);
51+
} else {
4252
EntityData.register(ZombieVillagerData.class, "zombie villager", ZombieVillager.class, 0,
4353
"zombie villager", "zombie farmer", "zombie librarian", "zombie priest", "zombie blacksmith", "zombie butcher", "zombie nitwit");
54+
try {
55+
professions = Arrays.asList((Profession[]) MethodHandles.lookup().findStatic(Profession.class, "values", MethodType.methodType(Profession[].class)).invoke());
56+
} catch (Throwable e) {
57+
throw new RuntimeException("Failed to load legacy villager profession support", e);
58+
}
59+
}
4460
}
45-
46-
private Villager.Profession profession = PROFESSION_UPDATE ? Profession.NONE : Profession.valueOf("NORMAL");
61+
62+
// prevent IncompatibleClassChangeError due to Enum->Interface change
63+
@SuppressWarnings({"unchecked", "rawtypes"})
64+
private Villager.Profession profession = PROFESSION_UPDATE ? Profession.NONE
65+
: (Profession) Enum.valueOf((Class) Profession.class, "NORMAL");
4766

4867
public ZombieVillagerData() {}
4968

5069
public ZombieVillagerData(Profession prof) {
5170
profession = prof;
52-
super.matchedPattern = prof.ordinal();
71+
super.matchedPattern = professions.indexOf(prof);
5372
}
5473

5574
@SuppressWarnings("null")
5675
@Override
5776
protected boolean init(final Literal<?>[] exprs, final int matchedPattern, final ParseResult parseResult) {
58-
profession = professions[matchedPattern];
77+
profession = professions.get(matchedPattern);
5978
return true;
6079
}
6180

@@ -73,8 +92,8 @@ protected boolean init(final @Nullable Class<? extends ZombieVillager> c, final
7392
@Override
7493
protected boolean deserialize(final String s) {
7594
try {
76-
profession = professions[Integer.parseInt(s)];
77-
} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
95+
profession = professions.get(Integer.parseInt(s));
96+
} catch (NumberFormatException | IndexOutOfBoundsException e) {
7897
throw new SkriptAPIException("Cannot parse zombie villager type " + s);
7998
}
8099

@@ -106,13 +125,13 @@ protected boolean equals_i(final EntityData<?> obj) {
106125

107126
@Override
108127
protected int hashCode_i() {
109-
return profession.hashCode();
128+
return Objects.hashCode(profession);
110129
}
111130

112131
@Override
113132
public boolean isSupertypeOf(final EntityData<?> e) {
114133
if (e instanceof ZombieVillagerData)
115-
return ((ZombieVillagerData) e).profession.equals(profession);
134+
return Objects.equals(((ZombieVillagerData) e).profession, profession);
116135
return false;
117136
}
118137

0 commit comments

Comments
 (0)