From 2db12fb2ef183e0820b21caf2830a5812d36db8a Mon Sep 17 00:00:00 2001 From: PseudoKnight Date: Sun, 28 Jan 2024 06:09:13 -0800 Subject: [PATCH 1/2] Update armor stand equipment abstraction --- .../bukkit/BukkitMCEntityEquipment.java | 2 - .../bukkit/entities/BukkitMCArmorStand.java | 371 +----------------- .../abstraction/entities/MCArmorStand.java | 71 ---- .../core/functions/MobManagement.java | 37 +- 4 files changed, 26 insertions(+), 455 deletions(-) diff --git a/src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCEntityEquipment.java b/src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCEntityEquipment.java index 0a0d14b753..427aebbac7 100644 --- a/src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCEntityEquipment.java +++ b/src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCEntityEquipment.java @@ -144,8 +144,6 @@ public void setAllDropChances(Map slots) { } } - // For the purposes of faking a normal inventory, we most likely will not be accessing - // anything below this line, but they are here for flexibility and completion @Override public MCItemStack getWeapon() { return new BukkitMCItemStack(ee.getItemInMainHand()); diff --git a/src/main/java/com/laytonsmith/abstraction/bukkit/entities/BukkitMCArmorStand.java b/src/main/java/com/laytonsmith/abstraction/bukkit/entities/BukkitMCArmorStand.java index 1e20fea3d3..9ef47113c5 100644 --- a/src/main/java/com/laytonsmith/abstraction/bukkit/entities/BukkitMCArmorStand.java +++ b/src/main/java/com/laytonsmith/abstraction/bukkit/entities/BukkitMCArmorStand.java @@ -2,47 +2,26 @@ import com.laytonsmith.PureUtilities.Vector3D; import com.laytonsmith.abstraction.entities.MCArmorStand; -import com.laytonsmith.abstraction.MCEntityEquipment; -import com.laytonsmith.abstraction.MCItemStack; -import com.laytonsmith.abstraction.bukkit.BukkitMCEntityEquipment; -import com.laytonsmith.abstraction.bukkit.BukkitMCItemStack; import com.laytonsmith.abstraction.enums.MCBodyPart; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.inventory.EntityEquipment; -import org.bukkit.inventory.ItemStack; import org.bukkit.util.EulerAngle; import java.util.EnumMap; import java.util.Map; -import org.bukkit.inventory.EquipmentSlot; public class BukkitMCArmorStand extends BukkitMCLivingEntity implements MCArmorStand { ArmorStand as; - ArmorStandEquipmentProxy ase; public BukkitMCArmorStand(Entity le) { - super((LivingEntity) le); + super(le); as = (ArmorStand) le; - ase = new ArmorStandEquipmentProxy(as); - } - - /** - * LivingEntity#getEquipment returns null for ArmorStands, so we need to supply our own. Needed for - * get|set_mob_equipment. - * - * @return Custom implementation of org.bukkit.inventory.EntityEquipment - */ - @Override - public MCEntityEquipment getEquipment() { - return new BukkitMCEntityEquipment(ase); } @Override public Map getAllPoses() { - Map slots = new EnumMap(MCBodyPart.class); + Map slots = new EnumMap<>(MCBodyPart.class); for(MCBodyPart key : MCBodyPart.values()) { switch(key) { case Head: @@ -96,68 +75,6 @@ public void setAllPoses(Map posemap) { } } - @Override - public MCItemStack getItemInHand() { - return new BukkitMCItemStack(as.getItemInHand()); - } - - @Override - public void setItemInHand(MCItemStack item) { - as.setItemInHand(item == null ? null : ((BukkitMCItemStack) item).asItemStack()); - } - - @Override - public MCItemStack getBoots() { - return new BukkitMCItemStack(as.getBoots()); - } - - @Override - public void setBoots(MCItemStack item) { - if(item == null) { - as.setBoots(null); - } else { - as.setBoots(((BukkitMCItemStack) item).asItemStack()); - } - } - - @Override - public MCItemStack getLeggings() { - return new BukkitMCItemStack(as.getLeggings()); - } - - @Override - public void setLeggings(MCItemStack item) { - as.setLeggings(item == null ? null : ((BukkitMCItemStack) item).asItemStack()); - } - - @Override - public MCItemStack getChestplate() { - return new BukkitMCItemStack(as.getChestplate()); - } - - @Override - public void setChestplate(MCItemStack item) { - if(item == null) { - as.setChestplate(null); - } else { - as.setChestplate(((BukkitMCItemStack) item).asItemStack()); - } - } - - @Override - public MCItemStack getHelmet() { - return new BukkitMCItemStack(as.getHelmet()); - } - - @Override - public void setHelmet(MCItemStack item) { - if(item == null) { - as.setHelmet(null); - } else { - as.setHelmet(((BukkitMCItemStack) item).asItemStack()); - } - } - @Override public Vector3D getBodyPose() { EulerAngle pose = as.getBodyPose(); @@ -283,288 +200,4 @@ public Boolean isMarker() { public void setMarker(boolean marker) { as.setMarker(marker); } - - /** - * @author jb_aero - *

