Supersized Assembly

- Added option to add recipes for mechanical crafter exclusively, with a maximum grid of 9x9
- Cleaned up recipe registry foundation
- Fixed recipe type namespace issue
This commit is contained in:
simibubi 2020-01-19 23:10:00 +01:00
parent 40e9a1ee41
commit f48f5fe101
10 changed files with 210 additions and 54 deletions

View file

@ -3,18 +3,22 @@ package com.simibubi.create;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.components.crafter.MechanicalCraftingRecipe;
import com.simibubi.create.modules.contraptions.components.crusher.CrushingRecipe; import com.simibubi.create.modules.contraptions.components.crusher.CrushingRecipe;
import com.simibubi.create.modules.contraptions.components.fan.SplashingRecipe; import com.simibubi.create.modules.contraptions.components.fan.SplashingRecipe;
import com.simibubi.create.modules.contraptions.components.mixer.MixingRecipe; import com.simibubi.create.modules.contraptions.components.mixer.MixingRecipe;
import com.simibubi.create.modules.contraptions.components.press.PressingRecipe; import com.simibubi.create.modules.contraptions.components.press.PressingRecipe;
import com.simibubi.create.modules.contraptions.components.saw.CuttingRecipe; import com.simibubi.create.modules.contraptions.components.saw.CuttingRecipe;
import com.simibubi.create.modules.contraptions.processing.ProcessingRecipe;
import com.simibubi.create.modules.contraptions.processing.ProcessingRecipeSerializer; import com.simibubi.create.modules.contraptions.processing.ProcessingRecipeSerializer;
import com.simibubi.create.modules.contraptions.processing.ProcessingRecipeSerializer.IRecipeFactory;
import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunUpgradeRecipe; import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunUpgradeRecipe;
import net.minecraft.inventory.IInventory; import net.minecraft.inventory.IInventory;
import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.IRecipeSerializer; import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.item.crafting.IRecipeType; import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.Registry;
import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.event.RegistryEvent;
@ -22,46 +26,58 @@ import net.minecraftforge.event.RegistryEvent;
public enum AllRecipes { public enum AllRecipes {
BLOCKZAPPER_UPGRADE(BuilderGunUpgradeRecipe.Serializer::new, IRecipeType.CRAFTING), BLOCKZAPPER_UPGRADE(BuilderGunUpgradeRecipe.Serializer::new, IRecipeType.CRAFTING),
CRUSHING(() -> new ProcessingRecipeSerializer<>(CrushingRecipe::new), Types.CRUSHING), MECHANICAL_CRAFTING(MechanicalCraftingRecipe.Serializer::new),
SPLASHING(() -> new ProcessingRecipeSerializer<>(SplashingRecipe::new), Types.SPLASHING), CRUSHING(processingSerializer(CrushingRecipe::new)),
PRESSING(() -> new ProcessingRecipeSerializer<>(PressingRecipe::new), Types.PRESSING), SPLASHING(processingSerializer(SplashingRecipe::new)),
CUTTING(() -> new ProcessingRecipeSerializer<>(CuttingRecipe::new), Types.CUTTING), PRESSING(processingSerializer(PressingRecipe::new)),
MIXING(() -> new ProcessingRecipeSerializer<>(MixingRecipe::new), Types.MIXING), CUTTING(processingSerializer(CuttingRecipe::new)),
MIXING(processingSerializer(MixingRecipe::new)),
; ;
public static class Types {
public static IRecipeType<CrushingRecipe> CRUSHING = register("crushing");
public static IRecipeType<SplashingRecipe> SPLASHING = register("splashing");
public static IRecipeType<PressingRecipe> PRESSING = register("pressing");
public static IRecipeType<CuttingRecipe> CUTTING = register("cutting");
public static IRecipeType<MixingRecipe> MIXING = register("mixing");
static <T extends IRecipe<?>> IRecipeType<T> register(final String key) {
return Registry.register(Registry.RECIPE_TYPE, new ResourceLocation(key), new IRecipeType<T>() {
public String toString() {
return key;
}
});
}
}
public IRecipeSerializer<?> serializer; public IRecipeSerializer<?> serializer;
public Supplier<IRecipeSerializer<?>> supplier; public Supplier<IRecipeSerializer<?>> supplier;
public IRecipeType<? extends IRecipe<? extends IInventory>> type; public IRecipeType<? extends IRecipe<? extends IInventory>> type;
@SuppressWarnings("unchecked")
public <T extends IRecipeType<?>> T getType() {
return (T) type;
}
private AllRecipes(Supplier<IRecipeSerializer<?>> supplier) {
this(supplier, null);
}
private AllRecipes(Supplier<IRecipeSerializer<?>> supplier, private AllRecipes(Supplier<IRecipeSerializer<?>> supplier,
IRecipeType<? extends IRecipe<? extends IInventory>> type) { IRecipeType<? extends IRecipe<? extends IInventory>> existingType) {
this.supplier = supplier; this.supplier = supplier;
this.type = type; this.type = existingType;
} }
public static void register(RegistryEvent.Register<IRecipeSerializer<?>> event) { public static void register(RegistryEvent.Register<IRecipeSerializer<?>> event) {
ShapedRecipe.setCraftingSize(9, 9);
for (AllRecipes r : AllRecipes.values()) { for (AllRecipes r : AllRecipes.values()) {
if (r.type == null)
r.type = customType(Lang.asId(r.name()));
r.serializer = r.supplier.get(); r.serializer = r.supplier.get();
ResourceLocation location = new ResourceLocation(Create.ID, Lang.asId(r.name())); ResourceLocation location = new ResourceLocation(Create.ID, Lang.asId(r.name()));
event.getRegistry().register(r.serializer.setRegistryName(location)); event.getRegistry().register(r.serializer.setRegistryName(location));
} }
} }
private static <T extends IRecipe<?>> IRecipeType<T> customType(String id) {
return Registry.register(Registry.RECIPE_TYPE, new ResourceLocation(Create.ID, id), new IRecipeType<T>() {
public String toString() {
return Create.ID + ":" + id;
}
});
}
private static Supplier<IRecipeSerializer<?>> processingSerializer(IRecipeFactory<? extends ProcessingRecipe<?>> factory) {
return () -> new ProcessingRecipeSerializer<>(factory);
}
} }

