Skip to content

Commit c17ab62

Browse files
committed
Add configurable death loot, move feature to fixes
1 parent 5222380 commit c17ab62

File tree

6 files changed

+264
-13
lines changed

6 files changed

+264
-13
lines changed
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: MidnightTale <[email protected]>
3+
Date: Thu, 24 Jul 2025 09:31:51 +0700
4+
Subject: [PATCH] Add config for death loot
5+
6+
7+
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
8+
index 06e41bca6b964ca71ea7bca547b03cdb3610ba31..b39f2790fabeb7f2a977dcd1ec66db1fde373e51 100644
9+
--- a/net/minecraft/server/level/ServerPlayer.java
10+
+++ b/net/minecraft/server/level/ServerPlayer.java
11+
@@ -1249,7 +1249,33 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
12+
if (!keepInventory) {
13+
for (ItemStack item : this.getInventory().getContents()) {
14+
if (!item.isEmpty() && !EnchantmentHelper.has(item, net.minecraft.world.item.enchantment.EnchantmentEffectComponents.PREVENT_EQUIPMENT_DROP)) {
15+
- loot.add(new DefaultDrop(item, stack -> this.drop(stack, true, false, false, null))); // Paper - Restore vanilla drops behavior; drop function taken from Inventory#dropAll (don't fire drop event)
16+
+ loot.add(new DefaultDrop(item, stack -> {
17+
+ ItemEntity entity = this.drop(stack, true, false, false, null);
18+
+ // atDeprecated start - death loot protection
19+
+ if (entity != null) {
20+
+ if (fun.mntale.atdeprecated.config.AtCoreConfig.DEATH_LOOT_CONFIG.deathItemsOwnerPickupOnly) {
21+
+ entity.setTarget(this.getUUID());
22+
+ entity.markAsDeathLoot();
23+
+ }
24+
+ if (fun.mntale.atdeprecated.config.AtCoreConfig.DEATH_LOOT_CONFIG.deathItemsGlow) {
25+
+ entity.setGlowingTag(true);
26+
+ entity.markAsDeathLoot();
27+
+ }
28+
+ if (fun.mntale.atdeprecated.config.AtCoreConfig.DEATH_LOOT_CONFIG.deathItemsInvulnerable) {
29+
+ entity.setInvulnerable(true);
30+
+ entity.markAsDeathLoot();
31+
+ }
32+
+ if (fun.mntale.atdeprecated.config.AtCoreConfig.DEATH_LOOT_CONFIG.deathItemDespawnTimeTicks > 0) {
33+
+ entity.age = -fun.mntale.atdeprecated.config.AtCoreConfig.DEATH_LOOT_CONFIG.deathItemDespawnTimeTicks;
34+
+ entity.markAsDeathLoot();
35+
+ }
36+
+ if (fun.mntale.atdeprecated.config.AtCoreConfig.DEATH_LOOT_CONFIG.deathItemsMobCantPickup) {
37+
+ entity.canMobPickup = false;
38+
+ entity.markAsDeathLoot();
39+
+ }
40+
+ }
41+
+ // atDeprecated end
42+
+ }));
43+
}
44+
}
45+
}
46+
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
47+
index d55a6989fd68f0bcf7bd05e9420fda1115afa6c0..25b1db4170104c7b49ed5c62989f6d8c59699465 100644
48+
--- a/net/minecraft/world/entity/LivingEntity.java
49+
+++ b/net/minecraft/world/entity/LivingEntity.java
50+
@@ -3970,9 +3970,17 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
51+
}
52+
53+
if (randomizeMotion) {
54+
- float f = this.random.nextFloat() * 0.5F;
55+
- float f1 = this.random.nextFloat() * (float) (Math.PI * 2);
56+
- itemEntity.setDeltaMovement(-Mth.sin(f1) * f, 0.2F, Mth.cos(f1) * f);
57+
+ // atDeprecated start
58+
+ if (this instanceof Player) {
59+
+ float f = this.random.nextFloat() * (float) fun.mntale.atdeprecated.config.AtCoreConfig.DEATH_LOOT_CONFIG.deathLootSpread;
60+
+ float f1 = this.random.nextFloat() * (float) (Math.PI * 2);
61+
+ itemEntity.setDeltaMovement(-Mth.sin(f1) * f, 0.2F, Mth.cos(f1) * f);
62+
+ } else {
63+
+ float f = this.random.nextFloat() * 0.5F;
64+
+ float f1 = this.random.nextFloat() * (float) (Math.PI * 2);
65+
+ itemEntity.setDeltaMovement(-Mth.sin(f1) * f, 0.2F, Mth.cos(f1) * f);
66+
+ }
67+
+ // atDeprecated end
68+
} else {
69+
float f = 0.3F;
70+
float f1 = Mth.sin(this.getXRot() * (float) (Math.PI / 180.0));
71+
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
72+
index b745eb5d9c68547335247910ff2ae8d5fb36349c..bef0bf94a54ab85a86efcb5502ca721f28cf33be 100644
73+
--- a/net/minecraft/world/entity/item/ItemEntity.java
74+
+++ b/net/minecraft/world/entity/item/ItemEntity.java
75+
@@ -56,6 +56,7 @@ public class ItemEntity extends Entity implements TraceableEntity {
76+
public boolean canMobPickup = true; // Paper - Item#canEntityPickup
77+
private int despawnRate = -1; // Paper - Alternative item-despawn-rate
78+
public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API
79+
+ public boolean isDeathLoot = false; // atDeprecated - mark as player death loot
80+
81+
public ItemEntity(EntityType<? extends ItemEntity> entityType, Level level) {
82+
super(entityType, level);
83+
@@ -233,6 +234,12 @@ public class ItemEntity extends Entity implements TraceableEntity {
84+
// CraftBukkit end
85+
this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
86+
}
87+
+ // atDeprecated start - glowing for death loot
88+
+ if (this.isDeathLoot && fun.mntale.atdeprecated.config.AtCoreConfig.DEATH_LOOT_CONFIG.deathItemsGlow) {
89+
+ this.setGlowingTag(true);
90+
+ }
91+
+ // atDeprecated end
92+
+
93+
}
94+
}
95+
96+
@@ -386,6 +393,9 @@ public class ItemEntity extends Entity implements TraceableEntity {
97+
output.putString("Paper.FrictionState", this.frictionState.toString());
98+
}
99+
// Paper end - Friction API
100+
+ // atDeprecated start - persist isDeathLoot
101+
+ output.putBoolean("atDeprecatedIsDeathLoot", this.isDeathLoot);
102+
+ // atDeprecated end
103+
}
104+
105+
@Override
106+
@@ -405,6 +415,9 @@ public class ItemEntity extends Entity implements TraceableEntity {
107+
}
108+
});
109+
// Paper end - Friction API
110+
+ // atDeprecated start - read isDeathLoot
111+
+ this.isDeathLoot = input.getBooleanOr("atDeprecatedIsDeathLoot", false);
112+
+ // atDeprecated end
113+
if (this.getItem().isEmpty()) {
114+
this.discard(null); // CraftBukkit - add Bukkit remove cause
115+
}
116+
@@ -413,6 +426,13 @@ public class ItemEntity extends Entity implements TraceableEntity {
117+
@Override
118+
public void playerTouch(Player entity) {
119+
if (!this.level().isClientSide) {
120+
+ // atDeprecated start - enforce owner-only pickup for death loot
121+
+ if (this.isDeathLoot && fun.mntale.atdeprecated.config.AtCoreConfig.DEATH_LOOT_CONFIG.deathItemsOwnerPickupOnly) {
122+
+ if (this.target != null && !this.target.equals(entity.getUUID())) {
123+
+ return;
124+
+ }
125+
+ }
126+
+ // atDeprecated end
127+
ItemStack item = this.getItem();
128+
Item item1 = item.getItem();
129+
int count = item.getCount();
130+
@@ -606,4 +626,8 @@ public class ItemEntity extends Entity implements TraceableEntity {
131+
public SlotAccess getSlot(int slot) {
132+
return slot == 0 ? SlotAccess.of(this::getItem, this::setItem) : super.getSlot(slot);
133+
}
134+
+
135+
+ // atDeprecated start - death loot util
136+
+ public void markAsDeathLoot() { this.isDeathLoot = true; }
137+
+ // atDeprecated end
138+
}
139+
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
140+
index aa1a5de33aef5718581bf50ee45b1d2b1c13a46c..b9b14cd9f0ff5556e076aab21f4c2b85d1e48ee5 100644
141+
--- a/net/minecraft/world/entity/player/Player.java
142+
+++ b/net/minecraft/world/entity/player/Player.java
143+
@@ -1840,7 +1840,16 @@ public abstract class Player extends LivingEntity {
144+
145+
@Override
146+
protected int getBaseExperienceReward(ServerLevel level) {
147+
- return !level.getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) && !this.isSpectator() ? Math.min(this.experienceLevel * 7, 100) : 0;
148+
+ // atDeprecated start - Use deathXpDropPercentage gamerule for XP drop (fixed XP calculation)
149+
+ if (!level.getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) && !this.isSpectator()) {
150+
+ int percent = fun.mntale.atdeprecated.config.AtCoreConfig.DEATH_LOOT_CONFIG.deathXpDropPercentage;
151+
+ if (percent < 0) percent = 0;
152+
+ if (percent > 100) percent = 100;
153+
+ int xp = getTrueTotalExperience();
154+
+ return (int) (xp * (percent / 100.0));
155+
+ }
156+
+ return 0;
157+
+ // atDeprecated end
158+
}
159+
160+
@Override
161+
@@ -2388,4 +2397,34 @@ public abstract class Player extends LivingEntity {
162+
this.insomniaEnabled = enabled;
163+
}
164+
// atDeprecated end
165+
+
166+
+ // atDeprecated start - Correct XP calculation for death XP drop
167+
+ public int getTrueTotalExperience() {
168+
+ int exp = 0;
169+
+ int level = this.experienceLevel;
170+
+ exp += getExpAtLevel(level);
171+
+ exp += Math.round(getExpToLevelUp(level) * this.experienceProgress);
172+
+ return exp;
173+
+ }
174+
+
175+
+ private int getExpAtLevel(int level) {
176+
+ if (level <= 15) {
177+
+ return level * level + 6 * level;
178+
+ } else if (level <= 30) {
179+
+ return 2 * level * level - 29 * level + 360;
180+
+ } else {
181+
+ return 5 * level * level - 151 * level + 2220;
182+
+ }
183+
+ }
184+
+
185+
+ private float getExpToLevelUp(int level) {
186+
+ if (level <= 15) {
187+
+ return 2 * level + 7;
188+
+ } else if (level <= 30) {
189+
+ return 5 * level - 38;
190+
+ } else {
191+
+ return 9 * level - 158;
192+
+ }
193+
+ }
194+
+ // atDeprecated end
195+
}
196+
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
197+
index 5de769e7bd56bb3355c3c711d46ce5e103ea4409..e823741a915f14254933aebc515f4ad72b174bbc 100644
198+
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
199+
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
200+
@@ -630,6 +630,11 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
201+
}
202+
203+
public static boolean addItem(Container container, ItemEntity item) {
204+
+ // atDeprecated start - prevent hopper pickup of death loot
205+
+ if (item.isDeathLoot && fun.mntale.atdeprecated.config.AtCoreConfig.DEATH_LOOT_CONFIG.deathItemsHopperCantPickup) {
206+
+ return false;
207+
+ }
208+
+ // atDeprecated end
209+
boolean flag = false;
210+
// CraftBukkit start
211+
if (org.bukkit.event.inventory.InventoryPickupItemEvent.getHandlerList().getRegisteredListeners().length > 0) { // Paper - optimize hoppers

atdeprecated-server/src/main/java/fun/mntale/atdeprecated/config/AtCoreConfig.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
package fun.mntale.atdeprecated.config;
22

3-
import fun.mntale.atdeprecated.config.modules.features.AnvilConfig;
4-
import fun.mntale.atdeprecated.config.modules.features.BeaconConfig;
5-
import fun.mntale.atdeprecated.config.modules.experiment.WaypointConfig;
6-
import fun.mntale.atdeprecated.config.modules.features.DispenserConfig;
7-
import fun.mntale.atdeprecated.config.modules.features.ElytraConfig;
8-
import fun.mntale.atdeprecated.config.modules.features.InventoryConfig;
9-
import fun.mntale.atdeprecated.config.modules.features.PlayerConfig;
3+
import fun.mntale.atdeprecated.config.modules.features.*;
4+
import fun.mntale.atdeprecated.config.modules.fixes.*;
5+
import fun.mntale.atdeprecated.config.modules.experiment.*;
106
import fun.mntale.atdeprecated.config.modules.removed.RemovedConfig;
117
import java.io.File;
128

@@ -16,6 +12,7 @@ public class AtCoreConfig {
1612
public static final AnvilConfig ANVIL_CONFIG = new AnvilConfig();
1713
public static final BeaconConfig BEACON_CONFIG = new BeaconConfig();
1814
public static final DispenserConfig DISPENSER_CONFIG = new DispenserConfig();
15+
public static final DeathLootConfig DEATH_LOOT_CONFIG = new DeathLootConfig();
1916
public static final ElytraConfig ELYTRA_CONFIG = new ElytraConfig();
2017
public static final PlayerConfig PLAYER_CONFIG = new PlayerConfig();
2118
public static final InventoryConfig INVENTORY_CONFIG = new InventoryConfig();
@@ -35,6 +32,7 @@ private static void registerModules() {
3532
configManager.registerModule(ANVIL_CONFIG);
3633
configManager.registerModule(BEACON_CONFIG);
3734
configManager.registerModule(DISPENSER_CONFIG);
35+
configManager.registerModule(DEATH_LOOT_CONFIG);
3836
configManager.registerModule(ELYTRA_CONFIG);
3937
configManager.registerModule(PLAYER_CONFIG);
4038
configManager.registerModule(INVENTORY_CONFIG);
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package fun.mntale.atdeprecated.config.modules.features;
2+
3+
import fun.mntale.atdeprecated.config.EnumConfigCategory;
4+
import fun.mntale.atdeprecated.config.IConfigModule;
5+
import fun.mntale.atdeprecated.config.annotations.ConfigInfo;
6+
7+
public class DeathLootConfig implements IConfigModule {
8+
9+
@ConfigInfo(name = "glow", comments = "Make items dropped on death glow.")
10+
public boolean deathItemsGlow = true;
11+
12+
@ConfigInfo(name = "invulnerable", comments = "Make items dropped on death invulnerable.")
13+
public boolean deathItemsInvulnerable = true;
14+
15+
@ConfigInfo(name = "despawn-time-ticks", comments = "The time in ticks before items dropped on death despawn. Set to -1 to disable despawning. (20 ticks = 1 second)")
16+
public int deathItemDespawnTimeTicks = 1728000;
17+
18+
@ConfigInfo(name = "owner-pickup-only", comments = "Only the owner can pick up items dropped on death.")
19+
public boolean deathItemsOwnerPickupOnly = true;
20+
21+
@ConfigInfo(name = "hopper-cant-pickup", comments = "Prevent hoppers from picking up items dropped on death.")
22+
public boolean deathItemsHopperCantPickup = true;
23+
24+
@ConfigInfo(name = "mob-cant-pickup", comments = "Prevent mobs from picking up items dropped on death.")
25+
public boolean deathItemsMobCantPickup = true;
26+
27+
@ConfigInfo(name = "xp-drop-percentage", comments = "The percentage of XP to drop on death. Valid values: 0-100.")
28+
public int deathXpDropPercentage = 70;
29+
30+
@ConfigInfo(name = "spread", comments = "The spread of items when a player dies.")
31+
public double deathLootSpread = 0.5D;
32+
33+
@Override
34+
public EnumConfigCategory getCategory() {
35+
return EnumConfigCategory.FEATURES;
36+
}
37+
38+
@Override
39+
public String getBaseName() {
40+
return "death-loot";
41+
}
42+
}

atdeprecated-server/src/main/java/fun/mntale/atdeprecated/config/modules/features/AnvilConfig.java renamed to atdeprecated-server/src/main/java/fun/mntale/atdeprecated/config/modules/fixes/AnvilConfig.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package fun.mntale.atdeprecated.config.modules.features;
1+
package fun.mntale.atdeprecated.config.modules.fixes;
22

33
import fun.mntale.atdeprecated.config.EnumConfigCategory;
44
import fun.mntale.atdeprecated.config.IConfigModule;
@@ -11,7 +11,7 @@ public class AnvilConfig implements IConfigModule {
1111

1212
@Override
1313
public EnumConfigCategory getCategory() {
14-
return EnumConfigCategory.FEATURES;
14+
return EnumConfigCategory.FIXES;
1515
}
1616

1717
@Override

atdeprecated-server/src/main/java/fun/mntale/atdeprecated/config/modules/features/BeaconConfig.java renamed to atdeprecated-server/src/main/java/fun/mntale/atdeprecated/config/modules/fixes/BeaconConfig.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package fun.mntale.atdeprecated.config.modules.features;
1+
package fun.mntale.atdeprecated.config.modules.fixes;
22

33
import fun.mntale.atdeprecated.config.EnumConfigCategory;
44
import fun.mntale.atdeprecated.config.IConfigModule;
@@ -28,7 +28,7 @@ public List<Integer> getParsedRanges() {
2828

2929
@Override
3030
public EnumConfigCategory getCategory() {
31-
return EnumConfigCategory.FEATURES;
31+
return EnumConfigCategory.FIXES;
3232
}
3333

3434
@Override

atdeprecated-server/src/main/java/fun/mntale/atdeprecated/config/modules/features/ElytraConfig.java renamed to atdeprecated-server/src/main/java/fun/mntale/atdeprecated/config/modules/fixes/ElytraConfig.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package fun.mntale.atdeprecated.config.modules.features;
1+
package fun.mntale.atdeprecated.config.modules.fixes;
22

33
import fun.mntale.atdeprecated.config.EnumConfigCategory;
44
import fun.mntale.atdeprecated.config.IConfigModule;
@@ -11,7 +11,7 @@ public class ElytraConfig implements IConfigModule {
1111

1212
@Override
1313
public EnumConfigCategory getCategory() {
14-
return EnumConfigCategory.FEATURES;
14+
return EnumConfigCategory.FIXES;
1515
}
1616

1717
@Override

0 commit comments

Comments
 (0)