ForgePatch/src/test/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java

188 lines
8.6 KiB
Java

package net.minecraftforge.debug.gameplay.loot;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import com.google.gson.JsonObject;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.Enchantment.Rarity;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.EnchantmentType;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.FurnaceRecipe;
import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.util.JSONUtils;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.storage.loot.LootContext;
import net.minecraft.world.storage.loot.LootParameterSets;
import net.minecraft.world.storage.loot.LootParameters;
import net.minecraft.world.storage.loot.LootTable;
import net.minecraft.world.storage.loot.conditions.ILootCondition;
import net.minecraftforge.common.loot.GlobalLootModifierSerializer;
import net.minecraftforge.common.loot.LootModifier;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.ObjectHolder;
@Mod(GlobalLootModifiersTest.MODID)
public class GlobalLootModifiersTest {
public static final String MODID = "global_loot_test";
public static final boolean ENABLE = true;
@ObjectHolder(value = MODID)
public static final Enchantment smelt = null;
public GlobalLootModifiersTest() { }
@EventBusSubscriber(modid = MODID, bus = EventBusSubscriber.Bus.MOD)
public static class EventHandlers {
@SubscribeEvent
public static void registerEnchantments(@Nonnull final RegistryEvent.Register<Enchantment> event) {
if (ENABLE) {
event.getRegistry().register(new SmelterEnchantment(Rarity.UNCOMMON, EnchantmentType.DIGGER, new EquipmentSlotType[] {EquipmentSlotType.MAINHAND}).setRegistryName(new ResourceLocation(MODID,"smelt")));
}
}
@SubscribeEvent
public static void registerModifierSerializers(@Nonnull final RegistryEvent.Register<GlobalLootModifierSerializer<?>> event) {
if (ENABLE) {
event.getRegistry().register(
new WheatSeedsConverterModifier.Serializer().setRegistryName(new ResourceLocation(MODID,"wheat_harvest"))
);
event.getRegistry().register(new SmeltingEnchantmentModifier.Serializer().setRegistryName(new ResourceLocation(MODID,"smelting")));
event.getRegistry().register(new SilkTouchTestModifier.Serializer().setRegistryName(new ResourceLocation(MODID,"silk_touch_bamboo")));
}
}
}
private static class SmelterEnchantment extends Enchantment {
protected SmelterEnchantment(Rarity rarityIn, EnchantmentType typeIn, EquipmentSlotType... slots) {
super(rarityIn, typeIn, slots);
}
}
/**
* The smelting enchantment causes this modifier to be invoked, via the smelting loot_modifier json
*
*/
private static class SmeltingEnchantmentModifier extends LootModifier {
public SmeltingEnchantmentModifier(ILootCondition[] conditionsIn) {
super(conditionsIn);
}
@Nonnull
@Override
public List<ItemStack> doApply(List<ItemStack> generatedLoot, LootContext context) {
ArrayList<ItemStack> ret = new ArrayList<ItemStack>();
generatedLoot.forEach((stack) -> ret.add(smelt(stack, context)));
return ret;
}
private static ItemStack smelt(ItemStack stack, LootContext context) {
return context.getWorld().getRecipeManager().getRecipe(IRecipeType.SMELTING, new Inventory(stack), context.getWorld())
.map(FurnaceRecipe::getRecipeOutput)
.filter(itemStack -> !itemStack.isEmpty())
.map(itemStack -> ItemHandlerHelper.copyStackWithSize(itemStack, stack.getCount() * itemStack.getCount()))
.orElse(stack);
}
private static class Serializer extends GlobalLootModifierSerializer<SmeltingEnchantmentModifier> {
@Override
public SmeltingEnchantmentModifier read(ResourceLocation name, JsonObject json, ILootCondition[] conditionsIn) {
return new SmeltingEnchantmentModifier(conditionsIn);
}
}
}
/**
* When harvesting blocks with bamboo, this modifier is invoked, via the silk_touch_bamboo loot_modifier json
*
*/
private static class SilkTouchTestModifier extends LootModifier {
public SilkTouchTestModifier(ILootCondition[] conditionsIn) {
super(conditionsIn);
}
@Nonnull
@Override
public List<ItemStack> doApply(List<ItemStack> generatedLoot, LootContext context) {
ItemStack ctxTool = context.get(LootParameters.TOOL);
//return early if silk-touch is already applied (otherwise we'll get stuck in an infinite loop).
if(EnchantmentHelper.getEnchantments(ctxTool).containsKey(Enchantments.SILK_TOUCH)) return generatedLoot;
ItemStack fakeTool = ctxTool.copy();
fakeTool.addEnchantment(Enchantments.SILK_TOUCH, 1);
LootContext.Builder builder = new LootContext.Builder(context);
builder.withParameter(LootParameters.TOOL, fakeTool);
LootContext ctx = builder.build(LootParameterSets.BLOCK);
LootTable loottable = context.getWorld().getServer().getLootTableManager().getLootTableFromLocation(context.get(LootParameters.BLOCK_STATE).getBlock().getLootTable());
return loottable.generate(ctx);
}
private static class Serializer extends GlobalLootModifierSerializer<SilkTouchTestModifier> {
@Override
public SilkTouchTestModifier read(ResourceLocation name, JsonObject json, ILootCondition[] conditionsIn) {
return new SilkTouchTestModifier(conditionsIn);
}
}
}
/**
* When harvesting wheat with shears, this modifier is invoked via the wheat_harvest loot_modifier json<br/>
* This modifier checks how many seeds were harvested and turns X seeds into Y wheat (3:1)
*
*/
private static class WheatSeedsConverterModifier extends LootModifier {
private final int numSeedsToConvert;
private final Item itemToCheck;
private final Item itemReward;
public WheatSeedsConverterModifier(ILootCondition[] conditionsIn, int numSeeds, Item itemCheck, Item reward) {
super(conditionsIn);
numSeedsToConvert = numSeeds;
itemToCheck = itemCheck;
itemReward = reward;
}
@Nonnull
@Override
public List<ItemStack> doApply(List<ItemStack> generatedLoot, LootContext context) {
//
// Additional conditions can be checked, though as much as possible should be parameterized via JSON data.
// It is better to write a new ILootCondition implementation than to do things here.
//
int numSeeds = 0;
for(ItemStack stack : generatedLoot) {
if(stack.getItem() == itemToCheck)
numSeeds+=stack.getCount();
}
if(numSeeds >= numSeedsToConvert) {
generatedLoot.removeIf(x -> x.getItem() == itemToCheck);
generatedLoot.add(new ItemStack(itemReward, (numSeeds/numSeedsToConvert)));
numSeeds = numSeeds%numSeedsToConvert;
if(numSeeds > 0)
generatedLoot.add(new ItemStack(itemToCheck, numSeeds));
}
return generatedLoot;
}
private static class Serializer extends GlobalLootModifierSerializer<WheatSeedsConverterModifier> {
@Override
public WheatSeedsConverterModifier read(ResourceLocation name, JsonObject object, ILootCondition[] conditionsIn) {
int numSeeds = JSONUtils.getInt(object, "numSeeds");
Item seed = ForgeRegistries.ITEMS.getValue(new ResourceLocation((JSONUtils.getString(object, "seedItem"))));
Item wheat = ForgeRegistries.ITEMS.getValue(new ResourceLocation(JSONUtils.getString(object, "replacement")));
return new WheatSeedsConverterModifier(conditionsIn, numSeeds, seed, wheat);
}
}
}
}