From ad1535c18e15a90f82c53b99956df197dacc7be5 Mon Sep 17 00:00:00 2001 From: unldenis Date: Fri, 30 Jan 2026 05:57:13 +0100 Subject: [PATCH 1/2] add CorpseBuilder api --- README.md | 23 ++- .../github/unldenis/corpse/api/CorpseAPI.java | 149 ------------------ .../corpse/command/RemoveCorpseCommand.java | 1 - .../corpse/command/SpawnCorpseCommand.java | 7 +- .../github/unldenis/corpse/corpse/Corpse.java | 48 ++++-- .../unldenis/corpse/corpse/CorpseBuilder.java | 92 +++++++++++ .../unldenis/corpse/manager/CorpsePool.java | 2 +- 7 files changed, 138 insertions(+), 184 deletions(-) delete mode 100644 src/main/java/com/github/unldenis/corpse/api/CorpseAPI.java create mode 100644 src/main/java/com/github/unldenis/corpse/corpse/CorpseBuilder.java diff --git a/README.md b/README.md index 2effa18..45e6e3a 100644 --- a/README.md +++ b/README.md @@ -27,24 +27,23 @@ Dead bodies in minecraft for 1.8-1.21.11 servers. ## API -Add the dependency (e.g. JitPack) and use `CorpseAPI.getInstance()`: +Add the dependency (e.g. JitPack) and use the **builder API** via `Corpse.fromPlayer()` or `Corpse.fromLocation()`: ```java -CorpseAPI api = CorpseAPI.getInstance(); - -// At player location, with their skin and inventory -Corpse corpse = api.spawnCorpse(player); +// At player location, with their skin and armor +Corpse corpse = Corpse.fromPlayer(player).spawn(); // At a specific location -Corpse corpse = api.spawnCorpse(player, location); -Corpse corpse = api.spawnCorpse(offlinePlayer, location); +Corpse corpse = Corpse.fromPlayer(player).location(location).spawn(); +Corpse corpse = Corpse.fromLocation(location).name(offlinePlayer.getName()).spawn(); -// Custom armor (player/offline + location + helmet, chestplate, leggings, boots) -Corpse corpse = api.spawnCorpse(player, location, helmet, chestPlate, leggings, boots); -Corpse corpse = api.spawnCorpse(offlinePlayer, location, helmet, chestPlate, leggings, boots); +// 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(); // Remove a corpse -api.removeCorpse(corpse); +corpse.destroy(); ``` -Listen for right‑clicks (and attack) on corpses via `AsyncCorpseInteractEvent`; use `getAction()` to tell interact vs attack. +The builder also supports `.textures(List)` for custom skins. Listen for right‑clicks and attacks on corpses via `AsyncCorpseInteractEvent`; use `getAction()` to distinguish interact vs attack. diff --git a/src/main/java/com/github/unldenis/corpse/api/CorpseAPI.java b/src/main/java/com/github/unldenis/corpse/api/CorpseAPI.java deleted file mode 100644 index 6ed50de..0000000 --- a/src/main/java/com/github/unldenis/corpse/api/CorpseAPI.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Corpse - Dead bodies in bukkit - * Copyright (C) unldenis - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.github.unldenis.corpse.api; - -import com.github.unldenis.corpse.corpse.*; -import com.github.unldenis.corpse.manager.*; -import io.github.retrooper.packetevents.util.SpigotReflectionUtil; -import org.apache.commons.lang.*; -import org.bukkit.*; -import org.bukkit.entity.*; -import org.bukkit.inventory.*; -import org.jetbrains.annotations.*; - -public class CorpseAPI { - - private static CorpseAPI instance; - - public CorpseAPI() { - throw new IllegalArgumentException(); - } - - private CorpseAPI(Object dummy) { - } - - /** - * Class method that allows you to use the API. - * - * @return an instance of this class - */ - @NotNull - public static synchronized CorpseAPI getInstance() { - if (instance == null) { - instance = new CorpseAPI(null); - } - return instance; - } - - /** - * Method that creates a corpse in the player's position and with its skin and inventory - * - * @return a new Corpse object - */ - public Corpse spawnCorpse(@NotNull Player player) { - Validate.notNull(player, "Player cannot be null"); - return new Corpse(player); - } - - /** - * Method that creates a corpse in the given place and with the skin, name and inventory of the - * player - * - * @param location The location where to spawn the corpse - * @return a new Corpse object - */ - public Corpse spawnCorpse(@NotNull Player player, @NotNull Location location) { - Validate.notNull(player, "Player cannot be null"); - Validate.notNull(location, "Spawn location cannot be null"); - return new Corpse(location, player, null); - } - - /** - * Method that creates a corpse in the given place and with the skin and name of the - * offlinePlayer - * - * @param location The location where to spawn the corpse - * @return a new Corpse object - */ - public Corpse spawnCorpse(@NotNull OfflinePlayer offlinePlayer, @NotNull Location location) { - Validate.notNull(offlinePlayer, "OfflinePlayer cannot be null"); - Validate.notNull(location, "Spawn location cannot be null"); - return new Corpse(location, offlinePlayer, null); - } - - /** - * Method that creates a corpse in the given place and with the skin and name of the player with a - * custom inventory. - * - * @param location The location where to spawn the corpse - * @param helmet The helmet to put on the corpse - * @param chestPlate The chestPlate to put on the corpse - * @param leggings The leggings to put on the corpse - * @param boots The boots to put on the corpse - * @return a new Corpse object - */ - public Corpse spawnCorpse( - @NotNull Player player, - @NotNull Location location, - @Nullable ItemStack helmet, - @Nullable ItemStack chestPlate, - @Nullable ItemStack leggings, - @Nullable ItemStack boots - ) { - Validate.notNull(player, "Player cannot be null"); - Validate.notNull(location, "Spawn location cannot be null"); - return new Corpse(location, SpigotReflectionUtil.getUserProfile(player), - new ItemStack[]{boots, leggings, chestPlate, helmet}, player.getName()); - } - - /** - * Method that creates a corpse in the given place and with the skin and name of the offlinePlayer - * with a custom inventory. - * - * @param location The location where to spawn the corpse - * @param helmet The helmet to put on the corpse - * @param chestPlate The chestPlate to put on the corpse - * @param leggings The leggings to put on the corpse - * @param boots The boots to put on the corpse - * @return a new Corpse object - */ - public Corpse spawnCorpse( - @NotNull OfflinePlayer offlinePlayer, - @NotNull Location location, - @Nullable ItemStack helmet, - @Nullable ItemStack chestPlate, - @Nullable ItemStack leggings, - @Nullable ItemStack boots - ) { - Validate.notNull(offlinePlayer, "OfflinePlayer cannot be null"); - Validate.notNull(location, "Spawn location cannot be null"); - return new Corpse(location, offlinePlayer, - new ItemStack[]{boots, leggings, chestPlate, helmet}); - } - - /** - * Method that removes a corpse - * - * @param corpse The corpse to be removed - */ - public void removeCorpse(@NotNull Corpse corpse) { - Validate.notNull(corpse, "Corpse cannot be null"); - CorpsePool.getInstance().remove(corpse.getId()); - } -} 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 165e8dc..60347eb 100644 --- a/src/main/java/com/github/unldenis/corpse/command/RemoveCorpseCommand.java +++ b/src/main/java/com/github/unldenis/corpse/command/RemoveCorpseCommand.java @@ -25,7 +25,6 @@ import org.bukkit.entity.*; import org.jetbrains.annotations.*; -import java.util.concurrent.atomic.*; public class RemoveCorpseCommand implements CommandExecutor { diff --git a/src/main/java/com/github/unldenis/corpse/command/SpawnCorpseCommand.java b/src/main/java/com/github/unldenis/corpse/command/SpawnCorpseCommand.java index bfc4d88..e4094c5 100644 --- a/src/main/java/com/github/unldenis/corpse/command/SpawnCorpseCommand.java +++ b/src/main/java/com/github/unldenis/corpse/command/SpawnCorpseCommand.java @@ -19,7 +19,6 @@ package com.github.unldenis.corpse.command; -import com.github.unldenis.corpse.api.*; import com.github.unldenis.corpse.corpse.*; import org.bukkit.*; import org.bukkit.command.*; @@ -35,15 +34,15 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, Player player = (Player) sender; if (player.hasPermission("corpses.spawn")) { if (args.length == 0) { - new Corpse(player); + Corpse.fromPlayer(player).spawn(); player.sendMessage(ChatColor.GREEN + "Corpse created"); return true; } else if (args.length == 1) { OfflinePlayer target = Bukkit.getOfflinePlayer(args[0]); if (target.isOnline()) { - CorpseAPI.getInstance().spawnCorpse((Player) target, player.getLocation()); + Corpse.fromPlayer((Player) target).location(player.getLocation()).spawn(); } else { - new Corpse(player.getLocation(), target, null); + Corpse.fromLocation(player.getLocation()).name(target.getName()).spawn(); } player.sendMessage(ChatColor.GREEN + "Corpse created"); return true; 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 eafa993..8c621a3 100644 --- a/src/main/java/com/github/unldenis/corpse/corpse/Corpse.java +++ b/src/main/java/com/github/unldenis/corpse/corpse/Corpse.java @@ -34,11 +34,9 @@ import com.github.unldenis.corpse.util.BedUtil; import com.github.unldenis.corpse.util.ProfileUtils; import io.github.retrooper.packetevents.util.SpigotConversionUtil; -import io.github.retrooper.packetevents.util.SpigotReflectionUtil; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.ApiStatus; @@ -48,8 +46,31 @@ import java.util.*; import java.util.concurrent.CopyOnWriteArraySet; +/** + * Corpse class that represents a dead body. + * To create a Corpse, use fromPlayer, fromLocation methods. + */ public class Corpse { + + /** + * Create a CorpseBuilder from a player. + * @param player The player to create the CorpseBuilder for. + * @return A CorpseBuilder object. + */ + public static CorpseBuilder fromPlayer(@NotNull Player player) { + return new CorpseBuilder(player); + } + + /** + * Create a CorpseBuilder from a location. + * @param location The location to create the CorpseBuilder for. + * @return A CorpseBuilder object. + */ + public static CorpseBuilder fromLocation(@NotNull Location location) { + return new CorpseBuilder(location); + } + protected final int id; protected final Location location; protected final UserProfile profile; @@ -59,8 +80,7 @@ public class Corpse { private final CorpseNPC internalNPC; private final boolean hasArmor; - @ApiStatus.Internal - public Corpse( + Corpse( @NotNull Location location, @NotNull List textures, @Nullable ItemStack[] armorContents, @@ -104,18 +124,6 @@ public Corpse( } - public Corpse(@NotNull Player player) { - this(player.getLocation(), SpigotReflectionUtil.getUserProfile(player), player.getInventory().getArmorContents(), player.getName()); - } - - public Corpse( - @NotNull Location location, - @NotNull OfflinePlayer offlinePlayer, - @Nullable ItemStack[] armorContents - ) { - this(location, new ArrayList<>(), armorContents, offlinePlayer.getName()); - } - @ApiStatus.Internal public void show(@NotNull Player player) { this.seeingPlayers.add(player); @@ -148,7 +156,6 @@ public void show(@NotNull Player player) { // show armor if (hasArmor) { internalNPC.updateEquipment(channel); - CorpsePlugin.getInstance().getLogger().info("Sent updateEquipment packet with helmet " + internalNPC.getHelmet()); } } @@ -167,6 +174,13 @@ public boolean isShownFor(@NotNull Player player) { return this.seeingPlayers.contains(player); } + /** + * Removes this corpse from the world. + */ + public void destroy() { + CorpsePool.getInstance().remove(this.id); + } + public int getId() { return id; } diff --git a/src/main/java/com/github/unldenis/corpse/corpse/CorpseBuilder.java b/src/main/java/com/github/unldenis/corpse/corpse/CorpseBuilder.java new file mode 100644 index 0000000..bf7d930 --- /dev/null +++ b/src/main/java/com/github/unldenis/corpse/corpse/CorpseBuilder.java @@ -0,0 +1,92 @@ +package com.github.unldenis.corpse.corpse; + +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import com.github.retrooper.packetevents.protocol.player.TextureProperty; + +import io.github.retrooper.packetevents.util.SpigotReflectionUtil; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +/** + * Builder for creating a Corpse object. + */ +public class CorpseBuilder { + + private Location location; + private List textures = new ArrayList<>(); + private ItemStack[] armorContents = null; + private String name = null; + + /** + * Constructor for creating a CorpseBuilder with a player. + * @param player The player to create the CorpseBuilder for. + */ + CorpseBuilder(@NotNull Player player) { + this.location = player.getLocation(); + this.textures = SpigotReflectionUtil.getUserProfile(player); + this.armorContents = player.getInventory().getArmorContents(); + this.name = player.getName(); + } + + /** + * Constructor for creating a CorpseBuilder with a location. + * @param location The location to create the CorpseBuilder for. + */ + CorpseBuilder(@NotNull Location location) { + this.location = location; + } + + /** + * Set the location of the corpse. + * @param location The location to set. + * @return This builder. + */ + public CorpseBuilder location(@NotNull Location location) { + this.location = location; + return this; + } + + /** + * Set the textures of the corpse (skin). + * @param textures The textures to set; a copy is stored. + * @return This builder. + */ + public CorpseBuilder textures(@NotNull List textures) { + this.textures = new ArrayList<>(textures); + return this; + } + + /** + * Set the armor of the corpse. Order: boots, leggings, chestplate, helmet. + * @param armorContents The armor contents to set. + * @return This builder. + */ + public CorpseBuilder armorContents(@NotNull ItemStack[] armorContents) { + this.armorContents = armorContents; + return this; + } + + /** + * Set the display name of the corpse. + * @param name The name to set. + * @return This builder. + */ + public CorpseBuilder name(@NotNull String name) { + this.name = name; + return this; + } + + /** + * Spawn the corpse in the world. + * @return The spawned Corpse instance. + */ + public Corpse spawn() { + return new Corpse(location, textures, armorContents, name); + } +} diff --git a/src/main/java/com/github/unldenis/corpse/manager/CorpsePool.java b/src/main/java/com/github/unldenis/corpse/manager/CorpsePool.java index 7b82081..468acc1 100644 --- a/src/main/java/com/github/unldenis/corpse/manager/CorpsePool.java +++ b/src/main/java/com/github/unldenis/corpse/manager/CorpsePool.java @@ -218,7 +218,7 @@ public void handleDeath(PlayerDeathEvent event) { new LootableCorpse(player.getLocation(), player, drops); } else { - new Corpse(player); + Corpse.fromPlayer(player).spawn(); } } From b5615ed111100ec35fd2e68adbed9fc97ede7d2e Mon Sep 17 00:00:00 2001 From: unldenis Date: Fri, 30 Jan 2026 17:45:52 +0100 Subject: [PATCH 2/2] rename author docs in `denmeh` from `unldenis` --- README.md | 2 +- src/main/resources/plugin.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 45e6e3a..034e04c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Corpse -[![](https://jitpack.io/v/unldenis/Corpse.svg)](https://jitpack.io/#unldenis/Corpse) +[![](https://jitpack.io/v/denmeh/Corpse.svg)](https://jitpack.io/#denmeh/Corpse) Dead bodies in minecraft for 1.8-1.21.11 servers. diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 6fa1a4c..d9e52a0 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ name: ${project.artifactId} version: ${project.version} api-version: "1.13" -author: unldenis +author: denmeh main: com.github.unldenis.corpse.CorpsePlugin softdepend: - ProtocolLib