diff --git a/README.md b/README.md index 034e04c..9c49451 100644 --- a/README.md +++ b/README.md @@ -24,12 +24,16 @@ Dead bodies in minecraft for 1.8-1.21.11 servers. - `render-armor` – Render armor/items on the corpse. - `corpse-distance` – Max blocks at which corpses are visible. - `lootable-corpses` – Right‑click to open inventory and loot. +- `entity-pose` – Pose used for the corpse entity (`SLEEPING` or `SWIMMING`). ## API Add the dependency (e.g. JitPack) and use the **builder API** via `Corpse.fromPlayer()` or `Corpse.fromLocation()`: ```java +import com.github.unldenis.corpse.corpse.Corpse; +import com.github.unldenis.corpse.model.CorpseArmor; + // At player location, with their skin and armor Corpse corpse = Corpse.fromPlayer(player).spawn(); @@ -37,10 +41,10 @@ Corpse corpse = Corpse.fromPlayer(player).spawn(); Corpse corpse = Corpse.fromPlayer(player).location(location).spawn(); Corpse corpse = Corpse.fromLocation(location).name(offlinePlayer.getName()).spawn(); -// Custom armor (array order: boots, leggings, chestplate, helmet) -ItemStack[] armor = new ItemStack[]{boots, leggings, chestPlate, helmet}; -Corpse corpse = Corpse.fromPlayer(player).location(location).armorContents(armor).spawn(); -Corpse corpse = Corpse.fromLocation(location).name(name).armorContents(armor).spawn(); +// Custom armor (use CorpseArmor) +CorpseArmor armor = new CorpseArmor().boots(boots).leggings(leggings).chestplate(chestplate).helmet(helmet); +Corpse corpse = Corpse.fromPlayer(player).location(location).armor(armor).spawn(); +Corpse corpse = Corpse.fromLocation(location).name(name).armor(armor).spawn(); // Remove a corpse corpse.destroy(); diff --git a/src/main/java/com/github/unldenis/corpse/CorpsePlugin.java b/src/main/java/com/github/unldenis/corpse/CorpsePlugin.java index e155094..f460724 100644 --- a/src/main/java/com/github/unldenis/corpse/CorpsePlugin.java +++ b/src/main/java/com/github/unldenis/corpse/CorpsePlugin.java @@ -26,10 +26,11 @@ import com.github.retrooper.packetevents.settings.PacketEventsSettings; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity; import com.github.unldenis.corpse.command.*; -import com.github.unldenis.corpse.data.*; +import com.github.unldenis.corpse.config.*; import com.github.unldenis.corpse.corpse.*; import com.github.unldenis.corpse.event.AsyncCorpseInteractEvent; -import com.github.unldenis.corpse.manager.*; +import com.github.unldenis.corpse.pool.*; + import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; import org.bukkit.Bukkit; import org.bukkit.configuration.file.*; diff --git a/src/main/java/com/github/unldenis/corpse/command/RemoveCorpseCommand.java b/src/main/java/com/github/unldenis/corpse/command/RemoveCorpseCommand.java index 60347eb..c6b107e 100644 --- a/src/main/java/com/github/unldenis/corpse/command/RemoveCorpseCommand.java +++ b/src/main/java/com/github/unldenis/corpse/command/RemoveCorpseCommand.java @@ -19,7 +19,8 @@ package com.github.unldenis.corpse.command; import com.github.unldenis.corpse.corpse.Corpse; -import com.github.unldenis.corpse.manager.*; +import com.github.unldenis.corpse.pool.*; + import org.bukkit.*; import org.bukkit.command.*; import org.bukkit.entity.*; diff --git a/src/main/java/com/github/unldenis/corpse/data/DataManager.java b/src/main/java/com/github/unldenis/corpse/config/DataManager.java similarity index 98% rename from src/main/java/com/github/unldenis/corpse/data/DataManager.java rename to src/main/java/com/github/unldenis/corpse/config/DataManager.java index 61c4213..308636e 100644 --- a/src/main/java/com/github/unldenis/corpse/data/DataManager.java +++ b/src/main/java/com/github/unldenis/corpse/config/DataManager.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.github.unldenis.corpse.data; +package com.github.unldenis.corpse.config; import org.bukkit.configuration.Configuration; import org.bukkit.configuration.file.FileConfiguration; diff --git a/src/main/java/com/github/unldenis/corpse/corpse/Corpse.java b/src/main/java/com/github/unldenis/corpse/corpse/Corpse.java index 8c621a3..4c9f642 100644 --- a/src/main/java/com/github/unldenis/corpse/corpse/Corpse.java +++ b/src/main/java/com/github/unldenis/corpse/corpse/Corpse.java @@ -30,7 +30,8 @@ import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerTeams; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUseBed; import com.github.unldenis.corpse.CorpsePlugin; -import com.github.unldenis.corpse.manager.CorpsePool; +import com.github.unldenis.corpse.model.CorpseArmor; +import com.github.unldenis.corpse.pool.CorpsePool; import com.github.unldenis.corpse.util.BedUtil; import com.github.unldenis.corpse.util.ProfileUtils; import io.github.retrooper.packetevents.util.SpigotConversionUtil; @@ -83,7 +84,7 @@ public static CorpseBuilder fromLocation(@NotNull Location location) { Corpse( @NotNull Location location, @NotNull List textures, - @Nullable ItemStack[] armorContents, + @Nullable CorpseArmor armor, @Nullable String name ) { pool = CorpsePool.getInstance(); @@ -92,20 +93,16 @@ public static CorpseBuilder fromLocation(@NotNull Location location) { this.location = location; this.profile = new UserProfile(UUID.randomUUID(), name != null ? name : ProfileUtils.randomName(), textures); + // create npc internalNPC = new CorpseNPC(profile, id, pool.isShowTags() ? null : WrapperPlayServerTeams.NameTagVisibility.NEVER); + // set npc location internalNPC.setLocation(SpigotConversionUtil.fromBukkitLocation(location)); - if (pool.isRenderArmor() && armorContents != null) { - if (armorContents[0] != null) - internalNPC.setBoots(SpigotConversionUtil.fromBukkitItemStack(armorContents[0])); - if (armorContents[1] != null) - internalNPC.setLeggings(SpigotConversionUtil.fromBukkitItemStack(armorContents[1])); - if (armorContents[2] != null) - internalNPC.setChestplate(SpigotConversionUtil.fromBukkitItemStack(armorContents[2])); - if (armorContents[3] != null) - internalNPC.setHelmet(SpigotConversionUtil.fromBukkitItemStack(armorContents[3])); + // set npc armor + if (pool.isRenderArmor() && armor != null) { + this.setArmor(armor); hasArmor = true; } else { hasArmor = false; @@ -148,7 +145,7 @@ public void show(@NotNull Player player) { } else { List> entityData = new ArrayList<>(); - entityData.add(new EntityData<>(6, EntityDataTypes.ENTITY_POSE, EntityPose.SLEEPING)); + entityData.add(new EntityData<>(6, EntityDataTypes.ENTITY_POSE, pool.getEntityPose())); WrapperPlayServerEntityMetadata packet = new WrapperPlayServerEntityMetadata(id, entityData); PacketEvents.getAPI().getProtocolManager().sendPacket(channel, packet); } @@ -181,23 +178,53 @@ public void destroy() { CorpsePool.getInstance().remove(this.id); } + /** + * Gets the entity id of the corpse. + * @return The entity id of the corpse. + */ public int getId() { return id; } + /** + * Gets the name of the corpse. + * @return The name of the corpse. + */ @NotNull public String getName() { return profile.getName(); } + /** + * Gets the location of the corpse. + * @return The location of the corpse. + */ @NotNull public Location getLocation() { return location; } + /** + * Gets the players that are seeing the corpse. + * @return The players that are seeing the corpse. + */ @NotNull public Collection getSeeingPlayers() { return Collections.unmodifiableCollection(this.seeingPlayers); } + /** + * Sets the armor of the corpse. + * @param armor The armor to set. + */ + private void setArmor(@NotNull CorpseArmor armor) { + if (armor.getBoots() != null) + internalNPC.setBoots(SpigotConversionUtil.fromBukkitItemStack(armor.getBoots())); + if (armor.getLeggings() != null) + internalNPC.setLeggings(SpigotConversionUtil.fromBukkitItemStack(armor.getLeggings())); + if (armor.getChestplate() != null) + internalNPC.setChestplate(SpigotConversionUtil.fromBukkitItemStack(armor.getChestplate())); + if (armor.getHelmet() != null) + internalNPC.setHelmet(SpigotConversionUtil.fromBukkitItemStack(armor.getHelmet())); + } } diff --git a/src/main/java/com/github/unldenis/corpse/corpse/CorpseBuilder.java b/src/main/java/com/github/unldenis/corpse/corpse/CorpseBuilder.java index bf7d930..b542bcc 100644 --- a/src/main/java/com/github/unldenis/corpse/corpse/CorpseBuilder.java +++ b/src/main/java/com/github/unldenis/corpse/corpse/CorpseBuilder.java @@ -10,9 +10,10 @@ import java.util.ArrayList; import java.util.List; -import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import com.github.unldenis.corpse.model.CorpseArmor; + /** * Builder for creating a Corpse object. */ @@ -20,7 +21,7 @@ public class CorpseBuilder { private Location location; private List textures = new ArrayList<>(); - private ItemStack[] armorContents = null; + private CorpseArmor armor = null; private String name = null; /** @@ -30,7 +31,7 @@ public class CorpseBuilder { CorpseBuilder(@NotNull Player player) { this.location = player.getLocation(); this.textures = SpigotReflectionUtil.getUserProfile(player); - this.armorContents = player.getInventory().getArmorContents(); + this.armor = new CorpseArmor(player); this.name = player.getName(); } @@ -63,12 +64,12 @@ public CorpseBuilder textures(@NotNull List textures) { } /** - * Set the armor of the corpse. Order: boots, leggings, chestplate, helmet. - * @param armorContents The armor contents to set. + * Set the armor of the corpse. + * @param armor The armor to set. * @return This builder. */ - public CorpseBuilder armorContents(@NotNull ItemStack[] armorContents) { - this.armorContents = armorContents; + public CorpseBuilder armor(@NotNull CorpseArmor armor) { + this.armor = armor; return this; } @@ -87,6 +88,6 @@ public CorpseBuilder name(@NotNull String name) { * @return The spawned Corpse instance. */ public Corpse spawn() { - return new Corpse(location, textures, armorContents, name); + return new Corpse(location, textures, armor, name); } } diff --git a/src/main/java/com/github/unldenis/corpse/model/CorpseArmor.java b/src/main/java/com/github/unldenis/corpse/model/CorpseArmor.java new file mode 100644 index 0000000..a15bd14 --- /dev/null +++ b/src/main/java/com/github/unldenis/corpse/model/CorpseArmor.java @@ -0,0 +1,111 @@ +package com.github.unldenis.corpse.model; + +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +import org.bukkit.entity.Player; + +/** + * Represents the armor of a corpse. + */ +public class CorpseArmor { + + public static final CorpseArmor EMPTY = new CorpseArmor(); + + + private ItemStack boots; + private ItemStack leggings; + private ItemStack chestplate; + private ItemStack helmet; + + /** + * Creates a new CorpseArmor. + * @return A new CorpseArmor. + */ + public CorpseArmor() {} + + /** + * Creates a new CorpseArmor from a player. + * @param player The player to create the CorpseArmor for. + * @return A new CorpseArmor. + */ + public CorpseArmor(@NotNull Player player) { + ItemStack[] armorContents = player.getInventory().getArmorContents(); + this.boots = armorContents[0]; + this.leggings = armorContents[1]; + this.chestplate = armorContents[2]; + this.helmet = armorContents[3]; + } + + /** + * Sets the boots of the armor. + * @param boots The boots item stack. + * @return This armor. + */ + public CorpseArmor boots(@NotNull ItemStack boots) { + this.boots = boots; + return this; + } + + /** + * Sets the leggings of the armor. + * @param leggings The leggings item stack. + * @return This armor. + */ + public CorpseArmor leggings(@NotNull ItemStack leggings) { + this.leggings = leggings; + return this; + } + + /** + * Sets the chestplate of the armor. + * @param chestplate The chestplate item stack. + * @return This armor. + */ + public CorpseArmor chestplate(@NotNull ItemStack chestplate) { + this.chestplate = chestplate; + return this; + } + + /** + * Sets the helmet of the armor. + * @param helmet The helmet item stack. + * @return This armor. + */ + public CorpseArmor helmet(@NotNull ItemStack helmet) { + this.helmet = helmet; + return this; + } + + /** + * Gets the boots of the armor. + * @return The boots item stack. + */ + public ItemStack getBoots() { + return boots; + } + + /** + * Gets the leggings of the armor. + * @return The leggings item stack. + */ + public ItemStack getLeggings() { + return leggings; + } + + /** + * Gets the chestplate of the armor. + * @return The chestplate item stack. + */ + public ItemStack getChestplate() { + return chestplate; + } + + /** + * Gets the helmet of the armor. + * @return The helmet item stack. + */ + public ItemStack getHelmet() { + return helmet; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/unldenis/corpse/manager/CorpsePool.java b/src/main/java/com/github/unldenis/corpse/pool/CorpsePool.java similarity index 93% rename from src/main/java/com/github/unldenis/corpse/manager/CorpsePool.java rename to src/main/java/com/github/unldenis/corpse/pool/CorpsePool.java index 468acc1..5c02514 100644 --- a/src/main/java/com/github/unldenis/corpse/manager/CorpsePool.java +++ b/src/main/java/com/github/unldenis/corpse/pool/CorpsePool.java @@ -16,8 +16,9 @@ * along with this program. If not, see . */ -package com.github.unldenis.corpse.manager; +package com.github.unldenis.corpse.pool; +import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity; import com.github.unldenis.corpse.*; import com.github.unldenis.corpse.corpse.*; @@ -49,7 +50,8 @@ public class CorpsePool implements Listener { private final boolean showTags; private final boolean renderArmor; private final boolean lootableCorpses; - + private final EntityPose entityPose; + private final Map corpseMap = new ConcurrentHashMap<>(); private BukkitTask tickTask; @@ -66,6 +68,14 @@ private CorpsePool() { this.renderArmor = config.getBoolean("render-armor"); this.lootableCorpses = config.getBoolean("lootable-corpses"); + // get entity pose + String entityPoseString = config.getString("entity-pose"); + if (entityPoseString == null) { + this.entityPose = EntityPose.SLEEPING; + } else { + this.entityPose = EntityPose.valueOf(entityPoseString.toUpperCase()); + } + Bukkit.getPluginManager().registerEvents(this, plugin); this.corpseTick(); } @@ -178,6 +188,10 @@ public boolean isShowTags() { return showTags; } + public EntityPose getEntityPose() { + return entityPose; + } + @Nullable public BukkitTask getTickTask() { return tickTask; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 2ddc94d..e65cd92 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -14,4 +14,8 @@ render-armor: true corpse-distance: 60 ## Lootable corpses -lootable-corpses: true \ No newline at end of file +lootable-corpses: true + +## Entity Pose to use for the corpses. +## Possible values: SLEEPING, SWIMMING +entity-pose: "SLEEPING" \ No newline at end of file