From e95060f997540402ee45b74051bf8e5251a80a8e Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Mon, 16 Sep 2019 12:27:28 +0200 Subject: [PATCH] JEI integration & Placement QOL - Added JEI support for all added recipe types - Changed a few recipes - Kinetic blocks with shafts now try to connect to other shafts when placed --- build.gradle | 18 +++ .../java/com/simibubi/create/AllItems.java | 1 + .../java/com/simibubi/create/AllRecipes.java | 18 +-- .../com/simibubi/create/ClientEvents.java | 4 + .../{foundation/gui => }/ScreenResources.java | 10 +- .../compat/jei/AnimatedCrushingWheels.java | 58 ++++++++ .../create/compat/jei/AnimatedKinetics.java | 18 +++ .../create/compat/jei/AnimatedPress.java | 81 +++++++++++ .../compat/jei/BlastingViaFanCategory.java | 83 ++++++++++++ .../jei/BlockzapperUpgradeCategory.java | 126 ++++++++++++++++++ .../simibubi/create/compat/jei/CreateJEI.java | 117 ++++++++++++++++ .../create/compat/jei/CrushingCategory.java | 93 +++++++++++++ .../create/compat/jei/DoubleItemIcon.java | 61 +++++++++ .../create/compat/jei/PressingCategory.java | 85 ++++++++++++ .../compat/jei/ProcessingViaFanCategory.java | 85 ++++++++++++ .../compat/jei/ScreenResourceWrapper.java | 33 +++++ .../compat/jei/SmokingViaFanCategory.java | 49 +++++++ .../create/compat/jei/SplashingCategory.java | 82 ++++++++++++ .../foundation/gui/ScreenElementRenderer.java | 17 +++ .../foundation/gui/TextInputPromptScreen.java | 1 + .../foundation/gui/ToolSelectionScreen.java | 1 + .../foundation/gui/widgets/IconButton.java | 2 +- .../foundation/gui/widgets/Indicator.java | 2 +- .../contraptions/base/ProcessingRecipe.java | 29 ++-- .../base/ProcessingRecipeSerializer.java | 4 +- .../base/RotatedPillarKineticBlock.java | 19 +++ .../contraptions/generators/MotorBlock.java | 9 ++ .../receivers/EncasedFanBlock.java | 23 +++- .../constructs/MechanicalPistonBlock.java | 45 ++++++- .../relays/EncasedShaftBlock.java | 4 +- .../contraptions/relays/GearboxBlock.java | 50 +++++++ .../placementHandgun/BuilderGunItem.java | 2 +- .../placementHandgun/BuilderGunScreen.java | 2 +- .../BuilderGunUpgradeRecipe.java | 34 +++-- .../placementHandgun/PlacementPatterns.java | 2 +- .../symmetry/SymmetryWandScreen.java | 2 +- .../logistics/block/EntityDetectorBlock.java | 25 +++- .../logistics/block/FlexcrateScreen.java | 6 +- .../logistics/block/StockswitchBlock.java | 40 ++++-- .../logistics/block/StockswitchScreen.java | 4 +- .../block/SchematicTableScreen.java | 6 +- .../block/SchematicannonScreen.java | 2 +- .../client/BlueprintHotbarOverlay.java | 2 +- .../client/SchematicEditScreen.java | 2 +- .../schematics/client/tools/Tools.java | 2 +- .../resources/assets/create/lang/en_us.json | 35 +++++ .../assets/create/models/item/gold_sheet.json | 6 + .../assets/create/textures/gui/recipes1.png | Bin 0 -> 27001 bytes .../assets/create/textures/gui/recipes2.png | Bin 0 -> 22198 bytes .../create/textures/item/gold_sheet.png | Bin 0 -> 439 bytes .../create/recipes/crafting/belt_funnel.json | 10 +- .../create/recipes/crafting/belt_support.json | 26 ++++ .../data/create/recipes/crafting/clutch.json | 2 +- .../data/create/recipes/crafting/contact.json | 2 +- .../create/recipes/crafting/encased_fan.json | 2 +- .../recipes/crafting/entity_detector.json | 2 +- .../create/recipes/crafting/extractor.json | 4 +- .../create/recipes/crafting/flexcrate.json | 4 +- .../create/recipes/crafting/gearshift.json | 2 +- .../create/recipes/crafting/harvester.json | 2 +- .../data/create/recipes/crafting/motor.json | 2 +- .../recipes/crafting/redstone_bridge.json | 2 +- .../create/recipes/crafting/stockswitch.json | 2 +- .../create/recipes/pressing/gold_ingot.json | 16 +++ 64 files changed, 1381 insertions(+), 97 deletions(-) rename src/main/java/com/simibubi/create/{foundation/gui => }/ScreenResources.java (94%) create mode 100644 src/main/java/com/simibubi/create/compat/jei/AnimatedCrushingWheels.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/AnimatedKinetics.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/AnimatedPress.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/BlastingViaFanCategory.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/BlockzapperUpgradeCategory.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/CreateJEI.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/CrushingCategory.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/DoubleItemIcon.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/PressingCategory.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/ProcessingViaFanCategory.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/ScreenResourceWrapper.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/SmokingViaFanCategory.java create mode 100644 src/main/java/com/simibubi/create/compat/jei/SplashingCategory.java create mode 100644 src/main/resources/assets/create/models/item/gold_sheet.json create mode 100644 src/main/resources/assets/create/textures/gui/recipes1.png create mode 100644 src/main/resources/assets/create/textures/gui/recipes2.png create mode 100644 src/main/resources/assets/create/textures/item/gold_sheet.png create mode 100644 src/main/resources/data/create/recipes/crafting/belt_support.json create mode 100644 src/main/resources/data/create/recipes/pressing/gold_ingot.json diff --git a/build.gradle b/build.gradle index bbde7129e..605b20a5e 100644 --- a/build.gradle +++ b/build.gradle @@ -57,8 +57,26 @@ minecraft { } } +repositories { + maven { + // location of the maven that hosts JEI files + name = "Progwml6 maven" + url = "https://dvs1.progwml6.com/files/maven/" + } + maven { + // location of a maven mirror for JEI files, as a fallback + name = "ModMaven" + url = "https://modmaven.k-4u.nl" + } +} + dependencies { minecraft 'net.minecraftforge:forge:1.14.4-28.0.102' + + // compile against the JEI API but do not include it at runtime + compileOnly fg.deobf("mezz.jei:jei-1.14.4:6.0.0.10:api") + // at runtime, use the full JEI jar + runtimeOnly fg.deobf("mezz.jei:jei-1.14.4:6.0.0.10") } jar { diff --git a/src/main/java/com/simibubi/create/AllItems.java b/src/main/java/com/simibubi/create/AllItems.java index c579bb095..d4e04920a 100644 --- a/src/main/java/com/simibubi/create/AllItems.java +++ b/src/main/java/com/simibubi/create/AllItems.java @@ -42,6 +42,7 @@ public enum AllItems { __MATERIALS__(), IRON_SHEET(ingredient()), + GOLD_SHEET(ingredient()), ANDESITE_ALLOY_CUBE(ingredient()), BLAZE_BRASS_CUBE(ingredient()), CHORUS_CHROME_CUBE(ingredient(Rarity.UNCOMMON)), diff --git a/src/main/java/com/simibubi/create/AllRecipes.java b/src/main/java/com/simibubi/create/AllRecipes.java index 16cb3af25..f77466f78 100644 --- a/src/main/java/com/simibubi/create/AllRecipes.java +++ b/src/main/java/com/simibubi/create/AllRecipes.java @@ -18,19 +18,10 @@ import net.minecraftforge.event.RegistryEvent; public enum AllRecipes { - PLACEMENT_HANDGUN_UPGRADE(BuilderGunUpgradeRecipe.Serializer::new, IRecipeType.CRAFTING), - - CRUSHING(() -> { - return new ProcessingRecipeSerializer<>(CrushingRecipe::new); - }, Types.CRUSHING), - - SPLASHING(() -> { - return new ProcessingRecipeSerializer<>(SplashingRecipe::new); - }, Types.SPLASHING), - - PRESSING(() -> { - return new ProcessingRecipeSerializer<>(PressingRecipe::new); - }, Types.PRESSING), + PLACEMENT_HANDGUN_UPGRADE(BuilderGunUpgradeRecipe.Serializer::new, Types.BLOCKZAPPER_UPGRADE), + CRUSHING(() -> new ProcessingRecipeSerializer<>(CrushingRecipe::new), Types.CRUSHING), + SPLASHING(() -> new ProcessingRecipeSerializer<>(SplashingRecipe::new), Types.SPLASHING), + PRESSING(() -> new ProcessingRecipeSerializer<>(PressingRecipe::new), Types.PRESSING), ; @@ -38,6 +29,7 @@ public enum AllRecipes { public static IRecipeType CRUSHING = register("crushing"); public static IRecipeType SPLASHING = register("splashing"); public static IRecipeType PRESSING = register("pressing"); + public static IRecipeType BLOCKZAPPER_UPGRADE = register("blockzapper_upgrade"); static > IRecipeType register(final String key) { return Registry.register(Registry.RECIPE_TYPE, new ResourceLocation(key), new IRecipeType() { diff --git a/src/main/java/com/simibubi/create/ClientEvents.java b/src/main/java/com/simibubi/create/ClientEvents.java index 66c95f5ea..07e0ed649 100644 --- a/src/main/java/com/simibubi/create/ClientEvents.java +++ b/src/main/java/com/simibubi/create/ClientEvents.java @@ -3,6 +3,7 @@ package com.simibubi.create; import java.util.ArrayList; import java.util.List; +import com.simibubi.create.compat.jei.AnimatedKinetics; import com.simibubi.create.foundation.block.IBlockWithScrollableValue; import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.utility.TooltipHelper; @@ -36,6 +37,9 @@ public class ClientEvents { public static void onTick(ClientTickEvent event) { if (event.phase == Phase.START) return; + + AnimatedKinetics.tick(); + if (!isGameActive()) return; diff --git a/src/main/java/com/simibubi/create/foundation/gui/ScreenResources.java b/src/main/java/com/simibubi/create/ScreenResources.java similarity index 94% rename from src/main/java/com/simibubi/create/foundation/gui/ScreenResources.java rename to src/main/java/com/simibubi/create/ScreenResources.java index c65cc285a..a62fbedc1 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/ScreenResources.java +++ b/src/main/java/com/simibubi/create/ScreenResources.java @@ -1,6 +1,4 @@ -package com.simibubi.create.foundation.gui; - -import com.simibubi.create.Create; +package com.simibubi.create; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.AbstractGui; @@ -34,6 +32,12 @@ public enum ScreenResources { STOCKSWITCH_BOUND_LEFT("flex_crate_and_stockpile_switch.png", 234, 129, 7, 21), STOCKSWITCH_BOUND_RIGHT("flex_crate_and_stockpile_switch.png", 241, 129, 7, 21), + // JEI + CRUSHING_RECIPE("recipes1.png", 177, 109), + FAN_RECIPE("recipes1.png", 0, 128, 177, 109), + BLOCKZAPPER_UPGRADE_RECIPE("recipes2.png", 144, 66), + PRESSER_RECIPE("recipes2.png", 0, 108, 177, 109), + // Widgets PALETTE_BUTTON("palette_picker.png", 0, 236, 20, 20), TEXT_INPUT("widgets.png", 0, 28, 194, 47), diff --git a/src/main/java/com/simibubi/create/compat/jei/AnimatedCrushingWheels.java b/src/main/java/com/simibubi/create/compat/jei/AnimatedCrushingWheels.java new file mode 100644 index 000000000..6145c3c3d --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/AnimatedCrushingWheels.java @@ -0,0 +1,58 @@ +package com.simibubi.create.compat.jei; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.gui.ScreenElementRenderer; + +import net.minecraft.block.BlockState; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.util.Direction.Axis; + +public class AnimatedCrushingWheels extends AnimatedKinetics { + + @Override + public int getWidth() { + return 150; + } + + @Override + public int getHeight() { + return 100; + } + + @Override + public void draw(int xOffset, int yOffset) { + GlStateManager.enableDepthTest(); + GlStateManager.translatef(xOffset, yOffset, 0); + GlStateManager.translatef(-45, 10, 0); + GlStateManager.rotatef(22.5f, 0, 1, 0); + GlStateManager.scaled(.45f, .45f, .45f); + ScreenElementRenderer.renderBlock(this::leftWheel); + ScreenElementRenderer.renderBlock(this::rightWheel); + } + + private BlockState leftWheel() { + float angle = getCurrentAngle(); + GlStateManager.translatef(-50, 0, 0); + + float t = 25; + GlStateManager.translatef(t, -t, t); + GlStateManager.rotated(angle, 0, 0, 1); + GlStateManager.translatef(-t, t, -t); + + return AllBlocks.CRUSHING_WHEEL.get().getDefaultState().with(BlockStateProperties.AXIS, Axis.X); + } + + private BlockState rightWheel() { + float angle = -getCurrentAngle(); + GlStateManager.translatef(50, 0, 0); + + float t = 25; + GlStateManager.translatef(t, -t, t); + GlStateManager.rotated(angle, 0, 0, 1); + GlStateManager.translatef(-t, t, -t); + + return AllBlocks.CRUSHING_WHEEL.get().getDefaultState().with(BlockStateProperties.AXIS, Axis.X); + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/AnimatedKinetics.java b/src/main/java/com/simibubi/create/compat/jei/AnimatedKinetics.java new file mode 100644 index 000000000..59571a2a9 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/AnimatedKinetics.java @@ -0,0 +1,18 @@ +package com.simibubi.create.compat.jei; + +import mezz.jei.api.gui.drawable.IDrawable; +import net.minecraft.client.Minecraft; + +public abstract class AnimatedKinetics implements IDrawable { + + protected static int ticks; + + public static void tick() { + ticks++; + } + + public static float getCurrentAngle() { + return ((ticks + Minecraft.getInstance().getRenderPartialTicks()) * 4f) % 360; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/AnimatedPress.java b/src/main/java/com/simibubi/create/compat/jei/AnimatedPress.java new file mode 100644 index 000000000..55fee1255 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/AnimatedPress.java @@ -0,0 +1,81 @@ +package com.simibubi.create.compat.jei; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.gui.ScreenElementRenderer; + +import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; + +public class AnimatedPress extends AnimatedKinetics { + + @Override + public int getWidth() { + return 50; + } + + @Override + public int getHeight() { + return 100; + } + + @Override + public void draw(int xOffset, int yOffset) { + GlStateManager.pushMatrix(); + GlStateManager.enableDepthTest(); + GlStateManager.translatef(xOffset, yOffset, 0); + GlStateManager.rotatef(-15.5f, 1, 0, 0); + GlStateManager.rotatef(22.5f, 0, 1, 0); + GlStateManager.translatef(-45, -5, 0); + GlStateManager.scaled(.45f, .45f, .45f); + + GlStateManager.pushMatrix(); + ScreenElementRenderer.renderBlock(this::shaft); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + ScreenElementRenderer.renderBlock(this::body); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + ScreenElementRenderer.renderBlock(this::head); + GlStateManager.popMatrix(); + + GlStateManager.popMatrix(); + } + + private BlockState shaft() { + float t = 25; + GlStateManager.translatef(t, -t, t); + GlStateManager.rotated(getCurrentAngle() * 2, 0, 0, 1); + GlStateManager.translatef(-t, t, -t); + return AllBlocks.SHAFT.get().getDefaultState().with(BlockStateProperties.AXIS, Axis.X); + } + + private BlockState body() { + return AllBlocks.MECHANICAL_PRESS.get().getDefaultState().with(BlockStateProperties.HORIZONTAL_FACING, + Direction.EAST); + } + + private BlockState head() { + float cycle = (ticks + Minecraft.getInstance().getRenderPartialTicks()) % 30; + float verticalOffset = 0; + if (cycle < 10) { + float progress = cycle / 10; + verticalOffset = -(progress * progress * progress); + } else if (cycle < 15) { + verticalOffset = -1; + } else if (cycle < 20) { + verticalOffset = -1 + (1 - ((20 - cycle) / 5)); + } else { + verticalOffset = 0; + } + GlStateManager.translated(0, -verticalOffset * 50, 0); + return AllBlocks.MECHANICAL_PRESS_HEAD.get().getDefaultState().with(BlockStateProperties.HORIZONTAL_FACING, + Direction.EAST); + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/BlastingViaFanCategory.java b/src/main/java/com/simibubi/create/compat/jei/BlastingViaFanCategory.java new file mode 100644 index 000000000..d1fd3164d --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/BlastingViaFanCategory.java @@ -0,0 +1,83 @@ +package com.simibubi.create.compat.jei; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.AllItems; +import com.simibubi.create.Create; +import com.simibubi.create.ScreenResources; +import com.simibubi.create.foundation.gui.ScreenElementRenderer; +import com.simibubi.create.foundation.utility.Lang; + +import mezz.jei.api.gui.drawable.IDrawable; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.FlowingFluidBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.item.crafting.AbstractCookingRecipe; +import net.minecraft.util.ResourceLocation; + +public class BlastingViaFanCategory extends ProcessingViaFanCategory { + + private static ResourceLocation ID = new ResourceLocation(Create.ID, "blasting_via_fan"); + private IDrawable icon; + + public BlastingViaFanCategory() { + icon = new DoubleItemIcon(() -> new ItemStack(AllItems.PROPELLER.get()), + () -> new ItemStack(Items.LAVA_BUCKET)); + } + + @Override + public IDrawable getIcon() { + return icon; + } + + @Override + public ResourceLocation getUid() { + return ID; + } + + @Override + public Class getRecipeClass() { + return AbstractCookingRecipe.class; + } + + @Override + public String getTitle() { + return Lang.translate("recipe.blastingViaFan"); + } + + @Override + public IDrawable getBackground() { + return new ScreenResourceWrapper(ScreenResources.FAN_RECIPE); + } + + @Override + public void renderAttachedBlock() { + BlockState state = Blocks.LAVA.getDefaultState().with(FlowingFluidBlock.LEVEL, 8); + // This is stupid + GlStateManager.pushMatrix(); + GlStateManager.translated(0, 0, 200); + GlStateManager.enableRescaleNormal(); + + GlStateManager.pushMatrix(); + GlStateManager.translated(0, 200, 0); + GlStateManager.rotated(90, 1, 0, 0); + ScreenElementRenderer.renderBlock(() -> state); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + GlStateManager.translated(0, 200, 0); + GlStateManager.rotated(90, 1, 0, 0); + GlStateManager.rotated(270, 0, 0, 1); + ScreenElementRenderer.renderBlock(() -> state); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + GlStateManager.translated(-103, -100, 0); + ScreenElementRenderer.renderBlock(() -> state); + GlStateManager.popMatrix(); + + GlStateManager.popMatrix(); + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/BlockzapperUpgradeCategory.java b/src/main/java/com/simibubi/create/compat/jei/BlockzapperUpgradeCategory.java new file mode 100644 index 000000000..a0516c980 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/BlockzapperUpgradeCategory.java @@ -0,0 +1,126 @@ +package com.simibubi.create.compat.jei; + +import static com.simibubi.create.ScreenResources.BLOCKZAPPER_UPGRADE_RECIPE; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.AllItems; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.gui.ScreenElementRenderer; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunUpgradeRecipe; + +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.item.crafting.ShapedRecipe; +import net.minecraft.util.NonNullList; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.ITextComponent; + +public class BlockzapperUpgradeCategory implements IRecipeCategory { + + private static ResourceLocation ID = new ResourceLocation(Create.ID, "blockzapper_upgrade"); + private IDrawable icon; + + public BlockzapperUpgradeCategory() { + icon = new DoubleItemIcon(() -> new ItemStack(AllItems.PLACEMENT_HANDGUN.get()), + () -> ItemStack.EMPTY); // replace with uparrow when available + } + + @Override + public IDrawable getIcon() { + return icon; + } + + @Override + public ResourceLocation getUid() { + return ID; + } + + @Override + public Class getRecipeClass() { + return BuilderGunUpgradeRecipe.class; + } + + @Override + public String getTitle() { + return Lang.translate("recipe.blockzapperUpgrade"); + } + + @Override + public IDrawable getBackground() { + return new ScreenResourceWrapper(BLOCKZAPPER_UPGRADE_RECIPE); + } + + @Override + public void setIngredients(BuilderGunUpgradeRecipe recipe, IIngredients ingredients) { + ingredients.setInputIngredients(recipe.getIngredients()); + ingredients.setOutput(VanillaTypes.ITEM, recipe.getRecipeOutput()); + } + + @Override + public void setRecipe(IRecipeLayout recipeLayout, BuilderGunUpgradeRecipe recipe, IIngredients ingredients) { + IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); + ShapedRecipe shape = recipe.getRecipe(); + NonNullList shapedIngredients = shape.getIngredients(); + + int top = 0; + int left = 0; + + int i = 0; + for (int y = 0; y < shape.getRecipeHeight(); y++) { + for (int x = 0; x < shape.getRecipeWidth(); x++) { + itemStacks.init(i, true, left + x * 18, top + y * 18); + itemStacks.set(i, Arrays.asList(shapedIngredients.get(i).getMatchingStacks())); + i++; + } + } +// itemStacks.init(9, false, BLOCKZAPPER_UPGRADE_RECIPE.width / 2 - 9, BLOCKZAPPER_UPGRADE_RECIPE.height - 18 - 10); +// itemStacks.set(9, recipe.getRecipeOutput()); + } + + @Override + public List getTooltipStrings(BuilderGunUpgradeRecipe recipe, double mouseX, double mouseY) { + List list = new ArrayList<>(); + if (mouseX < 91 || mouseX > 91 + 52 || mouseY < 1 || mouseY > 53) + return list; + list.addAll(recipe.getRecipeOutput() + .getTooltip(Minecraft.getInstance().player, + Minecraft.getInstance().gameSettings.advancedItemTooltips ? ITooltipFlag.TooltipFlags.ADVANCED + : ITooltipFlag.TooltipFlags.NORMAL) + .stream().map(ITextComponent::getFormattedText).collect(Collectors.toList())); + return list; + } + + @Override + public void draw(BuilderGunUpgradeRecipe recipe, double mouseX, double mouseY) { + FontRenderer font = Minecraft.getInstance().fontRenderer; + String componentName = Lang + .translate("blockzapper.component." + recipe.getUpgradedComponent().name().toLowerCase()); + String text = "+ " + recipe.getTier().color + componentName; + font.drawStringWithShadow(text, + (BLOCKZAPPER_UPGRADE_RECIPE.width - font.getStringWidth(text)) / 2, 57, 0x8B8B8B); + + GlStateManager.pushMatrix(); + GlStateManager.translated(126, 0, 0); + GlStateManager.scaled(3.5, 3.5, 3.5); + GlStateManager.translated(-10, 0, 0); + GlStateManager.color3f(1, 1, 1); + GlStateManager.enableDepthTest(); + ScreenElementRenderer.render3DItem(() -> recipe.getRecipeOutput()); + GlStateManager.popMatrix(); + } +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java new file mode 100644 index 000000000..084157341 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java @@ -0,0 +1,117 @@ +package com.simibubi.create.compat.jei; + +import java.util.List; +import java.util.stream.Collectors; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllRecipes; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.utility.Lang; + +import mezz.jei.api.IModPlugin; +import mezz.jei.api.JeiPlugin; +import mezz.jei.api.registration.IRecipeCatalystRegistration; +import mezz.jei.api.registration.IRecipeCategoryRegistration; +import mezz.jei.api.registration.IRecipeRegistration; +import mezz.jei.api.registration.ISubtypeRegistration; +import net.minecraft.client.Minecraft; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.IRecipeType; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.TextFormatting; + +@JeiPlugin +public class CreateJEI implements IModPlugin { + + private static ResourceLocation ID = new ResourceLocation(Create.ID, "jei_plugin"); + private CrushingCategory crushingCategory; + private SplashingCategory splashingCategory; + private SmokingViaFanCategory smokingCategory; + private PressingCategory pressingCategory; + private BlastingViaFanCategory blastingCategory; + private BlockzapperUpgradeCategory blockzapperCategory; + + @Override + public ResourceLocation getPluginUid() { + return ID; + } + + public CreateJEI() { + crushingCategory = new CrushingCategory(); + splashingCategory = new SplashingCategory(); + pressingCategory = new PressingCategory(); + smokingCategory = new SmokingViaFanCategory(); + blastingCategory = new BlastingViaFanCategory(); + blockzapperCategory = new BlockzapperUpgradeCategory(); + } + + @Override + public void registerItemSubtypes(ISubtypeRegistration registration) { + registration.useNbtForSubtypes(AllItems.PLACEMENT_HANDGUN.item); + } + + @Override + public void registerCategories(IRecipeCategoryRegistration registration) { + registration.addRecipeCategories(crushingCategory, splashingCategory, pressingCategory, smokingCategory, + blastingCategory, blockzapperCategory); + } + + @Override + public void registerRecipes(IRecipeRegistration registration) { + registration.addRecipes(findRecipes(AllRecipes.CRUSHING), crushingCategory.getUid()); + registration.addRecipes(findRecipes(AllRecipes.SPLASHING), splashingCategory.getUid()); + registration.addRecipes(findRecipes(AllRecipes.PRESSING), pressingCategory.getUid()); + registration.addRecipes(findRecipes(AllRecipes.PLACEMENT_HANDGUN_UPGRADE), blockzapperCategory.getUid()); + registration.addRecipes(findRecipesByType(IRecipeType.SMOKING), smokingCategory.getUid()); + registration.addRecipes(findRecipesByTypeExcluding(IRecipeType.SMELTING, IRecipeType.SMOKING), + blastingCategory.getUid()); + } + + @Override + public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) { + ItemStack fan = new ItemStack(AllBlocks.ENCASED_FAN.get()); + + ItemStack splashingFan = fan.copy() + .setDisplayName(new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.splashing.fan"))); + ItemStack smokingFan = fan.copy().setDisplayName( + new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.smokingViaFan.fan"))); + ItemStack blastingFan = fan.copy().setDisplayName( + new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.blastingViaFan.fan"))); + + registration.addRecipeCatalyst(new ItemStack(AllBlocks.CRUSHING_WHEEL.get()), crushingCategory.getUid()); + registration.addRecipeCatalyst(splashingFan, splashingCategory.getUid()); + registration.addRecipeCatalyst(smokingFan, smokingCategory.getUid()); + registration.addRecipeCatalyst(blastingFan, blastingCategory.getUid()); + registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_PRESS.get()), pressingCategory.getUid()); + registration.addRecipeCatalyst(new ItemStack(AllItems.PLACEMENT_HANDGUN.get()), blockzapperCategory.getUid()); + } + + private static List> findRecipes(AllRecipes recipe) { + return findRecipesByType(recipe.type); + } + + private static List> findRecipesByType(IRecipeType type) { + return Minecraft.getInstance().world.getRecipeManager().getRecipes().stream().filter(r -> r.getType() == type) + .collect(Collectors.toList()); + } + + private static List> findRecipesByTypeExcluding(IRecipeType type, IRecipeType excludingType) { + List> byType = findRecipesByType(type); + List> byExcludingType = findRecipesByType(excludingType); + byType.removeIf(recipe -> { + for (IRecipe r : byExcludingType) { + ItemStack[] matchingStacks = recipe.getIngredients().get(0).getMatchingStacks(); + if (matchingStacks.length == 0) + return true; + if (r.getIngredients().get(0).test(matchingStacks[0])) + return true; + } + return false; + }); + return byType; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/CrushingCategory.java b/src/main/java/com/simibubi/create/compat/jei/CrushingCategory.java new file mode 100644 index 000000000..27d8eb0b3 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/CrushingCategory.java @@ -0,0 +1,93 @@ +package com.simibubi.create.compat.jei; + +import java.util.Arrays; +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.Create; +import com.simibubi.create.ScreenResources; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.modules.contraptions.base.StochasticOutput; +import com.simibubi.create.modules.contraptions.receivers.CrushingRecipe; + +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.TextFormatting; + +public class CrushingCategory implements IRecipeCategory { + + private static ResourceLocation ID = new ResourceLocation(Create.ID, "crushing"); + private AnimatedCrushingWheels crushingWheels = new AnimatedCrushingWheels(); + private IDrawable icon; + + public CrushingCategory() { + icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.CRUSHING_WHEEL.get()), + () -> new ItemStack(AllItems.FLOUR.get())); + } + + @Override + public ResourceLocation getUid() { + return ID; + } + + @Override + public Class getRecipeClass() { + return CrushingRecipe.class; + } + + @Override + public String getTitle() { + return Lang.translate("recipe.crushing"); + } + + @Override + public IDrawable getBackground() { + return new ScreenResourceWrapper(ScreenResources.CRUSHING_RECIPE); + } + + @Override + public IDrawable getIcon() { + return icon; + } + + @Override + public void setIngredients(CrushingRecipe recipe, IIngredients ingredients) { + ingredients.setInputIngredients(recipe.getIngredients()); + ingredients.setOutputs(VanillaTypes.ITEM, recipe.getPossibleOutputs()); + } + + @Override + public void setRecipe(IRecipeLayout recipeLayout, CrushingRecipe recipe, IIngredients ingredients) { + IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); + itemStacks.init(0, true, 60, 2); + itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks())); + + List results = recipe.getRollableResults(); + for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) { + itemStacks.init(outputIndex + 1, false, 60 + 18 * outputIndex, 78); + itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack()); + } + + itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> { + if (input) + return; + StochasticOutput output = results.get(slotIndex - 1); + if (output.getChance() != 1) + tooltip.add(1, TextFormatting.GOLD + + Lang.translate("recipe.processing.chance", (int) (output.getChance() * 100))); + }); + } + + @Override + public void draw(CrushingRecipe recipe, double mouseX, double mouseY) { + crushingWheels.draw(100, 47); + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/DoubleItemIcon.java b/src/main/java/com/simibubi/create/compat/jei/DoubleItemIcon.java new file mode 100644 index 000000000..b1bc80078 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/DoubleItemIcon.java @@ -0,0 +1,61 @@ +package com.simibubi.create.compat.jei; + +import java.util.function.Supplier; + +import com.mojang.blaze3d.platform.GlStateManager; + +import mezz.jei.api.gui.drawable.IDrawable; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.item.ItemStack; + +public class DoubleItemIcon implements IDrawable { + + private Supplier primarySupplier; + private Supplier secondarySupplier; + private ItemStack primaryStack; + private ItemStack secondaryStack; + + public DoubleItemIcon(Supplier primary, Supplier secondary) { + this.primarySupplier = primary; + this.secondarySupplier = secondary; + } + + @Override + public int getWidth() { + return 18; + } + + @Override + public int getHeight() { + return 18; + } + + @Override + public void draw(int xOffset, int yOffset) { + if (primaryStack == null) { + primaryStack = primarySupplier.get(); + secondaryStack = secondarySupplier.get(); + } + + RenderHelper.enableGUIStandardItemLighting(); + GlStateManager.color4f(1, 1, 1, 1); + GlStateManager.enableDepthTest(); + GlStateManager.pushMatrix(); + GlStateManager.translated(xOffset, yOffset, 0); + + GlStateManager.pushMatrix(); + GlStateManager.translated(1, 1, 0); + Minecraft.getInstance().getItemRenderer().renderItemIntoGUI(primaryStack, 0, 0); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + GlStateManager.translated(10, 10, 100); + GlStateManager.scaled(.5, .5, .5); + Minecraft.getInstance().getItemRenderer().renderItemIntoGUI(secondaryStack, 0, 0); + GlStateManager.popMatrix(); + + GlStateManager.popMatrix(); + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/PressingCategory.java b/src/main/java/com/simibubi/create/compat/jei/PressingCategory.java new file mode 100644 index 000000000..d4cc98ead --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/PressingCategory.java @@ -0,0 +1,85 @@ +package com.simibubi.create.compat.jei; + +import java.util.Arrays; +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.Create; +import com.simibubi.create.ScreenResources; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.modules.contraptions.base.StochasticOutput; +import com.simibubi.create.modules.contraptions.receivers.PressingRecipe; + +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; + +public class PressingCategory implements IRecipeCategory { + + private AnimatedPress press; + private static ResourceLocation ID = new ResourceLocation(Create.ID, "pressing"); + private IDrawable icon; + + public PressingCategory() { + icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.MECHANICAL_PRESS.get()), + () -> new ItemStack(AllItems.IRON_SHEET.get())); + press = new AnimatedPress(); + } + + @Override + public IDrawable getIcon() { + return icon; + } + + @Override + public ResourceLocation getUid() { + return ID; + } + + @Override + public Class getRecipeClass() { + return PressingRecipe.class; + } + + @Override + public String getTitle() { + return Lang.translate("recipe.pressing"); + } + + @Override + public IDrawable getBackground() { + return new ScreenResourceWrapper(ScreenResources.PRESSER_RECIPE); + } + + @Override + public void setIngredients(PressingRecipe recipe, IIngredients ingredients) { + ingredients.setInputIngredients(recipe.getIngredients()); + ingredients.setOutputs(VanillaTypes.ITEM, recipe.getPossibleOutputs()); + } + + @Override + public void setRecipe(IRecipeLayout recipeLayout, PressingRecipe recipe, IIngredients ingredients) { + IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); + itemStacks.init(0, true, 27, 60); + itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks())); + + List results = recipe.getRollableResults(); + for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) { + itemStacks.init(outputIndex + 1, false, 113 + 19 * outputIndex, 60); + itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack()); + } + } + + @Override + public void draw(PressingRecipe recipe, double mouseX, double mouseY) { + press.draw(ScreenResources.PRESSER_RECIPE.width / 2, 30); + + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/ProcessingViaFanCategory.java b/src/main/java/com/simibubi/create/compat/jei/ProcessingViaFanCategory.java new file mode 100644 index 000000000..8711e518c --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/ProcessingViaFanCategory.java @@ -0,0 +1,85 @@ +package com.simibubi.create.compat.jei; + +import java.util.Arrays; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.ScreenResources; +import com.simibubi.create.foundation.gui.ScreenElementRenderer; + +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.block.BlockState; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.util.Direction.Axis; + +public abstract class ProcessingViaFanCategory> implements IRecipeCategory { + + @Override + public IDrawable getBackground() { + return new ScreenResourceWrapper(ScreenResources.FAN_RECIPE); + } + + @Override + public void setIngredients(T recipe, IIngredients ingredients) { + ingredients.setInputIngredients(recipe.getIngredients()); + ingredients.setOutput(VanillaTypes.ITEM, recipe.getRecipeOutput()); + } + + @Override + public void setRecipe(IRecipeLayout recipeLayout, T recipe, IIngredients ingredients) { + IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); + itemStacks.init(0, true, 20, 67); + itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks())); + + itemStacks.init(1, false, 139, 67); + itemStacks.set(1, recipe.getRecipeOutput()); + } + + @Override + public void draw(T recipe, double mouseX, double mouseY) { + GlStateManager.pushMatrix(); + GlStateManager.color3f(1, 1, 1); + GlStateManager.enableDepthTest(); + + GlStateManager.translated(28, 42, 0); + GlStateManager.rotated(10.5, -1f, 0, 0); + GlStateManager.rotated(15.5, 0, 1, 0); + GlStateManager.scaled(.6f, .6f, .6f); + ScreenElementRenderer.renderBlock(this::renderFanCasing); + + GlStateManager.pushMatrix(); + float angle = AnimatedKinetics.getCurrentAngle() * 12; + float t = 25; + GlStateManager.translatef(t, -t, t); + GlStateManager.rotated(angle, 0, 0, 1); + GlStateManager.translatef(-t, t, -t); + ScreenElementRenderer.renderBlock(this::renderFanInner); + GlStateManager.popMatrix(); + + GlStateManager.translated(-10, 0, 95); + GlStateManager.rotated(7, 0, 1, 0); + renderAttachedBlock(); + + GlStateManager.popMatrix(); + + } + + protected BlockState renderFanCasing() { + + return AllBlocks.ENCASED_FAN.get().getDefaultState().with(BlockStateProperties.AXIS, Axis.X); + } + + protected BlockState renderFanInner() { + + return AllBlocks.ENCASED_FAN_INNER.get().getDefaultState().with(BlockStateProperties.AXIS, Axis.X); + } + + public abstract void renderAttachedBlock(); + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/ScreenResourceWrapper.java b/src/main/java/com/simibubi/create/compat/jei/ScreenResourceWrapper.java new file mode 100644 index 000000000..e6f9f3526 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/ScreenResourceWrapper.java @@ -0,0 +1,33 @@ +package com.simibubi.create.compat.jei; + +import com.simibubi.create.ScreenResources; + +import mezz.jei.api.gui.drawable.IDrawable; +import net.minecraft.client.gui.AbstractGui; + +public class ScreenResourceWrapper implements IDrawable { + + private ScreenResources resource; + + public ScreenResourceWrapper(ScreenResources resource) { + this.resource = resource; + } + + @Override + public int getWidth() { + return resource.width; + } + + @Override + public int getHeight() { + return resource.height; + } + + @Override + public void draw(int xOffset, int yOffset) { + resource.bind(); + AbstractGui.blit(xOffset, yOffset, 0, resource.startX, resource.startY, resource.width, resource.height, 256, + 256); + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/SmokingViaFanCategory.java b/src/main/java/com/simibubi/create/compat/jei/SmokingViaFanCategory.java new file mode 100644 index 000000000..d81083c57 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/SmokingViaFanCategory.java @@ -0,0 +1,49 @@ +package com.simibubi.create.compat.jei; + +import com.simibubi.create.AllItems; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.gui.ScreenElementRenderer; +import com.simibubi.create.foundation.utility.Lang; + +import mezz.jei.api.gui.drawable.IDrawable; +import net.minecraft.block.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.item.crafting.SmokingRecipe; +import net.minecraft.util.ResourceLocation; + +public class SmokingViaFanCategory extends ProcessingViaFanCategory { + + private static ResourceLocation ID = new ResourceLocation(Create.ID, "smoking_via_fan"); + private IDrawable icon; + + public SmokingViaFanCategory() { + icon = new DoubleItemIcon(() -> new ItemStack(AllItems.PROPELLER.get()), + () -> new ItemStack(Items.BLAZE_POWDER)); + } + + @Override + public IDrawable getIcon() { + return icon; + } + + @Override + public ResourceLocation getUid() { + return ID; + } + + @Override + public Class getRecipeClass() { + return SmokingRecipe.class; + } + + @Override + public String getTitle() { + return Lang.translate("recipe.smokingViaFan"); + } + + @Override + public void renderAttachedBlock() { + ScreenElementRenderer.renderBlock(() -> Blocks.FIRE.getDefaultState()); + } +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/compat/jei/SplashingCategory.java b/src/main/java/com/simibubi/create/compat/jei/SplashingCategory.java new file mode 100644 index 000000000..24eb86065 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/SplashingCategory.java @@ -0,0 +1,82 @@ +package com.simibubi.create.compat.jei; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.AllItems; +import com.simibubi.create.Create; +import com.simibubi.create.ScreenResources; +import com.simibubi.create.foundation.gui.ScreenElementRenderer; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.modules.contraptions.receivers.SplashingRecipe; + +import mezz.jei.api.gui.drawable.IDrawable; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.FlowingFluidBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.ResourceLocation; + +public class SplashingCategory extends ProcessingViaFanCategory { + + private static ResourceLocation ID = new ResourceLocation(Create.ID, "splashing"); + private IDrawable icon; + + public SplashingCategory() { + icon = new DoubleItemIcon(() -> new ItemStack(AllItems.PROPELLER.get()), + () -> new ItemStack(Items.WATER_BUCKET)); + } + + @Override + public IDrawable getIcon() { + return icon; + } + + @Override + public ResourceLocation getUid() { + return ID; + } + + @Override + public Class getRecipeClass() { + return SplashingRecipe.class; + } + + @Override + public String getTitle() { + return Lang.translate("recipe.splashing"); + } + + @Override + public IDrawable getBackground() { + return new ScreenResourceWrapper(ScreenResources.FAN_RECIPE); + } + + @Override + public void renderAttachedBlock() { + BlockState state = Blocks.WATER.getDefaultState().with(FlowingFluidBlock.LEVEL, 8); + // This is stupid + GlStateManager.pushMatrix(); + GlStateManager.translated(0, 0, 200); + + GlStateManager.pushMatrix(); + GlStateManager.translated(0, 200, 0); + GlStateManager.rotated(90, 1, 0, 0); + ScreenElementRenderer.renderBlock(() -> state); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + GlStateManager.translated(0, 200, 0); + GlStateManager.rotated(90, 1, 0, 0); + GlStateManager.rotated(270, 0, 0, 1); + ScreenElementRenderer.renderBlock(() -> state); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + GlStateManager.translated(-103, -100, 0); + ScreenElementRenderer.renderBlock(() -> state); + GlStateManager.popMatrix(); + + GlStateManager.popMatrix(); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/ScreenElementRenderer.java b/src/main/java/com/simibubi/create/foundation/gui/ScreenElementRenderer.java index f622f5739..db6dad85a 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/ScreenElementRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/gui/ScreenElementRenderer.java @@ -2,13 +2,19 @@ package com.simibubi.create.foundation.gui; import java.util.function.Supplier; +import org.lwjgl.opengl.GL11; + import com.mojang.blaze3d.platform.GlStateManager; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.texture.AtlasTexture; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; public class ScreenElementRenderer { @@ -46,6 +52,17 @@ public class ScreenElementRenderer { mc.getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE); mc.getBlockRendererDispatcher().renderBlockBrightness(toRender, 1); + if (!toRender.getFluidState().isEmpty()) { + RenderHelper.disableStandardItemLighting(); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + bufferbuilder.setTranslation(0, -300, 0); + bufferbuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); + mc.getBlockRendererDispatcher().renderFluid(new BlockPos(0, 300, 0), mc.world, bufferbuilder, toRender.getFluidState()); + Tessellator.getInstance().draw(); + bufferbuilder.setTranslation(0, 0, 0); + } + GlStateManager.disableAlphaTest(); GlStateManager.disableRescaleNormal(); diff --git a/src/main/java/com/simibubi/create/foundation/gui/TextInputPromptScreen.java b/src/main/java/com/simibubi/create/foundation/gui/TextInputPromptScreen.java index 934cea3d7..ea0e9d294 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/TextInputPromptScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/TextInputPromptScreen.java @@ -4,6 +4,7 @@ import java.util.function.Consumer; import org.lwjgl.glfw.GLFW; +import com.simibubi.create.ScreenResources; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.client.gui.widget.TextFieldWidget; diff --git a/src/main/java/com/simibubi/create/foundation/gui/ToolSelectionScreen.java b/src/main/java/com/simibubi/create/foundation/gui/ToolSelectionScreen.java index 441ccd322..8d16c4312 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/ToolSelectionScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/ToolSelectionScreen.java @@ -5,6 +5,7 @@ import java.util.function.Consumer; import com.mojang.blaze3d.platform.GlStateManager; import com.simibubi.create.AllKeys; +import com.simibubi.create.ScreenResources; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.modules.schematics.client.tools.Tools; diff --git a/src/main/java/com/simibubi/create/foundation/gui/widgets/IconButton.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/IconButton.java index 8e716cbd7..78b27b044 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widgets/IconButton.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/IconButton.java @@ -1,7 +1,7 @@ package com.simibubi.create.foundation.gui.widgets; import com.mojang.blaze3d.platform.GlStateManager; -import com.simibubi.create.foundation.gui.ScreenResources; +import com.simibubi.create.ScreenResources; import net.minecraft.client.Minecraft; import net.minecraft.util.ResourceLocation; diff --git a/src/main/java/com/simibubi/create/foundation/gui/widgets/Indicator.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/Indicator.java index c8a42ef42..e1b41c2b3 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widgets/Indicator.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/Indicator.java @@ -1,7 +1,7 @@ package com.simibubi.create.foundation.gui.widgets; import com.google.common.collect.ImmutableList; -import com.simibubi.create.foundation.gui.ScreenResources; +import com.simibubi.create.ScreenResources; public class Indicator extends AbstractSimiWidget { diff --git a/src/main/java/com/simibubi/create/modules/contraptions/base/ProcessingRecipe.java b/src/main/java/com/simibubi/create/modules/contraptions/base/ProcessingRecipe.java index 66d83ad50..0d552fa13 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/base/ProcessingRecipe.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/base/ProcessingRecipe.java @@ -2,6 +2,7 @@ package com.simibubi.create.modules.contraptions.base; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import com.simibubi.create.AllRecipes; @@ -16,15 +17,15 @@ import net.minecraft.util.ResourceLocation; public abstract class ProcessingRecipe implements IRecipe { protected final List ingredients; - protected final List results; + private final List results; private final IRecipeType type; private final IRecipeSerializer serializer; protected final ResourceLocation id; protected final String group; protected final int processingDuration; - public ProcessingRecipe(AllRecipes recipeType, ResourceLocation id, String group, - List ingredients, List results, int processingDuration) { + public ProcessingRecipe(AllRecipes recipeType, ResourceLocation id, String group, List ingredients, + List results, int processingDuration) { this.type = recipeType.type; this.serializer = recipeType.serializer; this.id = id; @@ -40,18 +41,14 @@ public abstract class ProcessingRecipe implements IRecipe< nonnulllist.addAll(this.ingredients); return nonnulllist; } - + public int getProcessingDuration() { return processingDuration; } - - public List getAllResults() { - return results; - } - + public List rollResults() { List stacks = new ArrayList<>(); - for (StochasticOutput output : results) { + for (StochasticOutput output : getRollableResults()) { ItemStack stack = output.rollOutput(); if (!stack.isEmpty()) stacks.add(stack); @@ -71,7 +68,7 @@ public abstract class ProcessingRecipe implements IRecipe< @Override public ItemStack getRecipeOutput() { - return results.isEmpty() ? ItemStack.EMPTY : results.get(0).getStack(); + return getRollableResults().isEmpty() ? ItemStack.EMPTY : getRollableResults().get(0).getStack(); } @Override @@ -83,7 +80,7 @@ public abstract class ProcessingRecipe implements IRecipe< public IRecipeSerializer getSerializer() { return serializer; } - + @Override public String getGroup() { return group; @@ -93,4 +90,12 @@ public abstract class ProcessingRecipe implements IRecipe< public IRecipeType getType() { return type; } + + public List getRollableResults() { + return results; + } + + public List getPossibleOutputs() { + return getRollableResults().stream().map(output -> output.getStack()).collect(Collectors.toList()); + } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/base/ProcessingRecipeSerializer.java b/src/main/java/com/simibubi/create/modules/contraptions/base/ProcessingRecipeSerializer.java index 2df6a9bf9..d6cc2e9c8 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/base/ProcessingRecipeSerializer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/base/ProcessingRecipeSerializer.java @@ -70,8 +70,8 @@ public class ProcessingRecipeSerializer> buffer.writeInt(recipe.ingredients.size()); recipe.ingredients.forEach(i -> i.write(buffer)); - buffer.writeInt(recipe.results.size()); - recipe.results.forEach(i -> i.write(buffer)); + buffer.writeInt(recipe.getRollableResults().size()); + recipe.getRollableResults().forEach(i -> i.write(buffer)); buffer.writeInt(recipe.processingDuration); } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/base/RotatedPillarKineticBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/base/RotatedPillarKineticBlock.java index 182644828..fdd23d59d 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/base/RotatedPillarKineticBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/base/RotatedPillarKineticBlock.java @@ -7,6 +7,7 @@ import net.minecraft.state.EnumProperty; import net.minecraft.state.StateContainer; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; import net.minecraft.util.Rotation; public abstract class RotatedPillarKineticBlock extends KineticBlock { @@ -35,6 +36,24 @@ public abstract class RotatedPillarKineticBlock extends KineticBlock { return state; } } + + public Axis getPreferredAxis(BlockItemUseContext context) { + Axis prefferedAxis = null; + for (Direction side : Direction.values()) { + BlockState blockState = context.getWorld().getBlockState(context.getPos().offset(side)); + if (blockState.getBlock() instanceof IRotate) { + if (((IRotate) blockState.getBlock()).hasShaftTowards(context.getWorld(), context.getPos().offset(side), + blockState, side.getOpposite())) + if (prefferedAxis != null && prefferedAxis != side.getAxis()) { + prefferedAxis = null; + break; + } else { + prefferedAxis = side.getAxis(); + } + } + } + return prefferedAxis; + } @Override protected void fillStateContainer(StateContainer.Builder builder) { diff --git a/src/main/java/com/simibubi/create/modules/contraptions/generators/MotorBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/generators/MotorBlock.java index faffc09a4..6e0d0074e 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/generators/MotorBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/generators/MotorBlock.java @@ -7,6 +7,7 @@ import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; +import net.minecraft.item.BlockItemUseContext; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; @@ -40,6 +41,14 @@ public class MotorBlock extends HorizontalKineticBlock return new MotorTileEntity(); } + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + Direction preferred = getPreferredHorizontalFacing(context); + if (context.isPlacerSneaking() || preferred == null) + return super.getStateForPlacement(context); + return getDefaultState().with(HORIZONTAL_FACING, preferred); + } + // IRotate: @Override diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanBlock.java index ea253fccd..089a2cfae 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanBlock.java @@ -1,13 +1,16 @@ package com.simibubi.create.modules.contraptions.receivers; +import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.block.IWithTileEntity; import com.simibubi.create.modules.contraptions.relays.EncasedShaftBlock; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.item.BlockItemUseContext; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorld; @@ -29,13 +32,27 @@ public class EncasedFanBlock extends EncasedShaftBlock implements IWithTileEntit public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) { notifyFanTile(worldIn, pos); - + if (worldIn.isRemote || state.get(AXIS).isHorizontal()) return; - + withTileEntityDo(worldIn, pos, EncasedFanTileEntity::updateGenerator); } - + + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + if (context.isPlacerSneaking()) + return super.getStateForPlacement(context); + BlockState blockState = context.getWorld() + .getBlockState(context.getPos().offset(context.getFace().getOpposite())); + if (AllBlocks.ENCASED_FAN.typeOf(blockState)) + return getDefaultState().with(AXIS, blockState.get(AXIS)); + Axis preferred = getPreferredAxis(context); + if (preferred != null) + return getDefaultState().with(AXIS, preferred); + return super.getStateForPlacement(context); + } + protected void notifyFanTile(IWorld world, BlockPos pos) { withTileEntityDo(world, pos, EncasedFanTileEntity::updateFrontBlock); } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MechanicalPistonBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MechanicalPistonBlock.java index 2ced37da1..32fc8531d 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MechanicalPistonBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MechanicalPistonBlock.java @@ -2,6 +2,7 @@ package com.simibubi.create.modules.contraptions.receivers.constructs; import com.simibubi.create.AllBlocks; import com.simibubi.create.CreateConfig; +import com.simibubi.create.modules.contraptions.base.IRotate; import com.simibubi.create.modules.contraptions.base.KineticBlock; import net.minecraft.block.Block; @@ -19,7 +20,6 @@ import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.IStringSerializable; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShapes; @@ -63,13 +63,48 @@ public class MechanicalPistonBlock extends KineticBlock { @Override public BlockState getStateForPlacement(BlockItemUseContext context) { Direction facing = context.getNearestLookingDirection().getOpposite(); + BlockPos pos = context.getPos(); + World world = context.getWorld(); + boolean alongFirst = false; if (context.isPlacerSneaking()) facing = facing.getOpposite(); - Vec3d diff = context.getHitVec().subtract(new Vec3d(context.getPos())); - double firstCoord = facing.getAxis() == Axis.X ? diff.y : diff.x; - double secondCoord = facing.getAxis() == Axis.Z ? diff.y : diff.z; - boolean alongFirst = firstCoord + secondCoord < 1 ^ firstCoord < secondCoord; + if (facing.getAxis().isHorizontal()) { + alongFirst = facing.getAxis() == Axis.Z; + + Block blockAbove = world.getBlockState(pos.offset(Direction.UP)).getBlock(); + boolean shaftAbove = blockAbove instanceof IRotate && ((IRotate) blockAbove).hasShaftTowards(world, + pos.up(), world.getBlockState(pos.up()), Direction.DOWN); + Block blockBelow = world.getBlockState(pos.offset(Direction.DOWN)).getBlock(); + boolean shaftBelow = blockBelow instanceof IRotate && ((IRotate) blockBelow).hasShaftTowards(world, + pos.down(), world.getBlockState(pos.down()), Direction.UP); + + if (shaftAbove || shaftBelow) + alongFirst = facing.getAxis() == Axis.X; + } + + if (facing.getAxis().isVertical()) { + alongFirst = context.getPlacementHorizontalFacing().getAxis() == Axis.X; + Direction prefferedSide = null; + for (Direction side : Direction.values()) { + if (side.getAxis().isVertical()) + continue; + BlockState blockState = context.getWorld().getBlockState(context.getPos().offset(side)); + if (blockState.getBlock() instanceof IRotate) { + if (((IRotate) blockState.getBlock()).hasShaftTowards(context.getWorld(), + context.getPos().offset(side), blockState, side.getOpposite())) + if (prefferedSide != null && prefferedSide.getAxis() != side.getAxis()) { + prefferedSide = null; + break; + } else { + prefferedSide = side; + } + } + } + if (prefferedSide != null) { + alongFirst = prefferedSide.getAxis() == Axis.X; + } + } return this.getDefaultState().with(FACING, facing).with(STATE, PistonState.RETRACTED) .with(AXIS_ALONG_FIRST_COORDINATE, alongFirst); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/EncasedShaftBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/EncasedShaftBlock.java index 9301eb08f..48a0976a4 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/EncasedShaftBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/EncasedShaftBlock.java @@ -38,7 +38,9 @@ public class EncasedShaftBlock extends RotatedPillarKineticBlock { public BlockState getStateForPlacement(BlockItemUseContext context) { if (context.isPlacerSneaking()) return super.getStateForPlacement(context); - return this.getDefaultState().with(AXIS, context.getNearestLookingDirection().getAxis()); + Axis preferredAxis = getPreferredAxis(context); + return this.getDefaultState().with(AXIS, + preferredAxis == null ? context.getNearestLookingDirection().getAxis() : preferredAxis); } @Override diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/GearboxBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/GearboxBlock.java index 2abc89192..8e561381a 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/GearboxBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/GearboxBlock.java @@ -1,12 +1,16 @@ package com.simibubi.create.modules.contraptions.relays; +import com.simibubi.create.modules.contraptions.base.IRotate; import com.simibubi.create.modules.contraptions.base.RotatedPillarKineticBlock; +import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.material.PushReaction; +import net.minecraft.item.BlockItemUseContext; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; @@ -27,6 +31,52 @@ public class GearboxBlock extends RotatedPillarKineticBlock { return PushReaction.PUSH_ONLY; } + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + BlockState placedOnState = context.getWorld() + .getBlockState(context.getPos().offset(context.getFace().getOpposite())); + Block placedOn = placedOnState.getBlock(); + + if (!(placedOn instanceof IRotate) || !((IRotate) placedOn).hasShaftTowards(context.getWorld(), + context.getPos(), placedOnState, context.getFace())) + return getDefaultState().with(AXIS, context.getFace().getAxis()); + + Axis badAxis = context.getFace().getAxis(); + Axis otherBadAxis = null; + + for (Direction side : Direction.values()) { + if (side.getAxis() == badAxis) + continue; + + BlockState blockState = context.getWorld().getBlockState(context.getPos().offset(side)); + if (blockState.getBlock() instanceof IRotate) { + if (((IRotate) blockState.getBlock()).hasShaftTowards(context.getWorld(), context.getPos().offset(side), + blockState, side.getOpposite())) + if (otherBadAxis != null && otherBadAxis != side.getAxis()) { + otherBadAxis = null; + break; + } else { + otherBadAxis = side.getAxis(); + } + } + } + + boolean skipped = false; + for (Axis axis : Axis.values()) { + if (axis == badAxis) + continue; + if (!skipped && context.isPlacerSneaking() && (otherBadAxis == null || badAxis == null)) { + skipped = true; + continue; + } + if (axis == otherBadAxis) + continue; + return getDefaultState().with(AXIS, axis); + } + + return super.getStateForPlacement(context); + } + // IRotate: @Override diff --git a/src/main/java/com/simibubi/create/modules/curiosities/placementHandgun/BuilderGunItem.java b/src/main/java/com/simibubi/create/modules/curiosities/placementHandgun/BuilderGunItem.java index 8c4831f24..5ce44020e 100644 --- a/src/main/java/com/simibubi/create/modules/curiosities/placementHandgun/BuilderGunItem.java +++ b/src/main/java/com/simibubi/create/modules/curiosities/placementHandgun/BuilderGunItem.java @@ -72,7 +72,7 @@ public class BuilderGunItem extends Item { ; - protected TextFormatting color; + public TextFormatting color; private ComponentTier(TextFormatting color) { this.color = color; diff --git a/src/main/java/com/simibubi/create/modules/curiosities/placementHandgun/BuilderGunScreen.java b/src/main/java/com/simibubi/create/modules/curiosities/placementHandgun/BuilderGunScreen.java index 0aeb49d81..d0dfc3a4a 100644 --- a/src/main/java/com/simibubi/create/modules/curiosities/placementHandgun/BuilderGunScreen.java +++ b/src/main/java/com/simibubi/create/modules/curiosities/placementHandgun/BuilderGunScreen.java @@ -7,8 +7,8 @@ import org.lwjgl.opengl.GL11; import com.mojang.blaze3d.platform.GlStateManager; import com.simibubi.create.AllPackets; +import com.simibubi.create.ScreenResources; import com.simibubi.create.foundation.gui.AbstractSimiScreen; -import com.simibubi.create.foundation.gui.ScreenResources; import com.simibubi.create.foundation.gui.widgets.IconButton; import com.simibubi.create.foundation.gui.widgets.Indicator; import com.simibubi.create.foundation.gui.widgets.Indicator.State; diff --git a/src/main/java/com/simibubi/create/modules/curiosities/placementHandgun/BuilderGunUpgradeRecipe.java b/src/main/java/com/simibubi/create/modules/curiosities/placementHandgun/BuilderGunUpgradeRecipe.java index 0efa2b4f0..6f8cbf309 100644 --- a/src/main/java/com/simibubi/create/modules/curiosities/placementHandgun/BuilderGunUpgradeRecipe.java +++ b/src/main/java/com/simibubi/create/modules/curiosities/placementHandgun/BuilderGunUpgradeRecipe.java @@ -10,6 +10,7 @@ import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.ICraftingRecipe; import net.minecraft.item.crafting.IRecipeSerializer; +import net.minecraft.item.crafting.IRecipeType; import net.minecraft.item.crafting.ShapedRecipe; import net.minecraft.network.PacketBuffer; import net.minecraft.util.JSONUtils; @@ -31,7 +32,7 @@ public class BuilderGunUpgradeRecipe implements ICraftingRecipe { @Override public boolean matches(CraftingInventory inv, World worldIn) { - return recipe.matches(inv, worldIn); + return getRecipe().matches(inv, worldIn); } @Override @@ -40,7 +41,7 @@ public class BuilderGunUpgradeRecipe implements ICraftingRecipe { ItemStack handgun = inv.getStackInSlot(slot).copy(); if (!AllItems.PLACEMENT_HANDGUN.typeOf(handgun)) continue; - BuilderGunItem.setTier(component, tier, handgun); + BuilderGunItem.setTier(getUpgradedComponent(), getTier(), handgun); return handgun; } return ItemStack.EMPTY; @@ -49,7 +50,7 @@ public class BuilderGunUpgradeRecipe implements ICraftingRecipe { @Override public ItemStack getRecipeOutput() { ItemStack handgun = new ItemStack(AllItems.PLACEMENT_HANDGUN.get()); - BuilderGunItem.setTier(component, tier, handgun); + BuilderGunItem.setTier(getUpgradedComponent(), getTier(), handgun); return handgun; } @@ -60,9 +61,14 @@ public class BuilderGunUpgradeRecipe implements ICraftingRecipe { @Override public ResourceLocation getId() { - return recipe.getId(); + return getRecipe().getId(); } + @Override + public IRecipeType getType() { + return AllRecipes.Types.BLOCKZAPPER_UPGRADE; + } + @Override public IRecipeSerializer getSerializer() { return AllRecipes.PLACEMENT_HANDGUN_UPGRADE.serializer; @@ -90,10 +96,10 @@ public class BuilderGunUpgradeRecipe implements ICraftingRecipe { @Override public void write(PacketBuffer buffer, BuilderGunUpgradeRecipe recipe) { - IRecipeSerializer.CRAFTING_SHAPED.write(buffer, recipe.recipe); + IRecipeSerializer.CRAFTING_SHAPED.write(buffer, recipe.getRecipe()); - String name = recipe.component.name(); - String name2 = recipe.tier.name(); + String name = recipe.getUpgradedComponent().name(); + String name2 = recipe.getTier().name(); buffer.writeInt(name.length()); buffer.writeString(name); buffer.writeInt(name2.length()); @@ -104,7 +110,19 @@ public class BuilderGunUpgradeRecipe implements ICraftingRecipe { @Override public boolean canFit(int width, int height) { - return recipe.canFit(width, height); + return getRecipe().canFit(width, height); + } + + public ShapedRecipe getRecipe() { + return recipe; + } + + public Components getUpgradedComponent() { + return component; + } + + public ComponentTier getTier() { + return tier; } } diff --git a/src/main/java/com/simibubi/create/modules/curiosities/placementHandgun/PlacementPatterns.java b/src/main/java/com/simibubi/create/modules/curiosities/placementHandgun/PlacementPatterns.java index 0fffb637a..639bb7ed3 100644 --- a/src/main/java/com/simibubi/create/modules/curiosities/placementHandgun/PlacementPatterns.java +++ b/src/main/java/com/simibubi/create/modules/curiosities/placementHandgun/PlacementPatterns.java @@ -1,6 +1,6 @@ package com.simibubi.create.modules.curiosities.placementHandgun; -import com.simibubi.create.foundation.gui.ScreenResources; +import com.simibubi.create.ScreenResources; public enum PlacementPatterns { diff --git a/src/main/java/com/simibubi/create/modules/curiosities/symmetry/SymmetryWandScreen.java b/src/main/java/com/simibubi/create/modules/curiosities/symmetry/SymmetryWandScreen.java index 459a730b0..674fb3cea 100644 --- a/src/main/java/com/simibubi/create/modules/curiosities/symmetry/SymmetryWandScreen.java +++ b/src/main/java/com/simibubi/create/modules/curiosities/symmetry/SymmetryWandScreen.java @@ -4,8 +4,8 @@ import org.lwjgl.opengl.GL11; import com.mojang.blaze3d.platform.GlStateManager; import com.simibubi.create.AllPackets; +import com.simibubi.create.ScreenResources; import com.simibubi.create.foundation.gui.AbstractSimiScreen; -import com.simibubi.create.foundation.gui.ScreenResources; import com.simibubi.create.foundation.gui.widgets.Label; import com.simibubi.create.foundation.gui.widgets.ScrollInput; import com.simibubi.create.foundation.gui.widgets.SelectionScrollInput; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorBlock.java index 5aad21ed4..c10fde58c 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorBlock.java @@ -97,8 +97,27 @@ public class EntityDetectorBlock extends HorizontalBlock public BlockState getStateForPlacement(BlockItemUseContext context) { BlockState state = getDefaultState(); - if (context.getFace().getAxis().isHorizontal()) { - state = state.with(HORIZONTAL_FACING, context.getFace().getOpposite()); + Direction preferredFacing = null; + for (Direction face : Direction.values()) { + if (face.getAxis().isVertical()) + continue; + + BlockState blockState = context.getWorld().getBlockState(context.getPos().offset(face)); + if (AllBlocks.BELT.typeOf(blockState) + && blockState.get(BlockStateProperties.HORIZONTAL_FACING).getAxis() != face.getAxis() + && blockState.get(BeltBlock.SLOPE) == Slope.HORIZONTAL) + if (preferredFacing == null) + preferredFacing = face; + else { + preferredFacing = null; + break; + } + } + + if (preferredFacing != null) { + state = state.with(HORIZONTAL_FACING, preferredFacing); + } else if (context.getFace().getAxis().isHorizontal()) { + state = state.with(HORIZONTAL_FACING, context.getFace()); } else { state = state.with(HORIZONTAL_FACING, context.getPlacementHorizontalFacing()); } @@ -221,7 +240,7 @@ public class EntityDetectorBlock extends HorizontalBlock itemPositions.add(position); } } - + @Override public float getItemHitboxScale() { return 1.76f / 16f; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/FlexcrateScreen.java b/src/main/java/com/simibubi/create/modules/logistics/block/FlexcrateScreen.java index b573915f8..d148a057b 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/FlexcrateScreen.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/FlexcrateScreen.java @@ -1,14 +1,14 @@ package com.simibubi.create.modules.logistics.block; -import static com.simibubi.create.foundation.gui.ScreenResources.FLEXCRATE; -import static com.simibubi.create.foundation.gui.ScreenResources.PLAYER_INVENTORY; +import static com.simibubi.create.ScreenResources.FLEXCRATE; +import static com.simibubi.create.ScreenResources.PLAYER_INVENTORY; import com.mojang.blaze3d.platform.GlStateManager; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPackets; +import com.simibubi.create.ScreenResources; import com.simibubi.create.foundation.gui.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.ScreenElementRenderer; -import com.simibubi.create.foundation.gui.ScreenResources; import com.simibubi.create.foundation.gui.widgets.Label; import com.simibubi.create.foundation.gui.widgets.ScrollInput; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/StockswitchBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/StockswitchBlock.java index 765dc0ad3..23fa288d8 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/StockswitchBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/StockswitchBlock.java @@ -21,6 +21,7 @@ import net.minecraft.world.World; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.items.CapabilityItemHandler; public class StockswitchBlock extends HorizontalBlock { @@ -34,12 +35,12 @@ public class StockswitchBlock extends HorizontalBlock { public boolean isSolid(BlockState state) { return false; } - + @Override public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { updateObservedInventory(state, worldIn, pos); } - + @Override public void onNeighborChange(BlockState state, IWorldReader world, BlockPos pos, BlockPos neighbor) { if (world.isRemote()) @@ -48,32 +49,32 @@ public class StockswitchBlock extends HorizontalBlock { return; updateObservedInventory(state, world, pos); } - + private void updateObservedInventory(BlockState state, IWorldReader world, BlockPos pos) { StockswitchTileEntity te = (StockswitchTileEntity) world.getTileEntity(pos); if (te == null) return; te.updateCurrentLevel(); } - + private boolean isObserving(BlockState state, BlockPos pos, BlockPos observing) { return observing.equals(pos.offset(state.get(HORIZONTAL_FACING))); } - + @Override public boolean canConnectRedstone(BlockState state, IBlockReader world, BlockPos pos, Direction side) { return side != null && side.getOpposite() != state.get(HORIZONTAL_FACING); } - + @Override public boolean canProvidePower(BlockState state) { return true; } - + @Override public int getWeakPower(BlockState blockState, IBlockReader blockAccess, BlockPos pos, Direction side) { StockswitchTileEntity te = (StockswitchTileEntity) blockAccess.getTileEntity(pos); - return te == null || !te.powered ? 0 : 15 ; + return te == null || !te.powered ? 0 : 15; } @Override @@ -100,10 +101,27 @@ public class StockswitchBlock extends HorizontalBlock { public BlockState getStateForPlacement(BlockItemUseContext context) { BlockState state = getDefaultState(); - if (context.getFace().getAxis().isHorizontal()) { - state = state.with(HORIZONTAL_FACING, context.getFace().getOpposite()); + Direction preferredFacing = null; + for (Direction face : Direction.values()) { + if (face.getAxis().isVertical()) + continue; + + TileEntity te = context.getWorld().getTileEntity(context.getPos().offset(face)); + if (te != null && te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).isPresent()) + if (preferredFacing == null) + preferredFacing = face; + else { + preferredFacing = null; + break; + } + } + + if (preferredFacing != null) { + state = state.with(HORIZONTAL_FACING, preferredFacing); + } else if (context.getFace().getAxis().isHorizontal()) { + state = state.with(HORIZONTAL_FACING, context.getFace()); } else { - state = state.with(HORIZONTAL_FACING, context.getPlacementHorizontalFacing()); + state = state.with(HORIZONTAL_FACING, context.getPlacementHorizontalFacing().getOpposite()); } return state; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/StockswitchScreen.java b/src/main/java/com/simibubi/create/modules/logistics/block/StockswitchScreen.java index 3dcb21ba4..801e19772 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/StockswitchScreen.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/StockswitchScreen.java @@ -1,15 +1,15 @@ package com.simibubi.create.modules.logistics.block; -import static com.simibubi.create.foundation.gui.ScreenResources.STOCKSWITCH; +import static com.simibubi.create.ScreenResources.STOCKSWITCH; import java.util.Arrays; import com.mojang.blaze3d.platform.GlStateManager; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPackets; +import com.simibubi.create.ScreenResources; import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.ScreenElementRenderer; -import com.simibubi.create.foundation.gui.ScreenResources; import com.simibubi.create.foundation.gui.widgets.Label; import com.simibubi.create.foundation.gui.widgets.ScrollInput; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/modules/schematics/block/SchematicTableScreen.java b/src/main/java/com/simibubi/create/modules/schematics/block/SchematicTableScreen.java index 3a0b44198..86accd556 100644 --- a/src/main/java/com/simibubi/create/modules/schematics/block/SchematicTableScreen.java +++ b/src/main/java/com/simibubi/create/modules/schematics/block/SchematicTableScreen.java @@ -1,7 +1,7 @@ package com.simibubi.create.modules.schematics.block; -import static com.simibubi.create.foundation.gui.ScreenResources.SCHEMATIC_TABLE; -import static com.simibubi.create.foundation.gui.ScreenResources.SCHEMATIC_TABLE_PROGRESS; +import static com.simibubi.create.ScreenResources.SCHEMATIC_TABLE; +import static com.simibubi.create.ScreenResources.SCHEMATIC_TABLE_PROGRESS; import java.nio.file.Paths; import java.util.List; @@ -9,8 +9,8 @@ import java.util.List; import com.mojang.blaze3d.platform.GlStateManager; import com.simibubi.create.AllBlocks; import com.simibubi.create.CreateClient; +import com.simibubi.create.ScreenResources; import com.simibubi.create.foundation.gui.AbstractSimiContainerScreen; -import com.simibubi.create.foundation.gui.ScreenResources; import com.simibubi.create.foundation.gui.widgets.IconButton; import com.simibubi.create.foundation.gui.widgets.Label; import com.simibubi.create.foundation.gui.widgets.ScrollInput; diff --git a/src/main/java/com/simibubi/create/modules/schematics/block/SchematicannonScreen.java b/src/main/java/com/simibubi/create/modules/schematics/block/SchematicannonScreen.java index ffb726b90..dea178076 100644 --- a/src/main/java/com/simibubi/create/modules/schematics/block/SchematicannonScreen.java +++ b/src/main/java/com/simibubi/create/modules/schematics/block/SchematicannonScreen.java @@ -10,8 +10,8 @@ import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.platform.GlStateManager; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPackets; +import com.simibubi.create.ScreenResources; import com.simibubi.create.foundation.gui.AbstractSimiContainerScreen; -import com.simibubi.create.foundation.gui.ScreenResources; import com.simibubi.create.foundation.gui.widgets.IconButton; import com.simibubi.create.foundation.gui.widgets.Indicator; import com.simibubi.create.foundation.gui.widgets.Indicator.State; diff --git a/src/main/java/com/simibubi/create/modules/schematics/client/BlueprintHotbarOverlay.java b/src/main/java/com/simibubi/create/modules/schematics/client/BlueprintHotbarOverlay.java index bba678a52..125d09bd1 100644 --- a/src/main/java/com/simibubi/create/modules/schematics/client/BlueprintHotbarOverlay.java +++ b/src/main/java/com/simibubi/create/modules/schematics/client/BlueprintHotbarOverlay.java @@ -1,7 +1,7 @@ package com.simibubi.create.modules.schematics.client; import com.mojang.blaze3d.platform.GlStateManager; -import com.simibubi.create.foundation.gui.ScreenResources; +import com.simibubi.create.ScreenResources; import net.minecraft.client.MainWindow; import net.minecraft.client.Minecraft; diff --git a/src/main/java/com/simibubi/create/modules/schematics/client/SchematicEditScreen.java b/src/main/java/com/simibubi/create/modules/schematics/client/SchematicEditScreen.java index f4aae8c14..eb99c1fd4 100644 --- a/src/main/java/com/simibubi/create/modules/schematics/client/SchematicEditScreen.java +++ b/src/main/java/com/simibubi/create/modules/schematics/client/SchematicEditScreen.java @@ -6,8 +6,8 @@ import java.util.List; import com.mojang.blaze3d.platform.GlStateManager; import com.simibubi.create.AllItems; import com.simibubi.create.CreateClient; +import com.simibubi.create.ScreenResources; import com.simibubi.create.foundation.gui.AbstractSimiScreen; -import com.simibubi.create.foundation.gui.ScreenResources; import com.simibubi.create.foundation.gui.widgets.Label; import com.simibubi.create.foundation.gui.widgets.ScrollInput; import com.simibubi.create.foundation.gui.widgets.SelectionScrollInput; diff --git a/src/main/java/com/simibubi/create/modules/schematics/client/tools/Tools.java b/src/main/java/com/simibubi/create/modules/schematics/client/tools/Tools.java index 60a090217..2b6965d2b 100644 --- a/src/main/java/com/simibubi/create/modules/schematics/client/tools/Tools.java +++ b/src/main/java/com/simibubi/create/modules/schematics/client/tools/Tools.java @@ -4,7 +4,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import com.simibubi.create.foundation.gui.ScreenResources; +import com.simibubi.create.ScreenResources; import com.simibubi.create.foundation.utility.Lang; public enum Tools { diff --git a/src/main/resources/assets/create/lang/en_us.json b/src/main/resources/assets/create/lang/en_us.json index b57e5e916..4ec27263b 100644 --- a/src/main/resources/assets/create/lang/en_us.json +++ b/src/main/resources/assets/create/lang/en_us.json @@ -19,6 +19,7 @@ "item.create.refined_rose_quartz": "Refined Rose Quartz", "item.create.refined_radiance_cube": "Refined Radiance", "item.create.iron_sheet": "Iron Sheets", + "item.create.gold_sheet": "Gold Sheets", "item.create.propeller": "Propeller", "item.create.flour": "Wheat Flour", "item.create.dough": "Dough", @@ -144,6 +145,17 @@ "death.attack.create.fan_lava": "%1$s was burned to death by lava fan", "death.attack.create.drill": "%1$s was impaled by Mechanical Drill", + "create.recipe.crushing": "Crushing", + "create.recipe.splashing": "Bulk Washing", + "create.recipe.splashing.fan": "Fan behind §9Flowing Water", + "create.recipe.smokingViaFan": "Bulk Smoking", + "create.recipe.smokingViaFan.fan": "Fan behind §6Fire", + "create.recipe.blastingViaFan": "Bulk Smelting", + "create.recipe.blastingViaFan.fan": "Fan behind §6Lava", + "create.recipe.pressing": "Mechanical Press", + "create.recipe.blockzapperUpgrade": "Handheld Blockzapper", + "create.recipe.processing.chance": "%1$s%% Chance", + "create.generic.range": "Range", "create.generic.radius": "Radius", "create.generic.speed": "Speed", @@ -363,6 +375,29 @@ "item.create.tree_fertilizer.tooltip.condition1": "When used on Sapling", "item.create.tree_fertilizer.tooltip.behaviour1": "Grows Trees regardless of their spacing Conditions", + "item.create.empty_blueprint.tooltip": "EMPTY SCHEMATIC", + "item.create.empty_blueprint.tooltip.summary": "Used as a recipe ingredient and for writing at the _Schematic_ _Table._", + + "item.create.blueprint.tooltip": "SCHEMATIC", + "item.create.blueprint.tooltip.summary": "Holds a structure to be positioned and placed into the world. Position the Hologram as desired and use a _Schematicannon_ to build it.", + "item.create.blueprint.tooltip.condition1": "When Held", + "item.create.blueprint.tooltip.behaviour1": "Can be positioned using the Tools on Screen", + "item.create.blueprint.tooltip.control1": "R-Click while Sneaking", + "item.create.blueprint.tooltip.action1": "Opens an _Interface_ for entering exact _Coordinates._", + + "item.create.blueprint_and_quill.tooltip": "SCHEMATIC AND QUILL", + "item.create.blueprint_and_quill.tooltip.summary": "Used for saving a Structure in your world to a .nbt file.", + "item.create.blueprint_and_quill.tooltip.condition1": "Step 1", + "item.create.blueprint_and_quill.tooltip.behaviour1": "Select two corner points using R-Click", + "item.create.blueprint_and_quill.tooltip.condition2": "Step 2", + "item.create.blueprint_and_quill.tooltip.behaviour2": "_Ctrl-Scroll_ on the faces to adjust the size. R-Click again to Save.", + "item.create.blueprint_and_quill.tooltip.control1": "R-Click", + "item.create.blueprint_and_quill.tooltip.action1": "Select a corner point / confirm save", + "item.create.blueprint_and_quill.tooltip.control2": "Ctrl Held", + "item.create.blueprint_and_quill.tooltip.action2": "Select points in _mid-air_. _Scroll_ to adjust the distance.", + "item.create.blueprint_and_quill.tooltip.control3": "R-Click while Sneaking", + "item.create.blueprint_and_quill.tooltip.action3": "_Resets_ and removes the selection.", + "block.create.creative_crate.tooltip": "CREATIVE CRATE", "block.create.creative_crate.tooltip.summary": "tis a crate", diff --git a/src/main/resources/assets/create/models/item/gold_sheet.json b/src/main/resources/assets/create/models/item/gold_sheet.json new file mode 100644 index 000000000..84fabd09e --- /dev/null +++ b/src/main/resources/assets/create/models/item/gold_sheet.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "create:item/gold_sheet" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/textures/gui/recipes1.png b/src/main/resources/assets/create/textures/gui/recipes1.png new file mode 100644 index 0000000000000000000000000000000000000000..49228f8aadbd9f83443b7828d8beb88717def6b6 GIT binary patch literal 27001 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�A`=7h}Ti& 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 R&ST92E?C%`*C4%9{s+5I1tI_d literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/create/textures/item/gold_sheet.png b/src/main/resources/assets/create/textures/item/gold_sheet.png new file mode 100644 index 0000000000000000000000000000000000000000..5464e581359c8d35c871194bff16ed54fa61a46e GIT binary patch literal 439 zcmV;o0Z9IdP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0Zd6mK~y+TW1s~5 z|NozX5kyb|7@;&?fY%aATmbh1BO`8yY)TP?+u%3nJ&Hn{1|VzlnZAjE;ooD1zpt(_ zY;T;3VhD->$eKJVLl~H)^?>3s3=B*_{Qn~mKVkU$;tIp|=DBb~;0A0?75eWx^E|`9 z-`l{pG5mi43|^3CSq4Us0Zh_B@h1%bf%xC^%M9CFmx2ue>16_22?W1yW-&0adI1%S z0W}K(4S5a3uORflH$X8lpo>HqSma6=yeIm>T?{wi{q55X|9;d14G9D)76pnhgEcd< z*fTIPD+6633S=8GyxL;QaDU+zhQmjI-U0%YFfjLJVGvX`WnfjG29^W?kcQ7s|3P^S z4A;*618eTS@eiUGW&jAl3=whhVtBJ>8(8DaN$QCL=nMb=002ovPDHLkV1oBxsW|`u literal 0 HcmV?d00001 diff --git a/src/main/resources/data/create/recipes/crafting/belt_funnel.json b/src/main/resources/data/create/recipes/crafting/belt_funnel.json index 830b3da8b..ef3356b01 100644 --- a/src/main/resources/data/create/recipes/crafting/belt_funnel.json +++ b/src/main/resources/data/create/recipes/crafting/belt_funnel.json @@ -1,16 +1,16 @@ { "type": "crafting_shaped", "pattern": [ - "N ", - "P ", - "ND" + "NN", + "PD", + "PD" ], "key": { "D": { "item": "minecraft:dried_kelp" }, "N": { - "item": "minecraft:gold_nugget" + "item": "create:gold_sheet" }, "P": { "tag": "minecraft:planks" @@ -18,7 +18,7 @@ }, "result": { "item": "create:belt_funnel", - "count": 1 + "count": 4 }, "conditions": [ { diff --git a/src/main/resources/data/create/recipes/crafting/belt_support.json b/src/main/resources/data/create/recipes/crafting/belt_support.json new file mode 100644 index 000000000..b1b9518c2 --- /dev/null +++ b/src/main/resources/data/create/recipes/crafting/belt_support.json @@ -0,0 +1,26 @@ +{ + "type": "crafting_shaped", + "pattern": [ + "N", + "P", + "P" + ], + "key": { + "N": { + "item": "create:gold_sheet" + }, + "P": { + "tag": "minecraft:planks" + } + }, + "result": { + "item": "create:belt_support", + "count": 4 + }, + "conditions": [ + { + "type": "create:module", + "module": "logistics" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/crafting/clutch.json b/src/main/resources/data/create/recipes/crafting/clutch.json index fe2b2e4a9..b0db25466 100644 --- a/src/main/resources/data/create/recipes/crafting/clutch.json +++ b/src/main/resources/data/create/recipes/crafting/clutch.json @@ -10,7 +10,7 @@ "tag": "minecraft:planks" }, "A": { - "item": "create:andesite_alloy_cube" + "item": "create:iron_sheet" }, "S": { "item": "create:shaft" diff --git a/src/main/resources/data/create/recipes/crafting/contact.json b/src/main/resources/data/create/recipes/crafting/contact.json index 0b40c1e29..72c1b68a7 100644 --- a/src/main/resources/data/create/recipes/crafting/contact.json +++ b/src/main/resources/data/create/recipes/crafting/contact.json @@ -16,7 +16,7 @@ "item": "minecraft:redstone" }, "G": { - "item": "minecraft:gold_nugget" + "item": "create:gold_sheet" } }, "result": { diff --git a/src/main/resources/data/create/recipes/crafting/encased_fan.json b/src/main/resources/data/create/recipes/crafting/encased_fan.json index ae505f03e..5c57844f9 100644 --- a/src/main/resources/data/create/recipes/crafting/encased_fan.json +++ b/src/main/resources/data/create/recipes/crafting/encased_fan.json @@ -10,7 +10,7 @@ "item": "minecraft:iron_bars" }, "A": { - "item": "create:andesite_alloy_cube" + "item": "create:iron_sheet" }, "S": { "item": "create:propeller" diff --git a/src/main/resources/data/create/recipes/crafting/entity_detector.json b/src/main/resources/data/create/recipes/crafting/entity_detector.json index 5c5184a6d..786d32a08 100644 --- a/src/main/resources/data/create/recipes/crafting/entity_detector.json +++ b/src/main/resources/data/create/recipes/crafting/entity_detector.json @@ -10,7 +10,7 @@ "tag": "minecraft:planks" }, "A": { - "item": "minecraft:gold_nugget" + "item": "create:gold_sheet" }, "S": { "item": "minecraft:observer" diff --git a/src/main/resources/data/create/recipes/crafting/extractor.json b/src/main/resources/data/create/recipes/crafting/extractor.json index 50766a887..69ef667fc 100644 --- a/src/main/resources/data/create/recipes/crafting/extractor.json +++ b/src/main/resources/data/create/recipes/crafting/extractor.json @@ -16,7 +16,7 @@ "item": "minecraft:dried_kelp" }, "N": { - "item": "minecraft:gold_nugget" + "item": "create:gold_sheet" }, "P": { "tag": "minecraft:planks" @@ -24,7 +24,7 @@ }, "result": { "item": "create:extractor", - "count": 1 + "count": 4 }, "conditions": [ { diff --git a/src/main/resources/data/create/recipes/crafting/flexcrate.json b/src/main/resources/data/create/recipes/crafting/flexcrate.json index a88bb7faf..9cbd917be 100644 --- a/src/main/resources/data/create/recipes/crafting/flexcrate.json +++ b/src/main/resources/data/create/recipes/crafting/flexcrate.json @@ -10,7 +10,7 @@ "tag": "minecraft:planks" }, "A": { - "item": "minecraft:gold_nugget" + "item": "create:gold_sheet" }, "S": { "item": "minecraft:chest" @@ -18,7 +18,7 @@ }, "result": { "item": "create:flexcrate", - "count": 1 + "count": 2 }, "conditions": [ { diff --git a/src/main/resources/data/create/recipes/crafting/gearshift.json b/src/main/resources/data/create/recipes/crafting/gearshift.json index 16e6c600a..7ce1869f4 100644 --- a/src/main/resources/data/create/recipes/crafting/gearshift.json +++ b/src/main/resources/data/create/recipes/crafting/gearshift.json @@ -10,7 +10,7 @@ "tag": "minecraft:planks" }, "A": { - "item": "create:andesite_alloy_cube" + "item": "create:iron_sheet" }, "S": { "item": "create:cogwheel" diff --git a/src/main/resources/data/create/recipes/crafting/harvester.json b/src/main/resources/data/create/recipes/crafting/harvester.json index 223866399..deb1bef86 100644 --- a/src/main/resources/data/create/recipes/crafting/harvester.json +++ b/src/main/resources/data/create/recipes/crafting/harvester.json @@ -7,7 +7,7 @@ ], "key": { "A": { - "item": "create:andesite_alloy_cube" + "item": "create:iron_sheet" }, "I": { "item": "minecraft:iron_nugget" diff --git a/src/main/resources/data/create/recipes/crafting/motor.json b/src/main/resources/data/create/recipes/crafting/motor.json index 60dd5b2d8..5bc80460f 100644 --- a/src/main/resources/data/create/recipes/crafting/motor.json +++ b/src/main/resources/data/create/recipes/crafting/motor.json @@ -10,7 +10,7 @@ "item": "create:blaze_brass_cube" }, "A": { - "item": "create:andesite_alloy_cube" + "item": "create:iron_sheet" }, "I": { "item": "minecraft:iron_block" diff --git a/src/main/resources/data/create/recipes/crafting/redstone_bridge.json b/src/main/resources/data/create/recipes/crafting/redstone_bridge.json index 351155d30..a5c46d639 100644 --- a/src/main/resources/data/create/recipes/crafting/redstone_bridge.json +++ b/src/main/resources/data/create/recipes/crafting/redstone_bridge.json @@ -9,7 +9,7 @@ "tag": "minecraft:planks" }, "G": { - "item": "minecraft:gold_ingot" + "item": "create:gold_sheet" }, "T": { "item": "minecraft:redstone_torch" diff --git a/src/main/resources/data/create/recipes/crafting/stockswitch.json b/src/main/resources/data/create/recipes/crafting/stockswitch.json index d336248d0..e2fe37d6e 100644 --- a/src/main/resources/data/create/recipes/crafting/stockswitch.json +++ b/src/main/resources/data/create/recipes/crafting/stockswitch.json @@ -16,7 +16,7 @@ "item": "minecraft:comparator" }, "G": { - "item": "minecraft:gold_nugget" + "item": "create:gold_sheet" } }, "result": { diff --git a/src/main/resources/data/create/recipes/pressing/gold_ingot.json b/src/main/resources/data/create/recipes/pressing/gold_ingot.json new file mode 100644 index 000000000..76b05f691 --- /dev/null +++ b/src/main/resources/data/create/recipes/pressing/gold_ingot.json @@ -0,0 +1,16 @@ +{ + "type": "create:pressing", + "group": "minecraft:misc", + "ingredients": [ + { + "item": "minecraft:gold_ingot" + } + ], + "results": [ + { + "item": "create:gold_sheet", + "count": 1 + } + ], + "processingTime": 100 +} \ No newline at end of file