Foliage Machine

- Mechanical Harvesters can now be used to gather Leaves
- Mechanical Harvesters can now be used to gather Weeping and Twisting Vines
- Fixed JEI integration of Basin recipes with multiple and/or stochastic outputs
This commit is contained in:
simibubi 2021-08-31 13:46:28 +02:00
parent 42fac69721
commit aecd988384
2 changed files with 53 additions and 32 deletions

View file

@ -6,7 +6,6 @@ import java.util.stream.Collectors;
import org.apache.commons.lang3.mutable.MutableInt; import org.apache.commons.lang3.mutable.MutableInt;
import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
@ -73,17 +72,10 @@ public class BasinCategory extends CreateRecipeCategory<BasinRecipe> {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
IGuiFluidStackGroup fluidStacks = recipeLayout.getFluidStacks(); IGuiFluidStackGroup fluidStacks = recipeLayout.getFluidStacks();
ItemStack itemOutput = recipe.getRollableResultsAsItemStacks()
.isEmpty() ? ItemStack.EMPTY
: recipe.getRollableResultsAsItemStacks()
.get(0);
FluidStack fluidOutput = recipe.getFluidResults()
.isEmpty() ? FluidStack.EMPTY
: recipe.getFluidResults()
.get(0);
NonNullList<FluidIngredient> fluidIngredients = recipe.getFluidIngredients(); NonNullList<FluidIngredient> fluidIngredients = recipe.getFluidIngredients();
List<Pair<Ingredient, MutableInt>> ingredients = ItemHelper.condenseIngredients(recipe.getIngredients()); List<Pair<Ingredient, MutableInt>> ingredients = ItemHelper.condenseIngredients(recipe.getIngredients());
List<ItemStack> itemOutputs = recipe.getRollableResultsAsItemStacks();
NonNullList<FluidStack> fluidOutputs = recipe.getFluidResults();
int size = ingredients.size() + fluidIngredients.size(); int size = ingredients.size() + fluidIngredients.size();
int xOffset = size < 3 ? (3 - size) * 19 / 2 : 0; int xOffset = size < 3 ? (3 - size) * 19 / 2 : 0;
@ -115,28 +107,41 @@ public class BasinCategory extends CreateRecipeCategory<BasinRecipe> {
fluidStacks.set(j, withImprovedVisibility(stacks)); fluidStacks.set(j, withImprovedVisibility(stacks));
} }
if (!itemOutput.isEmpty()) { int outSize = fluidOutputs.size() + recipe.getRollableResults()
itemStacks.init(i, false, 141, 50 + yOffset); .size();
itemStacks.set(i, recipe.getResultItem() int outputIndex = 0;
.getStack());
yOffset -= 19; if (!itemOutputs.isEmpty())
addStochasticTooltip(itemStacks, recipe.getRollableResults(), i);
for (; outputIndex < outSize; outputIndex++) {
int xPosition = 141 - (outSize % 2 != 0 && outputIndex == outSize - 1 ? 0 : outputIndex % 2 == 0 ? 10 : -9);
int yPosition = -19 * (outputIndex / 2) + 50 + yOffset;
if (itemOutputs.size() > outputIndex) {
itemStacks.init(i, false, xPosition, yPosition + yOffset);
itemStacks.set(i, itemOutputs.get(outputIndex));
i++;
} else {
fluidStacks.init(j, false, xPosition + 1, yPosition + 1 + yOffset);
fluidStacks.set(j, withImprovedVisibility(fluidOutputs.get(outputIndex - itemOutputs.size())));
j++;
}
} }
if (!fluidOutput.isEmpty()) { addFluidTooltip(fluidStacks, fluidIngredients, fluidOutputs);
fluidStacks.init(j, false, 142, 51 + yOffset);
fluidStacks.set(j, withImprovedVisibility(fluidOutput));
}
addFluidTooltip(fluidStacks, fluidIngredients, ImmutableList.of(fluidOutput));
HeatCondition requiredHeat = recipe.getRequiredHeat(); HeatCondition requiredHeat = recipe.getRequiredHeat();
if (!requiredHeat.testBlazeBurner(HeatLevel.NONE)) { if (!requiredHeat.testBlazeBurner(HeatLevel.NONE)) {
itemStacks.init(++i, true, 133, 80); itemStacks.init(i, true, 133, 80);
itemStacks.set(i, AllBlocks.BLAZE_BURNER.asStack()); itemStacks.set(i, AllBlocks.BLAZE_BURNER.asStack());
i++;
} }
if (!requiredHeat.testBlazeBurner(HeatLevel.KINDLED)) { if (!requiredHeat.testBlazeBurner(HeatLevel.KINDLED)) {
itemStacks.init(++i, true, 152, 80); itemStacks.init(i, true, 152, 80);
itemStacks.set(i, AllItems.BLAZE_CAKE.asStack()); itemStacks.set(i, AllItems.BLAZE_CAKE.asStack());
i++;
} }
} }
@ -146,6 +151,8 @@ public class BasinCategory extends CreateRecipeCategory<BasinRecipe> {
int size = actualIngredients.size() + recipe.getFluidIngredients() int size = actualIngredients.size() + recipe.getFluidIngredients()
.size(); .size();
int outSize = recipe.getFluidResults().size() + recipe.getRollableResults().size();
int xOffset = size < 3 ? (3 - size) * 19 / 2 : 0; int xOffset = size < 3 ? (3 - size) * 19 / 2 : 0;
HeatCondition requiredHeat = recipe.getRequiredHeat(); HeatCondition requiredHeat = recipe.getRequiredHeat();
int yOffset = 0; int yOffset = 0;
@ -154,8 +161,13 @@ public class BasinCategory extends CreateRecipeCategory<BasinRecipe> {
AllGuiTextures.JEI_SLOT.draw(matrixStack, 16 + xOffset + (i % 3) * 19, 50 - (i / 3) * 19 + yOffset); AllGuiTextures.JEI_SLOT.draw(matrixStack, 16 + xOffset + (i % 3) * 19, 50 - (i / 3) * 19 + yOffset);
boolean noHeat = requiredHeat == HeatCondition.NONE; boolean noHeat = requiredHeat == HeatCondition.NONE;
AllGuiTextures.JEI_SLOT.draw(matrixStack, 141, 50 + yOffset);
AllGuiTextures.JEI_DOWN_ARROW.draw(matrixStack, 136, 32 + yOffset); int vRows = (1 + outSize) / 2;
for (int i = 0; i < outSize; i++)
AllGuiTextures.JEI_SLOT.draw(matrixStack,
141 - (outSize % 2 != 0 && i == outSize - 1 ? 0 : i % 2 == 0 ? 10 : -9), -19 * (i / 2) + 50 + yOffset);
if (vRows <= 2)
AllGuiTextures.JEI_DOWN_ARROW.draw(matrixStack, 136, -19 * (vRows - 1) + 32 + yOffset);
AllGuiTextures shadow = noHeat ? AllGuiTextures.JEI_SHADOW : AllGuiTextures.JEI_LIGHT; AllGuiTextures shadow = noHeat ? AllGuiTextures.JEI_SHADOW : AllGuiTextures.JEI_LIGHT;
shadow.draw(matrixStack, 81, 58 + (noHeat ? 10 : 30)); shadow.draw(matrixStack, 81, 58 + (noHeat ? 10 : 30));

View file

@ -16,19 +16,20 @@ import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
import net.minecraft.block.AbstractPlantBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.CocoaBlock; import net.minecraft.block.CocoaBlock;
import net.minecraft.block.CropsBlock; import net.minecraft.block.CropsBlock;
import net.minecraft.block.KelpBlock;
import net.minecraft.block.KelpTopBlock;
import net.minecraft.block.SugarCaneBlock; import net.minecraft.block.SugarCaneBlock;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.state.IntegerProperty; import net.minecraft.state.IntegerProperty;
import net.minecraft.state.Property; import net.minecraft.state.Property;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -83,9 +84,17 @@ public class HarvesterMovementBehaviour extends MovementBehaviour {
return; return;
} }
ItemStack item = ItemStack.EMPTY;
float effectChance = 1;
if (stateVisited.getBlock().is(BlockTags.LEAVES)) {
item = new ItemStack(Items.SHEARS);
effectChance = .45f;
}
MutableBoolean seedSubtracted = new MutableBoolean(notCropButCuttable); MutableBoolean seedSubtracted = new MutableBoolean(notCropButCuttable);
BlockState state = stateVisited; BlockState state = stateVisited;
BlockHelper.destroyBlock(world, pos, 1, stack -> { BlockHelper.destroyBlockAs(world, pos, null, item, effectChance, stack -> {
if (!seedSubtracted.getValue() && stack.sameItem(new ItemStack(state.getBlock()))) { if (!seedSubtracted.getValue() && stack.sameItem(new ItemStack(state.getBlock()))) {
stack.shrink(1); stack.shrink(1);
seedSubtracted.setTrue(); seedSubtracted.setTrue();
@ -127,12 +136,12 @@ public class HarvesterMovementBehaviour extends MovementBehaviour {
return false; return false;
if (state.getBlock() instanceof SugarCaneBlock) if (state.getBlock() instanceof SugarCaneBlock)
return true; return true;
if (state.getBlock().is(BlockTags.LEAVES))
return true;
if (state.getCollisionShape(world, pos) if (state.getCollisionShape(world, pos)
.isEmpty() || state.getBlock() instanceof CocoaBlock) { .isEmpty() || state.getBlock() instanceof CocoaBlock) {
if (state.getBlock() instanceof KelpBlock) if (state.getBlock() instanceof AbstractPlantBlock)
return true;
if (state.getBlock() instanceof KelpTopBlock)
return true; return true;
for (Property<?> property : state.getProperties()) { for (Property<?> property : state.getProperties()) {
@ -160,7 +169,7 @@ public class HarvesterMovementBehaviour extends MovementBehaviour {
if (block == Blocks.SWEET_BERRY_BUSH) { if (block == Blocks.SWEET_BERRY_BUSH) {
return state.setValue(BlockStateProperties.AGE_3, Integer.valueOf(1)); return state.setValue(BlockStateProperties.AGE_3, Integer.valueOf(1));
} }
if (block == Blocks.SUGAR_CANE || block == Blocks.KELP) { if (block == Blocks.SUGAR_CANE || block instanceof AbstractPlantBlock) {
if (state.getFluidState() if (state.getFluidState()
.isEmpty()) .isEmpty())
return Blocks.AIR.defaultBlockState(); return Blocks.AIR.defaultBlockState();