Skip to content

Commit 22ebcac

Browse files
committed
feat: 1.21.3+ 支持
1 parent 125ab01 commit 22ebcac

8 files changed

Lines changed: 186 additions & 47 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ gradle-app.setting
2222

2323
.idea/
2424
vscode/
25+
run/

build.gradle.kts

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@ plugins {
22
id("java")
33
id("maven-publish")
44
id("io.freefair.lombok") version "8.7.1"
5-
id("com.gradleup.shadow") version "8.3.0"
6-
id("net.minecrell.plugin-yml.bukkit") version "0.6.0"
5+
id("com.gradleup.shadow") version "8.3.6"
6+
id("de.eldoria.plugin-yml.bukkit") version "0.7.1"
7+
id("xyz.jpenilla.run-paper") version "2.3.1"
78
}
89

910
repositories {
1011
mavenLocal()
1112
mavenCentral()
12-
maven("https://s01.oss.sonatype.org/content/groups/public/")
1313
maven("https://repo.papermc.io/repository/maven-public/")
1414
maven("https://jitpack.io")
1515
}
1616

1717
dependencies {
18-
compileOnly("io.papermc.paper:paper-api:1.21-R0.1-SNAPSHOT")
19-
compileOnly("com.github.Slimefun:Slimefun4:RC-37")
20-
compileOnly("net.guizhanss:GuizhanLibPlugin:2.2.0")
18+
compileOnly("io.papermc.paper:paper-api:1.21.7-R0.1-SNAPSHOT")
19+
compileOnly("com.github.SlimefunGuguProject:Slimefun4:2025.1")
20+
compileOnly("net.guizhanss:GuizhanLibPlugin:2.3.0")
2121
implementation("org.bstats:bstats-bukkit:3.0.3")
2222
implementation("com.google.code.findbugs:jsr305:3.0.2")
2323
}
@@ -27,7 +27,8 @@ version = "UNOFFICIAL"
2727
description = "MobCapturer"
2828

2929
java {
30-
sourceCompatibility = JavaVersion.VERSION_21
30+
disableAutoTargetJvm()
31+
sourceCompatibility = JavaVersion.VERSION_17
3132
}
3233

