The Filter Brothers
- Torque generators no longer show stress impact levels - Added Filters for matching outputs against a group of items / nested filters - Added Attribute Filters for matching outputs against a collection of item properties - Extraction count on Extractors and Transposers can now be adjusted through scrolling on the value box
|
@ -3,6 +3,10 @@ package com.simibubi.create;
|
|||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.modules.logistics.block.inventories.FlexcrateContainer;
|
||||
import com.simibubi.create.modules.logistics.block.inventories.FlexcrateScreen;
|
||||
import com.simibubi.create.modules.logistics.item.filter.AttributeFilterContainer;
|
||||
import com.simibubi.create.modules.logistics.item.filter.AttributeFilterScreen;
|
||||
import com.simibubi.create.modules.logistics.item.filter.FilterContainer;
|
||||
import com.simibubi.create.modules.logistics.item.filter.FilterScreen;
|
||||
import com.simibubi.create.modules.logistics.management.controller.LogisticalInventoryControllerContainer;
|
||||
import com.simibubi.create.modules.logistics.management.controller.LogisticalInventoryControllerScreen;
|
||||
import com.simibubi.create.modules.logistics.management.index.LogisticalIndexContainer;
|
||||
|
@ -33,6 +37,9 @@ public enum AllContainers {
|
|||
LOGISTICAL_INDEX(LogisticalIndexContainer::new),
|
||||
LOGISTICAL_CONTROLLER(LogisticalInventoryControllerContainer::new),
|
||||
|
||||
FILTER(FilterContainer::new),
|
||||
ATTRIBUTE_FILTER(AttributeFilterContainer::new),
|
||||
|
||||
;
|
||||
|
||||
public ContainerType<? extends Container> type;
|
||||
|
@ -57,6 +64,8 @@ public enum AllContainers {
|
|||
bind(FLEXCRATE, FlexcrateScreen::new);
|
||||
bind(LOGISTICAL_INDEX, LogisticalIndexScreen::new);
|
||||
bind(LOGISTICAL_CONTROLLER, LogisticalInventoryControllerScreen::new);
|
||||
bind(FILTER, FilterScreen::new);
|
||||
bind(ATTRIBUTE_FILTER, AttributeFilterScreen::new);
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
|
|
|
@ -17,7 +17,7 @@ import com.simibubi.create.modules.curiosities.symmetry.SymmetryWandItem;
|
|||
import com.simibubi.create.modules.curiosities.symmetry.client.SymmetryWandItemRenderer;
|
||||
import com.simibubi.create.modules.gardens.TreeFertilizerItem;
|
||||
import com.simibubi.create.modules.logistics.item.CardboardBoxItem;
|
||||
import com.simibubi.create.modules.logistics.item.FilterItem;
|
||||
import com.simibubi.create.modules.logistics.item.filter.FilterItem;
|
||||
import com.simibubi.create.modules.logistics.management.LogisticalDialItem;
|
||||
import com.simibubi.create.modules.logistics.management.base.LogisticalControllerBlock.Type;
|
||||
import com.simibubi.create.modules.logistics.management.base.LogisticalControllerItem;
|
||||
|
@ -108,6 +108,8 @@ public enum AllItems {
|
|||
CARDBOARD_BOX_1410(new CardboardBoxItem(standardItemProperties())),
|
||||
|
||||
FILTER(new FilterItem(standardItemProperties()), true),
|
||||
PROPERTY_FILTER(new FilterItem(standardItemProperties()), true),
|
||||
LOGISTICAL_FILTER(new FilterItem(standardItemProperties())),
|
||||
LOGISTICAL_DIAL(new LogisticalDialItem(standardItemProperties())),
|
||||
LOGISTICAL_CONTROLLER_SUPPLY(new LogisticalControllerItem(standardItemProperties(), Type.SUPPLY)),
|
||||
LOGISTICAL_CONTROLLER_REQUEST(new LogisticalControllerItem(standardItemProperties(), Type.REQUEST)),
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.util.function.BiConsumer;
|
|||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.foundation.behaviour.filtering.FilteringCountUpdatePacket;
|
||||
import com.simibubi.create.foundation.packet.NbtPacket;
|
||||
import com.simibubi.create.foundation.packet.SimplePacketBase;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ConfigureChassisPacket;
|
||||
|
@ -12,6 +13,7 @@ import com.simibubi.create.modules.contraptions.components.motor.ConfigureMotorP
|
|||
import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunBeamPacket;
|
||||
import com.simibubi.create.modules.curiosities.symmetry.SymmetryEffectPacket;
|
||||
import com.simibubi.create.modules.logistics.block.diodes.ConfigureFlexpeaterPacket;
|
||||
import com.simibubi.create.modules.logistics.item.filter.FilterScreenPacket;
|
||||
import com.simibubi.create.modules.logistics.management.controller.LogisticalControllerConfigurationPacket;
|
||||
import com.simibubi.create.modules.logistics.management.index.IndexContainerUpdatePacket;
|
||||
import com.simibubi.create.modules.logistics.management.index.IndexOrderRequest;
|
||||
|
@ -43,6 +45,8 @@ public enum AllPackets {
|
|||
PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new),
|
||||
UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new),
|
||||
INDEX_ORDER_REQUEST(IndexOrderRequest.class, IndexOrderRequest::new),
|
||||
CONFIGURE_FILTER(FilterScreenPacket.class, FilterScreenPacket::new),
|
||||
CONFIGURE_FILTERING_AMOUNT(FilteringCountUpdatePacket.class, FilteringCountUpdatePacket::new),
|
||||
|
||||
// Server to Client
|
||||
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new),
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.simibubi.create;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.foundation.behaviour.filtering.FilteringHandler;
|
||||
import com.simibubi.create.foundation.block.IHaveScrollableValue;
|
||||
import com.simibubi.create.foundation.gui.ScreenOpener;
|
||||
import com.simibubi.create.foundation.item.TooltipHelper;
|
||||
|
@ -100,7 +101,8 @@ public class ClientEvents {
|
|||
|
||||
boolean cancelled = CreateClient.schematicHandler.mouseScrolled(delta)
|
||||
|| CreateClient.schematicAndQuillHandler.mouseScrolled(delta)
|
||||
|| IHaveScrollableValue.onScroll(delta);
|
||||
|| IHaveScrollableValue.onScroll(delta)
|
||||
|| FilteringHandler.onScroll(delta);
|
||||
event.setCanceled(cancelled);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,9 @@ public enum ScreenResources {
|
|||
STOCKSWITCH_BOUND_LEFT("flex_crate_and_stockpile_switch.png", 234, 129, 7, 21),
|
||||
STOCKSWITCH_BOUND_RIGHT("flex_crate_and_stockpile_switch.png", 241, 129, 7, 21),
|
||||
|
||||
FILTER("filter.png", 200, 100),
|
||||
ATTRIBUTE_FILTER("filter.png", 0, 100, 200, 86),
|
||||
|
||||
// Logistical Index
|
||||
INDEX_TOP("index.png", 41, 0, 174, 22),
|
||||
INDEX_TOP_TRIM("index.png", 41, 22, 174, 6),
|
||||
|
@ -130,6 +133,15 @@ public enum ScreenResources {
|
|||
I_PRIORITY_VERY_HIGH(112, 0),
|
||||
I_ACTIVE(64, 16),
|
||||
I_PASSIVE(80, 16),
|
||||
|
||||
I_BLACKLIST(128, 0),
|
||||
I_WHITELIST(144, 0),
|
||||
I_WHITELIST_OR(160, 0),
|
||||
I_WHITELIST_AND(176, 0),
|
||||
I_WHITELIST_NOT(192, 0),
|
||||
|
||||
I_RESPECT_NBT(208, 0),
|
||||
I_IGNORE_NBT(224, 0),
|
||||
|
||||
;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.simibubi.create.foundation.behaviour;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
|
@ -28,10 +29,12 @@ public class ValueBox {
|
|||
}
|
||||
|
||||
public static class ItemValueBox extends ValueBox {
|
||||
ItemStack stack;
|
||||
int count;
|
||||
|
||||
public ItemValueBox(String label, AxisAlignedBB bb, int count) {
|
||||
public ItemValueBox(String label, AxisAlignedBB bb, ItemStack stack, int count) {
|
||||
super(label, bb);
|
||||
this.stack = stack;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package com.simibubi.create.foundation.behaviour;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.foundation.behaviour.ValueBox.ItemValueBox;
|
||||
import com.simibubi.create.foundation.utility.ColorHelper;
|
||||
import com.simibubi.create.foundation.utility.TessellatorHelper;
|
||||
import com.simibubi.create.modules.contraptions.relays.elementary.CogWheelBlock;
|
||||
import com.simibubi.create.modules.logistics.item.filter.FilterItem;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Blocks;
|
||||
|
@ -67,12 +67,20 @@ public class ValueBoxRenderer {
|
|||
}
|
||||
|
||||
if (box instanceof ItemValueBox) {
|
||||
String count = ((ItemValueBox) box).count + "";
|
||||
GlStateManager.translated(-7 - font.getStringWidth(count), 10, 10 + 1 / 4f);
|
||||
GlStateManager.scaled(1.5, 1.5, 1.5);
|
||||
font.drawString(count, 0, 0, 0xEDEDED);
|
||||
GlStateManager.translated(0, 0, -1 / 4f);
|
||||
font.drawString(count, 1, 1, 0x4F4F4F);
|
||||
ItemValueBox itemValueBox = (ItemValueBox) box;
|
||||
String count = itemValueBox.count == 0 ? "*" : itemValueBox.count + "";
|
||||
|
||||
boolean isFilter = itemValueBox.stack.getItem() instanceof FilterItem;
|
||||
if (isFilter)
|
||||
GlStateManager.translated(3, 8, 7.25f);
|
||||
else
|
||||
GlStateManager.translated(-7 - font.getStringWidth(count), 10, 10 + 1 / 4f);
|
||||
|
||||
double scale = 1.5;
|
||||
GlStateManager.scaled(scale, scale, scale);
|
||||
font.drawString(count, 0, 0, isFilter ? 0xFFFFFF : 0xEDEDED);
|
||||
GlStateManager.translated(0, 0, -1 / 16f);
|
||||
font.drawString(count, 1 - 1 / 8f, 1 - 1 / 8f, 0x4F4F4F);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,7 +97,7 @@ public class ValueBoxRenderer {
|
|||
|
||||
private static float customZOffset(Item item) {
|
||||
float NUDGE = -.1f;
|
||||
if (AllItems.FILTER.get() == item)
|
||||
if (item instanceof FilterItem)
|
||||
return NUDGE;
|
||||
if (item instanceof BlockItem) {
|
||||
Block block = ((BlockItem) item).getBlock();
|
||||
|
|
|
@ -69,6 +69,12 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka
|
|||
behaviours.values().forEach(tb -> tb.writeNBT(compound));
|
||||
return super.write(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT writeToClient(CompoundNBT compound) {
|
||||
behaviours.values().forEach(tb -> tb.writeToClient(compound));
|
||||
return super.writeToClient(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
|
|
|
@ -98,4 +98,8 @@ public abstract class TileEntityBehaviour {
|
|||
return ste.getBehaviour(type);
|
||||
}
|
||||
|
||||
public CompoundNBT writeToClient(CompoundNBT compound) {
|
||||
return compound;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,9 +3,11 @@ package com.simibubi.create.foundation.behaviour.filtering;
|
|||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.simibubi.create.AllPackets;
|
||||
import com.simibubi.create.foundation.behaviour.base.IBehaviourType;
|
||||
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
|
||||
import com.simibubi.create.modules.logistics.item.filter.FilterItem;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
@ -22,8 +24,13 @@ public class FilteringBehaviour extends TileEntityBehaviour {
|
|||
Vec3d textShift;
|
||||
|
||||
private ItemStack filter;
|
||||
public int count;
|
||||
private Consumer<ItemStack> callback;
|
||||
|
||||
int scrollableValue;
|
||||
int ticksUntilScrollPacket;
|
||||
boolean forceClientState;
|
||||
|
||||
public FilteringBehaviour(SmartTileEntity te) {
|
||||
super(te);
|
||||
filter = ItemStack.EMPTY;
|
||||
|
@ -32,20 +39,54 @@ public class FilteringBehaviour extends TileEntityBehaviour {
|
|||
callback = stack -> {
|
||||
};
|
||||
textShift = Vec3d.ZERO;
|
||||
count = -1;
|
||||
ticksUntilScrollPacket = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeNBT(CompoundNBT nbt) {
|
||||
nbt.put("Filter", getFilter().serializeNBT());
|
||||
nbt.putInt("FilterAmount", count);
|
||||
super.writeNBT(nbt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readNBT(CompoundNBT nbt) {
|
||||
filter = ItemStack.read(nbt.getCompound("Filter"));
|
||||
count = nbt.getInt("FilterAmount");
|
||||
if (nbt.contains("ForceScrollable")) {
|
||||
scrollableValue = count;
|
||||
ticksUntilScrollPacket = -1;
|
||||
}
|
||||
super.readNBT(nbt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT writeToClient(CompoundNBT compound) {
|
||||
if (forceClientState) {
|
||||
compound.putBoolean("ForceScrollable", true);
|
||||
forceClientState = false;
|
||||
}
|
||||
return super.writeToClient(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
if (!getWorld().isRemote)
|
||||
return;
|
||||
if (ticksUntilScrollPacket == -1)
|
||||
return;
|
||||
if (ticksUntilScrollPacket > 0) {
|
||||
ticksUntilScrollPacket--;
|
||||
return;
|
||||
}
|
||||
|
||||
AllPackets.channel.sendToServer(new FilteringCountUpdatePacket(getPos(), scrollableValue));
|
||||
ticksUntilScrollPacket = -1;
|
||||
}
|
||||
|
||||
public FilteringBehaviour withCallback(Consumer<ItemStack> filterCallback) {
|
||||
callback = filterCallback;
|
||||
return this;
|
||||
|
@ -65,10 +106,23 @@ public class FilteringBehaviour extends TileEntityBehaviour {
|
|||
textShift = shift;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
scrollableValue = count;
|
||||
}
|
||||
|
||||
public void setFilter(ItemStack stack) {
|
||||
filter = stack.copy();
|
||||
callback.accept(filter);
|
||||
|
||||
if (filter.getItem() instanceof FilterItem)
|
||||
count = 0;
|
||||
else
|
||||
count = stack.getCount();
|
||||
forceClientState = true;
|
||||
|
||||
tileEntity.markDirty();
|
||||
tileEntity.sendData();
|
||||
}
|
||||
|
@ -82,7 +136,7 @@ public class FilteringBehaviour extends TileEntityBehaviour {
|
|||
}
|
||||
|
||||
public boolean test(ItemStack stack) {
|
||||
return filter.isEmpty() || ItemStack.areItemsEqual(filter, stack);
|
||||
return filter.isEmpty() || FilterItem.test(stack, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -98,6 +152,14 @@ public class FilteringBehaviour extends TileEntityBehaviour {
|
|||
Vec3d localHit = hit.subtract(new Vec3d(tileEntity.getPos()));
|
||||
return localHit.distanceTo(offset) < slotPositioning.scale / 2;
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public boolean anyAmount() {
|
||||
return count == 0;
|
||||
}
|
||||
|
||||
public static class SlotPositioning {
|
||||
Function<BlockState, Vec3d> offset;
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package com.simibubi.create.foundation.behaviour.filtering;
|
||||
|
||||
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.packet.TileEntityConfigurationPacket;
|
||||
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class FilteringCountUpdatePacket extends TileEntityConfigurationPacket<SmartTileEntity> {
|
||||
|
||||
int amount;
|
||||
|
||||
public FilteringCountUpdatePacket(PacketBuffer buffer) {
|
||||
super(buffer);
|
||||
}
|
||||
|
||||
public FilteringCountUpdatePacket(BlockPos pos, int amount) {
|
||||
super(pos);
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeSettings(PacketBuffer buffer) {
|
||||
buffer.writeInt(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readSettings(PacketBuffer buffer) {
|
||||
amount = buffer.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applySettings(SmartTileEntity te) {
|
||||
FilteringBehaviour behaviour = TileEntityBehaviour.get(te, FilteringBehaviour.TYPE);
|
||||
if (behaviour == null)
|
||||
return;
|
||||
behaviour.forceClientState = true;
|
||||
behaviour.count = amount;
|
||||
te.markDirty();
|
||||
te.sendData();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,16 +1,25 @@
|
|||
package com.simibubi.create.foundation.behaviour.filtering;
|
||||
|
||||
import com.simibubi.create.AllKeys;
|
||||
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.utility.RaycastHelper;
|
||||
import com.simibubi.create.modules.logistics.item.filter.FilterItem;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.SoundEvents;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
|
@ -38,12 +47,54 @@ public class FilteringHandler {
|
|||
return;
|
||||
|
||||
if (behaviour.testHit(ray.getHitVec())) {
|
||||
if (event.getSide() != LogicalSide.CLIENT)
|
||||
behaviour.setFilter(player.getHeldItem(hand));
|
||||
if (event.getSide() != LogicalSide.CLIENT) {
|
||||
ItemStack heldItem = player.getHeldItem(hand).copy();
|
||||
if (!player.isCreative()) {
|
||||
if (behaviour.getFilter().getItem() instanceof FilterItem)
|
||||
player.inventory.placeItemBackInInventory(world, behaviour.getFilter());
|
||||
if (heldItem.getItem() instanceof FilterItem)
|
||||
player.getHeldItem(hand).shrink(1);
|
||||
}
|
||||
if (heldItem.getItem() instanceof FilterItem)
|
||||
heldItem.setCount(1);
|
||||
behaviour.setFilter(heldItem);
|
||||
}
|
||||
event.setCanceled(true);
|
||||
event.setCancellationResult(ActionResultType.SUCCESS);
|
||||
world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_ADD_ITEM, SoundCategory.BLOCKS, .25f, .1f);
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static boolean onScroll(double delta) {
|
||||
RayTraceResult objectMouseOver = Minecraft.getInstance().objectMouseOver;
|
||||
if (!(objectMouseOver instanceof BlockRayTraceResult))
|
||||
return false;
|
||||
|
||||
BlockRayTraceResult result = (BlockRayTraceResult) objectMouseOver;
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
ClientWorld world = mc.world;
|
||||
BlockPos blockPos = result.getPos();
|
||||
|
||||
FilteringBehaviour filtering = TileEntityBehaviour.get(world, blockPos, FilteringBehaviour.TYPE);
|
||||
if (filtering == null)
|
||||
return false;
|
||||
if (mc.player.isSneaking())
|
||||
return false;
|
||||
if (!mc.player.isAllowEdit())
|
||||
return false;
|
||||
if (!filtering.isCountVisible())
|
||||
return false;
|
||||
if (!filtering.testHit(objectMouseOver.getHitVec()))
|
||||
return false;
|
||||
if (filtering.getFilter().isEmpty())
|
||||
return false;
|
||||
|
||||
filtering.ticksUntilScrollPacket = 10;
|
||||
filtering.scrollableValue = (int) MathHelper
|
||||
.clamp(filtering.scrollableValue + delta * (AllKeys.ctrlDown() ? 16 : 1), 0, 64);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,10 +10,12 @@ import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour.Slo
|
|||
import com.simibubi.create.foundation.utility.GlHelper;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.TessellatorHelper;
|
||||
import com.simibubi.create.modules.logistics.item.filter.FilterItem;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
|
@ -41,6 +43,8 @@ public class FilteringRenderer {
|
|||
FilteringBehaviour behaviour = TileEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE);
|
||||
if (behaviour == null)
|
||||
return;
|
||||
if (Minecraft.getInstance().player.isSneaking())
|
||||
return;
|
||||
|
||||
TessellatorHelper.prepareForDrawing();
|
||||
GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ());
|
||||
|
@ -50,7 +54,10 @@ public class FilteringRenderer {
|
|||
|
||||
AxisAlignedBB bb = new AxisAlignedBB(Vec3d.ZERO, Vec3d.ZERO).grow(.25f);
|
||||
String label = Lang.translate("logistics.filter");
|
||||
ValueBox box = behaviour.isCountVisible() ? new ItemValueBox(label, bb, behaviour.getFilter().getCount())
|
||||
ItemStack filter = behaviour.getFilter();
|
||||
if (filter.getItem() instanceof FilterItem)
|
||||
label = "";
|
||||
ValueBox box = behaviour.isCountVisible() ? new ItemValueBox(label, bb, filter, behaviour.scrollableValue)
|
||||
: new ValueBox(label, bb);
|
||||
box.offsetLabel(behaviour.textShift).withColors(0x7777BB, 0xCCBBFF);
|
||||
ValueBoxRenderer.renderBox(box, behaviour.testHit(target.getHitVec()));
|
||||
|
|
|
@ -39,19 +39,17 @@ public class ExtractingBehaviour extends InventoryManagementBehaviour {
|
|||
this.customAmountFilter = filter;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public ExtractingBehaviour withAdditionalFilter(Predicate<ItemStack> filter) {
|
||||
this.customFilter = filter;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public boolean extract() {
|
||||
int amount = -1;
|
||||
FilteringBehaviour filter = get(tileEntity, FilteringBehaviour.TYPE);
|
||||
if (filter != null) {
|
||||
ItemStack filterItem = filter.getFilter();
|
||||
amount = filterItem.isEmpty() ? -1 : filterItem.getCount();
|
||||
}
|
||||
if (filter != null && !filter.anyAmount())
|
||||
amount = filter.getAmount();
|
||||
return extract(amount);
|
||||
}
|
||||
|
||||
|
@ -70,7 +68,7 @@ public class ExtractingBehaviour extends InventoryManagementBehaviour {
|
|||
extract = ItemHelper.extract(inv, test, exactAmount, false);
|
||||
else
|
||||
extract = ItemHelper.extract(inv, test, customAmountFilter, false);
|
||||
|
||||
|
||||
if (!extract.isEmpty()) {
|
||||
callback.accept(extract);
|
||||
return true;
|
||||
|
|
|
@ -29,7 +29,7 @@ public abstract class AbstractSimiContainerScreen<T extends Container> extends C
|
|||
|
||||
protected List<Widget> widgets;
|
||||
|
||||
protected AbstractSimiContainerScreen(T container, PlayerInventory inv, ITextComponent title) {
|
||||
public AbstractSimiContainerScreen(T container, PlayerInventory inv, ITextComponent title) {
|
||||
super(container, inv, title);
|
||||
widgets = new ArrayList<>();
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ public abstract class AbstractSimiContainerScreen<T extends Container> extends C
|
|||
}
|
||||
|
||||
protected void renderWindowForeground(int mouseX, int mouseY, float partialTicks) {
|
||||
super.renderHoveredToolTip(mouseX, mouseY);
|
||||
renderHoveredToolTip(mouseX, mouseY);
|
||||
for (Widget widget : widgets) {
|
||||
if (!widget.isHovered())
|
||||
continue;
|
||||
|
|
|
@ -12,7 +12,7 @@ public class Label extends AbstractSimiWidget {
|
|||
protected boolean hasShadow;
|
||||
protected int color;
|
||||
protected FontRenderer font;
|
||||
|
||||
|
||||
public Label(int x, int y, String text) {
|
||||
super(x, y, Minecraft.getInstance().fontRenderer.getStringWidth(text), 10);
|
||||
font = Minecraft.getInstance().fontRenderer;
|
||||
|
@ -21,34 +21,60 @@ public class Label extends AbstractSimiWidget {
|
|||
hasShadow = false;
|
||||
suffix = "";
|
||||
}
|
||||
|
||||
|
||||
public Label colored(int color) {
|
||||
this.color = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public Label withShadow() {
|
||||
this.hasShadow = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public Label withSuffix(String s) {
|
||||
suffix = s;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public void setTextAndTrim(String newText, boolean trimFront, int maxWidthPx) {
|
||||
FontRenderer fontRenderer = Minecraft.getInstance().fontRenderer;
|
||||
|
||||
if (fontRenderer.getStringWidth(newText) <= maxWidthPx) {
|
||||
text = newText;
|
||||
return;
|
||||
}
|
||||
|
||||
String trim = "...";
|
||||
int trimWidth = fontRenderer.getStringWidth(trim);
|
||||
|
||||
StringBuilder builder = new StringBuilder(newText);
|
||||
int startIndex = trimFront ? 0 : newText.length() - 1;
|
||||
int endIndex = !trimFront ? 0 : newText.length() - 1;
|
||||
int step = (int) Math.signum(endIndex - startIndex);
|
||||
|
||||
for (int i = startIndex; i != endIndex; i += step) {
|
||||
String sub = builder.substring(trimFront ? i : startIndex, trimFront ? endIndex + 1 : i + 1);
|
||||
if (fontRenderer.getStringWidth(sub) + trimWidth <= maxWidthPx) {
|
||||
text = trimFront ? trim + sub : sub + trim;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(int mouseX, int mouseY, float partialTicks) {
|
||||
if (!visible)
|
||||
return;
|
||||
if (text == null || text.isEmpty())
|
||||
return;
|
||||
|
||||
|
||||
GlStateManager.color4f(1, 1, 1, 1);
|
||||
if (hasShadow)
|
||||
font.drawStringWithShadow(text + suffix, x, y, color);
|
||||
else
|
||||
font.drawString(text + suffix, x, y, color);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ public class ItemDescription {
|
|||
linesOnShift = new ArrayList<>();
|
||||
linesOnCtrl = new ArrayList<>();
|
||||
}
|
||||
|
||||
|
||||
public ItemDescription withSummary(String summary) {
|
||||
add(linesOnShift, cutString(summary, palette.color, palette.hColor));
|
||||
add(linesOnShift, "");
|
||||
|
@ -86,11 +86,12 @@ public class ItemDescription {
|
|||
if (hasSpeedRequirement) {
|
||||
List<String> speedLevels = Lang.translatedOptions("tooltip.speedRequirement", "none", "medium", "high");
|
||||
int index = minimumRequiredSpeedLevel.ordinal();
|
||||
String level = minimumRequiredSpeedLevel.getTextColor() + makeProgressBar(3, index) + speedLevels.get(index);
|
||||
String level = minimumRequiredSpeedLevel.getTextColor() + makeProgressBar(3, index)
|
||||
+ speedLevels.get(index);
|
||||
add(linesOnShift, GRAY + Lang.translate("tooltip.speedRequirement"));
|
||||
add(linesOnShift, level);
|
||||
}
|
||||
if (hasStressImpact) {
|
||||
if (hasStressImpact && !block.hideStressImpact()) {
|
||||
List<String> stressLevels = Lang.translatedOptions("tooltip.stressImpact", "low", "medium", "high");
|
||||
double impact = parameters.stressEntries.get(id).get();
|
||||
StressImpact impactId = impact >= parameters.highStressImpact.get() ? StressImpact.HIGH
|
||||
|
@ -109,6 +110,10 @@ public class ItemDescription {
|
|||
: (capacity >= parameters.mediumCapacity.get() ? StressImpact.MEDIUM : StressImpact.HIGH);
|
||||
int index = StressImpact.values().length - 1 - impactId.ordinal();
|
||||
String level = impactId.getColor() + makeProgressBar(3, index) + stressCapacityLevels.get(index);
|
||||
if (block.showCapacityWithAnnotation())
|
||||
level += " " + DARK_GRAY + TextFormatting.ITALIC
|
||||
+ Lang.translate("tooltip.capacityProvided.asGenerator");
|
||||
|
||||
add(linesOnShift, GRAY + Lang.translate("tooltip.capacityProvided"));
|
||||
add(linesOnShift, level);
|
||||
}
|
||||
|
|
|
@ -57,5 +57,13 @@ public interface IRotate extends IWrenchable {
|
|||
public default SpeedLevel getMinimumRequiredSpeedLevel() {
|
||||
return SpeedLevel.NONE;
|
||||
}
|
||||
|
||||
public default boolean hideStressImpact() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public default boolean showCapacityWithAnnotation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,10 +43,15 @@ public class MechanicalBearingBlock extends DirectionalKineticBlock
|
|||
protected boolean hasStaticPart() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Axis getRotationAxis(BlockState state) {
|
||||
return state.get(FACING).getAxis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showCapacityWithAnnotation() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -77,5 +77,10 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements IWithTil
|
|||
public boolean hasShaftTowards(World world, BlockPos pos, BlockState state, Direction face) {
|
||||
return face == state.get(FACING).getOpposite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showCapacityWithAnnotation() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@ import net.minecraft.world.IBlockReader;
|
|||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class MotorBlock extends HorizontalKineticBlock implements IWithTileEntity<MotorTileEntity>, IHaveScrollableValue {
|
||||
public class MotorBlock extends HorizontalKineticBlock
|
||||
implements IWithTileEntity<MotorTileEntity>, IHaveScrollableValue {
|
||||
|
||||
private static final Vec3d valuePos = new Vec3d(15 / 16f, 5 / 16f, 5 / 16f);
|
||||
|
||||
|
@ -91,4 +92,9 @@ public class MotorBlock extends HorizontalKineticBlock implements IWithTileEntit
|
|||
public Direction getValueBoxDirection(BlockState state, IWorld world, BlockPos pos) {
|
||||
return state.get(HORIZONTAL_FACING).getOpposite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hideStressImpact() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -144,4 +144,9 @@ public class WaterWheelBlock extends HorizontalKineticBlock {
|
|||
return 1f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hideStressImpact() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ public abstract class BeltAttachableLogisticalBlock extends AttachedLogisticalBl
|
|||
|
||||
if (extracting == null)
|
||||
return false;
|
||||
if (filtering != null && (!filtering.test(stack) || stack.getCount() < filtering.getFilter().getCount()))
|
||||
if (filtering != null && (!filtering.test(stack) || stack.getCount() < filtering.getAmount()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -76,10 +76,10 @@ public abstract class BeltAttachableLogisticalBlock extends AttachedLogisticalBl
|
|||
return false;
|
||||
|
||||
FilteringBehaviour filtering = TileEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE);
|
||||
if (filtering != null && (!filtering.test(stack) || stack.getCount() < filtering.getFilter().getCount()))
|
||||
if (filtering != null && (!filtering.test(stack) || stack.getCount() < filtering.getAmount()))
|
||||
return false;
|
||||
if (!extracting.getShouldExtract().get())
|
||||
return !filtering.getFilter().isEmpty();
|
||||
return !filtering.anyAmount();
|
||||
|
||||
return !extracting.extractFromInventory();
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ public class TransposerTileEntity extends ExtractorTileEntity {
|
|||
return te.tryInsertingFromSide(facing, stack, true);
|
||||
}
|
||||
|
||||
if (filtering.getFilter().isEmpty())
|
||||
if (filtering.anyAmount())
|
||||
return true;
|
||||
return inserting.insert(stack, true).isEmpty();
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
package com.simibubi.create.modules.logistics.item;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
public class FilterItem extends Item {
|
||||
|
||||
public FilterItem(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
package com.simibubi.create.modules.logistics.item.filter;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.inventory.container.ClickType;
|
||||
import net.minecraft.inventory.container.Container;
|
||||
import net.minecraft.inventory.container.ContainerType;
|
||||
import net.minecraft.inventory.container.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
|
||||
public abstract class AbstractFilterContainer extends Container {
|
||||
|
||||
public PlayerEntity player;
|
||||
protected PlayerInventory playerInventory;
|
||||
public ItemStack filterItem;
|
||||
public ItemStackHandler filterInventory;
|
||||
|
||||
protected AbstractFilterContainer(ContainerType<?> type, int id, PlayerInventory inv, PacketBuffer extraData) {
|
||||
this(type, id, inv, extraData.readItemStack());
|
||||
}
|
||||
|
||||
protected AbstractFilterContainer(ContainerType<?> type, int id, PlayerInventory inv, ItemStack filterItem) {
|
||||
super(type, id);
|
||||
player = inv.player;
|
||||
playerInventory = inv;
|
||||
this.filterItem = filterItem;
|
||||
init();
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
this.filterInventory = createFilterInventory();
|
||||
readData(filterItem);
|
||||
addPlayerSlots();
|
||||
addFilterSlots();
|
||||
detectAndSendChanges();
|
||||
}
|
||||
|
||||
protected void clearContents() {
|
||||
for (int i = 0; i < filterInventory.getSlots(); i++)
|
||||
filterInventory.setStackInSlot(i, ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
protected abstract int getInventoryOffset();
|
||||
|
||||
protected abstract void addFilterSlots();
|
||||
|
||||
protected abstract ItemStackHandler createFilterInventory();
|
||||
|
||||
protected abstract void readData(ItemStack filterItem);
|
||||
|
||||
protected abstract void saveData(ItemStack filterItem);
|
||||
|
||||
protected void addPlayerSlots() {
|
||||
int x = 58;
|
||||
int y = 28 + getInventoryOffset();
|
||||
|
||||
for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot)
|
||||
this.addSlot(new Slot(playerInventory, hotbarSlot, x + hotbarSlot * 18, y + 58));
|
||||
for (int row = 0; row < 3; ++row)
|
||||
for (int col = 0; col < 9; ++col)
|
||||
this.addSlot(new Slot(playerInventory, col + row * 9 + 9, x + col * 18, y + row * 18));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canMergeSlot(ItemStack stack, Slot slotIn) {
|
||||
return canDragIntoSlot(slotIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDragIntoSlot(Slot slotIn) {
|
||||
return slotIn.inventory == playerInventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInteractWith(PlayerEntity playerIn) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, PlayerEntity player) {
|
||||
if (slotId == playerInventory.currentItem && clickTypeIn != ClickType.THROW)
|
||||
return ItemStack.EMPTY;
|
||||
|
||||
ItemStack held = playerInventory.getItemStack();
|
||||
if (slotId < 36)
|
||||
return super.slotClick(slotId, dragType, clickTypeIn, player);
|
||||
if (clickTypeIn == ClickType.THROW)
|
||||
return ItemStack.EMPTY;
|
||||
|
||||
int slot = slotId - 36;
|
||||
if (clickTypeIn == ClickType.CLONE) {
|
||||
if (player.isCreative() && held.isEmpty()) {
|
||||
ItemStack stackInSlot = filterInventory.getStackInSlot(slot).copy();
|
||||
stackInSlot.setCount(64);
|
||||
playerInventory.setItemStack(stackInSlot);
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
if (held.isEmpty()) {
|
||||
filterInventory.setStackInSlot(slot, ItemStack.EMPTY);
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
ItemStack insert = held.copy();
|
||||
insert.setCount(1);
|
||||
filterInventory.setStackInSlot(slot, insert);
|
||||
return held;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) {
|
||||
if (index < 36) {
|
||||
ItemStack stackToInsert = playerInventory.getStackInSlot(index);
|
||||
for (int i = 0; i < filterInventory.getSlots(); i++) {
|
||||
ItemStack stack = filterInventory.getStackInSlot(i);
|
||||
if (ItemHandlerHelper.canItemStacksStack(stack, stackToInsert))
|
||||
break;
|
||||
if (stack.isEmpty()) {
|
||||
ItemStack copy = stackToInsert.copy();
|
||||
copy.setCount(1);
|
||||
filterInventory.insertItem(i, copy, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
filterInventory.extractItem(index - 36, 1, false);
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContainerClosed(PlayerEntity playerIn) {
|
||||
super.onContainerClosed(playerIn);
|
||||
filterItem.getOrCreateTag().put("Items", filterInventory.serializeNBT());
|
||||
saveData(filterItem);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
package com.simibubi.create.modules.logistics.item.filter;
|
||||
|
||||
import static com.simibubi.create.ScreenResources.PLAYER_INVENTORY;
|
||||
import static net.minecraft.util.text.TextFormatting.GRAY;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.simibubi.create.AllPackets;
|
||||
import com.simibubi.create.ScreenResources;
|
||||
import com.simibubi.create.foundation.gui.AbstractSimiContainerScreen;
|
||||
import com.simibubi.create.foundation.gui.widgets.IconButton;
|
||||
import com.simibubi.create.foundation.gui.widgets.Indicator;
|
||||
import com.simibubi.create.foundation.gui.widgets.Indicator.State;
|
||||
import com.simibubi.create.foundation.item.ItemDescription.Palette;
|
||||
import com.simibubi.create.foundation.item.TooltipHelper;
|
||||
import com.simibubi.create.modules.logistics.item.filter.FilterScreenPacket.Option;
|
||||
|
||||
import net.minecraft.client.gui.widget.Widget;
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
public abstract class AbstractFilterScreen<F extends AbstractFilterContainer> extends AbstractSimiContainerScreen<F> {
|
||||
|
||||
protected ScreenResources background;
|
||||
|
||||
private IconButton resetButton;
|
||||
private IconButton confirmButton;
|
||||
|
||||
protected AbstractFilterScreen(F container, PlayerInventory inv, ITextComponent title, ScreenResources background) {
|
||||
super(container, inv, title);
|
||||
this.background = background;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
setWindowSize(background.width + 80, background.height + PLAYER_INVENTORY.height + 20);
|
||||
super.init();
|
||||
widgets.clear();
|
||||
|
||||
resetButton = new IconButton(guiLeft + 15, guiTop + background.height - 30, ScreenResources.I_TRASH);
|
||||
confirmButton = new IconButton(guiLeft + 159, guiTop + background.height - 30, ScreenResources.I_CONFIRM);
|
||||
|
||||
widgets.add(resetButton);
|
||||
widgets.add(confirmButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderWindow(int mouseX, int mouseY, float partialTicks) {
|
||||
int x = guiLeft;
|
||||
int y = guiTop;
|
||||
background.draw(this, x, y);
|
||||
|
||||
int invX = x + 50;
|
||||
int invY = y + background.height + 10;
|
||||
PLAYER_INVENTORY.draw(this, invX, invY);
|
||||
|
||||
font.drawString(playerInventory.getDisplayName().getFormattedText(), invX + 7, invY + 6, 0x666666);
|
||||
font.drawString(I18n.format(container.filterItem.getTranslationKey()), x + 15, y + 9, 0x5B5037);
|
||||
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translated(guiLeft + background.width + 0, guiTop + background.height - 60, 0);
|
||||
GlStateManager.scaled(5, 5, 5);
|
||||
itemRenderer.renderItemIntoGUI(container.filterItem, 0, 0);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
handleTooltips();
|
||||
super.tick();
|
||||
handleIndicators();
|
||||
|
||||
if (!container.player.getHeldItemMainhand().equals(container.filterItem, false))
|
||||
minecraft.player.closeScreen();
|
||||
}
|
||||
|
||||
public void handleIndicators() {
|
||||
List<IconButton> tooltipButtons = getTooltipButtons();
|
||||
for (IconButton button : tooltipButtons)
|
||||
button.active = isButtonEnabled(button);
|
||||
for (Widget w : widgets)
|
||||
if (w instanceof Indicator)
|
||||
((Indicator) w).state = isIndicatorOn((Indicator) w) ? State.ON : State.OFF;
|
||||
}
|
||||
|
||||
protected abstract boolean isButtonEnabled(IconButton button);
|
||||
|
||||
protected abstract boolean isIndicatorOn(Indicator indicator);
|
||||
|
||||
protected void handleTooltips() {
|
||||
List<IconButton> tooltipButtons = getTooltipButtons();
|
||||
|
||||
for (IconButton button : tooltipButtons) {
|
||||
if (!button.getToolTip().isEmpty()) {
|
||||
button.setToolTip(button.getToolTip().get(0));
|
||||
button.getToolTip().add(TooltipHelper.holdShift(Palette.Yellow, hasShiftDown()));
|
||||
}
|
||||
}
|
||||
|
||||
if (hasShiftDown()) {
|
||||
List<String> tooltipDescriptions = getTooltipDescriptions();
|
||||
for (int i = 0; i < tooltipButtons.size(); i++)
|
||||
fillToolTip(tooltipButtons.get(i), tooltipDescriptions.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
protected List<IconButton> getTooltipButtons() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
protected List<String> getTooltipDescriptions() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private void fillToolTip(IconButton button, String tooltip) {
|
||||
if (!button.isHovered())
|
||||
return;
|
||||
List<String> tip = button.getToolTip();
|
||||
tip.addAll(TooltipHelper.cutString(tooltip, GRAY, GRAY));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double x, double y, int button) {
|
||||
boolean mouseClicked = super.mouseClicked(x, y, button);
|
||||
|
||||
if (button == 0) {
|
||||
if (confirmButton.isHovered()) {
|
||||
minecraft.player.closeScreen();
|
||||
return true;
|
||||
}
|
||||
if (resetButton.isHovered()) {
|
||||
container.clearContents();
|
||||
contentsCleared();
|
||||
sendOptionUpdate(Option.CLEAR);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return mouseClicked;
|
||||
}
|
||||
|
||||
protected void contentsCleared() {
|
||||
}
|
||||
|
||||
protected void sendOptionUpdate(Option option) {
|
||||
AllPackets.channel.sendToServer(new FilterScreenPacket(option));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
package com.simibubi.create.modules.logistics.item.filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.AllContainers;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.inventory.container.ClickType;
|
||||
import net.minecraft.inventory.container.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraftforge.common.util.Constants.NBT;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import net.minecraftforge.items.SlotItemHandler;
|
||||
|
||||
public class AttributeFilterContainer extends AbstractFilterContainer {
|
||||
|
||||
public enum WhitelistMode {
|
||||
WHITELIST_DISJ, WHITELIST_CONJ, BLACKLIST;
|
||||
}
|
||||
|
||||
WhitelistMode whitelistMode;
|
||||
List<ItemAttribute> selectedAttributes;
|
||||
|
||||
public AttributeFilterContainer(int id, PlayerInventory inv, PacketBuffer extraData) {
|
||||
super(AllContainers.ATTRIBUTE_FILTER.type, id, inv, extraData);
|
||||
}
|
||||
|
||||
public AttributeFilterContainer(int id, PlayerInventory inv, ItemStack stack) {
|
||||
super(AllContainers.ATTRIBUTE_FILTER.type, id, inv, stack);
|
||||
}
|
||||
|
||||
public void appendSelectedAttribute(ItemAttribute itemAttribute) {
|
||||
selectedAttributes.add(itemAttribute);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearContents() {
|
||||
selectedAttributes.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
ItemStack stack = new ItemStack(Items.NAME_TAG);
|
||||
stack.setDisplayName(
|
||||
new StringTextComponent("Selected Tags").applyTextStyles(TextFormatting.RESET, TextFormatting.BLUE));
|
||||
filterInventory.setStackInSlot(1, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemStackHandler createFilterInventory() {
|
||||
return new ItemStackHandler(2);
|
||||
}
|
||||
|
||||
protected void addFilterSlots() {
|
||||
this.addSlot(new SlotItemHandler(filterInventory, 0, 16, 23));
|
||||
this.addSlot(new SlotItemHandler(filterInventory, 1, 59, 56) {
|
||||
@Override
|
||||
public boolean canTakeStack(PlayerEntity playerIn) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, PlayerEntity player) {
|
||||
if (slotId == 37)
|
||||
return ItemStack.EMPTY;
|
||||
return super.slotClick(slotId, dragType, clickTypeIn, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDragIntoSlot(Slot slotIn) {
|
||||
if (slotIn.slotNumber == 37)
|
||||
return false;
|
||||
return super.canDragIntoSlot(slotIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canMergeSlot(ItemStack stack, Slot slotIn) {
|
||||
if (slotIn.slotNumber == 37)
|
||||
return false;
|
||||
return super.canMergeSlot(stack, slotIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) {
|
||||
if (index == 37)
|
||||
return ItemStack.EMPTY;
|
||||
if (index == 36) {
|
||||
filterInventory.setStackInSlot(37, ItemStack.EMPTY);
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
if (index < 36) {
|
||||
ItemStack stackToInsert = playerInventory.getStackInSlot(index);
|
||||
ItemStack copy = stackToInsert.copy();
|
||||
copy.setCount(1);
|
||||
filterInventory.setStackInSlot(0, copy);
|
||||
}
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getInventoryOffset() {
|
||||
return 86;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readData(ItemStack filterItem) {
|
||||
selectedAttributes = new ArrayList<>();
|
||||
whitelistMode = WhitelistMode.values()[filterItem.getOrCreateTag().getInt("WhitelistMode")];
|
||||
ListNBT attributes = filterItem.getOrCreateTag().getList("MatchedAttributes", NBT.TAG_COMPOUND);
|
||||
attributes.forEach(inbt -> selectedAttributes.add(ItemAttribute.fromNBT((CompoundNBT) inbt)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveData(ItemStack filterItem) {
|
||||
filterItem.getOrCreateTag().putInt("WhitelistMode", whitelistMode.ordinal());
|
||||
ListNBT attributes = new ListNBT();
|
||||
selectedAttributes.forEach(at -> {
|
||||
if (at == null)
|
||||
return;
|
||||
CompoundNBT compoundNBT = new CompoundNBT();
|
||||
at.serializeNBT(compoundNBT);
|
||||
attributes.add(compoundNBT);
|
||||
});
|
||||
filterItem.getOrCreateTag().put("MatchedAttributes", attributes);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
package com.simibubi.create.modules.logistics.item.filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.simibubi.create.AllPackets;
|
||||
import com.simibubi.create.ScreenResources;
|
||||
import com.simibubi.create.foundation.gui.widgets.IconButton;
|
||||
import com.simibubi.create.foundation.gui.widgets.Indicator;
|
||||
import com.simibubi.create.foundation.gui.widgets.Label;
|
||||
import com.simibubi.create.foundation.gui.widgets.SelectionScrollInput;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.modules.logistics.item.filter.AttributeFilterContainer.WhitelistMode;
|
||||
import com.simibubi.create.modules.logistics.item.filter.FilterScreenPacket.Option;
|
||||
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
|
||||
public class AttributeFilterScreen extends AbstractFilterScreen<AttributeFilterContainer> {
|
||||
|
||||
private static final String PREFIX = "gui.attribute_filter.";
|
||||
|
||||
private IconButton whitelistDis, whitelistCon, blacklist;
|
||||
private Indicator whitelistDisIndicator, whitelistConIndicator, blacklistIndicator;
|
||||
private IconButton add;
|
||||
|
||||
private String whitelistDisN = Lang.translate(PREFIX + "whitelist_disjunctive");
|
||||
private String whitelistDisDESC = Lang.translate(PREFIX + "whitelist_disjunctive.description");
|
||||
private String whitelistConN = Lang.translate(PREFIX + "whitelist_conjunctive");
|
||||
private String whitelistConDESC = Lang.translate(PREFIX + "whitelist_conjunctive.description");
|
||||
private String blacklistN = Lang.translate(PREFIX + "blacklist");
|
||||
private String blacklistDESC = Lang.translate(PREFIX + "blacklist.description");
|
||||
|
||||
private String referenceH = Lang.translate(PREFIX + "add_reference_item");
|
||||
private String noSelectedT = Lang.translate(PREFIX + "no_selected_attributes");
|
||||
private String selectedT = Lang.translate(PREFIX + "selected_attributes");
|
||||
|
||||
private ItemStack lastItemScanned = ItemStack.EMPTY;
|
||||
private List<ItemAttribute> attributesOfItem = new ArrayList<>();
|
||||
private List<String> selectedAttributes = new ArrayList<>();
|
||||
private SelectionScrollInput attributeSelector;
|
||||
private Label attributeSelectorLabel;
|
||||
|
||||
public AttributeFilterScreen(AttributeFilterContainer container, PlayerInventory inv, ITextComponent title) {
|
||||
super(container, inv, title, ScreenResources.ATTRIBUTE_FILTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
int x = guiLeft;
|
||||
int y = guiTop;
|
||||
|
||||
whitelistDis = new IconButton(x + 84, y + 58, ScreenResources.I_WHITELIST_OR);
|
||||
whitelistDis.setToolTip(whitelistDisN);
|
||||
whitelistCon = new IconButton(x + 102, y + 58, ScreenResources.I_WHITELIST_AND);
|
||||
whitelistCon.setToolTip(whitelistConN);
|
||||
blacklist = new IconButton(x + 120, y + 58, ScreenResources.I_WHITELIST_NOT);
|
||||
blacklist.setToolTip(blacklistN);
|
||||
|
||||
whitelistDisIndicator = new Indicator(x + 84, y + 53, "");
|
||||
whitelistConIndicator = new Indicator(x + 102, y + 53, "");
|
||||
blacklistIndicator = new Indicator(x + 120, y + 53, "");
|
||||
|
||||
widgets.addAll(Arrays.asList(blacklist, whitelistCon, whitelistDis, blacklistIndicator, whitelistConIndicator,
|
||||
whitelistDisIndicator));
|
||||
|
||||
add = new IconButton(x + 159, y + 22, ScreenResources.I_ADD);
|
||||
widgets.add(add);
|
||||
handleIndicators();
|
||||
|
||||
attributeSelectorLabel = new Label(x + 40, y + 27, "").colored(0xF3EBDE).withShadow();
|
||||
attributeSelector = new SelectionScrollInput(x + 37, y + 24, 118, 14);
|
||||
attributeSelector.forOptions(Arrays.asList(""));
|
||||
attributeSelector.calling(s -> {
|
||||
});
|
||||
referenceItemChanged(container.filterInventory.getStackInSlot(0));
|
||||
|
||||
widgets.add(attributeSelector);
|
||||
widgets.add(attributeSelectorLabel);
|
||||
|
||||
selectedAttributes.clear();
|
||||
selectedAttributes
|
||||
.add(TextFormatting.YELLOW + (container.selectedAttributes.isEmpty() ? noSelectedT : selectedT));
|
||||
container.selectedAttributes.forEach(at -> selectedAttributes.add(TextFormatting.GRAY + "- " + at.format()));
|
||||
|
||||
}
|
||||
|
||||
private void referenceItemChanged(ItemStack stack) {
|
||||
lastItemScanned = stack;
|
||||
|
||||
if (stack.isEmpty()) {
|
||||
attributeSelector.active = false;
|
||||
attributeSelector.visible = false;
|
||||
attributeSelectorLabel.text = TextFormatting.ITALIC + referenceH;
|
||||
add.active = false;
|
||||
attributeSelector.calling(s -> {
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
add.active = true;
|
||||
attributeSelector.titled(stack.getDisplayName().getFormattedText() + "...");
|
||||
attributesOfItem.clear();
|
||||
for (ItemAttribute itemAttribute : ItemAttribute.types)
|
||||
attributesOfItem.addAll(itemAttribute.listAttributesOf(stack));
|
||||
List<String> options = attributesOfItem.stream().map(ItemAttribute::format).collect(Collectors.toList());
|
||||
attributeSelector.forOptions(options);
|
||||
attributeSelector.active = true;
|
||||
attributeSelector.visible = true;
|
||||
attributeSelector.setState(0);
|
||||
attributeSelector.calling(i -> {
|
||||
attributeSelectorLabel.setTextAndTrim(options.get(i), true, 112);
|
||||
ItemAttribute selected = attributesOfItem.get(i);
|
||||
for (ItemAttribute existing : container.selectedAttributes) {
|
||||
CompoundNBT testTag = new CompoundNBT();
|
||||
CompoundNBT testTag2 = new CompoundNBT();
|
||||
existing.serializeNBT(testTag);
|
||||
selected.serializeNBT(testTag2);
|
||||
if (testTag.equals(testTag2)) {
|
||||
add.active = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
add.active = true;
|
||||
});
|
||||
attributeSelector.onChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderWindowForeground(int mouseX, int mouseY, float partialTicks) {
|
||||
ItemStack stack = container.filterInventory.getStackInSlot(1);
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translatef(0.0F, 0.0F, 32.0F);
|
||||
this.blitOffset = 200;
|
||||
this.itemRenderer.zLevel = 200.0F;
|
||||
this.itemRenderer.renderItemOverlayIntoGUI(font, stack, guiLeft + 59, guiTop + 56,
|
||||
String.valueOf(selectedAttributes.size() - 1));
|
||||
this.blitOffset = 0;
|
||||
this.itemRenderer.zLevel = 0.0F;
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
super.renderWindowForeground(mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
ItemStack stackInSlot = container.filterInventory.getStackInSlot(0);
|
||||
if (!stackInSlot.equals(lastItemScanned, false))
|
||||
referenceItemChanged(stackInSlot);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderHoveredToolTip(int mouseX, int mouseY) {
|
||||
if (this.minecraft.player.inventory.getItemStack().isEmpty() && this.hoveredSlot != null
|
||||
&& this.hoveredSlot.getHasStack()) {
|
||||
if (this.hoveredSlot.slotNumber == 37) {
|
||||
renderTooltip(selectedAttributes, mouseX, mouseY, font);
|
||||
return;
|
||||
}
|
||||
this.renderTooltip(this.hoveredSlot.getStack(), mouseX, mouseY);
|
||||
}
|
||||
super.renderHoveredToolTip(mouseX, mouseY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<IconButton> getTooltipButtons() {
|
||||
return Arrays.asList(blacklist, whitelistCon, whitelistDis);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getTooltipDescriptions() {
|
||||
return Arrays.asList(blacklistDESC, whitelistConDESC, whitelistDisDESC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double x, double y, int button) {
|
||||
boolean mouseClicked = super.mouseClicked(x, y, button);
|
||||
|
||||
if (button != 0)
|
||||
return mouseClicked;
|
||||
|
||||
if (blacklist.isHovered()) {
|
||||
container.whitelistMode = WhitelistMode.BLACKLIST;
|
||||
sendOptionUpdate(Option.BLACKLIST);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (whitelistCon.isHovered()) {
|
||||
container.whitelistMode = WhitelistMode.WHITELIST_CONJ;
|
||||
sendOptionUpdate(Option.WHITELIST2);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (whitelistDis.isHovered()) {
|
||||
container.whitelistMode = WhitelistMode.WHITELIST_DISJ;
|
||||
sendOptionUpdate(Option.WHITELIST);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (add.isHovered() && add.active) {
|
||||
int index = attributeSelector.getState();
|
||||
if (index < attributesOfItem.size()) {
|
||||
add.active = false;
|
||||
CompoundNBT tag = new CompoundNBT();
|
||||
ItemAttribute itemAttribute = attributesOfItem.get(index);
|
||||
itemAttribute.serializeNBT(tag);
|
||||
AllPackets.channel.sendToServer(new FilterScreenPacket(Option.ADD_TAG, tag));
|
||||
container.selectedAttributes.add(itemAttribute);
|
||||
if (container.selectedAttributes.size() == 1)
|
||||
selectedAttributes.set(0, TextFormatting.YELLOW + selectedT);
|
||||
selectedAttributes.add(TextFormatting.GRAY + "- " + itemAttribute.format());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return mouseClicked;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void contentsCleared() {
|
||||
selectedAttributes.clear();
|
||||
selectedAttributes.add(TextFormatting.YELLOW + noSelectedT);
|
||||
if (!lastItemScanned.isEmpty())
|
||||
add.active = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isButtonEnabled(IconButton button) {
|
||||
if (button == blacklist)
|
||||
return container.whitelistMode != WhitelistMode.BLACKLIST;
|
||||
if (button == whitelistCon)
|
||||
return container.whitelistMode != WhitelistMode.WHITELIST_CONJ;
|
||||
if (button == whitelistDis)
|
||||
return container.whitelistMode != WhitelistMode.WHITELIST_DISJ;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isIndicatorOn(Indicator indicator) {
|
||||
if (indicator == blacklistIndicator)
|
||||
return container.whitelistMode == WhitelistMode.BLACKLIST;
|
||||
if (indicator == whitelistConIndicator)
|
||||
return container.whitelistMode == WhitelistMode.WHITELIST_CONJ;
|
||||
if (indicator == whitelistDisIndicator)
|
||||
return container.whitelistMode == WhitelistMode.WHITELIST_DISJ;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package com.simibubi.create.modules.logistics.item.filter;
|
||||
|
||||
import com.simibubi.create.AllContainers;
|
||||
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import net.minecraftforge.items.SlotItemHandler;
|
||||
|
||||
public class FilterContainer extends AbstractFilterContainer {
|
||||
|
||||
boolean respectNBT;
|
||||
boolean blacklist;
|
||||
|
||||
public FilterContainer(int id, PlayerInventory inv, PacketBuffer extraData) {
|
||||
super(AllContainers.FILTER.type, id, inv, extraData);
|
||||
}
|
||||
|
||||
public FilterContainer(int id, PlayerInventory inv, ItemStack stack) {
|
||||
super(AllContainers.FILTER.type, id, inv, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addFilterSlots() {
|
||||
int x = 16;
|
||||
int y = 21;
|
||||
|
||||
for (int row = 0; row < 2; ++row)
|
||||
for (int col = 0; col < 9; ++col)
|
||||
this.addSlot(new SlotItemHandler(filterInventory, col + row * 9, x + col * 18, y + row * 18));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemStackHandler createFilterInventory() {
|
||||
return FilterItem.getFilterItems(filterItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getInventoryOffset() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readData(ItemStack filterItem) {
|
||||
CompoundNBT tag = filterItem.getOrCreateTag();
|
||||
respectNBT = tag.getBoolean("RespectNBT");
|
||||
blacklist = tag.getBoolean("Blacklist");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveData(ItemStack filterItem) {
|
||||
CompoundNBT tag = filterItem.getOrCreateTag();
|
||||
tag.putBoolean("RespectNBT", respectNBT);
|
||||
tag.putBoolean("Blacklist", blacklist);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
package com.simibubi.create.modules.logistics.item.filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.AllKeys;
|
||||
import com.simibubi.create.foundation.item.ItemDescription;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.modules.logistics.item.filter.AttributeFilterContainer.WhitelistMode;
|
||||
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.inventory.container.Container;
|
||||
import net.minecraft.inventory.container.INamedContainerProvider;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemUseContext;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.INBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.common.util.Constants.NBT;
|
||||
import net.minecraftforge.fml.network.NetworkHooks;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
|
||||
public class FilterItem extends Item implements INamedContainerProvider {
|
||||
|
||||
public FilterItem(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResultType onItemUse(ItemUseContext context) {
|
||||
return onItemRightClick(context.getWorld(), context.getPlayer(), context.getHand()).getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void addInformation(ItemStack stack, World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
|
||||
if (!AllKeys.shiftDown()) {
|
||||
List<String> makeSummary = makeSummary(stack);
|
||||
if (makeSummary.isEmpty())
|
||||
return;
|
||||
ItemDescription.add(tooltip, " ");
|
||||
ItemDescription.add(tooltip, makeSummary);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> makeSummary(ItemStack filter) {
|
||||
List<String> list = new ArrayList<>();
|
||||
|
||||
if (AllItems.FILTER.typeOf(filter)) {
|
||||
ItemStackHandler filterItems = getFilterItems(filter);
|
||||
boolean blacklist = filter.getOrCreateTag().getBoolean("Blacklist");
|
||||
|
||||
list.add(TextFormatting.GOLD
|
||||
+ (blacklist ? Lang.translate("gui.filter.blacklist") : Lang.translate("gui.filter.whitelist")));
|
||||
int count = 0;
|
||||
for (int i = 0; i < filterItems.getSlots(); i++) {
|
||||
if (count > 3) {
|
||||
list.add(TextFormatting.DARK_GRAY + "- ...");
|
||||
break;
|
||||
}
|
||||
|
||||
ItemStack filterStack = filterItems.getStackInSlot(i);
|
||||
if (filterStack.isEmpty())
|
||||
continue;
|
||||
list.add(TextFormatting.GRAY + "- " + filterStack.getDisplayName().getFormattedText());
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
if (AllItems.PROPERTY_FILTER.typeOf(filter)) {
|
||||
WhitelistMode whitelistMode = WhitelistMode.values()[filter.getOrCreateTag().getInt("WhitelistMode")];
|
||||
list.add(TextFormatting.GOLD + (whitelistMode == WhitelistMode.WHITELIST_CONJ
|
||||
? Lang.translate("gui.attribute_filter.whitelist_conjunctive")
|
||||
: whitelistMode == WhitelistMode.WHITELIST_DISJ
|
||||
? Lang.translate("gui.attribute_filter.whitelist_disjunctive")
|
||||
: Lang.translate("gui.attribute_filter.blacklist")));
|
||||
|
||||
int count = 0;
|
||||
ListNBT attributes = filter.getOrCreateTag().getList("MatchedAttributes", NBT.TAG_COMPOUND);
|
||||
for (INBT inbt : attributes) {
|
||||
ItemAttribute attribute = ItemAttribute.fromNBT((CompoundNBT) inbt);
|
||||
if (count > 3) {
|
||||
list.add(TextFormatting.DARK_GRAY + "- ...");
|
||||
break;
|
||||
}
|
||||
list.add(TextFormatting.GRAY + "- " + attribute.format());
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult<ItemStack> onItemRightClick(World world, PlayerEntity player, Hand hand) {
|
||||
ItemStack heldItem = player.getHeldItem(hand);
|
||||
|
||||
if (!player.isSneaking() && hand == Hand.MAIN_HAND) {
|
||||
if (AllItems.LOGISTICAL_FILTER.typeOf(heldItem))
|
||||
return ActionResult.newResult(ActionResultType.FAIL, heldItem);
|
||||
if (!world.isRemote && player instanceof ServerPlayerEntity)
|
||||
NetworkHooks.openGui((ServerPlayerEntity) player, this, buf -> {
|
||||
buf.writeItemStack(heldItem);
|
||||
});
|
||||
return ActionResult.newResult(ActionResultType.SUCCESS, heldItem);
|
||||
}
|
||||
return ActionResult.newResult(ActionResultType.PASS, heldItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Container createMenu(int id, PlayerInventory inv, PlayerEntity player) {
|
||||
ItemStack heldItem = player.getHeldItemMainhand();
|
||||
if (AllItems.FILTER.typeOf(heldItem))
|
||||
return new FilterContainer(id, inv, heldItem);
|
||||
if (AllItems.PROPERTY_FILTER.typeOf(heldItem))
|
||||
return new AttributeFilterContainer(id, inv, heldItem);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITextComponent getDisplayName() {
|
||||
return new StringTextComponent(getTranslationKey());
|
||||
}
|
||||
|
||||
public static ItemStackHandler getFilterItems(ItemStack stack) {
|
||||
ItemStackHandler newInv = new ItemStackHandler(18);
|
||||
if (!AllItems.FILTER.typeOf(stack))
|
||||
throw new IllegalArgumentException("Cannot get filter items from non-filter: " + stack);
|
||||
CompoundNBT invNBT = stack.getOrCreateChildTag("Items");
|
||||
if (!invNBT.isEmpty())
|
||||
newInv.deserializeNBT(invNBT);
|
||||
return newInv;
|
||||
}
|
||||
|
||||
public static boolean test(ItemStack stack, ItemStack filter) {
|
||||
return test(stack, filter, false);
|
||||
}
|
||||
|
||||
private static boolean test(ItemStack stack, ItemStack filter, boolean matchNBT) {
|
||||
if (!(filter.getItem() instanceof FilterItem))
|
||||
return (matchNBT ? ItemHandlerHelper.canItemStacksStack(filter, stack)
|
||||
: ItemStack.areItemsEqual(filter, stack));
|
||||
|
||||
if (AllItems.FILTER.typeOf(filter)) {
|
||||
ItemStackHandler filterItems = getFilterItems(filter);
|
||||
boolean respectNBT = filter.getOrCreateTag().getBoolean("RespectNBT");
|
||||
boolean blacklist = filter.getOrCreateTag().getBoolean("Blacklist");
|
||||
for (int slot = 0; slot < filterItems.getSlots(); slot++) {
|
||||
ItemStack stackInSlot = filterItems.getStackInSlot(slot);
|
||||
if (stackInSlot.isEmpty())
|
||||
continue;
|
||||
boolean matches = test(stack, stackInSlot, respectNBT);
|
||||
if (matches)
|
||||
return !blacklist;
|
||||
}
|
||||
return blacklist;
|
||||
}
|
||||
|
||||
if (AllItems.PROPERTY_FILTER.typeOf(filter)) {
|
||||
WhitelistMode whitelistMode = WhitelistMode.values()[filter.getOrCreateTag().getInt("WhitelistMode")];
|
||||
ListNBT attributes = filter.getOrCreateTag().getList("MatchedAttributes", NBT.TAG_COMPOUND);
|
||||
for (INBT inbt : attributes) {
|
||||
ItemAttribute attribute = ItemAttribute.fromNBT((CompoundNBT) inbt);
|
||||
boolean matches = attribute.appliesTo(stack);
|
||||
|
||||
if (matches) {
|
||||
switch (whitelistMode) {
|
||||
case BLACKLIST:
|
||||
return false;
|
||||
case WHITELIST_CONJ:
|
||||
continue;
|
||||
case WHITELIST_DISJ:
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
switch (whitelistMode) {
|
||||
case BLACKLIST:
|
||||
continue;
|
||||
case WHITELIST_CONJ:
|
||||
return false;
|
||||
case WHITELIST_DISJ:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (whitelistMode) {
|
||||
case BLACKLIST:
|
||||
return true;
|
||||
case WHITELIST_CONJ:
|
||||
return true;
|
||||
case WHITELIST_DISJ:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
package com.simibubi.create.modules.logistics.item.filter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.ScreenResources;
|
||||
import com.simibubi.create.foundation.gui.widgets.IconButton;
|
||||
import com.simibubi.create.foundation.gui.widgets.Indicator;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.modules.logistics.item.filter.FilterScreenPacket.Option;
|
||||
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
public class FilterScreen extends AbstractFilterScreen<FilterContainer> {
|
||||
|
||||
private static final String PREFIX = "gui.filter.";
|
||||
|
||||
private String whitelistN = Lang.translate(PREFIX + "whitelist");
|
||||
private String whitelistDESC = Lang.translate(PREFIX + "whitelist.description");
|
||||
private String blacklistN = Lang.translate(PREFIX + "blacklist");
|
||||
private String blacklistDESC = Lang.translate(PREFIX + "blacklist.description");
|
||||
|
||||
private String respectDataN = Lang.translate(PREFIX + "respect_data");
|
||||
private String respectDataDESC = Lang.translate(PREFIX + "respect_data.description");
|
||||
private String ignoreDataN = Lang.translate(PREFIX + "ignore_data");
|
||||
private String ignoreDataDESC = Lang.translate(PREFIX + "ignore_data.description");
|
||||
|
||||
private IconButton whitelist, blacklist;
|
||||
private IconButton respectNBT, ignoreNBT;
|
||||
private Indicator whitelistIndicator, blacklistIndicator;
|
||||
private Indicator respectNBTIndicator, ignoreNBTIndicator;
|
||||
|
||||
public FilterScreen(FilterContainer container, PlayerInventory inv, ITextComponent title) {
|
||||
super(container, inv, title, ScreenResources.FILTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
int x = guiLeft;
|
||||
int y = guiTop;
|
||||
|
||||
blacklist = new IconButton(x + 58, y + 72, ScreenResources.I_BLACKLIST);
|
||||
blacklist.setToolTip(blacklistN);
|
||||
whitelist = new IconButton(x + 76, y + 72, ScreenResources.I_WHITELIST);
|
||||
whitelist.setToolTip(whitelistN);
|
||||
blacklistIndicator = new Indicator(x + 58, y + 67, "");
|
||||
whitelistIndicator = new Indicator(x + 76, y + 67, "");
|
||||
widgets.addAll(Arrays.asList(blacklist, whitelist, blacklistIndicator, whitelistIndicator));
|
||||
|
||||
respectNBT = new IconButton(x + 98, y + 72, ScreenResources.I_RESPECT_NBT);
|
||||
respectNBT.setToolTip(respectDataN);
|
||||
ignoreNBT = new IconButton(x + 116, y + 72, ScreenResources.I_IGNORE_NBT);
|
||||
ignoreNBT.setToolTip(ignoreDataN);
|
||||
respectNBTIndicator = new Indicator(x + 98, y + 67, "");
|
||||
ignoreNBTIndicator = new Indicator(x + 116, y + 67, "");
|
||||
widgets.addAll(Arrays.asList(respectNBT, ignoreNBT, respectNBTIndicator, ignoreNBTIndicator));
|
||||
handleIndicators();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double x, double y, int button) {
|
||||
boolean mouseClicked = super.mouseClicked(x, y, button);
|
||||
|
||||
if (button != 0)
|
||||
return mouseClicked;
|
||||
|
||||
if (blacklist.isHovered()) {
|
||||
container.blacklist = true;
|
||||
sendOptionUpdate(Option.BLACKLIST);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (whitelist.isHovered()) {
|
||||
container.blacklist = false;
|
||||
sendOptionUpdate(Option.WHITELIST);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (respectNBT.isHovered()) {
|
||||
container.respectNBT = true;
|
||||
sendOptionUpdate(Option.RESPECT_DATA);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ignoreNBT.isHovered()) {
|
||||
container.respectNBT = false;
|
||||
sendOptionUpdate(Option.IGNORE_DATA);
|
||||
return true;
|
||||
}
|
||||
|
||||
return mouseClicked;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<IconButton> getTooltipButtons() {
|
||||
return Arrays.asList(blacklist, whitelist, respectNBT, ignoreNBT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getTooltipDescriptions() {
|
||||
return Arrays.asList(blacklistDESC, whitelistDESC, respectDataDESC, ignoreDataDESC);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isButtonEnabled(IconButton button) {
|
||||
if (button == blacklist)
|
||||
return !container.blacklist;
|
||||
if (button == whitelist)
|
||||
return container.blacklist;
|
||||
if (button == respectNBT)
|
||||
return !container.respectNBT;
|
||||
if (button == ignoreNBT)
|
||||
return container.respectNBT;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isIndicatorOn(Indicator indicator) {
|
||||
if (indicator == blacklistIndicator)
|
||||
return container.blacklist;
|
||||
if (indicator == whitelistIndicator)
|
||||
return !container.blacklist;
|
||||
if (indicator == respectNBTIndicator)
|
||||
return container.respectNBT;
|
||||
if (indicator == ignoreNBTIndicator)
|
||||
return !container.respectNBT;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package com.simibubi.create.modules.logistics.item.filter;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.foundation.packet.SimplePacketBase;
|
||||
import com.simibubi.create.modules.logistics.item.filter.AttributeFilterContainer.WhitelistMode;
|
||||
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraftforge.fml.network.NetworkEvent.Context;
|
||||
|
||||
public class FilterScreenPacket extends SimplePacketBase {
|
||||
|
||||
enum Option {
|
||||
CLEAR, WHITELIST, WHITELIST2, BLACKLIST, RESPECT_DATA, IGNORE_DATA, ADD_TAG;
|
||||
}
|
||||
|
||||
private Option option;
|
||||
private CompoundNBT data;
|
||||
|
||||
public FilterScreenPacket(Option option) {
|
||||
this(option, new CompoundNBT());
|
||||
}
|
||||
|
||||
public FilterScreenPacket(Option option, CompoundNBT data) {
|
||||
this.option = option;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public FilterScreenPacket(PacketBuffer buffer) {
|
||||
option = Option.values()[buffer.readInt()];
|
||||
data = buffer.readCompoundTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketBuffer buffer) {
|
||||
buffer.writeInt(option.ordinal());
|
||||
buffer.writeCompoundTag(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Supplier<Context> context) {
|
||||
context.get().enqueueWork(() -> {
|
||||
ServerPlayerEntity player = context.get().getSender();
|
||||
|
||||
if (player.openContainer instanceof AbstractFilterContainer) {
|
||||
AbstractFilterContainer c = (AbstractFilterContainer) player.openContainer;
|
||||
if (option == Option.CLEAR) {
|
||||
c.clearContents();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (player.openContainer instanceof FilterContainer) {
|
||||
FilterContainer c = (FilterContainer) player.openContainer;
|
||||
if (option == Option.WHITELIST)
|
||||
c.blacklist = false;
|
||||
if (option == Option.BLACKLIST)
|
||||
c.blacklist = true;
|
||||
if (option == Option.RESPECT_DATA)
|
||||
c.respectNBT = true;
|
||||
if (option == Option.IGNORE_DATA)
|
||||
c.respectNBT = false;
|
||||
}
|
||||
|
||||
if (player.openContainer instanceof AttributeFilterContainer) {
|
||||
AttributeFilterContainer c = (AttributeFilterContainer) player.openContainer;
|
||||
if (option == Option.WHITELIST)
|
||||
c.whitelistMode = WhitelistMode.WHITELIST_DISJ;
|
||||
if (option == Option.WHITELIST2)
|
||||
c.whitelistMode = WhitelistMode.WHITELIST_CONJ;
|
||||
if (option == Option.BLACKLIST)
|
||||
c.whitelistMode = WhitelistMode.BLACKLIST;
|
||||
if (option == Option.ADD_TAG)
|
||||
c.appendSelectedAttribute(ItemAttribute.fromNBT(data));
|
||||
}
|
||||
|
||||
});
|
||||
context.get().setPacketHandled(true);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,274 @@
|
|||
package com.simibubi.create.modules.logistics.item.filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.tileentity.AbstractFurnaceTileEntity;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
|
||||
public interface ItemAttribute {
|
||||
|
||||
static List<ItemAttribute> types = new ArrayList<>();
|
||||
|
||||
static ItemAttribute standard = register(StandardTraits.DUMMY);
|
||||
static ItemAttribute inTag = register(new InTag(new ResourceLocation("dummy")));
|
||||
static ItemAttribute inItemGroup = register(new InItemGroup(ItemGroup.MISC));
|
||||
static ItemAttribute addedBy = register(new AddedBy("dummy"));
|
||||
|
||||
static ItemAttribute register(ItemAttribute attributeType) {
|
||||
types.add(attributeType);
|
||||
return attributeType;
|
||||
}
|
||||
|
||||
public boolean appliesTo(ItemStack stack);
|
||||
|
||||
public List<ItemAttribute> listAttributesOf(ItemStack stack);
|
||||
|
||||
public String getTranslationKey();
|
||||
|
||||
void writeNBT(CompoundNBT nbt);
|
||||
|
||||
ItemAttribute readNBT(CompoundNBT nbt);
|
||||
|
||||
public default void serializeNBT(CompoundNBT nbt) {
|
||||
CompoundNBT compound = new CompoundNBT();
|
||||
writeNBT(compound);
|
||||
nbt.put(getNBTKey(), compound);
|
||||
}
|
||||
|
||||
public static ItemAttribute fromNBT(CompoundNBT nbt) {
|
||||
for (ItemAttribute itemAttribute : types) {
|
||||
if (!itemAttribute.canRead(nbt))
|
||||
continue;
|
||||
return itemAttribute.readNBT(nbt.getCompound(itemAttribute.getNBTKey()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
default Object[] getTranslationParameters() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
default boolean canRead(CompoundNBT nbt) {
|
||||
return nbt.contains(getNBTKey());
|
||||
}
|
||||
|
||||
default String getNBTKey() {
|
||||
return getTranslationKey();
|
||||
}
|
||||
|
||||
@OnlyIn(value = Dist.CLIENT)
|
||||
default String format() {
|
||||
return Lang.translate("item_attributes." + getTranslationKey(), getTranslationParameters());
|
||||
}
|
||||
|
||||
public static enum StandardTraits implements ItemAttribute {
|
||||
|
||||
DUMMY(s -> false),
|
||||
PLACEABLE(s -> s.getItem() instanceof BlockItem),
|
||||
CONSUMABLE(ItemStack::isFood),
|
||||
ENCHANTED(ItemStack::isEnchanted),
|
||||
DAMAGED(ItemStack::isDamaged),
|
||||
BADLY_DAMAGED(s -> s.isDamaged() && s.getDamage() / s.getMaxDamage() > 3 / 4f),
|
||||
NOT_STACKABLE(Predicates.not(ItemStack::isStackable)),
|
||||
EQUIPABLE(s -> s.getEquipmentSlot() != null),
|
||||
FURNACE_FUEL(AbstractFurnaceTileEntity::isFuel);
|
||||
|
||||
private Predicate<ItemStack> test;
|
||||
|
||||
private StandardTraits(Predicate<ItemStack> test) {
|
||||
this.test = test;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean appliesTo(ItemStack stack) {
|
||||
return test.test(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemAttribute> listAttributesOf(ItemStack stack) {
|
||||
List<ItemAttribute> attributes = new ArrayList<>();
|
||||
for (StandardTraits trait : values())
|
||||
if (trait.test.test(stack))
|
||||
attributes.add(trait);
|
||||
return attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTranslationKey() {
|
||||
return Lang.asId(name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNBTKey() {
|
||||
return "standard_trait";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeNBT(CompoundNBT nbt) {
|
||||
nbt.putBoolean(name(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemAttribute readNBT(CompoundNBT nbt) {
|
||||
for (StandardTraits trait : values())
|
||||
if (nbt.contains(trait.name()))
|
||||
return trait;
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class InTag implements ItemAttribute {
|
||||
|
||||
ResourceLocation tagName;
|
||||
|
||||
public InTag(ResourceLocation tagName) {
|
||||
this.tagName = tagName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean appliesTo(ItemStack stack) {
|
||||
return stack.getItem().getTags().contains(tagName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemAttribute> listAttributesOf(ItemStack stack) {
|
||||
return stack.getItem().getTags().stream().map(InTag::new).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTranslationKey() {
|
||||
return "in_tag";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getTranslationParameters() {
|
||||
return new Object[] { "#" + tagName.toString() };
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeNBT(CompoundNBT nbt) {
|
||||
nbt.putString("space", tagName.getNamespace());
|
||||
nbt.putString("path", tagName.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemAttribute readNBT(CompoundNBT nbt) {
|
||||
return new InTag(new ResourceLocation(nbt.getString("space"), nbt.getString("path")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class InItemGroup implements ItemAttribute {
|
||||
|
||||
private ItemGroup group;
|
||||
|
||||
public InItemGroup(ItemGroup group) {
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean appliesTo(ItemStack stack) {
|
||||
Item item = stack.getItem();
|
||||
return item.getGroup() == group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemAttribute> listAttributesOf(ItemStack stack) {
|
||||
ItemGroup group = stack.getItem().getGroup();
|
||||
return group == null ? Collections.emptyList() : Arrays.asList(new InItemGroup(group));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTranslationKey() {
|
||||
return "in_item_group";
|
||||
}
|
||||
|
||||
@OnlyIn(value = Dist.CLIENT)
|
||||
public String format() {
|
||||
return Lang.translate("item_attributes." + getTranslationKey(), I18n.format(group.getTranslationKey()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeNBT(CompoundNBT nbt) {
|
||||
nbt.putString("path", group.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemAttribute readNBT(CompoundNBT nbt) {
|
||||
String readPath = nbt.getString("path");
|
||||
for (ItemGroup group : ItemGroup.GROUPS)
|
||||
if (group.getPath().equals(readPath))
|
||||
return new InItemGroup(group);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class AddedBy implements ItemAttribute {
|
||||
|
||||
private String modId;
|
||||
|
||||
public AddedBy(String modId) {
|
||||
this.modId = modId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean appliesTo(ItemStack stack) {
|
||||
return modId.equals(stack.getItem().getCreatorModId(stack));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemAttribute> listAttributesOf(ItemStack stack) {
|
||||
String id = stack.getItem().getCreatorModId(stack);
|
||||
return id == null ? Collections.emptyList() : Arrays.asList(new AddedBy(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTranslationKey() {
|
||||
return "added_by";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getTranslationParameters() {
|
||||
Optional<? extends ModContainer> modContainerById = ModList.get().getModContainerById(modId);
|
||||
String name = modContainerById.map(ModContainer::getModInfo).map(IModInfo::getDisplayName)
|
||||
.orElse(StringUtils.capitalize(modId));
|
||||
return new Object[] { name };
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeNBT(CompoundNBT nbt) {
|
||||
nbt.putString("id", modId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemAttribute readNBT(CompoundNBT nbt) {
|
||||
return new AddedBy(nbt.getString("id"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -16,6 +16,8 @@
|
|||
"item.create.belt_connector": "Mechanical Belt",
|
||||
"item.create.goggles": "Engineer's Goggles",
|
||||
"item.create.filter": "Filter",
|
||||
"item.create.property_filter": "Attribute Filter",
|
||||
"item.create.logistical_filter": "Address Filter",
|
||||
"item.create.rose_quartz": "Rose Quartz",
|
||||
"item.create.refined_rose_quartz": "Refined Rose Quartz",
|
||||
"item.create.refined_radiance_cube": "Refined Radiance",
|
||||
|
@ -406,6 +408,37 @@
|
|||
"create.gui.requester.requestedItemCount": "Requested Amount",
|
||||
"create.gui.storage.passiveModeOnly": "Item Storage is Passive only",
|
||||
|
||||
"create.gui.filter.blacklist": "Blacklist",
|
||||
"create.gui.filter.blacklist.description": "Items pass if they do NOT match any of the above. An empty Blacklist accepts everything.",
|
||||
"create.gui.filter.whitelist": "Whitelist",
|
||||
"create.gui.filter.whitelist.description": "Items pass if they match any of the above. An empty Whitelist rejects anything.",
|
||||
"create.gui.filter.respect_data": "Respect Data",
|
||||
"create.gui.filter.respect_data.description": "Items only match if their durability, enchantments and other attributes match as well.",
|
||||
"create.gui.filter.ignore_data": "Ignore Data",
|
||||
"create.gui.filter.ignore_data.description": "Items match regardless of their attributes.",
|
||||
|
||||
"create.item_attributes.placeable": "is placeable",
|
||||
"create.item_attributes.consumable": "can be eaten",
|
||||
"create.item_attributes.enchanted": "is enchanted",
|
||||
"create.item_attributes.damaged": "is damaged",
|
||||
"create.item_attributes.badly_damaged": "is heavily damaged",
|
||||
"create.item_attributes.not_stackable": "cannot stack",
|
||||
"create.item_attributes.equipable": "can be equipped",
|
||||
"create.item_attributes.furnace_fuel": "is furnace fuel",
|
||||
"create.item_attributes.in_tag": "is tagged %1$s",
|
||||
"create.item_attributes.in_item_group": "belongs to %1$s",
|
||||
"create.item_attributes.added_by": "was added by %1$s",
|
||||
|
||||
"create.gui.attribute_filter.no_selected_attributes": "No attributes selected",
|
||||
"create.gui.attribute_filter.selected_attributes": "Selected attributes:",
|
||||
"create.gui.attribute_filter.whitelist_disjunctive": "Whitelist (Any)",
|
||||
"create.gui.attribute_filter.whitelist_disjunctive.description": "Items pass if they have at least one of the selected attributes.",
|
||||
"create.gui.attribute_filter.whitelist_conjunctive": "Whitelist (All)",
|
||||
"create.gui.attribute_filter.whitelist_conjunctive.description": "Items pass only if they have ALL of the selected attributes.",
|
||||
"create.gui.attribute_filter.blacklist": "Blacklist",
|
||||
"create.gui.attribute_filter.blacklist.description": "Items pass if they do NOT have any of the selected attributes.",
|
||||
"create.gui.attribute_filter.add_reference_item": "Add Reference Item",
|
||||
|
||||
"create.tooltip.holdKey": "Hold [%1$s]",
|
||||
"create.tooltip.holdKeyOrKey": "Hold [%1$s] or [%2$s]",
|
||||
"create.tooltip.keyShift": "Shift",
|
||||
|
@ -425,6 +458,7 @@
|
|||
"create.tooltip.capacityProvided.low": "Small",
|
||||
"create.tooltip.capacityProvided.medium": "Medium",
|
||||
"create.tooltip.capacityProvided.high": "Large",
|
||||
"create.tooltip.capacityProvided.asGenerator": "(As Generator)",
|
||||
|
||||
"create.tooltip.wip": "WIP",
|
||||
"create.tooltip.workInProgress": "Work in progress!",
|
||||
|
@ -484,7 +518,21 @@
|
|||
"item.create.tree_fertilizer.tooltip.summary": "A powerful combination of minerals suitable for common tree types",
|
||||
"item.create.tree_fertilizer.tooltip.condition1": "When used on Sapling",
|
||||
"item.create.tree_fertilizer.tooltip.behaviour1": "Grows Trees regardless of their spacing Conditions",
|
||||
|
||||
|
||||
"item.create.filter.tooltip": "FILTER",
|
||||
"item.create.filter.tooltip.summary": "_Controls_ _outputs_ and inputs of logistical devices with more _precision,_ matching them against a _set_ _of_ _items_ or several _nested_ _filters._",
|
||||
"item.create.filter.tooltip.condition1": "When in filter slot",
|
||||
"item.create.filter.tooltip.behaviour1": "_Controls_ item flow according to its _configuration._",
|
||||
"item.create.filter.tooltip.condition2": "When R-Clicked",
|
||||
"item.create.filter.tooltip.behaviour2": "Opens the _configuration_ _interface._",
|
||||
|
||||
"item.create.property_filter.tooltip": "ATTRIBUTE FILTER",
|
||||
"item.create.property_filter.tooltip.summary": "_Controls_ _outputs_ and inputs of logistical devices with more _precision,_ matching them against a _set_ _of_ item _attributes_ and _categories._",
|
||||
"item.create.property_filter.tooltip.condition1": "When in filter slot",
|
||||
"item.create.property_filter.tooltip.behaviour1": "_Controls_ item flow according to its _configuration._",
|
||||
"item.create.property_filter.tooltip.condition2": "When R-Clicked",
|
||||
"item.create.property_filter.tooltip.behaviour2": "Opens the _configuration_ _interface._",
|
||||
|
||||
"block.create.cocoa_log.tooltip": "COCOA LOG",
|
||||
"block.create.cocoa_log.tooltip.summary": "An augmented jungle log allowing for easier automation of _Cocoa_ _Beans_",
|
||||
"block.create.cocoa_log.tooltip.condition1": "When Mature",
|
||||
|
@ -734,6 +782,7 @@
|
|||
"block.create.package_funnel.tooltip": "WIP",
|
||||
"block.create.logisticians_table.tooltip": "WIP",
|
||||
"item.create.logistical_dial.tooltip": "WIP",
|
||||
"item.create.logistical_filter.tooltip": "WIP",
|
||||
|
||||
"itemGroup.create": "Create"
|
||||
}
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"0": "create:block/net",
|
||||
"1": "create:block/brass_casing",
|
||||
"2": "create:block/clutch_off",
|
||||
"particle": "create:block/net"
|
||||
"0": "create:item/filter",
|
||||
"particle": "create:item/filter"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
|
@ -13,12 +11,12 @@
|
|||
"from": [13, 0, 3],
|
||||
"to": [15, 2, 13],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 6, 2, 8], "texture": "#1"},
|
||||
"east": {"uv": [3, 0, 13, 2], "texture": "#1"},
|
||||
"south": {"uv": [14, 6, 16, 8], "texture": "#1"},
|
||||
"west": {"uv": [3, 0, 13, 2], "texture": "#1"},
|
||||
"up": {"uv": [0, 3, 2, 13], "rotation": 180, "texture": "#1"},
|
||||
"down": {"uv": [14, 3, 16, 13], "texture": "#1"}
|
||||
"north": {"uv": [14, 0, 16, 2], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 2, 10], "rotation": 90, "texture": "#0"},
|
||||
"south": {"uv": [14, 0, 16, 2], "rotation": 180, "texture": "#0"},
|
||||
"west": {"uv": [14, 0, 16, 10], "rotation": 270, "texture": "#0"},
|
||||
"up": {"uv": [14, 0, 16, 10], "rotation": 180, "texture": "#0"},
|
||||
"down": {"uv": [14, 0, 16, 10], "rotation": 180, "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -26,12 +24,12 @@
|
|||
"from": [1, 0, 3],
|
||||
"to": [3, 2, 13],
|
||||
"faces": {
|
||||
"north": {"uv": [2, 6, 0, 8], "texture": "#1"},
|
||||
"east": {"uv": [13, 0, 3, 2], "texture": "#1"},
|
||||
"south": {"uv": [16, 6, 14, 8], "texture": "#1"},
|
||||
"west": {"uv": [13, 0, 3, 2], "texture": "#1"},
|
||||
"up": {"uv": [2, 3, 0, 13], "rotation": 180, "texture": "#1"},
|
||||
"down": {"uv": [16, 3, 14, 13], "texture": "#1"}
|
||||
"north": {"uv": [16, 0, 14, 2], "texture": "#0"},
|
||||
"east": {"uv": [14, 10, 16, 0], "rotation": 270, "texture": "#0"},
|
||||
"south": {"uv": [16, 0, 14, 2], "rotation": 180, "texture": "#0"},
|
||||
"west": {"uv": [0, 10, 2, 0], "rotation": 90, "texture": "#0"},
|
||||
"up": {"uv": [16, 0, 14, 10], "rotation": 180, "texture": "#0"},
|
||||
"down": {"uv": [16, 0, 14, 10], "rotation": 180, "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -39,8 +37,12 @@
|
|||
"from": [3, 1, 4],
|
||||
"to": [13, 1.1, 12],
|
||||
"faces": {
|
||||
"up": {"uv": [3.5, 4.5, 13.5, 12.5], "texture": "#0"},
|
||||
"down": {"uv": [3.5, 4.5, 13.5, 12.5], "texture": "#0"}
|
||||
"north": {"uv": [0, 0, 0, 0], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 0, 0], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 0, 0], "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 0, 0], "texture": "#0"},
|
||||
"up": {"uv": [2.5, 0.5, 12.5, 8.5], "texture": "#0"},
|
||||
"down": {"uv": [2.5, 0.5, 12.5, 8.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -48,10 +50,12 @@
|
|||
"from": [3, 0.5, 3],
|
||||
"to": [13, 1.5, 4],
|
||||
"faces": {
|
||||
"north": {"uv": [2, 7, 12, 8], "texture": "#2"},
|
||||
"south": {"uv": [3, 7, 13, 8], "texture": "#2"},
|
||||
"up": {"uv": [3, 7, 13, 8], "texture": "#2"},
|
||||
"down": {"uv": [3, 7, 13, 8], "texture": "#2"}
|
||||
"north": {"uv": [3, 9, 13, 10], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 0, 0], "texture": "#0"},
|
||||
"south": {"uv": [3, 9, 13, 10], "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 0, 0], "texture": "#0"},
|
||||
"up": {"uv": [3, 9, 13, 10], "texture": "#0"},
|
||||
"down": {"uv": [3, 9, 13, 10], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -59,10 +63,12 @@
|
|||
"from": [3, 0.5, 12],
|
||||
"to": [13, 1.5, 13],
|
||||
"faces": {
|
||||
"north": {"uv": [13, 7, 3, 8], "texture": "#2"},
|
||||
"south": {"uv": [14, 7, 4, 8], "texture": "#2"},
|
||||
"up": {"uv": [3, 8, 13, 7], "texture": "#2"},
|
||||
"down": {"uv": [3, 8, 13, 7], "texture": "#2"}
|
||||
"north": {"uv": [3, 9, 13, 10], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 0, 0], "texture": "#0"},
|
||||
"south": {"uv": [3, 9, 13, 10], "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 0, 0], "texture": "#0"},
|
||||
"up": {"uv": [3, 9, 13, 10], "texture": "#0"},
|
||||
"down": {"uv": [3, 9, 13, 10], "texture": "#0"}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -88,7 +94,7 @@
|
|||
"scale": [0.5, 0.5, 0.5]
|
||||
},
|
||||
"ground": {
|
||||
"translation": [0, 0.75, 0],
|
||||
"translation": [0, 3, 0],
|
||||
"scale": [0.5, 0.5, 0.5]
|
||||
},
|
||||
"gui": {
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"parent": "create:item/filter",
|
||||
"textures": {
|
||||
"0": "create:item/logistical_filter",
|
||||
"particle": "create:item/logistical_filter"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"parent": "create:item/filter",
|
||||
"textures": {
|
||||
"0": "create:item/property_filter",
|
||||
"particle": "create:item/property_filter"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 554 B |
BIN
src/main/resources/assets/create/textures/gui/filter.png
Normal file
After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 278 B After Width: | Height: | Size: 337 B |
Before Width: | Height: | Size: 164 B |
Before Width: | Height: | Size: 173 B |
After Width: | Height: | Size: 376 B |
After Width: | Height: | Size: 329 B |