View file

@ -0,0 +1,31 @@
package com.simibubi.create.modules.contraptions.components.crafter;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.modules.contraptions.components.crafter.RecipeGridHandler.GroupedItems;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.item.ItemStack;
public class MechanicalCraftingInventory extends CraftingInventory {
private static Container dummyContainer = new Container(null, -1) {
public boolean canInteractWith(PlayerEntity playerIn) {
return false;
}
};
public MechanicalCraftingInventory(GroupedItems items) {
super(dummyContainer, items.width, items.height);
for (int y = 0; y < items.height; y++) {
for (int x = 0; x < items.width; x++) {
ItemStack stack = items.grid.get(Pair.of(x + items.minX, y + items.minY));
setInventorySlotContents(x + (items.height - y - 1) * items.width,
stack == null ? ItemStack.EMPTY : stack.copy());
}
}
}
}

View file

@ -0,0 +1,58 @@
package com.simibubi.create.modules.contraptions.components.crafter;
import com.google.gson.JsonObject;
import com.simibubi.create.AllRecipes;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
public class MechanicalCraftingRecipe extends ShapedRecipe {
public MechanicalCraftingRecipe(ResourceLocation idIn, String groupIn, int recipeWidthIn, int recipeHeightIn,
NonNullList<Ingredient> recipeItemsIn, ItemStack recipeOutputIn) {
super(idIn, groupIn, recipeWidthIn, recipeHeightIn, recipeItemsIn, recipeOutputIn);
}
private static MechanicalCraftingRecipe fromShaped(ShapedRecipe recipe) {
return new MechanicalCraftingRecipe(recipe.getId(), recipe.getGroup(), recipe.getWidth(), recipe.getHeight(),
recipe.getIngredients(), recipe.getRecipeOutput());
}
@Override
public boolean matches(CraftingInventory inv, World worldIn) {
return inv instanceof MechanicalCraftingInventory && super.matches(inv, worldIn);
}
@Override
public IRecipeType<?> getType() {
return AllRecipes.MECHANICAL_CRAFTING.type;
}
@Override
public IRecipeSerializer<?> getSerializer() {
return AllRecipes.MECHANICAL_CRAFTING.serializer;
}
public static class Serializer extends ShapedRecipe.Serializer {
@Override
public ShapedRecipe read(ResourceLocation recipeId, JsonObject json) {
return fromShaped(super.read(recipeId, json));
}
@Override
public ShapedRecipe read(ResourceLocation recipeId, PacketBuffer buffer) {
return fromShaped(super.read(recipeId, buffer));
}
}
}