3334
publishing {
@@ -61,7 +62,24 @@ bukkit {
6162
apiVersion = "1.18"
6263
authors = listOf("TheBusyBiscuit", "ybw0014")
6364
description = "A Slimefun Addon that adds a tool that allows you to capture mobs"
64-
website = "https://github.com/Slimefun-Addon-Community/MobCapturer"
65+
website = "https://github.com/SlimefunGuguProject/MobCapturer"
6566
depend = listOf("Slimefun")
6667
softDepend = listOf("GuizhanLibPlugin")
6768
}
69+
70+
tasks {
71+
runServer {
72+
downloadPlugins {
73+
// Slimefun
74+
url("https://builds.guizhanss.com/api/download/SlimefunGuguProject/Slimefun4/master/218")
75+
// GuizhanLibPlugin
76+
url("https://builds.guizhanss.com/api/download/ybw0014/GuizhanLibPlugin/master/latest")
77+
// SlimeHUD
78+
url("https://builds.guizhanss.com/api/download/SlimefunGuguProject/SlimeHUD/master/latest")
79+
// GuizhanCraft for testing convenient
80+
url("https://builds.guizhanss.com/api/download/ybw0014/GuizhanCraft/master/latest")
81+
}
82+
jvmArgs("-Dcom.mojang.eula.agree=true")
83+
minecraftVersion("1.21.6")
84+
}
85+
}

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
44
networkTimeout=10000
55
validateDistributionUrl=true
66
zipStoreBase=GRADLE_USER_HOME

src/main/java/io/github/thebusybiscuit/mobcapturer/adapters/MobAdapter.java

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import com.google.gson.JsonObject;
1414
import com.google.gson.JsonParser;
1515

16+
import io.github.thebusybiscuit.mobcapturer.utils.compatibility.AttributeX;
17+
1618
import org.bukkit.ChatColor;
1719
import org.bukkit.NamespacedKey;
1820
import org.bukkit.attribute.Attribute;
@@ -94,7 +96,13 @@ default void apply(T entity, JsonObject json) {
9496
JsonObject attributes = json.getAsJsonObject("_attributes");
9597

9698
for (Map.Entry<String, JsonElement> entry : attributes.entrySet()) {
97-
AttributeInstance instance = entity.getAttribute(Attribute.valueOf(entry.getKey()));
99+
Attribute attr = AttributeX.valueOf(entry.getKey());
100+
101+
if (attr == null) {
102+
continue;
103+
}
104+
105+
AttributeInstance instance = entity.getAttribute(attr);
98106

99107
if (instance != null) {
100108
for (AttributeModifier modifier : new ArrayList<>(instance.getModifiers())) {
@@ -176,32 +184,7 @@ default JsonObject saveData(@Nonnull T entity) {
176184
json.addProperty("_gravity", entity.hasGravity());
177185
json.addProperty("_fireTicks", entity.getFireTicks());
178186

179-
JsonObject attributes = new JsonObject();
180-
181-
for (Attribute attribute : Attribute.values()) {
182-
AttributeInstance instance = entity.getAttribute(attribute);
183-
184-
if (instance != null) {
185-
JsonObject obj = new JsonObject();
186-
obj.addProperty("base", instance.getBaseValue());
187-
188-
JsonArray modifiers = new JsonArray();
189-
190-
for (AttributeModifier modifier : instance.getModifiers()) {
191-
JsonObject mod = new JsonObject();
192-
Map<String, Object> serializedMod = modifier.serialize();
193-
194-
for (var entry : serializedMod.entrySet()) {
195-
mod.addProperty(entry.getKey(), entry.getValue().toString());
196-
}
197-
198-
modifiers.add(mod);
199-
}
200-
201-
obj.add("modifiers", modifiers);
202-
attributes.add(attribute.toString(), obj);
203-
}
204-
}
187+
JsonObject attributes = AttributeX.serializeAttributesFromEntity(entity);
205188

206189
json.add("_attributes", attributes);
207190

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package io.github.thebusybiscuit.mobcapturer.adapters.mobs;
2+
3+
import io.github.thebusybiscuit.mobcapturer.adapters.InventoryAdapter;
4+
import org.bukkit.entity.HappyGhast;
5+
import org.bukkit.inventory.EquipmentSlot;
6+
import org.bukkit.inventory.ItemStack;
7+
8+
import javax.annotation.Nonnull;
9+
import javax.annotation.ParametersAreNonnullByDefault;
10+
import java.util.HashMap;
11+
import java.util.Map;
12+
13+
public class HappyGhastAdapter extends AnimalsAdapter<HappyGhast> implements InventoryAdapter<HappyGhast> {
14+
15+
public HappyGhastAdapter() {
16+
super(HappyGhast.class);
17+
}
18+
19+
@Override
20+
@ParametersAreNonnullByDefault
21+
public void applyInventory(HappyGhast entity, Map<String, ItemStack> inventory) {
22+
entity.getEquipment().setItem(EquipmentSlot.BODY, inventory.get("harness"));
23+
}
24+
25+
@Nonnull
26+
@Override
27+
public Map<String, ItemStack> saveInventory(@Nonnull HappyGhast entity) {
28+
Map<String, ItemStack> inventory = new HashMap<>();
29+
30+
inventory.put("harness", entity.getEquipment().getItem(EquipmentSlot.BODY));
31+
32+
return inventory;
33+
}
34+
35+
}

src/main/java/io/github/thebusybiscuit/mobcapturer/setup/Setup.java

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import javax.annotation.ParametersAreNonnullByDefault;
44

5+
import io.github.thebusybiscuit.mobcapturer.adapters.mobs.HappyGhastAdapter;
6+
57
import org.bukkit.ChatColor;
68
import org.bukkit.Material;
79
import org.bukkit.entity.Armadillo;
@@ -14,6 +16,7 @@
1416
import org.bukkit.entity.Chicken;
1517
import org.bukkit.entity.Cod;
1618
import org.bukkit.entity.Cow;
19+
import org.bukkit.entity.Creaking;
1720
import org.bukkit.entity.Dolphin;
1821
import org.bukkit.entity.Donkey;
1922
import org.bukkit.entity.Drowned;
@@ -192,9 +195,8 @@ private static void setupMobEggs() {
192195
registerMob(EntityType.SNIFFER, new SnifferAdapter(), "a9946dda3e6162dfaf37921bab6bd31b87a3000624848b65eca1efe73167c960");
193196
}
194197
if (MinecraftVersionUtil.isAtLeast(20, 5)) {
195-
// https://minecraft-heads.com/custom-heads/head/74256-armadillo
196-
// TODO: use a spawn egg texture when available
197-
registerMob(EntityType.ARMADILLO, new AnimalsAdapter<>(Armadillo.class), "c9c1e96ce985725e22ed6ccf0f4c4810c729a2538b97bda06faeb3b92799c878");
198+
// https://minecraft-heads.com/custom-heads/head/109893-spawn-egg-armadillo
199+
registerMob(EntityType.ARMADILLO, new AnimalsAdapter<>(Armadillo.class), "2c8abc4e6fc02333ae72a8526fb41e87a348e31cf09f398d36a4398786605abd");
198200
}
199201
// </editor-fold>
200202

@@ -218,9 +220,18 @@ private static void setupMobEggs() {
218220
registerMob(EntityType.ALLAY, new AllayAdapter(), "6c3f114efbd908284c7aadd81993769057361dd756bf5e7883b8e0b1cea446e7");
219221
}
220222
if (MinecraftVersionUtil.isAtLeast(21)) {
221-
// https://minecraft-heads.com/custom-heads/head/68476-breeze
222-
// TODO: use a spawn egg texture when available
223-
registerMob(EntityType.BREEZE, new StandardMobAdapter<>(Breeze.class), "cd6e602f76f80c0657b5aed64e267eeea702b31e6dae86346c8506f2535ced02");
223+
// https://minecraft-heads.com/custom-heads/head/109899-spawn-egg-breeze
224+
registerMob(EntityType.BREEZE, new StandardMobAdapter<>(Breeze.class), "38eef639b9c151ee810adf488f29f74b9077dcc8c4816e27a34a6491fce04677");
225+
}
226+
if (MinecraftVersionUtil.isAtLeast(21, 4)) {
227+
// https://minecraft-heads.com/index.php/custom-heads/head/111645-creaking
228+
// TODO: spawn egg texture for creaking
229+
registerMob(EntityType.CREAKING, new StandardMobAdapter<>(Creaking.class), "a575bac234cf86b124d3cc870bd6b737d27679673a616faf2e996f9949c6153f");
230+
}
231+
if (MinecraftVersionUtil.isAtLeast(21, 6)) {
232+
// https://minecraft-heads.com/custom-heads/head/117418-happy-ghast
233+
// TODO: spawn egg texture for happy ghast
234+
registerMob(EntityType.HAPPY_GHAST, new HappyGhastAdapter(), "a1a36cb93d01675c4622dd5c8d872110911ec12c372e89afa8ba03862867f6fb");
224235
}
225236
// </editor-fold>
226237

@@ -346,9 +357,8 @@ private static void setupMobEggs() {
346357
// https://minecraft-heads.com/custom-heads/decoration/23705-spawn-egg-stray
347358
registerMob(EntityType.STRAY, new SkeletonAdapter<>(Stray.class), "5b45aae241779f0617ffaff468f3f2cf666d2f8a803002f9ae1ba0f14ed79fdd");
348359
if (MinecraftVersionUtil.isAtLeast(21)) {
349-
// https://minecraft-heads.com/custom-heads/head/87691-bogged
350-
// TODO: use a spawn egg texture when available
351-
registerMob(EntityType.BOGGED, new SkeletonAdapter<>(Bogged.class), "a3b9003ba2d05562c75119b8a62185c67130e9282f7acbac4bc2824c21eb95d9");
360+
// https://minecraft-heads.com/custom-heads/head/109898-spawn-egg-bogged
361+
registerMob(EntityType.BOGGED, new SkeletonAdapter<>(Bogged.class), "64722ae02b77d1288f7afee8b8c752796923f9b9840ff47d98d2a470a3d990fb");
352362
}
353363
// </editor-fold>
354364

src/main/java/io/github/thebusybiscuit/mobcapturer/utils/ReflectionUtils.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
import lombok.experimental.UtilityClass;
44

5+
import javax.annotation.Nullable;
6+
7+
import java.lang.reflect.InvocationTargetException;
8+
59
/**
610
* Reflection utilities used for backward compatibility.
711
* Other plugins should not use this class.
@@ -10,18 +14,28 @@
1014
@SuppressWarnings("unchecked")
1115
public final class ReflectionUtils {
1216

17+
@Nullable
1318
public static Object invoke(Object instance, String methodName, Object... args) {
1419
Class<?> currentClass = instance.getClass();
20+
Class<?>[] paramTypes = new Class<?>[args.length];
21+
for (int i = 0; i < args.length; i++) {
22+
paramTypes[i] = (args[i] != null) ? args[i].getClass() : Object.class;
23+
}
1524
while (currentClass != null) {
1625
try {
17-
return currentClass.getDeclaredMethod(methodName).invoke(instance, args);
18-
} catch (Exception x) {
26+
var method = currentClass.getDeclaredMethod(methodName, paramTypes);
27+
method.setAccessible(true);
28+
return method.invoke(instance, args);
29+
} catch (NoSuchMethodException ex) {
1930
currentClass = currentClass.getSuperclass();
31+
} catch (IllegalAccessException | InvocationTargetException ex) {
32+
return null;
2033
}
2134
}
2235
return null;
2336
}
2437

38+
@Nullable
2539
public static Object valueOf(Class<?> clazz, String fieldName) {
2640
if (clazz.isEnum()) {
2741
return Enum.valueOf(clazz.asSubclass(Enum.class), fieldName);
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package io.github.thebusybiscuit.mobcapturer.utils.compatibility;
2+
3+
import com.google.gson.JsonArray;
4+
import com.google.gson.JsonObject;
5+
import io.github.thebusybiscuit.mobcapturer.MobCapturer;
6+
import io.github.thebusybiscuit.mobcapturer.utils.ReflectionUtils;
7+
import lombok.experimental.UtilityClass;
8+
import org.bukkit.Registry;
9+
import org.bukkit.attribute.Attribute;
10+
import org.bukkit.attribute.AttributeInstance;
11+
import org.bukkit.attribute.AttributeModifier;
12+
import org.bukkit.entity.LivingEntity;
13+
14+
import javax.annotation.Nonnull;
15+
import java.util.ArrayList;
16+
import java.util.List;
17+
import java.util.Map;
18+
import java.util.logging.Level;
19+
20+
@UtilityClass
21+
public final class AttributeX {
22+
23+
private static final List<Object> allAttributes = new ArrayList<>();
24+
25+
static {
26+
try {
27+
final var registry = ReflectionUtils.valueOf(Registry.class, "ATTRIBUTE");
28+
if (registry != null) {
29+
for (Object attribute : (Iterable<?>) registry) {
30+
allAttributes.add(attribute);
31+
}
32+
}
33+
} catch (Exception ex) {
34+
MobCapturer.getInstance().getLogger().log(Level.SEVERE, "Failed to load attributes", ex);
35+
}
36+
}
37+
38+
@Nonnull
39+
public static Attribute valueOf(@Nonnull String name) {
40+
Attribute attr = (Attribute) ReflectionUtils.valueOf(Attribute.class, name);
41+
if (attr == null) {
42+
throw new IllegalArgumentException("No field found for Attribute with name " + name);
43+
}
44+
return attr;
45+
}
46+
47+
@Nonnull
48+
public static JsonObject serializeAttributesFromEntity(@Nonnull LivingEntity entity) {
49+
JsonObject attributes = new JsonObject();
50+
51+
for (var attribute : allAttributes) {
52+
AttributeInstance instance = (AttributeInstance) ReflectionUtils.invoke(entity, "getAttribute", attribute);
53+
if (instance != null) {
54+
JsonObject attributeObj = new JsonObject();
55+
attributeObj.addProperty("base", instance.getBaseValue());
56+
57+
JsonArray modifiers = new JsonArray();
58+
59+
for (AttributeModifier modifier : instance.getModifiers()) {
60+
JsonObject mod = new JsonObject();
61+
Map<String, Object> serializedMod = modifier.serialize();
62+
63+
for (var entry : serializedMod.entrySet()) {
64+
mod.addProperty(entry.getKey(), entry.getValue().toString());
65+
}
66+
67+
modifiers.add(mod);
68+
}
69+
70+
attributeObj.add("modifiers", modifiers);
71+
72+
attributes.add(attribute.toString(), attributeObj);
73+
}
74+
}
75+
76+
return attributes;
77+
}
78+
}

0 commit comments

Comments
 (0)