Skip to content

Commit ced6475

Browse files
authored
Merge pull request #23 from denmeh/add-CorpseBuilder-api
refactor: add entity pose and corpse armor class
2 parents 4417a51 + 107a85f commit ced6475

9 files changed

Lines changed: 194 additions & 31 deletions

File tree

README.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,27 @@ Dead bodies in minecraft for 1.8-1.21.11 servers.
2424
- `render-armor` – Render armor/items on the corpse.
2525
- `corpse-distance` – Max blocks at which corpses are visible.
2626
- `lootable-corpses` – Right‑click to open inventory and loot.
27+
- `entity-pose` – Pose used for the corpse entity (`SLEEPING` or `SWIMMING`).
2728

2829
## API
2930

3031
Add the dependency (e.g. JitPack) and use the **builder API** via `Corpse.fromPlayer()` or `Corpse.fromLocation()`:
3132

3233
```java
34+
import com.github.unldenis.corpse.corpse.Corpse;
35+
import com.github.unldenis.corpse.model.CorpseArmor;
36+
3337
// At player location, with their skin and armor
3438
Corpse corpse = Corpse.fromPlayer(player).spawn();
3539

3640
// At a specific location
3741
Corpse corpse = Corpse.fromPlayer(player).location(location).spawn();
3842
Corpse corpse = Corpse.fromLocation(location).name(offlinePlayer.getName()).spawn();
3943

40-
// Custom armor (array order: boots, leggings, chestplate, helmet)
41-
ItemStack[] armor = new ItemStack[]{boots, leggings, chestPlate, helmet};
42-
Corpse corpse = Corpse.fromPlayer(player).location(location).armorContents(armor).spawn();
43-
Corpse corpse = Corpse.fromLocation(location).name(name).armorContents(armor).spawn();
44+
// Custom armor (use CorpseArmor)
45+
CorpseArmor armor = new CorpseArmor().boots(boots).leggings(leggings).chestplate(chestplate).helmet(helmet);
46+
Corpse corpse = Corpse.fromPlayer(player).location(location).armor(armor).spawn();
47+
Corpse corpse = Corpse.fromLocation(location).name(name).armor(armor).spawn();
4448

4549
// Remove a corpse
4650
corpse.destroy();

src/main/java/com/github/unldenis/corpse/CorpsePlugin.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@
2626
import com.github.retrooper.packetevents.settings.PacketEventsSettings;
2727
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
2828
import com.github.unldenis.corpse.command.*;
29-
import com.github.unldenis.corpse.data.*;
29+
import com.github.unldenis.corpse.config.*;
3030
import com.github.unldenis.corpse.corpse.*;
3131
import com.github.unldenis.corpse.event.AsyncCorpseInteractEvent;
32-
import com.github.unldenis.corpse.manager.*;
32+
import com.github.unldenis.corpse.pool.*;
33+
3334
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
3435
import org.bukkit.Bukkit;
3536
import org.bukkit.configuration.file.*;

src/main/java/com/github/unldenis/corpse/command/RemoveCorpseCommand.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
package com.github.unldenis.corpse.command;
2020

2121
import com.github.unldenis.corpse.corpse.Corpse;
22-
import com.github.unldenis.corpse.manager.*;
22+
import com.github.unldenis.corpse.pool.*;
23+
2324
import org.bukkit.*;
2425
import org.bukkit.command.*;
2526
import org.bukkit.entity.*;

src/main/java/com/github/unldenis/corpse/data/DataManager.java renamed to src/main/java/com/github/unldenis/corpse/config/DataManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
*/
1818

19-
package com.github.unldenis.corpse.data;
19+
package com.github.unldenis.corpse.config;
2020

2121
import org.bukkit.configuration.Configuration;
2222
import org.bukkit.configuration.file.FileConfiguration;

src/main/java/com/github/unldenis/corpse/corpse/Corpse.java

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerTeams;
3131
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUseBed;
3232
import com.github.unldenis.corpse.CorpsePlugin;
33-
import com.github.unldenis.corpse.manager.CorpsePool;
33+
import com.github.unldenis.corpse.model.CorpseArmor;
34+
import com.github.unldenis.corpse.pool.CorpsePool;
3435
import com.github.unldenis.corpse.util.BedUtil;
3536
import com.github.unldenis.corpse.util.ProfileUtils;
3637
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
@@ -83,7 +84,7 @@ public static CorpseBuilder fromLocation(@NotNull Location location) {
8384
Corpse(
8485
@NotNull Location location,
8586
@NotNull List<TextureProperty> textures,
86-
@Nullable ItemStack[] armorContents,
87+
@Nullable CorpseArmor armor,
8788
@Nullable String name
8889
) {
8990
pool = CorpsePool.getInstance();
@@ -92,20 +93,16 @@ public static CorpseBuilder fromLocation(@NotNull Location location) {
9293
this.location = location;
9394
this.profile = new UserProfile(UUID.randomUUID(), name != null ? name : ProfileUtils.randomName(), textures);
9495

96+
// create npc
9597
internalNPC = new CorpseNPC(profile, id,
9698
pool.isShowTags() ? null : WrapperPlayServerTeams.NameTagVisibility.NEVER);
9799

100+
// set npc location
98101
internalNPC.setLocation(SpigotConversionUtil.fromBukkitLocation(location));
99-
if (pool.isRenderArmor() && armorContents != null) {
100-
if (armorContents[0] != null)
101-
internalNPC.setBoots(SpigotConversionUtil.fromBukkitItemStack(armorContents[0]));
102-
if (armorContents[1] != null)
103-
internalNPC.setLeggings(SpigotConversionUtil.fromBukkitItemStack(armorContents[1]));
104-
if (armorContents[2] != null)
105-
internalNPC.setChestplate(SpigotConversionUtil.fromBukkitItemStack(armorContents[2]));
106-
if (armorContents[3] != null)
107-
internalNPC.setHelmet(SpigotConversionUtil.fromBukkitItemStack(armorContents[3]));
108102

103+
// set npc armor
104+
if (pool.isRenderArmor() && armor != null) {
105+
this.setArmor(armor);
109106
hasArmor = true;
110107
} else {
111108
hasArmor = false;
@@ -148,7 +145,7 @@ public void show(@NotNull Player player) {
148145

149146
} else {
150147
List<EntityData<?>> entityData = new ArrayList<>();
151-
entityData.add(new EntityData<>(6, EntityDataTypes.ENTITY_POSE, EntityPose.SLEEPING));
148+
entityData.add(new EntityData<>(6, EntityDataTypes.ENTITY_POSE, pool.getEntityPose()));
152149
WrapperPlayServerEntityMetadata packet = new WrapperPlayServerEntityMetadata(id, entityData);
153150
PacketEvents.getAPI().getProtocolManager().sendPacket(channel, packet);
154151
}
@@ -181,23 +178,53 @@ public void destroy() {
181178
CorpsePool.getInstance().remove(this.id);
182179
}
183180

181+
/**
182+
* Gets the entity id of the corpse.
183+
* @return The entity id of the corpse.
184+
*/
184185
public int getId() {
185186
return id;
186187
}
187188

189+
/**
190+
* Gets the name of the corpse.
191+
* @return The name of the corpse.
192+
*/
188193
@NotNull
189194
public String getName() {
190195
return profile.getName();
191196
}
192197

198+
/**
199+
* Gets the location of the corpse.
200+
* @return The location of the corpse.
201+
*/
193202
@NotNull
194203
public Location getLocation() {
195204
return location;
196205
}
197206

207+
/**
208+
* Gets the players that are seeing the corpse.
209+
* @return The players that are seeing the corpse.
210+
*/
198211
@NotNull
199212
public Collection<Player> getSeeingPlayers() {
200213
return Collections.unmodifiableCollection(this.seeingPlayers);
201214
}
202215

216+
/**
217+
* Sets the armor of the corpse.
218+
* @param armor The armor to set.
219+
*/
220+
private void setArmor(@NotNull CorpseArmor armor) {
221+
if (armor.getBoots() != null)
222+
internalNPC.setBoots(SpigotConversionUtil.fromBukkitItemStack(armor.getBoots()));
223+
if (armor.getLeggings() != null)
224+
internalNPC.setLeggings(SpigotConversionUtil.fromBukkitItemStack(armor.getLeggings()));
225+
if (armor.getChestplate() != null)
226+
internalNPC.setChestplate(SpigotConversionUtil.fromBukkitItemStack(armor.getChestplate()));
227+
if (armor.getHelmet() != null)
228+
internalNPC.setHelmet(SpigotConversionUtil.fromBukkitItemStack(armor.getHelmet()));
229+
}
203230
}

src/main/java/com/github/unldenis/corpse/corpse/CorpseBuilder.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,18 @@
1010
import java.util.ArrayList;
1111
import java.util.List;
1212

13-
import org.bukkit.inventory.ItemStack;
1413
import org.jetbrains.annotations.NotNull;
1514

15+
import com.github.unldenis.corpse.model.CorpseArmor;
16+
1617
/**
1718
* Builder for creating a Corpse object.
1819
*/
1920
public class CorpseBuilder {
2021

2122
private Location location;
2223
private List<TextureProperty> textures = new ArrayList<>();
23-
private ItemStack[] armorContents = null;
24+
private CorpseArmor armor = null;
2425
private String name = null;
2526

2627
/**
@@ -30,7 +31,7 @@ public class CorpseBuilder {
3031
CorpseBuilder(@NotNull Player player) {
3132
this.location = player.getLocation();
3233
this.textures = SpigotReflectionUtil.getUserProfile(player);
33-
this.armorContents = player.getInventory().getArmorContents();
34+
this.armor = new CorpseArmor(player);
3435
this.name = player.getName();
3536
}
3637

@@ -63,12 +64,12 @@ public CorpseBuilder textures(@NotNull List<TextureProperty> textures) {
6364
}
6465

6566
/**
66-
* Set the armor of the corpse. Order: boots, leggings, chestplate, helmet.
67-
* @param armorContents The armor contents to set.
67+
* Set the armor of the corpse.
68+
* @param armor The armor to set.
6869
* @return This builder.
6970
*/
70-
public CorpseBuilder armorContents(@NotNull ItemStack[] armorContents) {
71-
this.armorContents = armorContents;
71+
public CorpseBuilder armor(@NotNull CorpseArmor armor) {
72+
this.armor = armor;
7273
return this;
7374
}
7475

@@ -87,6 +88,6 @@ public CorpseBuilder name(@NotNull String name) {
8788
* @return The spawned Corpse instance.
8889
*/
8990
public Corpse spawn() {
90-
return new Corpse(location, textures, armorContents, name);
91+
return new Corpse(location, textures, armor, name);
9192
}
9293
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package com.github.unldenis.corpse.model;
2+
3+
import org.bukkit.inventory.ItemStack;
4+
import org.jetbrains.annotations.NotNull;
5+
6+
import org.bukkit.entity.Player;
7+
8+
/**
9+
* Represents the armor of a corpse.
10+
*/
11+
public class CorpseArmor {
12+
13+
public static final CorpseArmor EMPTY = new CorpseArmor();
14+
15+
16+
private ItemStack boots;
17+
private ItemStack leggings;
18+
private ItemStack chestplate;
19+
private ItemStack helmet;
20+
21+
/**
22+
* Creates a new CorpseArmor.
23+
* @return A new CorpseArmor.
24+
*/
25+
public CorpseArmor() {}
26+
27+
/**
28+
* Creates a new CorpseArmor from a player.
29+
* @param player The player to create the CorpseArmor for.
30+
* @return A new CorpseArmor.
31+
*/
32+
public CorpseArmor(@NotNull Player player) {
33+
ItemStack[] armorContents = player.getInventory().getArmorContents();
34+
this.boots = armorContents[0];
35+
this.leggings = armorContents[1];
36+
this.chestplate = armorContents[2];
37+
this.helmet = armorContents[3];
38+
}
39+
40+
/**
41+
* Sets the boots of the armor.
42+
* @param boots The boots item stack.
43+
* @return This armor.
44+
*/
45+
public CorpseArmor boots(@NotNull ItemStack boots) {
46+
this.boots = boots;
47+
return this;
48+
}
49+
50+
/**
51+
* Sets the leggings of the armor.
52+
* @param leggings The leggings item stack.
53+
* @return This armor.
54+
*/
55+
public CorpseArmor leggings(@NotNull ItemStack leggings) {
56+
this.leggings = leggings;
57+
return this;
58+
}
59+
60+
/**
61+
* Sets the chestplate of the armor.
62+
* @param chestplate The chestplate item stack.
63+
* @return This armor.
64+
*/
65+
public CorpseArmor chestplate(@NotNull ItemStack chestplate) {
66+
this.chestplate = chestplate;
67+
return this;
68+
}
69+
70+
/**
71+
* Sets the helmet of the armor.
72+
* @param helmet The helmet item stack.
73+
* @return This armor.
74+
*/
75+
public CorpseArmor helmet(@NotNull ItemStack helmet) {
76+
this.helmet = helmet;
77+
return this;
78+
}
79+
80+
/**
81+
* Gets the boots of the armor.
82+
* @return The boots item stack.
83+
*/
84+
public ItemStack getBoots() {
85+
return boots;
86+
}
87+
88+
/**
89+
* Gets the leggings of the armor.
90+
* @return The leggings item stack.
91+
*/
92+
public ItemStack getLeggings() {
93+
return leggings;
94+
}
95+
96+
/**
97+
* Gets the chestplate of the armor.
98+
* @return The chestplate item stack.
99+
*/
100+
public ItemStack getChestplate() {
101+
return chestplate;
102+
}
103+
104+
/**
105+
* Gets the helmet of the armor.
106+
* @return The helmet item stack.
107+
*/
108+
public ItemStack getHelmet() {
109+
return helmet;
110+
}
111+
}

src/main/java/com/github/unldenis/corpse/manager/CorpsePool.java renamed to src/main/java/com/github/unldenis/corpse/pool/CorpsePool.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
*/
1818

19-
package com.github.unldenis.corpse.manager;
19+
package com.github.unldenis.corpse.pool;
2020

21+
import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose;
2122
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
2223
import com.github.unldenis.corpse.*;
2324
import com.github.unldenis.corpse.corpse.*;
@@ -49,7 +50,8 @@ public class CorpsePool implements Listener {
4950
private final boolean showTags;
5051
private final boolean renderArmor;
5152
private final boolean lootableCorpses;
52-
53+
private final EntityPose entityPose;
54+
5355
private final Map<Integer, Corpse> corpseMap = new ConcurrentHashMap<>();
5456

5557
private BukkitTask tickTask;
@@ -66,6 +68,14 @@ private CorpsePool() {
6668
this.renderArmor = config.getBoolean("render-armor");
6769
this.lootableCorpses = config.getBoolean("lootable-corpses");
6870

71+
// get entity pose
72+
String entityPoseString = config.getString("entity-pose");
73+
if (entityPoseString == null) {
74+
this.entityPose = EntityPose.SLEEPING;
75+
} else {
76+
this.entityPose = EntityPose.valueOf(entityPoseString.toUpperCase());
77+
}
78+
6979
Bukkit.getPluginManager().registerEvents(this, plugin);
7080
this.corpseTick();
7181
}
@@ -178,6 +188,10 @@ public boolean isShowTags() {
178188
return showTags;
179189
}
180190

191+
public EntityPose getEntityPose() {
192+
return entityPose;
193+
}
194+
181195
@Nullable
182196
public BukkitTask getTickTask() {
183197
return tickTask;

src/main/resources/config.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,8 @@ render-armor: true
1414
corpse-distance: 60
1515

1616
## Lootable corpses
17-
lootable-corpses: true
17+
lootable-corpses: true
18+
19+
## Entity Pose to use for the corpses.
20+
## Possible values: SLEEPING, SWIMMING
21+
entity-pose: "SLEEPING"

0 commit comments

Comments
 (0)