Refactor in-world Scrollinputs

- Reworked Scollable inputs on blocks to use a unified TE behaviour & generic value box rendering
This commit is contained in:
simibubi 2020-02-18 15:08:45 +01:00
parent 81a2e314bc
commit fb046ddfb7
55 changed files with 1358 additions and 1102 deletions

View file

@ -5,17 +5,14 @@ import java.util.function.Function;
import java.util.function.Supplier;
import com.simibubi.create.foundation.behaviour.filtering.FilteringCountUpdatePacket;
import com.simibubi.create.foundation.behaviour.scrollvalue.ScrollValueUpdatePacket;
import com.simibubi.create.foundation.command.ConfigureConfigPacket;
import com.simibubi.create.foundation.packet.NbtPacket;
import com.simibubi.create.foundation.packet.SimplePacketBase;
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionStallPacket;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ConfigureChassisPacket;
import com.simibubi.create.modules.contraptions.components.mixer.ConfigureMixerPacket;
import com.simibubi.create.modules.contraptions.components.motor.ConfigureMotorPacket;
import com.simibubi.create.modules.curiosities.blockzapper.BlockzapperBeamPacket;
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.packet.ConfigureFlexcratePacket;
import com.simibubi.create.modules.logistics.packet.ConfigureStockswitchPacket;
@ -36,14 +33,11 @@ public enum AllPackets {
CONFIGURE_SCHEMATICANNON(ConfigureSchematicannonPacket.class, ConfigureSchematicannonPacket::new),
CONFIGURE_FLEXCRATE(ConfigureFlexcratePacket.class, ConfigureFlexcratePacket::new),
CONFIGURE_STOCKSWITCH(ConfigureStockswitchPacket.class, ConfigureStockswitchPacket::new),
CONFIGURE_CHASSIS(ConfigureChassisPacket.class, ConfigureChassisPacket::new),
CONFIGURE_MOTOR(ConfigureMotorPacket.class, ConfigureMotorPacket::new),
CONFIGURE_FLEXPEATER(ConfigureFlexpeaterPacket.class, ConfigureFlexpeaterPacket::new),
CONFIGURE_MIXER(ConfigureMixerPacket.class, ConfigureMixerPacket::new),
PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new),
UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new),
CONFIGURE_FILTER(FilterScreenPacket.class, FilterScreenPacket::new),
CONFIGURE_FILTERING_AMOUNT(FilteringCountUpdatePacket.class, FilteringCountUpdatePacket::new),
CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new),
// Server to Client
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new),

View file

@ -5,7 +5,7 @@ import java.util.List;
import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.foundation.behaviour.filtering.FilteringHandler;
import com.simibubi.create.foundation.block.IHaveScrollableValue;
import com.simibubi.create.foundation.behaviour.scrollvalue.ScrollValueHandler;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.item.TooltipHelper;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
@ -101,8 +101,8 @@ public class ClientEvents {
boolean cancelled = CreateClient.schematicHandler.mouseScrolled(delta)
|| CreateClient.schematicAndQuillHandler.mouseScrolled(delta)
|| IHaveScrollableValue.onScroll(delta)
|| FilteringHandler.onScroll(delta);
|| FilteringHandler.onScroll(delta)
|| ScrollValueHandler.onScroll(delta);
event.setCanceled(cancelled);
}

View file

@ -0,0 +1,33 @@
package com.simibubi.create.foundation.behaviour;
import java.util.function.BiPredicate;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
import net.minecraft.util.math.Vec3d;
public class CenteredSideValueBoxTransform extends ValueBoxTransform.Sided {
private BiPredicate<BlockState, Direction> allowedDirections;
public CenteredSideValueBoxTransform() {
this((b, d) -> true);
}
public CenteredSideValueBoxTransform(BiPredicate<BlockState, Direction> allowedDirections) {
this.allowedDirections = allowedDirections;
}
@Override
protected Vec3d getSouthLocation() {
return VecHelper.voxelSpace(8, 8, 16);
}
@Override
protected boolean isSideActive(BlockState state, Direction direction) {
return allowedDirections.test(state, direction);
}
}

View file

