mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-15 14:13:42 +01:00
Millstone cont'd
- Overstressed components now show a tooltip, unless disabled in config - JEI compat for millstone recipes - Crushing Wheels now require mechanical crafting in order to be assembled - Millstones now drop contents when broken - Players can manually collect millstone outputs via right-click - Fixed millstone removing ingredients before looking up a recipe - Gauges no longer require a block to sit on (QOL)
This commit is contained in:
parent
c3f781b762
commit
ca86273f5f
33 changed files with 550 additions and 122 deletions
|
@ -67,7 +67,7 @@ public enum AllBlockPartials {
|
|||
ROPE_COIL("pulley/rope_coil"),
|
||||
ROPE_HALF("pulley/rope_half"),
|
||||
ROPE_HALF_MAGNET("pulley/rope_half_magnet"),
|
||||
MILL_STONE_COG("millstone/inner"),
|
||||
MILLSTONE_COG("millstone/inner"),
|
||||
|
||||
;
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import com.simibubi.create.compat.jei.category.BlockCuttingCategory.CondensedBlo
|
|||
import com.simibubi.create.compat.jei.category.BlockzapperUpgradeCategory;
|
||||
import com.simibubi.create.compat.jei.category.CrushingCategory;
|
||||
import com.simibubi.create.compat.jei.category.MechanicalCraftingCategory;
|
||||
import com.simibubi.create.compat.jei.category.MillingCategory;
|
||||
import com.simibubi.create.compat.jei.category.MixingCategory;
|
||||
import com.simibubi.create.compat.jei.category.MysteriousItemConversionCategory;
|
||||
import com.simibubi.create.compat.jei.category.PackingCategory;
|
||||
|
@ -55,6 +56,7 @@ import net.minecraft.util.text.TextFormatting;
|
|||
public class CreateJEI implements IModPlugin {
|
||||
|
||||
private static ResourceLocation ID = new ResourceLocation(Create.ID, "jei_plugin");
|
||||
private MillingCategory millingCategory;
|
||||
private CrushingCategory crushingCategory;
|
||||
private SplashingCategory splashingCategory;
|
||||
private SmokingViaFanCategory smokingCategory;
|
||||
|
@ -76,6 +78,7 @@ public class CreateJEI implements IModPlugin {
|
|||
}
|
||||
|
||||
public CreateJEI() {
|
||||
millingCategory = new MillingCategory();
|
||||
crushingCategory = new CrushingCategory();
|
||||
splashingCategory = new SplashingCategory();
|
||||
pressingCategory = new PressingCategory();
|
||||
|
@ -99,14 +102,15 @@ public class CreateJEI implements IModPlugin {
|
|||
|
||||
@Override
|
||||
public void registerCategories(IRecipeCategoryRegistration registration) {
|
||||
registration.addRecipeCategories(crushingCategory, splashingCategory, pressingCategory, smokingCategory,
|
||||
blastingCategory, blockzapperCategory, mixingCategory, sawingCategory, blockCuttingCategory,
|
||||
packingCategory, polishingCategory, mysteryConversionCategory, smallMechanicalCraftingCategory,
|
||||
largeMechanicalCraftingCategory);
|
||||
registration.addRecipeCategories(millingCategory, crushingCategory, splashingCategory, pressingCategory,
|
||||
smokingCategory, blastingCategory, blockzapperCategory, mixingCategory, sawingCategory,
|
||||
blockCuttingCategory, packingCategory, polishingCategory, mysteryConversionCategory,
|
||||
smallMechanicalCraftingCategory, largeMechanicalCraftingCategory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerRecipes(IRecipeRegistration registration) {
|
||||
registration.addRecipes(findRecipes(AllRecipes.MILLING), millingCategory.getUid());
|
||||
registration.addRecipes(findRecipes(AllRecipes.CRUSHING), crushingCategory.getUid());
|
||||
registration.addRecipes(findRecipesByTypeExcluding(AllRecipes.MILLING.getType(), AllRecipes.CRUSHING.getType()),
|
||||
crushingCategory.getUid());
|
||||
|
@ -135,12 +139,15 @@ public class CreateJEI implements IModPlugin {
|
|||
registration.addRecipes(findRecipes(
|
||||
r -> (r instanceof MechanicalCraftingRecipe) && MechanicalCraftingCategory.isSmall((ShapedRecipe) r)),
|
||||
smallMechanicalCraftingCategory.getUid());
|
||||
registration.addRecipes(findRecipes(r -> r.getType() == IRecipeType.CRAFTING && (r instanceof ShapedRecipe)
|
||||
&& !(r instanceof MechanicalCraftingRecipe) && MechanicalCraftingCategory.isSmall((ShapedRecipe) r)),
|
||||
smallMechanicalCraftingCategory.getUid());
|
||||
registration.addRecipes(
|
||||
findRecipes(r -> r.getType() == IRecipeType.CRAFTING && (r instanceof ShapedRecipe)
|
||||
&& !MechanicalCraftingCategory.isSmall((ShapedRecipe) r)),
|
||||
findRecipes(
|
||||
r -> (r.getType() == IRecipeType.CRAFTING || r.getType() == AllRecipes.MECHANICAL_CRAFTING.type)
|
||||
&& (r instanceof ShapedRecipe) && !(r instanceof MechanicalCraftingRecipe)
|
||||
&& MechanicalCraftingCategory.isSmall((ShapedRecipe) r)),
|
||||
smallMechanicalCraftingCategory.getUid());
|
||||
registration.addRecipes(findRecipes(
|
||||
r -> (r.getType() == IRecipeType.CRAFTING || r.getType() == AllRecipes.MECHANICAL_CRAFTING.type)
|
||||
&& (r instanceof ShapedRecipe) && !MechanicalCraftingCategory.isSmall((ShapedRecipe) r)),
|
||||
largeMechanicalCraftingCategory.getUid());
|
||||
|
||||
}
|
||||
|
@ -156,6 +163,7 @@ public class CreateJEI implements IModPlugin {
|
|||
ItemStack blastingFan = fan.copy().setDisplayName(
|
||||
new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.blastingViaFan.fan")));
|
||||
|
||||
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MILLSTONE.get()), millingCategory.getUid());
|
||||
registration.addRecipeCatalyst(new ItemStack(AllBlocks.CRUSHING_WHEEL.get()), crushingCategory.getUid());
|
||||
registration.addRecipeCatalyst(splashingFan, splashingCategory.getUid());
|
||||
registration.addRecipeCatalyst(smokingFan, smokingCategory.getUid());
|
||||
|
|
|
@ -33,7 +33,7 @@ public class CrushingCategory implements IRecipeCategory<AbstractCrushingRecipe>
|
|||
|
||||
public CrushingCategory() {
|
||||
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.CRUSHING_WHEEL.get()),
|
||||
() -> new ItemStack(AllItems.FLOUR.get()));
|
||||
() -> new ItemStack(AllItems.CRUSHED_GOLD.get()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
package com.simibubi.create.compat.jei.category;
|
||||
|
||||
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.compat.jei.CreateJEI;
|
||||
import com.simibubi.create.compat.jei.DoubleItemIcon;
|
||||
import com.simibubi.create.compat.jei.EmptyBackground;
|
||||
import com.simibubi.create.compat.jei.category.animations.AnimatedMillstone;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.modules.contraptions.components.crusher.AbstractCrushingRecipe;
|
||||
import com.simibubi.create.modules.contraptions.processing.ProcessingOutput;
|
||||
|
||||
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 MillingCategory implements IRecipeCategory<AbstractCrushingRecipe> {
|
||||
|
||||
private static ResourceLocation ID = new ResourceLocation(Create.ID, "milling");
|
||||
private AnimatedMillstone millstone = new AnimatedMillstone();
|
||||
private IDrawable icon;
|
||||
private IDrawable background = new EmptyBackground(177, 53);
|
||||
|
||||
public MillingCategory() {
|
||||
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.MILLSTONE.get()),
|
||||
() -> new ItemStack(AllItems.FLOUR.get()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDrawable getBackground() {
|
||||
return background;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getUid() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AbstractCrushingRecipe> getRecipeClass() {
|
||||
return AbstractCrushingRecipe.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return Lang.translate("recipe.milling");
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDrawable getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIngredients(AbstractCrushingRecipe recipe, IIngredients ingredients) {
|
||||
ingredients.setInputIngredients(recipe.getIngredients());
|
||||
ingredients.setOutputs(VanillaTypes.ITEM, recipe.getPossibleOutputs());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(IRecipeLayout recipeLayout, AbstractCrushingRecipe recipe, IIngredients ingredients) {
|
||||
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
|
||||
itemStacks.init(0, true, 14, 8);
|
||||
itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks()));
|
||||
|
||||
List<ProcessingOutput> results = recipe.getRollableResults();
|
||||
boolean single = results.size() == 1;
|
||||
for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) {
|
||||
int xOffset = outputIndex % 2 == 0 ? 0 : 19;
|
||||
int yOffset = (outputIndex / 2) * -19;
|
||||
|
||||
itemStacks.init(outputIndex + 1, false, single ? 139 : 133 + xOffset, 27 + yOffset);
|
||||
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
|
||||
}
|
||||
|
||||
CreateJEI.addStochasticTooltip(itemStacks, results);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(AbstractCrushingRecipe recipe, double mouseX, double mouseY) {
|
||||
int size = recipe.getPossibleOutputs().size();
|
||||
|
||||
ScreenResources.JEI_SLOT.draw(14, 8);
|
||||
ScreenResources.JEI_SHADOW.draw(30, 40);
|
||||
ScreenResources.JEI_ARROW.draw(85, 32);
|
||||
ScreenResources.JEI_DOWN_ARROW.draw(43, 4);
|
||||
|
||||
if (size > 1) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
int xOffset = i % 2 == 0 ? 0 : 19;
|
||||
int yOffset = (i / 2) * -19;
|
||||
ScreenResources.JEI_SLOT.draw(133 + xOffset, 27 + yOffset);
|
||||
}
|
||||
} else {
|
||||
ScreenResources.JEI_SLOT.draw(139, 27);
|
||||
}
|
||||
|
||||
millstone.draw(57, 27);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.simibubi.create.compat.jei.category.animations;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.simibubi.create.AllBlockPartials;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.foundation.gui.ScreenElementRenderer;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
|
||||
public class AnimatedMillstone extends AnimatedKinetics {
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return 50;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return 50;
|
||||
}
|
||||
|
||||
@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.renderModel(this::cogwheel);
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
ScreenElementRenderer.renderBlock(this::body);
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
private IBakedModel cogwheel() {
|
||||
float t = 25;
|
||||
GlStateManager.translatef(t, -t, -t);
|
||||
GlStateManager.rotated(getCurrentAngle() * 2, 0, 1, 0);
|
||||
GlStateManager.translatef(-t, t, t);
|
||||
return AllBlockPartials.MILLSTONE_COG.get();
|
||||
}
|
||||
|
||||
private BlockState body() {
|
||||
return AllBlocks.MILLSTONE.get().getDefaultState();
|
||||
}
|
||||
}
|
|
@ -5,6 +5,8 @@ public class CClient extends ConfigBase {
|
|||
public ConfigGroup client = group(0, "client",
|
||||
"Client-only settings - If you're looking for general settings, look inside your worlds serverconfig folder!");
|
||||
public ConfigBool tooltips = b(true, "enableTooltips", "Show item descriptions on Shift and controls on Ctrl.");
|
||||
public ConfigBool enableOverstressedTooltip =
|
||||
b(true, "enableOverstressedTooltip", "Display a tooltip when looking at overstressed components.");
|
||||
public ConfigBool explainRenderErrors =
|
||||
b(false, "explainRenderErrors", "Log a stack-trace when rendering issues happen within a moving contraption.");
|
||||
public ConfigFloat fanParticleDensity = f(.5f, 0, 1, "fanParticleDensity");
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.simibubi.create.modules.contraptions.base;
|
||||
|
||||
import static net.minecraft.util.text.TextFormatting.GOLD;
|
||||
import static net.minecraft.util.text.TextFormatting.GRAY;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -19,6 +20,7 @@ import com.simibubi.create.modules.contraptions.RotationPropagator;
|
|||
import com.simibubi.create.modules.contraptions.base.IRotate.SpeedLevel;
|
||||
import com.simibubi.create.modules.contraptions.base.IRotate.StressImpact;
|
||||
import com.simibubi.create.modules.contraptions.goggle.IHaveGoggleInformation;
|
||||
import com.simibubi.create.modules.contraptions.goggle.IHaveHoveringInformation;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
@ -33,7 +35,8 @@ import net.minecraft.util.text.TextFormatting;
|
|||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.ForgeConfigSpec.ConfigValue;
|
||||
|
||||
public abstract class KineticTileEntity extends SmartTileEntity implements ITickableTileEntity, IHaveGoggleInformation {
|
||||
public abstract class KineticTileEntity extends SmartTileEntity
|
||||
implements ITickableTileEntity, IHaveGoggleInformation, IHaveHoveringInformation {
|
||||
|
||||
public @Nullable Long network;
|
||||
public @Nullable BlockPos source;
|
||||
|
@ -353,28 +356,51 @@ public abstract class KineticTileEntity extends SmartTileEntity implements ITick
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addToTooltip(List<String> tooltip, boolean isPlayerSneaking) {
|
||||
boolean notFastEnough = !isSpeedRequirementFulfilled() && getSpeed() != 0;
|
||||
|
||||
if (overStressed && AllConfigs.CLIENT.enableOverstressedTooltip.get()) {
|
||||
tooltip.add(spacing + GOLD + Lang.translate("gui.stress_gauge.overstressed"));
|
||||
String hint = Lang.translate("gui.contraptions.network_overstressed",
|
||||
I18n.format(getBlockState().getBlock().getTranslationKey()));
|
||||
List<String> cutString = TooltipHelper.cutString(spacing + hint, GRAY, TextFormatting.WHITE);
|
||||
for (int i = 0; i < cutString.size(); i++)
|
||||
tooltip.add((i == 0 ? "" : spacing) + cutString.get(i));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (notFastEnough) {
|
||||
tooltip.add(spacing + GOLD + Lang.translate("tooltip.speedRequirement"));
|
||||
String hint = Lang.translate("gui.contraptions.not_fast_enough",
|
||||
I18n.format(getBlockState().getBlock().getTranslationKey()));
|
||||
List<String> cutString = TooltipHelper.cutString(spacing + hint, GRAY, TextFormatting.WHITE);
|
||||
for (int i = 0; i < cutString.size(); i++)
|
||||
tooltip.add((i == 0 ? "" : spacing) + cutString.get(i));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addToGoggleTooltip(List<String> tooltip, boolean isPlayerSneaking) {
|
||||
boolean added = false;
|
||||
float stressAtBase = getStressApplied();
|
||||
|
||||
boolean notFastEnough = !isSpeedRequirementFulfilled() && getSpeed() != 0;
|
||||
|
||||
if (notFastEnough) {
|
||||
tooltip.addAll(TooltipHelper.cutString(spacing + Lang.translate("gui.contraptions.not_fast_enough", I18n.format(getBlockState().getBlock().getTranslationKey())), GRAY, TextFormatting.WHITE));
|
||||
added = true;
|
||||
}
|
||||
|
||||
if (getStressApplied() != 0 && StressImpact.isEnabled()){
|
||||
if (getStressApplied() != 0 && StressImpact.isEnabled()) {
|
||||
tooltip.add(spacing + Lang.translate("gui.goggles.kinetic_stats"));
|
||||
tooltip.add(spacing + TextFormatting.GRAY + Lang.translate("tooltip.stressImpact"));
|
||||
|
||||
float stressTotal = stressAtBase * Math.abs(getSpeed());
|
||||
|
||||
String stressString = spacing + "%s%s" + Lang.translate("generic.unit.stress") + " " + TextFormatting.DARK_GRAY + "%s";
|
||||
String stressString =
|
||||
spacing + "%s%s" + Lang.translate("generic.unit.stress") + " " + TextFormatting.DARK_GRAY + "%s";
|
||||
|
||||
tooltip.add(String.format(stressString, TextFormatting.AQUA, IHaveGoggleInformation.format(stressAtBase), Lang.translate("gui.goggles.base_value")));
|
||||
tooltip.add(String.format(stressString, TextFormatting.GRAY, IHaveGoggleInformation.format(stressTotal), Lang.translate("gui.goggles.at_current_speed")));
|
||||
tooltip.add(String.format(stressString, TextFormatting.AQUA, IHaveGoggleInformation.format(stressAtBase),
|
||||
Lang.translate("gui.goggles.base_value")));
|
||||
tooltip.add(String.format(stressString, TextFormatting.GRAY, IHaveGoggleInformation.format(stressTotal),
|
||||
Lang.translate("gui.goggles.at_current_speed")));
|
||||
|
||||
added = true;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ public class MillingRecipe extends AbstractCrushingRecipe {
|
|||
|
||||
@Override
|
||||
protected int getMaxOutputCount() {
|
||||
return 7;
|
||||
return 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,14 +5,27 @@ import com.simibubi.create.modules.contraptions.base.KineticBlock;
|
|||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.InventoryHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Direction.Axis;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.shapes.ISelectionContext;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.IWorldReader;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
|
||||
public class MillstoneBlock extends KineticBlock {
|
||||
|
||||
|
@ -29,7 +42,7 @@ public class MillstoneBlock extends KineticBlock {
|
|||
protected boolean hasStaticPart() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
|
||||
return AllShapes.MILLSTONE;
|
||||
|
@ -39,6 +52,81 @@ public class MillstoneBlock extends KineticBlock {
|
|||
public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) {
|
||||
return face == Direction.DOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
|
||||
BlockRayTraceResult hit) {
|
||||
if (!player.getHeldItem(handIn).isEmpty())
|
||||
return false;
|
||||
if (worldIn.getTileEntity(pos) == null)
|
||||
return false;
|
||||
if (worldIn.isRemote)
|
||||
return true;
|
||||
|
||||
TileEntity tileEntity = worldIn.getTileEntity(pos);
|
||||
if (!(tileEntity instanceof MillstoneTileEntity))
|
||||
return false;
|
||||
MillstoneTileEntity millstone = (MillstoneTileEntity) tileEntity;
|
||||
|
||||
IItemHandlerModifiable inv = millstone.outputInv;
|
||||
for (int slot = 0; slot < inv.getSlots(); slot++) {
|
||||
player.inventory.placeItemBackInInventory(worldIn, inv.getStackInSlot(slot));
|
||||
inv.setStackInSlot(slot, ItemStack.EMPTY);
|
||||
}
|
||||
millstone.markDirty();
|
||||
millstone.sendData();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLanded(IBlockReader worldIn, Entity entityIn) {
|
||||
super.onLanded(worldIn, entityIn);
|
||||
|
||||
if (entityIn.world.isRemote)
|
||||
return;
|
||||
if (!(entityIn instanceof ItemEntity))
|
||||
return;
|
||||
|
||||
BlockPos pos = entityIn.getPosition();
|
||||
TileEntity tileEntity = worldIn.getTileEntity(pos);
|
||||
if (!(tileEntity instanceof MillstoneTileEntity)) {
|
||||
tileEntity = worldIn.getTileEntity(pos.down());
|
||||
if (!(tileEntity instanceof MillstoneTileEntity))
|
||||
return;
|
||||
}
|
||||
|
||||
MillstoneTileEntity millstone = (MillstoneTileEntity) tileEntity;
|
||||
ItemEntity itemEntity = (ItemEntity) entityIn;
|
||||
LazyOptional<IItemHandler> capability = millstone.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
|
||||
if (!capability.isPresent())
|
||||
return;
|
||||
|
||||
ItemStack remainder = capability.orElse(new ItemStackHandler()).insertItem(0, itemEntity.getItem(), false);
|
||||
if (remainder.isEmpty())
|
||||
itemEntity.remove();
|
||||
if (remainder.getCount() < itemEntity.getItem().getCount())
|
||||
itemEntity.setItem(remainder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
if (state.hasTileEntity() && state.getBlock() != newState.getBlock()) {
|
||||
TileEntity tileEntity = worldIn.getTileEntity(pos);
|
||||
if (!(tileEntity instanceof MillstoneTileEntity))
|
||||
return;
|
||||
MillstoneTileEntity te = (MillstoneTileEntity) tileEntity;
|
||||
for (int slot = 0; slot < te.inputInv.getSlots(); slot++) {
|
||||
InventoryHelper.spawnItemStack(worldIn, pos.getX(), pos.getY(), pos.getZ(),
|
||||
te.inputInv.getStackInSlot(slot));
|
||||
}
|
||||
for (int slot = 0; slot < te.outputInv.getSlots(); slot++) {
|
||||
InventoryHelper.spawnItemStack(worldIn, pos.getX(), pos.getY(), pos.getZ(),
|
||||
te.outputInv.getStackInSlot(slot));
|
||||
}
|
||||
|
||||
worldIn.removeTileEntity(pos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasIntegratedCogwheel(IWorldReader world, BlockPos pos, BlockState state) {
|
||||
|
|
|
@ -10,7 +10,7 @@ public class MillstoneRenderer extends KineticTileEntityRenderer {
|
|||
|
||||
@Override
|
||||
protected SuperByteBuffer getRotatedModel(KineticTileEntity te) {
|
||||
return CreateClient.bufferCache.renderPartial(AllBlockPartials.MILL_STONE_COG, te.getBlockState());
|
||||
return CreateClient.bufferCache.renderPartial(AllBlockPartials.MILLSTONE_COG, te.getBlockState());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -65,7 +65,6 @@ public class MillstoneTileEntity extends KineticTileEntity {
|
|||
if (lastRecipe == null || !lastRecipe.matches(inventoryIn, world)) {
|
||||
Optional<MillingRecipe> recipe =
|
||||
world.getRecipeManager().getRecipe(AllRecipes.MILLING.getType(), inventoryIn, world);
|
||||
inputInv.getStackInSlot(0).shrink(1);
|
||||
if (!recipe.isPresent()) {
|
||||
timer = 100;
|
||||
sendData();
|
||||
|
@ -83,9 +82,6 @@ public class MillstoneTileEntity extends KineticTileEntity {
|
|||
|
||||
private void process() {
|
||||
RecipeWrapper inventoryIn = new RecipeWrapper(inputInv);
|
||||
ItemStack stackInSlot = inputInv.getStackInSlot(0);
|
||||
stackInSlot.shrink(1);
|
||||
inputInv.setStackInSlot(0, stackInSlot);
|
||||
|
||||
if (lastRecipe == null || !lastRecipe.matches(inventoryIn, world)) {
|
||||
Optional<MillingRecipe> recipe =
|
||||
|
@ -95,6 +91,9 @@ public class MillstoneTileEntity extends KineticTileEntity {
|
|||
lastRecipe = recipe.get();
|
||||
}
|
||||
|
||||
ItemStack stackInSlot = inputInv.getStackInSlot(0);
|
||||
stackInSlot.shrink(1);
|
||||
inputInv.setStackInSlot(0, stackInSlot);
|
||||
lastRecipe.rollResults().forEach(stack -> ItemHandlerHelper.insertItemStacked(outputInv, stack, false));
|
||||
sendData();
|
||||
markDirty();
|
||||
|
|
|
@ -41,17 +41,34 @@ public class GoggleOverlayRenderer {
|
|||
ItemStack goggles = mc.player.getItemStackFromSlot(EquipmentSlotType.HEAD);
|
||||
TileEntity te = world.getTileEntity(pos);
|
||||
|
||||
if (!AllItems.GOGGLES.typeOf(goggles))
|
||||
return;
|
||||
boolean goggleInformation = te instanceof IHaveGoggleInformation;
|
||||
boolean hoveringInformation = te instanceof IHaveHoveringInformation;
|
||||
|
||||
if (!(te instanceof IHaveGoggleInformation))
|
||||
if (!goggleInformation && !hoveringInformation)
|
||||
return;
|
||||
|
||||
IHaveGoggleInformation gte = (IHaveGoggleInformation) te;
|
||||
|
||||
List<String> tooltip = new ArrayList<>();
|
||||
|
||||
if (!gte.addToGoggleTooltip(tooltip, mc.player.isSneaking()))
|
||||
if (goggleInformation && AllItems.GOGGLES.typeOf(goggles)) {
|
||||
IHaveGoggleInformation gte = (IHaveGoggleInformation) te;
|
||||
if (!gte.addToGoggleTooltip(tooltip, mc.player.isSneaking()))
|
||||
goggleInformation = false;
|
||||
}
|
||||
|
||||
if (hoveringInformation) {
|
||||
boolean goggleAddedInformation = !tooltip.isEmpty();
|
||||
if (goggleAddedInformation)
|
||||
tooltip.add("");
|
||||
IHaveHoveringInformation hte = (IHaveHoveringInformation) te;
|
||||
if (!hte.addToTooltip(tooltip, mc.player.isSneaking()))
|
||||
hoveringInformation = false;
|
||||
if (goggleAddedInformation && !hoveringInformation)
|
||||
tooltip.remove(tooltip.size() - 1);
|
||||
}
|
||||
|
||||
if (!goggleInformation && !hoveringInformation)
|
||||
return;
|
||||
if (tooltip.isEmpty())
|
||||
return;
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
@ -70,7 +87,7 @@ public class GoggleOverlayRenderer {
|
|||
|
||||
tooltipScreen.init(mc, mc.mainWindow.getScaledWidth(), mc.mainWindow.getScaledHeight());
|
||||
tooltipScreen.renderTooltip(tooltip, tooltipScreen.width / 2, tooltipScreen.height / 2);
|
||||
ItemStack item = goggles;
|
||||
ItemStack item = AllItems.GOGGLES.asStack();
|
||||
ScreenElementRenderer.render3DItem(() -> {
|
||||
GlStateManager.translated(tooltipScreen.width / 2 + 10, tooltipScreen.height / 2 - 16, 0);
|
||||
return item;
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package com.simibubi.create.modules.contraptions.goggle;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* Implement this Interface in the TileEntity class that wants to add info to the screen
|
||||
* */
|
||||
public interface IHaveHoveringInformation {
|
||||
|
||||
default boolean addToTooltip(List<String> tooltip, boolean isPlayerSneaking){
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -51,6 +51,8 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
|
|||
}
|
||||
|
||||
public void gatherInputs() {
|
||||
if (!basinInv.isPresent())
|
||||
return;
|
||||
BasinInventory inv = (BasinInventory) basinInv.orElse(null);
|
||||
inputs = new ArrayList<>();
|
||||
IItemHandlerModifiable inputHandler = inv.getInputHandler();
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.simibubi.create.foundation.utility.ColorHelper;
|
|||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
import com.simibubi.create.modules.contraptions.base.DirectionalAxisKineticBlock;
|
||||
import com.simibubi.create.modules.contraptions.base.IRotate;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
|
@ -25,7 +26,6 @@ import net.minecraft.util.math.Vec3d;
|
|||
import net.minecraft.util.math.shapes.ISelectionContext;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.IWorldReader;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class GaugeBlock extends DirectionalAxisKineticBlock {
|
||||
|
@ -65,34 +65,41 @@ public class GaugeBlock extends DirectionalAxisKineticBlock {
|
|||
return Blocks.SPRUCE_PLANKS.getMaterialColor(state, worldIn, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockItemUseContext context) {
|
||||
World world = context.getWorld();
|
||||
Direction face = context.getFace();
|
||||
BlockPos placedOnPos = context.getPos().offset(context.getFace().getOpposite());
|
||||
BlockState placedOnState = world.getBlockState(placedOnPos);
|
||||
Block block = placedOnState.getBlock();
|
||||
|
||||
if (block instanceof IRotate && ((IRotate) block).hasShaftTowards(world, placedOnPos, placedOnState, face)) {
|
||||
BlockState toPlace = getDefaultState();
|
||||
Direction horizontalFacing = context.getPlacementHorizontalFacing();
|
||||
Direction nearestLookingDirection = context.getNearestLookingDirection();
|
||||
boolean lookPositive = nearestLookingDirection.getAxisDirection() == AxisDirection.POSITIVE;
|
||||
if (face.getAxis() == Axis.X) {
|
||||
toPlace = toPlace.with(FACING, lookPositive ? Direction.NORTH : Direction.SOUTH)
|
||||
.with(AXIS_ALONG_FIRST_COORDINATE, true);
|
||||
} else if (face.getAxis() == Axis.Y) {
|
||||
toPlace = toPlace.with(FACING, horizontalFacing.getOpposite()).with(AXIS_ALONG_FIRST_COORDINATE,
|
||||
horizontalFacing.getAxis() == Axis.X);
|
||||
} else {
|
||||
toPlace = toPlace.with(FACING, lookPositive ? Direction.WEST : Direction.EAST)
|
||||
.with(AXIS_ALONG_FIRST_COORDINATE, false);
|
||||
}
|
||||
|
||||
return toPlace;
|
||||
}
|
||||
|
||||
return super.getStateForPlacement(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasStaticPart() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) {
|
||||
Direction facing = state.get(FACING).getOpposite();
|
||||
BlockPos neighbourPos = pos.offset(facing);
|
||||
BlockState neighbour = worldIn.getBlockState(neighbourPos);
|
||||
return Block.hasSolidSide(neighbour, worldIn, neighbourPos, facing.getOpposite());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
|
||||
boolean isMoving) {
|
||||
if (worldIn.isRemote)
|
||||
return;
|
||||
|
||||
Direction blockFacing = state.get(FACING);
|
||||
if (fromPos.equals(pos.offset(blockFacing.getOpposite()))) {
|
||||
if (!isValidPosition(state, worldIn, pos)) {
|
||||
worldIn.destroyBlock(pos, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Direction getFacingForPlacement(BlockItemUseContext context) {
|
||||
return context.getFace();
|
||||
|
|
|
@ -58,7 +58,7 @@ public class FilterItem extends Item implements INamedContainerProvider {
|
|||
ItemDescription.add(tooltip, makeSummary);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<String> makeSummary(ItemStack filter) {
|
||||
List<String> list = new ArrayList<>();
|
||||
|
||||
|
|
|
@ -269,6 +269,7 @@
|
|||
"death.attack.create.cuckoo_clock_explosion": "%1$s was blown up by tampered cuckoo clock",
|
||||
|
||||
"create.recipe.crushing": "Crushing",
|
||||
"create.recipe.milling": "Milling",
|
||||
"create.recipe.splashing": "Bulk Washing",
|
||||
"create.recipe.splashing.fan": "Fan behind Flowing Water",
|
||||
"create.recipe.smokingViaFan": "Bulk Smoking",
|
||||
|
@ -400,6 +401,7 @@
|
|||
"create.gui.stress_gauge.no_rotation": "No Rotation",
|
||||
|
||||
"create.gui.contraptions.not_fast_enough": "It appears that this %1$s is _not_ rotating with _enough_ _speed_.",
|
||||
"create.gui.contraptions.network_overstressed": "It appears that this contraption is _overstressed_. Add more sources or _slow_ _down_ the components with a high _stress_ _impact_.",
|
||||
|
||||
"create.gui.flexcrate.title": "Adjustable Crate",
|
||||
"create.gui.flexcrate.storageSpace": "Storage Space",
|
||||
|
@ -849,6 +851,11 @@
|
|||
|
||||
"block.create.turntable.tooltip": "TURNTABLE",
|
||||
"block.create.turntable.tooltip.summary": "Turns _Rotational_ _Force_ into refined Motion Sickness.",
|
||||
|
||||
"block.create.millstone.tooltip": "MILLSTONE",
|
||||
"block.create.millstone.tooltip.summary": "A kinetic component suitable for _grinding_ inserted _materials_. Can be powered by an adjacent cogwheel or by connecting to the shaft at the bottom.",
|
||||
"block.create.millstone.tooltip.condition1": "When Rotated",
|
||||
"block.create.millstone.tooltip.behaviour1": "Starts applying _milling_ _recipes_ to any items inserted from the side or the top of the block.",
|
||||
|
||||
"block.create.crushing_wheel.tooltip": "CRUSHING WHEEL",
|
||||
"block.create.crushing_wheel.tooltip.summary": "Large rotatable wheels that _break_ _down_ anything.",
|
||||
|
|
|
@ -83,7 +83,9 @@
|
|||
"north": {"uv": [1, 1.5, 5, 5], "texture": "#5"},
|
||||
"east": {"uv": [1, 1.5, 5, 5], "texture": "#5"},
|
||||
"south": {"uv": [1, 1.5, 5, 5], "texture": "#5"},
|
||||
"west": {"uv": [1, 1.5, 5, 5], "texture": "#5"}
|
||||
"west": {"uv": [1, 1.5, 5, 5], "texture": "#5"},
|
||||
"up": {"uv": [1, 1, 5, 5], "texture": "#5"},
|
||||
"down": {"uv": [1, 1, 5, 5], "texture": "#5"}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"type": "crafting_shaped",
|
||||
"pattern": [
|
||||
"ABA",
|
||||
"BSB",
|
||||
"ABA"
|
||||
],
|
||||
"key": {
|
||||
"B": {
|
||||
"item": "minecraft:polished_andesite"
|
||||
},
|
||||
"A": {
|
||||
"item": "create:andesite_alloy"
|
||||
},
|
||||
"S": {
|
||||
"item": "create:large_cogwheel"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "create:crushing_wheel",
|
||||
"count": 1
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"type": "create:module",
|
||||
"module": "contraptions"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"type": "create:milling",
|
||||
"type": "create:crushing",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "minecraft:diamond_horse_armor"
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"type": "create:milling",
|
||||
"type": "create:crushing",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "minecraft:golden_horse_armor"
|
25
src/main/resources/data/create/recipes/crushing/gravel.json
Normal file
25
src/main/resources/data/create/recipes/crushing/gravel.json
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"type": "create:crushing",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "minecraft:gravel"
|
||||
}
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"item": "minecraft:sand",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item": "minecraft:clay_ball",
|
||||
"count": 1,
|
||||
"chance": 0.1
|
||||
},
|
||||
{
|
||||
"item": "minecraft:flint",
|
||||
"count": 1,
|
||||
"chance": 0.2
|
||||
}
|
||||
],
|
||||
"processingTime": 250
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"type": "create:milling",
|
||||
"type": "create:crushing",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "minecraft:iron_horse_armor"
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"type": "create:milling",
|
||||
"type": "create:crushing",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "minecraft:leather_horse_armor"
|
25
src/main/resources/data/create/recipes/crushing/sand.json
Normal file
25
src/main/resources/data/create/recipes/crushing/sand.json
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"type": "create:crushing",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "minecraft:sand"
|
||||
}
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"item": "create:limesand",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item": "create:limesand",
|
||||
"count": 1,
|
||||
"chance": 0.5
|
||||
},
|
||||
{
|
||||
"item": "minecraft:bone_meal",
|
||||
"count": 1,
|
||||
"chance": 0.05
|
||||
}
|
||||
],
|
||||
"processingTime": 150
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"type": "create:mechanical_crafting",
|
||||
"pattern": [
|
||||
" PPP ",
|
||||
"PSBSP",
|
||||
"PBCBP",
|
||||
"PSBSP",
|
||||
" PPP "
|
||||
],
|
||||
"key": {
|
||||
"P": {
|
||||
"item": "create:andesite_alloy"
|
||||
},
|
||||
"S": {
|
||||
"tag": "forge:rods/wooden"
|
||||
},
|
||||
"C": {
|
||||
"item": "create:andesite_casing"
|
||||
},
|
||||
"B": {
|
||||
"tag": "forge:stone"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "create:crushing_wheel",
|
||||
"count": 2
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"type": "create:module",
|
||||
"module": "contraptions"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -14,11 +14,6 @@
|
|||
"item": "minecraft:clay_ball",
|
||||
"count": 1,
|
||||
"chance": 0.5
|
||||
},
|
||||
{
|
||||
"item": "minecraft:flint",
|
||||
"count": 1,
|
||||
"chance": 0.2
|
||||
}
|
||||
],
|
||||
"processingTime": 50
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"type": "create:milling",
|
||||
"ingredients": [
|
||||
{
|
||||
"tag": "forge:ores/copper"
|
||||
}
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"item": "create:crushed_copper",
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"processingTime": 350
|
||||
}
|
15
src/main/resources/data/create/recipes/milling/gold_ore.json
Normal file
15
src/main/resources/data/create/recipes/milling/gold_ore.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"type": "create:milling",
|
||||
"ingredients": [
|
||||
{
|
||||
"tag": "forge:ores/gold"
|
||||
}
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"item": "create:crushed_gold",
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"processingTime": 350
|
||||
}
|
|
@ -6,19 +6,9 @@
|
|||
}
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"item": "minecraft:sand",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item": "minecraft:clay_ball",
|
||||
"count": 1,
|
||||
"chance": 0.1
|
||||
},
|
||||
{
|
||||
"item": "minecraft:flint",
|
||||
"count": 1,
|
||||
"chance": 0.2
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"processingTime": 250
|
||||
|
|
15
src/main/resources/data/create/recipes/milling/iron_ore.json
Normal file
15
src/main/resources/data/create/recipes/milling/iron_ore.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"type": "create:milling",
|
||||
"ingredients": [
|
||||
{
|
||||
"tag": "forge:ores/iron"
|
||||
}
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"item": "create:crushed_iron",
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"processingTime": 400
|
||||
}
|
|
@ -9,16 +9,6 @@
|
|||
{
|
||||
"item": "create:limesand",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item": "create:limesand",
|
||||
"count": 1,
|
||||
"chance": 0.5
|
||||
},
|
||||
{
|
||||
"item": "minecraft:bone_meal",
|
||||
"count": 1,
|
||||
"chance": 0.05
|
||||
}
|
||||
],
|
||||
"processingTime": 150
|
||||
|
|
15
src/main/resources/data/create/recipes/milling/zinc_ore.json
Normal file
15
src/main/resources/data/create/recipes/milling/zinc_ore.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"type": "create:milling",
|
||||
"ingredients": [
|
||||
{
|
||||
"tag": "forge:ores/zinc"
|
||||
}
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"item": "create:crushed_zinc",
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"processingTime": 350
|
||||
}
|
Loading…
Reference in a new issue