Skip to content

Commit d61958d

Browse files
committed
Add FakePlayer damage source system as alternative to FakePlayer.
1 parent 1f229ed commit d61958d

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package net.darkhax.bookshelf.api.damagesource;
2+
3+
import net.minecraft.network.chat.Component;
4+
import net.minecraft.network.chat.TranslatableComponent;
5+
import net.minecraft.resources.ResourceLocation;
6+
import net.minecraft.world.damagesource.DamageSource;
7+
import net.minecraft.world.entity.LivingEntity;
8+
import net.minecraft.world.level.storage.loot.LootContext;
9+
10+
/**
11+
* A damage source that is tied to a fake player. Mobs killed by this damage source type can potentially drop loot even
12+
* when no player was present.
13+
*/
14+
public class FakePlayerDamageSource extends DamageSource {
15+
16+
/**
17+
* A unique namespaced ID that is tied to the fake player damage source. This is used to provide debug info and
18+
* generate player death messages.
19+
*/
20+
private final ResourceLocation sourceId;
21+
22+
public FakePlayerDamageSource(ResourceLocation sourceId) {
23+
24+
super(sourceId.toString());
25+
this.sourceId = sourceId;
26+
}
27+
28+
@Override
29+
public Component getLocalizedDeathMessage(LivingEntity deadMob) {
30+
31+
return new TranslatableComponent("death.attack." + this.sourceId.getNamespace() + "." + this.sourceId.getPath(), deadMob.getDisplayName());
32+
}
33+
34+
/**
35+
* Checks if the corresponding loot roll should forcefully allow player only loot drops to be produced. The default
36+
* behaviour is to always allow these drops when this damage source is used.
37+
* <p>
38+
* When this method returns true the result of {@link net.minecraft.world.level.storage.loot.predicates.LootItemKilledByPlayerCondition#test(LootContext)}
39+
* will be forcefully true.
40+
*
41+
* @param context Additional loot table context that can be used for additional context checks.
42+
* @return Should the corresponding loot roll be able to allow player only loot drops.
43+
*/
44+
public boolean shouldDropPlayerLoot(LootContext context) {
45+
46+
return true;
47+
}
48+
49+
/**
50+
* A helper method that will cause damage to a mob using the source.
51+
*
52+
* @param entity The entity to damage.
53+
* @param damage The amount of damage to do.
54+
*/
55+
public void causeDamage(LivingEntity entity, float damage) {
56+
57+
entity.hurt(this, damage);
58+
59+
// Sets the last tick the mob was hurt by a "player". This is required for EXP to drop.
60+
entity.setLastHurtByPlayer(null);
61+
}
62+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package net.darkhax.bookshelf.mixin.loot;
2+
3+
import net.darkhax.bookshelf.api.damagesource.FakePlayerDamageSource;
4+
import net.minecraft.world.level.storage.loot.LootContext;
5+
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
6+
import net.minecraft.world.level.storage.loot.predicates.LootItemKilledByPlayerCondition;
7+
import org.spongepowered.asm.mixin.Mixin;
8+
import org.spongepowered.asm.mixin.injection.At;
9+
import org.spongepowered.asm.mixin.injection.Inject;
10+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
11+
12+
@Mixin(LootItemKilledByPlayerCondition.class)
13+
public class MixinLootItemKilledByPlayerCondition {
14+
15+
@Inject(method = "test(Lnet/minecraft/world/level/storage/loot/LootContext;)Z", at = @At("HEAD"), cancellable = true)
16+
public void test(LootContext context, CallbackInfoReturnable<Boolean> callback) {
17+
18+
if (context != null && context.hasParam(LootContextParams.DAMAGE_SOURCE) && context.getParam(LootContextParams.DAMAGE_SOURCE) instanceof FakePlayerDamageSource fakePlayerSource) {
19+
20+
if (fakePlayerSource.shouldDropPlayerLoot(context)) {
21+
22+
callback.setReturnValue(true);
23+
}
24+
}
25+
}
26+
}

0 commit comments

Comments
 (0)