@ -7,6 +7,8 @@ import net.minecraft.util.math.Vec3d;
public class ValueBox {
String label = "Value Box";
String sublabel = "";
String scrollTooltip = "";
Vec3d labelOffset = Vec3d.ZERO;
int passiveColor;
int highlightColor;
@ -22,6 +24,16 @@ public class ValueBox {
return this;
}
public ValueBox subLabel(String sublabel) {
this.sublabel = sublabel;
return this;
}
public ValueBox scrollTooltip(String scrollTip) {
this.scrollTooltip = scrollTip;
return this;
}
public ValueBox withColors(int passive, int highlight) {
this.passiveColor = passive;
this.highlightColor = highlight;
@ -40,4 +52,14 @@ public class ValueBox {
}
public static class TextValueBox extends ValueBox {
String text;
public TextValueBox(String label, AxisAlignedBB bb, String text) {
super(label, bb);
this.text = text;
}
}
}

View file

@ -2,6 +2,7 @@ package com.simibubi.create.foundation.behaviour;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.foundation.behaviour.ValueBox.ItemValueBox;
import com.simibubi.create.foundation.behaviour.ValueBox.TextValueBox;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.modules.contraptions.relays.elementary.ShaftBlock;
@ -52,23 +53,30 @@ public class ValueBoxRenderer {
float fontScale = -1 / 64f;
Vec3d shift = box.labelOffset;
GlStateManager.scaled(fontScale, fontScale, fontScale);
GlStateManager.translated(17.5f, -5f, 7f);
GlStateManager.translated(shift.x, shift.y, shift.z);
GlStateManager.rotated(0, 1, 0, 0);
FontRenderer font = Minecraft.getInstance().fontRenderer;
GlStateManager.scaled(fontScale, fontScale, fontScale);
if (highlighted) {
String text = box.label;
font.drawString(text, 0, 0, box.highlightColor);
GlStateManager.translated(0, 0, -1 / 4f);
font.drawString(text, 1, 1, ColorHelper.mixColors(box.passiveColor, 0, 0.75f));
GlStateManager.translated(0, 0, 1 / 4f);
GlStateManager.pushMatrix();
GlStateManager.translated(17.5f, -5f, 7f);
GlStateManager.translated(shift.x, shift.y, shift.z);
// GlStateManager.rotated(0, 1, 0, 0);
renderText(box, font, box.label);
if (!box.sublabel.isEmpty()) {
GlStateManager.translated(0, 10, 0);
renderText(box, font, box.sublabel);
}
if (!box.scrollTooltip.isEmpty()) {
GlStateManager.translated(0, 10, 0);
renderText(font, box.scrollTooltip, 0x998899, 0x111111);
}
GlStateManager.popMatrix();
}
if (box instanceof ItemValueBox) {
ItemValueBox itemValueBox = (ItemValueBox) box;
String count = itemValueBox.count == 0 ? "*" : itemValueBox.count + "";
GlStateManager.translated(17.5f, -5f, 7f);
boolean isFilter = itemValueBox.stack.getItem() instanceof FilterItem;
if (isFilter)
@ -77,11 +85,44 @@ public class ValueBoxRenderer {
GlStateManager.translated(-7 - font.getStringWidth(count), 10, 10 + 1 / 4f);
double scale = 1.5;
GlStateManager.rotated(0, 1, 0, 0);
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);
}
if (box instanceof TextValueBox) {
double scale = 4;
GlStateManager.scaled(scale, scale, 1);
GlStateManager.translated(-4, -4, 5);
String text = ((TextValueBox) box).text;
int stringWidth = font.getStringWidth(text);
float numberScale = (float) font.FONT_HEIGHT / stringWidth;
boolean singleDigit = stringWidth < 10;
if (singleDigit)
numberScale = numberScale / 2;
float verticalMargin = (stringWidth - font.FONT_HEIGHT) / 2f;
GlStateManager.scaled(numberScale, numberScale, numberScale);
GlStateManager.translated(singleDigit ? stringWidth / 2 : 0, singleDigit ? -verticalMargin : verticalMargin,
0);
renderText(font, text, 0xEDEDED, 0x4f4f4f);
}
}
public static void renderText(ValueBox box, FontRenderer font, String text) {
renderText(font, text, box.highlightColor, ColorHelper.mixColors(box.passiveColor, 0, 0.75f));
}
public static void renderText(FontRenderer font, String text, int color, int shadowColor) {
font.drawString(text, 0, 0, color);
GlStateManager.translated(0, 0, -1 / 4f);
font.drawString(text, 1, 1, shadowColor);
GlStateManager.translated(0, 0, 1 / 4f);
}
public static void renderItemIntoValueBox(ItemStack filter) {

View file

@ -0,0 +1,121 @@
package com.simibubi.create.foundation.behaviour;
import java.util.function.Function;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.GlHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.Vec3d;
public abstract class ValueBoxTransform {
protected float scale = getScale();
protected abstract Vec3d getLocation(BlockState state);
protected abstract Vec3d getOrientation(BlockState state);
public boolean testHit(BlockState state, Vec3d localHit) {
Vec3d offset = getLocation(state);
if (offset == null)
return false;
return localHit.distanceTo(offset) < scale / 2;
}
public void renderTransformed(BlockState state, Runnable render) {
Vec3d position = getLocation(state);
Vec3d rotation = getOrientation(state);
GlHelper.renderTransformed(position, rotation, scale, render);
}
protected Vec3d rotateHorizontally(BlockState state, Vec3d vec) {
float yRot = 0;
if (state.has(BlockStateProperties.FACING))
yRot = AngleHelper.horizontalAngle(state.get(BlockStateProperties.FACING));
if (state.has(BlockStateProperties.HORIZONTAL_FACING))
yRot = AngleHelper.horizontalAngle(state.get(BlockStateProperties.HORIZONTAL_FACING));
return VecHelper.rotateCentered(vec, yRot, Axis.Y);
}
protected float getScale() {
return .4f;
}
public static abstract class Dual extends ValueBoxTransform {
protected boolean first;
public Dual(boolean first) {
this.first = first;
}
public boolean isFirst() {
return first;
}
public static Pair<ValueBoxTransform, ValueBoxTransform> makeSlots(Function<Boolean, ? extends Dual> factory) {
return Pair.of(factory.apply(true), factory.apply(false));
}
public boolean testHit(BlockState state, Vec3d localHit) {
Vec3d offset = getLocation(state);
if (offset == null)
return false;
return localHit.distanceTo(offset) < scale / 3.5f;
}
}
public static abstract class Sided extends ValueBoxTransform {
Direction direction = Direction.UP;
public Sided fromSide(Direction direction) {
this.direction = direction;
return this;
}
@Override
protected Vec3d getLocation(BlockState state) {
Vec3d location = getSouthLocation();
location = VecHelper.rotateCentered(location, AngleHelper.horizontalAngle(direction), Axis.Y);
location = VecHelper.rotateCentered(location, AngleHelper.verticalAngle(direction), Axis.Z);
return location;
}
protected abstract Vec3d getSouthLocation();
@Override
protected Vec3d getOrientation(BlockState state) {
float yRot = AngleHelper.horizontalAngle(direction) + 180;
float zRot = direction == Direction.UP ? 90 : direction == Direction.DOWN ? 270 : 0;
return new Vec3d(0, yRot, zRot);
}
@Override
public void renderTransformed(BlockState state, Runnable render) {
if (!isSideActive(state, direction))
return;
super.renderTransformed(state, render);
}
@Override
public boolean testHit(BlockState state, Vec3d localHit) {
return isSideActive(state, direction) && super.testHit(state, localHit);
}
protected boolean isSideActive(BlockState state, Direction direction) {
return true;
}
}
}

View file

@ -1,9 +1,9 @@
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.ValueBoxTransform;
import com.simibubi.create.foundation.behaviour.base.IBehaviourType;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
@ -22,7 +22,7 @@ public class FilteringBehaviour extends TileEntityBehaviour {
public static IBehaviourType<FilteringBehaviour> TYPE = new IBehaviourType<FilteringBehaviour>() {
};
SlotPositioning slotPositioning;
ValueBoxTransform slotPositioning;
boolean showCount;
Vec3d textShift;
@ -34,10 +34,10 @@ public class FilteringBehaviour extends TileEntityBehaviour {
int ticksUntilScrollPacket;
boolean forceClientState;
public FilteringBehaviour(SmartTileEntity te) {
public FilteringBehaviour(SmartTileEntity te, ValueBoxTransform slot) {
super(te);
filter = ItemStack.EMPTY;
slotPositioning = new SlotPositioning(state -> Vec3d.ZERO, state -> Vec3d.ZERO);
slotPositioning = slot;
showCount = false;
callback = stack -> {
};
@ -95,11 +95,6 @@ public class FilteringBehaviour extends TileEntityBehaviour {
return this;
}
public FilteringBehaviour withSlotPositioning(SlotPositioning mapping) {
this.slotPositioning = mapping;
return this;
}
public FilteringBehaviour showCount() {
showCount = true;
return this;
@ -160,11 +155,8 @@ public class FilteringBehaviour extends TileEntityBehaviour {
public boolean testHit(Vec3d hit) {
BlockState state = tileEntity.getBlockState();
Vec3d offset = slotPositioning.offset.apply(state);
if (offset == null)
return false;
Vec3d localHit = hit.subtract(new Vec3d(tileEntity.getPos()));
return localHit.distanceTo(offset) < slotPositioning.scale / 2;
return slotPositioning.testHit(state, localHit);
}
public int getAmount() {
@ -175,23 +167,4 @@ public class FilteringBehaviour extends TileEntityBehaviour {
return count == 0;
}
public static class SlotPositioning {
Function<BlockState, Vec3d> offset;
Function<BlockState, Vec3d> rotation;
float scale;
public SlotPositioning(Function<BlockState, Vec3d> offsetForState,
Function<BlockState, Vec3d> rotationForState) {
offset = offsetForState;
rotation = rotationForState;
scale = 1;
}
public SlotPositioning scale(float scale) {
this.scale = scale;
return this;
}
}
}

View file

@ -6,8 +6,6 @@ import com.simibubi.create.foundation.behaviour.ValueBox.ItemValueBox;
import com.simibubi.create.foundation.behaviour.ValueBoxRenderer;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour.SlotPositioning;
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;
@ -49,16 +47,18 @@ public class FilteringRenderer {
TessellatorHelper.prepareForDrawing();
GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ());
SlotPositioning slotPositioning = behaviour.slotPositioning;
renderTransformed(state, slotPositioning, () -> {
behaviour.slotPositioning.renderTransformed(state, () -> {
AxisAlignedBB bb = new AxisAlignedBB(Vec3d.ZERO, Vec3d.ZERO).grow(.25f);
String label = Lang.translate("logistics.filter");
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);
boolean showCount = behaviour.isCountVisible();
ValueBox box =
showCount ? new ItemValueBox(label, bb, filter, behaviour.scrollableValue) : new ValueBox(label, bb);
if (showCount)
box.scrollTooltip("[" + Lang.translate("action.scroll") + "]");
box.offsetLabel(behaviour.textShift).withColors(0x7777BB, 0xCCBBFF);
ValueBoxRenderer.renderBox(box, behaviour.testHit(target.getHitVec()));
@ -79,24 +79,15 @@ public class FilteringRenderer {
return;
BlockState state = tileEntityIn.getBlockState();
SlotPositioning slotPositioning = behaviour.slotPositioning;
TessellatorHelper.prepareForDrawing();
BlockPos pos = tileEntityIn.getPos();
GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ());
renderTransformed(state, slotPositioning, () -> {
behaviour.slotPositioning.renderTransformed(state, () -> {
ValueBoxRenderer.renderItemIntoValueBox(behaviour.getFilter());
});
TessellatorHelper.cleanUpAfterDrawing();
}
private static void renderTransformed(BlockState state, SlotPositioning positioning, Runnable render) {
Vec3d position = positioning.offset.apply(state);
Vec3d rotation = positioning.rotation.apply(state);
float scale = positioning.scale;
GlHelper.renderTransformed(position, rotation, scale, render);
}
}

View file

@ -7,6 +7,7 @@ import java.util.function.Supplier;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.behaviour.base.IBehaviourType;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
@ -29,40 +30,39 @@ public class LinkBehaviour extends TileEntityBehaviour {
Frequency frequencyFirst;
Frequency frequencyLast;
SlotPositioning slotPositioning;
ValueBoxTransform firstSlot;
ValueBoxTransform secondSlot;
Vec3d textShift;
private Mode mode;
private Supplier<Boolean> transmission;
private Consumer<Boolean> signalCallback;
protected LinkBehaviour(SmartTileEntity te) {
protected LinkBehaviour(SmartTileEntity te, Pair<ValueBoxTransform, ValueBoxTransform> slots) {
super(te);
slotPositioning = new SlotPositioning(state -> Pair.of(Vec3d.ZERO, Vec3d.ZERO), state -> Vec3d.ZERO);
frequencyFirst = new Frequency(ItemStack.EMPTY);
frequencyLast = new Frequency(ItemStack.EMPTY);
firstSlot = slots.getLeft();
secondSlot = slots.getRight();
textShift = Vec3d.ZERO;
}
public static LinkBehaviour receiver(SmartTileEntity te, Consumer<Boolean> signalCallback) {
LinkBehaviour behaviour = new LinkBehaviour(te);
public static LinkBehaviour receiver(SmartTileEntity te, Pair<ValueBoxTransform, ValueBoxTransform> slots,
Consumer<Boolean> signalCallback) {
LinkBehaviour behaviour = new LinkBehaviour(te, slots);
behaviour.signalCallback = signalCallback;
behaviour.mode = Mode.RECEIVE;
return behaviour;
}
public static LinkBehaviour transmitter(SmartTileEntity te, Supplier<Boolean> transmission) {
LinkBehaviour behaviour = new LinkBehaviour(te);
public static LinkBehaviour transmitter(SmartTileEntity te, Pair<ValueBoxTransform, ValueBoxTransform> slots,
Supplier<Boolean> transmission) {
LinkBehaviour behaviour = new LinkBehaviour(te, slots);
behaviour.transmission = transmission;
behaviour.mode = Mode.TRANSMIT;
return behaviour;
}
public LinkBehaviour withSlotPositioning(SlotPositioning mapping) {
this.slotPositioning = mapping;
return this;
}
public LinkBehaviour moveText(Vec3d shift) {
textShift = shift;
return this;
@ -129,8 +129,8 @@ public class LinkBehaviour extends TileEntityBehaviour {
stack = stack.copy();
stack.setCount(1);
ItemStack toCompare = first ? frequencyFirst.getStack() : frequencyLast.getStack();
boolean changed = !ItemStack.areItemsEqual(stack, toCompare)
|| !ItemStack.areItemStackTagsEqual(stack, toCompare);
boolean changed =
!ItemStack.areItemsEqual(stack, toCompare) || !ItemStack.areItemStackTagsEqual(stack, toCompare);
if (changed)
getHandler().removeFromNetwork(this);
@ -177,12 +177,8 @@ public class LinkBehaviour extends TileEntityBehaviour {
public boolean testHit(Boolean first, Vec3d hit) {
BlockState state = tileEntity.getBlockState();
Pair<Vec3d, Vec3d> pair = slotPositioning.offsets.apply(state);
Vec3d offset = first ? pair.getKey() : pair.getValue();
if (offset == null)
return false;
Vec3d localHit = hit.subtract(new Vec3d(tileEntity.getPos()));
return localHit.distanceTo(offset) < slotPositioning.scale / 3.5f;
return (first ? firstSlot : secondSlot).testHit(state, localHit);
}
}

View file

@ -2,15 +2,11 @@ package com.simibubi.create.foundation.behaviour.linked;
import java.util.function.Consumer;
import org.apache.commons.lang3.tuple.Pair;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.foundation.behaviour.ValueBox;
import com.simibubi.create.foundation.behaviour.ValueBoxRenderer;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.linked.LinkBehaviour.SlotPositioning;
import com.simibubi.create.foundation.utility.GlHelper;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.TessellatorHelper;
@ -48,11 +44,10 @@ public class LinkRenderer {
TessellatorHelper.prepareForDrawing();
GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ());
SlotPositioning slotPositioning = behaviour.slotPositioning;
String freq1 = Lang.translate("logistics.firstFrequency");
String freq2 = Lang.translate("logistics.secondFrequency");
renderEachSlot(state, slotPositioning, first -> {
renderEachSlot(state, behaviour, first -> {
AxisAlignedBB bb = new AxisAlignedBB(Vec3d.ZERO, Vec3d.ZERO).grow(.25f);
String label = first ? freq2 : freq1;
ValueBox box = new ValueBox(label, bb).withColors(0x992266, 0xFF55AA).offsetLabel(behaviour.textShift);
@ -72,13 +67,11 @@ public class LinkRenderer {
return;
BlockState state = tileEntityIn.getBlockState();
SlotPositioning slotPositioning = behaviour.slotPositioning;
TessellatorHelper.prepareForDrawing();
BlockPos pos = tileEntityIn.getPos();
GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ());
renderEachSlot(state, slotPositioning, first -> {
renderEachSlot(state, behaviour, first -> {
ValueBoxRenderer.renderItemIntoValueBox(
first ? behaviour.frequencyFirst.getStack() : behaviour.frequencyLast.getStack());
});
@ -86,13 +79,9 @@ public class LinkRenderer {
TessellatorHelper.cleanUpAfterDrawing();
}
private static void renderEachSlot(BlockState state, SlotPositioning positioning, Consumer<Boolean> render) {
Pair<Vec3d, Vec3d> position = positioning.offsets.apply(state);
Vec3d rotation = positioning.rotation.apply(state);
float scale = positioning.scale;
GlHelper.renderTransformed(position.getKey(), rotation, scale, () -> render.accept(true));
GlHelper.renderTransformed(position.getValue(), rotation, scale, () -> render.accept(false));
private static void renderEachSlot(BlockState state, LinkBehaviour behaviour, Consumer<Boolean> render) {
behaviour.firstSlot.renderTransformed(state, () -> render.accept(true));
behaviour.secondSlot.renderTransformed(state, () -> render.accept(false));
}
}

View file

@ -0,0 +1,171 @@
package com.simibubi.create.foundation.behaviour.scrollvalue;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import com.simibubi.create.AllPackets;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
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 net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
public class ScrollValueBehaviour extends TileEntityBehaviour {
public static IBehaviourType<ScrollValueBehaviour> TYPE = new IBehaviourType<ScrollValueBehaviour>() {
};
ValueBoxTransform slotPositioning;
Vec3d textShift;
int min = 0;
int max = 1;
public int value;
int scrollableValue;
int ticksUntilScrollPacket;
boolean forceClientState;
String label;
Consumer<Integer> callback;
Function<Integer, String> formatter;
Function<Integer, String> unit;
BiFunction<Integer, Boolean, Integer> step;
boolean needsWrench;
public ScrollValueBehaviour(String label, SmartTileEntity te, ValueBoxTransform slot) {
super(te);
this.setLabel(label);
slotPositioning = slot;
callback = i -> {
};
textShift = Vec3d.ZERO;
formatter = i -> Integer.toString(i);
step = (i, b) -> 1;
value = 0;
ticksUntilScrollPacket = -1;
}
@Override
public void writeNBT(CompoundNBT nbt) {
nbt.putInt("ScrollValue", value);
super.writeNBT(nbt);
}
@Override
public void readNBT(CompoundNBT nbt) {
value = nbt.getInt("ScrollValue");
if (nbt.contains("ForceScrollable")) {
ticksUntilScrollPacket = -1;
scrollableValue = value;
}
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 ScrollValueUpdatePacket(getPos(), scrollableValue));
ticksUntilScrollPacket = -1;
}
public ScrollValueBehaviour withCallback(Consumer<Integer> valueCallback) {
callback = valueCallback;
return this;
}
public ScrollValueBehaviour between(int min, int max) {
this.min = min;
this.max = max;
return this;
}
public ScrollValueBehaviour moveText(Vec3d shift) {
textShift = shift;
return this;
}
public ScrollValueBehaviour requiresWrench() {
this.needsWrench = true;
return this;
}
public ScrollValueBehaviour withFormatter(Function<Integer, String> formatter) {
this.formatter = formatter;
return this;
}
public ScrollValueBehaviour withUnit(Function<Integer, String> unit) {
this.unit = unit;
return this;
}
public ScrollValueBehaviour withStepFunction(BiFunction<Integer, Boolean, Integer> step) {
this.step = step;
return this;
}
@Override
public void initialize() {
super.initialize();
setValue(value);
scrollableValue = value;
}
public void setValue(int value) {
value = MathHelper.clamp(value, min, max);
if (value == this.value)
return;
this.value = value;
forceClientState = true;
callback.accept(value);
tileEntity.markDirty();
tileEntity.sendData();
}
public int getValue() {
return value;
}
public String formatValue() {
return formatter.apply(scrollableValue);
}
@Override
public IBehaviourType<?> getType() {
return TYPE;
}
public boolean testHit(Vec3d hit) {
BlockState state = tileEntity.getBlockState();
Vec3d localHit = hit.subtract(new Vec3d(tileEntity.getPos()));
return slotPositioning.testHit(state, localHit);
}
public void setLabel(String label) {
this.label = label;
}
}

View file

@ -0,0 +1,52 @@
package com.simibubi.create.foundation.behaviour.scrollvalue;
import com.simibubi.create.AllItems;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform.Sided;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import net.minecraft.client.Minecraft;
import net.minecraft.client.world.ClientWorld;
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.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber
public class ScrollValueHandler {
@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();
ScrollValueBehaviour scrolling = TileEntityBehaviour.get(world, blockPos, ScrollValueBehaviour.TYPE);
if (scrolling == null)
return false;
if (!mc.player.isAllowEdit())
return false;
if (scrolling.needsWrench && !AllItems.WRENCH.typeOf(mc.player.getHeldItemMainhand()))
return false;
if (scrolling.slotPositioning instanceof Sided)
((Sided) scrolling.slotPositioning).fromSide(result.getFace());
if (!scrolling.testHit(objectMouseOver.getHitVec()))
return false;
scrolling.ticksUntilScrollPacket = 10;
scrolling.scrollableValue = (int) MathHelper.clamp(
scrolling.scrollableValue
+ Math.signum(delta) * scrolling.step.apply(scrolling.scrollableValue, delta > 0),
scrolling.min, scrolling.max);
return true;
}
}

View file

@ -0,0 +1,68 @@
package com.simibubi.create.foundation.behaviour.scrollvalue;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllItems;
import com.simibubi.create.foundation.behaviour.ValueBox;
import com.simibubi.create.foundation.behaviour.ValueBox.TextValueBox;
import com.simibubi.create.foundation.behaviour.ValueBoxRenderer;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform.Sided;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber(value = Dist.CLIENT)
public class ScrollValueRenderer {
@SubscribeEvent
public static void renderBlockHighlight(DrawBlockHighlightEvent event) {
RayTraceResult target = event.getTarget();
if (target == null || !(target instanceof BlockRayTraceResult))
return;
BlockRayTraceResult result = (BlockRayTraceResult) target;
ClientWorld world = Minecraft.getInstance().world;
BlockPos pos = result.getPos();
BlockState state = world.getBlockState(pos);
ScrollValueBehaviour behaviour = TileEntityBehaviour.get(world, pos, ScrollValueBehaviour.TYPE);
if (behaviour == null)
return;
if (behaviour.needsWrench && !AllItems.WRENCH.typeOf(Minecraft.getInstance().player.getHeldItemMainhand()))
return;
TessellatorHelper.prepareForDrawing();
GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ());
if (behaviour.slotPositioning instanceof Sided)
((Sided) behaviour.slotPositioning).fromSide(result.getFace());
behaviour.slotPositioning.renderTransformed(state, () -> {
AxisAlignedBB bb =
new AxisAlignedBB(Vec3d.ZERO, Vec3d.ZERO).grow(.5f).contract(0, 0, -.5f).offset(0, 0, -.125f);
String label = behaviour.label;
ValueBox box = new TextValueBox(label, bb, behaviour.formatValue());
if (behaviour.unit != null)
box.subLabel("(" + behaviour.unit.apply(behaviour.scrollableValue) + ")");
box.scrollTooltip("[" + Lang.translate("action.scroll") + "]");
box.offsetLabel(behaviour.textShift.add(20, -10, 0)).withColors(0xbe970b, 0xffe75e);
ValueBoxRenderer.renderBox(box, behaviour.testHit(target.getHitVec()));
});
TessellatorHelper.cleanUpAfterDrawing();
}
}

View file

@ -0,0 +1,41 @@
package com.simibubi.create.foundation.behaviour.scrollvalue;
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 ScrollValueUpdatePacket extends TileEntityConfigurationPacket<SmartTileEntity> {
int value;
public ScrollValueUpdatePacket(PacketBuffer buffer) {
super(buffer);
}
public ScrollValueUpdatePacket(BlockPos pos, int amount) {
super(pos);
this.value = amount;
}
@Override
protected void writeSettings(PacketBuffer buffer) {
buffer.writeInt(value);
}
@Override
protected void readSettings(PacketBuffer buffer) {
value = buffer.readInt();
}
@Override
protected void applySettings(SmartTileEntity te) {
ScrollValueBehaviour behaviour = TileEntityBehaviour.get(te, ScrollValueBehaviour.TYPE);
if (behaviour == null)
return;
behaviour.setValue(value);
}
}

View file

@ -1,223 +0,0 @@
package com.simibubi.create.foundation.block;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllItems;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.IWorld;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber(value = Dist.CLIENT)
public interface IHaveScrollableValue {
public static final AxisAlignedBB VALUE_BB = new AxisAlignedBB(0, 0, 0, 2 / 16f, 6 / 16f, 6 / 16f);
public int getCurrentValue(BlockState state, IWorld world, BlockPos pos);
public void onScroll(BlockState state, IWorld world, BlockPos pos, double delta);
public String getValueName(BlockState state, IWorld world, BlockPos pos);
public Vec3d getValueBoxPosition(BlockState state, IWorld world, BlockPos pos);
public Direction getValueBoxDirection(BlockState state, IWorld world, BlockPos pos);
public default boolean isValueOnMultipleFaces() {
return false;
}
public default boolean requiresWrench() {
return false;
}
public default boolean isValueOnFace(Direction face) {
return true;
}
public default String getValueSuffix(BlockState state, IWorld world, BlockPos pos) {
return "";
}
@SubscribeEvent
@OnlyIn(Dist.CLIENT)
public static void onDrawBlockHighlight(DrawBlockHighlightEvent event) {
if (event.getTarget() == null || !(event.getTarget() instanceof BlockRayTraceResult))
return;
BlockRayTraceResult result = (BlockRayTraceResult) event.getTarget();
Minecraft mc = Minecraft.getInstance();
ClientWorld world = mc.world;
BlockPos blockPos = result.getPos();
BlockState state = world.getBlockState(blockPos);
if (!(state.getBlock() instanceof IHaveScrollableValue))
return;
if (!mc.player.isAllowEdit())
return;
IHaveScrollableValue block = (IHaveScrollableValue) state.getBlock();
Vec3d pos = new Vec3d(blockPos);
if (block.requiresWrench() && !AllItems.WRENCH.typeOf(mc.player.getHeldItemMainhand()))
return;
Vec3d valueBoxPosition = block.getValueBoxPosition(state, world, blockPos);
AxisAlignedBB bb = VALUE_BB.offset(valueBoxPosition);
bb = bb.grow(1 / 128f);
Direction facing = block.isValueOnMultipleFaces() ? result.getFace()
: block.getValueBoxDirection(state, world, blockPos);
if (block.isValueOnMultipleFaces() && !block.isValueOnFace(result.getFace()))
return;
Vec3d cursor = result.getHitVec().subtract(VecHelper.getCenterOf(blockPos));
cursor = VecHelper.rotate(cursor, facing.getHorizontalAngle() + 90, Axis.Y);
cursor = VecHelper.rotate(cursor, facing == Direction.UP ? -90 : facing == Direction.DOWN ? 90 : 0, Axis.Z)
.add(.5, .5, .5);
boolean contains = bb.contains(cursor);
TessellatorHelper.prepareForDrawing();
GlStateManager.enableBlend();
GlStateManager.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA,
GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE,
GlStateManager.DestFactor.ZERO);
GlStateManager.disableTexture();
GlStateManager.depthMask(false);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
bufferbuilder.begin(3, DefaultVertexFormats.POSITION_COLOR);
GlStateManager.translated(pos.x, pos.y, pos.z);
GlStateManager.translated(.5f, .5f, .5f);
GlStateManager.rotated(-facing.getHorizontalAngle() - 90, 0, 1, 0);
GlStateManager.rotated(facing == Direction.UP ? 90 : facing == Direction.DOWN ? -90 : 0, 0, 0, 1);
GlStateManager.translated(-.5f, -.5f, -.5f);
GlStateManager.pushMatrix();
if (contains) {
GlStateManager.lineWidth(2);
WorldRenderer.drawBoundingBox(bufferbuilder, bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ, 1, .5f,
.75f, 1f);
} else {
GlStateManager.lineWidth(2);
WorldRenderer.drawBoundingBox(bufferbuilder, bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ, .5f,
.25f, .35f, 1f);
}
tessellator.draw();
GlStateManager.popMatrix();
GlStateManager.enableTexture();
GlStateManager.depthMask(true);
float textScale = 1 / 128f;
GlStateManager.rotated(90, 0, 1, 0);
GlStateManager.translated(1 - valueBoxPosition.z - bb.getZSize(), valueBoxPosition.y + bb.getYSize(),
valueBoxPosition.x);
GlStateManager.translated(-1, 0, 3 / 32f);
if (contains) {
GlStateManager.pushMatrix();
GlStateManager.translated(bb.getZSize() + 1 / 32f, -1 / 16f, 0);
GlStateManager.scaled(textScale, -textScale, textScale);
String text = block.getValueName(state, world, blockPos);
mc.fontRenderer.drawString(text, 0, 0, 0xFF88BB);
GlStateManager.translated(0, 0, -1 / 4f);
mc.fontRenderer.drawString(text, 1, 1, 0x224433);
GlStateManager.translated(0, 0, 1 / 4f);
text = TextFormatting.ITALIC + "<" + Lang.translate("action.scroll") + ">";
mc.fontRenderer.drawString(text, 0, 10, 0xCCBBCC);
GlStateManager.translated(0, 0, -1 / 4f);
mc.fontRenderer.drawString(text, 1, 11, 0x111111);
GlStateManager.translated(0, 0, 1 / 4f);
GlStateManager.popMatrix();
}
String numberText = block.getCurrentValue(state, world, blockPos)
+ block.getValueSuffix(state, world, blockPos);
int stringWidth = mc.fontRenderer.getStringWidth(numberText);
float numberScale = 4 / 128f * ((float) mc.fontRenderer.FONT_HEIGHT / stringWidth);
boolean singleDigit = stringWidth < 10;
if (singleDigit)
numberScale = numberScale / 2;
GlStateManager.translated(4 / 64f, -5 / 64f, 0);
GlStateManager.scaled(numberScale, -numberScale, numberScale);
float verticalMargin = (stringWidth - mc.fontRenderer.FONT_HEIGHT) / 2f;
GlStateManager.translated(singleDigit ? stringWidth / 2 : 0, singleDigit ? -verticalMargin : verticalMargin, 0);
mc.fontRenderer.drawString(numberText, 0, 0, 0xFFFFFF);
GlStateManager.translated(0, 0, -1 / 4f);
mc.fontRenderer.drawString(numberText, 1, 1, 0x224433);
GlStateManager.disableBlend();
GlStateManager.lineWidth(1);
TessellatorHelper.cleanUpAfterDrawing();
}
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();
BlockState state = world.getBlockState(blockPos);
if (!(state.getBlock() instanceof IHaveScrollableValue))
return false;
if (!mc.player.isAllowEdit())
return false;
IHaveScrollableValue block = (IHaveScrollableValue) state.getBlock();
if (block.requiresWrench() && !AllItems.WRENCH.typeOf(mc.player.getHeldItemMainhand()))
return false;
Vec3d valueBoxPosition = block.getValueBoxPosition(state, world, blockPos);
AxisAlignedBB bb = VALUE_BB.offset(valueBoxPosition);
bb = bb.grow(1 / 128f);
Direction facing = block.isValueOnMultipleFaces() ? result.getFace()
: block.getValueBoxDirection(state, world, blockPos);
Vec3d cursor = result.getHitVec().subtract(VecHelper.getCenterOf(blockPos));
cursor = VecHelper.rotate(cursor, facing.getHorizontalAngle() + 90, Axis.Y);
cursor = VecHelper.rotate(cursor, facing == Direction.UP ? -90 : facing == Direction.DOWN ? 90 : 0, Axis.Z)
.add(.5, .5, .5);
if (!bb.contains(cursor))
return false;
block.onScroll(state, world, blockPos, delta);
return true;
}
}

View file

@ -3,9 +3,6 @@ package com.simibubi.create.modules.contraptions.components.contraptions.chassis
import java.util.List;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.foundation.block.IHaveScrollableValue;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@ -23,14 +20,10 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraftforge.common.Tags;
public abstract class AbstractChassisBlock extends RotatedPillarBlock
implements IWithTileEntity<ChassisTileEntity>, IHaveScrollableValue {
private static final Vec3d valuePos = new Vec3d(15 / 16f, 9 / 16f, 9 / 16f);
public abstract class AbstractChassisBlock extends RotatedPillarBlock {
public AbstractChassisBlock(Properties properties) {
super(properties);
@ -81,34 +74,6 @@ public abstract class AbstractChassisBlock extends RotatedPillarBlock
public abstract BooleanProperty getGlueableSide(BlockState state, Direction face);
@Override
public int getCurrentValue(BlockState state, IWorld world, BlockPos pos) {
ChassisTileEntity tileEntity = (ChassisTileEntity) world.getTileEntity(pos);
if (tileEntity == null)
return 0;
return tileEntity.getRange();
}
@Override
public String getValueName(BlockState state, IWorld world, BlockPos pos) {
return Lang.translate("generic.range");
}
@Override
public boolean requiresWrench() {
return true;
}
@Override
public Vec3d getValueBoxPosition(BlockState state, IWorld world, BlockPos pos) {
return valuePos;
}
@Override
public Direction getValueBoxDirection(BlockState state, IWorld world, BlockPos pos) {
return null;
}
@Override
public List<ItemStack> getDrops(BlockState state, net.minecraft.world.storage.loot.LootContext.Builder builder) {
@SuppressWarnings("deprecation")
@ -121,14 +86,4 @@ public abstract class AbstractChassisBlock extends RotatedPillarBlock
return drops;
}
@Override
public boolean isValueOnMultipleFaces() {
return true;
}
@Override
public void onScroll(BlockState state, IWorld world, BlockPos pos, double value) {
withTileEntityDo(world, pos, te -> te.setRangeLazily((int) (te.getRange() + value)));
}
}

View file

@ -1,65 +1,42 @@
package com.simibubi.create.modules.contraptions.components.contraptions.chassis;
import com.simibubi.create.AllPackets;
import java.util.List;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.foundation.block.SyncedTileEntity;
import com.simibubi.create.foundation.behaviour.CenteredSideValueBoxTransform;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.scrollvalue.ScrollValueBehaviour;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.util.math.MathHelper;
public class ChassisTileEntity extends SmartTileEntity {
public class ChassisTileEntity extends SyncedTileEntity implements ITickableTileEntity {
private int range;
public int newRange;
public int lastModified;
ScrollValueBehaviour range;
public ChassisTileEntity() {
super(AllTileEntities.CHASSIS.type);
newRange = range = AllConfigs.SERVER.kinetics.maxChassisRange.get() / 2;
}
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.putInt("Range", range);
return super.write(compound);
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
int max = AllConfigs.SERVER.kinetics.maxChassisRange.get();
range = new ScrollValueBehaviour(Lang.translate("generic.range"), this, new CenteredSideValueBoxTransform());
range.requiresWrench();
range.between(1, max);
range.value = max / 2;
behaviours.add(range);
}
@Override
public void read(CompoundNBT compound) {
newRange = range = compound.getInt("Range");
super.read(compound);
public void initialize() {
super.initialize();
if (getBlockState().getBlock() instanceof RadialChassisBlock)
range.setLabel(Lang.translate("generic.radius"));
}
public int getRange() {
if (world.isRemote)
return newRange;
return range;
}
public void setRange(int range) {
this.range = range;
sendData();
}
public void setRangeLazily(int range) {
this.newRange = MathHelper.clamp(range, 1, AllConfigs.SERVER.kinetics.maxChassisRange.get());
if (newRange == this.range)
return;
this.lastModified = 0;
}
@Override
public void tick() {
if (!world.isRemote)
return;
if (lastModified == -1)
return;
if (lastModified++ > 10) {
lastModified = -1;
AllPackets.channel.sendToServer(new ConfigureChassisPacket(pos, newRange));
}
return range.getValue();
}
}

View file

@ -1,38 +0,0 @@
package com.simibubi.create.modules.contraptions.components.contraptions.chassis;
import com.simibubi.create.foundation.packet.TileEntityConfigurationPacket;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
public class ConfigureChassisPacket extends TileEntityConfigurationPacket<ChassisTileEntity> {
private int range;
public ConfigureChassisPacket(BlockPos pos, int range) {
super(pos);
this.range = range;
}
public ConfigureChassisPacket(PacketBuffer buffer) {
super(buffer);
}
@Override
protected void writeSettings(PacketBuffer buffer) {
buffer.writeInt(range);
}
@Override
protected void readSettings(PacketBuffer buffer) {
range = buffer.readInt();
}
@Override
protected void applySettings(ChassisTileEntity te) {
te.setRange(range);
te.markDirty();
te.sendData();
}
}

View file

@ -1,7 +1,5 @@
package com.simibubi.create.modules.contraptions.components.contraptions.chassis;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
@ -9,8 +7,6 @@ import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld;
public class RadialChassisBlock extends AbstractChassisBlock {
@ -31,11 +27,6 @@ public class RadialChassisBlock extends AbstractChassisBlock {
super.fillStateContainer(builder);
}
@Override
public String getValueName(BlockState state, IWorld world, BlockPos pos) {
return Lang.translate("generic.radius");
}
@Override
public BooleanProperty getGlueableSide(BlockState state, Direction face) {
Axis axis = state.get(AXIS);

View file

@ -3,8 +3,6 @@ package com.simibubi.create.modules.contraptions.components.deployer;
import com.simibubi.create.AllItems;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.DirectionalAxisKineticBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
@ -17,12 +15,9 @@ import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
@ -108,25 +103,6 @@ public class DeployerBlock extends DirectionalAxisKineticBlock
return true;
}
public static Vec3d getFilterSlotPosition(BlockState state) {
Direction facing = state.get(FACING);
Vec3d vec = VecHelper.voxelSpace(8f, 13.5f, 11.5f);
float yRot = AngleHelper.horizontalAngle(facing);
float zRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0;
vec = VecHelper.rotateCentered(vec, yRot, Axis.Y);
vec = VecHelper.rotateCentered(vec, zRot, Axis.Z);
return vec;
}
public static Vec3d getFilterSlotOrientation(BlockState state) {
Direction facing = state.get(FACING);
float yRot = AngleHelper.horizontalAngle(facing) + 180;
float zRot = facing == Direction.UP ? 90 : facing == Direction.DOWN ? 270 : 0;
return new Vec3d(0, yRot, zRot);
}
@Override
public MovementBehaviour getMovementBehaviour() {
return MOVEMENT;

View file

@ -0,0 +1,35 @@
package com.simibubi.create.modules.contraptions.components.deployer;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.Vec3d;
public class DeployerFilterSlot extends ValueBoxTransform {
@Override
protected Vec3d getLocation(BlockState state) {
Direction facing = state.get(DeployerBlock.FACING);
Vec3d vec = VecHelper.voxelSpace(8f, 13.5f, 11.5f);
float yRot = AngleHelper.horizontalAngle(facing);
float zRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0;
vec = VecHelper.rotateCentered(vec, yRot, Axis.Y);
vec = VecHelper.rotateCentered(vec, zRot, Axis.Z);
return vec;
}
@Override
protected Vec3d getOrientation(BlockState state) {
Direction facing = state.get(DeployerBlock.FACING);
float yRot = AngleHelper.horizontalAngle(facing) + 180;
float zRot = facing == Direction.UP ? 90 : facing == Direction.DOWN ? 270 : 0;
return new Vec3d(0, yRot, zRot);
}
}

View file

@ -16,7 +16,6 @@ import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.advancement.AllCriterionTriggers;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour.SlotPositioning;
import com.simibubi.create.foundation.behaviour.inventory.ExtractingBehaviour;
import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.utility.NBTHelper;
@ -81,9 +80,7 @@ public class DeployerTileEntity extends KineticTileEntity {
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
super.addBehaviours(behaviours);
filtering = new FilteringBehaviour(this).withSlotPositioning(
new SlotPositioning(DeployerBlock::getFilterSlotPosition, DeployerBlock::getFilterSlotOrientation)
.scale(.4f));
filtering = new FilteringBehaviour(this, new DeployerFilterSlot());
extracting = new ExtractingBehaviour(this, this::getExtractingLocations, this::onExtract);
behaviours.add(filtering);

View file

@ -1,39 +0,0 @@
package com.simibubi.create.modules.contraptions.components.mixer;
import com.simibubi.create.foundation.packet.TileEntityConfigurationPacket;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
public class ConfigureMixerPacket extends TileEntityConfigurationPacket<MechanicalMixerTileEntity> {
private int value;
public ConfigureMixerPacket(BlockPos pos, int value) {
super(pos);
this.value = value;
}
public ConfigureMixerPacket(PacketBuffer buffer) {
super(buffer);
}
@Override
protected void writeSettings(PacketBuffer buffer) {
buffer.writeInt(value);
}
@Override
protected void readSettings(PacketBuffer buffer) {
value = buffer.readInt();
}
@Override
protected void applySettings(MechanicalMixerTileEntity te) {
te.minIngredients = value;
te.markDirty();
te.sendData();
te.checkBasin = true;
}
}

View file

@ -2,10 +2,8 @@ package com.simibubi.create.modules.contraptions.components.mixer;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IHaveCustomBlockItem;
import com.simibubi.create.foundation.block.IHaveScrollableValue;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.base.KineticBlock;
import net.minecraft.block.BlockState;
@ -17,17 +15,14 @@ import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader;
public class MechanicalMixerBlock extends KineticBlock
implements IWithTileEntity<MechanicalMixerTileEntity>, IHaveScrollableValue, IHaveCustomBlockItem {
implements IWithTileEntity<MechanicalMixerTileEntity>, IHaveCustomBlockItem {
private static final Vec3d valuePos = new Vec3d(15.8f / 16f, 6 / 16f, 5 / 16f);
public MechanicalMixerBlock() {
super(Properties.from(Blocks.ANDESITE));
@ -76,49 +71,6 @@ public class MechanicalMixerBlock extends KineticBlock
return face.getAxis().isHorizontal();
}
@Override
public String getValueName(BlockState state, IWorld world, BlockPos pos) {
return Lang.translate("mechanical_mixer.min_ingredients");
}
@Override
public Vec3d getValueBoxPosition(BlockState state, IWorld world, BlockPos pos) {
return valuePos;
}
@Override
public Direction getValueBoxDirection(BlockState state, IWorld world, BlockPos pos) {
return null;
}
@Override
public boolean isValueOnMultipleFaces() {
return true;
}
@Override
public boolean requiresWrench() {
return true;
}
@Override
public boolean isValueOnFace(Direction face) {
return face.getAxis().isHorizontal();
}
@Override
public void onScroll(BlockState state, IWorld world, BlockPos pos, double value) {
withTileEntityDo(world, pos, te -> te.setMinIngredientsLazily((int) (te.currentValue + value)));
}
@Override
public int getCurrentValue(BlockState state, IWorld world, BlockPos pos) {
MechanicalMixerTileEntity tileEntity = (MechanicalMixerTileEntity) world.getTileEntity(pos);
if (tileEntity == null)
return 0;
return tileEntity.currentValue;
}
@Override
public float getParticleTargetRadius() {
return .85f;

View file

@ -4,9 +4,12 @@ import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import com.simibubi.create.AllPackets;
import com.simibubi.create.AllRecipes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.behaviour.CenteredSideValueBoxTransform;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.scrollvalue.ScrollValueBehaviour;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.components.press.MechanicalPressTileEntity;
import com.simibubi.create.modules.contraptions.processing.BasinOperatingTileEntity;
@ -35,15 +38,29 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
public int processingTicks;
public boolean running;
public int minIngredients;
public int currentValue;
public int lastModified;
public ScrollValueBehaviour minIngredients;
public MechanicalMixerTileEntity() {
super(AllTileEntities.MECHANICAL_MIXER.type);
minIngredients = currentValue = 1;
lastModified = -1;
processingTicks = -1;
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
super.addBehaviours(behaviours);
CenteredSideValueBoxTransform slot =
new CenteredSideValueBoxTransform((state, direction) -> direction.getAxis().isHorizontal()) {
@Override
protected Vec3d getSouthLocation() {
return super.getSouthLocation().add(0, 4/16f, 0);
}
};
minIngredients = new ScrollValueBehaviour(Lang.translate("mechanical_mixer.min_ingredients"), this, slot);
minIngredients.between(1, 9);
minIngredients.withCallback(i -> checkBasin = true);
minIngredients.requiresWrench();
behaviours.add(minIngredients);
}
public float getRenderedHeadOffset(float partialTicks) {
@ -92,7 +109,6 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
public void read(CompoundNBT compound) {
running = compound.getBoolean("Running");
runningTicks = compound.getInt("Ticks");
currentValue = minIngredients = compound.getInt("MinIngredients");
super.read(compound);
}
@ -100,27 +116,11 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
public CompoundNBT write(CompoundNBT compound) {
compound.putBoolean("Running", running);
compound.putInt("Ticks", runningTicks);
compound.putInt("MinIngredients", minIngredients);
return super.write(compound);
}
public void setMinIngredientsLazily(int minIngredients) {
this.currentValue = MathHelper.clamp(minIngredients, 1, 9);
if (currentValue == this.minIngredients)
return;
this.lastModified = 0;
}
@Override
public void tick() {
if (world.isRemote && lastModified != -1) {
if (lastModified++ > 10) {
lastModified = -1;
AllPackets.channel.sendToServer(new ConfigureMixerPacket(pos, currentValue));
}
}
super.tick();
if (runningTicks >= 40) {
@ -187,7 +187,7 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity {
protected <C extends IInventory> boolean matchBasinRecipe(IRecipe<C> recipe) {
if (recipe == null)
return false;
if (recipe.getIngredients().size() < minIngredients)
if (recipe.getIngredients().size() < minIngredients.getValue())
return false;
NonNullList<Ingredient> ingredients = recipe.getIngredients();

View file

@ -1,37 +0,0 @@
package com.simibubi.create.modules.contraptions.components.motor;
import com.simibubi.create.foundation.packet.TileEntityConfigurationPacket;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
public class ConfigureMotorPacket extends TileEntityConfigurationPacket<MotorTileEntity> {
private int speed;
public ConfigureMotorPacket(BlockPos pos, int speed) {
super(pos);
this.speed = speed;
}
public ConfigureMotorPacket(PacketBuffer buffer) {
super(buffer);
}
@Override
protected void writeSettings(PacketBuffer buffer) {
buffer.writeInt(speed);
}
@Override
protected void readSettings(PacketBuffer buffer) {
speed = buffer.readInt();
}
@Override
protected void applySettings(MotorTileEntity te) {
te.generatedSpeed = speed;
te.updateGeneratedRotation();
}
}

View file

@ -1,9 +1,6 @@
package com.simibubi.create.modules.contraptions.components.motor;
import com.simibubi.create.foundation.block.IHaveScrollableValue;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
import net.minecraft.block.BlockState;
@ -13,17 +10,12 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader;
public class MotorBlock extends HorizontalKineticBlock
implements IWithTileEntity<MotorTileEntity>, IHaveScrollableValue {
private static final Vec3d valuePos = new Vec3d(15 / 16f, 5 / 16f, 5 / 16f);
public class MotorBlock extends HorizontalKineticBlock {
public MotorBlock() {
super(Properties.from(Blocks.IRON_BLOCK));
@ -64,54 +56,6 @@ public class MotorBlock extends HorizontalKineticBlock
return true;
}
@Override
public int getCurrentValue(BlockState state, IWorld world, BlockPos pos) {
MotorTileEntity tileEntity = (MotorTileEntity) world.getTileEntity(pos);
if (tileEntity == null)
return 0;
return tileEntity.newGeneratedSpeed;
}
@Override
public void onScroll(BlockState state, IWorld world, BlockPos pos, double delta) {
withTileEntityDo(world, pos, te -> {
boolean forward = delta > 0;
int step = forward ? 1 : -1;
int currentSpeed = te.newGeneratedSpeed;
if (world.getClosestPlayer(pos.getX(), pos.getY(), pos.getZ()).isSneaking()){
te.setSpeedValueLazily(currentSpeed + step);
return;
}
int magnitude = Math.abs(currentSpeed) - (forward == currentSpeed > 0 ? 0 : 1);
if (magnitude >= 4)
step *= 4;
if (magnitude >= 32)
step *= 4;
if (magnitude >= 128)
step *= 4;
te.setSpeedValueLazily(currentSpeed + step);
});
}
@Override
public String getValueName(BlockState state, IWorld world, BlockPos pos) {
return Lang.translate("generic.speed") + " (" + Lang.translate("generic.unit.rpm") + ")";
}
@Override
public Vec3d getValueBoxPosition(BlockState state, IWorld world, BlockPos pos) {
return valuePos;
}
@Override
public Direction getValueBoxDirection(BlockState state, IWorld world, BlockPos pos) {
return state.get(HORIZONTAL_FACING).getOpposite();
}
@Override
public boolean hideStressImpact() {
return true;

View file

@ -1,74 +1,64 @@
package com.simibubi.create.modules.contraptions.components.motor;
import java.util.List;
import java.util.UUID;
import com.simibubi.create.AllPackets;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.foundation.behaviour.CenteredSideValueBoxTransform;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.scrollvalue.ScrollValueBehaviour;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.base.GeneratingKineticTileEntity;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.math.MathHelper;
public class MotorTileEntity extends GeneratingKineticTileEntity {
public static final int DEFAULT_SPEED = 16;
public int newGeneratedSpeed;
public int generatedSpeed;
public int lastModified;
protected ScrollValueBehaviour generatedSpeed;
public MotorTileEntity() {
super(AllTileEntities.MOTOR.type);
speed = generatedSpeed = newGeneratedSpeed = DEFAULT_SPEED;
updateNetwork = true;
newNetworkID = UUID.randomUUID();
lastModified = -1;
speed = DEFAULT_SPEED;
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
super.addBehaviours(behaviours);
Integer max = AllConfigs.SERVER.kinetics.maxMotorSpeed.get();
CenteredSideValueBoxTransform slot = new CenteredSideValueBoxTransform((motor, side) -> {
return motor.get(MotorBlock.HORIZONTAL_FACING) == side.getOpposite();
});
generatedSpeed = new ScrollValueBehaviour(Lang.translate("generic.speed"), this, slot);
generatedSpeed.between(-max, max);
generatedSpeed.value = DEFAULT_SPEED;
generatedSpeed.withUnit(i -> Lang.translate("generic.unit.rpm"));
generatedSpeed.withCallback(i -> this.updateGeneratedRotation());
generatedSpeed.withStepFunction(this::step);
behaviours.add(generatedSpeed);
}
@Override
public float getGeneratedSpeed() {
return generatedSpeed;
return generatedSpeed.getValue();
}
@Override
public boolean hasFastRenderer() {
return true;
}
private int step(int current, boolean forward) {
if (world.getClosestPlayer(pos.getX(), pos.getY(), pos.getZ()).isSneaking())
return 1;
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.putInt("GeneratedSpeed", generatedSpeed);
return super.write(compound);
}
@Override
public void read(CompoundNBT compound) {
generatedSpeed = compound.getInt("GeneratedSpeed");
if (lastModified == -1)
newGeneratedSpeed = generatedSpeed;
super.read(compound);
}
public void setSpeedValueLazily(int speed) {
if (newGeneratedSpeed == speed)
return;
Integer max = AllConfigs.SERVER.kinetics.maxMotorSpeed.get();
newGeneratedSpeed = MathHelper.clamp(speed, -max, max);
this.lastModified = 0;
}
@Override
public void tick() {
super.tick();
if (!world.isRemote)
return;
if (lastModified == -1)
return;
if (lastModified++ > 10) {
lastModified = -1;
AllPackets.channel.sendToServer(new ConfigureMotorPacket(pos, newGeneratedSpeed));
}
int magnitude = Math.abs(current) - (forward == current > 0 ? 0 : 1);
int step = 1;
if (magnitude >= 4)
step *= 4;
if (magnitude >= 32)
step *= 4;
if (magnitude >= 128)
step *= 4;
return step;
}
}

View file

@ -0,0 +1,26 @@
package com.simibubi.create.modules.contraptions.components.saw;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
import net.minecraft.util.math.Vec3d;
public class SawFilterSlot extends ValueBoxTransform {
@Override
protected Vec3d getLocation(BlockState state) {
if (state.get(SawBlock.FACING) != Direction.UP)
return null;
Vec3d x = VecHelper.voxelSpace(8f, 12.5f, 12.25f);
Vec3d z = VecHelper.voxelSpace(12.25f, 12.5f, 8f);
return state.get(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? z : x;
}
@Override
protected Vec3d getOrientation(BlockState state) {
return new Vec3d(0, state.get(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? 270 : 180, 90);
}
}

View file

@ -12,7 +12,6 @@ import com.simibubi.create.AllRecipes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour.SlotPositioning;
import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.TreeCutter;
import com.simibubi.create.foundation.utility.TreeCutter.Tree;
@ -50,7 +49,6 @@ import net.minecraftforge.items.IItemHandler;
public class SawTileEntity extends BlockBreakingKineticTileEntity {
private static final Object cuttingRecipesKey = new Object();
private static FilteringBehaviour.SlotPositioning slots;
public ProcessingInventory inventory;
private int recipeIndex;
@ -68,9 +66,7 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity {
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
super.addBehaviours(behaviours);
if (slots == null)
createSlotPositioning();
filtering = new FilteringBehaviour(this).withSlotPositioning(slots);
filtering = new FilteringBehaviour(this, new SawFilterSlot());
behaviours.add(filtering);
}
@ -389,16 +385,4 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity {
return super.canBreak(stateToBreak, blockHardness) && stateToBreak.isIn(BlockTags.LOGS);
}
protected void createSlotPositioning() {
slots = new SlotPositioning(state -> {
if (state.get(SawBlock.FACING) != Direction.UP)
return null;
Vec3d x = VecHelper.voxelSpace(8f, 12.5f, 12.25f);
Vec3d z = VecHelper.voxelSpace(12.25f, 12.5f, 8f);
return state.get(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? z : x;
}, state -> {
return new Vec3d(0, state.get(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? 270 : 180, 90);
}).scale(.4f);
}
}

View file

@ -0,0 +1,52 @@
package com.simibubi.create.modules.logistics.block;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.Vec3d;
public class RedstoneLinkFrequencySlot extends ValueBoxTransform.Dual {
public RedstoneLinkFrequencySlot(boolean first) {
super(first);
}
Vec3d horizontal = VecHelper.voxelSpace(10f, 5.5f, 2.5f);
Vec3d vertical = VecHelper.voxelSpace(10f, 2.5f, 5.5f);
@Override
protected Vec3d getLocation(BlockState state) {
Direction facing = state.get(RedstoneLinkBlock.FACING);
Vec3d location = vertical;
if (facing.getAxis().isHorizontal()) {
location = horizontal;
if (!isFirst())
location = location.add(0, 5 / 16f, 0);
return rotateHorizontally(state, location);
}
if (!isFirst())
location = location.add(0, 0, 5 / 16f);
location = VecHelper.rotateCentered(location, facing == Direction.DOWN ? 180 : 0, Axis.X);
return location;
}
@Override
protected Vec3d getOrientation(BlockState state) {
Direction facing = state.get(RedstoneLinkBlock.FACING);
float yRot = facing.getAxis().isVertical() ? 180 : AngleHelper.horizontalAngle(facing);
float zRot = facing == Direction.UP ? 90 : facing == Direction.DOWN ? 270 : 0;
return new Vec3d(0, yRot + 180, zRot);
}
@Override
protected float getScale() {
return .5f;
}
}

View file

@ -7,23 +7,18 @@ import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.linked.LinkBehaviour;
import com.simibubi.create.foundation.behaviour.linked.LinkBehaviour.SlotPositioning;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
public class RedstoneLinkTileEntity extends SmartTileEntity {
private static LinkBehaviour.SlotPositioning slots;
private boolean receivedSignal;
private boolean transmittedSignal;
private LinkBehaviour link;
@ -49,13 +44,10 @@ public class RedstoneLinkTileEntity extends SmartTileEntity {
}
protected void createLink() {
if (slots == null)
createSlotPositioning();
if (transmitter)
link = LinkBehaviour.transmitter(this, this::getSignal);
else
link = LinkBehaviour.receiver(this, this::setSignal);
link.withSlotPositioning(slots);
Pair<ValueBoxTransform, ValueBoxTransform> slots =
ValueBoxTransform.Dual.makeSlots(RedstoneLinkFrequencySlot::new);
link = transmitter ? LinkBehaviour.transmitter(this, slots, this::getSignal)
: LinkBehaviour.receiver(this, slots, this::setSignal);
}
public boolean getSignal() {
@ -117,39 +109,4 @@ public class RedstoneLinkTileEntity extends SmartTileEntity {
return !getBlockState().get(RedstoneLinkBlock.RECEIVER);
}
protected void createSlotPositioning() {
slots = new SlotPositioning(state -> {
Direction facing = state.get(RedstoneLinkBlock.FACING);
Vec3d first = Vec3d.ZERO;
Vec3d second = Vec3d.ZERO;
if (facing.getAxis().isHorizontal()) {
first = VecHelper.voxelSpace(10f, 5.5f, 2.5f);
second = VecHelper.voxelSpace(10f, 10.5f, 2.5f);
float angle = facing.getHorizontalAngle();
if (facing.getAxis() == Axis.X)
angle = -angle;
first = VecHelper.rotateCentered(first, angle, Axis.Y);
second = VecHelper.rotateCentered(second, angle, Axis.Y);
} else {
first = VecHelper.voxelSpace(10f, 2.5f, 5.5f);
second = VecHelper.voxelSpace(10f, 2.5f, 10.5f);
if (facing == Direction.DOWN) {
first = VecHelper.rotateCentered(first, 180, Axis.X);
second = VecHelper.rotateCentered(second, 180, Axis.X);
}
}
return Pair.of(first, second);
}, state -> {
Direction facing = state.get(RedstoneLinkBlock.FACING);
float yRot = facing.getAxis().isVertical() ? 180 : AngleHelper.horizontalAngle(facing);
float zRot = facing == Direction.UP ? 90 : facing == Direction.DOWN ? 270 : 0;
return new Vec3d(0, yRot + 180, zRot);
}).scale(.5f);
}
}

View file

@ -0,0 +1,26 @@
package com.simibubi.create.modules.logistics.block.belts;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.block.HorizontalBlock;
import net.minecraft.util.math.Vec3d;
public class BeltObserverFilterSlot extends ValueBoxTransform {
Vec3d position = VecHelper.voxelSpace(8f, 14.5f, 16f);
@Override
protected Vec3d getLocation(BlockState state) {
return rotateHorizontally(state, position);
}
@Override
protected Vec3d getOrientation(BlockState state) {
float yRot = AngleHelper.horizontalAngle(state.get(HorizontalBlock.HORIZONTAL_FACING));
return new Vec3d(0, 180 + yRot, 90);
}
}

View file

@ -6,21 +6,15 @@ import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour.SlotPositioning;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.block.belts.BeltObserverBlock.Mode;
import net.minecraft.block.HorizontalBlock;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.Vec3d;
public class BeltObserverTileEntity extends SmartTileEntity {
private static FilteringBehaviour.SlotPositioning slots;
private FilteringBehaviour filtering;
public int turnOffTicks = 0;
@ -29,6 +23,12 @@ public class BeltObserverTileEntity extends SmartTileEntity {
setLazyTickRate(20);
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
filtering = new FilteringBehaviour(this, new BeltObserverFilterSlot()).moveText(new Vec3d(0, 5, 0));
behaviours.add(filtering);
}
@Override
public void tick() {
super.tick();
@ -83,23 +83,4 @@ public class BeltObserverTileEntity extends SmartTileEntity {
super.read(compound);
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
if (slots == null)
createSlotPositioning();
filtering = new FilteringBehaviour(this).withSlotPositioning(slots).moveText(new Vec3d(0, 5, 0));
behaviours.add(filtering);
}
protected void createSlotPositioning() {
slots = new SlotPositioning(state -> {
float yRot = AngleHelper.horizontalAngle(state.get(HorizontalBlock.HORIZONTAL_FACING));
Vec3d position = VecHelper.voxelSpace(8f, 14.5f, 16f);
return VecHelper.rotateCentered(position, yRot, Axis.Y);
}, state -> {
float yRot = AngleHelper.horizontalAngle(state.get(HorizontalBlock.HORIZONTAL_FACING));
return new Vec3d(0, 180 + yRot, 90);
}).scale(.4f);
}
}

View file

@ -0,0 +1,47 @@
package com.simibubi.create.modules.logistics.block.belts;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.logistics.block.extractor.ExtractorBlock;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.Vec3d;
public class FunnelFilterSlot extends ValueBoxTransform {
Vec3d offsetForHorizontal = VecHelper.voxelSpace(8f, 14f, 13.5f);
Vec3d offsetForBelt = VecHelper.voxelSpace(8f, 8.5f, 14f);
Vec3d offsetForUpward = VecHelper.voxelSpace(8f, 13.5f, 2f);
Vec3d offsetForDownward = VecHelper.voxelSpace(8f, 2.5f, 2f);
@Override
protected Vec3d getLocation(BlockState state) {
Vec3d vec = offsetForHorizontal;
float yRot = AngleHelper.horizontalAngle(state.get(ExtractorBlock.HORIZONTAL_FACING));
if (AttachedLogisticalBlock.isVertical(state))
vec = state.get(AttachedLogisticalBlock.UPWARD) ? offsetForUpward : offsetForDownward;
else if (state.get(FunnelBlock.BELT))
vec = offsetForBelt;
return VecHelper.rotateCentered(vec, yRot, Axis.Y);
}
@Override
protected Vec3d getOrientation(BlockState state) {
Direction blockFacing = AttachedLogisticalBlock.getBlockFacing(state);
boolean vertical = AttachedLogisticalBlock.isVertical(state);
float horizontalAngle = AngleHelper.horizontalAngle(state.get(ExtractorBlock.HORIZONTAL_FACING));
float yRot = blockFacing == Direction.DOWN ? horizontalAngle + 180 : horizontalAngle;
float zRot = (vertical || state.get(FunnelBlock.BELT)) ? 90 : 0;
if (blockFacing == Direction.UP)
zRot += 180;
return new Vec3d(0, yRot, zRot);
}
}

View file

@ -8,13 +8,10 @@ import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour.SlotPositioning;
import com.simibubi.create.foundation.behaviour.inventory.InsertingBehaviour;
import com.simibubi.create.foundation.behaviour.inventory.InventoryManagementBehaviour.Attachments;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.block.extractor.ExtractorBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
@ -23,7 +20,6 @@ import net.minecraft.particles.ParticleTypes;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
@ -31,7 +27,6 @@ import net.minecraft.util.math.Vec3i;
public class FunnelTileEntity extends SmartTileEntity {
private static FilteringBehaviour.SlotPositioning slots;
private FilteringBehaviour filtering;
private InsertingBehaviour inserting;
private ItemStack justEaten;
@ -42,9 +37,7 @@ public class FunnelTileEntity extends SmartTileEntity {
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
if (slots == null)
createSlotPositioning();
filtering = new FilteringBehaviour(this).withCallback(this::filterChanged).withSlotPositioning(slots);
filtering = new FilteringBehaviour(this, new FunnelFilterSlot()).withCallback(this::filterChanged);
behaviours.add(filtering);
inserting = new InsertingBehaviour(this,
Attachments.toward(() -> AttachedLogisticalBlock.getBlockFacing(getBlockState())));
@ -125,35 +118,4 @@ public class FunnelTileEntity extends SmartTileEntity {
1 / 6f, zSpeed);
}
protected void createSlotPositioning() {
slots = new SlotPositioning(state -> {
Vec3d offsetForHorizontal = VecHelper.voxelSpace(8f, 14f, 13.5f);
Vec3d offsetForBelt = VecHelper.voxelSpace(8f, 8.5f, 14f);
Vec3d offsetForUpward = VecHelper.voxelSpace(8f, 13.5f, 2f);
Vec3d offsetForDownward = VecHelper.voxelSpace(8f, 2.5f, 2f);
Vec3d vec = offsetForHorizontal;
float yRot = AngleHelper.horizontalAngle(state.get(ExtractorBlock.HORIZONTAL_FACING));
if (AttachedLogisticalBlock.isVertical(state))
vec = state.get(AttachedLogisticalBlock.UPWARD) ? offsetForUpward : offsetForDownward;
else if (state.get(FunnelBlock.BELT))
vec = offsetForBelt;
return VecHelper.rotateCentered(vec, yRot, Axis.Y);
}, state -> {
Direction blockFacing = AttachedLogisticalBlock.getBlockFacing(state);
boolean vertical = AttachedLogisticalBlock.isVertical(state);
float horizontalAngle = AngleHelper.horizontalAngle(state.get(ExtractorBlock.HORIZONTAL_FACING));
float yRot = blockFacing == Direction.DOWN ? horizontalAngle + 180 : horizontalAngle;
float zRot = (vertical || state.get(FunnelBlock.BELT)) ? 90 : 0;
if (blockFacing == Direction.UP)
zRot += 180;
return new Vec3d(0, yRot, zRot);
}).scale(.4f);
}
}

View file

@ -1,41 +0,0 @@
package com.simibubi.create.modules.logistics.block.diodes;
import com.simibubi.create.foundation.packet.TileEntityConfigurationPacket;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
public class ConfigureFlexpeaterPacket extends TileEntityConfigurationPacket<FlexpeaterTileEntity> {
private int maxState;
public ConfigureFlexpeaterPacket(BlockPos pos, int newMaxState) {
super(pos);
this.maxState = newMaxState;
}
public ConfigureFlexpeaterPacket(PacketBuffer buffer) {
super(buffer);
}
@Override
protected void writeSettings(PacketBuffer buffer) {
buffer.writeInt(maxState);
}
@Override
protected void readSettings(PacketBuffer buffer) {
maxState = buffer.readInt();
}
@Override
protected void applySettings(FlexpeaterTileEntity te) {
te.maxState = maxState;
te.state = MathHelper.clamp(te.state, 0, maxState);
te.forceClientState = true;
te.sendData();
te.forceClientState = false;
}
}

View file

@ -1,7 +1,6 @@
package com.simibubi.create.modules.logistics.block.diodes;
import static com.simibubi.create.modules.logistics.block.diodes.FlexpeaterBlock.POWERING;
import static net.minecraft.block.RedstoneDiodeBlock.POWERED;
import com.simibubi.create.AllTileEntities;
@ -12,14 +11,7 @@ public class FlexPulsepeaterTileEntity extends FlexpeaterTileEntity {
}
@Override
public void tick() {
updateConfigurableValue();
boolean powered = getBlockState().get(POWERED);
boolean powering = getBlockState().get(POWERING);
boolean atMax = state >= maxState;
boolean isReset = state == 0;
protected void updateState(boolean powered, boolean powering, boolean atMax, boolean atMin) {
if (!charging && powered && !atMax)
charging = true;
@ -37,7 +29,7 @@ public class FlexPulsepeaterTileEntity extends FlexpeaterTileEntity {
if (!charging && powered)
return;
if (!charging && !isReset) {
if (!charging && !atMin) {
if (!world.isRemote)
world.setBlockState(pos, getBlockState().with(POWERING, false));
state = 0;

View file

@ -1,9 +1,6 @@
package com.simibubi.create.modules.logistics.block.diodes;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IHaveScrollableValue;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@ -14,15 +11,11 @@ import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
public class FlexpeaterBlock extends RedstoneDiodeBlock
implements IWithTileEntity<FlexpeaterTileEntity>, IHaveScrollableValue {
public class FlexpeaterBlock extends RedstoneDiodeBlock {
public static BooleanProperty POWERING = BooleanProperty.create("powering");
private static Vec3d VALUE_POS = new Vec3d(2 / 16f, 5 / 16f, 5 / 16f);
public FlexpeaterBlock() {
super(Properties.from(Blocks.REPEATER));
@ -67,43 +60,4 @@ public class FlexpeaterBlock extends RedstoneDiodeBlock
return side.getAxis() == state.get(HORIZONTAL_FACING).getAxis();
}
@Override
public int getCurrentValue(BlockState state, IWorld world, BlockPos pos) {
FlexpeaterTileEntity te = (FlexpeaterTileEntity) world.getTileEntity(pos);
if (te == null)
return 0;
return te.getDisplayValue();
}
@Override
public void onScroll(BlockState state, IWorld world, BlockPos pos, double delta) {
withTileEntityDo(world, pos, te -> te.increment((int) Math.signum(delta)));
}
@Override
public String getValueName(BlockState state, IWorld world, BlockPos pos) {
FlexpeaterTileEntity te = (FlexpeaterTileEntity) world.getTileEntity(pos);
if (te == null)
return "";
return Lang.translate("generic.delay") + " (" + Lang.translate("generic.unit." + te.getUnit()) + ")";
}
@Override
public String getValueSuffix(BlockState state, IWorld world, BlockPos pos) {
FlexpeaterTileEntity te = (FlexpeaterTileEntity) world.getTileEntity(pos);
if (te == null)
return "";
return "" + te.getUnit().charAt(0);
}
@Override
public Vec3d getValueBoxPosition(BlockState state, IWorld world, BlockPos pos) {
return VALUE_POS;
}
@Override
public Direction getValueBoxDirection(BlockState state, IWorld world, BlockPos pos) {
return Direction.UP;
}
}

View file

@ -0,0 +1,23 @@
package com.simibubi.create.modules.logistics.block.diodes;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.math.Vec3d;
public class FlexpeaterScrollSlot extends ValueBoxTransform {
@Override
protected Vec3d getLocation(BlockState state) {
return VecHelper.voxelSpace(8, 3f, 8);
}
@Override
protected Vec3d getOrientation(BlockState state) {
return new Vec3d(0, AngleHelper.horizontalAngle(state.get(BlockStateProperties.HORIZONTAL_FACING)) + 180, 90);
}
}

View file

@ -3,23 +3,22 @@ package com.simibubi.create.modules.logistics.block.diodes;
import static com.simibubi.create.modules.logistics.block.diodes.FlexpeaterBlock.POWERING;
import static net.minecraft.block.RedstoneDiodeBlock.POWERED;
import com.simibubi.create.AllPackets;
import java.util.List;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.block.SyncedTileEntity;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.scrollvalue.ScrollValueBehaviour;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.math.MathHelper;
public class FlexpeaterTileEntity extends SyncedTileEntity implements ITickableTileEntity {
public class FlexpeaterTileEntity extends SmartTileEntity {
public int state;
public int maxState;
public int newMaxState;
public int lastModified;
public boolean charging;
public boolean forceClientState;
ScrollValueBehaviour maxState;
public FlexpeaterTileEntity() {
this(AllTileEntities.FLEXPEATER.type);
@ -27,67 +26,67 @@ public class FlexpeaterTileEntity extends SyncedTileEntity implements ITickableT
protected FlexpeaterTileEntity(TileEntityType<?> type) {
super(type);
lastModified = -1;
maxState = newMaxState = 1;
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
maxState = new ScrollValueBehaviour(Lang.translate("generic.delay"), this, new FlexpeaterScrollSlot())
.between(1, 60 * 20 * 30);
maxState.withStepFunction(this::step);
maxState.withFormatter(this::format);
maxState.withUnit(this::getUnit);
behaviours.add(maxState);
}
@Override
public void read(CompoundNBT compound) {
readClientUpdate(compound);
newMaxState = maxState;
super.read(compound);
}
@Override
public void readClientUpdate(CompoundNBT compound) {
state = compound.getInt("State");
charging = compound.getBoolean("Charging");
maxState = compound.getInt("MaxState");
state = MathHelper.clamp(state, 0, maxState - 1);
if (compound.contains("Force"))
newMaxState = maxState;
}
@Override
public CompoundNBT writeToClient(CompoundNBT tag) {
if (forceClientState)
tag.putBoolean("Force", true);
return super.writeToClient(tag);
super.read(compound);
}
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.putInt("State", state);
compound.putInt("MaxState", maxState);
compound.putBoolean("Charging", charging);
return super.write(compound);
}
public void increment(int amount) {
private int step(int value, boolean positive) {
if (!positive)
value--;
if (amount > 0) {
if (newMaxState < 20) {
newMaxState += amount;
} else if (newMaxState < 20 * 60) {
newMaxState += amount * 20;
} else {
newMaxState += amount * 20 * 60;
}
lastModified = 0;
if (value < 20)
return 1;
if (value < 20 * 60)
return 20;
return 20 * 60;
}
if (amount < 0) {
if (newMaxState <= 20) {
newMaxState += amount;
} else if (newMaxState <= 20 * 60) {
newMaxState += amount * 20;
} else {
newMaxState += amount * 20 * 60;
}
lastModified = 0;
private String format(int value) {
if (value < 20)
return value + "t";
if (value < 20 * 60)
return (value / 20) + "s";
return (value / 20 / 60) + "m";
}
newMaxState = MathHelper.clamp(newMaxState, 1, 60 * 20 * 30);
private String getUnit(int value) {
if (value < 20)
return Lang.translate("generic.unit.ticks");
if (value < 20 * 60)
return Lang.translate("generic.unit.seconds");
return Lang.translate("generic.unit.minutes");
}
@Override
public void tick() {
super.tick();
boolean powered = getBlockState().get(POWERED);
boolean powering = getBlockState().get(POWERING);
boolean atMax = state >= maxState.getValue();
boolean atMin = state <= 0;
updateState(powered, powering, atMax, atMin);
}
@Override
@ -95,30 +94,7 @@ public class FlexpeaterTileEntity extends SyncedTileEntity implements ITickableT
return true;
}
public int getDisplayValue() {
if (newMaxState < 20)
return newMaxState;
if (newMaxState < 20 * 60)
return newMaxState / 20;
return newMaxState / 20 / 60;
}
public String getUnit() {
if (newMaxState < 20)
return "ticks";
if (newMaxState < 20 * 60)
return "seconds";
return "minutes";
}
@Override
public void tick() {
updateConfigurableValue();
boolean powered = getBlockState().get(POWERED);
boolean powering = getBlockState().get(POWERING);
boolean atMax = state >= maxState;
boolean atMin = state <= 0;
protected void updateState(boolean powered, boolean powering, boolean atMax, boolean atMin) {
if (!charging && powered)
charging = true;
@ -139,15 +115,4 @@ public class FlexpeaterTileEntity extends SyncedTileEntity implements ITickableT
state += charging ? 1 : -1;
}
public void updateConfigurableValue() {
if (!world.isRemote)
return;
if (lastModified == -1)
return;
if (lastModified++ > 10) {
lastModified = -1;
AllPackets.channel.sendToServer(new ConfigureFlexpeaterPacket(pos, newMaxState));
}
}
}

View file

@ -9,7 +9,7 @@ public class FlexpeaterTileEntityRenderer extends ColoredOverlayTileEntityRender
@Override
protected int getColor(FlexpeaterTileEntity te, float partialTicks) {
return ColorHelper.mixColors(0x2C0300, 0xCD0000, te.state / (float) te.maxState);
return ColorHelper.mixColors(0x2C0300, 0xCD0000, te.state / (float) te.maxState.getValue());
}
@Override

View file

@ -0,0 +1,82 @@
package com.simibubi.create.modules.logistics.block.extractor;
import static net.minecraft.block.HorizontalBlock.HORIZONTAL_FACING;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.logistics.block.belts.AttachedLogisticalBlock;
import com.simibubi.create.modules.logistics.block.transposer.TransposerBlock;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.Vec3d;
public class ExtractorSlots {
static class Filter extends ValueBoxTransform {
Vec3d offsetForHorizontal = VecHelper.voxelSpace(8f, 10.5f, 14f);
Vec3d offsetForUpward = VecHelper.voxelSpace(8f, 14.15f, 3.5f);
Vec3d offsetForDownward = VecHelper.voxelSpace(8f, 1.85f, 3.5f);
@Override
protected Vec3d getLocation(BlockState state) {
Vec3d location = offsetForHorizontal;
if (state.getBlock() instanceof TransposerBlock)
location = location.add(0, 2/16f, 0);
if (AttachedLogisticalBlock.isVertical(state))
location = state.get(AttachedLogisticalBlock.UPWARD) ? offsetForUpward : offsetForDownward;
return rotateHorizontally(state, location);
}
@Override
protected Vec3d getOrientation(BlockState state) {
float yRot = AngleHelper.horizontalAngle(state.get(HORIZONTAL_FACING));
float zRot = (AttachedLogisticalBlock.isVertical(state)) ? 0 : 90;
return new Vec3d(0, yRot, zRot);
}
}
public static class Link extends ValueBoxTransform.Dual {
public Link(boolean first) {
super(first);
}
Vec3d offsetForHorizontal = VecHelper.voxelSpace(11.5f, 4f, 14f);
Vec3d offsetForUpward = VecHelper.voxelSpace(10f, 14f, 11.5f);
Vec3d offsetForDownward = VecHelper.voxelSpace(10f, 2f, 11.5f);
@Override
protected Vec3d getLocation(BlockState state) {
Vec3d location = offsetForHorizontal;
if (state.getBlock() instanceof TransposerBlock)
location = location.add(0, 2/16f, 0);
if (!isFirst())
location = location.add(0, 4/16f, 0);
if (AttachedLogisticalBlock.isVertical(state)) {
location = state.get(AttachedLogisticalBlock.UPWARD) ? offsetForUpward : offsetForDownward;
if (!isFirst())
location = location.add(-4/16f, 0, 0);
}
float yRot = AngleHelper.horizontalAngle(state.get(HORIZONTAL_FACING));
location = VecHelper.rotateCentered(location, yRot, Axis.Y);
return location;
}
@Override
protected Vec3d getOrientation(BlockState state) {
float horizontalAngle = AngleHelper.horizontalAngle(state.get(HORIZONTAL_FACING));
boolean vertical = AttachedLogisticalBlock.isVertical(state);
float xRot = vertical ? (state.get(AttachedLogisticalBlock.UPWARD) ? 90 : 270) : 0;
float yRot = vertical ? horizontalAngle + 180 : horizontalAngle + 270;
return new Vec3d(xRot, yRot, 0);
}
}
}

View file

@ -8,7 +8,6 @@ import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour.SlotPositioning;
import com.simibubi.create.foundation.behaviour.inventory.AutoExtractingBehaviour;
import com.simibubi.create.foundation.behaviour.inventory.ExtractingBehaviour;
import com.simibubi.create.foundation.behaviour.inventory.SingleTargetAutoExtractingBehaviour;
@ -31,8 +30,6 @@ import net.minecraft.util.math.Vec3d;
public class ExtractorTileEntity extends SmartTileEntity {
protected static FilteringBehaviour.SlotPositioning slots;
protected ExtractingBehaviour extracting;
protected FilteringBehaviour filtering;
protected boolean extractingToBelt;
@ -53,11 +50,8 @@ public class ExtractorTileEntity extends SmartTileEntity {
this::onExtract, delay).pauseWhen(this::isPowered).waitUntil(this::canExtract);
behaviours.add(extracting);
if (slots == null)
slots = new SlotPositioning(ExtractorBlock::getFilterSlotPosition, ExtractorBlock::getFilterSlotOrientation)
.scale(.4f);
filtering =
new FilteringBehaviour(this).withCallback(this::filterChanged).withSlotPositioning(slots).showCount();
filtering = new FilteringBehaviour(this, new ExtractorSlots.Filter()).withCallback(this::filterChanged);
filtering.showCount();
behaviours.add(filtering);
}

View file

@ -4,14 +4,15 @@ import static net.minecraft.state.properties.BlockStateProperties.POWERED;
import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.linked.LinkBehaviour;
import com.simibubi.create.foundation.behaviour.linked.LinkBehaviour.SlotPositioning;
public class LinkedExtractorTileEntity extends ExtractorTileEntity {
private static LinkBehaviour.SlotPositioning slots;
public boolean receivedSignal;
public LinkBehaviour receiver;
@ -21,10 +22,8 @@ public class LinkedExtractorTileEntity extends ExtractorTileEntity {
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
if (slots == null)
slots = new SlotPositioning(LinkedExtractorBlock::getFrequencySlotPosition,
LinkedExtractorBlock::getFrequencySlotOrientation).scale(.4f);
receiver = LinkBehaviour.receiver(this, this::setSignal).withSlotPositioning(slots);
Pair<ValueBoxTransform, ValueBoxTransform> slots = ValueBoxTransform.Dual.makeSlots(ExtractorSlots.Link::new);
receiver = LinkBehaviour.receiver(this, slots, this::setSignal);
behaviours.add(receiver);
super.addBehaviours(behaviours);
}

View file

@ -4,15 +4,16 @@ import static net.minecraft.state.properties.BlockStateProperties.POWERED;
import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.linked.LinkBehaviour;
import com.simibubi.create.foundation.behaviour.linked.LinkBehaviour.SlotPositioning;
import com.simibubi.create.modules.logistics.block.extractor.LinkedExtractorBlock;
import com.simibubi.create.modules.logistics.block.extractor.ExtractorSlots;
public class LinkedTransposerTileEntity extends TransposerTileEntity {
private static LinkBehaviour.SlotPositioning slots;
public boolean receivedSignal;
public LinkBehaviour receiver;
@ -22,10 +23,8 @@ public class LinkedTransposerTileEntity extends TransposerTileEntity {
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
if (slots == null)
slots = new SlotPositioning(LinkedExtractorBlock::getFrequencySlotPosition,
LinkedExtractorBlock::getFrequencySlotOrientation).scale(.4f);
receiver = LinkBehaviour.receiver(this, this::setSignal).withSlotPositioning(slots);
Pair<ValueBoxTransform, ValueBoxTransform> slots = ValueBoxTransform.Dual.makeSlots(ExtractorSlots.Link::new);
receiver = LinkBehaviour.receiver(this, slots, this::setSignal);
behaviours.add(receiver);
super.addBehaviours(behaviours);
}

View file

@ -311,6 +311,7 @@
"create.gui.scrollInput.defaultTitle": "Choose an Option:",
"create.gui.scrollInput.scrollToModify": "Scroll to Modify",
"create.gui.scrollInput.scrollToAdjustAmount": "Scroll to Adjust Amount",
"create.gui.scrollInput.scrollToSelect": "Scroll to Select",
"create.gui.scrollInput.shiftScrollsFaster": "Shift to Scroll faster",

View file

@ -3,7 +3,6 @@
"parent": "block/block",
"textures": {
"flexpeater_off": "create:block/flexpeater_off",
"torch": "minecraft:block/redstone_torch_off",
"smooth_stone": "minecraft:block/smooth_stone",
"particle": "create:block/flexpeater_off"
},

View file

@ -1,7 +1,7 @@
{
"parent": "create:block/repeaters/flexpeater",
"textures": {
"flexpeater_off": "create:block/flexpeater_on",
"particle": "create:block/flexpeater_on"
"flexpeater_off": "create:block/flexpeater_charging",
"particle": "create:block/flexpeater_charging"
}
}

View file

@ -1,6 +1,7 @@
{
"parent": "create:block/repeaters/flexpeater_powered",
"parent": "create:block/repeaters/flexpeater",
"textures": {
"torch": "minecraft:block/redstone_torch"
"flexpeater_off": "create:block/flexpeater_on",
"particle": "create:block/flexpeater_on"
}
}

View file

@ -1,6 +1,7 @@
{
"parent": "create:block/repeaters/flexpeater",
"textures": {
"torch": "minecraft:block/redstone_torch"
"flexpeater_off": "create:block/flexpeater_powering",
"particle": "create:block/flexpeater_powering"
}
}

View file

@ -0,0 +1,132 @@
{
"credit": "Made with Blockbench",
"parent": "create:block/large_wheels",
"textures": {
"4": "create:block/brass_gearbox",
"5": "create:block/brass_casing_side",
"6": "create:block/brass_casing",
"7": "create:block/extractor",
"8": "create:block/encased_belt_middle",
"9": "create:block/brass_block",
"particle": "create:block/brass_casing"
},
"elements": [
{
"from": [1, 2, 10],
"to": [5, 15, 15],
"faces": {
"north": {"uv": [12, 1, 16, 14], "texture": "#5"},
"east": {"uv": [4, 1, 9, 14], "texture": "#6"},
"south": {"uv": [1, 1, 5, 14], "texture": "#6"},
"west": {"uv": [10, 1, 15, 14], "texture": "#4"},
"up": {"uv": [1, 10, 5, 15], "texture": "#9"},
"down": {"uv": [0, 0, 14, 5], "texture": "#missing"}
}
},
{
"from": [1, 2, 1],
"to": [5, 15, 6],
"faces": {
"north": {"uv": [5, 1, 1, 14], "texture": "#6"},
"east": {"uv": [9, 1, 4, 14], "texture": "#6"},
"south": {"uv": [16, 1, 12, 14], "texture": "#5"},
"west": {"uv": [15, 1, 10, 14], "texture": "#4"},
"up": {"uv": [1, 1, 5, 6], "texture": "#9"},
"down": {"uv": [0, 5, 14, 0], "texture": "#missing"}
}
},
{
"from": [11, 2, 10],
"to": [15, 15, 15],
"faces": {
"north": {"uv": [0, 1, 4, 14], "texture": "#5"},
"east": {"uv": [1, 1, 6, 14], "texture": "#4"},
"south": {"uv": [11, 1, 15, 14], "texture": "#6"},
"west": {"uv": [4, 1, 9, 14], "texture": "#6"},
"up": {"uv": [11, 10, 15, 15], "texture": "#9"},
"down": {"uv": [0, 0, 14, 5], "texture": "#missing"}
}
},
{
"from": [11, 2, 1],
"to": [15, 15, 6],
"faces": {
"north": {"uv": [15, 1, 11, 14], "texture": "#6"},
"east": {"uv": [6, 1, 1, 14], "texture": "#4"},
"south": {"uv": [4, 1, 0, 14], "texture": "#5"},
"west": {"uv": [9, 1, 4, 14], "texture": "#6"},
"up": {"uv": [11, 1, 15, 6], "texture": "#9"},
"down": {"uv": [0, 5, 14, 0], "texture": "#missing"}
}
},
{
"from": [5, 2, 10],
"to": [11, 8, 15],
"faces": {
"east": {"uv": [0, 0, 5, 16], "texture": "#missing"},
"south": {"uv": [5, 8, 11, 14], "texture": "#6"},
"west": {"uv": [10, 1, 15, 14], "texture": "#4"},
"up": {"uv": [5, 3, 11, 8], "texture": "#6"},
"down": {"uv": [0, 0, 14, 5], "texture": "#missing"}
}
},
{
"from": [5, 2, 1],
"to": [11, 8, 6],
"faces": {
"north": {"uv": [11, 8, 5, 14], "texture": "#6"},
"east": {"uv": [5, 0, 0, 16], "texture": "#missing"},
"west": {"uv": [15, 1, 10, 14], "texture": "#4"},
"up": {"uv": [5, 8, 11, 3], "texture": "#6"},
"down": {"uv": [0, 5, 14, 0], "texture": "#missing"}
}
},
{
"from": [5, 9, 10],
"to": [11, 14, 14],
"faces": {
"north": {"uv": [6, 9, 12, 14], "texture": "#7"},
"east": {"uv": [0, 0, 5, 16], "texture": "#missing"},
"south": {"uv": [6, 9, 12, 14], "texture": "#7"},
"west": {"uv": [10, 1, 15, 14], "texture": "#4"},
"up": {"uv": [6, 8, 12, 12], "texture": "#7"},
"down": {"uv": [6, 8, 12, 12], "texture": "#7"}
}
},
{
"from": [5, 9, 2],
"to": [11, 14, 6],
"faces": {
"north": {"uv": [6, 10, 12, 15], "texture": "#7"},
"east": {"uv": [5, 0, 0, 16], "texture": "#missing"},
"south": {"uv": [6, 8, 12, 13], "texture": "#7"},
"west": {"uv": [15, 1, 10, 14], "texture": "#4"},
"up": {"uv": [6, 12, 12, 8], "texture": "#7"},
"down": {"uv": [6, 8, 12, 12], "texture": "#7"}
}
},
{
"from": [0, 0, 0],
"to": [16, 2, 16],
"faces": {
"north": {"uv": [0, 14, 16, 16], "texture": "#5"},
"east": {"uv": [0, 14, 16, 16], "texture": "#5"},
"south": {"uv": [0, 14, 16, 16], "texture": "#5"},
"west": {"uv": [0, 14, 16, 16], "texture": "#5"},
"up": {"uv": [0, 0, 16, 16], "texture": "#4"},
"down": {"uv": [0, 0, 16, 16], "texture": "#6"}
}
},
{
"from": [1, 2, 6],
"to": [15, 11, 10],
"faces": {
"east": {"uv": [6, 5, 10, 14], "texture": "#4"},
"west": {"uv": [6, 5, 10, 14], "texture": "#4"},
"up": {"uv": [1, 6, 15, 10], "texture": "#8"},
"down": {"uv": [0, 0, 14, 6], "texture": "#missing"}
}
}
],
"display": {}
}

View file

@ -0,0 +1,148 @@
{
"credit": "Made with Blockbench",
"parent": "create:block/large_wheels",
"textures": {
"0": "create:block/axis",
"3": "create:block/axis_top",
"4": "create:block/brass_gearbox",
"5": "create:block/brass_casing_side",
"6": "create:block/brass_casing",
"7": "create:block/extractor",
"8": "create:block/encased_belt_middle",
"9": "create:block/brass_block",
"particle": "create:block/stripped_spruce_log"
},
"elements": [
{
"from": [1, 2, 10],
"to": [5, 15, 15],
"faces": {
"north": {"uv": [12, 1, 16, 14], "texture": "#5"},
"east": {"uv": [4, 1, 9, 14], "texture": "#6"},
"south": {"uv": [1, 1, 5, 14], "texture": "#6"},
"west": {"uv": [10, 1, 15, 14], "texture": "#4"},
"up": {"uv": [1, 10, 5, 15], "texture": "#9"},
"down": {"uv": [0, 0, 14, 5], "texture": "#missing"}
}
},
{
"from": [1, 2, 1],
"to": [5, 15, 6],
"faces": {
"north": {"uv": [5, 1, 1, 14], "texture": "#6"},
"east": {"uv": [9, 1, 4, 14], "texture": "#6"},
"south": {"uv": [16, 1, 12, 14], "texture": "#5"},
"west": {"uv": [15, 1, 10, 14], "texture": "#4"},
"up": {"uv": [1, 1, 5, 6], "texture": "#9"},
"down": {"uv": [0, 5, 14, 0], "texture": "#missing"}
}
},
{
"from": [11, 2, 10],
"to": [15, 15, 15],
"faces": {
"north": {"uv": [0, 1, 4, 14], "texture": "#5"},
"east": {"uv": [1, 1, 6, 14], "texture": "#4"},
"south": {"uv": [11, 1, 15, 14], "texture": "#6"},
"west": {"uv": [4, 1, 9, 14], "texture": "#6"},
"up": {"uv": [11, 10, 15, 15], "texture": "#9"},
"down": {"uv": [0, 0, 14, 5], "texture": "#missing"}
}
},
{
"from": [11, 2, 1],
"to": [15, 15, 6],
"faces": {
"north": {"uv": [15, 1, 11, 14], "texture": "#6"},
"east": {"uv": [6, 1, 1, 14], "texture": "#4"},
"south": {"uv": [4, 1, 0, 14], "texture": "#5"},
"west": {"uv": [9, 1, 4, 14], "texture": "#6"},
"up": {"uv": [11, 1, 15, 6], "texture": "#9"},
"down": {"uv": [0, 5, 14, 0], "texture": "#missing"}
}
},
{
"from": [5, 2, 10],
"to": [11, 8, 15],
"faces": {
"east": {"uv": [0, 0, 5, 16], "texture": "#missing"},
"south": {"uv": [5, 8, 11, 14], "texture": "#6"},
"west": {"uv": [10, 1, 15, 14], "texture": "#4"},
"up": {"uv": [5, 3, 11, 8], "texture": "#6"},
"down": {"uv": [0, 0, 14, 5], "texture": "#missing"}
}
},
{
"from": [5, 2, 1],
"to": [11, 8, 6],
"faces": {
"north": {"uv": [11, 8, 5, 14], "texture": "#6"},
"east": {"uv": [5, 0, 0, 16], "texture": "#missing"},
"west": {"uv": [15, 1, 10, 14], "texture": "#4"},
"up": {"uv": [5, 8, 11, 3], "texture": "#6"},
"down": {"uv": [0, 5, 14, 0], "texture": "#missing"}
}
},
{
"from": [5, 9, 10],
"to": [11, 14, 14],
"faces": {
"north": {"uv": [6, 9, 12, 14], "texture": "#7"},
"east": {"uv": [0, 0, 5, 16], "texture": "#missing"},
"south": {"uv": [6, 9, 12, 14], "texture": "#7"},
"west": {"uv": [10, 1, 15, 14], "texture": "#4"},
"up": {"uv": [6, 8, 12, 12], "texture": "#7"},
"down": {"uv": [6, 8, 12, 12], "texture": "#7"}
}
},
{
"from": [5, 9, 2],
"to": [11, 14, 6],
"faces": {
"north": {"uv": [6, 10, 12, 15], "texture": "#7"},
"east": {"uv": [5, 0, 0, 16], "texture": "#missing"},
"south": {"uv": [6, 8, 12, 13], "texture": "#7"},
"west": {"uv": [15, 1, 10, 14], "texture": "#4"},
"up": {"uv": [6, 12, 12, 8], "texture": "#7"},
"down": {"uv": [6, 8, 12, 12], "texture": "#7"}
}
},
{
"name": "Axis",
"from": [0, 6, 6],
"to": [16, 10, 10],
"shade": false,
"faces": {
"north": {"uv": [6, 0, 10, 16], "rotation": 90, "texture": "#0"},
"east": {"uv": [6, 6, 10, 10], "texture": "#3"},
"south": {"uv": [6, 0, 10, 16], "rotation": 270, "texture": "#0"},
"west": {"uv": [6, 6, 10, 10], "rotation": 180, "texture": "#3"},
"up": {"uv": [6, 0, 10, 16], "rotation": 270, "texture": "#0"},
"down": {"uv": [6, 0, 10, 16], "rotation": 270, "texture": "#0"}
}
},
{
"from": [0, 0, 0],
"to": [16, 2, 16],
"faces": {
"north": {"uv": [0, 14, 16, 16], "texture": "#5"},
"east": {"uv": [0, 14, 16, 16], "texture": "#5"},
"south": {"uv": [0, 14, 16, 16], "texture": "#5"},
"west": {"uv": [0, 14, 16, 16], "texture": "#5"},
"up": {"uv": [0, 0, 16, 16], "texture": "#4"},
"down": {"uv": [0, 0, 16, 16], "texture": "#6"}
}
},
{
"from": [1, 2, 6],
"to": [15, 11, 10],
"faces": {
"east": {"uv": [6, 5, 10, 14], "texture": "#4"},
"west": {"uv": [6, 5, 10, 14], "texture": "#4"},
"up": {"uv": [1, 6, 15, 10], "texture": "#8"},
"down": {"uv": [0, 0, 14, 6], "texture": "#missing"}
}
}
],
"display": {}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B