View file

@ -14,12 +14,11 @@ import org.apache.commons.lang3.tuple.Pair;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllRecipes;
import com.simibubi.create.modules.contraptions.components.crafter.MechanicalCrafterBlock.Pointing; import com.simibubi.create.modules.contraptions.components.crafter.MechanicalCrafterBlock.Pointing;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.CraftingInventory; import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipeType; import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
@ -116,31 +115,18 @@ public class RecipeGridHandler {
} }
public static ItemStack tryToApplyRecipe(World world, GroupedItems items) { public static ItemStack tryToApplyRecipe(World world, GroupedItems items) {
CraftingInventory craftinginventory = getCraftingInventory(items); items.calcStats();
CraftingInventory craftinginventory = new MechanicalCraftingInventory(items);
ItemStack result = world.getRecipeManager().getRecipe(IRecipeType.CRAFTING, craftinginventory, world) ItemStack result = world.getRecipeManager().getRecipe(IRecipeType.CRAFTING, craftinginventory, world)
.map(r -> r.getCraftingResult(craftinginventory)).orElse(null); .map(r -> r.getCraftingResult(craftinginventory)).orElse(null);
if (result == null)
result = world.getRecipeManager()
.getRecipe(AllRecipes.MECHANICAL_CRAFTING.getType(), craftinginventory, world)
.map(r -> r.getCraftingResult(craftinginventory)).orElse(null);
return result; return result;
} }
private static CraftingInventory getCraftingInventory(GroupedItems items) {
items.calcStats();
CraftingInventory craftinginventory = new CraftingInventory(new Container(null, -1) {
public boolean canInteractWith(PlayerEntity playerIn) {
return false;
}
}, items.width, items.height);
for (int y = 0; y < items.height; y++) {
for (int x = 0; x < items.width; x++) {
ItemStack stack = items.grid.get(Pair.of(x + items.minX, y + items.minY));
craftinginventory.setInventorySlotContents(x + (items.height - y - 1) * items.width,
stack == null ? ItemStack.EMPTY : stack.copy());
}
}
return craftinginventory;
}
public static class GroupedItems { public static class GroupedItems {
Map<Pair<Integer, Integer>, ItemStack> grid = new HashMap<>(); Map<Pair<Integer, Integer>, ItemStack> grid = new HashMap<>();
int minX, minY, maxX, maxY, width, height; int minX, minY, maxX, maxY, width, height;

View file

@ -141,7 +141,7 @@ public class CrushingWheelControllerTileEntity extends SyncedTileEntity implemen
} }
private void applyRecipe() { private void applyRecipe() {
Optional<CrushingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.CRUSHING, inventory, Optional<CrushingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.CRUSHING.getType(), inventory,
world); world);
if (recipe.isPresent()) { if (recipe.isPresent()) {
@ -200,7 +200,7 @@ public class CrushingWheelControllerTileEntity extends SyncedTileEntity implemen
private void insertItem(ItemEntity entity) { private void insertItem(ItemEntity entity) {
inventory.clear(); inventory.clear();
inventory.setInventorySlotContents(0, entity.getItem()); inventory.setInventorySlotContents(0, entity.getItem());
Optional<CrushingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.CRUSHING, inventory, Optional<CrushingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.CRUSHING.getType(), inventory,
world); world);
inventory.remainingTime = recipe.isPresent() ? recipe.get().getProcessingDuration() : 100; inventory.remainingTime = recipe.isPresent() ? recipe.get().getProcessingDuration() : 100;

View file

@ -257,7 +257,7 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
public Optional<PressingRecipe> getRecipe(ItemStack item) { public Optional<PressingRecipe> getRecipe(ItemStack item) {
pressingInv.setInventorySlotContents(0, item); pressingInv.setInventorySlotContents(0, item);
Optional<PressingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.PRESSING, pressingInv, Optional<PressingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.PRESSING.getType(), pressingInv,
world); world);
return recipe; return recipe;
} }

View file

@ -292,7 +292,7 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity {
private List<? extends IRecipe<?>> getRecipes() { private List<? extends IRecipe<?>> getRecipes() {
List<IRecipe<?>> startedSearch = RecipeFinder.get(cuttingRecipesKey, world, List<IRecipe<?>> startedSearch = RecipeFinder.get(cuttingRecipesKey, world,
RecipeConditions.isOfType(IRecipeType.STONECUTTING, AllRecipes.Types.CUTTING)); RecipeConditions.isOfType(IRecipeType.STONECUTTING, AllRecipes.CUTTING.getType()));
return startedSearch.stream().filter(RecipeConditions.outputMatchesFilter(filtering)) return startedSearch.stream().filter(RecipeConditions.outputMatchesFilter(filtering))
.filter(RecipeConditions.firstIngredientMatches(inventory.getStackInSlot(0))) .filter(RecipeConditions.firstIngredientMatches(inventory.getStackInSlot(0)))
.collect(Collectors.toList()); .collect(Collectors.toList());

View file

@ -105,7 +105,7 @@ public class InWorldProcessing {
if (type == Type.SPLASHING) { if (type == Type.SPLASHING) {
splashingInv.setInventorySlotContents(0, stack); splashingInv.setInventorySlotContents(0, stack);
Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING, Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.SPLASHING.getType(),
splashingInv, world); splashingInv, world);
return recipe.isPresent(); return recipe.isPresent();
} }
@ -158,7 +158,7 @@ public class InWorldProcessing {
private static List<ItemStack> process(ItemStack stack, Type type, World world) { private static List<ItemStack> process(ItemStack stack, Type type, World world) {
if (type == Type.SPLASHING) { if (type == Type.SPLASHING) {
splashingInv.setInventorySlotContents(0, stack); splashingInv.setInventorySlotContents(0, stack);
Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING, Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.SPLASHING.getType(),
splashingInv, world); splashingInv, world);
if (recipe.isPresent()) if (recipe.isPresent())
return applyRecipeOn(stack, recipe.get()); return applyRecipeOn(stack, recipe.get());

View file

@ -0,0 +1,28 @@
{
"type": "create:mechanical_crafting",
"pattern": [
"GI ",
"NNN"
],
"key": {
"G": {
"tag": "forge:dyes/green"
},
"I": {
"item": "create:iron_sheet"
},
"N": {
"item": "create:copper_nugget"
}
},
"result": {
"item": "create:circuit",
"count": 1
},
"conditions": [
{
"type": "create:module",
"module": "contraptions"
}
]
}

View file

@ -0,0 +1,37 @@
{
"type": "create:mechanical_crafting",
"pattern": [
"SAAA ",
"AABBI",
"ABBBI",
"ABBII",
" IIIO"
],
"key": {
"B": {
"item": "create:chorus_chrome_cube"
},
"A": {
"item": "create:iron_sheet"
},
"I": {
"item": "minecraft:iron_block"
},
"S": {
"item": "create:shaft"
},
"O": {
"item": "minecraft:obsidian"
}
},
"result": {
"item": "create:motor",
"count": 1
},
"conditions": [
{
"type": "create:module",
"module": "contraptions"
}
]
}