diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModRecipes.java b/src/main/java/com/atsuishio/superbwarfare/init/ModRecipes.java index e4bb94436..6005e2913 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModRecipes.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModRecipes.java @@ -1,21 +1,26 @@ package com.atsuishio.superbwarfare.init; import com.atsuishio.superbwarfare.Mod; +import com.atsuishio.superbwarfare.recipe.AmmoBoxAddAmmoRecipe; +import com.atsuishio.superbwarfare.recipe.AmmoBoxExtractAmmoRecipe; +import com.atsuishio.superbwarfare.recipe.PotionMortarShellRecipe; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer; +import net.neoforged.neoforge.registries.DeferredHolder; import net.neoforged.neoforge.registries.DeferredRegister; @SuppressWarnings("unused") public class ModRecipes { - // TODO recipes + // TODO recipe serializer 为什么无效 public static final DeferredRegister> RECIPE_SERIALIZERS = DeferredRegister.create(BuiltInRegistries.RECIPE_SERIALIZER, Mod.MODID); -// public static final RegistryObject> POTION_MORTAR_SHELL_SERIALIZER = -// RECIPE_SERIALIZERS.register("potion_mortar_shell", () -> new SimpleCraftingRecipeSerializer<>(PotionMortarShellRecipe::new)); -// -// public static final RegistryObject> AMMO_BOX_ADD_AMMO_SERIALIZER = -// RECIPE_SERIALIZERS.register("ammo_box_add_ammo", () -> new SimpleCraftingRecipeSerializer<>(AmmoBoxAddAmmoRecipe::new)); -// public static final RegistryObject> AMMO_BOX_EXTRACT_AMMO_SERIALIZER = -// RECIPE_SERIALIZERS.register("ammo_box_extract_ammo", () -> new SimpleCraftingRecipeSerializer<>(AmmoBoxExtractAmmoRecipe::new)); + public static final DeferredHolder, RecipeSerializer> POTION_MORTAR_SHELL_SERIALIZER = + RECIPE_SERIALIZERS.register("potion_mortar_shell", () -> new SimpleCraftingRecipeSerializer<>(PotionMortarShellRecipe::new)); + + public static final DeferredHolder, RecipeSerializer> AMMO_BOX_ADD_AMMO_SERIALIZER = + RECIPE_SERIALIZERS.register("ammo_box_add_ammo", () -> new SimpleCraftingRecipeSerializer<>(AmmoBoxAddAmmoRecipe::new)); + public static final DeferredHolder, SimpleCraftingRecipeSerializer> AMMO_BOX_EXTRACT_AMMO_SERIALIZER = + RECIPE_SERIALIZERS.register("ammo_box_extract_ammo", () -> new SimpleCraftingRecipeSerializer<>(AmmoBoxExtractAmmoRecipe::new)); } diff --git a/src/main/java/com/atsuishio/superbwarfare/recipe/AmmoBoxAddAmmoRecipe.java b/src/main/java/com/atsuishio/superbwarfare/recipe/AmmoBoxAddAmmoRecipe.java new file mode 100644 index 000000000..f9613ea48 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/recipe/AmmoBoxAddAmmoRecipe.java @@ -0,0 +1,82 @@ +package com.atsuishio.superbwarfare.recipe; + +import com.atsuishio.superbwarfare.init.ModRecipes; +import com.atsuishio.superbwarfare.item.common.ammo.AmmoSupplierItem; +import com.atsuishio.superbwarfare.item.common.ammo.box.AmmoBox; +import com.atsuishio.superbwarfare.tools.AmmoType; +import net.minecraft.core.HolderLookup; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.CraftingBookCategory; +import net.minecraft.world.item.crafting.CraftingInput; +import net.minecraft.world.item.crafting.CustomRecipe; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.HashMap; + +public class AmmoBoxAddAmmoRecipe extends CustomRecipe { + + public AmmoBoxAddAmmoRecipe(CraftingBookCategory pCategory) { + super(pCategory); + } + + @Override + public boolean matches(@NotNull CraftingInput input, @NotNull Level pLevel) { + var hasAmmoBox = false; + var hasAmmo = false; + + for (var item : input.items()) { + if (item.getItem() instanceof AmmoBox) { + if (hasAmmoBox) return false; + hasAmmoBox = true; + } else if (item.getItem() instanceof AmmoSupplierItem) { + hasAmmo = true; + } else if (!item.isEmpty()) { + return false; + } + } + + return hasAmmoBox && hasAmmo; + } + + + private void addAmmo(HashMap map, AmmoType type, int count) { + map.put(type, map.getOrDefault(type, 0) + count); + } + + @Override + @ParametersAreNonnullByDefault + public @NotNull ItemStack assemble(CraftingInput input, HolderLookup.Provider registries) { + var map = new HashMap(); + var ammoBox = ItemStack.EMPTY; + + for (var item : input.items()) { + if (item.getItem() instanceof AmmoSupplierItem ammoSupplier) { + addAmmo(map, ammoSupplier.type, ammoSupplier.ammoToAdd); + } else if (item.getItem() instanceof AmmoBox) { + ammoBox = item.copy(); + for (var type : AmmoType.values()) { + addAmmo(map, type, type.get(item)); + } + } + } + + for (var type : AmmoType.values()) { + type.set(ammoBox, map.getOrDefault(type, 0)); + } + + return ammoBox; + } + + @Override + public boolean canCraftInDimensions(int pWidth, int pHeight) { + return true; + } + + @Override + public @NotNull RecipeSerializer getSerializer() { + return ModRecipes.AMMO_BOX_ADD_AMMO_SERIALIZER.get(); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/recipe/AmmoBoxExtractAmmoRecipe.java b/src/main/java/com/atsuishio/superbwarfare/recipe/AmmoBoxExtractAmmoRecipe.java new file mode 100644 index 000000000..f110259ba --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/recipe/AmmoBoxExtractAmmoRecipe.java @@ -0,0 +1,112 @@ +package com.atsuishio.superbwarfare.recipe; + +import com.atsuishio.superbwarfare.component.ModDataComponents; +import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.init.ModRecipes; +import com.atsuishio.superbwarfare.item.common.ammo.box.AmmoBox; +import com.atsuishio.superbwarfare.tools.AmmoType; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.NonNullList; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.CraftingBookCategory; +import net.minecraft.world.item.crafting.CraftingInput; +import net.minecraft.world.item.crafting.CustomRecipe; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.ParametersAreNonnullByDefault; + +public class AmmoBoxExtractAmmoRecipe extends CustomRecipe { + + public AmmoBoxExtractAmmoRecipe(CraftingBookCategory pCategory) { + super(pCategory); + } + + @Override + @ParametersAreNonnullByDefault + public boolean matches(CraftingInput input, Level level) { + var hasAmmoBox = false; + var ammoBoxItem = ItemStack.EMPTY; + + for (var item : input.items()) { + if (item.getItem() instanceof AmmoBox) { + if (hasAmmoBox) return false; + hasAmmoBox = true; + ammoBoxItem = item; + } else if (!item.isEmpty()) { + return false; + } + } + + var data = ammoBoxItem.get(ModDataComponents.AMMO_BOX_INFO); + if (data == null) return false; + + var typeString = data.type(); + var type = AmmoType.getType(typeString); + if (type == null) return false; + + return type.get(ammoBoxItem) > 0; + } + + @Override + @ParametersAreNonnullByDefault + public @NotNull ItemStack assemble(CraftingInput input, HolderLookup.Provider registries) { + AmmoType type = null; + + for (var item : input.items()) { + if (item.getItem() instanceof AmmoBox) { + var data = item.get(ModDataComponents.AMMO_BOX_INFO); + assert data != null; + type = AmmoType.getType(data.type()); + break; + } + } + + assert type != null; + + // 也许这边有更好的方案? + return switch (type) { + case HANDGUN -> new ItemStack(ModItems.HANDGUN_AMMO.get()); + case RIFLE -> new ItemStack(ModItems.RIFLE_AMMO.get()); + case SHOTGUN -> new ItemStack(ModItems.SHOTGUN_AMMO.get()); + case SNIPER -> new ItemStack(ModItems.SNIPER_AMMO.get()); + case HEAVY -> new ItemStack(ModItems.HEAVY_AMMO.get()); + default -> throw new IllegalStateException("Unexpected value: " + type); + }; + } + + @Override + public @NotNull NonNullList getRemainingItems(@NotNull CraftingInput input) { + var remaining = super.getRemainingItems(input); + + for (int i = 0; i < input.items().size(); i++) { + var item = input.getItem(i); + if (item.getItem() instanceof AmmoBox) { + var ammoBox = item.copy(); + + var data = ammoBox.get(ModDataComponents.AMMO_BOX_INFO); + assert data != null; + AmmoType type = AmmoType.getType(data.type()); + + assert type != null; + type.add(ammoBox, -1); + remaining.set(i, ammoBox); + + break; + } + } + + return remaining; + } + + @Override + public boolean canCraftInDimensions(int pWidth, int pHeight) { + return true; + } + + @Override + public @NotNull RecipeSerializer getSerializer() { + return ModRecipes.AMMO_BOX_ADD_AMMO_SERIALIZER.get(); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/recipe/PotionMortarShellRecipe.java b/src/main/java/com/atsuishio/superbwarfare/recipe/PotionMortarShellRecipe.java new file mode 100644 index 000000000..99ce5b470 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/recipe/PotionMortarShellRecipe.java @@ -0,0 +1,76 @@ +package com.atsuishio.superbwarfare.recipe; + +import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.init.ModRecipes; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.component.DataComponents; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.alchemy.PotionContents; +import net.minecraft.world.item.crafting.CraftingBookCategory; +import net.minecraft.world.item.crafting.CraftingInput; +import net.minecraft.world.item.crafting.CustomRecipe; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.ParametersAreNonnullByDefault; + +public class PotionMortarShellRecipe extends CustomRecipe { + + public PotionMortarShellRecipe(CraftingBookCategory pCategory) { + super(pCategory); + } + + @Override + public boolean matches(@NotNull CraftingInput input, @NotNull Level pLevel) { + if (input.width() == 3 && input.height() == 3) { + for (int i = 0; i < input.width(); ++i) { + for (int j = 0; j < input.height(); ++j) { + int index = i + j * input.width(); + + ItemStack itemstack = input.getItem(index); + + if (index % 2 == 0) { + if (i == 1 && j == 1) { + if (!itemstack.is(Items.LINGERING_POTION)) { + return false; + } + } else if (!itemstack.isEmpty()) { + return false; + } + } else if (!itemstack.is(ModItems.MORTAR_SHELL.get())) { + return false; + } + } + } + return true; + } else { + return false; + } + } + + @Override + @ParametersAreNonnullByDefault + public @NotNull ItemStack assemble(CraftingInput input, HolderLookup.Provider registries) { + ItemStack stack = input.getItem(1 + input.width()); + if (!stack.is(Items.LINGERING_POTION)) { + return ItemStack.EMPTY; + } else { + ItemStack res = new ItemStack(ModItems.POTION_MORTAR_SHELL.get(), 4); + res.set(DataComponents.POTION_CONTENTS, res.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY)); + + return res; + } + } + + @Override + public boolean canCraftInDimensions(int pWidth, int pHeight) { + return pWidth >= 2 && pHeight >= 2; + } + + @Override + public @NotNull RecipeSerializer getSerializer() { + return ModRecipes.POTION_MORTAR_SHELL_SERIALIZER.get(); + } +}