Skip to content

Commit

Permalink
Fix enum back compat after Spigot changes
Browse files Browse the repository at this point in the history
Villager professions, cat types, and frog types were changed from enums to interfaces. If built against these changes, they break backwards binary compatibility when invoking their methods. So reflection was needed. Used Registry where possible, but until 1.20.4 Cat.Type didn't extend Keyed and wasn't added to the Registry.
  • Loading branch information
PseudoKnight committed Jul 13, 2024
1 parent f95e5af commit 04ec9ef
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package com.laytonsmith.abstraction.bukkit.entities;

import com.laytonsmith.PureUtilities.Common.ReflectionUtils;
import com.laytonsmith.PureUtilities.Common.ReflectionUtils.ReflectionException;
import com.laytonsmith.abstraction.entities.MCCat;
import com.laytonsmith.abstraction.enums.MCCatType;
import com.laytonsmith.abstraction.enums.MCDyeColor;
import org.bukkit.DyeColor;
import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.entity.Cat;
import org.bukkit.entity.Entity;

import java.util.Locale;

public class BukkitMCCat extends BukkitMCTameable implements MCCat {

Cat c;
Expand Down Expand Up @@ -38,11 +45,33 @@ public void setSitting(boolean sitting) {

@Override
public MCCatType getCatType() {
return MCCatType.valueOf(c.getCatType().name());
// changed from enum to interface in 1.21
try {
NamespacedKey key = ReflectionUtils.invokeMethod(Keyed.class, c.getCatType(), "getKey");
return MCCatType.valueOf(key.getKey().toUpperCase(Locale.ROOT));
} catch(ReflectionException ex) {
// probably before 1.20.4
return MCCatType.valueOf(ReflectionUtils.invokeMethod(Enum.class, c.getCatType(), "name"));
}
}

@Override
public void setCatType(MCCatType type) {
c.setCatType(Cat.Type.valueOf(type.name()));
try {
Cat.Type t = Registry.CAT_VARIANT.get(NamespacedKey.minecraft(type.name().toLowerCase(Locale.ROOT)));
if(t == null) {
return;
}
c.setCatType(t);
} catch(NoSuchFieldError ex) {
// probably before 1.20.4
try {
Class cls = Class.forName("org.bukkit.entity.Cat$Type");
c.setCatType(ReflectionUtils.invokeMethod(cls, null, "valueOf",
new Class[]{String.class}, new Object[]{type.name()}));
} catch (ClassNotFoundException exc) {
throw new RuntimeException(exc);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package com.laytonsmith.abstraction.bukkit.entities;

import com.laytonsmith.PureUtilities.Common.ReflectionUtils;
import com.laytonsmith.abstraction.MCEntity;
import com.laytonsmith.abstraction.bukkit.BukkitConvertor;
import com.laytonsmith.abstraction.entities.MCFrog;
import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Frog;
import org.bukkit.entity.Frog.Variant;

import java.util.Locale;

public class BukkitMCFrog extends BukkitMCAnimal implements MCFrog {

Expand All @@ -23,12 +28,17 @@ public Frog getHandle() {

@Override
public MCFrogType getFrogType() {
return MCFrogType.valueOf(f.getVariant().name());
// changed from enum to interface in 1.21
NamespacedKey key = ReflectionUtils.invokeMethod(Keyed.class, f.getVariant(), "getKey");
return MCFrogType.valueOf(key.getKey().toUpperCase(Locale.ROOT));
}

@Override
public void setFrogType(MCFrogType type) {
f.setVariant(Variant.valueOf(type.name()));
Frog.Variant v = Registry.FROG_VARIANT.get(NamespacedKey.minecraft(type.name().toLowerCase(Locale.ROOT)));
if(v != null) {
f.setVariant(v);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package com.laytonsmith.abstraction.enums.bukkit;

import com.laytonsmith.PureUtilities.Common.ReflectionUtils;
import com.laytonsmith.abstraction.enums.MCProfession;
import com.laytonsmith.core.MSLog;
import com.laytonsmith.core.Static;
import com.laytonsmith.core.constructs.Target;
import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.entity.Villager;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

public class BukkitMCProfession extends MCProfession<Villager.Profession> {
Expand All @@ -19,14 +24,20 @@ public BukkitMCProfession(MCVanillaProfession vanillaProfession, Villager.Profes

@Override
public String name() {
return getAbstracted() == MCVanillaProfession.NONE ? getConcrete().name() : getAbstracted().name();
if(getAbstracted() == MCVanillaProfession.UNKNOWN) {
// changed from enum to interface in 1.21
NamespacedKey key = ReflectionUtils.invokeMethod(Keyed.class, getConcrete(), "getKey");
return key.getKey().toUpperCase(Locale.ROOT);
}
return getAbstracted().name();
}

public static MCProfession valueOfConcrete(Villager.Profession test) {
MCProfession profession = BUKKIT_MAP.get(test);
if(profession == null) {
NamespacedKey key = ReflectionUtils.invokeMethod(Keyed.class, test, "getKey");
MSLog.GetLogger().e(MSLog.Tags.GENERAL, "Bukkit Villager Profession missing in BUKKIT_MAP: "
+ test.name(), Target.UNKNOWN);
+ key.getKey().toUpperCase(Locale.ROOT), Target.UNKNOWN);
return new BukkitMCProfession(MCVanillaProfession.UNKNOWN, test);
}
return profession;
Expand All @@ -48,15 +59,16 @@ public static void build() {
BUKKIT_MAP.put(profession, wrapper);
}
}
for(Villager.Profession pr : Villager.Profession.values()) {
for(Villager.Profession pr : Registry.VILLAGER_PROFESSION) {
if(pr != null && !BUKKIT_MAP.containsKey(pr)) {
MAP.put(pr.name(), new BukkitMCProfession(MCVanillaProfession.UNKNOWN, pr));
NamespacedKey key = ReflectionUtils.invokeMethod(Keyed.class, pr, "getKey");
MAP.put(key.getKey().toUpperCase(Locale.ROOT), new BukkitMCProfession(MCVanillaProfession.UNKNOWN, pr));
BUKKIT_MAP.put(pr, new BukkitMCProfession(MCVanillaProfession.UNKNOWN, pr));
}
}
}

private static Villager.Profession getBukkitType(MCVanillaProfession v) {
return Villager.Profession.valueOf(v.name());
return Registry.VILLAGER_PROFESSION.get(NamespacedKey.minecraft(v.name().toLowerCase(Locale.ROOT)));
}
}

0 comments on commit 04ec9ef

Please sign in to comment.