diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java index 81b3beab652..6acf2d9be75 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java @@ -1542,6 +1542,19 @@ public String toVariableNameString(EnchantmentOffer eo) { .description("Represents a change reason of an experience cooldown change event.") .since("INSERT VERSION")); + Classes.registerClass(new RegistryClassInfo<>(Villager.Type.class, Registry.VILLAGER_TYPE, "villagertype", "villager types") + .user("villager ?types?") + .name("Villager Type") + .description("Represents the different types of villagers. These are usually the biomes a villager can be from.") + .after("biome") + .since("INSERT VERSION")); + + Classes.registerClass(new RegistryClassInfo<>(Villager.Profession.class, Registry.VILLAGER_PROFESSION, "villagerprofession", "villager professions") + .user("villager ?professions?") + .name("Villager Profession") + .description("Represents the different professions of villagers.") + .since("INSERT VERSION")); + if (Skript.classExists("org.bukkit.entity.EntitySnapshot")) { Classes.registerClass(new ClassInfo<>(EntitySnapshot.class, "entitysnapshot") .user("entity ?snapshots?") @@ -1554,6 +1567,7 @@ public String toVariableNameString(EnchantmentOffer eo) { .since("INSERT VERSION") ); } + } } diff --git a/src/main/java/ch/njol/skript/expressions/ExprVillagerLevel.java b/src/main/java/ch/njol/skript/expressions/ExprVillagerLevel.java new file mode 100644 index 00000000000..d57be3c4fc5 --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprVillagerLevel.java @@ -0,0 +1,92 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.SimplePropertyExpression; +import ch.njol.util.Math2; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Villager; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; + +@Name("Villager Level") +@Description({ + "Represents the level of a villager.", + "Level must be between 1 and 5, with 1 being the default level.", + "Do note when a villager's level is 1, they may lose their profession."}) +@Examples({ + "set {_level} to villager level of {_villager}", + "set villager level of last spawned villager to 2", + "add 1 to villager level of target entity", + "remove 1 from villager level of event-entity", + "reset villager level of event-entity" +}) +@Since("INSERT VERSION") +public class ExprVillagerLevel extends SimplePropertyExpression { + + private static final boolean HAS_INCREASE_METHOD = Skript.methodExists(Villager.class, "increaseLevel", int.class); + + static { + register(ExprVillagerLevel.class, Number.class, "villager level", "livingentities"); + } + + @Override + public @Nullable Number convert(LivingEntity from) { + if (from instanceof Villager villager) + return villager.getVillagerLevel(); + return null; + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + return switch (mode) { + case SET, ADD, REMOVE, RESET -> + CollectionUtils.array(Number.class); + default -> null; + }; + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + Number number = delta != null && delta[0] instanceof Number num ? num : 1; + int changeValue = number.intValue(); + + for (LivingEntity livingEntity : getExpr().getArray(event)) { + if (!(livingEntity instanceof Villager villager)) continue; + + int previousLevel = villager.getVillagerLevel(); + int newLevel = switch (mode) { + case SET -> changeValue; + case ADD -> previousLevel + changeValue; + case REMOVE -> previousLevel - changeValue; + default -> 1; + }; + newLevel = Math2.fit(1, newLevel, 5); + if (newLevel > previousLevel && HAS_INCREASE_METHOD) { + int increase = Math2.fit(1, newLevel - previousLevel, 5); + // According to the docs for this method: + // Increases the level of this villager. + // The villager will also unlock new recipes unlike the raw 'setVillagerLevel' method + villager.increaseLevel(increase); + } else { + villager.setVillagerLevel(newLevel); + } + } + } + + @Override + protected String getPropertyName() { + return "villager level"; + } + + @Override + public Class getReturnType() { + return Number.class; + } + +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprVillagerProfession.java b/src/main/java/ch/njol/skript/expressions/ExprVillagerProfession.java new file mode 100644 index 00000000000..65eb4bc7827 --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprVillagerProfession.java @@ -0,0 +1,66 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.SimplePropertyExpression; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Villager; +import org.bukkit.entity.Villager.Profession; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; + +@Name("Villager Profession") +@Description("Represents the profession of a villager.") +@Examples({ + "set {_p} to villager profession of event-entity", + "villager profession of event-entity = nitwit profession", + "set villager profession of {_villager} to librarian profession", + "delete villager profession of event-entity" +}) +@Since("INSERT VERSION") +public class ExprVillagerProfession extends SimplePropertyExpression { + + static { + register(ExprVillagerProfession.class, Profession.class, "villager profession", "livingentities"); + } + + @Override + public @Nullable Profession convert(LivingEntity from) { + if (from instanceof Villager villager) + return villager.getProfession(); + return null; + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + return switch (mode) { + case SET, DELETE -> CollectionUtils.array(Profession.class); + default -> null; + }; + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + Profession profession = delta != null && delta[0] instanceof Profession pro ? pro : Profession.NONE; + + for (LivingEntity livingEntity : getExpr().getArray(event)) { + if (livingEntity instanceof Villager villager) + villager.setProfession(profession); + } + } + + @Override + protected String getPropertyName() { + return "villager profession"; + } + + @Override + public Class getReturnType() { + return Profession.class; + } + +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprVillagerType.java b/src/main/java/ch/njol/skript/expressions/ExprVillagerType.java new file mode 100644 index 00000000000..f29da4972ba --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprVillagerType.java @@ -0,0 +1,66 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.SimplePropertyExpression; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Villager; +import org.bukkit.entity.Villager.Type; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; + +@Name("Villager Type") +@Description("Represents the type of a villager. This usually represents the biome the villager is from.") +@Examples({ + "set {_type} to villager type of {_villager}", + "villager type of {_villager} = plains", + "set villager type of event-entity to plains" +}) +@Since("INSERT VERSION") +public class ExprVillagerType extends SimplePropertyExpression { + + static { + register(ExprVillagerType.class, Type.class, "villager type", "livingentities"); + } + + @Override + public @Nullable Type convert(LivingEntity from) { + if (from instanceof Villager villager) + return villager.getVillagerType(); + return null; + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + if (mode == ChangeMode.SET) + return CollectionUtils.array(Type.class); + return null; + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + Type type = delta != null && delta[0] instanceof Type t ? t : null; + if (type == null) + return; + + for (LivingEntity livingEntity : getExpr().getArray(event)) { + if (livingEntity instanceof Villager villager) + villager.setVillagerType(type); + } + } + + @Override + protected String getPropertyName() { + return "villager type"; + } + + @Override + public Class getReturnType() { + return Type.class; + } + +} diff --git a/src/main/resources/lang/default.lang b/src/main/resources/lang/default.lang index 7ce573c244a..c35f69dfefc 100644 --- a/src/main/resources/lang/default.lang +++ b/src/main/resources/lang/default.lang @@ -2439,6 +2439,34 @@ item display transforms: thirdperson_lefthand: third person left handed, third person left hand, left handed in third person thirdperson_righthand: third person right handed, third person right hand, right handed in third person +# -- Villager Types/Professions -- +villager types: + snow: snow + plains: plains + jungle: jungle + taiga: taiga + desert: desert + savanna: savanna + swamp: swamp + +villager professions: + # Suffix "profession" options added to help with EntityData conflicts + leatherworker: leatherworker, leatherworker profession + mason: mason, mason profession + fletcher: fletcher, fletcher profession + weaponsmith: weaponsmith, weaponsmith profession + toolsmith: toolsmith, toolsmith profession + librarian: librarian, librarian profession + shepherd: shepherd, shepherd profession + farmer: farmer, farmer profession + cleric: cleric, cleric profession + nitwit: nitwit, nitwit profession + cartographer: cartographer, cartographer profession + armorer: armorer, armorer profession + butcher: butcher, butcher profession + none: no profession, none profession, unemployed + fisherman: fisherman, fisherman profession + # -- Change Reasons -- experience cooldown change reasons: plugin: plugin @@ -2542,6 +2570,8 @@ types: itemdisplaytransform: item display transform¦s @an experiencecooldownchangereason: experience cooldown change reason¦s @a inputkey: input key¦s @an + villagertype: villager type¦s @a + villagerprofession: villager profession¦s @a entitysnapshot: entity snapshot¦s @an loottable: loot table¦s @a lootcontext: loot context¦s @a diff --git a/src/test/skript/tests/syntaxes/expressions/ExprVillagerLevel.sk b/src/test/skript/tests/syntaxes/expressions/ExprVillagerLevel.sk new file mode 100644 index 00000000000..2884356cfe0 --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprVillagerLevel.sk @@ -0,0 +1,18 @@ +test "villager level expression": + spawn a villager at event-location: + set {_e} to entity + + assert villager level of {_e} = 1 with "Villager should start out with a level of 1" + set villager level of {_e} to 2 + assert villager level of {_e} = 2 with "Villager level should now be 2" + add 2 to villager level of {_e} + assert villager level of {_e} = 4 with "Villager level should now be 4" + add 5 to villager level of {_e} + assert villager level of {_e} = 5 with "Villager level is capped at 5, and should now be 5" + remove 2 from villager level of {_e} + assert villager level of {_e} = 3 with "Villager level should be 3 now" + reset villager level of {_e} + assert villager level of {_e} = 1 with "Villager level should reset back to 1" + + # Thank you for your service + delete entity within {_e} diff --git a/src/test/skript/tests/syntaxes/expressions/ExprVillagerProfession.sk b/src/test/skript/tests/syntaxes/expressions/ExprVillagerProfession.sk new file mode 100644 index 00000000000..71e2250d6fe --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprVillagerProfession.sk @@ -0,0 +1,14 @@ +test "villager profession expression": + spawn a librarian at event-location: + # Make sure he keeps his job + set villager level of entity to 2 + set {_e} to entity + + assert villager profession of {_e} = librarian profession with "The villager should have spawned as a librarian" + set villager profession of {_e} to nitwit profession + assert villager profession of {_e} = nitwit profession with "The villager should now be a nitwit" + delete villager profession of {_e} + assert villager profession of {_e} = no profession with "The villager should now have no profession" + + # Thank you for your service + delete entity within {_e} diff --git a/src/test/skript/tests/syntaxes/expressions/ExprVillagerType.sk b/src/test/skript/tests/syntaxes/expressions/ExprVillagerType.sk new file mode 100644 index 00000000000..ebae093a5db --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprVillagerType.sk @@ -0,0 +1,11 @@ +test "villager type expression": + spawn a villager at event-location: + set {_e} to event-entity + + set villager type of {_e} to plains + assert villager type of {_e} = plains with "The villager should now have the type plains" + set villager type of {_e} to desert + assert villager type of {_e} = desert with "The villager should now have the type desert" + + # Thank you for your service + delete entity within {_e}