From 3385a2429ad4960764e57250047cb7dbb6979092 Mon Sep 17 00:00:00 2001 From: PseudoKnight Date: Sat, 18 May 2024 04:53:51 -0700 Subject: [PATCH] Add psend_equipment() --- .../com/laytonsmith/abstraction/MCPlayer.java | 3 + .../bukkit/entities/BukkitMCPlayer.java | 32 ++++++ .../core/functions/PlayerManagement.java | 97 +++++++++++++++++-- 3 files changed, 124 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/laytonsmith/abstraction/MCPlayer.java b/src/main/java/com/laytonsmith/abstraction/MCPlayer.java index 55c0e2d7e..09e110bbc 100644 --- a/src/main/java/com/laytonsmith/abstraction/MCPlayer.java +++ b/src/main/java/com/laytonsmith/abstraction/MCPlayer.java @@ -4,6 +4,7 @@ import com.laytonsmith.abstraction.blocks.MCMaterial; import com.laytonsmith.abstraction.blocks.MCSign; import com.laytonsmith.abstraction.enums.MCEntityType; +import com.laytonsmith.abstraction.enums.MCEquipmentSlot; import com.laytonsmith.abstraction.enums.MCInstrument; import com.laytonsmith.abstraction.enums.MCParticle; import com.laytonsmith.abstraction.enums.MCPlayerStatistic; @@ -209,4 +210,6 @@ public interface MCPlayer extends MCCommandSender, MCHumanEntity, MCOfflinePlaye String getLocale(); void respawn(); + + void sendEquipmentChange(MCLivingEntity entity, MCEquipmentSlot slot, MCItemStack item); } 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 50d5ef435..412cf1220 100644 --- a/src/main/java/com/laytonsmith/abstraction/bukkit/entities/BukkitMCPlayer.java +++ b/src/main/java/com/laytonsmith/abstraction/bukkit/entities/BukkitMCPlayer.java @@ -4,6 +4,7 @@ import com.laytonsmith.abstraction.MCCommandSender; import com.laytonsmith.abstraction.MCEntity; import com.laytonsmith.abstraction.MCItemStack; +import com.laytonsmith.abstraction.MCLivingEntity; import com.laytonsmith.abstraction.MCLocation; import com.laytonsmith.abstraction.MCNote; import com.laytonsmith.abstraction.MCOfflinePlayer; @@ -23,6 +24,7 @@ import com.laytonsmith.abstraction.bukkit.BukkitMCServer; import com.laytonsmith.abstraction.bukkit.BukkitMCWorldBorder; import com.laytonsmith.abstraction.enums.MCEntityType; +import com.laytonsmith.abstraction.enums.MCEquipmentSlot; import com.laytonsmith.abstraction.enums.MCInstrument; import com.laytonsmith.abstraction.enums.MCParticle; import com.laytonsmith.abstraction.enums.MCPlayerStatistic; @@ -49,7 +51,9 @@ import org.bukkit.block.data.BlockData; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; +import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; +import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.bukkit.permissions.PermissionAttachmentInfo; import org.bukkit.potion.PotionEffect; @@ -816,4 +820,32 @@ public void setScoreboard(MCScoreboard board) { public void respawn() { p.spigot().respawn(); } + + @Override + public void sendEquipmentChange(MCLivingEntity entity, MCEquipmentSlot slot, MCItemStack item) { + LivingEntity le = (LivingEntity) entity.getHandle(); + ItemStack is; + if(item == null) { + if(Static.getServer().getMinecraftVersion().lt(MCVersion.MC1_19_3)) { + // null isn't supported prior to 1.19.3 + is = new ItemStack(Material.AIR); + } else { + is = null; + } + } else { + is = (ItemStack) item.getHandle(); + } + try { + switch(slot) { + case WEAPON -> p.sendEquipmentChange(le, EquipmentSlot.HAND, is); + case OFF_HAND -> p.sendEquipmentChange(le, EquipmentSlot.OFF_HAND, is); + case BOOTS -> p.sendEquipmentChange(le, EquipmentSlot.FEET, is); + case LEGGINGS -> p.sendEquipmentChange(le, EquipmentSlot.LEGS, is); + case CHESTPLATE -> p.sendEquipmentChange(le, EquipmentSlot.CHEST, is); + case HELMET -> p.sendEquipmentChange(le, EquipmentSlot.HEAD, is); + } + } catch(NoSuchMethodError ex) { + // probably before 1.18, which is unsupported + } + } } diff --git a/src/main/java/com/laytonsmith/core/functions/PlayerManagement.java b/src/main/java/com/laytonsmith/core/functions/PlayerManagement.java index 26ceafb09..75b17bdd1 100644 --- a/src/main/java/com/laytonsmith/core/functions/PlayerManagement.java +++ b/src/main/java/com/laytonsmith/core/functions/PlayerManagement.java @@ -9,6 +9,7 @@ import com.laytonsmith.abstraction.MCEntity; import com.laytonsmith.abstraction.MCHumanEntity; import com.laytonsmith.abstraction.MCItemStack; +import com.laytonsmith.abstraction.MCLivingEntity; import com.laytonsmith.abstraction.MCLocation; import com.laytonsmith.abstraction.MCNamespacedKey; import com.laytonsmith.abstraction.MCOfflinePlayer; @@ -25,6 +26,7 @@ import com.laytonsmith.abstraction.entities.MCCommandMinecart; import com.laytonsmith.abstraction.enums.MCDyeColor; import com.laytonsmith.abstraction.enums.MCEntityType; +import com.laytonsmith.abstraction.enums.MCEquipmentSlot; import com.laytonsmith.abstraction.enums.MCGameMode; import com.laytonsmith.abstraction.enums.MCPlayerStatistic; import com.laytonsmith.abstraction.enums.MCPotionEffectType; @@ -2233,7 +2235,7 @@ public Integer[] numArgs() { @Override public String docs() { - return "boolean {player, potionEffect, [strength], [seconds], [ambient], [particles]}" + return "boolean {player, potionEffect, [strength], [seconds], [ambient], [particles], [icon]}" + " Adds one, or modifies an existing, potion effect on a mob." + " The potionEffect can be " + StringUtils.Join(MCPotionEffectType.types(), ", ", ", or ", " or ") + ". It also accepts an integer corresponding to the effect id listed on the Minecraft wiki." @@ -2243,6 +2245,7 @@ public String docs() { + " Negative seconds makes the effect infinite. (or max in versions prior to 1.19.4)" + " Ambient takes a boolean of whether the particles should be more transparent." + " Particles takes a boolean of whether the particles should be visible at all." + + " Icon argument takes a boolean of whether the effect icon should be displayed." + " The function returns whether or not the effect was modified."; } @@ -6710,7 +6713,7 @@ public Version since() { } } - @api + @api(environments = {CommandHelperEnvironment.class}) public static class plocale extends AbstractFunction { @Override @@ -6761,7 +6764,7 @@ public Boolean runAsync() { } } - @api + @api(environments = {CommandHelperEnvironment.class}) public static class phas_recipe extends AbstractFunction { @Override @@ -6819,7 +6822,7 @@ public Boolean runAsync() { } } - @api + @api(environments = {CommandHelperEnvironment.class}) public static class pgive_recipe extends AbstractFunction { @Override @@ -6892,7 +6895,7 @@ public Boolean runAsync() { } } - @api + @api(environments = {CommandHelperEnvironment.class}) public static class pforce_respawn extends AbstractFunction { @Override @@ -6944,7 +6947,7 @@ public Boolean runAsync() { } } - @api + @api(environments = {CommandHelperEnvironment.class}) public static class phide_entity extends AbstractFunction { @Override @@ -7001,7 +7004,7 @@ public Boolean runAsync() { } } - @api + @api(environments = {CommandHelperEnvironment.class}) public static class pshow_entity extends AbstractFunction { @Override @@ -7056,7 +7059,7 @@ public Boolean runAsync() { } } - @api + @api(environments = {CommandHelperEnvironment.class}) public static class pcan_see_entity extends AbstractFunction { @Override @@ -7110,4 +7113,82 @@ public Boolean runAsync() { return false; } } + + @api(environments = {CommandHelperEnvironment.class}) + public static class psend_equipment extends AbstractFunction { + + @Override + public String getName() { + return "psend_equipment"; + } + + @Override + public String docs() { + return "void {[player], entityUUID, equipmentArray} Changes a living entity's equipment only for the" + + " specified player. (MC 1.18+) Equipment array can be null to make all equipment not visible." + + " Otherwise equipment array must be an associative array where the keys are equipment slots and" + + " the values are item arrays or null. The equipment slots are: " + + StringUtils.Join(MCEquipmentSlot.values(), ", ", ", or ", " or "); + } + + @Override + public Integer[] numArgs() { + return new Integer[]{2, 3}; + } + + @Override + public Mixed exec(Target t, Environment env, Mixed... args) throws ConfigRuntimeException { + MCPlayer p; + MCLivingEntity le; + Mixed equipment; + if(args.length == 2) { + p = env.getEnv(CommandHelperEnvironment.class).GetPlayer(); + Static.AssertPlayerNonNull(p, t); + le = Static.getLivingEntity(args[0], t); + equipment = args[1]; + } else { + p = Static.GetPlayer(args[0], t); + le = Static.getLivingEntity(args[1], t); + equipment = args[2]; + } + if(equipment instanceof CNull) { + for(MCEquipmentSlot slot : MCEquipmentSlot.values()) { + p.sendEquipmentChange(le, slot, null); + } + } else if(equipment.isInstanceOf(CArray.TYPE)) { + CArray ea = (CArray) equipment; + for(String key : ea.stringKeySet()) { + try { + p.sendEquipmentChange(le, MCEquipmentSlot.valueOf(key.toUpperCase()), + ObjectGenerator.GetGenerator().item(ea.get(key, t), t)); + } catch (IllegalArgumentException iae) { + throw new CREFormatException("Not an equipment slot: " + key, t); + } + } + } else { + throw new CREFormatException("Expected last argument to be an array or null", t); + } + return CVoid.VOID; + } + + @Override + public Class[] thrown() { + return new Class[]{CREPlayerOfflineException.class, CRELengthException.class, CREBadEntityException.class}; + } + + @Override + public Version since() { + return MSVersion.V3_3_5; + } + + @Override + public boolean isRestricted() { + return true; + } + + @Override + public Boolean runAsync() { + return false; + } + } }