- * Custom implementation of EntityEquipment This remaps calls to EntityEquipment's methods to those of the - * associated ArmorStand - *

- * Methods related to droprates are unmodified as they do nothing, but are not needed anyway. - */ - private class ArmorStandEquipmentProxy implements EntityEquipment { - - ArmorStand holder; - - ArmorStandEquipmentProxy(ArmorStand stand) { - holder = stand; - } - - @Override - public Entity getHolder() { - return holder; - } - - @Override - @SuppressWarnings("deprecation") - public ItemStack getItemInHand() { - return holder.getItemInHand(); - } - - @Override - @SuppressWarnings("deprecation") - public void setItemInHand(ItemStack itemStack) { - holder.setItemInHand(itemStack); - } - - @Override - public ItemStack getItemInMainHand() { - return holder.getItemInHand(); - } - - @Override - public void setItemInMainHand(ItemStack itemStack) { - holder.setItemInHand(itemStack); - } - - @Override - public void setItemInMainHand(ItemStack itemStack, boolean silent) { - setItemInHand(itemStack); - } - - @Override - public ItemStack getItemInOffHand() { - return holder.getEquipment().getItemInOffHand(); - } - - @Override - public void setItemInOffHand(ItemStack itemStack) { - holder.getEquipment().setItemInOffHand(itemStack); - } - - @Override - public void setItemInOffHand(ItemStack itemStack, boolean silent) { - setItemInOffHand(itemStack); - } - - @Override - public ItemStack getHelmet() { - return holder.getHelmet(); - } - - @Override - public void setHelmet(ItemStack itemStack) { - holder.setHelmet(itemStack); - } - - @Override - public void setHelmet(ItemStack itemStack, boolean silent) { - setHelmet(itemStack); - } - - @Override - public ItemStack getChestplate() { - return holder.getChestplate(); - } - - @Override - public void setChestplate(ItemStack itemStack) { - holder.setChestplate(itemStack); - } - - @Override - public void setChestplate(ItemStack itemStack, boolean silent) { - setChestplate(itemStack); - } - - @Override - public ItemStack getLeggings() { - return holder.getLeggings(); - } - - @Override - public void setLeggings(ItemStack itemStack) { - holder.setLeggings(itemStack); - } - - @Override - public void setLeggings(ItemStack itemStack, boolean silent) { - setLeggings(itemStack); - } - - @Override - public ItemStack getBoots() { - return holder.getBoots(); - } - - @Override - public void setBoots(ItemStack itemStack) { - holder.setBoots(itemStack); - } - - @Override - public void setBoots(ItemStack itemStack, boolean silent) { - setBoots(itemStack); - } - - @Override - public ItemStack[] getArmorContents() { - return new ItemStack[]{getBoots(), getLeggings(), getChestplate(), getHelmet()}; - } - - @Override - @SuppressWarnings("checkstyle:fallthrough") - public void setArmorContents(ItemStack[] itemStacks) { - switch(itemStacks.length) { - case 4: - setHelmet(itemStacks[3]); - case 3: - setChestplate(itemStacks[2]); - case 2: - setLeggings(itemStacks[1]); - case 1: - setBoots(itemStacks[0]); - case 0: - return; - default: - setHelmet(itemStacks[3]); - setChestplate(itemStacks[2]); - setLeggings(itemStacks[1]); - setBoots(itemStacks[0]); - } - } - - @Override - public void clear() { - setHelmet(null); - setChestplate(null); - setLeggings(null); - setBoots(null); - setItemInHand(null); - setItemInOffHand(null); - } - - @Override - @SuppressWarnings("deprecation") - public float getItemInHandDropChance() { - return 0; - } - - @Override - @SuppressWarnings("deprecation") - public void setItemInHandDropChance(float v) { - - } - - @Override - public float getItemInMainHandDropChance() { - return 0; - } - - @Override - public void setItemInMainHandDropChance(float v) { - - } - - @Override - public float getItemInOffHandDropChance() { - return 0; - } - - @Override - public void setItemInOffHandDropChance(float v) { - - } - - @Override - public float getHelmetDropChance() { - return 0; - } - - @Override - public void setHelmetDropChance(float v) { - - } - - @Override - public float getChestplateDropChance() { - return 0; - } - - @Override - public void setChestplateDropChance(float v) { - - } - - @Override - public float getLeggingsDropChance() { - return 0; - } - - @Override - public void setLeggingsDropChance(float v) { - - } - - @Override - public float getBootsDropChance() { - return 0; - } - - @Override - public void setBootsDropChance(float v) { - - } - - @Override - public void setItem(EquipmentSlot es, ItemStack is) { - switch(es) { - case HEAD: - setHelmet(is); - return; - case CHEST: - setChestplate(is); - return; - case LEGS: - setLeggings(is); - return; - case FEET: - setBoots(is); - return; - case HAND: - setItemInMainHand(is); - return; - case OFF_HAND: - setItemInOffHand(is); - return; - default: - throw new UnsupportedOperationException("Missing case in ArmorStandEquipmentProxy.setItem!"); - } - } - - @Override - public void setItem(EquipmentSlot equipmentSlot, ItemStack itemStack, boolean b) { - setItem(equipmentSlot, itemStack); - } - - @Override - public ItemStack getItem(EquipmentSlot es) { - switch(es) { - case HEAD: - return getHelmet(); - case CHEST: - return getChestplate(); - case LEGS: - return getLeggings(); - case FEET: - return getBoots(); - case HAND: - return getItemInMainHand(); - case OFF_HAND: - return getItemInOffHand(); - default: - throw new UnsupportedOperationException("Missing case in ArmorStandEquipmentProxy.getItem!"); - } - } - } } diff --git a/src/main/java/com/laytonsmith/abstraction/entities/MCArmorStand.java b/src/main/java/com/laytonsmith/abstraction/entities/MCArmorStand.java index dee8c16821..b927a87331 100644 --- a/src/main/java/com/laytonsmith/abstraction/entities/MCArmorStand.java +++ b/src/main/java/com/laytonsmith/abstraction/entities/MCArmorStand.java @@ -1,7 +1,6 @@ package com.laytonsmith.abstraction.entities; import com.laytonsmith.PureUtilities.Vector3D; -import com.laytonsmith.abstraction.MCItemStack; import com.laytonsmith.abstraction.enums.MCBodyPart; import java.util.Map; @@ -21,76 +20,6 @@ public interface MCArmorStand { */ void setAllPoses(Map posemap); - /** - * Returns the item the armor stand is currently holding - * - * @return the held item - */ - MCItemStack getItemInHand(); - - /** - * Sets the item the armor stand is currently holding - * - * @param item the item to hold - */ - void setItemInHand(MCItemStack item); - - /** - * Returns the item currently being worn by the armor stand on its feet - * - * @return the worn item - */ - MCItemStack getBoots(); - - /** - * Sets the item currently being worn by the armor stand on its feet - * - * @param item the item to wear - */ - void setBoots(MCItemStack item); - - /** - * Returns the item currently being worn by the armor stand on its legs - * - * @return the worn item - */ - MCItemStack getLeggings(); - - /** - * Sets the item currently being worn by the armor stand on its legs - * - * @param item the item to wear - */ - void setLeggings(MCItemStack item); - - /** - * Returns the item currently being worn by the armor stand on its chest - * - * @return the worn item - */ - MCItemStack getChestplate(); - - /** - * Sets the item currently being worn by the armor stand on its chest - * - * @param item the item to wear - */ - void setChestplate(MCItemStack item); - - /** - * Returns the item currently being worn by the armor stand on its head - * - * @return the worn item - */ - MCItemStack getHelmet(); - - /** - * Sets the item currently being worn by the armor stand on its head - * - * @param item the item to wear - */ - void setHelmet(MCItemStack item); - /** * Returns the armor stand's body's current pose as a 3D vector of doubles. Each component is the angle for that * axis in radians. diff --git a/src/main/java/com/laytonsmith/core/functions/MobManagement.java b/src/main/java/com/laytonsmith/core/functions/MobManagement.java index 360f6e8cc5..c37f26e1ba 100644 --- a/src/main/java/com/laytonsmith/core/functions/MobManagement.java +++ b/src/main/java/com/laytonsmith/core/functions/MobManagement.java @@ -14,6 +14,7 @@ import com.laytonsmith.abstraction.blocks.MCBlock; import com.laytonsmith.abstraction.entities.MCAgeable; import com.laytonsmith.abstraction.entities.MCAnimal; +import com.laytonsmith.abstraction.entities.MCArmorStand; import com.laytonsmith.abstraction.entities.MCBreedable; import com.laytonsmith.abstraction.entities.MCTameable; import com.laytonsmith.abstraction.enums.MCAttribute; @@ -702,7 +703,7 @@ public Mixed exec(Target t, Environment environment, Mixed... args) throws Confi if(eq == null) { throw new CREBadEntityTypeException("Entities of type \"" + le.getType() + "\" do not have equipment.", t); } - Map eqmap = le.getEquipment().getAllEquipment(); + Map eqmap = eq.getAllEquipment(); CArray ret = CArray.GetAssociativeArray(t); for(MCEquipmentSlot key : eqmap.keySet()) { ret.set(key.name().toLowerCase(), ObjectGenerator.GetGenerator().item(eqmap.get(key), t), t); @@ -718,7 +719,7 @@ public String getName() { @Override public String docs() { return "array {entityUUID} Returns an associative array showing the equipment this mob is wearing." - + " This does not work on most \"dumb\" entities, only mobs (entities with AI)."; + + " This only works on mobs and armor stands."; } @Override @@ -776,8 +777,8 @@ public String getName() { @Override public String docs() { return "void {entityUUID, array} Takes an associative array with keys representing equipment slots and" - + " values of itemArrays, the same used by set_pinv. This does not work on most \"dumb\" entities," - + " only mobs (entities with AI). Unless a mod, plugin, or future update changes vanilla functionality," + + " values of itemArrays, the same used by set_pinv(). This only works on mobs and armor stands." + + " Unless a mod, plugin, or future update changes vanilla functionality," + " only humanoid mobs will render their equipment slots. The equipment slots are: " + StringUtils.Join(MCEquipmentSlot.values(), ", ", ", or ", " or "); } @@ -861,9 +862,13 @@ public static class get_equipment_droprates extends EntityManagement.EntityGette @Override public Mixed exec(Target t, Environment environment, Mixed... args) throws ConfigRuntimeException { - MCEntityEquipment eq = Static.getLivingEntity(args[0], t).getEquipment(); - if(eq.getHolder() instanceof MCPlayer) { - throw new CREBadEntityException(getName() + " does not work on players.", t); + MCLivingEntity le = Static.getLivingEntity(args[0], t); + if(le instanceof MCPlayer || le instanceof MCArmorStand) { + throw new CREBadEntityException(getName() + "() does not work on type: " + le.getType(), t); + } + MCEntityEquipment eq = le.getEquipment(); + if(eq == null) { + throw new CREBadEntityTypeException("Entities of type \"" + le.getType() + "\" do not have equipment.", t); } CArray ret = CArray.GetAssociativeArray(t); for(Map.Entry ent : eq.getAllDropChances().entrySet()) { @@ -881,7 +886,8 @@ public String getName() { public String docs() { return "array {entityUUID} Returns an associative array of the drop rate for each equipment slot." + " If the rate is 0.0, the equipment will not drop. A rate of 1.0 will guarantee a drop" - + " if the entity is killed by a player. A rate above 1.0 will guarantee a drop by any cause."; + + " if the entity is killed by a player. A rate above 1.0 will guarantee a drop by any cause." + + " Non-mobs, like players and armor stands, cannot have their drop-rates modified."; } @Override @@ -895,11 +901,15 @@ public static class set_equipment_droprates extends EntityManagement.EntitySette @Override public Mixed exec(Target t, Environment environment, Mixed... args) throws ConfigRuntimeException { - MCEntityEquipment ee = Static.getLivingEntity(args[0], t).getEquipment(); - Map eq = ee.getAllDropChances(); - if(ee.getHolder() instanceof MCPlayer) { - throw new CREBadEntityException(getName() + " does not work on players.", t); + MCLivingEntity le = Static.getLivingEntity(args[0], t); + if(le instanceof MCPlayer || le instanceof MCArmorStand) { + throw new CREBadEntityException(getName() + "() does not work on type: " + le.getType(), t); + } + MCEntityEquipment ee = le.getEquipment(); + if(ee == null) { + throw new CREBadEntityTypeException("Entities of type \"" + le.getType() + "\" do not have equipment.", t); } + Map eq = ee.getAllDropChances(); if(args[1] instanceof CNull) { for(Map.Entry ent : eq.entrySet()) { eq.put(ent.getKey(), 0F); @@ -930,7 +940,8 @@ public String docs() { return "void {entityUUID, array} Sets the drop chances for each equipment slot on a mob," + " but does not work on players. Passing null instead of an array will automatically" + " set all rates to 0.0, which will cause nothing to drop. A rate of 1.0 will guarantee a drop" - + " if the entity is killed by a player. A rate above 1.0 will guarantee a drop by any cause."; + + " if the entity is killed by a player. A rate above 1.0 will guarantee a drop by any cause." + + " Non-mobs, like players and armor stands, cannot have their drop-rates modified."; } @Override From d10e11798fe38ffa6cc646e2ab6952a58d945f8f Mon Sep 17 00:00:00 2001 From: PseudoKnight Date: Sun, 28 Jan 2024 06:11:06 -0800 Subject: [PATCH 2/2] Add pforce_respawn() --- .../com/laytonsmith/abstraction/MCPlayer.java | 2 + .../bukkit/entities/BukkitMCPlayer.java | 5 ++ .../core/functions/PlayerManagement.java | 52 +++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/src/main/java/com/laytonsmith/abstraction/MCPlayer.java b/src/main/java/com/laytonsmith/abstraction/MCPlayer.java index 5695fd9306..a117e6932b 100644 --- a/src/main/java/com/laytonsmith/abstraction/MCPlayer.java +++ b/src/main/java/com/laytonsmith/abstraction/MCPlayer.java @@ -195,4 +195,6 @@ public interface MCPlayer extends MCCommandSender, MCHumanEntity, MCOfflinePlaye void setWorldBorder(MCWorldBorder border); String getLocale(); + + void respawn(); } diff --git a/src/main/java/com/laytonsmith/abstraction/bukkit/entities/BukkitMCPlayer.java b/src/main/java/com/laytonsmith/abstraction/bukkit/entities/BukkitMCPlayer.java index 30a0e5b209..49f6161680 100644 --- a/src/main/java/com/laytonsmith/abstraction/bukkit/entities/BukkitMCPlayer.java +++ b/src/main/java/com/laytonsmith/abstraction/bukkit/entities/BukkitMCPlayer.java @@ -759,4 +759,9 @@ public MCScoreboard getScoreboard() { public void setScoreboard(MCScoreboard board) { p.setScoreboard(((BukkitMCScoreboard) board)._scoreboard()); } + + @Override + public void respawn() { + p.spigot().respawn(); + } } diff --git a/src/main/java/com/laytonsmith/core/functions/PlayerManagement.java b/src/main/java/com/laytonsmith/core/functions/PlayerManagement.java index cbbb7c7f07..10e5ca48a0 100644 --- a/src/main/java/com/laytonsmith/core/functions/PlayerManagement.java +++ b/src/main/java/com/laytonsmith/core/functions/PlayerManagement.java @@ -6835,4 +6835,56 @@ public Boolean runAsync() { return false; } } + + @api + public static class pforce_respawn extends AbstractFunction { + + @Override + public String getName() { + return "pforce_respawn"; + } + + @Override + public String docs() { + return "void {[player]} Forces a player to respawn immediately if they're currently dead."; + } + + @Override + public Integer[] numArgs() { + return new Integer[]{0, 1}; + } + + @Override + public Mixed exec(Target t, Environment env, Mixed... args) throws ConfigRuntimeException { + MCPlayer p; + if(args.length == 0) { + p = env.getEnv(CommandHelperEnvironment.class).GetPlayer(); + Static.AssertPlayerNonNull(p, t); + } else { + p = Static.GetPlayer(args[0], t); + } + p.respawn(); + return CVoid.VOID; + } + + @Override + public Class[] thrown() { + return new Class[]{CREPlayerOfflineException.class, CRELengthException.class}; + } + + @Override + public Version since() { + return MSVersion.V3_3_5; + } + + @Override + public boolean isRestricted() { + return true; + } + + @Override + public Boolean runAsync() { + return false; + } + } }