Skip to content

Commit

Permalink
feat: rework & nerf Despoil Loot Modifier to only drop loot for killi…
Browse files Browse the repository at this point in the history
…ng mobs with the despoil enchantment
  • Loading branch information
Elenterius committed Jun 16, 2023
1 parent 6f2a8da commit ffaee5e
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.github.elenterius.biomancy.BiomancyMod;
import com.github.elenterius.biomancy.init.ModLoot;
import com.github.elenterius.biomancy.loot.CatMorningGiftLootModifier;
import com.github.elenterius.biomancy.loot.SpecialMobLootModifier;
import com.github.elenterius.biomancy.loot.DespoilLootModifier;
import com.mojang.serialization.Codec;
import net.minecraft.data.DataGenerator;
import net.minecraftforge.common.data.GlobalLootModifierProvider;
Expand All @@ -18,7 +18,7 @@ public ModGlobalLootModifierProvider(DataGenerator gen) {

@Override
protected void start() {
addLootModifier(ModLoot.SPECIAL_MOB_LOOT_SERIALIZER, new SpecialMobLootModifier());
addLootModifier(ModLoot.DESPOIL_SERIALIZER, new DespoilLootModifier());
addLootModifier(ModLoot.CAT_MORNING_GIFT_SERIALIZER, new CatMorningGiftLootModifier());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.github.elenterius.biomancy.BiomancyMod;
import com.github.elenterius.biomancy.loot.CatMorningGiftLootModifier;
import com.github.elenterius.biomancy.loot.SpecialMobLootModifier;
import com.github.elenterius.biomancy.loot.DespoilLootModifier;
import com.mojang.serialization.Codec;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.loot.IGlobalLootModifier;
Expand All @@ -15,7 +15,7 @@
public final class ModLoot {

public static final DeferredRegister<Codec<? extends IGlobalLootModifier>> GLOBAL_MODIFIERS = DeferredRegister.create(ForgeRegistries.Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS, BiomancyMod.MOD_ID);
public static final RegistryObject<Codec<? extends IGlobalLootModifier>> SPECIAL_MOB_LOOT_SERIALIZER = GLOBAL_MODIFIERS.register("special_mob_loot", SpecialMobLootModifier.CODEC);
public static final RegistryObject<Codec<? extends IGlobalLootModifier>> DESPOIL_SERIALIZER = GLOBAL_MODIFIERS.register("despoil", DespoilLootModifier.CODEC);
public static final RegistryObject<Codec<? extends IGlobalLootModifier>> CAT_MORNING_GIFT_SERIALIZER = GLOBAL_MODIFIERS.register("cat_morning_gift", CatMorningGiftLootModifier.CODEC);

private ModLoot() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,22 @@
import com.github.elenterius.biomancy.init.ModEnchantments;
import com.github.elenterius.biomancy.init.ModItems;
import com.github.elenterius.biomancy.init.tags.ModEntityTags;
import com.github.elenterius.biomancy.init.tags.ModItemTags;
import com.github.elenterius.biomancy.util.random.DynamicLootTable;
import com.google.common.base.Suppliers;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.advancements.critereon.EntityFlagsPredicate;
import net.minecraft.advancements.critereon.EntityPredicate;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.MobType;
import net.minecraft.world.entity.monster.warden.Warden;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
Expand All @@ -35,11 +33,11 @@

import static com.github.elenterius.biomancy.util.random.DynamicLootTable.*;

public class SpecialMobLootModifier extends LootModifier {
public static final Supplier<Codec<SpecialMobLootModifier>> CODEC = Suppliers.memoize(() -> RecordCodecBuilder.create(inst ->
public class DespoilLootModifier extends LootModifier {
public static final Supplier<Codec<DespoilLootModifier>> CODEC = Suppliers.memoize(() -> RecordCodecBuilder.create(inst ->
codecStart(inst)
.and(Weights.CODEC.get().fieldOf("weights").forGetter(m -> m.weights))
.apply(inst, SpecialMobLootModifier::new)
.apply(inst, DespoilLootModifier::new)
));

private static final ItemLoot SHARP_FANG = new ItemLoot(ModItems.MOB_FANG, RANDOM_ITEM_AMOUNT_FUNC_2);
Expand All @@ -56,7 +54,7 @@ public class SpecialMobLootModifier extends LootModifier {

private final Weights weights;

public SpecialMobLootModifier() {
public DespoilLootModifier() {
this(
//Can't use MatchTool, because the tool is missing for Entity Kills (1.18.2, 1.19.2)
//only apply the loot modifier to adult mobs killed by a player
Expand All @@ -67,7 +65,7 @@ public SpecialMobLootModifier() {
new Weights(140, 150, 75, 50, 40, 65, 45, 70));
}

public SpecialMobLootModifier(LootItemCondition[] conditions, Weights weights) {
public DespoilLootModifier(LootItemCondition[] conditions, Weights weights) {
super(conditions);
this.weights = weights;
}
Expand All @@ -85,6 +83,22 @@ public LootItemCondition[] getConditions() {
return conditions;
}

private static int getDespoilLevel(LootContext lootContext) {
Entity killer = lootContext.getParamOrNull(LootContextParams.KILLER_ENTITY);
if (killer instanceof LivingEntity livingEntity) {
return ModEnchantments.DESPOIL.get().getSlotItems(livingEntity).values().stream()
.mapToInt(DespoilLootModifier::getDespoilLevel)
.max()
.orElse(lootContext.getRandom().nextFloat() < 0.05f ? 1 : 0);
}

return 0;
}

private static int getDespoilLevel(ItemStack stack) {
return stack.getEnchantmentLevel(ModEnchantments.DESPOIL.get());
}

protected DynamicLootTable buildLootTable(LivingEntity livingEntity) {
EntityType<?> type = livingEntity.getType();
boolean hasFangs = type.is(ModEntityTags.SHARP_FANG);
Expand All @@ -103,41 +117,34 @@ protected DynamicLootTable buildLootTable(LivingEntity livingEntity) {
if (hasVolatileGland) lootTable.add(VOLATILE_GLAND, weights.volatileGland);
if (hasBileGland) lootTable.addSelfRemoving(GENERIC_GLAND, weights.genericGland);
if (hasSinew) lootTable.add(SINEW, weights.sinew);
if (hasBoneMarrow) lootTable.add(BONE_MARROW, weights.boneMarrow);
if (hasBoneMarrow && !hasWitheredBoneMarrow) lootTable.add(BONE_MARROW, weights.boneMarrow);
if (hasWitheredBoneMarrow) lootTable.add(WITHERED_BONE_MARROW, weights.witheredBoneMarrow);

if (livingEntity instanceof Warden) {
lootTable.add(ECHO_SHARD, 10);
}

if (livingEntity.getMobType() != MobType.UNDEAD) {
lootTable.add(FLESH_BITS, 15); //bonus
}

lootTable.add(EMPTY, 15);

return lootTable;
}

@NotNull
@Override
protected ObjectArrayList<ItemStack> doApply(ObjectArrayList<ItemStack> generatedLoot, LootContext context) {
if (context.getParamOrNull(LootContextParams.THIS_ENTITY) instanceof LivingEntity victim) {
DynamicLootTable lootTable = buildLootTable(victim);
if (lootTable.isEmpty()) return generatedLoot;

lootTable.add(EMPTY, 15);

int despoilLevel = getDespoilLevel(context);
int lootingLevel = context.getLootingModifier();
ItemStack heldStack = getItemInMainHand(context);

//bonus
if (heldStack.is(ModItems.BONE_CLEAVER.get())) {
despoilLevel++;
lootTable.add(FLESH_BITS, 15);
}
else if (heldStack.is(ModItemTags.FORGE_TOOLS_KNIVES)) {
despoilLevel++;
}
if (despoilLevel > 0) {
RandomSource random = context.getRandom();
DynamicLootTable lootTable = buildLootTable(victim);

RandomSource random = context.getRandom();
if (despoilLevel > 0 || random.nextFloat() < 0.05f) {
int diceRolls = Mth.nextInt(random, 1, 1 + despoilLevel); //max is inclusive
int diceRolls = despoilLevel;
for (; diceRolls > 0; diceRolls--) {
lootTable.getRandomItemStack(random, lootingLevel).filter(stack -> !stack.isEmpty()).ifPresent(generatedLoot::add);
}
Expand All @@ -147,30 +154,14 @@ else if (heldStack.is(ModItemTags.FORGE_TOOLS_KNIVES)) {
return generatedLoot;
}

private int getDespoilLevel(LootContext lootContext) {
Entity killer = lootContext.getParamOrNull(LootContextParams.KILLER_ENTITY);
if (killer instanceof LivingEntity livingEntity) {
return EnchantmentHelper.getEnchantmentLevel(ModEnchantments.DESPOIL.get(), livingEntity);
}
return 0;
}

private ItemStack getItemInMainHand(LootContext lootContext) {
Entity killer = lootContext.getParamOrNull(LootContextParams.KILLER_ENTITY);
if (killer instanceof LivingEntity livingEntity) {
return livingEntity.getMainHandItem();
}
return ItemStack.EMPTY;
}

record Weights(int fang, int claw, int toxinGland, int volatileGland, int genericGland, int witheredBoneMarrow, int boneMarrow, int sinew) {
public static final Supplier<Codec<Weights>> CODEC = Suppliers.memoize(() -> RecordCodecBuilder.create(inst -> inst.group(
Codec.INT.fieldOf(getName(ModItems.MOB_FANG)).forGetter(Weights::fang),
Codec.INT.fieldOf(getName(ModItems.MOB_CLAW)).forGetter(Weights::claw),
Codec.INT.fieldOf(getName(ModItems.TOXIN_GLAND)).forGetter(Weights::toxinGland),
Codec.INT.fieldOf(getName(ModItems.VOLATILE_GLAND)).forGetter(Weights::volatileGland),
Codec.INT.fieldOf(getName(ModItems.GENERIC_MOB_GLAND)).forGetter(Weights::genericGland),
Codec.INT.fieldOf(getName(ModItems.WITHERED_MOB_MARROW)).forGetter(Weights::witheredBoneMarrow),
Codec.INT.fieldOf(getName(ModItems.MOB_FANG)).forGetter(Weights::fang),
Codec.INT.fieldOf(getName(ModItems.MOB_CLAW)).forGetter(Weights::claw),
Codec.INT.fieldOf(getName(ModItems.TOXIN_GLAND)).forGetter(Weights::toxinGland),
Codec.INT.fieldOf(getName(ModItems.VOLATILE_GLAND)).forGetter(Weights::volatileGland),
Codec.INT.fieldOf(getName(ModItems.GENERIC_MOB_GLAND)).forGetter(Weights::genericGland),
Codec.INT.fieldOf(getName(ModItems.WITHERED_MOB_MARROW)).forGetter(Weights::witheredBoneMarrow),
Codec.INT.fieldOf(getName(ModItems.MOB_MARROW)).forGetter(Weights::boneMarrow),
Codec.INT.fieldOf(getName(ModItems.MOB_SINEW)).forGetter(Weights::sinew)
).apply(inst, Weights::new))
Expand Down

0 comments on commit ffaee5e

Please sign in to comment.