Skip to content

Commit 85beea7

Browse files
Pig Variants (#7846)
* Initial Commit * Update WolfData.java * Update PaperUtils.java * Requested Changes * Update BukkitClasses.java * Update BukkitClasses.java
1 parent fc51c90 commit 85beea7

File tree

6 files changed

+224
-54
lines changed

6 files changed

+224
-54
lines changed

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

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,15 @@
1111
import ch.njol.skript.classes.*;
1212
import ch.njol.skript.classes.registry.RegistryClassInfo;
1313
import ch.njol.skript.entity.EntityData;
14-
import ch.njol.skript.entity.WolfData;
14+
import ch.njol.skript.entity.PigData.PigVariantDummy;
15+
import ch.njol.skript.entity.WolfData.WolfVariantDummy;
1516
import ch.njol.skript.expressions.ExprDamageCause;
1617
import ch.njol.skript.expressions.base.EventValueExpression;
1718
import ch.njol.skript.lang.ParseContext;
1819
import ch.njol.skript.lang.util.SimpleLiteral;
1920
import ch.njol.skript.localization.Language;
2021
import ch.njol.skript.registrations.Classes;
21-
import ch.njol.skript.util.BlockUtils;
22-
import ch.njol.skript.util.PotionEffectUtils;
23-
import ch.njol.skript.util.StringMode;
24-
import ch.njol.skript.util.Utils;
22+
import ch.njol.skript.util.*;
2523
import ch.njol.yggdrasil.Fields;
2624
import io.papermc.paper.world.MoonPhase;
2725
import org.bukkit.*;
@@ -52,6 +50,7 @@
5250
import org.bukkit.event.player.PlayerQuitEvent.QuitReason;
5351
import org.bukkit.event.player.PlayerResourcePackStatusEvent.Status;
5452
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
53+
import org.bukkit.inventory.BlockInventoryHolder;
5554
import org.bukkit.inventory.*;
5655
import org.bukkit.metadata.Metadatable;
5756
import org.bukkit.potion.PotionEffect;
@@ -1410,14 +1409,15 @@ public String toVariableNameString(EnchantmentOffer eo) {
14101409
.description("Represents the cause of the action of a potion effect on an entity, e.g. arrow, command")
14111410
.since("2.10"));
14121411

1413-
ClassInfo<?> wolfVariantClassInfo;
1414-
if (Skript.classExists("org.bukkit.entity.Wolf$Variant") && BukkitUtils.registryExists("WOLF_VARIANT")) {
1415-
wolfVariantClassInfo = new RegistryClassInfo<>(Wolf.Variant.class, Registry.WOLF_VARIANT, "wolfvariant", "wolf variants");
1416-
} else {
1417-
/*
1418-
* Registers a dummy/placeholder class to ensure working operation on MC versions that do not have `Wolf.Variant`
1419-
*/
1420-
wolfVariantClassInfo = new ClassInfo<>(WolfData.VariantDummy.class, "wolfvariant");
1412+
ClassInfo<?> wolfVariantClassInfo = getRegistryClassInfo(
1413+
"org.bukkit.entity.Wolf$Variant",
1414+
"WOLF_VARIANT",
1415+
"wolfvariant",
1416+
"wolf variants"
1417+
);
1418+
if (wolfVariantClassInfo == null) {
1419+
// Registers a dummy/placeholder class to ensure working operation on MC versions that do not have 'Wolf.Variant' (1.20.4-)
1420+
wolfVariantClassInfo = new ClassInfo<>(WolfVariantDummy.class, "wolfvariant");
14211421
}
14221422
Classes.registerClass(wolfVariantClassInfo
14231423
.user("wolf ?variants?")
@@ -1550,14 +1550,75 @@ public String toVariableNameString(WorldBorder border) {
15501550
.changer(DefaultChangers.entityChanger)
15511551
);
15521552

1553-
15541553
Classes.registerClass(new EnumClassInfo<>(EquipmentSlot.class, "equipmentslot", "equipment slots")
15551554
.user("equipment ?slots?")
15561555
.name("Equipment Slot")
15571556
.description("Represents an equipment slot of an entity.")
15581557
.since("2.11")
15591558
);
15601559

1560+
ClassInfo<?> pigVariantClassInfo = getRegistryClassInfo(
1561+
"org.bukkit.entity.Pig$Variant",
1562+
"PIG_VARIANT",
1563+
"pigvariant",
1564+
"pig variants"
1565+
);
1566+
if (pigVariantClassInfo == null) {
1567+
// Registers a dummy/placeholder class to ensure working operation on MC versions that do not have 'Pig.Variant' (1.21.4-)
1568+
pigVariantClassInfo = new ClassInfo<>(PigVariantDummy.class, "pigvariant");
1569+
}
1570+
Classes.registerClass(pigVariantClassInfo
1571+
.user("pig ?variants?")
1572+
.name("Pig Variant")
1573+
.description("Represents the variant of a pig entity.",
1574+
"NOTE: Minecraft namespaces are supported, ex: 'minecraft:warm'.")
1575+
.since("INSERT VERSION")
1576+
.requiredPlugins("Minecraft 1.21.5+")
1577+
.documentationId("PigVariant"));
1578+
1579+
}
1580+
1581+
/**
1582+
* Gets a {@link RegistryClassInfo} by checking if the {@link Class} from {@code classPath} exists
1583+
* and {@link Registry} or {@link io.papermc.paper.registry.RegistryKey} contains {@code registryName}.
1584+
* @param classPath The {@link String} representation of the desired {@link Class}.
1585+
* @param registryName The {@link String} representation of the desired {@link Registry}.
1586+
* @param codeName The name used in patterns.
1587+
* @param languageNode The language node of the type.
1588+
* @return {@link RegistryClassInfo} if the class and registry exists, otherwise {@code null}.
1589+
*/
1590+
private static <R extends Keyed> @Nullable RegistryClassInfo<?> getRegistryClassInfo(
1591+
String classPath,
1592+
String registryName,
1593+
String codeName,
1594+
String languageNode
1595+
) {
1596+
if (!Skript.classExists(classPath))
1597+
return null;
1598+
Registry<R> registry = null;
1599+
if (BukkitUtils.registryExists(registryName)) {
1600+
try {
1601+
//noinspection unchecked
1602+
registry = (Registry<R>) Registry.class.getField(registryName).get(null);
1603+
} catch (NoSuchFieldException | IllegalAccessException e) {
1604+
throw new RuntimeException(e);
1605+
}
1606+
} else if (PaperUtils.registryExists(registryName)) {
1607+
registry = PaperUtils.getBukkitRegistry(registryName);
1608+
}
1609+
if (registry != null) {
1610+
Class<R> registryClass;
1611+
try {
1612+
//noinspection unchecked
1613+
registryClass = (Class<R>) Class.forName(classPath);
1614+
} catch (ClassNotFoundException e) {
1615+
Skript.debug("Could not retrieve the class with the path: '" + classPath + "'.");
1616+
throw new RuntimeException(e);
1617+
}
1618+
return new RegistryClassInfo<>(registryClass, registry, codeName, languageNode);
1619+
}
1620+
Skript.debug("There were no registries found for '" + registryName + "'.");
1621+
return null;
15611622
}
15621623

15631624
}
Lines changed: 72 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,83 @@
11
package ch.njol.skript.entity;
22

3+
import ch.njol.skript.Skript;
4+
import ch.njol.skript.lang.Literal;
5+
import ch.njol.skript.lang.SkriptParser.ParseResult;
6+
import ch.njol.skript.registrations.Classes;
7+
import ch.njol.util.coll.CollectionUtils;
8+
import com.google.common.collect.Iterators;
39
import org.bukkit.entity.Pig;
410
import org.jetbrains.annotations.Nullable;
511

6-
import ch.njol.skript.lang.Literal;
7-
import ch.njol.skript.lang.SkriptParser.ParseResult;
12+
import java.util.Objects;
813

9-
/**
10-
* @author Peter Güttinger
11-
*/
1214
public class PigData extends EntityData<Pig> {
15+
16+
public enum SaddleState {
17+
NOT_SADDLED, UNKNOWN, SADDLED
18+
}
19+
20+
private static final SaddleState[] SADDLE_STATES = SaddleState.values();
21+
private static boolean variantsEnabled = false;
22+
private static Object[] variants;
23+
1324
static {
1425
EntityData.register(PigData.class, "pig", Pig.class, 1, "unsaddled pig", "pig", "saddled pig");
26+
if (Skript.classExists("org.bukkit.entity.Pig$Variant")) {
27+
variantsEnabled = true;
28+
variants = Iterators.toArray(Classes.getExactClassInfo(Pig.Variant.class).getSupplier().get(), Pig.Variant.class);
29+
}
1530
}
1631

17-
private int saddled = 0;
32+
private SaddleState saddled = SaddleState.UNKNOWN;
33+
private @Nullable Object variant = null;
34+
35+
public PigData() {}
36+
37+
// TODO: When safe, 'variant' should have the type changed to 'Pig.Variant'
38+
public PigData(SaddleState saddled, @Nullable Object variant) {
39+
this.saddled = saddled;
40+
this.variant = variant;
41+
}
1842

1943
@Override
20-
protected boolean init(final Literal<?>[] exprs, final int matchedPattern, final ParseResult parseResult) {
21-
saddled = matchedPattern - 1;
44+
protected boolean init(Literal<?>[] exprs, int matchedPattern, ParseResult parseResult) {
45+
saddled = SADDLE_STATES[matchedPattern];
46+
if (exprs[0] != null && variantsEnabled)
47+
//noinspection unchecked
48+
variant = ((Literal<Pig.Variant>) exprs[0]).getSingle();
2249
return true;
2350
}
2451

2552
@Override
26-
protected boolean init(final @Nullable Class<? extends Pig> c, final @Nullable Pig e) {
27-
saddled = e == null ? 0 : e.hasSaddle() ? 1 : -1;
53+
protected boolean init(@Nullable Class<? extends Pig> entityClass, @Nullable Pig pig) {
54+
saddled = SaddleState.UNKNOWN;
55+
if (pig != null) {
56+
saddled = pig.hasSaddle() ? SaddleState.SADDLED : SaddleState.NOT_SADDLED;
57+
if (variantsEnabled)
58+
variant = pig.getVariant();
59+
}
2860
return true;
2961
}
30-
31-
// return "" + saddled;
62+
3263
@Override
33-
protected boolean deserialize(final String s) {
34-
try {
35-
saddled = Integer.parseInt(s);
36-
return Math.abs(saddled) <= 1;
37-
} catch (final NumberFormatException e) {
38-
return false;
39-
}
64+
protected boolean deserialize(String string) {
65+
return true;
4066
}
4167

4268
@Override
43-
public void set(final Pig entity) {
44-
if (saddled != 0)
45-
entity.setSaddle(saddled == 1);
69+
public void set(Pig pig) {
70+
pig.setSaddle(saddled == SaddleState.SADDLED);
71+
if (variantsEnabled) {
72+
Object finalVariant = variant != null ? variant : CollectionUtils.getRandom(variants);
73+
pig.setVariant((Pig.Variant) finalVariant);
74+
}
4675
}
4776

4877
@Override
49-
protected boolean match(final Pig entity) {
50-
return saddled == 0 || entity.hasSaddle() == (saddled == 1);
78+
protected boolean match(Pig pig) {
79+
return (saddled == SaddleState.UNKNOWN || (pig.hasSaddle() ? SaddleState.SADDLED : SaddleState.NOT_SADDLED) == saddled)
80+
&& (variant == null || variant == pig.getVariant());
5181
}
5282

5383
@Override
@@ -56,28 +86,36 @@ public Class<? extends Pig> getType() {
5686
}
5787

5888
@Override
59-
protected boolean equals_i(final EntityData<?> obj) {
60-
if (!(obj instanceof PigData))
89+
protected boolean equals_i(EntityData<?> obj) {
90+
if (!(obj instanceof PigData other))
91+
return false;
92+
if (saddled != other.saddled)
6193
return false;
62-
final PigData other = (PigData) obj;
63-
return other.saddled == saddled;
94+
return variant == null || variant == other.variant;
6495
}
6596

6697
@Override
6798
protected int hashCode_i() {
68-
return saddled;
99+
return saddled.ordinal() + Objects.hashCode(variant);
69100
}
70101

71102
@Override
72-
public boolean isSupertypeOf(final EntityData<?> e) {
73-
if (e instanceof PigData)
74-
return saddled == 0 || ((PigData) e).saddled == saddled;
75-
return false;
103+
public boolean isSupertypeOf(EntityData<?> entityData) {
104+
if (!(entityData instanceof PigData other))
105+
return false;
106+
if (saddled != SaddleState.UNKNOWN && saddled != other.saddled)
107+
return false;
108+
return variant == null || variant == other.variant;
76109
}
77110

78111
@Override
79-
public EntityData getSuperType() {
112+
public EntityData<Pig> getSuperType() {
80113
return new PigData();
81114
}
115+
116+
/**
117+
* A dummy/placeholder class to ensure working operation on MC versions that do not have `Pig.Variant`
118+
*/
119+
public static class PigVariantDummy {}
82120

83121
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class WolfData extends EntityData<Wolf> {
2323
EntityData.register(WolfData.class, "wolf", Wolf.class, 1,
2424
"peaceful wolf", "wolf", "angry wolf",
2525
"wild wolf", "tamed wolf");
26-
if (Skript.classExists("org.bukkit.entity.Wolf$Variant") && BukkitUtils.registryExists("WOLF_VARIANT")) {
26+
if (Skript.classExists("org.bukkit.entity.Wolf$Variant")) {
2727
variantsEnabled = true;
2828
variants = Iterators.toArray(Classes.getExactClassInfo(Wolf.Variant.class).getSupplier().get(), Wolf.Variant.class);
2929
}
@@ -152,6 +152,6 @@ public EntityData<Wolf> getSuperType() {
152152
/**
153153
* A dummy/placeholder class to ensure working operation on MC versions that do not have `Wolf.Variant`
154154
*/
155-
public static class VariantDummy {};
155+
public static class WolfVariantDummy {};
156156

157157
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package ch.njol.skript.util;
2+
3+
import ch.njol.skript.Skript;
4+
import io.papermc.paper.registry.RegistryAccess;
5+
import io.papermc.paper.registry.RegistryKey;
6+
import org.bukkit.Keyed;
7+
import org.bukkit.Registry;
8+
import org.jetbrains.annotations.Nullable;
9+
10+
public class PaperUtils {
11+
12+
private static final boolean REGISTRY_ACCESS_EXISTS = Skript.classExists("io.papermc.paper.registry.RegistryAccess");
13+
private static final boolean REGISTRY_KEY_EXISTS = Skript.classExists("io.papermc.paper.registry.RegistryKey");
14+
15+
/**
16+
* Check if a registry exists within {@link RegistryKey}
17+
* @param registry Registry to check for (Fully qualified name of registry)
18+
* @return True if registry exists else false
19+
*/
20+
public static boolean registryExists(String registry) {
21+
return REGISTRY_ACCESS_EXISTS
22+
&& REGISTRY_KEY_EXISTS
23+
&& Skript.fieldExists(RegistryKey.class, registry);
24+
}
25+
26+
/**
27+
* Gets the Bukkit {@link Registry} from Paper's {@link RegistryKey}.
28+
* @param registry Registry to get (Fully qualified name of registry).
29+
* @return The Bukkit {@link Registry} if registry exists else {@code null}.
30+
*/
31+
public static <T extends Keyed> @Nullable Registry<T> getBukkitRegistry(String registry) {
32+
if (!registryExists(registry))
33+
return null;
34+
RegistryKey registryKey;
35+
try {
36+
registryKey = (RegistryKey) RegistryKey.class.getField(registry).get(null);
37+
} catch (NoSuchFieldException | IllegalAccessException ignored) {
38+
return null;
39+
}
40+
//noinspection unchecked
41+
return (Registry<T>) RegistryAccess.registryAccess().getRegistry(registryKey);
42+
}
43+
44+
}

src/main/resources/lang/default.lang

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -701,13 +701,13 @@ entities:
701701
pattern: painting(|1¦s)
702702
pig:
703703
name: pig¦s
704-
pattern: <age> pig(|1¦s)|(4¦)piglet(|1¦s)
704+
pattern: <age> [%-pigvariant%] pig(|1¦s)|(4¦)piglet(|1¦s)
705705
saddled pig:
706706
name: saddled pig¦s
707-
pattern: saddled pig(|1¦s)
707+
pattern: saddled [%-pigvariant%] pig(|1¦s)
708708
unsaddled pig:
709709
name: unsaddled pig¦s @an
710-
pattern: unsaddled pig(|1¦s)
710+
pattern: unsaddled [%-pigvariant%] pig(|1¦s)
711711
player:
712712
name: player¦s
713713
pattern: player(|1¦s)
@@ -2586,6 +2586,12 @@ equipment slots:
25862586
off_hand: off hand slot, off hand
25872587
body: body slot, body armor slot, body armour slot
25882588

2589+
# -- Pig Variants --
2590+
pig variants:
2591+
cold: cold
2592+
temperate: temperate
2593+
warm: warm
2594+
25892595
# -- Boolean --
25902596
boolean:
25912597
true:
@@ -2689,7 +2695,7 @@ types:
26892695
vehicle: vehicle¦s @a
26902696
fishingstate: fishing state¦s @a
26912697
equipmentslot: equipment slot¦s @an
2692-
2698+
pigvariant: pig variant¦s @a
26932699

26942700
# Skript
26952701
weathertype: weather type¦s @a

0 commit comments

Comments
 (0)