In World in Style
- Overhauled UX of scroll values and item filtering - Filtered item extraction can now be configured to pull "up to x items" per operation - Removed some unused assets
|
@ -577,7 +577,7 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo
|
|||
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
|
||||
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
|
||||
30815cc68ddf59924be78b1c37a0e374fafe552a assets/create/lang/en_ud.json
|
||||
c1aabd0f4dfd58bbbb2618a367fc9b6b02bfb1b6 assets/create/lang/en_us.json
|
||||
c6c72491c2586f70e72d7510b230e7307a4d7c99 assets/create/lang/en_us.json
|
||||
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
|
||||
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
|
||||
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json
|
||||
|
|
|
@ -1070,20 +1070,41 @@
|
|||
"create.contraptions.cart_movement_mode.rotate_paused": "Pause actors while rotating",
|
||||
"create.contraptions.cart_movement_mode.rotation_locked": "Lock rotation",
|
||||
"create.contraptions.windmill.rotation_direction": "Rotation Direction",
|
||||
"create.contraptions.clockwork.clock_hands": "Clock Hands",
|
||||
"create.contraptions.clockwork.clock_hands": "Clock Hand Arrangement",
|
||||
"create.contraptions.clockwork.hour_first": "Hour hand first",
|
||||
"create.contraptions.clockwork.minute_first": "Minute hand first",
|
||||
"create.contraptions.clockwork.hour_first_24": "24-Hour hand first",
|
||||
|
||||
"create.logistics.crafter.connected": "Connected Crafters",
|
||||
"create.logistics.crafter.click_to_merge": "Click to merge Inventories",
|
||||
"create.logistics.crafter.click_to_separate": "Click to separate Inventories",
|
||||
"create.logistics.filter": "Filter",
|
||||
"create.logistics.recipe_filter": "Recipe Filter",
|
||||
"create.logistics.fluid_filter": "Fluid Filter",
|
||||
"create.logistics.firstFrequency": "Freq. #1",
|
||||
"create.logistics.secondFrequency": "Freq. #2",
|
||||
"create.logistics.filter.apply": "Applied filter to %1$s.",
|
||||
"create.logistics.filter.apply_click_again": "Applied filter to %1$s, click again to copy the amount.",
|
||||
"create.logistics.filter.apply_count": "Applied extraction count to filter.",
|
||||
"create.logistics.firstFrequency": "Frequency #1",
|
||||
"create.logistics.secondFrequency": "Frequency #2",
|
||||
"create.logistics.filter.click_to_set": "Click with item to set",
|
||||
"create.logistics.filter.click_to_replace": "Click with item to replace",
|
||||
"create.logistics.filter.hold_to_set_amount": "Click and hold for amount",
|
||||
"create.logistics.filter.extracted_amount": "Extracted Amount",
|
||||
"create.logistics.filter.any_amount_short": "Any",
|
||||
"create.logistics.filter.up_to": "Up to",
|
||||
"create.logistics.filter.exactly": "Exactly",
|
||||
"create.logistics.creative_crate.supply": "Infinite Supply",
|
||||
"create.logistics.train_observer.cargo_filter": "Cargo Filter",
|
||||
|
||||
"create.kinetics.creative_motor.rotation_speed": "Generated Speed in RPM",
|
||||
"create.kinetics.speed_controller.rotation_speed": "Targeted Speed in RPM",
|
||||
|
||||
"create.logistics.redstone_interval": "Redstone Interval",
|
||||
|
||||
"create.contraptions.contoller.target": "Targeted Component",
|
||||
"create.contraptions.chassis.radius": "Radius when Sticky",
|
||||
"create.contraptions.chassis.range": "Range of Sticky Sides",
|
||||
"create.contraptions.chassis.distance": "Distance",
|
||||
|
||||
"create.gui.value_settings.hold_to_edit": "Click and hold to edit",
|
||||
"create.gui.value_settings.release_to_confirm": "Release %1$s to Confirm",
|
||||
"create.gui.goggles.generator_stats": "Generator Stats:",
|
||||
"create.gui.goggles.kinetic_stats": "Kinetic Stats:",
|
||||
"create.gui.goggles.at_current_speed": "at current speed",
|
||||
|
@ -1374,7 +1395,7 @@
|
|||
"create.weighted_ejector.targeting": "Ejecting to [%1$s,%2$s,%3$s]",
|
||||
"create.weighted_ejector.stack_size": "Ejected Stack Size",
|
||||
|
||||
"create.logistics.when_multiple_outputs_available": "When Multiple Outputs Available",
|
||||
"create.logistics.when_multiple_outputs_available": "Distribution Method",
|
||||
|
||||
"create.mechanical_arm.selection_mode.round_robin": "Round Robin",
|
||||
"create.mechanical_arm.selection_mode.forced_round_robin": "Forced Round Robin",
|
||||
|
|
|
@ -42,8 +42,7 @@ public class AllSpriteShifts {
|
|||
VERTICAL_FRAMED_GLASS = getCT(AllCTTypes.VERTICAL, "palettes/framed_glass", "palettes/vertical_framed_glass"),
|
||||
ORNATE_IRON_WINDOW = vertical("palettes/ornate_iron_window");
|
||||
|
||||
public static final CTSpriteShiftEntry CRAFTER_FRONT =
|
||||
getCT(AllCTTypes.OMNIDIRECTIONAL, "crafter_top", "brass_casing"), CRAFTER_SIDE = vertical("crafter_side"),
|
||||
public static final CTSpriteShiftEntry CRAFTER_SIDE = vertical("crafter_side"),
|
||||
CRAFTER_OTHERSIDE = horizontal("crafter_side"),
|
||||
ANDESITE_ENCASED_COGWHEEL_SIDE = vertical("andesite_encased_cogwheel_side"),
|
||||
ANDESITE_ENCASED_COGWHEEL_OTHERSIDE = horizontal("andesite_encased_cogwheel_side"),
|
||||
|
|
|
@ -20,6 +20,7 @@ import com.simibubi.create.content.schematics.ClientSchematicLoader;
|
|||
import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler;
|
||||
import com.simibubi.create.content.schematics.client.SchematicHandler;
|
||||
import com.simibubi.create.foundation.ClientResourceReloadListener;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsClient;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.gui.UIRenderHelper;
|
||||
import com.simibubi.create.foundation.ponder.content.PonderIndex;
|
||||
|
@ -61,6 +62,7 @@ public class CreateClient {
|
|||
public static final PotatoCannonRenderHandler POTATO_CANNON_RENDER_HANDLER = new PotatoCannonRenderHandler();
|
||||
public static final SoulPulseEffectHandler SOUL_PULSE_EFFECT_HANDLER = new SoulPulseEffectHandler();
|
||||
public static final GlobalRailwayManager RAILWAYS = new GlobalRailwayManager();
|
||||
public static final ValueSettingsClient VALUE_SETTINGS_HANDLER = new ValueSettingsClient();
|
||||
|
||||
public static final ClientResourceReloadListener RESOURCE_RELOAD_LISTENER = new ClientResourceReloadListener();
|
||||
|
||||
|
@ -106,6 +108,7 @@ public class CreateClient {
|
|||
OverlayRegistry.registerOverlayAbove(ForgeIngameGui.HOTBAR_ELEMENT, "Create's Linked Controller", LinkedControllerClientHandler.OVERLAY);
|
||||
OverlayRegistry.registerOverlayAbove(ForgeIngameGui.HOTBAR_ELEMENT, "Create's Schematics", SCHEMATIC_HANDLER.getOverlayRenderer());
|
||||
OverlayRegistry.registerOverlayAbove(ForgeIngameGui.HOTBAR_ELEMENT, "Create's Toolboxes", ToolboxHandlerClient.OVERLAY);
|
||||
OverlayRegistry.registerOverlayAbove(ForgeIngameGui.HOTBAR_ELEMENT, "Create's Value Settings", VALUE_SETTINGS_HANDLER);
|
||||
}
|
||||
|
||||
public static void invalidateRenderers() {
|
||||
|
|
|
@ -48,7 +48,8 @@ public class ContraptionControlsBlockEntity extends SmartBlockEntity {
|
|||
|
||||
@Override
|
||||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
||||
behaviours.add(filtering = new FilteringBehaviour(this, new ControlsSlot()).moveText(new Vec3(-30, 20, 10)));
|
||||
behaviours.add(filtering = new FilteringBehaviour(this, new ControlsSlot()));
|
||||
filtering.setLabel(Lang.translateDirect("contraptions.contoller.target"));
|
||||
}
|
||||
|
||||
public void pressButton() {
|
||||
|
@ -107,13 +108,13 @@ public class ContraptionControlsBlockEntity extends SmartBlockEntity {
|
|||
.color(DyeHelper.DYE_TABLE.get(enabled ? DyeColor.LIME : DyeColor.ORANGE)
|
||||
.getFirst())
|
||||
.component();
|
||||
|
||||
|
||||
if (filter.isEmpty()) {
|
||||
Lang.translate("contraption.controls.all_actor_toggle", state)
|
||||
.sendStatus(player);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Lang.translate("contraption.controls.specific_actor_toggle", filter.getHoverName()
|
||||
.getString(), state)
|
||||
.sendStatus(player);
|
||||
|
@ -125,7 +126,7 @@ public class ContraptionControlsBlockEntity extends SmartBlockEntity {
|
|||
protected Vec3 getLocalOffset(BlockState state) {
|
||||
Direction facing = state.getValue(ControlsBlock.FACING);
|
||||
float yRot = AngleHelper.horizontalAngle(facing);
|
||||
return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 10.875f, 5.1f), yRot, Axis.Y);
|
||||
return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 12f, 5.5f), yRot, Axis.Y);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -47,12 +47,14 @@ public class ContraptionControlsRenderer extends SmartBlockEntityRenderer<Contra
|
|||
BlockState blockState = blockEntity.getBlockState();
|
||||
Direction facing = blockState.getValue(ContraptionControlsBlock.FACING)
|
||||
.getOpposite();
|
||||
Vec3 buttonAxis = VecHelper.rotate(new Vec3(0, 1, -.325), AngleHelper.horizontalAngle(facing), Axis.Y)
|
||||
.scale(-1 / 24f * blockEntity.button.getValue(pt));
|
||||
Vec3 buttonMovementAxis = VecHelper.rotate(new Vec3(0, 1, -.325), AngleHelper.horizontalAngle(facing), Axis.Y);
|
||||
Vec3 buttonMovement = buttonMovementAxis.scale(-0.07f + -1 / 24f * blockEntity.button.getValue(pt));
|
||||
Vec3 buttonOffset = buttonMovementAxis.scale(0.07f);
|
||||
|
||||
ms.pushPose();
|
||||
ms.translate(buttonAxis.x, buttonAxis.y, buttonAxis.z);
|
||||
ms.translate(buttonMovement.x, buttonMovement.y, buttonMovement.z);
|
||||
super.renderSafe(blockEntity, pt, ms, buffer, light, overlay);
|
||||
ms.translate(buttonOffset.x, buttonOffset.y, buttonOffset.z);
|
||||
|
||||
VertexConsumer vc = buffer.getBuffer(RenderType.solid());
|
||||
CachedBufferer.partialFacing(AllPartialModels.CONTRAPTION_CONTROLS_BUTTON, blockState, facing)
|
||||
|
|
|
@ -5,7 +5,6 @@ import static com.simibubi.create.content.contraptions.base.HorizontalKineticBlo
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.simibubi.create.AllSpriteShifts;
|
||||
import com.simibubi.create.content.contraptions.components.crafter.ConnectedInputHandler.ConnectedInput;
|
||||
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
|
||||
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour;
|
||||
|
||||
|
@ -26,23 +25,7 @@ public class CrafterCTBehaviour extends ConnectedTextureBehaviour.Base {
|
|||
return false;
|
||||
if (state.getValue(HORIZONTAL_FACING) != other.getValue(HORIZONTAL_FACING))
|
||||
return false;
|
||||
|
||||
ConnectedInput input1 = CrafterHelper.getInput(reader, pos);
|
||||
ConnectedInput input2 = CrafterHelper.getInput(reader, otherPos);
|
||||
|
||||
if (input1 == null || input2 == null)
|
||||
return false;
|
||||
if (input1.data.isEmpty() || input2.data.isEmpty())
|
||||
return false;
|
||||
try {
|
||||
if (pos.offset(input1.data.get(0))
|
||||
.equals(otherPos.offset(input2.data.get(0))))
|
||||
return true;
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
// race condition. data somehow becomes empty between the last 2 if statements
|
||||
}
|
||||
|
||||
return false;
|
||||
return CrafterHelper.areCraftersConnected(reader, pos, otherPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,7 +50,7 @@ public class CrafterCTBehaviour extends ConnectedTextureBehaviour.Base {
|
|||
boolean isVertical = direction.getAxis()
|
||||
.isVertical();
|
||||
boolean facingX = facing.getAxis() == Axis.X;
|
||||
return isFront ? AllSpriteShifts.CRAFTER_FRONT
|
||||
return isFront ? AllSpriteShifts.BRASS_CASING
|
||||
: isVertical && !facingX ? AllSpriteShifts.CRAFTER_OTHERSIDE : AllSpriteShifts.CRAFTER_SIDE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.simibubi.create.content.contraptions.components.crafter;
|
||||
|
||||
import com.simibubi.create.content.contraptions.components.crafter.ConnectedInputHandler.ConnectedInput;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
@ -18,4 +20,23 @@ public class CrafterHelper {
|
|||
return crafter == null ? null : crafter.input;
|
||||
}
|
||||
|
||||
public static boolean areCraftersConnected(BlockAndTintGetter reader, BlockPos pos, BlockPos otherPos) {
|
||||
ConnectedInput input1 = getInput(reader, pos);
|
||||
ConnectedInput input2 = getInput(reader, otherPos);
|
||||
|
||||
if (input1 == null || input2 == null)
|
||||
return false;
|
||||
if (input1.data.isEmpty() || input2.data.isEmpty())
|
||||
return false;
|
||||
try {
|
||||
if (pos.offset(input1.data.get(0))
|
||||
.equals(otherPos.offset(input2.data.get(0))))
|
||||
return true;
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
// race condition. data somehow becomes empty between the last 2 if statements
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ public class DeployerFilterSlot extends ValueBoxTransform {
|
|||
@Override
|
||||
protected Vec3 getLocalOffset(BlockState state) {
|
||||
Direction facing = state.getValue(DeployerBlock.FACING);
|
||||
Vec3 vec = VecHelper.voxelSpace(8f, 13.5f, 11.5f);
|
||||
Vec3 vec = VecHelper.voxelSpace(8f, 13f, 11.5f);
|
||||
|
||||
float yRot = AngleHelper.horizontalAngle(facing);
|
||||
float xRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0;
|
||||
|
|
|
@ -2,22 +2,29 @@ package com.simibubi.create.content.contraptions.components.motor;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.content.contraptions.base.GeneratingKineticBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.CenteredSideValueBoxTransform;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollValueBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollValueBehaviour.StepContext;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class CreativeMotorBlockEntity extends GeneratingKineticBlockEntity {
|
||||
|
||||
public static final int DEFAULT_SPEED = 16;
|
||||
public static final int MAX_SPEED = 256;
|
||||
|
||||
protected ScrollValueBehaviour generatedSpeed;
|
||||
|
||||
public CreativeMotorBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
|
@ -27,18 +34,12 @@ public class CreativeMotorBlockEntity extends GeneratingKineticBlockEntity {
|
|||
@Override
|
||||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
||||
super.addBehaviours(behaviours);
|
||||
Integer max = AllConfigs.server().kinetics.maxMotorSpeed.get();
|
||||
|
||||
CenteredSideValueBoxTransform slot = new CenteredSideValueBoxTransform(
|
||||
(motor, side) -> motor.getValue(CreativeMotorBlock.FACING) == side.getOpposite());
|
||||
|
||||
generatedSpeed = new ScrollValueBehaviour(Lang.translateDirect("generic.speed"), this, slot);
|
||||
int max = MAX_SPEED;
|
||||
generatedSpeed = new KineticScrollValueBehaviour(Lang.translateDirect("kinetics.creative_motor.rotation_speed"),
|
||||
this, new MotorValueBox());
|
||||
generatedSpeed.between(-max, max);
|
||||
generatedSpeed.value = DEFAULT_SPEED;
|
||||
generatedSpeed.scrollableValue = DEFAULT_SPEED;
|
||||
generatedSpeed.withUnit(i -> Lang.translateDirect("generic.unit.rpm"));
|
||||
generatedSpeed.withCallback(i -> this.updateGeneratedRotation());
|
||||
generatedSpeed.withStepFunction(CreativeMotorBlockEntity::step);
|
||||
behaviours.add(generatedSpeed);
|
||||
}
|
||||
|
||||
|
@ -56,22 +57,40 @@ public class CreativeMotorBlockEntity extends GeneratingKineticBlockEntity {
|
|||
return convertToDirection(generatedSpeed.getValue(), getBlockState().getValue(CreativeMotorBlock.FACING));
|
||||
}
|
||||
|
||||
public static int step(StepContext context) {
|
||||
int current = context.currentValue;
|
||||
int step = 1;
|
||||
class MotorValueBox extends ValueBoxTransform.Sided {
|
||||
|
||||
if (!context.shift) {
|
||||
int magnitude = Math.abs(current) - (context.forward == current > 0 ? 0 : 1);
|
||||
|
||||
if (magnitude >= 4)
|
||||
step *= 4;
|
||||
if (magnitude >= 32)
|
||||
step *= 4;
|
||||
if (magnitude >= 128)
|
||||
step *= 4;
|
||||
@Override
|
||||
protected Vec3 getSouthLocation() {
|
||||
return VecHelper.voxelSpace(8, 8, 12.5);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Vec3 getLocalOffset(BlockState state) {
|
||||
Direction facing = state.getValue(CreativeMotorBlock.FACING);
|
||||
return super.getLocalOffset(state).add(Vec3.atLowerCornerOf(facing.getNormal())
|
||||
.scale(-1 / 16f));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void rotate(BlockState state, PoseStack ms) {
|
||||
super.rotate(state, ms);
|
||||
Direction facing = state.getValue(CreativeMotorBlock.FACING);
|
||||
if (facing.getAxis() == Axis.Y)
|
||||
return;
|
||||
if (getSide() != Direction.UP)
|
||||
return;
|
||||
TransformStack.cast(ms)
|
||||
.rotateZ(-AngleHelper.horizontalAngle(facing) + 180);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSideActive(BlockState state, Direction direction) {
|
||||
Direction facing = state.getValue(CreativeMotorBlock.FACING);
|
||||
if (facing.getAxis() != Axis.Y && direction == Direction.DOWN)
|
||||
return false;
|
||||
return direction.getAxis() != facing.getAxis();
|
||||
}
|
||||
|
||||
return (int) (current + (context.forward ? step : -step) == 0 ? step + 1 : step);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package com.simibubi.create.content.contraptions.components.motor;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollValueBehaviour;
|
||||
import com.simibubi.create.foundation.utility.Components;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
|
||||
public class KineticScrollValueBehaviour extends ScrollValueBehaviour {
|
||||
|
||||
public KineticScrollValueBehaviour(Component label, SmartBlockEntity be, ValueBoxTransform slot) {
|
||||
super(label, be, slot);
|
||||
withFormatter(v -> String.valueOf(Math.abs(v)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) {
|
||||
ImmutableList<Component> rows = ImmutableList.of(Components.literal("\u27f3")
|
||||
.withStyle(ChatFormatting.BOLD),
|
||||
Components.literal("\u27f2")
|
||||
.withStyle(ChatFormatting.BOLD));
|
||||
ValueSettingsFormatter formatter = new ValueSettingsFormatter(this::formatSettings);
|
||||
return new ValueSettingsBoard(label, 256, 32, rows, formatter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueSettings(Player player, ValueSettings valueSetting, boolean ctrlHeld) {
|
||||
int value = Math.max(1, valueSetting.value());
|
||||
if (!valueSetting.equals(getValueSettings()))
|
||||
playFeedbackSound(this);
|
||||
setValue(valueSetting.row() == 0 ? -value : value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSettings getValueSettings() {
|
||||
return new ValueSettings(value < 0 ? 0 : 1, Math.abs(value));
|
||||
}
|
||||
|
||||
public MutableComponent formatSettings(ValueSettings settings) {
|
||||
return Lang.number(Math.max(1, Math.abs(settings.value())))
|
||||
.add(Lang.text(settings.row() == 0 ? "\u27f3" : "\u27f2")
|
||||
.style(ChatFormatting.BOLD))
|
||||
.component();
|
||||
}
|
||||
|
||||
}
|
|
@ -15,8 +15,8 @@ public class SawFilterSlot extends ValueBoxTransform {
|
|||
protected Vec3 getLocalOffset(BlockState state) {
|
||||
if (state.getValue(SawBlock.FACING) != Direction.UP)
|
||||
return null;
|
||||
Vec3 x = VecHelper.voxelSpace(8f, 12.5f, 12.25f);
|
||||
Vec3 z = VecHelper.voxelSpace(12.25f, 12.5f, 8f);
|
||||
Vec3 x = VecHelper.voxelSpace(8f, 12.5f, 11f);
|
||||
Vec3 z = VecHelper.voxelSpace(11f, 12.5f, 8f);
|
||||
return state.getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? z : x;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ public class SteamEngineValueBox extends ValueBoxTransform.Sided {
|
|||
if (engineFacing.getAxis() == Axis.Y)
|
||||
recessed ^= state.getValue(SteamEngineBlock.FACING).getAxis() == Axis.X;
|
||||
|
||||
Vec3 local = VecHelper.voxelSpace(8, recessed ? 13 : 15, 9);
|
||||
Vec3 local = VecHelper.voxelSpace(8, recessed ? 12.5 : 14.5, 9);
|
||||
|
||||
local = VecHelper.rotateCentered(local, roll, Axis.Z);
|
||||
local = VecHelper.rotateCentered(local, horizontalAngle, Axis.Y);
|
||||
|
|
|
@ -7,12 +7,18 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllKeys;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks;
|
||||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.CenteredSideValueBoxTransform;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.BulkScrollValueBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollValueBehaviour;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
|
@ -23,17 +29,24 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.core.Direction.AxisDirection;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
|
||||
public class ChassisBlockEntity extends SmartBlockEntity {
|
||||
|
||||
ScrollValueBehaviour range;
|
||||
|
||||
public int currentlySelectedRange;
|
||||
|
||||
public ChassisBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
}
|
||||
|
@ -41,22 +54,30 @@ public class ChassisBlockEntity extends SmartBlockEntity {
|
|||
@Override
|
||||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
||||
int max = AllConfigs.server().kinetics.maxChassisRange.get();
|
||||
range = new BulkScrollValueBehaviour(Lang.translateDirect("generic.range"), this, new CenteredSideValueBoxTransform(),
|
||||
be -> ((ChassisBlockEntity) be).collectChassisGroup());
|
||||
range = new ChassisScrollValueBehaviour(Lang.translateDirect("contraptions.chassis.range"), this,
|
||||
new CenteredSideValueBoxTransform(), be -> ((ChassisBlockEntity) be).collectChassisGroup());
|
||||
range.requiresWrench();
|
||||
range.between(1, max);
|
||||
range
|
||||
.withClientCallback(
|
||||
i -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ChassisRangeDisplay.display(this)));
|
||||
range.value = max / 2;
|
||||
range.withClientCallback(
|
||||
i -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ChassisRangeDisplay.display(this)));
|
||||
range.setValue(max / 2);
|
||||
range.withFormatter(s -> String.valueOf(currentlySelectedRange));
|
||||
behaviours.add(range);
|
||||
currentlySelectedRange = range.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
if (getBlockState().getBlock() instanceof RadialChassisBlock)
|
||||
range.setLabel(Lang.translateDirect("generic.radius"));
|
||||
range.setLabel(Lang.translateDirect("contraptions.chassis.radius"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void read(CompoundTag tag, boolean clientPacket) {
|
||||
super.read(tag, clientPacket);
|
||||
if (clientPacket)
|
||||
currentlySelectedRange = getRange();
|
||||
}
|
||||
|
||||
public int getRange() {
|
||||
|
@ -67,11 +88,12 @@ public class ChassisBlockEntity extends SmartBlockEntity {
|
|||
if (!(getBlockState().getBlock() instanceof AbstractChassisBlock))
|
||||
return Collections.emptyList();
|
||||
return isRadial() ? getIncludedBlockPositionsRadial(forcedMovement, visualize)
|
||||
: getIncludedBlockPositionsLinear(forcedMovement, visualize);
|
||||
: getIncludedBlockPositionsLinear(forcedMovement, visualize);
|
||||
}
|
||||
|
||||
protected boolean isRadial() {
|
||||
return level.getBlockState(worldPosition).getBlock() instanceof RadialChassisBlock;
|
||||
return level.getBlockState(worldPosition)
|
||||
.getBlock() instanceof RadialChassisBlock;
|
||||
}
|
||||
|
||||
public List<ChassisBlockEntity> collectChassisGroup() {
|
||||
|
@ -149,7 +171,7 @@ public class ChassisBlockEntity extends SmartBlockEntity {
|
|||
AbstractChassisBlock block = (AbstractChassisBlock) state.getBlock();
|
||||
Axis axis = state.getValue(AbstractChassisBlock.AXIS);
|
||||
Direction facing = Direction.get(AxisDirection.POSITIVE, axis);
|
||||
int chassisRange = visualize ? range.scrollableValue : getRange();
|
||||
int chassisRange = visualize ? currentlySelectedRange : getRange();
|
||||
|
||||
for (int offset : new int[] { 1, -1 }) {
|
||||
if (offset == -1)
|
||||
|
@ -183,7 +205,7 @@ public class ChassisBlockEntity extends SmartBlockEntity {
|
|||
BlockState state = level.getBlockState(worldPosition);
|
||||
Axis axis = state.getValue(AbstractChassisBlock.AXIS);
|
||||
AbstractChassisBlock block = (AbstractChassisBlock) state.getBlock();
|
||||
int chassisRange = visualize ? range.scrollableValue : getRange();
|
||||
int chassisRange = visualize ? currentlySelectedRange : getRange();
|
||||
|
||||
for (Direction facing : Iterate.directions) {
|
||||
if (facing.getAxis() == axis)
|
||||
|
@ -229,4 +251,46 @@ public class ChassisBlockEntity extends SmartBlockEntity {
|
|||
return positions;
|
||||
}
|
||||
|
||||
class ChassisScrollValueBehaviour extends BulkScrollValueBehaviour {
|
||||
|
||||
public ChassisScrollValueBehaviour(Component label, SmartBlockEntity be, ValueBoxTransform slot,
|
||||
Function<SmartBlockEntity, List<? extends SmartBlockEntity>> groupGetter) {
|
||||
super(label, be, slot, groupGetter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) {
|
||||
ImmutableList<Component> rows = ImmutableList.of(Lang.translateDirect("contraptions.chassis.distance"));
|
||||
ValueSettingsFormatter formatter =
|
||||
new ValueSettingsFormatter(vs -> new ValueSettings(vs.row(), vs.value() + 1).format());
|
||||
return new ValueSettingsBoard(label, max - 1, 1, rows, formatter);
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void newSettingHovered(ValueSettings valueSetting) {
|
||||
if (!level.isClientSide)
|
||||
return;
|
||||
if (!AllKeys.ctrlDown())
|
||||
currentlySelectedRange = valueSetting.value() + 1;
|
||||
else
|
||||
for (SmartBlockEntity be : getBulk())
|
||||
if (be instanceof ChassisBlockEntity cbe)
|
||||
cbe.currentlySelectedRange = valueSetting.value() + 1;
|
||||
ChassisRangeDisplay.display(ChassisBlockEntity.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueSettings(Player player, ValueSettings vs, boolean ctrlHeld) {
|
||||
super.setValueSettings(player, new ValueSettings(vs.row(), vs.value() + 1), ctrlHeld);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSettings getValueSettings() {
|
||||
ValueSettings vs = super.getValueSettings();
|
||||
return new ValueSettings(vs.row(), vs.value() - 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,10 +36,10 @@ public class ChassisRangeDisplay {
|
|||
this.be = be;
|
||||
timer = DISPLAY_TIME;
|
||||
CreateClient.OUTLINER.showCluster(getOutlineKey(), createSelection(be))
|
||||
.colored(0xFFFFFF)
|
||||
.disableNormals()
|
||||
.lineWidth(1 / 16f)
|
||||
.withFaceTexture(AllSpecialTextures.HIGHLIGHT_CHECKERED);
|
||||
.colored(0xFFFFFF)
|
||||
.disableNormals()
|
||||
.lineWidth(1 / 16f)
|
||||
.withFaceTexture(AllSpecialTextures.HIGHLIGHT_CHECKERED);
|
||||
}
|
||||
|
||||
protected Object getOutlineKey() {
|
||||
|
@ -173,7 +173,7 @@ public class ChassisRangeDisplay {
|
|||
GroupEntry hoveredGroup = new GroupEntry(chassis);
|
||||
|
||||
for (ChassisBlockEntity included : hoveredGroup.includedBEs)
|
||||
CreateClient.OUTLINER.remove(included.getBlockPos());
|
||||
CreateClient.OUTLINER.remove(Pair.of(included.getBlockPos(), 1));
|
||||
|
||||
groupEntries.forEach(entry -> CreateClient.OUTLINER.remove(entry.getOutlineKey()));
|
||||
groupEntries.clear();
|
||||
|
|
|
@ -277,7 +277,7 @@ public class CartAssemblerBlockEntity extends SmartBlockEntity implements IDispl
|
|||
|
||||
@Override
|
||||
protected Vec3 getSouthLocation() {
|
||||
return VecHelper.voxelSpace(8, 8, 18);
|
||||
return VecHelper.voxelSpace(8, 8, 17.5);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -71,10 +71,15 @@ public class SmartFluidPipeBlockEntity extends SmartBlockEntity {
|
|||
@Override
|
||||
protected Vec3 getLocalOffset(BlockState state) {
|
||||
AttachFace face = state.getValue(SmartFluidPipeBlock.FACE);
|
||||
float y = face == AttachFace.CEILING ? 0.3f : face == AttachFace.WALL ? 11.3f : 15.3f;
|
||||
float z = face == AttachFace.CEILING ? 4.6f : face == AttachFace.WALL ? 0.6f : 4.6f;
|
||||
float y = face == AttachFace.CEILING ? 0.55f : face == AttachFace.WALL ? 11.4f : 15.45f;
|
||||
float z = face == AttachFace.CEILING ? 4.6f : face == AttachFace.WALL ? 0.55f : 4.625f;
|
||||
return VecHelper.rotateCentered(VecHelper.voxelSpace(8, y, z), angleY(state), Axis.Y);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getScale() {
|
||||
return super.getScale() * 1.02f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void rotate(BlockState state, PoseStack ms) {
|
||||
|
|
|
@ -123,8 +123,7 @@ public class BasinBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
|
|||
@Override
|
||||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
||||
behaviours.add(new DirectBeltInputBehaviour(this));
|
||||
filtering = new FilteringBehaviour(this, new BasinValueBox()).moveText(new Vec3(2, -8, 0))
|
||||
.withCallback(newFilter -> contentsChanged = true)
|
||||
filtering = new FilteringBehaviour(this, new BasinValueBox()).withCallback(newFilter -> contentsChanged = true)
|
||||
.forRecipes();
|
||||
behaviours.add(filtering);
|
||||
|
||||
|
@ -194,7 +193,7 @@ public class BasinBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
|
|||
visualizedOutputItems.clear();
|
||||
visualizedOutputFluids.clear();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
|
@ -202,7 +201,7 @@ public class BasinBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
|
|||
ItemHelper.dropContents(level, worldPosition, outputInventory);
|
||||
spoutputBuffer.forEach(is -> Block.popResource(level, worldPosition, is));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
|
@ -212,7 +211,7 @@ public class BasinBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
|
|||
public void onEmptied() {
|
||||
getOperator().ifPresent(be -> be.basinRemoved = true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
super.invalidate();
|
||||
|
@ -740,7 +739,7 @@ public class BasinBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
|
|||
|
||||
@Override
|
||||
protected Vec3 getSouthLocation() {
|
||||
return VecHelper.voxelSpace(8, 12, 15.75);
|
||||
return VecHelper.voxelSpace(8, 12, 16.05);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,7 +4,7 @@ import java.util.List;
|
|||
|
||||
import com.simibubi.create.content.contraptions.RotationPropagator;
|
||||
import com.simibubi.create.content.contraptions.base.KineticBlockEntity;
|
||||
import com.simibubi.create.content.contraptions.components.motor.CreativeMotorBlockEntity;
|
||||
import com.simibubi.create.content.contraptions.components.motor.KineticScrollValueBehaviour;
|
||||
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
|
||||
import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel;
|
||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||
|
@ -44,16 +44,13 @@ public class SpeedControllerBlockEntity extends KineticBlockEntity {
|
|||
super.addBehaviours(behaviours);
|
||||
Integer max = AllConfigs.server().kinetics.maxRotationSpeed.get();
|
||||
|
||||
targetSpeed =
|
||||
new ScrollValueBehaviour(Lang.translateDirect("generic.speed"), this, new ControllerValueBoxTransform());
|
||||
targetSpeed = new KineticScrollValueBehaviour(Lang.translateDirect("kinetics.speed_controller.rotation_speed"),
|
||||
this, new ControllerValueBoxTransform());
|
||||
targetSpeed.between(-max, max);
|
||||
targetSpeed.value = DEFAULT_SPEED;
|
||||
targetSpeed.moveText(new Vec3(9, 0, 10));
|
||||
targetSpeed.withUnit(i -> Lang.translateDirect("generic.unit.rpm"));
|
||||
targetSpeed.withCallback(i -> this.updateTargetRotation());
|
||||
targetSpeed.withStepFunction(CreativeMotorBlockEntity::step);
|
||||
behaviours.add(targetSpeed);
|
||||
|
||||
|
||||
registerAwardables(behaviours, AllAdvancements.SPEED_CONTROLLER);
|
||||
}
|
||||
|
||||
|
@ -63,7 +60,7 @@ public class SpeedControllerBlockEntity extends KineticBlockEntity {
|
|||
RotationPropagator.handleRemoved(level, worldPosition, this);
|
||||
removeSource();
|
||||
attachKinetics();
|
||||
|
||||
|
||||
if (isCogwheelPresent() && getSpeed() != 0)
|
||||
award(AllAdvancements.SPEED_CONTROLLER);
|
||||
}
|
||||
|
@ -124,14 +121,15 @@ public class SpeedControllerBlockEntity extends KineticBlockEntity {
|
|||
private boolean isCogwheelPresent() {
|
||||
BlockState stateAbove = level.getBlockState(worldPosition.above());
|
||||
return ICogWheel.isDedicatedCogWheel(stateAbove.getBlock()) && ICogWheel.isLargeCog(stateAbove)
|
||||
&& stateAbove.getValue(CogWheelBlock.AXIS).isHorizontal();
|
||||
&& stateAbove.getValue(CogWheelBlock.AXIS)
|
||||
.isHorizontal();
|
||||
}
|
||||
|
||||
private class ControllerValueBoxTransform extends ValueBoxTransform.Sided {
|
||||
|
||||
@Override
|
||||
protected Vec3 getSouthLocation() {
|
||||
return VecHelper.voxelSpace(8, 11f, 16);
|
||||
return VecHelper.voxelSpace(8, 11f, 15.5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -144,7 +142,7 @@ public class SpeedControllerBlockEntity extends KineticBlockEntity {
|
|||
|
||||
@Override
|
||||
protected float getScale() {
|
||||
return 0.275f;
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public class SmartChuteBlockEntity extends ChuteBlockEntity {
|
|||
|
||||
@Override
|
||||
protected ExtractionCountMode getExtractionMode() {
|
||||
return filtering.isCountVisible() && !filtering.anyAmount() ? ExtractionCountMode.EXACTLY
|
||||
return filtering.isCountVisible() && !filtering.anyAmount() && !filtering.upTo ? ExtractionCountMode.EXACTLY
|
||||
: ExtractionCountMode.UPTO;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,11 @@ public class BrassDiodeBlock extends AbstractDiodeBlock implements IBE<BrassDiod
|
|||
@Override
|
||||
public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player player, InteractionHand pHand,
|
||||
BlockHitResult pHit) {
|
||||
return toggle(pLevel, pPos, pState, player, pHand);
|
||||
}
|
||||
|
||||
public InteractionResult toggle(Level pLevel, BlockPos pPos, BlockState pState, Player player,
|
||||
InteractionHand pHand) {
|
||||
if (!player.mayBuild())
|
||||
return InteractionResult.PASS;
|
||||
if (player.isShiftKeyDown())
|
||||
|
|
|
@ -7,12 +7,10 @@ import java.util.List;
|
|||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollValueBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollValueBehaviour.StepContext;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.block.DiodeBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
|
@ -29,12 +27,11 @@ public abstract class BrassDiodeBlockEntity extends SmartBlockEntity {
|
|||
|
||||
@Override
|
||||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
||||
maxState = new ScrollValueBehaviour(Lang.translateDirect("generic.delay"), this, new BrassDiodeScrollSlot())
|
||||
.between(2, 60 * 20 * 30);
|
||||
maxState.withStepFunction(this::step);
|
||||
maxState = new BrassDiodeScrollValueBehaviour(Lang.translateDirect("logistics.redstone_interval"), this,
|
||||
new BrassDiodeScrollSlot()).between(2, 60 * 20 * 60);
|
||||
maxState.withFormatter(this::format);
|
||||
maxState.withUnit(this::getUnit);
|
||||
maxState.withCallback(this::onMaxDelayChanged);
|
||||
maxState.setValue(2);
|
||||
behaviours.add(maxState);
|
||||
}
|
||||
|
||||
|
@ -76,32 +73,12 @@ public abstract class BrassDiodeBlockEntity extends SmartBlockEntity {
|
|||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
||||
private int step(StepContext context) {
|
||||
int value = context.currentValue;
|
||||
if (!context.forward)
|
||||
value--;
|
||||
|
||||
if (value < 20)
|
||||
return 1;
|
||||
if (value < 20 * 60)
|
||||
return 20;
|
||||
return 20 * 60;
|
||||
}
|
||||
|
||||
private String format(int value) {
|
||||
if (value < 20)
|
||||
if (value < 60)
|
||||
return value + "t";
|
||||
if (value < 20 * 60)
|
||||
return (value / 20) + "s";
|
||||
return (value / 20 / 60) + "m";
|
||||
}
|
||||
|
||||
private Component getUnit(int value) {
|
||||
if (value < 20)
|
||||
return Lang.translateDirect("generic.unit.ticks");
|
||||
if (value < 20 * 60)
|
||||
return Lang.translateDirect("generic.unit.seconds");
|
||||
return Lang.translateDirect("generic.unit.minutes");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ public class BrassDiodeScrollSlot extends ValueBoxTransform {
|
|||
|
||||
@Override
|
||||
protected Vec3 getLocalOffset(BlockState state) {
|
||||
return VecHelper.voxelSpace(8, 3f, 8);
|
||||
return VecHelper.voxelSpace(8, 2.6f, 8);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
package com.simibubi.create.content.logistics.block.diodes;
|
||||
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollValueBehaviour;
|
||||
import com.simibubi.create.foundation.utility.Components;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
|
||||
public class BrassDiodeScrollValueBehaviour extends ScrollValueBehaviour {
|
||||
|
||||
public BrassDiodeScrollValueBehaviour(Component label, SmartBlockEntity be, ValueBoxTransform slot) {
|
||||
super(label, be, slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) {
|
||||
return new ValueSettingsBoard(label, 60, 10,
|
||||
Lang.translatedOptions("generic.unit", "ticks", "seconds", "minutes"),
|
||||
new ValueSettingsFormatter(this::formatSettings));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShortInteract(Player player, InteractionHand hand, Direction side) {
|
||||
BlockState blockState = blockEntity.getBlockState();
|
||||
if (blockState.getBlock()instanceof BrassDiodeBlock bdb)
|
||||
bdb.toggle(getWorld(), getPos(), blockState, player, hand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueSettings(Player player, ValueSettings valueSetting, boolean ctrlHeld) {
|
||||
int value = valueSetting.value();
|
||||
int multiplier = switch (valueSetting.row()) {
|
||||
case 0 -> 1;
|
||||
case 1 -> 20;
|
||||
default -> 60 * 20;
|
||||
};
|
||||
if (!valueSetting.equals(getValueSettings()))
|
||||
playFeedbackSound(this);
|
||||
setValue(Math.max(2, Math.max(1, value) * multiplier));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSettings getValueSettings() {
|
||||
int row = 0;
|
||||
int value = this.value;
|
||||
|
||||
if (value > 60 * 20) {
|
||||
value = value / (60 * 20);
|
||||
row = 2;
|
||||
} else if (value > 60) {
|
||||
value = value / 20;
|
||||
row = 1;
|
||||
}
|
||||
|
||||
return new ValueSettings(row, value);
|
||||
}
|
||||
|
||||
public MutableComponent formatSettings(ValueSettings settings) {
|
||||
int value = Math.max(1, settings.value());
|
||||
return Components.literal(switch (settings.row()) {
|
||||
case 0 -> Math.max(2, value) + "t";
|
||||
case 1 -> "0:" + (value < 10 ? "0" : "") + value;
|
||||
default -> value + ":00";
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,7 @@ import com.simibubi.create.foundation.blockEntity.behaviour.belt.DirectBeltInput
|
|||
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.utility.BlockFace;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
@ -74,7 +75,8 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
|
|||
|
||||
BeltBlockEntity belt = BeltHelper.getSegmentBE(level, worldPosition.below());
|
||||
if (belt != null)
|
||||
return belt.getMovementFacing() == state.getValue(BeltFunnelBlock.HORIZONTAL_FACING) ? Mode.PUSHING_TO_BELT
|
||||
return belt.getMovementFacing() == state.getValue(BeltFunnelBlock.HORIZONTAL_FACING)
|
||||
? Mode.PUSHING_TO_BELT
|
||||
: Mode.TAKING_FROM_BELT;
|
||||
return Mode.INVALID;
|
||||
}
|
||||
|
@ -136,8 +138,9 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
|
|||
|
||||
// Find other entities blocking the extract (only if necessary)
|
||||
int amountToExtract = getAmountToExtract();
|
||||
ExtractionCountMode mode = getModeToExtract();
|
||||
ItemStack stack = invManipulation.simulate()
|
||||
.extract(amountToExtract);
|
||||
.extract(mode, amountToExtract);
|
||||
if (stack.isEmpty())
|
||||
return;
|
||||
for (ItemEntity itemEntity : level.getEntitiesOfClass(ItemEntity.class, area)) {
|
||||
|
@ -146,7 +149,7 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
|
|||
}
|
||||
|
||||
// Extract
|
||||
stack = invManipulation.extract(amountToExtract);
|
||||
stack = invManipulation.extract(mode, amountToExtract);
|
||||
if (stack.isEmpty())
|
||||
return;
|
||||
|
||||
|
@ -176,8 +179,7 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
|
|||
startCooldown();
|
||||
}
|
||||
|
||||
static final AABB coreBB =
|
||||
new AABB(VecHelper.CENTER_OF_ORIGIN, VecHelper.CENTER_OF_ORIGIN).inflate(.75f);
|
||||
static final AABB coreBB = new AABB(VecHelper.CENTER_OF_ORIGIN, VecHelper.CENTER_OF_ORIGIN).inflate(.75f);
|
||||
|
||||
private AABB getEntityOverflowScanningArea() {
|
||||
Direction facing = AbstractFunnelBlock.getFunnelFacing(getBlockState());
|
||||
|
@ -199,8 +201,10 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
|
|||
return;
|
||||
|
||||
int amountToExtract = getAmountToExtract();
|
||||
ItemStack stack = invManipulation.extract(amountToExtract, s -> inputBehaviour.handleInsertion(s, facing, true)
|
||||
.isEmpty());
|
||||
ExtractionCountMode mode = getModeToExtract();
|
||||
ItemStack stack =
|
||||
invManipulation.extract(mode, amountToExtract, s -> inputBehaviour.handleInsertion(s, facing, true)
|
||||
.isEmpty());
|
||||
if (stack.isEmpty())
|
||||
return;
|
||||
flap(false);
|
||||
|
@ -211,13 +215,19 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
|
|||
|
||||
public int getAmountToExtract() {
|
||||
if (!supportsAmountOnFilter())
|
||||
return -1;
|
||||
return 64;
|
||||
int amountToExtract = invManipulation.getAmountFromFilter();
|
||||
if (!filtering.isActive())
|
||||
amountToExtract = 1;
|
||||
return amountToExtract;
|
||||
}
|
||||
|
||||
public ExtractionCountMode getModeToExtract() {
|
||||
if (!supportsAmountOnFilter() || !filtering.isActive())
|
||||
return ExtractionCountMode.UPTO;
|
||||
return invManipulation.getModeFromFilter();
|
||||
}
|
||||
|
||||
private int startCooldown() {
|
||||
return extractionCooldown = AllConfigs.server().logistics.defaultExtractionTimer.get();
|
||||
}
|
||||
|
@ -284,7 +294,8 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
|
|||
|
||||
public void flap(boolean inward) {
|
||||
if (!level.isClientSide) {
|
||||
AllPackets.getChannel().send(packetTarget(), new FunnelFlapPacket(this, inward));
|
||||
AllPackets.getChannel()
|
||||
.send(packetTarget(), new FunnelFlapPacket(this, inward));
|
||||
} else {
|
||||
flap.setValue(inward ? 1 : -1);
|
||||
AllSoundEvents.FUNNEL_FLAP.playAt(level, worldPosition, 1, 1, true);
|
||||
|
@ -336,7 +347,7 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
|
|||
.onFunnelTransfer(level, worldPosition, stack);
|
||||
award(AllAdvancements.FUNNEL);
|
||||
}
|
||||
|
||||
|
||||
private LerpedFloat createChasingFlap() {
|
||||
return LerpedFloat.linear()
|
||||
.startWithValue(.25f)
|
||||
|
|
|
@ -28,7 +28,7 @@ public class FunnelFilterSlotPositioning extends ValueBoxTransform.Sided {
|
|||
return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 15.5f, 13), stateAngle, Axis.Y);
|
||||
case PULLING:
|
||||
case PUSHING:
|
||||
return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 12.1, 8.7f), horizontalAngle, Axis.Y);
|
||||
return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 12.0f, 8.675f), horizontalAngle, Axis.Y);
|
||||
default:
|
||||
case RETRACTED:
|
||||
return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 13, 7.5f), horizontalAngle, Axis.Y);
|
||||
|
@ -41,7 +41,7 @@ public class FunnelFilterSlotPositioning extends ValueBoxTransform.Sided {
|
|||
return VecHelper.rotateCentered(southLocation, horizontalAngle, Axis.Y);
|
||||
}
|
||||
|
||||
return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 12.1, 8.7f), horizontalAngle, Axis.Y);
|
||||
return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 12.2, 8.55f), horizontalAngle, Axis.Y);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,7 +5,6 @@ import java.util.List;
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||
import com.simibubi.create.content.logistics.item.filter.FilterItem;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.item.ItemHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
@ -74,11 +73,13 @@ public class FunnelMovementBehaviour implements MovementBehaviour {
|
|||
|
||||
ItemStack filter = getFilter(context);
|
||||
int filterAmount = context.blockEntityData.getInt("FilterAmount");
|
||||
boolean upTo = context.blockEntityData.getBoolean("UpTo");
|
||||
if (filterAmount <= 0)
|
||||
filterAmount = hasFilter ? AllConfigs.server().logistics.defaultExtractionLimit.get() : 1;
|
||||
filterAmount = hasFilter ? 64 : 1;
|
||||
|
||||
ItemStack extract = ItemHelper.extract(context.contraption.getSharedInventory(),
|
||||
s -> FilterItem.test(world, s, filter), ItemHelper.ExtractionCountMode.UPTO, filterAmount, false);
|
||||
s -> FilterItem.test(world, s, filter),
|
||||
upTo ? ItemHelper.ExtractionCountMode.UPTO : ItemHelper.ExtractionCountMode.EXACTLY, filterAmount, false);
|
||||
|
||||
if (extract.isEmpty())
|
||||
return;
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.mojang.blaze3d.vertex.PoseStack;
|
|||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
|
@ -33,6 +34,7 @@ public class CreativeCrateBlockEntity extends CrateBlockEntity {
|
|||
@Override
|
||||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
||||
behaviours.add(filtering = createFilter());
|
||||
filtering.setLabel(Lang.translateDirect("logistics.creative_crate.supply"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -60,11 +62,11 @@ public class CreativeCrateBlockEntity extends CrateBlockEntity {
|
|||
|
||||
@Override
|
||||
protected Vec3 getLocalOffset(BlockState state) {
|
||||
return new Vec3(0.5, 13 / 16d, 0.5);
|
||||
return new Vec3(0.5, 13.5 / 16d, 0.5);
|
||||
}
|
||||
|
||||
protected float getScale() {
|
||||
return super.getScale() * 1.5f;
|
||||
return super.getScale();
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
@ -598,14 +598,14 @@ public class ArmBlockEntity extends KineticBlockEntity implements ITransformable
|
|||
@Override
|
||||
protected Vec3 getLocalOffset(BlockState state) {
|
||||
int yPos = state.getValue(ArmBlock.CEILING) ? 16 - 3 : 3;
|
||||
Vec3 location = VecHelper.voxelSpace(8, yPos, 15.95);
|
||||
Vec3 location = VecHelper.voxelSpace(8, yPos, 15.5);
|
||||
location = VecHelper.rotateCentered(location, AngleHelper.horizontalAngle(getSide()), Direction.Axis.Y);
|
||||
return location;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getScale() {
|
||||
return .3f;
|
||||
return super.getScale();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import net.minecraft.core.Direction;
|
|||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class ContentObserverBlockEntity extends SmartBlockEntity {
|
||||
|
||||
|
@ -36,7 +35,7 @@ public class ContentObserverBlockEntity extends SmartBlockEntity {
|
|||
|
||||
@Override
|
||||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
||||
filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot()).moveText(new Vec3(0, 5, 0));
|
||||
filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot());
|
||||
behaviours.add(filtering);
|
||||
|
||||
InterfaceProvider towardBlockFacing = InterfaceProvider.towardBlockFacing();
|
||||
|
|
|
@ -20,7 +20,6 @@ import net.minecraft.world.level.block.Block;
|
|||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.ticks.TickPriority;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
|
@ -101,10 +100,10 @@ public class StockpileSwitchBlockEntity extends SmartBlockEntity {
|
|||
|
||||
if (targetBlockEntity instanceof StockpileSwitchObservable observable) {
|
||||
currentLevel = observable.getPercent() / 100f;
|
||||
|
||||
|
||||
} else if (StorageDrawers.isDrawer(targetBlockEntity) && observedInventory.hasInventory()) {
|
||||
currentLevel = StorageDrawers.getTrueFillLevel(observedInventory.getInventory(), filtering);
|
||||
|
||||
|
||||
} else if (observedInventory.hasInventory() || observedTank.hasInventory()) {
|
||||
if (observedInventory.hasInventory()) {
|
||||
// Item inventory
|
||||
|
@ -154,7 +153,7 @@ public class StockpileSwitchBlockEntity extends SmartBlockEntity {
|
|||
|
||||
currentLevel = Mth.clamp(currentLevel, 0, 1);
|
||||
changed = currentLevel != prevLevel;
|
||||
|
||||
|
||||
boolean previouslyPowered = redstoneState;
|
||||
if (redstoneState && currentLevel <= offWhenBelow)
|
||||
redstoneState = false;
|
||||
|
@ -194,8 +193,8 @@ public class StockpileSwitchBlockEntity extends SmartBlockEntity {
|
|||
|
||||
@Override
|
||||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
||||
filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot()).moveText(new Vec3(0, 5, 0))
|
||||
.withCallback($ -> updateCurrentLevel());
|
||||
filtering =
|
||||
new FilteringBehaviour(this, new FilteredDetectorFilterSlot()).withCallback($ -> updateCurrentLevel());
|
||||
behaviours.add(filtering);
|
||||
|
||||
InterfaceProvider towardBlockFacing = InterfaceProvider.towardBlockFacing();
|
||||
|
|
|
@ -15,6 +15,7 @@ import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
|||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
@ -37,6 +38,7 @@ public class TrackObserverBlockEntity extends SmartBlockEntity implements ITrans
|
|||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
||||
behaviours.add(edgePoint = new TrackTargetingBehaviour<>(this, EdgePointType.OBSERVER));
|
||||
behaviours.add(filtering = createFilter().withCallback(this::onFilterChanged));
|
||||
filtering.setLabel(Lang.translateDirect("logistics.train_observer.cargo_filter"));
|
||||
}
|
||||
|
||||
private void onFilterChanged(ItemStack newFilter) {
|
||||
|
@ -102,13 +104,9 @@ public class TrackObserverBlockEntity extends SmartBlockEntity implements ITrans
|
|||
|
||||
@Override
|
||||
protected Vec3 getLocalOffset(BlockState state) {
|
||||
return new Vec3(0.5, 15 / 16d, 0.5);
|
||||
return new Vec3(0.5, 15.5 / 16d, 0.5);
|
||||
}
|
||||
|
||||
protected float getScale() {
|
||||
return super.getScale() * 1.5f;
|
||||
};
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,6 @@ public class ClientEvents {
|
|||
|
||||
SoundScapes.tick();
|
||||
AnimationTickHolder.tick();
|
||||
ScrollValueHandler.tick();
|
||||
|
||||
CreateClient.SCHEMATIC_SENDER.tick();
|
||||
CreateClient.SCHEMATIC_AND_QUILL_HANDLER.tick();
|
||||
|
@ -160,6 +159,8 @@ public class ClientEvents {
|
|||
CameraDistanceModifier.tick();
|
||||
CameraAngleAnimationService.tick();
|
||||
TrainHUD.tick();
|
||||
CreateClient.VALUE_SETTINGS_HANDLER.tick();
|
||||
ScrollValueHandler.tick();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
|
|
@ -7,8 +7,6 @@ import com.simibubi.create.content.curiosities.toolbox.ToolboxHandlerClient;
|
|||
import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler;
|
||||
import com.simibubi.create.content.logistics.trains.entity.TrainRelocator;
|
||||
import com.simibubi.create.content.logistics.trains.track.CurvedTrackInteraction;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringHandler;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollValueHandler;
|
||||
|
||||
import net.minecraft.client.KeyMapping;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -43,8 +41,7 @@ public class InputEvents {
|
|||
double delta = event.getScrollDelta();
|
||||
// CollisionDebugger.onScroll(delta);
|
||||
boolean cancelled = CreateClient.SCHEMATIC_HANDLER.mouseScrolled(delta)
|
||||
|| CreateClient.SCHEMATIC_AND_QUILL_HANDLER.mouseScrolled(delta) || FilteringHandler.onScroll(delta)
|
||||
|| ScrollValueHandler.onScroll(delta) || TrainHUD.onScroll(delta)
|
||||
|| CreateClient.SCHEMATIC_AND_QUILL_HANDLER.mouseScrolled(delta) || TrainHUD.onScroll(delta)
|
||||
|| ElevatorControlsHandler.onScroll(delta);
|
||||
event.setCanceled(cancelled);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.simibubi.create.foundation.blockEntity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -26,7 +27,8 @@ import net.minecraftforge.common.capabilities.Capability;
|
|||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
|
||||
public abstract class SmartBlockEntity extends CachedRenderBBBlockEntity implements IPartialSafeNBT, IInteractionChecker, ISpecialBlockEntityItemRequirement {
|
||||
public abstract class SmartBlockEntity extends CachedRenderBBBlockEntity
|
||||
implements IPartialSafeNBT, IInteractionChecker, ISpecialBlockEntityItemRequirement {
|
||||
|
||||
private final Map<BehaviourType<?>, BlockEntityBehaviour> behaviours = new HashMap<>();
|
||||
private boolean initialized = false;
|
||||
|
@ -51,8 +53,8 @@ public abstract class SmartBlockEntity extends CachedRenderBBBlockEntity impleme
|
|||
public abstract void addBehaviours(List<BlockEntityBehaviour> behaviours);
|
||||
|
||||
/**
|
||||
* Gets called just before reading block entity data for behaviours. Register anything
|
||||
* here that depends on your custom BE data.
|
||||
* Gets called just before reading block entity data for behaviours. Register
|
||||
* anything here that depends on your custom BE data.
|
||||
*/
|
||||
public void addBehavioursDeferred(List<BlockEntityBehaviour> behaviours) {}
|
||||
|
||||
|
@ -173,9 +175,12 @@ public abstract class SmartBlockEntity extends CachedRenderBBBlockEntity impleme
|
|||
return (T) behaviours.get(type);
|
||||
}
|
||||
|
||||
protected void forEachBehaviour(Consumer<BlockEntityBehaviour> action) {
|
||||
behaviours.values()
|
||||
.forEach(action);
|
||||
public void forEachBehaviour(Consumer<BlockEntityBehaviour> action) {
|
||||
getAllBehaviours().forEach(action);
|
||||
}
|
||||
|
||||
public Collection<BlockEntityBehaviour> getAllBehaviours() {
|
||||
return behaviours.values();
|
||||
}
|
||||
|
||||
protected void attachBehaviourLate(BlockEntityBehaviour behaviour) {
|
||||
|
@ -184,8 +189,7 @@ public abstract class SmartBlockEntity extends CachedRenderBBBlockEntity impleme
|
|||
}
|
||||
|
||||
public ItemRequirement getRequiredItems(BlockState state) {
|
||||
return behaviours.values()
|
||||
.stream()
|
||||
return getAllBehaviours().stream()
|
||||
.reduce(ItemRequirement.NONE, (r, b) -> r.union(b.getRequiredItems()), (r, r1) -> r.union(r1));
|
||||
}
|
||||
|
||||
|
@ -208,7 +212,7 @@ public abstract class SmartBlockEntity extends CachedRenderBBBlockEntity impleme
|
|||
public boolean isVirtual() {
|
||||
return virtualMode;
|
||||
}
|
||||
|
||||
|
||||
public boolean isChunkUnloaded() {
|
||||
return chunkUnloaded;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ public class CenteredSideValueBoxTransform extends ValueBoxTransform.Sided {
|
|||
|
||||
@Override
|
||||
protected Vec3 getSouthLocation() {
|
||||
return VecHelper.voxelSpace(8, 8, 16);
|
||||
return VecHelper.voxelSpace(8, 8, 15.5);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,21 +6,22 @@ import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform.Si
|
|||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.INamedIconOptions;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
import com.simibubi.create.foundation.render.SuperRenderTypeBuffer;
|
||||
import com.simibubi.create.foundation.utility.Color;
|
||||
import com.simibubi.create.foundation.utility.Components;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.outliner.ChasingAABBOutline;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.entity.ItemRenderer;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.client.model.ItemMultiLayerBakedModel;
|
||||
|
||||
public class ValueBox extends ChasingAABBOutline {
|
||||
|
||||
|
@ -37,10 +38,12 @@ public class ValueBox extends ChasingAABBOutline {
|
|||
protected ValueBoxTransform transform;
|
||||
protected BlockState blockState;
|
||||
|
||||
protected AllIcons outline = AllIcons.VALUE_BOX_HOVER_4PX;
|
||||
|
||||
public ValueBox(Component label, AABB bb, BlockPos pos) {
|
||||
this(label, bb, pos, Minecraft.getInstance().level.getBlockState(pos));
|
||||
}
|
||||
|
||||
|
||||
public ValueBox(Component label, AABB bb, BlockPos pos, BlockState state) {
|
||||
super(bb);
|
||||
this.label = label;
|
||||
|
@ -53,24 +56,8 @@ public class ValueBox extends ChasingAABBOutline {
|
|||
return this;
|
||||
}
|
||||
|
||||
public ValueBox offsetLabel(Vec3 offset) {
|
||||
this.labelOffset = offset;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueBox subLabel(Component sublabel) {
|
||||
this.sublabel = sublabel;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueBox scrollTooltip(Component scrollTip) {
|
||||
this.scrollTooltip = scrollTip;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueBox withColors(int passive, int highlight) {
|
||||
this.passiveColor = passive;
|
||||
this.highlightColor = highlight;
|
||||
public ValueBox wideOutline() {
|
||||
this.outline = AllIcons.VALUE_BOX_HOVER_6PX;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -94,69 +81,82 @@ public class ValueBox extends ChasingAABBOutline {
|
|||
transformNormals = ms.last()
|
||||
.normal()
|
||||
.copy();
|
||||
params.colored(isPassive ? passiveColor : highlightColor);
|
||||
super.render(ms, buffer, pt);
|
||||
|
||||
float fontScale = hasTransform ? -transform.getFontScale() : -1 / 64f;
|
||||
ms.scale(fontScale, fontScale, fontScale);
|
||||
|
||||
ms.pushPose();
|
||||
renderContents(ms, buffer);
|
||||
ms.popPose();
|
||||
|
||||
if (!isPassive) {
|
||||
ms.pushPose();
|
||||
ms.translate(17.5, -.5, 7);
|
||||
ms.translate(labelOffset.x, labelOffset.y, labelOffset.z);
|
||||
|
||||
renderHoveringText(ms, buffer, label);
|
||||
if (!sublabel.getString().isEmpty()) {
|
||||
ms.translate(0, 10, 0);
|
||||
renderHoveringText(ms, buffer, sublabel);
|
||||
}
|
||||
if (!scrollTooltip.getString().isEmpty()) {
|
||||
ms.translate(0, 10, 0);
|
||||
renderHoveringText(ms, buffer, scrollTooltip, 0x998899, 0x111111);
|
||||
}
|
||||
|
||||
ms.scale(-2.01f, -2.01f, 2.01f);
|
||||
ms.translate(-8 / 16.0, -8 / 16.0, -.5 / 16.0);
|
||||
getOutline().render(ms, buffer, 0xffffff);
|
||||
ms.popPose();
|
||||
}
|
||||
|
||||
float fontScale = hasTransform ? -transform.getFontScale() : -1 / 64f;
|
||||
ms.scale(fontScale, fontScale, fontScale);
|
||||
renderContents(ms, buffer);
|
||||
|
||||
ms.popPose();
|
||||
}
|
||||
|
||||
public AllIcons getOutline() {
|
||||
return outline;
|
||||
}
|
||||
|
||||
public void renderContents(PoseStack ms, MultiBufferSource buffer) {}
|
||||
|
||||
public static class ItemValueBox extends ValueBox {
|
||||
ItemStack stack;
|
||||
int count;
|
||||
boolean upTo;
|
||||
|
||||
public ItemValueBox(Component label, AABB bb, BlockPos pos, ItemStack stack, int count) {
|
||||
public ItemValueBox(Component label, AABB bb, BlockPos pos, ItemStack stack, int count, boolean upTo) {
|
||||
super(label, bb, pos);
|
||||
this.stack = stack;
|
||||
this.count = count;
|
||||
this.upTo = upTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AllIcons getOutline() {
|
||||
if (stack.getItem() instanceof FilterItem)
|
||||
return AllIcons.VALUE_BOX_HOVER_8PX;
|
||||
if (!stack.isEmpty())
|
||||
return AllIcons.VALUE_BOX_HOVER_6PX;
|
||||
return super.getOutline();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderContents(PoseStack ms, MultiBufferSource buffer) {
|
||||
super.renderContents(ms, buffer);
|
||||
if (count == -1)
|
||||
return;
|
||||
|
||||
Font font = Minecraft.getInstance().font;
|
||||
Component countString = Components.literal(count == 0 ? "*" : count + "");
|
||||
boolean wildcard = count == 0 || upTo && count == stack.getMaxStackSize();
|
||||
Component countString = Components.literal(wildcard ? "*" : count + "");
|
||||
ms.translate(17.5f, -5f, 7f);
|
||||
|
||||
boolean isFilter = stack.getItem() instanceof FilterItem;
|
||||
boolean isEmpty = stack.isEmpty();
|
||||
|
||||
ItemRenderer itemRenderer = Minecraft.getInstance()
|
||||
.getItemRenderer();
|
||||
BakedModel modelWithOverrides = itemRenderer.getModel(stack, null, null, 0);
|
||||
boolean blockItem =
|
||||
modelWithOverrides.isGui3d() && !(modelWithOverrides instanceof ItemMultiLayerBakedModel);
|
||||
|
||||
float scale = 1.5f;
|
||||
ms.translate(-font.width(countString), 0, 0);
|
||||
|
||||
if (isFilter)
|
||||
ms.translate(3, 8, 7.25f);
|
||||
ms.translate(-5, 8, 7.25f);
|
||||
else if (isEmpty) {
|
||||
ms.translate(-17, -2, 3f);
|
||||
scale = 2f;
|
||||
}
|
||||
else
|
||||
ms.translate(-7, 10, 10 + 1 / 4f);
|
||||
ms.translate(-15, -1f, -2.75f);
|
||||
scale = 1.65f;
|
||||
} else
|
||||
ms.translate(-7, 10, blockItem ? 10 + 1 / 4f : 0);
|
||||
|
||||
if (wildcard)
|
||||
ms.translate(-1, 3f, 0);
|
||||
|
||||
ms.scale(scale, scale, scale);
|
||||
drawString(ms, buffer, countString, 0, 0, isFilter ? 0xFFFFFF : 0xEDEDED);
|
||||
|
@ -173,7 +173,7 @@ public class ValueBox extends ChasingAABBOutline {
|
|||
super(label, bb, pos);
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
|
||||
public TextValueBox(Component label, AABB bb, BlockPos pos, BlockState state, Component text) {
|
||||
super(label, bb, pos, state);
|
||||
this.text = text;
|
||||
|
@ -183,7 +183,7 @@ public class ValueBox extends ChasingAABBOutline {
|
|||
public void renderContents(PoseStack ms, MultiBufferSource buffer) {
|
||||
super.renderContents(ms, buffer);
|
||||
Font font = Minecraft.getInstance().font;
|
||||
float scale = 4;
|
||||
float scale = 3;
|
||||
ms.scale(scale, scale, 1);
|
||||
ms.translate(-4, -4, 5);
|
||||
|
||||
|
@ -207,27 +207,20 @@ public class ValueBox extends ChasingAABBOutline {
|
|||
|
||||
public IconValueBox(Component label, INamedIconOptions iconValue, AABB bb, BlockPos pos) {
|
||||
super(label, bb, pos);
|
||||
subLabel(Lang.translateDirect(iconValue.getTranslationKey()));
|
||||
icon = iconValue.getIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderContents(PoseStack ms, MultiBufferSource buffer) {
|
||||
super.renderContents(ms, buffer);
|
||||
float scale = 4 * 16;
|
||||
float scale = 2 * 16;
|
||||
ms.scale(scale, scale, scale);
|
||||
ms.translate(-.5f, -.5f, 1 / 32f);
|
||||
ms.translate(-.5f, -.5f, 5 / 32f);
|
||||
icon.render(ms, buffer, 0xFFFFFF);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// util
|
||||
|
||||
protected void renderHoveringText(PoseStack ms, MultiBufferSource buffer, Component text) {
|
||||
renderHoveringText(ms, buffer, text, highlightColor, Color.mixColors(passiveColor, 0, 0.75f));
|
||||
}
|
||||
|
||||
protected void renderHoveringText(PoseStack ms, MultiBufferSource buffer, Component text, int color,
|
||||
int shadowColor) {
|
||||
ms.pushPose();
|
||||
|
@ -237,7 +230,8 @@ public class ValueBox extends ChasingAABBOutline {
|
|||
ms.popPose();
|
||||
}
|
||||
|
||||
private static void drawString(PoseStack ms, MultiBufferSource buffer, Component text, float x, float y, int color) {
|
||||
private static void drawString(PoseStack ms, MultiBufferSource buffer, Component text, float x, float y,
|
||||
int color) {
|
||||
Minecraft.getInstance().font.drawInBatch(text, x, y, color, false, ms.last()
|
||||
.pose(), buffer, false, 0, LightTexture.FULL_BRIGHT);
|
||||
}
|
||||
|
|
|
@ -30,8 +30,8 @@ public class ValueBoxRenderer {
|
|||
.getItemRenderer();
|
||||
BakedModel modelWithOverrides = itemRenderer.getModel(filter, null, null, 0);
|
||||
boolean blockItem = modelWithOverrides.isGui3d() && !(modelWithOverrides instanceof ItemMultiLayerBakedModel);
|
||||
float scale = (!blockItem ? .5f : 1f) - 1 / 64f;
|
||||
float zOffset = (!blockItem ? -.225f : 0) + customZOffset(filter.getItem());
|
||||
float scale = (!blockItem ? .5f : 1f) + 1 / 64f;
|
||||
float zOffset = (!blockItem ? -.15f : 0) + customZOffset(filter.getItem());
|
||||
ms.scale(scale, scale, scale);
|
||||
ms.translate(0, 0, zOffset);
|
||||
itemRenderer.renderStatic(filter, TransformType.FIXED, light, overlay, ms, buffer, 0);
|
||||
|
|
|
@ -54,7 +54,7 @@ public abstract class ValueBoxTransform {
|
|||
}
|
||||
|
||||
protected float getScale() {
|
||||
return .4f;
|
||||
return .5f;
|
||||
}
|
||||
|
||||
protected float getFontScale() {
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour;
|
||||
|
||||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public interface ValueSettingsBehaviour {
|
||||
|
||||
public static record ValueSettings(int row, int value) {
|
||||
|
||||
public MutableComponent format() {
|
||||
return Lang.number(value)
|
||||
.component();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public boolean testHit(Vec3 hit);
|
||||
|
||||
public boolean isActive();
|
||||
|
||||
default boolean onlyVisibleWithWrench() {
|
||||
return false;
|
||||
}
|
||||
|
||||
default void newSettingHovered(ValueSettings valueSetting) {}
|
||||
|
||||
public ValueBoxTransform getSlotPositioning();
|
||||
|
||||
public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult);
|
||||
|
||||
public void setValueSettings(Player player, ValueSettings valueSetting, boolean ctrlDown);
|
||||
|
||||
public ValueSettings getValueSettings();
|
||||
|
||||
default boolean acceptsValueSettings() {
|
||||
return true;
|
||||
}
|
||||
|
||||
default void playFeedbackSound(BlockEntityBehaviour origin) {
|
||||
origin.getWorld()
|
||||
.playSound(null, origin.getPos(), SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, 0.25f, 2f);
|
||||
origin.getWorld()
|
||||
.playSound(null, origin.getPos(), SoundEvents.NOTE_BLOCK_IRON_XYLOPHONE, SoundSource.BLOCKS, 0.03f, 1.125f);
|
||||
}
|
||||
|
||||
default void onShortInteract(Player player, InteractionHand hand, Direction side) {}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
public record ValueSettingsBoard(Component title, int maxValue, int milestoneInterval, List<Component> rows,
|
||||
ValueSettingsFormatter formatter) {
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.gui.ScreenOpener;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.utility.Color;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraftforge.client.gui.ForgeIngameGui;
|
||||
import net.minecraftforge.client.gui.IIngameOverlay;
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
||||
|
||||
public class ValueSettingsClient implements IIngameOverlay {
|
||||
|
||||
private Minecraft mc;
|
||||
|
||||
public int interactHeldTicks = -1;
|
||||
public BlockPos interactHeldPos = null;
|
||||
public BehaviourType<?> interactHeldBehaviour = null;
|
||||
public InteractionHand interactHeldHand = null;
|
||||
public Direction interactHeldFace = null;
|
||||
|
||||
public List<MutableComponent> lastHoverTip;
|
||||
public int hoverTicks;
|
||||
public int hoverWarmup;
|
||||
|
||||
public ValueSettingsClient() {
|
||||
mc = Minecraft.getInstance();
|
||||
}
|
||||
|
||||
public void cancelIfWarmupAlreadyStarted(PlayerInteractEvent.RightClickBlock event) {
|
||||
if (interactHeldTicks != -1 && event.getPos()
|
||||
.equals(interactHeldPos)) {
|
||||
event.setCanceled(true);
|
||||
event.setCancellationResult(InteractionResult.FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
public void startInteractionWith(BlockPos pos, BehaviourType<?> behaviourType, InteractionHand hand,
|
||||
Direction side) {
|
||||
interactHeldTicks = 0;
|
||||
interactHeldPos = pos;
|
||||
interactHeldBehaviour = behaviourType;
|
||||
interactHeldHand = hand;
|
||||
interactHeldFace = side;
|
||||
}
|
||||
|
||||
public void cancelInteraction() {
|
||||
interactHeldTicks = -1;
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (hoverWarmup > 0)
|
||||
hoverWarmup--;
|
||||
if (hoverTicks > 0)
|
||||
hoverTicks--;
|
||||
if (interactHeldTicks == -1)
|
||||
return;
|
||||
Player player = mc.player;
|
||||
|
||||
if (!ValueSettingsInputHandler.canInteract(player)) {
|
||||
cancelInteraction();
|
||||
return;
|
||||
}
|
||||
HitResult hitResult = mc.hitResult;
|
||||
if (!(hitResult instanceof BlockHitResult blockHitResult) || !blockHitResult.getBlockPos()
|
||||
.equals(interactHeldPos)) {
|
||||
cancelInteraction();
|
||||
return;
|
||||
}
|
||||
BlockEntityBehaviour behaviour = BlockEntityBehaviour.get(mc.level, interactHeldPos, interactHeldBehaviour);
|
||||
if (!(behaviour instanceof ValueSettingsBehaviour valueSettingBehaviour)
|
||||
|| !valueSettingBehaviour.testHit(blockHitResult.getLocation())) {
|
||||
cancelInteraction();
|
||||
return;
|
||||
}
|
||||
if (!mc.options.keyUse.isDown()) {
|
||||
AllPackets.getChannel()
|
||||
.sendToServer(
|
||||
new ValueSettingsPacket(interactHeldPos, 0, 0, interactHeldHand, interactHeldFace, false));
|
||||
cancelInteraction();
|
||||
return;
|
||||
}
|
||||
|
||||
if (interactHeldTicks > 3)
|
||||
player.swinging = false;
|
||||
if (interactHeldTicks++ < 5)
|
||||
return;
|
||||
ScreenOpener
|
||||
.open(new ValueSettingsScreen(interactHeldPos, valueSettingBehaviour.createBoard(player, blockHitResult),
|
||||
valueSettingBehaviour.getValueSettings(), valueSettingBehaviour::newSettingHovered));
|
||||
interactHeldTicks = -1;
|
||||
}
|
||||
|
||||
public void showHoverTip(List<MutableComponent> tip) {
|
||||
if (mc.screen != null)
|
||||
return;
|
||||
if (hoverWarmup < 6) {
|
||||
hoverWarmup += 2;
|
||||
return;
|
||||
} else
|
||||
hoverWarmup++;
|
||||
hoverTicks = hoverTicks == 0 ? 11 : Math.max(hoverTicks, 6);
|
||||
lastHoverTip = tip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(ForgeIngameGui gui, PoseStack poseStack, float partialTicks, int width, int height) {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
if (mc.options.hideGui || !ValueSettingsInputHandler.canInteract(mc.player))
|
||||
return;
|
||||
if (hoverTicks == 0 || lastHoverTip == null)
|
||||
return;
|
||||
|
||||
int x = width / 2;
|
||||
int y = height - 93;
|
||||
float alpha = hoverTicks > 5 ? (11 - hoverTicks) / 5f : Math.min(1, hoverTicks / 5f);
|
||||
|
||||
Color color = new Color(0xffffff);
|
||||
Color titleColor = new Color(0xFBDC7D);
|
||||
color.setAlpha(alpha);
|
||||
titleColor.setAlpha(alpha);
|
||||
|
||||
for (int i = 0; i < lastHoverTip.size(); i++) {
|
||||
MutableComponent mutableComponent = lastHoverTip.get(i);
|
||||
mc.font.drawShadow(poseStack, mutableComponent, x - mc.font.width(mutableComponent) / 2, y,
|
||||
(i == 0 ? titleColor : color).getRGB());
|
||||
y += 12;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBehaviour.ValueSettings;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.INamedIconOptions;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
|
||||
public class ValueSettingsFormatter {
|
||||
|
||||
private Function<ValueSettings, MutableComponent> formatter;
|
||||
|
||||
public ValueSettingsFormatter(Function<ValueSettings, MutableComponent> formatter) {
|
||||
this.formatter = formatter;
|
||||
}
|
||||
|
||||
public MutableComponent format(ValueSettings valueSettings) {
|
||||
return formatter.apply(valueSettings);
|
||||
}
|
||||
|
||||
public static class ScrollOptionSettingsFormatter extends ValueSettingsFormatter {
|
||||
|
||||
private INamedIconOptions[] options;
|
||||
|
||||
public ScrollOptionSettingsFormatter(INamedIconOptions[] options) {
|
||||
super(v -> Lang.translateDirect(options[v.value()].getTranslationKey()));
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public AllIcons getIcon(ValueSettings valueSettings) {
|
||||
return options[valueSettings.value()].getIcon();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour;
|
||||
|
||||
import com.simibubi.create.AllTags.AllItemTags;
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.SidedFilteringBehaviour;
|
||||
import com.simibubi.create.foundation.utility.RaycastHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
|
||||
@EventBusSubscriber
|
||||
public class ValueSettingsInputHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onBlockActivated(PlayerInteractEvent.RightClickBlock event) {
|
||||
Level world = event.getWorld();
|
||||
BlockPos pos = event.getPos();
|
||||
Player player = event.getPlayer();
|
||||
InteractionHand hand = event.getHand();
|
||||
|
||||
if (!canInteract(player))
|
||||
return;
|
||||
if (!(world.getBlockEntity(pos)instanceof SmartBlockEntity sbe))
|
||||
return;
|
||||
|
||||
if (event.getSide() == LogicalSide.CLIENT)
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT,
|
||||
() -> () -> CreateClient.VALUE_SETTINGS_HANDLER.cancelIfWarmupAlreadyStarted(event));
|
||||
|
||||
if (event.isCanceled())
|
||||
return;
|
||||
|
||||
for (BlockEntityBehaviour behaviour : sbe.getAllBehaviours()) {
|
||||
if (!(behaviour instanceof ValueSettingsBehaviour valueSettingsBehaviour))
|
||||
continue;
|
||||
|
||||
BlockHitResult ray = RaycastHelper.rayTraceRange(world, player, 10);
|
||||
if (ray == null)
|
||||
return;
|
||||
if (behaviour instanceof SidedFilteringBehaviour) {
|
||||
behaviour = ((SidedFilteringBehaviour) behaviour).get(ray.getDirection());
|
||||
if (behaviour == null)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!valueSettingsBehaviour.isActive())
|
||||
continue;
|
||||
if (valueSettingsBehaviour.onlyVisibleWithWrench()
|
||||
&& !AllItemTags.WRENCH.matches(player.getItemInHand(hand)))
|
||||
continue;
|
||||
if (valueSettingsBehaviour.getSlotPositioning()instanceof ValueBoxTransform.Sided sidedSlot)
|
||||
sidedSlot.fromSide(ray.getDirection());
|
||||
if (!valueSettingsBehaviour.testHit(ray.getLocation()))
|
||||
continue;
|
||||
|
||||
event.setCanceled(true);
|
||||
event.setCancellationResult(InteractionResult.SUCCESS);
|
||||
|
||||
if (!valueSettingsBehaviour.acceptsValueSettings()) {
|
||||
valueSettingsBehaviour.onShortInteract(player, hand, ray.getDirection());
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getSide() == LogicalSide.CLIENT) {
|
||||
BehaviourType<?> type = behaviour.getType();
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.VALUE_SETTINGS_HANDLER
|
||||
.startInteractionWith(pos, type, hand, ray.getDirection()));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean canInteract(Player player) {
|
||||
return player != null && !player.isSpectator() && !player.isShiftKeyDown();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBehaviour.ValueSettings;
|
||||
import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
|
||||
public class ValueSettingsPacket extends BlockEntityConfigurationPacket<SmartBlockEntity> {
|
||||
|
||||
private int row;
|
||||
private int value;
|
||||
private InteractionHand interactHand;
|
||||
private Direction side;
|
||||
private boolean ctrlDown;
|
||||
|
||||
public ValueSettingsPacket(BlockPos pos, int row, int value, @Nullable InteractionHand interactHand, Direction side,
|
||||
boolean ctrlDown) {
|
||||
super(pos);
|
||||
this.row = row;
|
||||
this.value = value;
|
||||
this.interactHand = interactHand;
|
||||
this.side = side;
|
||||
this.ctrlDown = ctrlDown;
|
||||
}
|
||||
|
||||
public ValueSettingsPacket(FriendlyByteBuf buffer) {
|
||||
super(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeSettings(FriendlyByteBuf buffer) {
|
||||
buffer.writeVarInt(value);
|
||||
buffer.writeVarInt(row);
|
||||
buffer.writeBoolean(interactHand != null);
|
||||
if (interactHand != null)
|
||||
buffer.writeBoolean(interactHand == InteractionHand.MAIN_HAND);
|
||||
buffer.writeVarInt(side.ordinal());
|
||||
buffer.writeBoolean(ctrlDown);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readSettings(FriendlyByteBuf buffer) {
|
||||
value = buffer.readVarInt();
|
||||
row = buffer.readVarInt();
|
||||
if (buffer.readBoolean())
|
||||
interactHand = buffer.readBoolean() ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
||||
side = Direction.values()[buffer.readVarInt()];
|
||||
ctrlDown = buffer.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applySettings(ServerPlayer player, SmartBlockEntity be) {
|
||||
for (BlockEntityBehaviour behaviour : be.getAllBehaviours()) {
|
||||
if (!(behaviour instanceof ValueSettingsBehaviour valueSettingsBehaviour))
|
||||
continue;
|
||||
if (!valueSettingsBehaviour.acceptsValueSettings())
|
||||
continue;
|
||||
if (interactHand != null) {
|
||||
valueSettingsBehaviour.onShortInteract(player, interactHand, side);
|
||||
return;
|
||||
}
|
||||
valueSettingsBehaviour.setValueSettings(player, new ValueSettings(row, value), ctrlDown);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applySettings(SmartBlockEntity be) {}
|
||||
|
||||
}
|
|
@ -0,0 +1,315 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllKeys;
|
||||
import com.simibubi.create.AllSoundEvents;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBehaviour.ValueSettings;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter.ScrollOptionSettingsFormatter;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollValueHandler;
|
||||
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
|
||||
import com.simibubi.create.foundation.gui.AllGuiTextures;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
import com.simibubi.create.foundation.gui.UIRenderHelper;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.foundation.utility.Components;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.phys.Vec2;
|
||||
|
||||
public class ValueSettingsScreen extends AbstractSimiScreen {
|
||||
|
||||
private int ticksOpen;
|
||||
private ValueSettingsBoard board;
|
||||
private int maxLabelWidth;
|
||||
private int valueBarWidth;
|
||||
private BlockPos pos;
|
||||
private ValueSettings initialSettings;
|
||||
private ValueSettings lastHovered = new ValueSettings(-1, -1);
|
||||
private Consumer<ValueSettings> onHover;
|
||||
private boolean iconMode;
|
||||
private int milestoneSize;
|
||||
private int soundCoolDown;
|
||||
|
||||
public ValueSettingsScreen(BlockPos pos, ValueSettingsBoard board, ValueSettings valueSettings,
|
||||
Consumer<ValueSettings> onHover) {
|
||||
this.pos = pos;
|
||||
this.board = board;
|
||||
this.initialSettings = valueSettings;
|
||||
this.onHover = onHover;
|
||||
this.iconMode = board.formatter() instanceof ScrollOptionSettingsFormatter;
|
||||
this.milestoneSize = iconMode ? 8 : 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
int maxValue = board.maxValue();
|
||||
maxLabelWidth = 0;
|
||||
int milestoneCount = maxValue / board.milestoneInterval() + 1;
|
||||
int scale = maxValue > 128 ? 1 : 2;
|
||||
|
||||
for (Component component : board.rows())
|
||||
maxLabelWidth = Math.max(maxLabelWidth, font.width(component));
|
||||
if (iconMode)
|
||||
maxLabelWidth = -18;
|
||||
|
||||
valueBarWidth = (maxValue + 1) * scale + 1 + milestoneCount * milestoneSize;
|
||||
int width = (maxLabelWidth + 14) + (valueBarWidth + 10);
|
||||
int height = (board.rows()
|
||||
.size() * 11);
|
||||
|
||||
setWindowSize(width, height);
|
||||
super.init();
|
||||
|
||||
Vec2 coordinateOfValue = getCoordinateOfValue(initialSettings.row(), initialSettings.value());
|
||||
setCursor(coordinateOfValue);
|
||||
}
|
||||
|
||||
private void setCursor(Vec2 coordinateOfValue) {
|
||||
double guiScale = minecraft.getWindow()
|
||||
.getGuiScale();
|
||||
GLFW.glfwSetCursorPos(minecraft.getWindow()
|
||||
.getWindow(), coordinateOfValue.x * guiScale, coordinateOfValue.y * guiScale);
|
||||
}
|
||||
|
||||
public ValueSettings getClosestCoordinate(int mouseX, int mouseY) {
|
||||
int row = 0;
|
||||
int column = 0;
|
||||
boolean milestonesOnly = hasShiftDown();
|
||||
|
||||
double bestDiff = Double.MAX_VALUE;
|
||||
for (; row < board.rows()
|
||||
.size(); row++) {
|
||||
Vec2 coord = getCoordinateOfValue(row, 0);
|
||||
double diff = Math.abs(coord.y - mouseY);
|
||||
if (bestDiff < diff)
|
||||
break;
|
||||
bestDiff = diff;
|
||||
}
|
||||
row -= 1;
|
||||
|
||||
bestDiff = Double.MAX_VALUE;
|
||||
for (; column <= board.maxValue(); column++) {
|
||||
Vec2 coord = getCoordinateOfValue(row, milestonesOnly ? column * board.milestoneInterval() : column);
|
||||
double diff = Math.abs(coord.x - mouseX);
|
||||
if (bestDiff < diff)
|
||||
break;
|
||||
bestDiff = diff;
|
||||
}
|
||||
column -= 1;
|
||||
|
||||
return new ValueSettings(row,
|
||||
milestonesOnly ? Math.min(column * board.milestoneInterval(), board.maxValue()) : column);
|
||||
}
|
||||
|
||||
public Vec2 getCoordinateOfValue(int row, int column) {
|
||||
int scale = board.maxValue() > 128 ? 1 : 2;
|
||||
float xOut =
|
||||
guiLeft + ((Math.max(1, column) - 1) / board.milestoneInterval()) * milestoneSize + column * scale + 1.5f;
|
||||
xOut += maxLabelWidth + 14 + 4;
|
||||
|
||||
if (column % board.milestoneInterval() == 0)
|
||||
xOut += milestoneSize / 2;
|
||||
if (column > 0)
|
||||
xOut += milestoneSize;
|
||||
|
||||
float yOut = guiTop + (row + .5f) * 11 - .5f;
|
||||
return new Vec2(xOut, yOut);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||
int x = guiLeft;
|
||||
int y = guiTop;
|
||||
int milestoneCount = board.maxValue() / board.milestoneInterval() + 1;
|
||||
int blitOffset = getBlitOffset();
|
||||
int scale = board.maxValue() > 128 ? 1 : 2;
|
||||
|
||||
Component title = board.title();
|
||||
Component tip = Lang.translateDirect("gui.value_settings.release_to_confirm", Components.keybind("key.use"));
|
||||
double fadeIn = Math.pow(Mth.clamp((ticksOpen + partialTicks) / 4.0, 0, 1), 1);
|
||||
|
||||
int fattestLabel = Math.max(font.width(tip), font.width(title));
|
||||
if (iconMode)
|
||||
for (int i = 0; i <= board.maxValue(); i++)
|
||||
fattestLabel = Math.max(fattestLabel, font.width(board.formatter()
|
||||
.format(new ValueSettings(0, i))));
|
||||
|
||||
int fatTipOffset = Math.max(0, fattestLabel + 10 - (windowWidth + 13)) / 2;
|
||||
int bgWidth = Math.max((windowWidth + 13), fattestLabel + 10);
|
||||
int fadeInWidth = (int) (bgWidth * fadeIn);
|
||||
int fadeInStart = (bgWidth - fadeInWidth) / 2 - fatTipOffset;
|
||||
int additionalHeight = iconMode ? 46 : 33;
|
||||
|
||||
UIRenderHelper.drawStretched(ms, x - 11 + fadeInStart, y - 17, fadeInWidth, windowHeight + additionalHeight,
|
||||
blitOffset, AllGuiTextures.VALUE_SETTINGS_OUTER_BG);
|
||||
UIRenderHelper.drawStretched(ms, x - 10 + fadeInStart, y - 18, fadeInWidth - 2, 1, blitOffset,
|
||||
AllGuiTextures.VALUE_SETTINGS_OUTER_BG);
|
||||
UIRenderHelper.drawStretched(ms, x - 10 + fadeInStart, y - 17 + windowHeight + additionalHeight,
|
||||
fadeInWidth - 2, 1, blitOffset, AllGuiTextures.VALUE_SETTINGS_OUTER_BG);
|
||||
|
||||
if (fadeInWidth > fattestLabel) {
|
||||
int textX = x - 11 - fatTipOffset + bgWidth / 2;
|
||||
font.draw(ms, title, textX - font.width(title) / 2, y - 14, 0xdddddd);
|
||||
font.draw(ms, tip, textX - font.width(tip) / 2, y + windowHeight + additionalHeight - 27, 0xdddddd);
|
||||
}
|
||||
|
||||
renderBrassFrame(ms, x + maxLabelWidth + 14, y - 3, valueBarWidth + 8, board.rows()
|
||||
.size() * 11 + 5);
|
||||
UIRenderHelper.drawStretched(ms, x + maxLabelWidth + 17, y, valueBarWidth + 2, board.rows()
|
||||
.size() * 11 - 1, blitOffset, AllGuiTextures.VALUE_SETTINGS_BAR_BG);
|
||||
|
||||
int originalY = y;
|
||||
for (Component component : board.rows()) {
|
||||
int valueBarX = x + maxLabelWidth + 14 + 4;
|
||||
|
||||
if (!iconMode) {
|
||||
UIRenderHelper.drawCropped(ms, x - 4, y, maxLabelWidth + 8, 11, blitOffset,
|
||||
AllGuiTextures.VALUE_SETTINGS_LABEL_BG);
|
||||
for (int w = 0; w < valueBarWidth; w += AllGuiTextures.VALUE_SETTINGS_BAR.width - 1)
|
||||
UIRenderHelper.drawCropped(ms, valueBarX + w, y + 1,
|
||||
Math.min(AllGuiTextures.VALUE_SETTINGS_BAR.width - 1, valueBarWidth - w), 8, blitOffset,
|
||||
AllGuiTextures.VALUE_SETTINGS_BAR);
|
||||
font.draw(ms, component, x, y + 1, 0x442000);
|
||||
}
|
||||
|
||||
int milestoneX = valueBarX;
|
||||
for (int milestone = 0; milestone < milestoneCount; milestone++) {
|
||||
if (iconMode)
|
||||
AllGuiTextures.VALUE_SETTINGS_WIDE_MILESTONE.render(ms, milestoneX, y + 1);
|
||||
else
|
||||
AllGuiTextures.VALUE_SETTINGS_MILESTONE.render(ms, milestoneX, y + 1);
|
||||
milestoneX += milestoneSize + board.milestoneInterval() * scale;
|
||||
}
|
||||
|
||||
y += 11;
|
||||
}
|
||||
|
||||
if (!iconMode)
|
||||
renderBrassFrame(ms, x - 7, originalY - 3, maxLabelWidth + 14, board.rows()
|
||||
.size() * 11 + 5);
|
||||
|
||||
if (ticksOpen < 1)
|
||||
return;
|
||||
|
||||
ValueSettings closest = getClosestCoordinate(mouseX, mouseY);
|
||||
|
||||
if (!closest.equals(lastHovered)) {
|
||||
onHover.accept(closest);
|
||||
if (soundCoolDown == 0) {
|
||||
float pitch = (closest.value()) / (float) (board.maxValue());
|
||||
pitch = Mth.lerp(pitch, 1.15f, 1.5f);
|
||||
minecraft.getSoundManager()
|
||||
.play(SimpleSoundInstance.forUI(AllSoundEvents.SCROLL_VALUE.getMainEvent(), pitch, 0.25F));
|
||||
ScrollValueHandler.wrenchCog.bump(3, -(closest.value() - lastHovered.value()) * 10);
|
||||
soundCoolDown = 1;
|
||||
}
|
||||
}
|
||||
lastHovered = closest;
|
||||
|
||||
Vec2 coordinate = getCoordinateOfValue(closest.row(), closest.value());
|
||||
Component cursorText = board.formatter()
|
||||
.format(closest);
|
||||
|
||||
AllIcons cursorIcon = null;
|
||||
if (board.formatter()instanceof ScrollOptionSettingsFormatter sosf)
|
||||
cursorIcon = sosf.getIcon(closest);
|
||||
|
||||
int cursorWidth = ((cursorIcon != null ? 16 : font.width(cursorText)) / 2) * 2 + 3;
|
||||
int cursorX = ((int) (coordinate.x)) - cursorWidth / 2;
|
||||
int cursorY = ((int) (coordinate.y)) - 7;
|
||||
|
||||
if (cursorIcon != null) {
|
||||
AllGuiTextures.VALUE_SETTINGS_CURSOR_ICON.render(ms, cursorX - 2, cursorY - 3);
|
||||
RenderSystem.setShaderColor(0.265625f, 0.125f, 0, 1);
|
||||
cursorIcon.render(ms, cursorX + 1, cursorY - 1);
|
||||
RenderSystem.setShaderColor(1, 1, 1, 1);
|
||||
if (fadeInWidth > fattestLabel)
|
||||
font.draw(ms, cursorText, x - 11 - fatTipOffset + (bgWidth - font.width(cursorText)) / 2,
|
||||
originalY + windowHeight + additionalHeight - 40, 0xFBDC7D);
|
||||
return;
|
||||
}
|
||||
|
||||
AllGuiTextures.VALUE_SETTINGS_CURSOR_LEFT.render(ms, cursorX - 3, cursorY);
|
||||
UIRenderHelper.drawCropped(ms, cursorX, cursorY, cursorWidth, 14, blitOffset,
|
||||
AllGuiTextures.VALUE_SETTINGS_CURSOR);
|
||||
AllGuiTextures.VALUE_SETTINGS_CURSOR_RIGHT.render(ms, cursorX + cursorWidth, cursorY);
|
||||
|
||||
font.draw(ms, cursorText, cursorX + 2, cursorY + 3, 0x442000);
|
||||
}
|
||||
|
||||
protected void renderBrassFrame(PoseStack ms, int x, int y, int w, int h) {
|
||||
AllGuiTextures.BRASS_FRAME_TL.render(ms, x, y);
|
||||
AllGuiTextures.BRASS_FRAME_TR.render(ms, x + w - 4, y);
|
||||
AllGuiTextures.BRASS_FRAME_BL.render(ms, x, y + h - 4);
|
||||
AllGuiTextures.BRASS_FRAME_BR.render(ms, x + w - 4, y + h - 4);
|
||||
|
||||
if (h > 8) {
|
||||
UIRenderHelper.drawStretched(ms, x, y + 4, 3, h - 8, getBlitOffset(), AllGuiTextures.BRASS_FRAME_LEFT);
|
||||
UIRenderHelper.drawStretched(ms, x + w - 3, y + 4, 3, h - 8, getBlitOffset(),
|
||||
AllGuiTextures.BRASS_FRAME_RIGHT);
|
||||
}
|
||||
|
||||
if (w > 8) {
|
||||
UIRenderHelper.drawCropped(ms, x + 4, y, w - 8, 3, getBlitOffset(), AllGuiTextures.BRASS_FRAME_TOP);
|
||||
UIRenderHelper.drawCropped(ms, x + 4, y + h - 3, w - 8, 3, getBlitOffset(),
|
||||
AllGuiTextures.BRASS_FRAME_BOTTOM);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderBackground(PoseStack p_238651_1_, int p_238651_2_) {
|
||||
int a = ((int) (0x50 * Math.min(1, (ticksOpen + AnimationTickHolder.getPartialTicks()) / 20f))) << 24;
|
||||
fillGradient(p_238651_1_, 0, 0, this.width, this.height, 0x101010 | a, 0x101010 | a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
ticksOpen++;
|
||||
if (soundCoolDown > 0)
|
||||
soundCoolDown--;
|
||||
super.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(double pMouseX, double pMouseY, double pDelta) {
|
||||
ValueSettings closest = getClosestCoordinate((int) pMouseX, (int) pMouseY);
|
||||
int column = closest.value() + ((int) Math.signum(pDelta)) * (hasShiftDown() ? board.milestoneInterval() : 1);
|
||||
column = Mth.clamp(column, 0, board.maxValue());
|
||||
if (column == closest.value())
|
||||
return false;
|
||||
setCursor(getCoordinateOfValue(closest.row(), column));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseReleased(double pMouseX, double pMouseY, int pButton) {
|
||||
if (pButton == 1) {
|
||||
ValueSettings closest = getClosestCoordinate((int) pMouseX, (int) pMouseY);
|
||||
// FIXME: value settings may be face-sensitive on future components
|
||||
AllPackets.getChannel()
|
||||
.sendToServer(new ValueSettingsPacket(pos, closest.row(), closest.value(), null, Direction.UP,
|
||||
AllKeys.ctrlDown()));
|
||||
onClose();
|
||||
return true;
|
||||
}
|
||||
return super.mouseReleased(pMouseX, pMouseY, pButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
}
|
|
@ -96,7 +96,7 @@ public class EdgeInteractionHandler {
|
|||
int x = vec.getX();
|
||||
int y = vec.getY();
|
||||
int z = vec.getZ();
|
||||
double margin = 12 / 16f;
|
||||
double margin = 10 / 16f;
|
||||
double absX = Math.abs(x) * margin;
|
||||
double absY = Math.abs(y) * margin;
|
||||
double absZ = Math.abs(z) * margin;
|
||||
|
|
|
@ -1,21 +1,26 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour.edgeInteraction;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.AllSpecialTextures;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.content.contraptions.components.crafter.CrafterHelper;
|
||||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
|
||||
import com.simibubi.create.foundation.utility.Components;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.AxisDirection;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
|
@ -52,8 +57,9 @@ public class EdgeInteractionRenderer {
|
|||
double bestDistance = Double.MAX_VALUE;
|
||||
Vec3 center = VecHelper.getCenterOf(pos);
|
||||
for (Direction direction : connectiveSides) {
|
||||
double distance = Vec3.atLowerCornerOf(direction.getNormal()).subtract(target.getLocation()
|
||||
.subtract(center))
|
||||
double distance = Vec3.atLowerCornerOf(direction.getNormal())
|
||||
.subtract(target.getLocation()
|
||||
.subtract(center))
|
||||
.length();
|
||||
if (distance > bestDistance)
|
||||
continue;
|
||||
|
@ -63,31 +69,51 @@ public class EdgeInteractionRenderer {
|
|||
|
||||
AABB bb = EdgeInteractionHandler.getBB(pos, closestEdge);
|
||||
boolean hit = bb.contains(target.getLocation());
|
||||
Vec3 offset = Vec3.atLowerCornerOf(closestEdge.getNormal())
|
||||
.scale(.5)
|
||||
.add(Vec3.atLowerCornerOf(face.getNormal())
|
||||
.scale(.469))
|
||||
.add(VecHelper.CENTER_OF_ORIGIN);
|
||||
|
||||
ValueBox box = new ValueBox(Components.immutableEmpty(), bb.move(-pos.getX(), -pos.getY(), -pos.getZ()), pos);
|
||||
Vec3 textOffset = Vec3.ZERO;
|
||||
ValueBox box = new ValueBox(Components.immutableEmpty(), bb, pos).passive(!hit)
|
||||
.transform(new EdgeValueBoxTransform(offset))
|
||||
.wideOutline();
|
||||
CreateClient.OUTLINER.showValueBox("edge", box)
|
||||
.highlightFace(face);
|
||||
|
||||
boolean positive = closestEdge.getAxisDirection() == AxisDirection.POSITIVE;
|
||||
if (positive) {
|
||||
if (face.getAxis()
|
||||
.isHorizontal()) {
|
||||
if (closestEdge.getAxis()
|
||||
.isVertical())
|
||||
textOffset = textOffset.add(0, -128, 0);
|
||||
else
|
||||
textOffset = textOffset.add(-128, 0, 0);
|
||||
} else
|
||||
textOffset = textOffset.add(-128, 0, 0);
|
||||
if (!hit)
|
||||
return;
|
||||
|
||||
List<MutableComponent> tip = new ArrayList<>();
|
||||
tip.add(Lang.translateDirect("logistics.crafter.connected"));
|
||||
tip.add(Lang.translateDirect(CrafterHelper.areCraftersConnected(world, pos, pos.relative(closestEdge))
|
||||
? "logistics.crafter.click_to_separate"
|
||||
: "logistics.crafter.click_to_merge"));
|
||||
CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip);
|
||||
}
|
||||
|
||||
static class EdgeValueBoxTransform extends ValueBoxTransform.Sided {
|
||||
|
||||
private Vec3 add;
|
||||
|
||||
public EdgeValueBoxTransform(Vec3 add) {
|
||||
this.add = add;
|
||||
}
|
||||
|
||||
box.offsetLabel(textOffset)
|
||||
.withColors(0x7A6A2C, 0xB79D64)
|
||||
.passive(!hit);
|
||||
@Override
|
||||
protected Vec3 getSouthLocation() {
|
||||
return Vec3.ZERO;
|
||||
}
|
||||
|
||||
CreateClient.OUTLINER.showValueBox("edge", box)
|
||||
.lineWidth(1 / 64f)
|
||||
.withFaceTexture(hit ? AllSpecialTextures.THIN_CHECKERED : null)
|
||||
.highlightFace(face);
|
||||
@Override
|
||||
protected Vec3 getLocalOffset(BlockState state) {
|
||||
return add;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void rotate(BlockState state, PoseStack ms) {
|
||||
super.rotate(state, ms);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -3,43 +3,55 @@ package com.simibubi.create.foundation.blockEntity.behaviour.filtering;
|
|||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.content.logistics.item.filter.FilterItem;
|
||||
import com.simibubi.create.content.schematics.ItemRequirement;
|
||||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter;
|
||||
import com.simibubi.create.foundation.utility.Components;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
|
||||
public class FilteringBehaviour extends BlockEntityBehaviour {
|
||||
public class FilteringBehaviour extends BlockEntityBehaviour implements ValueSettingsBehaviour {
|
||||
|
||||
public static final BehaviourType<FilteringBehaviour> TYPE = new BehaviourType<>();
|
||||
|
||||
public MutableComponent customLabel;
|
||||
ValueBoxTransform slotPositioning;
|
||||
boolean showCount;
|
||||
Vec3 textShift;
|
||||
|
||||
private ItemStack filter;
|
||||
public int count;
|
||||
public boolean upTo;
|
||||
|
||||
private Consumer<ItemStack> callback;
|
||||
private Supplier<Boolean> isActive;
|
||||
private Supplier<Boolean> showCountPredicate;
|
||||
|
||||
int scrollableValue;
|
||||
int ticksUntilScrollPacket;
|
||||
boolean forceClientState;
|
||||
boolean recipeFilter;
|
||||
boolean fluidFilter;
|
||||
|
||||
|
@ -51,26 +63,23 @@ public class FilteringBehaviour extends BlockEntityBehaviour {
|
|||
callback = stack -> {
|
||||
};
|
||||
isActive = () -> true;
|
||||
textShift = Vec3.ZERO;
|
||||
count = 0;
|
||||
ticksUntilScrollPacket = -1;
|
||||
count = 64;
|
||||
showCountPredicate = () -> showCount;
|
||||
recipeFilter = false;
|
||||
fluidFilter = false;
|
||||
upTo = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSafeNBT() { return true; }
|
||||
public boolean isSafeNBT() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(CompoundTag nbt, boolean clientPacket) {
|
||||
nbt.put("Filter", getFilter().serializeNBT());
|
||||
nbt.putInt("FilterAmount", count);
|
||||
|
||||
if (clientPacket && forceClientState) {
|
||||
nbt.putBoolean("ForceScrollable", true);
|
||||
forceClientState = false;
|
||||
}
|
||||
nbt.putBoolean("UpTo", upTo);
|
||||
super.write(nbt, clientPacket);
|
||||
}
|
||||
|
||||
|
@ -78,30 +87,10 @@ public class FilteringBehaviour extends BlockEntityBehaviour {
|
|||
public void read(CompoundTag nbt, boolean clientPacket) {
|
||||
filter = ItemStack.of(nbt.getCompound("Filter"));
|
||||
count = nbt.getInt("FilterAmount");
|
||||
if (nbt.contains("ForceScrollable")) {
|
||||
scrollableValue = count;
|
||||
ticksUntilScrollPacket = -1;
|
||||
}
|
||||
upTo = nbt.getBoolean("UpTo");
|
||||
super.read(nbt, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
if (!getWorld().isClientSide)
|
||||
return;
|
||||
if (ticksUntilScrollPacket == -1)
|
||||
return;
|
||||
if (ticksUntilScrollPacket > 0) {
|
||||
ticksUntilScrollPacket--;
|
||||
return;
|
||||
}
|
||||
|
||||
AllPackets.getChannel().sendToServer(new FilteringCountUpdatePacket(getPos(), scrollableValue));
|
||||
ticksUntilScrollPacket = -1;
|
||||
}
|
||||
|
||||
public FilteringBehaviour withCallback(Consumer<ItemStack> filterCallback) {
|
||||
callback = filterCallback;
|
||||
return this;
|
||||
|
@ -132,33 +121,38 @@ public class FilteringBehaviour extends BlockEntityBehaviour {
|
|||
return this;
|
||||
}
|
||||
|
||||
public FilteringBehaviour moveText(Vec3 shift) {
|
||||
textShift = shift;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
scrollableValue = count;
|
||||
}
|
||||
|
||||
public void setFilter(Direction face, ItemStack stack) {
|
||||
setFilter(stack);
|
||||
}
|
||||
|
||||
public void setLabel(MutableComponent label) {
|
||||
this.customLabel = label;
|
||||
}
|
||||
|
||||
public void setFilter(ItemStack stack) {
|
||||
boolean confirm = ItemHandlerHelper.canItemStacksStack(stack, filter);
|
||||
filter = stack.copy();
|
||||
callback.accept(filter);
|
||||
count = !confirm ? 0
|
||||
: (filter.getItem() instanceof FilterItem) ? 0 : Math.min(stack.getCount(), stack.getMaxStackSize());
|
||||
forceClientState = true;
|
||||
|
||||
count = Math.min(count, stack.getMaxStackSize());
|
||||
blockEntity.setChanged();
|
||||
blockEntity.sendData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueSettings(Player player, ValueSettings settings, boolean ctrlDown) {
|
||||
if (getValueSettings().equals(settings))
|
||||
return;
|
||||
count = Mth.clamp(settings.value(), 1, filter.getMaxStackSize());
|
||||
upTo = settings.row() == 0;
|
||||
blockEntity.setChanged();
|
||||
blockEntity.sendData();
|
||||
playFeedbackSound(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSettings getValueSettings() {
|
||||
return new ValueSettings(upTo ? 0 : 1, count == 0 ? filter.getMaxStackSize() : count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
if (filter.getItem() instanceof FilterItem) {
|
||||
|
@ -166,7 +160,6 @@ public class FilteringBehaviour extends BlockEntityBehaviour {
|
|||
Level world = getWorld();
|
||||
world.addFreshEntity(new ItemEntity(world, pos.x, pos.y, pos.z, filter.copy()));
|
||||
}
|
||||
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
|
@ -188,7 +181,7 @@ public class FilteringBehaviour extends BlockEntityBehaviour {
|
|||
}
|
||||
|
||||
public boolean isCountVisible() {
|
||||
return showCountPredicate.get();
|
||||
return showCountPredicate.get() && filter.getMaxStackSize() > 1;
|
||||
}
|
||||
|
||||
public boolean test(ItemStack stack) {
|
||||
|
@ -204,6 +197,7 @@ public class FilteringBehaviour extends BlockEntityBehaviour {
|
|||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testHit(Vec3 hit) {
|
||||
BlockState state = blockEntity.getBlockState();
|
||||
Vec3 localHit = hit.subtract(Vec3.atLowerCornerOf(blockEntity.getBlockPos()));
|
||||
|
@ -218,8 +212,74 @@ public class FilteringBehaviour extends BlockEntityBehaviour {
|
|||
return count == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsValueSettings() {
|
||||
return isCountVisible();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return isActive.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueBoxTransform getSlotPositioning() {
|
||||
return slotPositioning;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) {
|
||||
ItemStack filter = getFilter(hitResult.getDirection());
|
||||
int maxAmount = (filter.getItem() instanceof FilterItem) ? 64 : filter.getMaxStackSize();
|
||||
return new ValueSettingsBoard(Lang.translateDirect("logistics.filter.extracted_amount"), maxAmount, 16,
|
||||
Lang.translatedOptions("logistics.filter", "up_to", "exactly"),
|
||||
new ValueSettingsFormatter(this::formatValue));
|
||||
}
|
||||
|
||||
public MutableComponent formatValue(ValueSettings value) {
|
||||
if (value.row() == 0 && value.value() == filter.getMaxStackSize())
|
||||
return Components.literal("Any");
|
||||
return Components.literal(((value.row() == 0) ? "\u2264" : "=") + Math.max(1, value.value()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShortInteract(Player player, InteractionHand hand, Direction side) {
|
||||
Level level = getWorld();
|
||||
BlockPos pos = getPos();
|
||||
ItemStack toApply = player.getItemInHand(hand)
|
||||
.copy();
|
||||
|
||||
if (AllItems.WRENCH.isIn(toApply))
|
||||
return;
|
||||
if (AllBlocks.MECHANICAL_ARM.isIn(toApply))
|
||||
return;
|
||||
if (level.isClientSide())
|
||||
return;
|
||||
|
||||
if (!player.isCreative()) {
|
||||
if (toApply.getItem() instanceof FilterItem) {
|
||||
if (toApply.getCount() == 1)
|
||||
player.setItemInHand(hand, ItemStack.EMPTY);
|
||||
else
|
||||
player.getItemInHand(hand)
|
||||
.shrink(1);
|
||||
}
|
||||
if (getFilter().getItem() instanceof FilterItem)
|
||||
player.getInventory()
|
||||
.placeItemBackInInventory(getFilter());
|
||||
}
|
||||
if (toApply.getItem() instanceof FilterItem)
|
||||
toApply.setCount(1);
|
||||
|
||||
setFilter(side, toApply);
|
||||
level.playSound(null, pos, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, .25f, .1f);
|
||||
}
|
||||
|
||||
public MutableComponent getLabel() {
|
||||
if (customLabel != null)
|
||||
return customLabel;
|
||||
return Lang.translateDirect(
|
||||
recipeFilter ? "logistics.recipe_filter" : fluidFilter ? "logistics.fluid_filter" : "logistics.filter");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour.filtering;
|
||||
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
public class FilteringCountUpdatePacket extends BlockEntityConfigurationPacket<SmartBlockEntity> {
|
||||
|
||||
int amount;
|
||||
|
||||
public FilteringCountUpdatePacket(FriendlyByteBuf buffer) {
|
||||
super(buffer);
|
||||
}
|
||||
|
||||
public FilteringCountUpdatePacket(BlockPos pos, int amount) {
|
||||
super(pos);
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeSettings(FriendlyByteBuf buffer) {
|
||||
buffer.writeInt(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readSettings(FriendlyByteBuf buffer) {
|
||||
amount = buffer.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applySettings(SmartBlockEntity be) {
|
||||
FilteringBehaviour behaviour = be.getBehaviour(FilteringBehaviour.TYPE);
|
||||
if (behaviour == null)
|
||||
return;
|
||||
behaviour.forceClientState = true;
|
||||
behaviour.count = amount;
|
||||
be.setChanged();
|
||||
be.sendData();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,152 +0,0 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour.filtering;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.AllKeys;
|
||||
import com.simibubi.create.AllSoundEvents;
|
||||
import com.simibubi.create.content.logistics.item.filter.FilterItem;
|
||||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform.Sided;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.RaycastHelper;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
|
||||
@EventBusSubscriber
|
||||
public class FilteringHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onBlockActivated(PlayerInteractEvent.RightClickBlock event) {
|
||||
Level world = event.getWorld();
|
||||
BlockPos pos = event.getPos();
|
||||
Player player = event.getPlayer();
|
||||
InteractionHand hand = event.getHand();
|
||||
|
||||
if (player.isShiftKeyDown() || player.isSpectator())
|
||||
return;
|
||||
|
||||
FilteringBehaviour behaviour = BlockEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE);
|
||||
if (behaviour == null)
|
||||
return;
|
||||
|
||||
BlockHitResult ray = RaycastHelper.rayTraceRange(world, player, 10);
|
||||
if (ray == null)
|
||||
return;
|
||||
if (behaviour instanceof SidedFilteringBehaviour) {
|
||||
behaviour = ((SidedFilteringBehaviour) behaviour).get(ray.getDirection());
|
||||
if (behaviour == null)
|
||||
return;
|
||||
}
|
||||
if (!behaviour.isActive())
|
||||
return;
|
||||
if (behaviour.slotPositioning instanceof ValueBoxTransform.Sided)
|
||||
((Sided) behaviour.slotPositioning).fromSide(ray.getDirection());
|
||||
if (!behaviour.testHit(ray.getLocation()))
|
||||
return;
|
||||
|
||||
ItemStack toApply = player.getItemInHand(hand)
|
||||
.copy();
|
||||
|
||||
if (AllItems.WRENCH.isIn(toApply))
|
||||
return;
|
||||
if (AllBlocks.MECHANICAL_ARM.isIn(toApply))
|
||||
return;
|
||||
|
||||
if (event.getSide() != LogicalSide.CLIENT) {
|
||||
if (!player.isCreative()) {
|
||||
if (toApply.getItem() instanceof FilterItem)
|
||||
player.getItemInHand(hand)
|
||||
.shrink(1);
|
||||
if (behaviour.getFilter()
|
||||
.getItem() instanceof FilterItem)
|
||||
player.getInventory().placeItemBackInInventory(behaviour.getFilter());
|
||||
}
|
||||
if (toApply.getItem() instanceof FilterItem)
|
||||
toApply.setCount(1);
|
||||
behaviour.setFilter(toApply);
|
||||
|
||||
} else {
|
||||
ItemStack filter = behaviour.getFilter();
|
||||
String feedback = "apply_click_again";
|
||||
if (toApply.getItem() instanceof FilterItem || !behaviour.isCountVisible())
|
||||
feedback = "apply";
|
||||
else if (ItemHandlerHelper.canItemStacksStack(toApply, filter))
|
||||
feedback = "apply_count";
|
||||
Component formattedText = world.getBlockState(pos)
|
||||
.getBlock()
|
||||
.getName();
|
||||
player.displayClientMessage(Lang.translateDirect("logistics.filter." + feedback, formattedText)
|
||||
.withStyle(ChatFormatting.WHITE), true);
|
||||
}
|
||||
|
||||
event.setCanceled(true);
|
||||
event.setCancellationResult(InteractionResult.SUCCESS);
|
||||
world.playSound(null, pos, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, .25f, .1f);
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static boolean onScroll(double delta) {
|
||||
HitResult objectMouseOver = Minecraft.getInstance().hitResult;
|
||||
if (!(objectMouseOver instanceof BlockHitResult))
|
||||
return false;
|
||||
|
||||
BlockHitResult result = (BlockHitResult) objectMouseOver;
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
ClientLevel world = mc.level;
|
||||
BlockPos blockPos = result.getBlockPos();
|
||||
|
||||
FilteringBehaviour filtering = BlockEntityBehaviour.get(world, blockPos, FilteringBehaviour.TYPE);
|
||||
if (filtering == null)
|
||||
return false;
|
||||
if (mc.player.isShiftKeyDown())
|
||||
return false;
|
||||
if (!mc.player.mayBuild())
|
||||
return false;
|
||||
if (!filtering.isCountVisible())
|
||||
return false;
|
||||
if (!filtering.isActive())
|
||||
return false;
|
||||
if (filtering.slotPositioning instanceof ValueBoxTransform.Sided)
|
||||
((Sided) filtering.slotPositioning).fromSide(result.getDirection());
|
||||
if (!filtering.testHit(objectMouseOver.getLocation()))
|
||||
return false;
|
||||
|
||||
ItemStack filterItem = filtering.getFilter();
|
||||
filtering.ticksUntilScrollPacket = 10;
|
||||
int maxAmount = (filterItem.getItem() instanceof FilterItem) ? 64 : filterItem.getMaxStackSize();
|
||||
int prev = filtering.scrollableValue;
|
||||
filtering.scrollableValue =
|
||||
(int) Mth.clamp(filtering.scrollableValue + delta * (AllKeys.ctrlDown() ? 16 : 1), 0, maxAmount);
|
||||
|
||||
if (prev != filtering.scrollableValue) {
|
||||
float pitch = (filtering.scrollableValue) / (float) (maxAmount);
|
||||
pitch = Mth.lerp(pitch, 1.5f, 2f);
|
||||
AllSoundEvents.SCROLL_VALUE.play(world, mc.player, blockPos, 1, pitch);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour.filtering;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllSpecialTextures;
|
||||
|
@ -13,7 +16,6 @@ import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxRenderer;
|
|||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform.Sided;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.utility.Components;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
@ -25,6 +27,7 @@ import net.minecraft.client.renderer.MultiBufferSource;
|
|||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
@ -66,28 +69,32 @@ public class FilteringRenderer {
|
|||
ItemStack filter = behaviour.getFilter();
|
||||
boolean isFilterSlotted = filter.getItem() instanceof FilterItem;
|
||||
boolean showCount = behaviour.isCountVisible();
|
||||
boolean fluids = behaviour.fluidFilter;
|
||||
Component label = isFilterSlotted ? Components.immutableEmpty()
|
||||
: Lang.translateDirect(behaviour.recipeFilter ? "logistics.recipe_filter"
|
||||
: fluids ? "logistics.fluid_filter" : "logistics.filter");
|
||||
Component label = behaviour.getLabel();
|
||||
boolean hit = behaviour.slotPositioning.testHit(state, target.getLocation()
|
||||
.subtract(Vec3.atLowerCornerOf(pos)));
|
||||
|
||||
AABB emptyBB = new AABB(Vec3.ZERO, Vec3.ZERO);
|
||||
AABB bb = isFilterSlotted ? emptyBB.inflate(.45f, .31f, .2f) : emptyBB.inflate(.25f);
|
||||
|
||||
ValueBox box = showCount ? new ItemValueBox(label, bb, pos, filter, behaviour.scrollableValue)
|
||||
: new ValueBox(label, bb, pos);
|
||||
|
||||
box.offsetLabel(behaviour.textShift)
|
||||
.withColors(fluids ? 0x407088 : 0x7A6A2C, fluids ? 0x70adb5 : 0xB79D64)
|
||||
.scrollTooltip(showCount && !isFilterSlotted ? Components.literal("[").append(Lang.translateDirect("action.scroll")).append("]") : Components.immutableEmpty())
|
||||
.passive(!hit);
|
||||
ValueBox box = new ItemValueBox(label, bb, pos, filter, showCount ? behaviour.count : -1, behaviour.upTo);
|
||||
box.passive(!hit);
|
||||
|
||||
CreateClient.OUTLINER.showValueBox(Pair.of("filter", pos), box.transform(behaviour.slotPositioning))
|
||||
.lineWidth(1 / 64f)
|
||||
.withFaceTexture(hit ? AllSpecialTextures.THIN_CHECKERED : null)
|
||||
.highlightFace(result.getDirection());
|
||||
.lineWidth(1 / 64f)
|
||||
.withFaceTexture(hit ? AllSpecialTextures.THIN_CHECKERED : null)
|
||||
.highlightFace(result.getDirection());
|
||||
|
||||
if (!hit)
|
||||
return;
|
||||
|
||||
List<MutableComponent> tip = new ArrayList<>();
|
||||
tip.add(label.copy());
|
||||
tip.add(Lang
|
||||
.translateDirect(filter.isEmpty() ? "logistics.filter.click_to_set" : "logistics.filter.click_to_replace"));
|
||||
if (showCount)
|
||||
tip.add(Lang.translateDirect("logistics.filter.hold_to_set_amount"));
|
||||
|
||||
CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip);
|
||||
}
|
||||
|
||||
public static void renderOnBlockEntity(SmartBlockEntity be, float partialTicks, PoseStack ms,
|
||||
|
@ -100,7 +107,8 @@ public class FilteringRenderer {
|
|||
Entity cameraEntity = Minecraft.getInstance().cameraEntity;
|
||||
if (cameraEntity != null && be.getLevel() == cameraEntity.getLevel()) {
|
||||
float max = AllConfigs.client().filterItemRenderDistance.getF();
|
||||
if (cameraEntity.position().distanceToSqr(VecHelper.getCenterOf(be.getBlockPos())) > (max * max)) {
|
||||
if (cameraEntity.position()
|
||||
.distanceToSqr(VecHelper.getCenterOf(be.getBlockPos())) > (max * max)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import javax.annotation.Nullable;
|
|||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour;
|
||||
import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode;
|
||||
import com.simibubi.create.foundation.utility.BlockFace;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
@ -101,6 +102,14 @@ public abstract class CapManipulationBehaviourBase<T, S extends CapManipulationB
|
|||
amount = filter.getAmount();
|
||||
return amount;
|
||||
}
|
||||
|
||||
public ExtractionCountMode getModeFromFilter() {
|
||||
ExtractionCountMode mode = ExtractionCountMode.UPTO;
|
||||
FilteringBehaviour filter = blockEntity.getBehaviour(FilteringBehaviour.TYPE);
|
||||
if (filter != null && !filter.upTo)
|
||||
mode = ExtractionCountMode.EXACTLY;
|
||||
return mode;
|
||||
}
|
||||
|
||||
public void findNewCapability() {
|
||||
Level world = getWorld();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour.inventory;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
|
@ -8,6 +7,7 @@ import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
|||
import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour;
|
||||
import com.simibubi.create.foundation.item.ItemHelper;
|
||||
import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
|
@ -48,18 +48,14 @@ public class InvManipulationBehaviour extends CapManipulationBehaviourBase<IItem
|
|||
}
|
||||
|
||||
public ItemStack extract() {
|
||||
return extract(getAmountFromFilter());
|
||||
return extract(getModeFromFilter(), getAmountFromFilter());
|
||||
}
|
||||
|
||||
public ItemStack extract(int amount) {
|
||||
return extract(amount, Predicates.alwaysTrue());
|
||||
public ItemStack extract(ExtractionCountMode mode, int amount) {
|
||||
return extract(mode, amount, Predicates.alwaysTrue());
|
||||
}
|
||||
|
||||
public ItemStack extract(int amount, Predicate<ItemStack> filter) {
|
||||
return extract(amount, filter, ItemStack::getMaxStackSize);
|
||||
}
|
||||
|
||||
public ItemStack extract(int amount, Predicate<ItemStack> filter, Function<ItemStack, Integer> amountThreshold) {
|
||||
public ItemStack extract(ExtractionCountMode mode, int amount, Predicate<ItemStack> filter) {
|
||||
boolean shouldSimulate = simulateNext;
|
||||
simulateNext = false;
|
||||
|
||||
|
@ -70,19 +66,10 @@ public class InvManipulationBehaviour extends CapManipulationBehaviourBase<IItem
|
|||
return ItemStack.EMPTY;
|
||||
|
||||
Predicate<ItemStack> test = getFilterTest(filter);
|
||||
|
||||
ItemStack simulatedItems = extractAmountOrThresh(inventory, test, amount, amountThreshold, true);
|
||||
ItemStack simulatedItems = ItemHelper.extract(inventory, test, mode, amount, true);
|
||||
if (shouldSimulate || simulatedItems.isEmpty())
|
||||
return simulatedItems;
|
||||
|
||||
return extractAmountOrThresh(inventory, test, amount, amountThreshold, false);
|
||||
}
|
||||
|
||||
private static ItemStack extractAmountOrThresh(IItemHandler inventory, Predicate<ItemStack> test, int amount,
|
||||
Function<ItemStack, Integer> amountThreshold, boolean shouldSimulate) {
|
||||
if (amount == -1)
|
||||
return ItemHelper.extract(inventory, test, amountThreshold, shouldSimulate);
|
||||
return ItemHelper.extract(inventory, test, amount, shouldSimulate);
|
||||
return ItemHelper.extract(inventory, test, mode, amount, false);
|
||||
}
|
||||
|
||||
public ItemStack insert(ItemStack stack) {
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour.linked;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.simibubi.create.AllSpecialTextures;
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
|
@ -19,6 +21,7 @@ import net.minecraft.client.multiplayer.ClientLevel;
|
|||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
|
@ -51,13 +54,26 @@ public class LinkRenderer {
|
|||
boolean hit = behaviour.testHit(first, target.getLocation());
|
||||
ValueBoxTransform transform = first ? behaviour.firstSlot : behaviour.secondSlot;
|
||||
|
||||
ValueBox box = new ValueBox(label, bb, pos).withColors(0x601F18, 0xB73C2D)
|
||||
.offsetLabel(behaviour.textShift)
|
||||
.passive(!hit);
|
||||
ValueBox box = new ValueBox(label, bb, pos).passive(!hit);
|
||||
boolean empty = behaviour.getNetworkKey()
|
||||
.get(first)
|
||||
.getStack()
|
||||
.isEmpty();
|
||||
|
||||
if (!empty)
|
||||
box.wideOutline();
|
||||
|
||||
CreateClient.OUTLINER.showValueBox(Pair.of(Boolean.valueOf(first), pos), box.transform(transform))
|
||||
.lineWidth(1 / 64f)
|
||||
.withFaceTexture(hit ? AllSpecialTextures.THIN_CHECKERED : null)
|
||||
.highlightFace(result.getDirection());
|
||||
.highlightFace(result.getDirection());
|
||||
|
||||
if (!hit)
|
||||
continue;
|
||||
|
||||
List<MutableComponent> tip = new ArrayList<>();
|
||||
tip.add(label.copy());
|
||||
tip.add(
|
||||
Lang.translateDirect(empty ? "logistics.filter.click_to_set" : "logistics.filter.click_to_replace"));
|
||||
CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +82,7 @@ public class LinkRenderer {
|
|||
|
||||
if (be == null || be.isRemoved())
|
||||
return;
|
||||
|
||||
|
||||
Entity cameraEntity = Minecraft.getInstance().cameraEntity;
|
||||
float max = AllConfigs.client().filterItemRenderDistance.getF();
|
||||
if (!be.isVirtual() && cameraEntity != null && cameraEntity.position()
|
||||
|
|
|
@ -7,18 +7,34 @@ import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
|||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
|
||||
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
||||
public class BulkScrollValueBehaviour extends ScrollValueBehaviour {
|
||||
|
||||
Function<SmartBlockEntity, List<? extends SmartBlockEntity>> groupGetter;
|
||||
|
||||
public BulkScrollValueBehaviour(Component label, SmartBlockEntity be, ValueBoxTransform slot,
|
||||
Function<SmartBlockEntity, List<? extends SmartBlockEntity>> groupGetter) {
|
||||
Function<SmartBlockEntity, List<? extends SmartBlockEntity>> groupGetter) {
|
||||
super(label, be, slot);
|
||||
this.groupGetter = groupGetter;
|
||||
}
|
||||
|
||||
List<? extends SmartBlockEntity> getBulk() {
|
||||
@Override
|
||||
public void setValueSettings(Player player, ValueSettings valueSetting, boolean ctrlDown) {
|
||||
if (!ctrlDown) {
|
||||
super.setValueSettings(player, valueSetting, ctrlDown);
|
||||
return;
|
||||
}
|
||||
if (!valueSetting.equals(getValueSettings()))
|
||||
playFeedbackSound(this);
|
||||
for (SmartBlockEntity be : getBulk()) {
|
||||
ScrollValueBehaviour other = be.getBehaviour(ScrollValueBehaviour.TYPE);
|
||||
if (other != null)
|
||||
other.setValue(valueSetting.value());
|
||||
}
|
||||
}
|
||||
|
||||
public List<? extends SmartBlockEntity> getBulk() {
|
||||
return groupGetter.apply(blockEntity);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter.ScrollOptionSettingsFormatter;
|
||||
import com.simibubi.create.foundation.utility.Components;
|
||||
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
|
||||
public class ScrollOptionBehaviour<E extends Enum<E> & INamedIconOptions> extends ScrollValueBehaviour {
|
||||
|
||||
|
@ -13,15 +19,20 @@ public class ScrollOptionBehaviour<E extends Enum<E> & INamedIconOptions> extend
|
|||
super(label, be, slot);
|
||||
options = enum_.getEnumConstants();
|
||||
between(0, options.length - 1);
|
||||
withStepFunction((c) -> -1);
|
||||
}
|
||||
|
||||
INamedIconOptions getIconForSelected() {
|
||||
return get();
|
||||
}
|
||||
|
||||
|
||||
public E get() {
|
||||
return options[scrollableValue];
|
||||
return options[value];
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) {
|
||||
return new ValueSettingsBoard(label, max, 1, ImmutableList.of(Components.literal("Select")),
|
||||
new ScrollOptionSettingsFormatter(options));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,19 +4,25 @@ import java.util.function.Consumer;
|
|||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter;
|
||||
import com.simibubi.create.foundation.utility.Components;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class ScrollValueBehaviour extends BlockEntityBehaviour {
|
||||
public class ScrollValueBehaviour extends BlockEntityBehaviour implements ValueSettingsBehaviour {
|
||||
|
||||
public static final BehaviourType<ScrollValueBehaviour> TYPE = new BehaviourType<>();
|
||||
|
||||
|
@ -24,17 +30,12 @@ public class ScrollValueBehaviour extends BlockEntityBehaviour {
|
|||
Vec3 textShift;
|
||||
|
||||
int min = 0;
|
||||
int max = 1;
|
||||
protected int max = 1;
|
||||
public int value;
|
||||
public int scrollableValue;
|
||||
int ticksUntilScrollPacket;
|
||||
boolean forceClientState;
|
||||
Component label;
|
||||
public Component label;
|
||||
Consumer<Integer> callback;
|
||||
Consumer<Integer> clientCallback;
|
||||
Function<Integer, String> formatter;
|
||||
Function<Integer, Component> unit;
|
||||
Function<StepContext, Integer> step;
|
||||
private Supplier<Boolean> isActive;
|
||||
boolean needsWrench;
|
||||
|
||||
|
@ -46,54 +47,28 @@ public class ScrollValueBehaviour extends BlockEntityBehaviour {
|
|||
};
|
||||
clientCallback = i -> {
|
||||
};
|
||||
textShift = Vec3.ZERO;
|
||||
formatter = i -> Integer.toString(i);
|
||||
step = (c) -> 1;
|
||||
value = 0;
|
||||
isActive = () -> true;
|
||||
ticksUntilScrollPacket = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSafeNBT() { return true; }
|
||||
public boolean isSafeNBT() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(CompoundTag nbt, boolean clientPacket) {
|
||||
nbt.putInt("ScrollValue", value);
|
||||
if (clientPacket && forceClientState) {
|
||||
nbt.putBoolean("ForceScrollable", true);
|
||||
forceClientState = false;
|
||||
}
|
||||
super.write(nbt, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundTag nbt, boolean clientPacket) {
|
||||
value = nbt.getInt("ScrollValue");
|
||||
if (nbt.contains("ForceScrollable")) {
|
||||
ticksUntilScrollPacket = -1;
|
||||
scrollableValue = value;
|
||||
}
|
||||
super.read(nbt, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
if (!getWorld().isClientSide)
|
||||
return;
|
||||
if (ticksUntilScrollPacket == -1)
|
||||
return;
|
||||
if (ticksUntilScrollPacket > 0) {
|
||||
ticksUntilScrollPacket--;
|
||||
return;
|
||||
}
|
||||
|
||||
AllPackets.getChannel().sendToServer(new ScrollValueUpdatePacket(getPos(), scrollableValue));
|
||||
ticksUntilScrollPacket = -1;
|
||||
}
|
||||
|
||||
public ScrollValueBehaviour withClientCallback(Consumer<Integer> valueCallback) {
|
||||
clientCallback = valueCallback;
|
||||
return this;
|
||||
|
@ -110,11 +85,6 @@ public class ScrollValueBehaviour extends BlockEntityBehaviour {
|
|||
return this;
|
||||
}
|
||||
|
||||
public ScrollValueBehaviour moveText(Vec3 shift) {
|
||||
textShift = shift;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ScrollValueBehaviour requiresWrench() {
|
||||
this.needsWrench = true;
|
||||
return this;
|
||||
|
@ -125,38 +95,19 @@ public class ScrollValueBehaviour extends BlockEntityBehaviour {
|
|||
return this;
|
||||
}
|
||||
|
||||
public ScrollValueBehaviour withUnit(Function<Integer, Component> unit) {
|
||||
this.unit = unit;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ScrollValueBehaviour onlyActiveWhen(Supplier<Boolean> condition) {
|
||||
isActive = condition;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ScrollValueBehaviour withStepFunction(Function<StepContext, Integer> step) {
|
||||
this.step = step;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
setValue(value);
|
||||
scrollableValue = value;
|
||||
}
|
||||
|
||||
public void setValue(int value) {
|
||||
value = Mth.clamp(value, min, max);
|
||||
if (value == this.value)
|
||||
return;
|
||||
this.value = value;
|
||||
forceClientState = true;
|
||||
callback.accept(value);
|
||||
blockEntity.setChanged();
|
||||
blockEntity.sendData();
|
||||
scrollableValue = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
|
@ -164,7 +115,7 @@ public class ScrollValueBehaviour extends BlockEntityBehaviour {
|
|||
}
|
||||
|
||||
public String formatValue() {
|
||||
return formatter.apply(scrollableValue);
|
||||
return formatter.apply(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -172,10 +123,12 @@ public class ScrollValueBehaviour extends BlockEntityBehaviour {
|
|||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return isActive.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testHit(Vec3 hit) {
|
||||
BlockState state = blockEntity.getBlockState();
|
||||
Vec3 localHit = hit.subtract(Vec3.atLowerCornerOf(blockEntity.getBlockPos()));
|
||||
|
@ -193,4 +146,33 @@ public class ScrollValueBehaviour extends BlockEntityBehaviour {
|
|||
public boolean control;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueBoxTransform getSlotPositioning() {
|
||||
return slotPositioning;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) {
|
||||
return new ValueSettingsBoard(label, max, 10, ImmutableList.of(Components.literal("Value")),
|
||||
new ValueSettingsFormatter(ValueSettings::format));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueSettings(Player player, ValueSettings valueSetting, boolean ctrlDown) {
|
||||
if (valueSetting.equals(getValueSettings()))
|
||||
return;
|
||||
setValue(valueSetting.value());
|
||||
playFeedbackSound(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSettings getValueSettings() {
|
||||
return new ValueSettings(0, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onlyVisibleWithWrench() {
|
||||
return needsWrench;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,82 +1,20 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue;
|
||||
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.AllKeys;
|
||||
import com.simibubi.create.AllSoundEvents;
|
||||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform.Sided;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollValueBehaviour.StepContext;
|
||||
import com.simibubi.create.foundation.utility.animation.PhysicalFloat;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
|
||||
@EventBusSubscriber
|
||||
public class ScrollValueHandler {
|
||||
|
||||
private static float lastPassiveScroll = 0.0f;
|
||||
private static float passiveScroll = 0.0f;
|
||||
private static float passiveScrollDirection = 1f;
|
||||
private static final PhysicalFloat wrenchCog = PhysicalFloat.create()
|
||||
public static final PhysicalFloat wrenchCog = PhysicalFloat.create()
|
||||
.withDrag(0.3);
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static boolean onScroll(double delta) {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
HitResult objectMouseOver = mc.hitResult;
|
||||
if (!(objectMouseOver instanceof BlockHitResult))
|
||||
return false;
|
||||
|
||||
BlockHitResult result = (BlockHitResult) objectMouseOver;
|
||||
ClientLevel world = mc.level;
|
||||
BlockPos blockPos = result.getBlockPos();
|
||||
|
||||
ScrollValueBehaviour scrolling = BlockEntityBehaviour.get(world, blockPos, ScrollValueBehaviour.TYPE);
|
||||
if (scrolling == null)
|
||||
return false;
|
||||
if (!scrolling.isActive())
|
||||
return false;
|
||||
if (!mc.player.mayBuild())
|
||||
return false;
|
||||
if (scrolling.needsWrench && !AllItems.WRENCH.isIn(mc.player.getMainHandItem()))
|
||||
return false;
|
||||
|
||||
passiveScrollDirection = (float) -delta;
|
||||
wrenchCog.bump(3, -delta * 10);
|
||||
int prev = scrolling.scrollableValue;
|
||||
|
||||
if (scrolling.slotPositioning instanceof Sided)
|
||||
((Sided) scrolling.slotPositioning).fromSide(result.getDirection());
|
||||
if (!scrolling.testHit(objectMouseOver.getLocation()))
|
||||
return false;
|
||||
|
||||
if (scrolling instanceof BulkScrollValueBehaviour && AllKeys.ctrlDown()) {
|
||||
BulkScrollValueBehaviour bulkScrolling = (BulkScrollValueBehaviour) scrolling;
|
||||
for (SmartBlockEntity be : bulkScrolling.getBulk()) {
|
||||
ScrollValueBehaviour other = be.getBehaviour(ScrollValueBehaviour.TYPE);
|
||||
if (other != null)
|
||||
applyTo(delta, other);
|
||||
}
|
||||
|
||||
} else
|
||||
applyTo(delta, scrolling);
|
||||
|
||||
if (prev != scrolling.scrollableValue) {
|
||||
float pitch = (scrolling.scrollableValue - scrolling.min) / (float) (scrolling.max - scrolling.min);
|
||||
pitch = Mth.lerp(pitch, 1.5f, 2f);
|
||||
AllSoundEvents.SCROLL_VALUE.play(world, mc.player, blockPos, 1, pitch);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static float getScroll(float partialTicks) {
|
||||
return wrenchCog.getValue(partialTicks) + Mth.lerp(partialTicks, lastPassiveScroll, passiveScroll);
|
||||
}
|
||||
|
@ -91,21 +29,4 @@ public class ScrollValueHandler {
|
|||
}
|
||||
}
|
||||
|
||||
protected static void applyTo(double delta, ScrollValueBehaviour scrolling) {
|
||||
scrolling.ticksUntilScrollPacket = 10;
|
||||
int valueBefore = scrolling.scrollableValue;
|
||||
|
||||
StepContext context = new StepContext();
|
||||
context.control = AllKeys.ctrlDown();
|
||||
context.shift = AllKeys.shiftDown();
|
||||
context.currentValue = scrolling.scrollableValue;
|
||||
context.forward = delta > 0;
|
||||
|
||||
double newValue = scrolling.scrollableValue + Math.signum(delta) * scrolling.step.apply(context);
|
||||
scrolling.scrollableValue = (int) Mth.clamp(newValue, scrolling.min, scrolling.max);
|
||||
|
||||
if (valueBefore != scrolling.scrollableValue)
|
||||
scrolling.clientCallback.accept(scrolling.scrollableValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.AllKeys;
|
||||
import com.simibubi.create.CreateClient;
|
||||
|
@ -16,6 +19,7 @@ import net.minecraft.client.multiplayer.ClientLevel;
|
|||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
|
@ -52,6 +56,14 @@ public class ScrollValueRenderer {
|
|||
}
|
||||
} else
|
||||
addBox(world, pos, face, behaviour, highlight);
|
||||
|
||||
if (!highlight)
|
||||
return;
|
||||
|
||||
List<MutableComponent> tip = new ArrayList<>();
|
||||
tip.add(behaviour.label.copy());
|
||||
tip.add(Lang.translateDirect("gui.value_settings.hold_to_edit"));
|
||||
CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip);
|
||||
}
|
||||
|
||||
protected static void addBox(ClientLevel world, BlockPos pos, Direction face, ScrollValueBehaviour behaviour,
|
||||
|
@ -66,18 +78,13 @@ public class ScrollValueRenderer {
|
|||
box = new IconValueBox(label, ((ScrollOptionBehaviour<?>) behaviour).getIconForSelected(), bb, pos);
|
||||
} else {
|
||||
box = new TextValueBox(label, bb, pos, Components.literal(behaviour.formatValue()));
|
||||
if (behaviour.unit != null)
|
||||
box.subLabel(Components.literal("(").append(behaviour.unit.apply(behaviour.scrollableValue)).append(")"));
|
||||
}
|
||||
|
||||
box.scrollTooltip(Components.literal("[").append(Lang.translateDirect("action.scroll")).append("]"));
|
||||
box.offsetLabel(behaviour.textShift.add(20, -10, 0))
|
||||
.withColors(0x5A5D5A, 0xB5B7B6)
|
||||
.passive(!highlight);
|
||||
box.passive(!highlight)
|
||||
.wideOutline();
|
||||
|
||||
CreateClient.OUTLINER.showValueBox(pos, box.transform(behaviour.slotPositioning))
|
||||
.lineWidth(1 / 64f)
|
||||
.highlightFace(face);
|
||||
.highlightFace(face);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
package com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue;
|
||||
|
||||
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||
import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
public class ScrollValueUpdatePacket extends BlockEntityConfigurationPacket<SmartBlockEntity> {
|
||||
|
||||
int value;
|
||||
|
||||
public ScrollValueUpdatePacket(FriendlyByteBuf buffer) {
|
||||
super(buffer);
|
||||
}
|
||||
|
||||
public ScrollValueUpdatePacket(BlockPos pos, int amount) {
|
||||
super(pos);
|
||||
this.value = amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeSettings(FriendlyByteBuf buffer) {
|
||||
buffer.writeInt(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readSettings(FriendlyByteBuf buffer) {
|
||||
value = buffer.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applySettings(SmartBlockEntity be) {
|
||||
ScrollValueBehaviour behaviour = be.getBehaviour(ScrollValueBehaviour.TYPE);
|
||||
if (behaviour == null)
|
||||
return;
|
||||
behaviour.setValue(value);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package com.simibubi.create.foundation.config;
|
||||
|
||||
import com.simibubi.create.foundation.config.ui.ConfigAnnotations;
|
||||
import com.simibubi.create.foundation.utility.ContraptionData;
|
||||
|
||||
public class CKinetics extends ConfigBase {
|
||||
|
@ -8,7 +7,6 @@ public class CKinetics extends ConfigBase {
|
|||
public final ConfigBool disableStress = b(false, "disableStress", Comments.disableStress);
|
||||
public final ConfigInt maxBeltLength = i(20, 5, "maxBeltLength", Comments.maxBeltLength);
|
||||
public final ConfigInt crushingDamage = i(4, 0, "crushingDamage", Comments.crushingDamage);
|
||||
public final ConfigInt maxMotorSpeed = i(256, 64, "maxMotorSpeed", Comments.rpm, Comments.maxMotorSpeed, ConfigAnnotations.RequiresRestart.BOTH.asComment());
|
||||
public final ConfigInt maxRotationSpeed = i(256, 64, "maxRotationSpeed", Comments.rpm, Comments.maxRotationSpeed);
|
||||
public final ConfigEnum<DeployerAggroSetting> ignoreDeployerAttacks =
|
||||
e(DeployerAggroSetting.CREEPERS, "ignoreDeployerAttacks", Comments.ignoreDeployerAttacks);
|
||||
|
@ -65,7 +63,6 @@ public class CKinetics extends ConfigBase {
|
|||
private static class Comments {
|
||||
static String maxBeltLength = "Maximum length in blocks of mechanical belts.";
|
||||
static String crushingDamage = "Damage dealt by active Crushing Wheels.";
|
||||
static String maxMotorSpeed = "Maximum allowed speed of a configurable motor.";
|
||||
static String maxRotationSpeed = "Maximum allowed rotation speed for any Kinetic Block.";
|
||||
static String fanPushDistance = "Maximum distance in blocks Fans can push entities.";
|
||||
static String fanPullDistance = "Maximum distance in blocks from where Fans can pull entities.";
|
||||
|
|
|
@ -2,8 +2,6 @@ package com.simibubi.create.foundation.config;
|
|||
|
||||
public class CLogistics extends ConfigBase {
|
||||
|
||||
public final ConfigInt defaultExtractionLimit =
|
||||
i(64, 1, 64, "defaultExtractionLimit", Comments.defaultExtractionLimit);
|
||||
public final ConfigInt defaultExtractionTimer = i(8, 1, "defaultExtractionTimer", Comments.defaultExtractionTimer);
|
||||
public final ConfigInt psiTimeout = i(20, 1, "psiTimeout", Comments.psiTimeout);
|
||||
public final ConfigInt mechanicalArmRange = i(5, 1, "mechanicalArmRange", Comments.mechanicalArmRange);
|
||||
|
@ -17,8 +15,6 @@ public class CLogistics extends ConfigBase {
|
|||
}
|
||||
|
||||
private static class Comments {
|
||||
static String defaultExtractionLimit =
|
||||
"The maximum amount of items a funnel pulls at a time without an applied filter.";
|
||||
static String defaultExtractionTimer =
|
||||
"The amount of ticks a funnel waits between item transferrals, when it is not re-activated by redstone.";
|
||||
static String linkRange = "Maximum possible range in blocks of redstone link connections.";
|
||||
|
|
|
@ -48,10 +48,6 @@ public enum AllGuiTextures implements ScreenElement {
|
|||
STOCKSWITCH_UNPOWERED_LANE("logistics", 36, 18, 102, 18),
|
||||
STOCKSWITCH_POWERED_LANE("logistics", 36, 40, 102, 18),
|
||||
|
||||
ADJUSTABLE_CRATE("logistics_2", 124, 127),
|
||||
ADJUSTABLE_DOUBLE_CRATE("logistics_2", 0, 127, 196, 127),
|
||||
ADJUSTABLE_CRATE_LOCKED_SLOT("logistics_2", 125, 109, 18, 18),
|
||||
|
||||
FILTER("filters", 214, 97),
|
||||
ATTRIBUTE_FILTER("filters", 0, 97, 241, 83),
|
||||
|
||||
|
@ -77,12 +73,6 @@ public enum AllGuiTextures implements ScreenElement {
|
|||
LINKED_CONTROLLER("curiosities_2", 179, 109),
|
||||
BLUEPRINT("curiosities_2", 0, 109, 179, 109),
|
||||
|
||||
PROJECTOR("projector", 235, 185),
|
||||
PROJECTOR_FILTER_STRENGTH("projector", 0, 14, 162, 22),
|
||||
PROJECTOR_FILTER("projector", 0, 36, 162, 22),
|
||||
PROJECTOR_END("projector", 0, 58, 162, 22),
|
||||
PROJECTOR_EMPTY("projector", 0, 80, 162, 22),
|
||||
|
||||
DATA_GATHERER("display_link", 235, 162),
|
||||
DATA_AREA_START("display_link", 0, 163, 2, 18),
|
||||
DATA_AREA_SPEECH("display_link", 8, 163, 5, 18),
|
||||
|
@ -134,6 +124,26 @@ public enum AllGuiTextures implements ScreenElement {
|
|||
|
||||
ELEVATOR_CONTACT("display_link", 20, 172, 233, 82),
|
||||
|
||||
BRASS_FRAME_TL("value_settings", 65, 9, 4, 4),
|
||||
BRASS_FRAME_TR("value_settings", 70, 9, 4, 4),
|
||||
BRASS_FRAME_BL("value_settings", 65, 19, 4, 4),
|
||||
BRASS_FRAME_BR("value_settings", 70, 19, 4, 4),
|
||||
BRASS_FRAME_LEFT("value_settings", 65, 14, 3, 4),
|
||||
BRASS_FRAME_RIGHT("value_settings", 71, 14, 3, 4),
|
||||
BRASS_FRAME_TOP("value_settings", 0, 24, 256, 3),
|
||||
BRASS_FRAME_BOTTOM("value_settings", 0, 27, 256, 3),
|
||||
|
||||
VALUE_SETTINGS_MILESTONE("value_settings", 0, 0, 7, 8),
|
||||
VALUE_SETTINGS_WIDE_MILESTONE("value_settings", 75, 14, 13, 8),
|
||||
VALUE_SETTINGS_BAR("value_settings", 7, 0, 249, 8),
|
||||
VALUE_SETTINGS_BAR_BG("value_settings", 75, 9, 1, 1),
|
||||
VALUE_SETTINGS_OUTER_BG("value_settings", 80, 9, 1, 1),
|
||||
VALUE_SETTINGS_CURSOR_LEFT("value_settings", 0, 9, 3, 14),
|
||||
VALUE_SETTINGS_CURSOR("value_settings", 4, 9, 56, 14),
|
||||
VALUE_SETTINGS_CURSOR_RIGHT("value_settings", 61, 9, 3, 14),
|
||||
VALUE_SETTINGS_CURSOR_ICON("value_settings", 0, 44, 22, 20),
|
||||
VALUE_SETTINGS_LABEL_BG("value_settings", 0, 31, 81, 11),
|
||||
|
||||
// JEI
|
||||
JEI_SLOT("jei/widgets", 18, 18),
|
||||
JEI_CHANCE_SLOT("jei/widgets", 20, 156, 18, 18),
|
||||
|
|
|
@ -126,6 +126,9 @@ public class AllIcons implements ScreenElement {
|
|||
|
||||
I_SCHEMATIC = newRow(),
|
||||
I_SEQ_REPEAT = next(),
|
||||
VALUE_BOX_HOVER_6PX = next(),
|
||||
VALUE_BOX_HOVER_4PX = next(),
|
||||
VALUE_BOX_HOVER_8PX = next(),
|
||||
|
||||
I_MTD_LEFT = newRow(),
|
||||
I_MTD_CLOSE = next(),
|
||||
|
@ -187,7 +190,7 @@ public class AllIcons implements ScreenElement {
|
|||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void render(PoseStack ms, MultiBufferSource buffer, int color) {
|
||||
VertexConsumer builder = buffer.getBuffer(RenderType.textSeeThrough(ICON_ATLAS));
|
||||
VertexConsumer builder = buffer.getBuffer(RenderType.text(ICON_ATLAS));
|
||||
Matrix4f matrix = ms.last().pose();
|
||||
Color rgb = new Color(color);
|
||||
int light = LightTexture.FULL_BRIGHT;
|
||||
|
|
|
@ -252,6 +252,13 @@ public class UIRenderHelper {
|
|||
tex.startY / 256f, (tex.startY + tex.height) / 256f);
|
||||
}
|
||||
|
||||
public static void drawCropped(PoseStack ms, int left, int top, int w, int h, int z, AllGuiTextures tex) {
|
||||
tex.bind();
|
||||
drawTexturedQuad(ms.last()
|
||||
.pose(), Color.WHITE, left, left + w, top, top + h, z, tex.startX / 256f, (tex.startX + w) / 256f,
|
||||
tex.startY / 256f, (tex.startY + h) / 256f);
|
||||
}
|
||||
|
||||
private static void drawColoredTexture(PoseStack ms, Color c, int left, int right, int top, int bot, int z, int tex_width, int tex_height, float tex_left, float tex_top, int sheet_width, int sheet_height) {
|
||||
drawTexturedQuad(ms.last().pose(), c, left, right, top, bot, z, (tex_left + 0.0F) / (float) sheet_width, (tex_left + (float) tex_width) / (float) sheet_width, (tex_top + 0.0F) / (float) sheet_height, (tex_top + (float) tex_height) / (float) sheet_height);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import javax.annotation.Nullable;
|
|||
|
||||
import org.apache.commons.lang3.mutable.MutableInt;
|
||||
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
@ -148,8 +147,7 @@ public class ItemHelper {
|
|||
}
|
||||
|
||||
public static ItemStack extract(IItemHandler inv, Predicate<ItemStack> test, boolean simulate) {
|
||||
return extract(inv, test, ExtractionCountMode.UPTO, AllConfigs.server().logistics.defaultExtractionLimit.get(),
|
||||
simulate);
|
||||
return extract(inv, test, ExtractionCountMode.UPTO, 64, simulate);
|
||||
}
|
||||
|
||||
public static ItemStack extract(IItemHandler inv, Predicate<ItemStack> test, int exactAmount, boolean simulate) {
|
||||
|
@ -224,7 +222,7 @@ public class ItemHelper {
|
|||
public static ItemStack extract(IItemHandler inv, Predicate<ItemStack> test,
|
||||
Function<ItemStack, Integer> amountFunction, boolean simulate) {
|
||||
ItemStack extracting = ItemStack.EMPTY;
|
||||
int maxExtractionCount = AllConfigs.server().logistics.defaultExtractionLimit.get();
|
||||
int maxExtractionCount = 64;
|
||||
|
||||
for (int slot = 0; slot < inv.getSlots(); slot++) {
|
||||
if (extracting.isEmpty()) {
|
||||
|
|
|
@ -80,8 +80,7 @@ import com.simibubi.create.content.schematics.packet.SchematicPlacePacket;
|
|||
import com.simibubi.create.content.schematics.packet.SchematicSyncPacket;
|
||||
import com.simibubi.create.content.schematics.packet.SchematicUploadPacket;
|
||||
import com.simibubi.create.foundation.blockEntity.RemoveBlockEntityPacket;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringCountUpdatePacket;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollValueUpdatePacket;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsPacket;
|
||||
import com.simibubi.create.foundation.command.HighlightPacket;
|
||||
import com.simibubi.create.foundation.command.SConfigureConfigPacket;
|
||||
import com.simibubi.create.foundation.config.ui.CConfigureConfigPacket;
|
||||
|
@ -111,8 +110,6 @@ public enum AllPackets {
|
|||
UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new, PLAY_TO_SERVER),
|
||||
CLEAR_CONTAINER(ClearMenuPacket.class, ClearMenuPacket::new, PLAY_TO_SERVER),
|
||||
CONFIGURE_FILTER(FilterScreenPacket.class, FilterScreenPacket::new, PLAY_TO_SERVER),
|
||||
CONFIGURE_FILTERING_AMOUNT(FilteringCountUpdatePacket.class, FilteringCountUpdatePacket::new, PLAY_TO_SERVER),
|
||||
CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new, PLAY_TO_SERVER),
|
||||
EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new, PLAY_TO_SERVER),
|
||||
CONTRAPTION_INTERACT(ContraptionInteractionPacket.class, ContraptionInteractionPacket::new, PLAY_TO_SERVER),
|
||||
CLIENT_MOTION(ClientMotionPacket.class, ClientMotionPacket::new, PLAY_TO_SERVER),
|
||||
|
@ -157,6 +154,7 @@ public enum AllPackets {
|
|||
REQUEST_FLOOR_LIST(ElevatorFloorListPacket.RequestFloorList.class, ElevatorFloorListPacket.RequestFloorList::new,
|
||||
PLAY_TO_SERVER),
|
||||
ELEVATOR_SET_FLOOR(ElevatorTargetFloorPacket.class, ElevatorTargetFloorPacket::new, PLAY_TO_SERVER),
|
||||
VALUE_SETTINGS(ValueSettingsPacket.class, ValueSettingsPacket::new, PLAY_TO_SERVER),
|
||||
|
||||
// Server to Client
|
||||
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT),
|
||||
|
|
|
@ -193,21 +193,47 @@
|
|||
"create.contraptions.cart_movement_mode.rotation_locked": "Lock rotation",
|
||||
|
||||
"create.contraptions.windmill.rotation_direction": "Rotation Direction",
|
||||
"create.contraptions.clockwork.clock_hands": "Clock Hands",
|
||||
"create.contraptions.clockwork.clock_hands": "Clock Hand Arrangement",
|
||||
"create.contraptions.clockwork.hour_first": "Hour hand first",
|
||||
"create.contraptions.clockwork.minute_first": "Minute hand first",
|
||||
"create.contraptions.clockwork.hour_first_24": "24-Hour hand first",
|
||||
|
||||
"create.logistics.crafter.connected": "Connected Crafters",
|
||||
"create.logistics.crafter.click_to_merge": "Click to merge Inventories",
|
||||
"create.logistics.crafter.click_to_separate": "Click to separate Inventories",
|
||||
|
||||
"create.logistics.filter": "Filter",
|
||||
"create.logistics.recipe_filter": "Recipe Filter",
|
||||
"create.logistics.fluid_filter": "Fluid Filter",
|
||||
"create.logistics.firstFrequency": "Freq. #1",
|
||||
"create.logistics.secondFrequency": "Freq. #2",
|
||||
|
||||
"create.logistics.filter.apply": "Applied filter to %1$s.",
|
||||
"create.logistics.filter.apply_click_again": "Applied filter to %1$s, click again to copy the amount.",
|
||||
"create.logistics.filter.apply_count": "Applied extraction count to filter.",
|
||||
"create.logistics.firstFrequency": "Frequency #1",
|
||||
"create.logistics.secondFrequency": "Frequency #2",
|
||||
|
||||
"create.logistics.filter.click_to_set": "Click with item to set",
|
||||
"create.logistics.filter.click_to_replace": "Click with item to replace",
|
||||
"create.logistics.filter.hold_to_set_amount": "Click and hold for amount",
|
||||
|
||||
"create.logistics.filter.extracted_amount": "Extracted Amount",
|
||||
"create.logistics.filter.any_amount_short": "Any",
|
||||
"create.logistics.filter.up_to": "Up to",
|
||||
"create.logistics.filter.exactly": "Exactly",
|
||||
|
||||
"create.logistics.creative_crate.supply": "Infinite Supply",
|
||||
"create.logistics.train_observer.cargo_filter": "Cargo Filter",
|
||||
|
||||
"create.kinetics.creative_motor.rotation_speed": "Generated Speed in RPM",
|
||||
"create.kinetics.speed_controller.rotation_speed": "Targeted Speed in RPM",
|
||||
|
||||
"create.logistics.redstone_interval": "Redstone Interval",
|
||||
|
||||
"create.contraptions.contoller.target": "Targeted Component",
|
||||
|
||||
"create.contraptions.chassis.radius": "Radius when Sticky",
|
||||
"create.contraptions.chassis.range": "Range of Sticky Sides",
|
||||
"create.contraptions.chassis.distance": "Distance",
|
||||
|
||||
"create.gui.value_settings.hold_to_edit": "Click and hold to edit",
|
||||
"create.gui.value_settings.release_to_confirm": "Release %1$s to Confirm",
|
||||
|
||||
"create.gui.goggles.generator_stats": "Generator Stats:",
|
||||
"create.gui.goggles.kinetic_stats": "Kinetic Stats:",
|
||||
"create.gui.goggles.at_current_speed": "at current speed",
|
||||
|
@ -515,7 +541,7 @@
|
|||
"create.weighted_ejector.targeting": "Ejecting to [%1$s,%2$s,%3$s]",
|
||||
"create.weighted_ejector.stack_size": "Ejected Stack Size",
|
||||
|
||||
"create.logistics.when_multiple_outputs_available": "When Multiple Outputs Available",
|
||||
"create.logistics.when_multiple_outputs_available": "Distribution Method",
|
||||
|
||||
"create.mechanical_arm.selection_mode.round_robin": "Round Robin",
|
||||
"create.mechanical_arm.selection_mode.forced_round_robin": "Forced Round Robin",
|
||||
|
|
|
@ -50,13 +50,13 @@
|
|||
},
|
||||
{
|
||||
"name": "Between Rims",
|
||||
"from": [3.5, 3.5, 3],
|
||||
"to": [12.5, 12.5, 6],
|
||||
"from": [3.5, 3.5, 2],
|
||||
"to": [12.5, 12.5, 5],
|
||||
"faces": {
|
||||
"east": {"uv": [3, 10, 12, 13], "rotation": 270, "texture": "#6"},
|
||||
"west": {"uv": [3, 10, 12, 13], "rotation": 90, "texture": "#6"},
|
||||
"up": {"uv": [3, 10, 12, 13], "rotation": 180, "texture": "#6"},
|
||||
"down": {"uv": [3, 10, 12, 13], "texture": "#6"}
|
||||
"east": {"uv": [3.5, 10, 12.5, 13], "rotation": 270, "texture": "#6"},
|
||||
"west": {"uv": [3.5, 10, 12.5, 13], "rotation": 90, "texture": "#6"},
|
||||
"up": {"uv": [3.5, 10, 12.5, 13], "rotation": 180, "texture": "#6"},
|
||||
"down": {"uv": [3.5, 10, 12.5, 13], "texture": "#6"}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -131,6 +131,30 @@
|
|||
"up": {"uv": [1, 2, 8, 16], "rotation": 90, "texture": "#7"},
|
||||
"down": {"uv": [1, 4, 15, 11], "texture": "#7"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 7, 4],
|
||||
"to": [11, 13, 10],
|
||||
"faces": {
|
||||
"north": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"east": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"south": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"west": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"up": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"down": {"uv": [10, 0, 16, 6], "texture": "#6"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [3, 5, 4],
|
||||
"to": [13, 11, 10],
|
||||
"faces": {
|
||||
"north": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"east": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"south": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"west": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"up": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"down": {"uv": [10, 0, 16, 6], "texture": "#6"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"display": {
|
||||
|
@ -155,6 +179,8 @@
|
|||
"origin": [8, 8, 8],
|
||||
"color": 0,
|
||||
"children": []
|
||||
}
|
||||
},
|
||||
10,
|
||||
11
|
||||
]
|
||||
}
|
|
@ -4,7 +4,6 @@
|
|||
"textures": {
|
||||
"5": "create:block/creative_casing",
|
||||
"6": "create:block/creative_motor",
|
||||
"7": "create:block/flap_display_front",
|
||||
"particle": "create:block/creative_casing",
|
||||
"1_0": "create:block/axis"
|
||||
},
|
||||
|
@ -74,6 +73,19 @@
|
|||
"down": {"uv": [10, 0, 0, 10], "rotation": 180, "texture": "#6"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Back",
|
||||
"from": [3, 0.1, 3],
|
||||
"to": [13, 2.1, 13],
|
||||
"faces": {
|
||||
"north": {"uv": [3, 16, 13, 14], "rotation": 180, "texture": "#5"},
|
||||
"east": {"uv": [3, 16, 13, 14], "rotation": 180, "texture": "#5"},
|
||||
"south": {"uv": [3, 16, 13, 14], "rotation": 180, "texture": "#5"},
|
||||
"west": {"uv": [3, 16, 13, 14], "rotation": 180, "texture": "#5"},
|
||||
"up": {"uv": [10, 0, 0, 10], "texture": "#6"},
|
||||
"down": {"uv": [10, 0, 0, 10], "rotation": 180, "texture": "#6"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Between Rims",
|
||||
"from": [5, 9, 5],
|
||||
|
@ -89,14 +101,14 @@
|
|||
},
|
||||
{
|
||||
"name": "Between Rims",
|
||||
"from": [3.5, 5, 3.5],
|
||||
"to": [12.5, 8, 12.5],
|
||||
"from": [3.5, 2, 3.5],
|
||||
"to": [12.5, 5, 12.5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [3, 10, 12, 13], "texture": "#6"},
|
||||
"east": {"uv": [3, 10, 12, 13], "texture": "#6"},
|
||||
"south": {"uv": [3, 10, 12, 13], "texture": "#6"},
|
||||
"west": {"uv": [3, 10, 12, 13], "texture": "#6"}
|
||||
"north": {"uv": [3.5, 10, 12.5, 13], "texture": "#6"},
|
||||
"east": {"uv": [3.5, 10, 12.5, 13], "texture": "#6"},
|
||||
"south": {"uv": [3.5, 10, 12.5, 13], "texture": "#6"},
|
||||
"west": {"uv": [3.5, 10, 12.5, 13], "texture": "#6"}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -113,15 +125,28 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"from": [3, 0.2, 3],
|
||||
"to": [13, 4, 13],
|
||||
"from": [3, 4, 5],
|
||||
"to": [13, 10, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [5, 0, 15, 4], "texture": "#7"},
|
||||
"east": {"uv": [5, 0, 15, 4], "texture": "#7"},
|
||||
"south": {"uv": [5, 0, 15, 4], "texture": "#7"},
|
||||
"west": {"uv": [3, 0, 13, 4], "rotation": 180, "texture": "#7"},
|
||||
"up": {"uv": [10, 10, 0, 0], "rotation": 90, "texture": "#6"},
|
||||
"down": {"uv": [10, 10, 0, 0], "rotation": 180, "texture": "#6"}
|
||||
"north": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"east": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"south": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"west": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"up": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"down": {"uv": [10, 0, 16, 6], "texture": "#6"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 4, 3],
|
||||
"to": [11, 10, 13],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 7, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"east": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"south": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"west": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"up": {"uv": [10, 0, 16, 6], "rotation": 90, "texture": "#6"},
|
||||
"down": {"uv": [10, 0, 16, 6], "rotation": 270, "texture": "#6"}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -146,6 +171,8 @@
|
|||
"origin": [8, 8, 8],
|
||||
"color": 0,
|
||||
"children": []
|
||||
}
|
||||
},
|
||||
9,
|
||||
10
|
||||
]
|
||||
}
|
|
@ -5,11 +5,25 @@
|
|||
"5": "create:block/creative_casing",
|
||||
"6": "create:block/creative_motor",
|
||||
"7": "create:block/flap_display_front",
|
||||
"1_1": "create:block/axis_top",
|
||||
"particle": "create:block/creative_casing",
|
||||
"1_0": "create:block/axis",
|
||||
"1_1": "create:block/axis_top"
|
||||
"1_0": "create:block/axis"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "Axis",
|
||||
"from": [6, 6, 6],
|
||||
"to": [10, 10, 16],
|
||||
"rotation": {"angle": 22.5, "axis": "z", "origin": [8, 8, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [6, 6, 10, 10], "rotation": 180, "texture": "#1_1"},
|
||||
"east": {"uv": [6, 0, 10, 10], "rotation": 270, "texture": "#1_0"},
|
||||
"south": {"uv": [6, 6, 10, 10], "texture": "#1_1"},
|
||||
"west": {"uv": [6, 0, 10, 10], "rotation": 90, "texture": "#1_0"},
|
||||
"up": {"uv": [6, 0, 10, 10], "rotation": 180, "texture": "#1_0"},
|
||||
"down": {"uv": [6, 0, 10, 10], "texture": "#1_0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Back",
|
||||
"from": [3, 3, 0.1],
|
||||
|
@ -51,13 +65,13 @@
|
|||
},
|
||||
{
|
||||
"name": "Between Rims",
|
||||
"from": [3.5, 3.5, 3],
|
||||
"to": [12.5, 12.5, 6],
|
||||
"from": [3.5, 3.5, 2],
|
||||
"to": [12.5, 12.5, 5],
|
||||
"faces": {
|
||||
"east": {"uv": [3, 10, 12, 13], "rotation": 270, "texture": "#6"},
|
||||
"west": {"uv": [3, 10, 12, 13], "rotation": 90, "texture": "#6"},
|
||||
"up": {"uv": [3, 10, 12, 13], "rotation": 180, "texture": "#6"},
|
||||
"down": {"uv": [3, 10, 12, 13], "texture": "#6"}
|
||||
"east": {"uv": [3.5, 10, 12.5, 13], "rotation": 270, "texture": "#6"},
|
||||
"west": {"uv": [3.5, 10, 12.5, 13], "rotation": 90, "texture": "#6"},
|
||||
"up": {"uv": [3.5, 10, 12.5, 13], "rotation": 180, "texture": "#6"},
|
||||
"down": {"uv": [3.5, 10, 12.5, 13], "texture": "#6"}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -134,17 +148,27 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"name": "Axis",
|
||||
"from": [6, 6, 6],
|
||||
"to": [10, 10, 16],
|
||||
"rotation": {"angle": 22.5, "axis": "z", "origin": [8, 8, 8]},
|
||||
"from": [5, 7, 4],
|
||||
"to": [11, 13, 10],
|
||||
"faces": {
|
||||
"north": {"uv": [6, 6, 10, 10], "rotation": 180, "texture": "#1_1"},
|
||||
"east": {"uv": [6, 0, 10, 10], "rotation": 270, "texture": "#1_0"},
|
||||
"south": {"uv": [6, 6, 10, 10], "texture": "#1_1"},
|
||||
"west": {"uv": [6, 0, 10, 10], "rotation": 90, "texture": "#1_0"},
|
||||
"up": {"uv": [6, 0, 10, 10], "rotation": 180, "texture": "#1_0"},
|
||||
"down": {"uv": [6, 0, 10, 10], "texture": "#1_0"}
|
||||
"north": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"east": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"south": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"west": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"up": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"down": {"uv": [10, 0, 16, 6], "texture": "#6"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [3, 5, 4],
|
||||
"to": [13, 11, 10],
|
||||
"faces": {
|
||||
"north": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"east": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"south": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"west": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"up": {"uv": [10, 0, 16, 6], "texture": "#6"},
|
||||
"down": {"uv": [10, 0, 16, 6], "texture": "#6"}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -155,21 +179,36 @@
|
|||
}
|
||||
},
|
||||
"groups": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
{
|
||||
"name": "shaft",
|
||||
"origin": [8, 8, 8],
|
||||
"color": 0,
|
||||
"children": [10]
|
||||
"children": [0]
|
||||
},
|
||||
{
|
||||
"name": "block",
|
||||
"origin": [8, 8, 8],
|
||||
"color": 0,
|
||||
"children": [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
{
|
||||
"name": "shaft",
|
||||
"origin": [8, 8, 8],
|
||||
"color": 0,
|
||||
"children": []
|
||||
},
|
||||
11,
|
||||
12
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
"credit": "Made with Blockbench",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"3": "create:block/belt/brass_belt_casing_sideways",
|
||||
"3": "create:block/mechanical_arm_side",
|
||||
"7": "create:block/brass_block",
|
||||
"particle": "create:block/crafter_top"
|
||||
},
|
||||
|
@ -12,10 +12,10 @@
|
|||
"from": [0, 0, 0],
|
||||
"to": [16, 6, 16],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 6.5, 8, 9.5], "texture": "#3"},
|
||||
"east": {"uv": [0, 6.5, 8, 9.5], "texture": "#3"},
|
||||
"south": {"uv": [0, 6.5, 8, 9.5], "texture": "#3"},
|
||||
"west": {"uv": [0, 6.5, 8, 9.5], "texture": "#3"},
|
||||
"north": {"uv": [0, 0, 16, 6], "texture": "#3"},
|
||||
"east": {"uv": [0, 0, 16, 6], "texture": "#3"},
|
||||
"south": {"uv": [0, 0, 16, 6], "texture": "#3"},
|
||||
"west": {"uv": [0, 0, 16, 6], "texture": "#3"},
|
||||
"up": {"uv": [0, 0, 16, 16], "texture": "#7"},
|
||||
"down": {"uv": [0, 0, 16, 16], "texture": "#7"}
|
||||
}
|
||||
|
|
|
@ -8,103 +8,108 @@
|
|||
"elements": [
|
||||
{
|
||||
"name": "siderim",
|
||||
"from": [13, 0, 3],
|
||||
"to": [15, 2, 13],
|
||||
"from": [5, -0.25, 6],
|
||||
"to": [6, 0.75, 10],
|
||||
"faces": {
|
||||
"north": {"uv": [14, 0, 16, 2], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 2, 10], "rotation": 90, "texture": "#0"},
|
||||
"south": {"uv": [14, 0, 16, 2], "rotation": 180, "texture": "#0"},
|
||||
"west": {"uv": [14, 10, 16, 0], "rotation": 270, "texture": "#0"},
|
||||
"up": {"uv": [14, 0, 16, 10], "rotation": 180, "texture": "#0"},
|
||||
"down": {"uv": [14, 0, 16, 10], "rotation": 180, "texture": "#0"}
|
||||
"north": {"uv": [15, 0, 16, 1], "texture": "#0"},
|
||||
"east": {"uv": [14, 7, 15, 3], "rotation": 270, "texture": "#0"},
|
||||
"south": {"uv": [15, 0, 16, 1], "texture": "#0"},
|
||||
"west": {"uv": [15, 8, 16, 4], "rotation": 270, "texture": "#0"},
|
||||
"up": {"uv": [15, 4, 16, 8], "rotation": 180, "texture": "#0"},
|
||||
"down": {"uv": [15, 4, 14, 8], "rotation": 180, "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "siderim",
|
||||
"from": [1, 0, 3],
|
||||
"to": [3, 2, 13],
|
||||
"from": [10, -0.25, 6],
|
||||
"to": [11, 0.75, 10],
|
||||
"faces": {
|
||||
"north": {"uv": [16, 0, 14, 2], "texture": "#0"},
|
||||
"east": {"uv": [14, 0, 16, 10], "rotation": 270, "texture": "#0"},
|
||||
"south": {"uv": [16, 0, 14, 2], "rotation": 180, "texture": "#0"},
|
||||
"west": {"uv": [0, 10, 2, 0], "rotation": 90, "texture": "#0"},
|
||||
"up": {"uv": [16, 0, 14, 10], "rotation": 180, "texture": "#0"},
|
||||
"down": {"uv": [16, 0, 14, 10], "rotation": 180, "texture": "#0"}
|
||||
"north": {"uv": [15, 0, 16, 1], "texture": "#0"},
|
||||
"east": {"uv": [15, 8, 16, 4], "rotation": 270, "texture": "#0"},
|
||||
"south": {"uv": [15, 0, 16, 1], "texture": "#0"},
|
||||
"west": {"uv": [14, 7, 15, 3], "rotation": 270, "texture": "#0"},
|
||||
"up": {"uv": [15, 5, 16, 9], "rotation": 180, "texture": "#0"},
|
||||
"down": {"uv": [15, 4, 14, 8], "rotation": 180, "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "net",
|
||||
"from": [3, 1, 4],
|
||||
"to": [13, 1.1, 12],
|
||||
"from": [6, 0.5, 6],
|
||||
"to": [10, 0.6, 10],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 0, 0], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 0, 0], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 0, 0], "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 0, 0], "texture": "#0"},
|
||||
"up": {"uv": [2.5, 0.5, 12.5, 8.5], "texture": "#0"},
|
||||
"down": {"uv": [2.5, 0.5, 12.5, 8.5], "texture": "#0"}
|
||||
"north": {"uv": [0, 0, 4, 0.1], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 4, 0.1], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 4, 0.1], "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 4, 0.1], "texture": "#0"},
|
||||
"up": {"uv": [2, 0, 6, 4], "texture": "#0"},
|
||||
"down": {"uv": [2.5, 0.5, 6.5, 4.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "toprim",
|
||||
"from": [3, 0.5, 3],
|
||||
"to": [13, 1.5, 4],
|
||||
"from": [5, -0.25, 5],
|
||||
"to": [11, 0.75, 6],
|
||||
"faces": {
|
||||
"north": {"uv": [3, 9, 13, 10], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 0, 0], "texture": "#0"},
|
||||
"south": {"uv": [3, 9, 13, 10], "rotation": 180, "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 0, 0], "texture": "#0"},
|
||||
"up": {"uv": [3, 9, 13, 10], "rotation": 180, "texture": "#0"},
|
||||
"down": {"uv": [3, 9, 13, 10], "rotation": 180, "texture": "#0"}
|
||||
"north": {"uv": [3, 9, 9, 10], "texture": "#0"},
|
||||
"east": {"uv": [12, 9, 13, 10], "texture": "#0"},
|
||||
"south": {"uv": [3, 9, 9, 10], "rotation": 180, "texture": "#0"},
|
||||
"west": {"uv": [12, 9, 13, 10], "texture": "#0"},
|
||||
"up": {"uv": [3, 9, 9, 10], "rotation": 180, "texture": "#0"},
|
||||
"down": {"uv": [3, 9, 9, 10], "rotation": 180, "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "toprim",
|
||||
"from": [3, 0.5, 12],
|
||||
"to": [13, 1.5, 13],
|
||||
"from": [5, -0.25, 10],
|
||||
"to": [11, 0.75, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [3, 9, 13, 10], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 0, 0], "texture": "#0"},
|
||||
"south": {"uv": [3, 9, 13, 10], "rotation": 180, "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 0, 0], "texture": "#0"},
|
||||
"up": {"uv": [3, 9, 13, 10], "rotation": 180, "texture": "#0"},
|
||||
"down": {"uv": [3, 9, 13, 10], "rotation": 180, "texture": "#0"}
|
||||
"north": {"uv": [3, 9, 9, 10], "texture": "#0"},
|
||||
"east": {"uv": [12, 9, 13, 10], "texture": "#0"},
|
||||
"south": {"uv": [5, 9, 11, 10], "rotation": 180, "texture": "#0"},
|
||||
"west": {"uv": [12, 9, 13, 10], "texture": "#0"},
|
||||
"up": {"uv": [5, 9, 11, 10], "rotation": 180, "texture": "#0"},
|
||||
"down": {"uv": [3, 9, 9, 10], "rotation": 180, "texture": "#0"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"display": {
|
||||
"thirdperson_righthand": {
|
||||
"rotation": [75, -180, 0],
|
||||
"translation": [-2.75, 3.25, 3.25],
|
||||
"scale": [0.5, 0.5, 0.5]
|
||||
"translation": [-2.75, 2, 4.75],
|
||||
"scale": [0.6, 0.6, 0.6]
|
||||
},
|
||||
"thirdperson_lefthand": {
|
||||
"rotation": [75, -180, 0],
|
||||
"translation": [-2.75, 3.25, 3.25],
|
||||
"scale": [0.5, 0.5, 0.5]
|
||||
"translation": [-2.75, 2, 4.75],
|
||||
"scale": [0.6, 0.6, 0.6]
|
||||
},
|
||||
"firstperson_righthand": {
|
||||
"rotation": [75, -180, 0],
|
||||
"translation": [-2.75, 3.25, 3.25],
|
||||
"scale": [0.5, 0.5, 0.5]
|
||||
"translation": [2.25, 1.5, 4.75],
|
||||
"scale": [1.35, 1.35, 1.35]
|
||||
},
|
||||
"firstperson_lefthand": {
|
||||
"rotation": [75, -180, 0],
|
||||
"translation": [-2.75, 3.25, 3.25],
|
||||
"scale": [0.5, 0.5, 0.5]
|
||||
"translation": [2.25, 1.5, 4.75],
|
||||
"scale": [1.35, 1.35, 1.35]
|
||||
},
|
||||
"ground": {
|
||||
"translation": [0, 3, 0],
|
||||
"scale": [0.5, 0.5, 0.5]
|
||||
"scale": [0.76, 0.76, 0.76]
|
||||
},
|
||||
"gui": {
|
||||
"rotation": [30, 225, 0],
|
||||
"translation": [0, 4.25, 0],
|
||||
"scale": [0.75, 0.75, 0.75]
|
||||
"translation": [0, 9.5, 0],
|
||||
"scale": [1.5, 1.5, 1.5]
|
||||
},
|
||||
"head": {
|
||||
"translation": [0, 18.25, 0],
|
||||
"scale": [1.43, 1.43, 1.43]
|
||||
},
|
||||
"fixed": {
|
||||
"rotation": [90, -180, 0],
|
||||
"translation": [0, 0, 6.5]
|
||||
"rotation": [90, 0, 179.5],
|
||||
"translation": [0, 0, -15],
|
||||
"scale": [2.04, 2.04, 2.04]
|
||||
}
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 366 B After Width: | Height: | Size: 438 B |
Before Width: | Height: | Size: 457 B After Width: | Height: | Size: 466 B |
After Width: | Height: | Size: 266 B |
Before Width: | Height: | Size: 346 B After Width: | Height: | Size: 389 B |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.6 KiB |
BIN
src/main/resources/assets/create/textures/gui/value_settings.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 238 B After Width: | Height: | Size: 309 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 237 B |