Pattern grid changes (#2344)

* Begin work on input configuration

* Sync

* Saving

* Readability

* Apply

* Invalidate pattern when declared tags are no longer applicable

* Move pattern creation to a factory

* Localize error message

* Add flag for input config slots

* Apply allowed tags when pattern is inserted

* Fix ctor

* Initial layout

* When putting a pattern, use processing from pattern

* When jei transferring, switch to correct mode
This commit is contained in:
Raoul
2019-11-04 14:35:38 +01:00
committed by GitHub
parent faf12d50df
commit b7e632b92d
22 changed files with 1034 additions and 193 deletions

View File

@@ -3,8 +3,10 @@ package com.raoulvdberge.refinedstorage.api.autocrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.fluids.FluidStack;
import javax.annotation.Nullable;
import java.util.List;
/**
@@ -26,16 +28,17 @@ public interface ICraftingPattern {
*/
boolean isValid();
/**
* @return an error message when this pattern is not valid, or null if there's no message
*/
@Nullable
ITextComponent getErrorMessage();
/**
* @return true if the crafting pattern can be treated as a processing pattern, false otherwise
*/
boolean isProcessing();
/**
* @return true if the crafting pattern is in exact mode, false otherwise
*/
boolean isExact();
/**
* @return the inputs per slot
*/

View File

@@ -5,142 +5,57 @@ import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternContaine
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.registry.CraftingTaskFactory;
import com.raoulvdberge.refinedstorage.item.PatternItem;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.AllowedTags;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluid;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.ICraftingRecipe;
import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.tags.FluidTags;
import net.minecraft.tags.ItemTags;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.fluids.FluidStack;
import java.util.ArrayList;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Optional;
public class CraftingPattern implements ICraftingPattern {
private ICraftingPatternContainer container;
private ItemStack stack;
private boolean processing;
private boolean exact;
private boolean valid;
private ICraftingRecipe recipe;
private List<NonNullList<ItemStack>> inputs = new ArrayList<>();
private NonNullList<ItemStack> outputs = NonNullList.create();
private NonNullList<ItemStack> byproducts = NonNullList.create();
private List<NonNullList<FluidStack>> fluidInputs = new ArrayList<>();
private NonNullList<FluidStack> fluidOutputs = NonNullList.create();
private final ICraftingPatternContainer container;
private final ItemStack stack;
private final boolean processing;
private final boolean exact;
private final boolean valid;
@Nullable
private final ITextComponent errorMessage;
@Nullable
private final ICraftingRecipe recipe;
private final List<NonNullList<ItemStack>> inputs;
private final NonNullList<ItemStack> outputs;
private final NonNullList<ItemStack> byproducts;
private final List<NonNullList<FluidStack>> fluidInputs;
private final NonNullList<FluidStack> fluidOutputs;
@Nullable
private final AllowedTags allowedTags;
public CraftingPattern(World world, ICraftingPatternContainer container, ItemStack stack) {
public CraftingPattern(ICraftingPatternContainer container, ItemStack stack, boolean processing, boolean exact, @Nullable ITextComponent errorMessage, boolean valid, @Nullable ICraftingRecipe recipe, List<NonNullList<ItemStack>> inputs, NonNullList<ItemStack> outputs, NonNullList<ItemStack> byproducts, List<NonNullList<FluidStack>> fluidInputs, NonNullList<FluidStack> fluidOutputs, @Nullable AllowedTags allowedTags) {
this.container = container;
this.stack = stack;
this.processing = PatternItem.isProcessing(stack);
this.exact = PatternItem.isExact(stack);
this.processing = processing;
this.exact = exact;
this.valid = valid;
this.errorMessage = errorMessage;
this.recipe = recipe;
this.inputs = inputs;
this.outputs = outputs;
this.byproducts = byproducts;
this.fluidInputs = fluidInputs;
this.fluidOutputs = fluidOutputs;
this.allowedTags = allowedTags;
}
if (processing) {
for (int i = 0; i < 9; ++i) {
{
ItemStack input = PatternItem.getInputSlot(stack, i);
if (input.isEmpty()) {
inputs.add(NonNullList.create());
} else if (!exact) {
NonNullList<ItemStack> possibilities = NonNullList.create();
possibilities.add(input.copy());
for (ResourceLocation owningTag : ItemTags.getCollection().getOwningTags(input.getItem())) {
for (Item element : ItemTags.getCollection().get(owningTag).getAllElements()) {
possibilities.add(new ItemStack(element, input.getCount()));
}
}
inputs.add(possibilities);
} else {
inputs.add(NonNullList.from(ItemStack.EMPTY, input));
}
ItemStack output = PatternItem.getOutputSlot(stack, i);
if (!output.isEmpty()) {
this.valid = true; // As soon as we have one output, we are valid.
outputs.add(output);
}
}
{
FluidStack fluidInput = PatternItem.getFluidInputSlot(stack, i);
if (fluidInput.isEmpty()) {
fluidInputs.add(NonNullList.create());
} else if (!exact) {
NonNullList<FluidStack> possibilities = NonNullList.create();
possibilities.add(fluidInput.copy());
for (ResourceLocation owningTag : FluidTags.getCollection().getOwningTags(fluidInput.getFluid())) {
for (Fluid element : FluidTags.getCollection().get(owningTag).getAllElements()) {
possibilities.add(new FluidStack(element, fluidInput.getAmount()));
}
}
fluidInputs.add(possibilities);
} else {
fluidInputs.add(NonNullList.from(FluidStack.EMPTY, fluidInput));
}
}
FluidStack fluidOutput = PatternItem.getFluidOutputSlot(stack, i);
if (!fluidOutput.isEmpty()) {
this.valid = true;
fluidOutputs.add(fluidOutput);
}
}
} else {
CraftingInventory inv = new DummyCraftingInventory();
for (int i = 0; i < 9; ++i) {
ItemStack input = PatternItem.getInputSlot(stack, i);
inputs.add(input.isEmpty() ? NonNullList.create() : NonNullList.from(ItemStack.EMPTY, input));
inv.setInventorySlotContents(i, input);
}
Optional<ICraftingRecipe> potentialRecipe = world.getRecipeManager().getRecipe(IRecipeType.CRAFTING, inv, world);
if (potentialRecipe.isPresent()) {
this.recipe = potentialRecipe.get();
this.byproducts = recipe.getRemainingItems(inv);
ItemStack output = recipe.getCraftingResult(inv);
if (!output.isEmpty()) {
this.valid = true;
outputs.add(output);
if (!exact) {
if (recipe.getIngredients().size() > 0) {
inputs.clear();
for (int i = 0; i < recipe.getIngredients().size(); ++i) {
inputs.add(i, NonNullList.from(ItemStack.EMPTY, recipe.getIngredients().get(i).getMatchingStacks()));
}
} else {
this.valid = false;
}
}
}
}
}
@Nullable
public AllowedTags getAllowedTags() {
return allowedTags;
}
@Override
@@ -158,14 +73,15 @@ public class CraftingPattern implements ICraftingPattern {
return valid;
}
@Nullable
@Override
public boolean isProcessing() {
return processing;
public ITextComponent getErrorMessage() {
return errorMessage;
}
@Override
public boolean isExact() {
return exact;
public boolean isProcessing() {
return processing;
}
@Override
@@ -255,7 +171,7 @@ public class CraftingPattern implements ICraftingPattern {
@Override
public boolean canBeInChainWith(ICraftingPattern other) {
if (other.isProcessing() != processing || other.isExact() != exact) {
if (other.isProcessing() != processing) {
return false;
}
@@ -357,7 +273,7 @@ public class CraftingPattern implements ICraftingPattern {
return result;
}
private class DummyCraftingInventory extends CraftingInventory {
public static class DummyCraftingInventory extends CraftingInventory {
public DummyCraftingInventory() {
super(new Container(null, 0) {
@Override

View File

@@ -0,0 +1,185 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternContainer;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.AllowedTags;
import com.raoulvdberge.refinedstorage.item.PatternItem;
import net.minecraft.fluid.Fluid;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.ICraftingRecipe;
import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.tags.FluidTags;
import net.minecraft.tags.ItemTags;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
import javax.annotation.Nullable;
import java.util.*;
public class CraftingPatternFactory {
public static final CraftingPatternFactory INSTANCE = new CraftingPatternFactory();
public CraftingPattern create(World world, ICraftingPatternContainer container, ItemStack stack) {
boolean processing = PatternItem.isProcessing(stack);
boolean exact = PatternItem.isExact(stack);
AllowedTags allowedTags = PatternItem.getAllowedTags(stack);
List<NonNullList<ItemStack>> inputs = new ArrayList<>();
NonNullList<ItemStack> outputs = NonNullList.create();
NonNullList<ItemStack> byproducts = NonNullList.create();
List<NonNullList<FluidStack>> fluidInputs = new ArrayList<>();
NonNullList<FluidStack> fluidOutputs = NonNullList.create();
ICraftingRecipe recipe = null;
boolean valid = true;
ITextComponent errorMessage = null;
try {
if (processing) {
for (int i = 0; i < 9; ++i) {
fillProcessingInputs(i, stack, inputs, outputs, allowedTags);
fillProcessingFluidInputs(i, stack, fluidInputs, fluidOutputs, allowedTags);
}
if (outputs.isEmpty() && fluidOutputs.isEmpty()) {
throw new CraftingPatternFactoryException(new TranslationTextComponent("misc.refinedstorage.pattern.error.processing_no_outputs"));
}
} else {
CraftingInventory inv = new CraftingPattern.DummyCraftingInventory();
for (int i = 0; i < 9; ++i) {
fillCraftingInputs(inv, stack, inputs, i);
}
Optional<ICraftingRecipe> foundRecipe = world.getRecipeManager().getRecipe(IRecipeType.CRAFTING, inv, world);
if (foundRecipe.isPresent()) {
recipe = foundRecipe.get();
byproducts = recipe.getRemainingItems(inv);
ItemStack output = recipe.getCraftingResult(inv);
if (!output.isEmpty()) {
outputs.add(output);
if (!exact) {
modifyCraftingInputsToUseAlternatives(recipe, inputs);
}
} else {
throw new CraftingPatternFactoryException(new TranslationTextComponent("misc.refinedstorage.pattern.error.no_output"));
}
} else {
throw new CraftingPatternFactoryException(new TranslationTextComponent("misc.refinedstorage.pattern.error.recipe_does_not_exist"));
}
}
} catch (CraftingPatternFactoryException e) {
valid = false;
errorMessage = e.getErrorMessage();
}
return new CraftingPattern(container, stack, processing, exact, errorMessage, valid, recipe, inputs, outputs, byproducts, fluidInputs, fluidOutputs, allowedTags);
}
private void fillProcessingInputs(int i, ItemStack stack, List<NonNullList<ItemStack>> inputs, NonNullList<ItemStack> outputs, @Nullable AllowedTags allowedTags) throws CraftingPatternFactoryException {
ItemStack input = PatternItem.getInputSlot(stack, i);
if (input.isEmpty()) {
inputs.add(NonNullList.create());
} else {
NonNullList<ItemStack> possibilities = NonNullList.create();
possibilities.add(input.copy());
if (allowedTags != null) {
Collection<ResourceLocation> tagsOfItem = ItemTags.getCollection().getOwningTags(input.getItem());
Set<ResourceLocation> declaredAllowedTags = allowedTags.getAllowedItemTags().get(i);
for (ResourceLocation declaredAllowedTag : declaredAllowedTags) {
if (!tagsOfItem.contains(declaredAllowedTag)) {
throw new CraftingPatternFactoryException(
new TranslationTextComponent(
"misc.refinedstorage.pattern.error.tag_no_longer_applicable",
declaredAllowedTag.toString(),
input.getDisplayName()
)
);
} else {
for (Item element : ItemTags.getCollection().get(declaredAllowedTag).getAllElements()) {
possibilities.add(new ItemStack(element, input.getCount()));
}
}
}
}
inputs.add(possibilities);
}
ItemStack output = PatternItem.getOutputSlot(stack, i);
if (!output.isEmpty()) {
outputs.add(output);
}
}
private void fillProcessingFluidInputs(int i, ItemStack stack, List<NonNullList<FluidStack>> fluidInputs, NonNullList<FluidStack> fluidOutputs, @Nullable AllowedTags allowedTags) throws CraftingPatternFactoryException {
FluidStack input = PatternItem.getFluidInputSlot(stack, i);
if (input.isEmpty()) {
fluidInputs.add(NonNullList.create());
} else {
NonNullList<FluidStack> possibilities = NonNullList.create();
possibilities.add(input.copy());
if (allowedTags != null) {
Collection<ResourceLocation> tagsOfFluid = FluidTags.getCollection().getOwningTags(input.getFluid());
Set<ResourceLocation> declaredAllowedTags = allowedTags.getAllowedFluidTags().get(i);
for (ResourceLocation declaredAllowedTag : declaredAllowedTags) {
if (!tagsOfFluid.contains(declaredAllowedTag)) {
throw new CraftingPatternFactoryException(
new TranslationTextComponent(
"misc.refinedstorage.pattern.error.tag_no_longer_applicable",
declaredAllowedTag.toString(),
input.getDisplayName()
)
);
} else {
for (Fluid element : FluidTags.getCollection().get(declaredAllowedTag).getAllElements()) {
possibilities.add(new FluidStack(element, input.getAmount()));
}
}
}
}
fluidInputs.add(possibilities);
}
FluidStack output = PatternItem.getFluidOutputSlot(stack, i);
if (!output.isEmpty()) {
fluidOutputs.add(output);
}
}
private void fillCraftingInputs(CraftingInventory inv, ItemStack stack, List<NonNullList<ItemStack>> inputs, int i) {
ItemStack input = PatternItem.getInputSlot(stack, i);
inputs.add(input.isEmpty() ? NonNullList.create() : NonNullList.from(ItemStack.EMPTY, input));
inv.setInventorySlotContents(i, input);
}
private void modifyCraftingInputsToUseAlternatives(ICraftingRecipe recipe, List<NonNullList<ItemStack>> inputs) throws CraftingPatternFactoryException {
if (!recipe.getIngredients().isEmpty()) {
inputs.clear();
for (int i = 0; i < recipe.getIngredients().size(); ++i) {
inputs.add(i, NonNullList.from(ItemStack.EMPTY, recipe.getIngredients().get(i).getMatchingStacks()));
}
} else {
throw new CraftingPatternFactoryException(new TranslationTextComponent("misc.refinedstorage.pattern.error.recipe_no_ingredients"));
}
}
}

View File

@@ -0,0 +1,15 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting;
import net.minecraft.util.text.ITextComponent;
public class CraftingPatternFactoryException extends Exception {
private final ITextComponent errorMessage;
public CraftingPatternFactoryException(ITextComponent errorMessage) {
this.errorMessage = errorMessage;
}
public ITextComponent getErrorMessage() {
return errorMessage;
}
}

View File

@@ -8,6 +8,7 @@ import com.raoulvdberge.refinedstorage.api.network.security.Permission;
import com.raoulvdberge.refinedstorage.api.util.Action;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.GridNetworkNode;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.InventoryHelper;
@@ -189,5 +190,10 @@ public class CraftingGridBehavior implements ICraftingGridBehavior {
}
}
}
if (grid.getGridType() == GridType.PATTERN) {
((GridNetworkNode) grid).setProcessingPattern(false);
((GridNetworkNode) grid).markDirty();
}
}
}

View File

@@ -0,0 +1,114 @@
package com.raoulvdberge.refinedstorage.apiimpl.network.node;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.nbt.StringNBT;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.util.Constants;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class AllowedTags {
private static final String NBT_ALLOWED_ITEM_TAGS = "AllowedItemTags";
private static final String NBT_ALLOWED_FLUID_TAGS = "AllowedFluidTags";
private List<Set<ResourceLocation>> allowedItemTags = new ArrayList<>();
private List<Set<ResourceLocation>> allowedFluidTags = new ArrayList<>();
@Nullable
private final Runnable listener;
public AllowedTags(@Nullable Runnable listener) {
for (int i = 0; i < 9; ++i) {
allowedItemTags.add(new HashSet<>());
allowedFluidTags.add(new HashSet<>());
}
this.listener = listener;
}
public CompoundNBT writeToNbt() {
CompoundNBT tag = new CompoundNBT();
tag.put(NBT_ALLOWED_ITEM_TAGS, getList(allowedItemTags));
tag.put(NBT_ALLOWED_FLUID_TAGS, getList(allowedFluidTags));
return tag;
}
public void readFromNbt(CompoundNBT tag) {
if (tag.contains(NBT_ALLOWED_ITEM_TAGS)) {
applyList(allowedItemTags, tag.getList(NBT_ALLOWED_ITEM_TAGS, Constants.NBT.TAG_LIST));
}
if (tag.contains(NBT_ALLOWED_FLUID_TAGS)) {
applyList(allowedFluidTags, tag.getList(NBT_ALLOWED_FLUID_TAGS, Constants.NBT.TAG_LIST));
}
}
private ListNBT getList(List<Set<ResourceLocation>> tagsPerSlot) {
ListNBT list = new ListNBT();
for (Set<ResourceLocation> tags : tagsPerSlot) {
ListNBT subList = new ListNBT();
tags.forEach(t -> subList.add(new StringNBT(t.toString())));
list.add(subList);
}
return list;
}
private void applyList(List<Set<ResourceLocation>> list, ListNBT tagList) {
for (int i = 0; i < tagList.size(); ++i) {
ListNBT subList = tagList.getList(i);
for (int j = 0; j < subList.size(); ++j) {
list.get(i).add(new ResourceLocation(subList.getString(j)));
}
}
}
public List<Set<ResourceLocation>> getAllowedItemTags() {
return allowedItemTags;
}
public List<Set<ResourceLocation>> getAllowedFluidTags() {
return allowedFluidTags;
}
public void setAllowedItemTags(List<Set<ResourceLocation>> allowedItemTags) {
this.allowedItemTags = allowedItemTags;
notifyListener();
}
public void setAllowedFluidTags(List<Set<ResourceLocation>> allowedFluidTags) {
this.allowedFluidTags = allowedFluidTags;
notifyListener();
}
public void clearItemTags(int slot) {
this.allowedItemTags.get(slot).clear();
notifyListener();
}
public void clearFluidTags(int slot) {
this.allowedFluidTags.get(slot).clear();
notifyListener();
}
private void notifyListener() {
if (listener != null) {
listener.run();
}
}
}

View File

@@ -37,6 +37,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.ICraftingRecipe;
import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
@@ -73,6 +74,9 @@ public class GridNetworkNode extends NetworkNode implements INetworkAwareGrid, I
private static final String NBT_PROCESSING_PATTERN = "ProcessingPattern";
private static final String NBT_PROCESSING_TYPE = "ProcessingType";
private static final String NBT_PROCESSING_MATRIX_FLUIDS = "ProcessingMatrixFluids";
private static final String NBT_ALLOWED_TAGS = "AllowedTags";
private final AllowedTags allowedTags = new AllowedTags(this::updateAllowedTags);
private Container craftingContainer = new Container(ContainerType.CRAFTING, 0) {
@Override
@@ -90,8 +94,20 @@ public class GridNetworkNode extends NetworkNode implements INetworkAwareGrid, I
private ICraftingRecipe currentRecipe;
private CraftingInventory matrix = new CraftingInventory(craftingContainer, 3, 3);
private CraftResultInventory result = new CraftResultInventory();
private BaseItemHandler processingMatrix = new BaseItemHandler(9 * 2).addListener(new NetworkNodeInventoryListener(this));
private FluidInventory processingMatrixFluids = new FluidInventory(9 * 2, FluidAttributes.BUCKET_VOLUME * 64).addListener(new NetworkNodeFluidInventoryListener(this));
private BaseItemHandler processingMatrix = new BaseItemHandler(9 * 2)
.addListener(new NetworkNodeInventoryListener(this))
.addListener((handler, slot, reading) -> {
if (!reading && slot < 9) {
allowedTags.clearItemTags(slot);
}
});
private FluidInventory processingMatrixFluids = new FluidInventory(9 * 2, FluidAttributes.BUCKET_VOLUME * 64)
.addListener(new NetworkNodeFluidInventoryListener(this))
.addListener((handler, slot, reading) -> {
if (!reading && slot < 9) {
allowedTags.clearFluidTags(slot);
}
});
private boolean reading;
@@ -124,9 +140,9 @@ public class GridNetworkNode extends NetworkNode implements INetworkAwareGrid, I
ItemStack pattern = handler.getStackInSlot(slot);
if (slot == 1 && !pattern.isEmpty()) {
boolean isPatternProcessing = PatternItem.isProcessing(pattern);
boolean processing = PatternItem.isProcessing(pattern);
if (isPatternProcessing && isProcessingPattern()) {
if (processing) {
for (int i = 0; i < 9; ++i) {
processingMatrix.setStackInSlot(i, PatternItem.getInputSlot(pattern, i));
processingMatrixFluids.setFluid(i, PatternItem.getFluidInputSlot(pattern, i));
@@ -136,11 +152,21 @@ public class GridNetworkNode extends NetworkNode implements INetworkAwareGrid, I
processingMatrix.setStackInSlot(9 + i, PatternItem.getOutputSlot(pattern, i));
processingMatrixFluids.setFluid(9 + i, PatternItem.getFluidOutputSlot(pattern, i));
}
} else if (!isPatternProcessing && !isProcessingPattern()) {
AllowedTags allowedTagsFromPattern = PatternItem.getAllowedTags(pattern);
if (allowedTagsFromPattern != null) {
allowedTags.setAllowedItemTags(allowedTagsFromPattern.getAllowedItemTags());
allowedTags.setAllowedFluidTags(allowedTagsFromPattern.getAllowedFluidTags());
}
} else {
for (int i = 0; i < 9; ++i) {
matrix.setInventorySlotContents(i, PatternItem.getInputSlot(pattern, i));
}
}
setProcessingPattern(processing);
markDirty();
}
}));
@@ -169,6 +195,21 @@ public class GridNetworkNode extends NetworkNode implements INetworkAwareGrid, I
this.type = type;
}
public AllowedTags getAllowedTags() {
return allowedTags;
}
private void updateAllowedTags() {
markDirty();
TileEntity tile = world.getTileEntity(pos);
if (tile instanceof GridTile) {
((GridTile) tile).getDataManager().sendParameterToWatchers(GridTile.ALLOWED_ITEM_TAGS);
((GridTile) tile).getDataManager().sendParameterToWatchers(GridTile.ALLOWED_FLUID_TAGS);
}
}
@Override
public int getEnergyUsage() {
switch (type) {
@@ -402,9 +443,14 @@ public class GridNetworkNode extends NetworkNode implements INetworkAwareGrid, I
ItemStack pattern = new ItemStack(RSItems.PATTERN);
PatternItem.setToCurrentVersion(pattern);
PatternItem.setExact(pattern, exactPattern);
PatternItem.setProcessing(pattern, processingPattern);
if (!processingPattern) {
PatternItem.setExact(pattern, exactPattern);
} else {
PatternItem.setAllowedTags(pattern, allowedTags);
}
if (processingPattern) {
for (int i = 0; i < 18; ++i) {
if (!processingMatrix.getStackInSlot(i).isEmpty()) {
@@ -580,6 +626,10 @@ public class GridNetworkNode extends NetworkNode implements INetworkAwareGrid, I
public void read(CompoundNBT tag) {
super.read(tag);
if (tag.contains(NBT_ALLOWED_TAGS)) {
allowedTags.readFromNbt(tag.getCompound(NBT_ALLOWED_TAGS));
}
reading = true;
StackUtils.readItems(matrix, 0, tag);
@@ -611,6 +661,8 @@ public class GridNetworkNode extends NetworkNode implements INetworkAwareGrid, I
public CompoundNBT write(CompoundNBT tag) {
super.write(tag);
tag.put(NBT_ALLOWED_TAGS, allowedTags.writeToNbt());
StackUtils.writeItems(matrix, 0, tag);
StackUtils.writeItems(patterns, 1, tag);
StackUtils.writeItems(filter, 2, tag);

View File

@@ -169,8 +169,18 @@ public class GridContainer extends BaseContainer implements ICraftingGridListene
int y = headerAndSlots + 4;
for (int i = 0; i < 9 * 2; ++i) {
addSlot(new FilterSlot(((GridNetworkNode) grid).getProcessingMatrix(), i, x, y, FilterSlot.FILTER_ALLOW_SIZE).setEnableHandler(() -> ((GridNetworkNode) grid).isProcessingPattern() && ((GridNetworkNode) grid).getType() == IType.ITEMS));
addSlot(new FluidFilterSlot(((GridNetworkNode) grid).getProcessingMatrixFluids(), i, x, y, FilterSlot.FILTER_ALLOW_SIZE).setEnableHandler(() -> ((GridNetworkNode) grid).isProcessingPattern() && ((GridNetworkNode) grid).getType() == IType.FLUIDS));
int itemFilterSlotConfig = FilterSlot.FILTER_ALLOW_SIZE;
if (i < 9) {
itemFilterSlotConfig |= FilterSlot.FILTER_ALLOW_INPUT_CONFIGURATION;
}
int fluidFilterSlotConfig = FluidFilterSlot.FILTER_ALLOW_SIZE;
if (i < 9) {
fluidFilterSlotConfig |= FluidFilterSlot.FILTER_ALLOW_INPUT_CONFIGURATION;
}
addSlot(new FilterSlot(((GridNetworkNode) grid).getProcessingMatrix(), i, x, y, itemFilterSlotConfig).setEnableHandler(() -> ((GridNetworkNode) grid).isProcessingPattern() && ((GridNetworkNode) grid).getType() == IType.ITEMS));
addSlot(new FluidFilterSlot(((GridNetworkNode) grid).getProcessingMatrixFluids(), i, x, y, fluidFilterSlotConfig).setEnableHandler(() -> ((GridNetworkNode) grid).isProcessingPattern() && ((GridNetworkNode) grid).getType() == IType.FLUIDS));
x += 18;

View File

@@ -0,0 +1,9 @@
package com.raoulvdberge.refinedstorage.container;
import net.minecraft.entity.player.PlayerEntity;
public class InputConfigurationContainer extends BaseContainer {
public InputConfigurationContainer(PlayerEntity player) {
super(null, null, player, 0);
}
}

View File

@@ -10,8 +10,9 @@ import javax.annotation.Nonnull;
public class FilterSlot extends BaseSlot {
public static final int FILTER_ALLOW_SIZE = 1;
public static final int FILTER_ALLOW_BLOCKS = 2;
public static final int FILTER_ALLOW_INPUT_CONFIGURATION = 4;
private int flags = 0;
private int flags;
public FilterSlot(IItemHandler handler, int inventoryIndex, int x, int y, int flags) {
super(handler, inventoryIndex, x, y);
@@ -52,4 +53,8 @@ public class FilterSlot extends BaseSlot {
public boolean isBlockAllowed() {
return (flags & FILTER_ALLOW_BLOCKS) == FILTER_ALLOW_BLOCKS;
}
public boolean isInputConfigurationAllowed() {
return (flags & FILTER_ALLOW_INPUT_CONFIGURATION) == FILTER_ALLOW_INPUT_CONFIGURATION;
}
}

View File

@@ -10,6 +10,7 @@ import javax.annotation.Nonnull;
public class FluidFilterSlot extends BaseSlot {
public static final int FILTER_ALLOW_SIZE = 1;
public static final int FILTER_ALLOW_INPUT_CONFIGURATION = 2;
private int flags;
private FluidInventory fluidInventory;
@@ -38,6 +39,10 @@ public class FluidFilterSlot extends BaseSlot {
return (flags & FILTER_ALLOW_SIZE) == FILTER_ALLOW_SIZE;
}
public boolean isInputConfigurationAllowed() {
return (flags & FILTER_ALLOW_INPUT_CONFIGURATION) == FILTER_ALLOW_INPUT_CONFIGURATION;
}
public FluidInventory getFluidInventory() {
return fluidInventory;
}

View File

@@ -3,13 +3,13 @@ package com.raoulvdberge.refinedstorage.integration.jei;
import com.raoulvdberge.refinedstorage.RS;
import com.raoulvdberge.refinedstorage.api.network.grid.GridType;
import com.raoulvdberge.refinedstorage.api.network.grid.IGrid;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.GridNetworkNode;
import com.raoulvdberge.refinedstorage.container.GridContainer;
import com.raoulvdberge.refinedstorage.network.grid.GridProcessingTransferMessage;
import com.raoulvdberge.refinedstorage.network.grid.GridTransferMessage;
import mezz.jei.api.constants.VanillaRecipeCategoryUid;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.ingredient.IGuiIngredient;
import mezz.jei.api.recipe.category.IRecipeCategory;
import mezz.jei.api.recipe.transfer.IRecipeTransferError;
import mezz.jei.api.recipe.transfer.IRecipeTransferHandler;
import net.minecraft.entity.player.PlayerEntity;
@@ -26,18 +26,6 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler {
public static final long TRANSFER_SCROLLBAR_DELAY_MS = 200;
public static long LAST_TRANSFER_TIME;
private static final IRecipeTransferError ERROR_CANNOT_TRANSFER = new IRecipeTransferError() {
@Override
public Type getType() {
return Type.INTERNAL;
}
@Override
public void showError(int i, int i1, IRecipeLayout iRecipeLayout, int i2, int i3) {
}
};
@Override
public Class<? extends Container> getContainerClass() {
return GridContainer.class;
@@ -50,7 +38,7 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler {
if (doTransfer) {
LAST_TRANSFER_TIME = System.currentTimeMillis();
if (grid.getGridType() == GridType.PATTERN && ((GridNetworkNode) grid).isProcessingPattern()) {
if (grid.getGridType() == GridType.PATTERN && !isCraftingRecipe(recipeLayout.getRecipeCategory())) {
List<ItemStack> inputs = new LinkedList<>();
List<ItemStack> outputs = new LinkedList<>();
@@ -88,18 +76,12 @@ public class GridRecipeTransferHandler implements IRecipeTransferHandler {
container.inventorySlots.stream().filter(s -> s.inventory instanceof CraftingInventory).collect(Collectors.toList())
));
}
} else {
if (grid.getGridType() == GridType.PATTERN && ((GridNetworkNode) grid).isProcessingPattern()) {
if (recipeLayout.getRecipeCategory().getUid().equals(VanillaRecipeCategoryUid.CRAFTING)) {
return ERROR_CANNOT_TRANSFER;
}
} else {
if (!recipeLayout.getRecipeCategory().getUid().equals(VanillaRecipeCategoryUid.CRAFTING)) {
return ERROR_CANNOT_TRANSFER;
}
}
}
return null;
}
private boolean isCraftingRecipe(IRecipeCategory<?> recipeCategory) {
return recipeCategory.getUid().equals(VanillaRecipeCategoryUid.CRAFTING);
}
}

View File

@@ -6,6 +6,8 @@ import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternContainer;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternProvider;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.CraftingPattern;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.CraftingPatternFactory;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.AllowedTags;
import com.raoulvdberge.refinedstorage.render.tesr.PatternItemStackTileRenderer;
import com.raoulvdberge.refinedstorage.util.RenderUtils;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
@@ -17,6 +19,7 @@ import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.ActionResult;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Hand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.Style;
import net.minecraft.util.text.TextFormatting;
@@ -29,6 +32,7 @@ import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class PatternItem extends Item implements ICraftingPatternProvider {
@@ -41,6 +45,7 @@ public class PatternItem extends Item implements ICraftingPatternProvider {
private static final String NBT_FLUID_OUTPUT_SLOT = "FluidOutput_%d";
private static final String NBT_EXACT = "Exact";
private static final String NBT_PROCESSING = "Processing";
private static final String NBT_ALLOWED_TAGS = "AllowedTags";
private static final int VERSION = 1;
@@ -52,7 +57,7 @@ public class PatternItem extends Item implements ICraftingPatternProvider {
public static CraftingPattern fromCache(World world, ItemStack stack) {
if (!CACHE.containsKey(stack)) {
CACHE.put(stack, new CraftingPattern(world, null, stack));
CACHE.put(stack, CraftingPatternFactory.INSTANCE.create(world, null, stack));
}
return CACHE.get(stack);
@@ -66,10 +71,11 @@ public class PatternItem extends Item implements ICraftingPatternProvider {
return;
}
ICraftingPattern pattern = fromCache(world, stack);
CraftingPattern pattern = fromCache(world, stack);
Style yellow = new Style().setColor(TextFormatting.YELLOW);
Style blue = new Style().setColor(TextFormatting.BLUE);
Style aqua = new Style().setColor(TextFormatting.AQUA);
Style red = new Style().setColor(TextFormatting.RED);
if (pattern.isValid()) {
@@ -85,6 +91,32 @@ public class PatternItem extends Item implements ICraftingPatternProvider {
RenderUtils.addCombinedItemsToTooltip(tooltip, true, pattern.getOutputs());
RenderUtils.addCombinedFluidsToTooltip(tooltip, true, pattern.getFluidOutputs());
if (pattern.getAllowedTags() != null) {
for (int i = 0; i < pattern.getAllowedTags().getAllowedItemTags().size(); ++i) {
Set<ResourceLocation> allowedTags = pattern.getAllowedTags().getAllowedItemTags().get(i);
for (ResourceLocation tag : allowedTags) {
tooltip.add(new TranslationTextComponent(
"misc.refinedstorage.pattern.allowed_item_tag",
tag.toString(),
pattern.getInputs().get(i).get(0).getDisplayName()
).setStyle(aqua));
}
}
for (int i = 0; i < pattern.getAllowedTags().getAllowedFluidTags().size(); ++i) {
Set<ResourceLocation> allowedTags = pattern.getAllowedTags().getAllowedFluidTags().get(i);
for (ResourceLocation tag : allowedTags) {
tooltip.add(new TranslationTextComponent(
"misc.refinedstorage.pattern.allowed_fluid_tag",
tag.toString(),
pattern.getFluidInputs().get(i).get(0).getDisplayName()
).setStyle(aqua));
}
}
}
if (isExact(stack)) {
tooltip.add(new TranslationTextComponent("misc.refinedstorage.pattern.exact").setStyle(blue));
}
@@ -94,6 +126,7 @@ public class PatternItem extends Item implements ICraftingPatternProvider {
}
} else {
tooltip.add(new TranslationTextComponent("misc.refinedstorage.pattern.invalid").setStyle(red));
tooltip.add(pattern.getErrorMessage().setStyle(new Style().setColor(TextFormatting.GRAY)));
}
}
@@ -109,7 +142,7 @@ public class PatternItem extends Item implements ICraftingPatternProvider {
@Override
@Nonnull
public ICraftingPattern create(World world, ItemStack stack, ICraftingPatternContainer container) {
return new CraftingPattern(world, container, stack);
return CraftingPatternFactory.INSTANCE.create(world, container, stack);
}
public static void setInputSlot(ItemStack pattern, int slot, ItemStack stack) {
@@ -200,7 +233,7 @@ public class PatternItem extends Item implements ICraftingPatternProvider {
public static boolean isExact(ItemStack pattern) {
if (!pattern.hasTag() || !pattern.getTag().contains(NBT_EXACT)) {
return true;
return false;
}
return pattern.getTag().getBoolean(NBT_EXACT);
@@ -221,4 +254,25 @@ public class PatternItem extends Item implements ICraftingPatternProvider {
pattern.getTag().putInt(NBT_VERSION, VERSION);
}
public static void setAllowedTags(ItemStack pattern, AllowedTags allowedTags) {
if (!pattern.hasTag()) {
pattern.setTag(new CompoundNBT());
}
pattern.getTag().put(NBT_ALLOWED_TAGS, allowedTags.writeToNbt());
}
@Nullable
public static AllowedTags getAllowedTags(ItemStack pattern) {
if (!pattern.hasTag() || !pattern.getTag().contains(NBT_ALLOWED_TAGS)) {
return null;
}
AllowedTags allowedTags = new AllowedTags(null);
allowedTags.readFromNbt(pattern.getTag().getCompound(NBT_ALLOWED_TAGS));
return allowedTags;
}
}

View File

@@ -113,6 +113,9 @@ public class GridProcessingTransferMessage {
setFluidInputs(handlerFluid, message.fluidInputs);
setFluidOutputs(handlerFluid, message.fluidOutputs);
((GridNetworkNode) grid).setProcessingPattern(true);
((GridNetworkNode) grid).markDirty();
}
}
});

View File

@@ -7,6 +7,7 @@ import com.raoulvdberge.refinedstorage.container.slot.filter.FilterSlot;
import com.raoulvdberge.refinedstorage.container.slot.filter.FluidFilterSlot;
import com.raoulvdberge.refinedstorage.integration.craftingtweaks.CraftingTweaksIntegration;
import com.raoulvdberge.refinedstorage.render.FluidRenderer;
import com.raoulvdberge.refinedstorage.screen.grid.InputConfigurationScreen;
import com.raoulvdberge.refinedstorage.screen.widget.CheckBoxWidget;
import com.raoulvdberge.refinedstorage.screen.widget.sidebutton.SideButton;
import com.raoulvdberge.refinedstorage.util.RenderUtils;
@@ -23,8 +24,8 @@ import net.minecraft.inventory.container.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fml.client.config.GuiCheckBox;
import net.minecraftforge.fml.client.config.GuiUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -175,25 +176,45 @@ public abstract class BaseScreen<T extends Container> extends ContainerScreen<T>
if (valid && slot instanceof FilterSlot && slot.isEnabled() && ((FilterSlot) slot).isSizeAllowed()) {
if (!slot.getStack().isEmpty()) {
minecraft.displayGuiScreen(new AmountScreen(
this,
minecraft.player,
slot.slotNumber,
slot.getStack(),
slot.getSlotStackLimit()
));
if (((FilterSlot) slot).isInputConfigurationAllowed() && hasControlDown()) {
minecraft.displayGuiScreen(new InputConfigurationScreen(
this,
minecraft.player,
new TranslationTextComponent("gui.refinedstorage.input_configuration"),
slot.getStack(),
slot.getSlotIndex()
));
} else {
minecraft.displayGuiScreen(new AmountScreen(
this,
minecraft.player,
slot.slotNumber,
slot.getStack(),
slot.getSlotStackLimit()
));
}
}
} else if (valid && slot instanceof FluidFilterSlot && slot.isEnabled() && ((FluidFilterSlot) slot).isSizeAllowed()) {
FluidStack stack = ((FluidFilterSlot) slot).getFluidInventory().getFluid(slot.getSlotIndex());
if (!stack.isEmpty()) {
minecraft.displayGuiScreen(new FluidAmountScreen(
this,
minecraft.player,
slot.slotNumber,
stack,
((FluidFilterSlot) slot).getFluidInventory().getMaxAmount()
));
if (((FluidFilterSlot) slot).isInputConfigurationAllowed() && hasControlDown()) {
minecraft.displayGuiScreen(new InputConfigurationScreen(
this,
minecraft.player,
new TranslationTextComponent("gui.refinedstorage.input_configuration"),
stack,
slot.getSlotIndex()
));
} else {
minecraft.displayGuiScreen(new FluidAmountScreen(
this,
minecraft.player,
slot.slotNumber,
stack,
((FluidFilterSlot) slot).getFluidInventory().getMaxAmount()
));
}
} else {
super.handleMouseClick(slot, slotId, mouseButton, type);
}
@@ -202,7 +223,7 @@ public abstract class BaseScreen<T extends Container> extends ContainerScreen<T>
}
}
public GuiCheckBox addCheckBox(int x, int y, String text, boolean checked, Button.IPressable onPress) {
public CheckBoxWidget addCheckBox(int x, int y, String text, boolean checked, Button.IPressable onPress) {
CheckBoxWidget checkBox = new CheckBoxWidget(x, y, text, checked, onPress);
this.addButton(checkBox);

View File

@@ -134,8 +134,10 @@ public class GridScreen extends BaseScreen<GridContainer> implements IScreenInfo
TileDataManager.setParameter(GridTile.PROCESSING_PATTERN, processingPattern.isChecked());
});
exactPattern = addCheckBox(processingPattern.x + processingPattern.getWidth() + 5, y + getTopHeight() + (getVisibleRows() * 18) + 60, I18n.format("misc.refinedstorage.exact"), GridTile.EXACT_PATTERN.getValue(), btn -> TileDataManager.setParameter(GridTile.EXACT_PATTERN, exactPattern.isChecked()));
if (!processingPattern.isChecked()) {
exactPattern = addCheckBox(processingPattern.x + processingPattern.getWidth() + 5, y + getTopHeight() + (getVisibleRows() * 18) + 60, I18n.format("misc.refinedstorage.exact"), GridTile.EXACT_PATTERN.getValue(), btn -> TileDataManager.setParameter(GridTile.EXACT_PATTERN, exactPattern.isChecked()));
}
addSideButton(new TypeSideButton(this, GridTile.PROCESSING_TYPE));
}

View File

@@ -0,0 +1,385 @@
package com.raoulvdberge.refinedstorage.screen.grid;
import com.raoulvdberge.refinedstorage.RS;
import com.raoulvdberge.refinedstorage.container.InputConfigurationContainer;
import com.raoulvdberge.refinedstorage.render.FluidRenderer;
import com.raoulvdberge.refinedstorage.screen.BaseScreen;
import com.raoulvdberge.refinedstorage.screen.widget.CheckBoxWidget;
import com.raoulvdberge.refinedstorage.screen.widget.ScrollbarWidget;
import com.raoulvdberge.refinedstorage.tile.config.IType;
import com.raoulvdberge.refinedstorage.tile.data.TileDataManager;
import com.raoulvdberge.refinedstorage.tile.grid.GridTile;
import com.raoulvdberge.refinedstorage.util.RenderUtils;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tags.FluidTags;
import net.minecraft.tags.ItemTags;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.fluids.FluidAttributes;
import net.minecraftforge.fluids.FluidStack;
import org.lwjgl.glfw.GLFW;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class InputConfigurationScreen extends BaseScreen {
private final Screen parent;
private final ScrollbarWidget scrollbar;
private final List<Line> lines = new ArrayList<>();
private int type;
private int slot;
private ItemStack item;
private FluidStack fluid;
private InputConfigurationScreen(Screen parent, PlayerEntity player, ITextComponent title) {
super(new InputConfigurationContainer(player), 175, 143, null, title);
this.parent = parent;
this.scrollbar = new ScrollbarWidget(this, 155, 20, 12, 89);
}
public InputConfigurationScreen(Screen parent, PlayerEntity player, ITextComponent title, ItemStack item, int slot) {
this(parent, player, title);
this.type = IType.ITEMS;
this.slot = slot;
this.item = item;
this.fluid = null;
}
public InputConfigurationScreen(Screen parent, PlayerEntity player, ITextComponent title, FluidStack fluid, int slot) {
this(parent, player, title);
this.type = IType.FLUIDS;
this.slot = slot;
this.item = null;
this.fluid = fluid;
}
@Override
public void onPostInit(int x, int y) {
Button apply = addButton(x + 7, y + 114, 50, 20, I18n.format("gui.refinedstorage.input_configuration.apply"), true, true, btn -> apply());
addButton(x + apply.getWidth() + 7 + 4, y + 114, 50, 20, I18n.format("gui.cancel"), true, true, btn -> close());
lines.clear();
if (item != null) {
lines.add(new ItemLine(item));
for (ResourceLocation owningTag : ItemTags.getCollection().getOwningTags(item.getItem())) {
lines.add(new TagLine(owningTag, GridTile.ALLOWED_ITEM_TAGS.getValue().get(slot).contains(owningTag)));
int itemCount = 0;
ItemListLine line = new ItemListLine();
for (Item item : ItemTags.getCollection().get(owningTag).getAllElements()) {
if (itemCount > 0 && itemCount % 7 == 0) {
lines.add(line);
line = new ItemListLine();
}
itemCount++;
line.addItem(new ItemStack(item));
}
lines.add(line);
}
} else if (fluid != null) {
lines.add(new FluidLine(fluid));
for (ResourceLocation owningTag : FluidTags.getCollection().getOwningTags(fluid.getFluid())) {
lines.add(new TagLine(owningTag, GridTile.ALLOWED_FLUID_TAGS.getValue().get(slot).contains(owningTag)));
int fluidCount = 0;
FluidListLine line = new FluidListLine();
for (Fluid fluid : FluidTags.getCollection().get(owningTag).getAllElements()) {
if (fluidCount > 0 && fluidCount % 7 == 0) {
lines.add(line);
line = new FluidListLine();
}
fluidCount++;
line.addFluid(new FluidStack(fluid, FluidAttributes.BUCKET_VOLUME));
}
lines.add(line);
}
}
// Do an initial layout
int xx = 8;
int yy = 20;
for (int i = 0; i < lines.size(); ++i) {
boolean visible = i >= scrollbar.getOffset() && i < scrollbar.getOffset() + getVisibleRows();
if (visible) {
lines.get(i).layoutDependantControls(true, guiLeft + xx + 3, guiTop + yy + 3);
yy += 18;
}
}
}
@Override
public void tick(int x, int y) {
scrollbar.setEnabled(getRows() > getVisibleRows());
scrollbar.setMaxOffset(getRows() - getVisibleRows());
}
private int getRows() {
return lines.size();
}
private int getVisibleRows() {
return 5;
}
@Override
public void renderBackground(int x, int y, int mouseX, int mouseY) {
bindTexture(RS.ID, "gui/input_configuration.png");
blit(x, y, 0, 0, xSize, ySize);
scrollbar.render();
}
@Override
public void renderForeground(int mouseX, int mouseY) {
renderString(7, 7, title.getFormattedText());
int x = 8;
int y = 20;
RenderHelper.enableGUIStandardItemLighting();
for (int i = 0; i < lines.size(); ++i) {
boolean visible = i >= scrollbar.getOffset() && i < scrollbar.getOffset() + getVisibleRows();
if (visible) {
lines.get(i).layoutDependantControls(true, guiLeft + x + 3, guiTop + y + 3);
lines.get(i).render(x, y);
y += 18;
} else {
lines.get(i).layoutDependantControls(false, -100, -100);
}
}
x = 8;
y = 20;
for (int i = 0; i < lines.size(); ++i) {
boolean visible = i >= scrollbar.getOffset() && i < scrollbar.getOffset() + getVisibleRows();
if (visible) {
lines.get(i).renderTooltip(x, y, mouseX, mouseY);
y += 18;
}
}
}
@Override
public void mouseMoved(double mx, double my) {
scrollbar.mouseMoved(mx, my);
super.mouseMoved(mx, my);
}
@Override
public boolean mouseClicked(double mx, double my, int button) {
return scrollbar.mouseClicked(mx, my, button) || super.mouseClicked(mx, my, button);
}
@Override
public boolean mouseReleased(double mx, double my, int button) {
return scrollbar.mouseReleased(mx, my, button) || super.mouseReleased(mx, my, button);
}
@Override
public boolean mouseScrolled(double x, double y, double delta) {
return this.scrollbar.mouseScrolled(x, y, delta) || super.mouseScrolled(x, y, delta);
}
@Override
public boolean keyPressed(int key, int scanCode, int modifiers) {
if (key == GLFW.GLFW_KEY_ESCAPE) {
close();
return true;
}
return super.keyPressed(key, scanCode, modifiers);
}
private void close() {
minecraft.displayGuiScreen(parent);
}
private void apply() {
Set<ResourceLocation> allowed = new HashSet<>();
for (Line line : lines) {
if (line instanceof TagLine) {
TagLine tagLine = (TagLine) line;
if (tagLine.widget.isChecked()) {
allowed.add(tagLine.tagName);
}
}
}
if (type == IType.ITEMS) {
List<Set<ResourceLocation>> existing = GridTile.ALLOWED_ITEM_TAGS.getValue();
existing.set(slot, allowed);
TileDataManager.setParameter(GridTile.ALLOWED_ITEM_TAGS, existing);
} else if (type == IType.FLUIDS) {
List<Set<ResourceLocation>> existing = GridTile.ALLOWED_FLUID_TAGS.getValue();
existing.set(slot, allowed);
TileDataManager.setParameter(GridTile.ALLOWED_FLUID_TAGS, existing);
}
close();
}
private interface Line {
default void render(int x, int y) {
}
default void renderTooltip(int x, int y, int mx, int my) {
}
default void layoutDependantControls(boolean visible, int x, int y) {
}
}
private class ItemLine implements Line {
private final ItemStack item;
public ItemLine(ItemStack item) {
this.item = item;
}
@Override
public void render(int x, int y) {
renderItem(x + 3, y + 2, item);
renderString(x + 4 + 19, y + 7, item.getDisplayName().getFormattedText());
}
}
private class FluidLine implements Line {
private final FluidStack fluid;
public FluidLine(FluidStack item) {
this.fluid = item;
}
@Override
public void render(int x, int y) {
FluidRenderer.INSTANCE.render(x + 3, y + 2, fluid);
renderString(x + 4 + 19, y + 7, fluid.getDisplayName().getFormattedText());
}
}
private class TagLine implements Line {
private final ResourceLocation tagName;
private final CheckBoxWidget widget;
public TagLine(ResourceLocation tagName, boolean checked) {
this.tagName = tagName;
this.widget = addCheckBox(-100, -100, RenderUtils.shorten(tagName.toString(), 22), checked, (btn) -> {
});
widget.setFGColor(0xFF373737);
widget.setShadow(false);
}
@Override
public void layoutDependantControls(boolean visible, int x, int y) {
widget.visible = visible;
widget.x = x;
widget.y = y;
}
}
private class ItemListLine implements Line {
private final List<ItemStack> items = new ArrayList<>();
public ItemListLine addItem(ItemStack stack) {
items.add(stack);
return this;
}
@Override
public void render(int x, int y) {
for (ItemStack item : items) {
renderItem(x + 3, y, item);
x += 18;
}
}
@Override
public void renderTooltip(int x, int y, int mx, int my) {
for (ItemStack item : items) {
if (RenderUtils.inBounds(x + 3, y, 16, 16, mx, my)) {
InputConfigurationScreen.this.renderTooltip(item, mx, my, RenderUtils.getTooltipFromItem(item));
}
x += 18;
}
}
}
private class FluidListLine implements Line {
private final List<FluidStack> fluids = new ArrayList<>();
public FluidListLine addFluid(FluidStack stack) {
fluids.add(stack);
return this;
}
@Override
public void render(int x, int y) {
for (FluidStack fluid : fluids) {
FluidRenderer.INSTANCE.render(x + 3, y, fluid);
x += 18;
}
}
@Override
public void renderTooltip(int x, int y, int mx, int my) {
for (FluidStack fluid : fluids) {
if (RenderUtils.inBounds(x + 3, y, 16, 16, mx, my)) {
InputConfigurationScreen.this.renderTooltip(mx, my, fluid.getDisplayName().getFormattedText());
}
x += 18;
}
}
}
}

View File

@@ -10,6 +10,7 @@ public class CheckBoxWidget extends GuiCheckBox {
private IPressable onPress;
private String displayString;
private boolean shadow = true;
public CheckBoxWidget(int xPos, int yPos, String displayString, boolean isChecked, IPressable onPress) {
super(xPos, yPos, displayString, isChecked);
@@ -19,6 +20,10 @@ public class CheckBoxWidget extends GuiCheckBox {
this.width = Minecraft.getInstance().fontRenderer.getStringWidth(displayString) + BOX_WIDTH + 3;
}
public void setShadow(boolean shadow) {
this.shadow = shadow;
}
@Override
public void renderButton(int mouseX, int mouseY, float partial) {
if (visible) {
@@ -26,17 +31,21 @@ public class CheckBoxWidget extends GuiCheckBox {
int color = 14737632;
if (packedFGColor != 0) {
color = packedFGColor;
} else if (!active) {
if (!active) {
color = 10526880;
} else if (packedFGColor != 0) {
color = packedFGColor;
}
if (isChecked()) {
drawCenteredString(Minecraft.getInstance().fontRenderer, "x", x + BOX_WIDTH / 2 + 1, y + 1, 14737632);
}
drawString(Minecraft.getInstance().fontRenderer, displayString, x + BOX_WIDTH + 2, y + 2, color);
if (!shadow) {
Minecraft.getInstance().fontRenderer.drawString(displayString, x + BOX_WIDTH + 2, y + 2, color);
} else {
Minecraft.getInstance().fontRenderer.drawStringWithShadow(displayString, x + BOX_WIDTH + 2, y + 2, color);
}
}
}

View File

@@ -9,9 +9,7 @@ import net.minecraft.network.datasync.IDataSerializer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fluids.FluidStack;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.*;
public final class RSSerializers {
public static final IDataSerializer<List<ClientNode>> CLIENT_NODE_SERIALIZER = new IDataSerializer<List<ClientNode>>() {
@@ -143,4 +141,47 @@ public final class RSSerializers {
return value;
}
};
public static final IDataSerializer<List<Set<ResourceLocation>>> LIST_OF_SET_SERIALIZER = new IDataSerializer<List<Set<ResourceLocation>>>() {
@Override
public void write(PacketBuffer buf, List<Set<ResourceLocation>> value) {
buf.writeInt(value.size());
for (Set<ResourceLocation> values : value) {
buf.writeInt(values.size());
values.forEach(buf::writeResourceLocation);
}
}
@Override
public List<Set<ResourceLocation>> read(PacketBuffer buf) {
List<Set<ResourceLocation>> value = new ArrayList<>();
int size = buf.readInt();
for (int i = 0; i < size; ++i) {
int setSize = buf.readInt();
Set<ResourceLocation> values = new HashSet<>();
for (int j = 0; j < setSize; ++j) {
values.add(buf.readResourceLocation());
}
value.add(values);
}
return value;
}
@Override
public DataParameter<List<Set<ResourceLocation>>> createKey(int id) {
return null;
}
@Override
public List<Set<ResourceLocation>> copyValue(List<Set<ResourceLocation>> value) {
return value;
}
};
}

View File

@@ -7,10 +7,12 @@ import com.raoulvdberge.refinedstorage.screen.BaseScreen;
import com.raoulvdberge.refinedstorage.screen.grid.GridScreen;
import com.raoulvdberge.refinedstorage.tile.NetworkNodeTile;
import com.raoulvdberge.refinedstorage.tile.config.IType;
import com.raoulvdberge.refinedstorage.tile.data.RSSerializers;
import com.raoulvdberge.refinedstorage.tile.data.TileDataParameter;
import com.raoulvdberge.refinedstorage.util.GridUtils;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
@@ -20,6 +22,9 @@ import net.minecraftforge.items.IItemHandler;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class GridTile extends NetworkNodeTile<GridNetworkNode> {
public static final TileDataParameter<Integer, GridTile> VIEW_TYPE = new TileDataParameter<>(DataSerializers.VARINT, 0, t -> t.getNode().getViewType(), (t, v) -> {
@@ -73,6 +78,14 @@ public class GridTile extends NetworkNodeTile<GridNetworkNode> {
}, (initial, p) -> BaseScreen.executeLater(GridScreen.class, BaseScreen::init));
public static final TileDataParameter<Integer, GridTile> PROCESSING_TYPE = IType.createParameter((initial, p) -> BaseScreen.executeLater(GridScreen.class, BaseScreen::init));
public static final TileDataParameter<List<Set<ResourceLocation>>, GridTile> ALLOWED_ITEM_TAGS = new TileDataParameter<>(RSSerializers.LIST_OF_SET_SERIALIZER, new ArrayList<>(), t -> t.getNode().getAllowedTags().getAllowedItemTags(), (t, v) -> {
t.getNode().getAllowedTags().setAllowedItemTags(v);
});
public static final TileDataParameter<List<Set<ResourceLocation>>, GridTile> ALLOWED_FLUID_TAGS = new TileDataParameter<>(RSSerializers.LIST_OF_SET_SERIALIZER, new ArrayList<>(), t -> t.getNode().getAllowedTags().getAllowedFluidTags(), (t, v) -> {
t.getNode().getAllowedTags().setAllowedFluidTags(v);
});
public static void trySortGrid(boolean initial) {
if (!initial) {
BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort());
@@ -98,6 +111,8 @@ public class GridTile extends NetworkNodeTile<GridNetworkNode> {
dataManager.addWatchedParameter(EXACT_PATTERN);
dataManager.addWatchedParameter(PROCESSING_PATTERN);
dataManager.addWatchedParameter(PROCESSING_TYPE);
dataManager.addParameter(ALLOWED_ITEM_TAGS);
dataManager.addParameter(ALLOWED_FLUID_TAGS);
}
@Override

View File

@@ -84,6 +84,8 @@
"gui.refinedstorage.security_manager.permission.5.tooltip": "Ability to change security options",
"gui.refinedstorage.storage_monitor": "Storage Monitor",
"gui.refinedstorage.crafter_manager": "Crafter Manager",
"gui.refinedstorage.input_configuration": "Input configuration",
"gui.refinedstorage.input_configuration.apply": "Apply",
"misc.refinedstorage.energy_stored": "%d / %d FE",
"misc.refinedstorage.energy_usage": "Usage: %d FE/t",
"misc.refinedstorage.energy_usage_minimal": "%d FE/t",
@@ -103,6 +105,13 @@
"misc.refinedstorage.pattern.outputs": "Outputs",
"misc.refinedstorage.pattern.invalid": "Invalid pattern",
"misc.refinedstorage.pattern.exact": "Uses exact mode",
"misc.refinedstorage.pattern.allowed_item_tag": "Uses items from %s for %s",
"misc.refinedstorage.pattern.allowed_fluid_tag": "Uses fluids from %s for %s",
"misc.refinedstorage.pattern.error.processing_no_outputs": "Processing pattern has no outputs",
"misc.refinedstorage.pattern.error.no_output": "Recipe has no output",
"misc.refinedstorage.pattern.error.recipe_does_not_exist": "Recipe doesn't exist",
"misc.refinedstorage.pattern.error.tag_no_longer_applicable": "Tag %s is no longer applicable for %s",
"misc.refinedstorage.pattern.error.recipe_no_ingredients": "Recipe has no ingredients",
"misc.refinedstorage.security.no_permission": "You have no permission to perform that action.",
"misc.refinedstorage.start": "Start",
"misc.refinedstorage.clear": "Clear",

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB