diff --git a/src/main/java/com/simibubi/create/AllBlockPartials.java b/src/main/java/com/simibubi/create/AllBlockPartials.java index dcef481c9..bfc1cb9fd 100644 --- a/src/main/java/com/simibubi/create/AllBlockPartials.java +++ b/src/main/java/com/simibubi/create/AllBlockPartials.java @@ -16,8 +16,11 @@ import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour.A import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; import com.simibubi.create.content.contraptions.relays.belt.BeltData; import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.RenderMaterials; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; @@ -259,4 +262,22 @@ public class AllBlockPartials { return dispatcher.getMaterial(KineticRenderMaterials.ROTATING).getModel(this, referenceState, facing, ms); } + public InstancedModel renderOnHorizontalModel(InstancedTileRenderer dispatcher, BlockState referenceState) { + Direction facing = referenceState.get(HORIZONTAL_FACING); + return renderOnDirectionalSouthModel(dispatcher, referenceState, facing); + } + + public InstancedModel renderOnDirectionalSouthModel(InstancedTileRenderer dispatcher, BlockState referenceState, Direction facing) { + Supplier ms = () -> { + MatrixStack stack = new MatrixStack(); + MatrixStacker.of(stack) + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(AngleHelper.verticalAngle(facing)) + .unCentre(); + return stack; + }; + return dispatcher.getMaterial(RenderMaterials.MODELS).getModel(this, referenceState, facing, ms); + } + } diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java index 0220a6c85..e480efc82 100644 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ b/src/main/java/com/simibubi/create/AllTileEntities.java @@ -32,6 +32,7 @@ import com.simibubi.create.content.contraptions.components.fan.NozzleTileEntity; import com.simibubi.create.content.contraptions.components.flywheel.FlyWheelInstance; import com.simibubi.create.content.contraptions.components.flywheel.FlywheelRenderer; import com.simibubi.create.content.contraptions.components.flywheel.FlywheelTileEntity; +import com.simibubi.create.content.contraptions.components.flywheel.engine.EngineInstance; import com.simibubi.create.content.contraptions.components.flywheel.engine.EngineRenderer; import com.simibubi.create.content.contraptions.components.flywheel.engine.FurnaceEngineTileEntity; import com.simibubi.create.content.contraptions.components.millstone.MillStoneCogInstance; @@ -39,10 +40,12 @@ import com.simibubi.create.content.contraptions.components.millstone.MillstoneRe import com.simibubi.create.content.contraptions.components.millstone.MillstoneTileEntity; import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerRenderer; import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerTileEntity; +import com.simibubi.create.content.contraptions.components.mixer.MixerInstance; import com.simibubi.create.content.contraptions.components.motor.CreativeMotorRenderer; import com.simibubi.create.content.contraptions.components.motor.CreativeMotorTileEntity; import com.simibubi.create.content.contraptions.components.press.MechanicalPressRenderer; import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity; +import com.simibubi.create.content.contraptions.components.press.PressInstance; import com.simibubi.create.content.contraptions.components.saw.SawInstance; import com.simibubi.create.content.contraptions.components.saw.SawRenderer; import com.simibubi.create.content.contraptions.components.saw.SawTileEntity; @@ -137,6 +140,7 @@ import com.simibubi.create.content.logistics.block.redstone.NixieTubeTileEntity; import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkTileEntity; import com.simibubi.create.content.logistics.block.redstone.StockpileSwitchTileEntity; import com.simibubi.create.content.schematics.block.SchematicTableTileEntity; +import com.simibubi.create.content.schematics.block.SchematicannonInstance; import com.simibubi.create.content.schematics.block.SchematicannonRenderer; import com.simibubi.create.content.schematics.block.SchematicannonTileEntity; import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; @@ -149,6 +153,7 @@ public class AllTileEntities { .tileEntity("schematicannon", SchematicannonTileEntity::new) .validBlocks(AllBlocks.SCHEMATICANNON) .renderer(() -> SchematicannonRenderer::new) + .onRegister(SchematicannonInstance::register) .register(); public static final TileEntityEntry SCHEMATIC_TABLE = Create.registrate() @@ -454,6 +459,7 @@ public class AllTileEntities { .tileEntity("furnace_engine", FurnaceEngineTileEntity::new) .validBlocks(AllBlocks.FURNACE_ENGINE) .renderer(() -> EngineRenderer::new) + .onRegister(EngineInstance::register) .register(); public static final TileEntityEntry MILLSTONE = Create.registrate() @@ -488,14 +494,14 @@ public class AllTileEntities { .tileEntity("mechanical_press", MechanicalPressTileEntity::new) .validBlocks(AllBlocks.MECHANICAL_PRESS) .renderer(() -> MechanicalPressRenderer::new) - .onRegister(ShaftInstance::register) + .onRegister(PressInstance::register) .register(); public static final TileEntityEntry MECHANICAL_MIXER = Create.registrate() .tileEntity("mechanical_mixer", MechanicalMixerTileEntity::new) .validBlocks(AllBlocks.MECHANICAL_MIXER) .renderer(() -> MechanicalMixerRenderer::new) - .onRegister(ShaftlessCogInstance::register) + .onRegister(MixerInstance::register) .register(); public static final TileEntityEntry DEPLOYER = Create.registrate() diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java index f3814c3e3..6ff654402 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java @@ -58,7 +58,7 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer { @@ -36,7 +37,8 @@ public class HarvesterRenderer extends SafeTileEntityRenderer ms.translate(0, isBlockItem ? 9 / 16f : 11 / 16f, 0); ms.scale(scale, scale, scale); transform = TransformType.GROUND; - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(AnimationTickHolder.getRenderTime())); + ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(AnimationTickHolder.getRenderTime(te.getWorld()))); } else { float scale = punching ? .75f : isBlockItem ? .75f - 1 / 64f : .5f; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanRenderer.java index 6421411d3..cb469d615 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanRenderer.java @@ -41,7 +41,7 @@ public class EncasedFanRenderer extends KineticTileEntityRenderer { SuperByteBuffer fanInner = AllBlockPartials.ENCASED_FAN_INNER.renderOnDirectionalSouth(te.getBlockState(), direction.getOpposite()); - float time = AnimationTickHolder.getRenderTime(); + float time = AnimationTickHolder.getRenderTime(te.getWorld()); float speed = te.getSpeed() * 5; if (speed > 0) speed = MathHelper.clamp(speed, 80, 64 * 20); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java index e81756d8f..267e05572 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java @@ -1,34 +1,59 @@ package com.simibubi.create.content.contraptions.components.flywheel; -import java.util.function.Consumer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.KineticTileInstance; import com.simibubi.create.content.contraptions.base.RotatingData; -import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.RenderMaterials; +import com.simibubi.create.foundation.render.backend.instancing.*; -import net.minecraft.block.BlockState; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; import net.minecraft.util.Rotation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.LightType; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.fml.DistExecutor; -public class FlyWheelInstance extends KineticTileInstance { +public class FlyWheelInstance extends KineticTileInstance implements ITickableInstance { public static void register(TileEntityType type) { DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedTileRenderRegistry.instance.register(type, FlyWheelInstance::new)); } protected Direction facing; + protected boolean connectedLeft; + protected float connectorAngleMult; + + protected Direction connection; protected InstanceKey shaft; -// protected InstanceKey wheel; + + protected InstanceKey wheel; + protected InstanceKey upperRotating; + protected InstanceKey lowerRotating; + protected InstanceKey upperSliding; + protected InstanceKey lowerSliding; + + protected List> connectors; + + protected float lastAngle = Float.NaN; + + protected boolean firstFrame = true; public FlyWheelInstance(InstancedTileRenderer modelManager, FlywheelTileEntity tile) { super(modelManager, tile); @@ -40,35 +65,154 @@ public class FlyWheelInstance extends KineticTileInstance { Direction.Axis axis = ((IRotate) lastState.getBlock()).getRotationAxis(lastState); shaft = setup(shaftModel().createInstance(), tile.getSpeed(), axis); -// wheel = wheelModel().setupInstance(setup); + + wheel = AllBlockPartials.FLYWHEEL.renderOnHorizontalModel(modelManager, lastState.rotate(Rotation.CLOCKWISE_90)).createInstance(); + + connection = FlywheelBlock.getConnection(lastState); + if (connection != null) { + connectedLeft = lastState.get(FlywheelBlock.CONNECTION) == FlywheelBlock.ConnectionState.LEFT; + + boolean flipAngle = connection.getAxis() == Direction.Axis.X ^ connection.getAxisDirection() == Direction.AxisDirection.NEGATIVE; + + connectorAngleMult = flipAngle ? -1 : 1; + + RenderMaterial> mat = modelManager.getMaterial(RenderMaterials.MODELS); + + upperRotating = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_ROTATING, lastState).createInstance(); + lowerRotating = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_ROTATING, lastState).createInstance(); + upperSliding = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_SLIDING, lastState).createInstance(); + lowerSliding = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_SLIDING, lastState).createInstance(); + + connectors = Lists.newArrayList(upperRotating, lowerRotating, upperSliding, lowerSliding); + } else { + connectors = Collections.emptyList(); + } + + updateLight(); + firstFrame = true; + } + + @Override + public void tick() { + + float partialTicks = AnimationTickHolder.getPartialTicks(); + + float speed = tile.visualSpeed.get(partialTicks) * 3 / 10f; + float angle = tile.angle + speed * partialTicks; + + if (!firstFrame && Math.abs(angle - lastAngle) < 0.001) return; + + MatrixStack ms = new MatrixStack(); + MatrixStacker msr = MatrixStacker.of(ms); + + msr.translate(getFloatingPos()); + + if (connection != null) { + float rotation = angle * connectorAngleMult; + + ms.push(); + rotateToFacing(msr, connection); + + ms.push(); + transformConnector(msr, true, true, rotation, connectedLeft); + upperRotating.getInstance().setTransform(ms); + ms.pop(); + + ms.push(); + transformConnector(msr, false, true, rotation, connectedLeft); + lowerRotating.getInstance().setTransform(ms); + ms.pop(); + + ms.push(); + transformConnector(msr, true, false, rotation, connectedLeft); + upperSliding.getInstance().setTransform(ms); + ms.pop(); + + ms.push(); + transformConnector(msr, false, false, rotation, connectedLeft); + lowerSliding.getInstance().setTransform(ms); + ms.pop(); + + ms.pop(); + } + + msr.centre() + .rotate(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, facing.getAxis()), AngleHelper.rad(angle)) + .unCentre(); + + wheel.getInstance().setTransformNoCopy(ms); + + lastAngle = angle; + firstFrame = false; } @Override protected void onUpdate() { Direction.Axis axis = ((IRotate) lastState.getBlock()).getRotationAxis(lastState); updateRotation(shaft, axis); -// updateRotation(wheel, axis); } @Override public void updateLight() { - relight(shaft); -// wheel.modifyInstance(this::relight); + int block = world.getLightLevel(LightType.BLOCK, pos); + int sky = world.getLightLevel(LightType.SKY, pos); + + shaft.getInstance().setBlockLight(block).setSkyLight(sky); + wheel.getInstance().setBlockLight(block).setSkyLight(sky); + + if (connection != null) { + BlockPos pos = this.pos.offset(connection); + + int connectionBlock = world.getLightLevel(LightType.BLOCK, pos); + int connectionSky = world.getLightLevel(LightType.SKY, pos); + connectors.stream() + .map(InstanceKey::getInstance) + .forEach(data -> data.setBlockLight(connectionBlock).setSkyLight(connectionSky)); + } } @Override public void remove() { shaft.delete(); -// wheel.delete(); -// wheel = null; + wheel.delete(); + + connectors.forEach(InstanceKey::delete); + connectors.clear(); } protected InstancedModel shaftModel() { return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, lastState, facing.getOpposite()); } - protected InstancedModel wheelModel() { - BlockState rotate = lastState.rotate(Rotation.CLOCKWISE_90); - return AllBlockPartials.FLYWHEEL.renderOnDirectionalSouthRotating(modelManager, rotate, rotate.get(BlockStateProperties.HORIZONTAL_FACING)); + protected void transformConnector(MatrixStacker ms, boolean upper, boolean rotating, float angle, boolean flip) { + float shift = upper ? 1 / 4f : -1 / 8f; + float offset = upper ? 1 / 4f : 1 / 4f; + float radians = (float) (angle / 180 * Math.PI); + float shifting = MathHelper.sin(radians) * shift + offset; + + float maxAngle = upper ? -5 : -15; + float minAngle = upper ? -45 : 5; + float barAngle = 0; + + if (rotating) + barAngle = MathHelper.lerp((MathHelper.sin((float) (radians + Math.PI / 2)) + 1) / 2, minAngle, maxAngle); + + float pivotX = (upper ? 8f : 3f) / 16; + float pivotY = (upper ? 8f : 2f) / 16; + float pivotZ = (upper ? 23f : 21.5f) / 16f; + + ms.translate(pivotX, pivotY, pivotZ + shifting); + if (rotating) + ms.rotate(Direction.EAST, AngleHelper.rad(barAngle)); + ms.translate(-pivotX, -pivotY, -pivotZ); + + if (flip && !upper) + ms.translate(9 / 16f, 0, 0); + } + + protected void rotateToFacing(MatrixStacker buffer, Direction facing) { + buffer.centre() + .rotate(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing))) + .unCentre(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelRenderer.java index be3d3e108..03434b9e9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelRenderer.java @@ -9,6 +9,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.components.flywheel.FlywheelBlock.ConnectionState; import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.AngleHelper; import net.minecraft.block.BlockState; @@ -33,10 +34,11 @@ public class FlywheelRenderer extends KineticTileEntityRenderer { int light, int overlay) { super.renderSafe(te, partialTicks, ms, buffer, light, overlay); + if (FastRenderDispatcher.available(te.getWorld())) return; + BlockState blockState = te.getBlockState(); FlywheelTileEntity wte = (FlywheelTileEntity) te; - SuperByteBuffer wheel = AllBlockPartials.FLYWHEEL.renderOnHorizontal(blockState.rotate(Rotation.CLOCKWISE_90)); float speed = wte.visualSpeed.get(partialTicks) * 3 / 10f; float angle = wte.angle + speed * partialTicks; @@ -68,6 +70,7 @@ public class FlywheelRenderer extends KineticTileEntityRenderer { .renderInto(ms, vb); } + SuperByteBuffer wheel = AllBlockPartials.FLYWHEEL.renderOnHorizontal(blockState.rotate(Rotation.CLOCKWISE_90)); kineticRotationTransform(wheel, te, blockState.get(HORIZONTAL_FACING) .getAxis(), AngleHelper.rad(angle), light); wheel.renderInto(ms, vb); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelTileEntity.java index 67f4952b7..2dab48a50 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelTileEntity.java @@ -100,9 +100,4 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity { updateGeneratedRotation(); } } - - @Override - public boolean shouldRenderAsTE() { - return true; - } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineInstance.java new file mode 100644 index 000000000..dcffdd401 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineInstance.java @@ -0,0 +1,78 @@ +package com.simibubi.create.content.contraptions.components.flywheel.engine; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.foundation.render.backend.RenderMaterials; +import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.render.backend.instancing.TileEntityInstance; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.MatrixStacker; +import net.minecraft.block.Block; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.LightType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class EngineInstance extends TileEntityInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, EngineInstance::new)); + } + + protected InstanceKey frame; + + public EngineInstance(InstancedTileRenderer modelManager, EngineTileEntity tile) { + super(modelManager, tile); + } + + @Override + protected void init() { + Block block = lastState + .getBlock(); + if (!(block instanceof EngineBlock)) + return; + + EngineBlock engineBlock = (EngineBlock) block; + AllBlockPartials frame = engineBlock.getFrameModel(); + + Direction facing = lastState.get(BlockStateProperties.HORIZONTAL_FACING); + + this.frame = modelManager.getMaterial(RenderMaterials.MODELS).getModel(frame, lastState).createInstance(); + + float angle = AngleHelper.rad(AngleHelper.horizontalAngle(facing)); + + MatrixStack ms = new MatrixStack(); + MatrixStacker msr = MatrixStacker.of(ms); + + msr.translate(getFloatingPos()) + .nudge(tile.hashCode()) + .centre() + .rotate(Direction.UP, angle) + .unCentre() + .translate(0, 0, -1); + + this.frame.getInstance() + .setTransformNoCopy(ms); + + updateLight(); + } + + @Override + public void remove() { + frame.delete(); + } + + @Override + public void updateLight() { + int block = world.getLightLevel(LightType.BLOCK, pos); + int sky = world.getLightLevel(LightType.SKY, pos); + + frame.getInstance().setBlockLight(block).setSkyLight(sky); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineRenderer.java index 477348870..597895c48 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineRenderer.java @@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.flywheel.engine; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; @@ -21,6 +22,9 @@ public class EngineRenderer extends SafeTileEntityRe @Override protected void renderSafe(T te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { + + if (FastRenderDispatcher.available(te.getWorld())) return; + Block block = te.getBlockState() .getBlock(); if (block instanceof EngineBlock) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineTileEntity.java index 6a3988caa..b14e7e47e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineTileEntity.java @@ -3,8 +3,10 @@ package com.simibubi.create.content.contraptions.components.flywheel.engine; import java.util.List; import com.simibubi.create.AllBlocks; +import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.components.flywheel.FlywheelBlock; import com.simibubi.create.content.contraptions.components.flywheel.FlywheelTileEntity; +import com.simibubi.create.foundation.render.backend.instancing.IInstanceRendered; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; @@ -16,8 +18,10 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; +import org.apache.http.client.CredentialsProvider; -public class EngineTileEntity extends SmartTileEntity { +public class EngineTileEntity extends SmartTileEntity implements IInstanceRendered { public float appliedCapacity; public float appliedSpeed; @@ -100,4 +104,16 @@ public class EngineTileEntity extends SmartTileEntity { poweredWheel.setRotation(appliedSpeed, appliedCapacity); } + @Override + public void onChunkLightUpdate() { + CreateClient.kineticRenderer.onLightUpdate(this); + } + + @Override + public void initialize() { + super.initialize(); + + DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> CreateClient.kineticRenderer.add(this)); + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerRenderer.java index 134b7b788..41635cb02 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerRenderer.java @@ -31,22 +31,23 @@ public class MechanicalMixerRenderer extends KineticTileEntityRenderer { @Override protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { + + if (FastRenderDispatcher.available(te.getWorld())) return; + BlockState blockState = te.getBlockState(); MechanicalMixerTileEntity mixer = (MechanicalMixerTileEntity) te; BlockPos pos = te.getPos(); IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); - if (!FastRenderDispatcher.available(te.getWorld())) { - SuperByteBuffer superBuffer = AllBlockPartials.SHAFTLESS_COGWHEEL.renderOn(blockState); - standardKineticRotationTransform(superBuffer, te, light).renderInto(ms, vb); - } + SuperByteBuffer superBuffer = AllBlockPartials.SHAFTLESS_COGWHEEL.renderOn(blockState); + standardKineticRotationTransform(superBuffer, te, light).renderInto(ms, vb); int packedLightmapCoords = WorldRenderer.getLightmapCoordinates(te.getWorld(), blockState, pos); float renderedHeadOffset = mixer.getRenderedHeadOffset(partialTicks); float speed = mixer.getRenderedHeadRotationSpeed(partialTicks); - float time = AnimationTickHolder.getRenderTime(); - float angle = (float) (((time * speed * 6 / 10f) % 360) / 180 * (float) Math.PI); + float time = AnimationTickHolder.getRenderTime(te.getWorld()); + float angle = ((time * speed * 6 / 10f) % 360) / 180 * (float) Math.PI; SuperByteBuffer poleRender = AllBlockPartials.MECHANICAL_MIXER_POLE.renderOn(blockState); poleRender.translate(0, -renderedHeadOffset, 0) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java new file mode 100644 index 000000000..4beadc933 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java @@ -0,0 +1,115 @@ +package com.simibubi.create.content.contraptions.components.mixer; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.content.contraptions.base.RotatingData; +import com.simibubi.create.content.contraptions.base.ShaftlessCogInstance; +import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity; +import com.simibubi.create.foundation.render.backend.RenderMaterials; +import com.simibubi.create.foundation.render.backend.instancing.*; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.MatrixStacker; +import net.minecraft.client.renderer.Vector3d; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.LightType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class MixerInstance extends ShaftlessCogInstance implements ITickableInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, MixerInstance::new)); + } + + private InstanceKey mixerHead; + private InstanceKey mixerPole; + + public MixerInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { + super(dispatcher, tile); + } + + @Override + protected void init() { + super.init(); + + mixerHead = rotatingMaterial().getModel(AllBlockPartials.MECHANICAL_MIXER_HEAD, lastState) + .createInstance(); + + mixerHead.getInstance() + .setRotationAxis(Direction.Axis.Y); + + mixerPole = modelManager.getMaterial(RenderMaterials.MODELS) + .getModel(AllBlockPartials.MECHANICAL_MIXER_POLE, lastState) + .createInstance(); + + + MechanicalMixerTileEntity mixer = (MechanicalMixerTileEntity) tile; + float renderedHeadOffset = getRenderedHeadOffset(mixer); + + transformPole(renderedHeadOffset); + transformHead(mixer, renderedHeadOffset); + updateLight(); + } + + @Override + public void tick() { + MechanicalMixerTileEntity mixer = (MechanicalMixerTileEntity) tile; + + float renderedHeadOffset = getRenderedHeadOffset(mixer); + + if (mixer.running) { + transformPole(renderedHeadOffset); + } + + transformHead(mixer, renderedHeadOffset); + } + + private void transformHead(MechanicalMixerTileEntity mixer, float renderedHeadOffset) { + float speed = mixer.getRenderedHeadRotationSpeed(AnimationTickHolder.getPartialTicks()); + + mixerHead.getInstance() + .setPosition(pos) + .nudge(0, -renderedHeadOffset, 0) + .setRotationalSpeed(speed * 2); + } + + private void transformPole(float renderedHeadOffset) { + MatrixStack ms = new MatrixStack(); + + MatrixStacker msr = MatrixStacker.of(ms); + msr.translate(getFloatingPos()); + msr.translate(0, -renderedHeadOffset, 0); + + mixerPole.getInstance().setTransformNoCopy(ms); + } + + private float getRenderedHeadOffset(MechanicalMixerTileEntity mixer) { + return mixer.getRenderedHeadOffset(AnimationTickHolder.getPartialTicks()); + } + + @Override + public void updateLight() { + super.updateLight(); + + BlockPos down = pos.down(); + mixerHead.getInstance() + .setBlockLight(world.getLightLevel(LightType.BLOCK, down)) + .setSkyLight(world.getLightLevel(LightType.SKY, down)); + + mixerPole.getInstance() + .setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) + .setSkyLight(world.getLightLevel(LightType.SKY, pos)); + } + + @Override + public void remove() { + super.remove(); + mixerHead.delete(); + mixerPole.delete(); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressRenderer.java index 18f2353a7..7bb36e753 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressRenderer.java @@ -6,6 +6,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; @@ -29,13 +30,17 @@ public class MechanicalPressRenderer extends KineticTileEntityRenderer { int light, int overlay) { super.renderSafe(te, partialTicks, ms, buffer, light, overlay); + if (FastRenderDispatcher.available(te.getWorld())) return; + BlockPos pos = te.getPos(); BlockState blockState = te.getBlockState(); int packedLightmapCoords = WorldRenderer.getLightmapCoordinates(te.getWorld(), blockState, pos); float renderedHeadOffset = ((MechanicalPressTileEntity) te).getRenderedHeadOffset(partialTicks); SuperByteBuffer headRender = AllBlockPartials.MECHANICAL_PRESS_HEAD.renderOnHorizontal(blockState); - headRender.translate(0, -renderedHeadOffset, 0).light(packedLightmapCoords).renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + headRender.translate(0, -renderedHeadOffset, 0) + .light(packedLightmapCoords) + .renderInto(ms, buffer.getBuffer(RenderType.getSolid())); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java new file mode 100644 index 000000000..53084bef4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java @@ -0,0 +1,84 @@ +package com.simibubi.create.content.contraptions.components.press; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; +import com.simibubi.create.foundation.render.backend.RenderMaterials; +import com.simibubi.create.foundation.render.backend.instancing.ITickableInstance; +import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.MatrixStacker; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.world.LightType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class PressInstance extends ShaftInstance implements ITickableInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, PressInstance::new)); + } + + private InstanceKey pressHead; + + public PressInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { + super(dispatcher, tile); + } + + @Override + protected void init() { + super.init(); + + pressHead = modelManager.getMaterial(RenderMaterials.MODELS) + .getModel(AllBlockPartials.MECHANICAL_PRESS_HEAD, lastState) + .createInstance(); + + updateLight(); + transformModels((MechanicalPressTileEntity) tile); + } + + @Override + public void tick() { + MechanicalPressTileEntity press = (MechanicalPressTileEntity) tile; + if (!press.running) + return; + + transformModels(press); + } + + private void transformModels(MechanicalPressTileEntity press) { + float renderedHeadOffset = getRenderedHeadOffset(press); + + MatrixStack ms = new MatrixStack(); + + MatrixStacker msr = MatrixStacker.of(ms); + msr.translate(getFloatingPos()); + msr.translate(0, -renderedHeadOffset, 0); + + pressHead.getInstance() + .setTransformNoCopy(ms); + } + + private float getRenderedHeadOffset(MechanicalPressTileEntity press) { + return press.getRenderedHeadOffset(AnimationTickHolder.getPartialTicks()); + } + + @Override + public void updateLight() { + super.updateLight(); + + pressHead.getInstance() + .setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) + .setSkyLight(world.getLightLevel(LightType.SKY, pos)); + } + + @Override + public void remove() { + super.remove(); + pressHead.delete(); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java index d80494f5e..660ced0b3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java @@ -20,6 +20,9 @@ import java.util.stream.Collectors; import javax.annotation.Nullable; +import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld; +import com.simibubi.create.foundation.render.backend.light.GridAlignedBB; +import com.simibubi.create.foundation.utility.*; import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.Pair; @@ -53,12 +56,6 @@ import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.fluid.CombinedTankWrapper; import com.simibubi.create.foundation.render.backend.light.EmptyLighter; -import com.simibubi.create.foundation.utility.BlockFace; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.NBTProcessors; -import com.simibubi.create.foundation.utility.UniqueLinkedList; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; import net.minecraft.block.AbstractButtonBlock; @@ -85,7 +82,6 @@ import net.minecraft.state.properties.PistonType; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; -import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.Rotation; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; @@ -853,16 +849,7 @@ public abstract class Contraption { TileEntity te = TileEntity.create(tag); if (te == null) return; - te.setLocation(new WrappedWorld(world) { - - @Override - public BlockState getBlockState(BlockPos pos) { - if (!pos.equals(te.getPos())) - return Blocks.AIR.getDefaultState(); - return info.state; - } - - }, te.getPos()); + te.setLocation(new ContraptionTileWorld(world, te, info), te.getPos()); if (te instanceof KineticTileEntity) ((KineticTileEntity) te).setSpeed(0); te.getBlockState(); @@ -1091,27 +1078,25 @@ public abstract class Contraption { } public void expandBoundsAroundAxis(Axis axis) { - AxisAlignedBB bb = bounds; - double maxXDiff = Math.max(bb.maxX - 1, -bb.minX); - double maxYDiff = Math.max(bb.maxY - 1, -bb.minY); - double maxZDiff = Math.max(bb.maxZ - 1, -bb.minZ); - double maxDiff = 0; + Set blocks = getBlocks().keySet(); - if (axis == Axis.X) - maxDiff = Math.max(maxZDiff, maxYDiff); - if (axis == Axis.Y) - maxDiff = Math.max(maxZDiff, maxXDiff); - if (axis == Axis.Z) - maxDiff = Math.max(maxXDiff, maxYDiff); + int radius = (int) (Math.ceil(Math.sqrt(getRadius(blocks, axis)))); - Vec3d vec = new Vec3d(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis) - .getDirectionVec()); - Vec3d planeByNormal = VecHelper.axisAlingedPlaneOf(vec); - Vec3d min = vec.mul(bb.minX, bb.minY, bb.minZ) - .add(planeByNormal.scale(-maxDiff)); - Vec3d max = vec.mul(bb.maxX, bb.maxY, bb.maxZ) - .add(planeByNormal.scale(maxDiff + 1)); - bounds = new AxisAlignedBB(min, max); + GridAlignedBB betterBounds = GridAlignedBB.ofRadius(radius); + + GridAlignedBB contraptionBounds = GridAlignedBB.fromAABB(bounds); + if (axis == Direction.Axis.X) { + betterBounds.maxX = contraptionBounds.maxX; + betterBounds.minX = contraptionBounds.minX; + } else if (axis == Direction.Axis.Y) { + betterBounds.maxY = contraptionBounds.maxY; + betterBounds.minY = contraptionBounds.minY; + } else if (axis == Direction.Axis.Z) { + betterBounds.maxZ = contraptionBounds.maxZ; + betterBounds.minZ = contraptionBounds.minZ; + } + + bounds = betterBounds.toAABB(); } public void addExtraInventories(Entity entity) {} @@ -1163,4 +1148,51 @@ public abstract class Contraption { return new EmptyLighter(this); } + public static float getRadius(Set blocks, Direction.Axis axis) { + switch (axis) { + case X: + return getMaxDistSqr(blocks, BlockPos::getY, BlockPos::getZ); + case Y: + return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getZ); + case Z: + return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getY); + } + + throw new IllegalStateException("Impossible axis"); + } + + public static float getMaxDistSqr(Set blocks, Coordinate one, Coordinate other) { + float maxDistSq = -1; + for (BlockPos pos : blocks) { + float a = one.get(pos); + float b = other.get(pos); + + float distSq = a * a + b * b; + + + if (distSq > maxDistSq) maxDistSq = distSq; + } + + return maxDistSq; + } + + private static class ContraptionTileWorld extends WrappedWorld implements IFlywheelWorld { + + private final TileEntity te; + private final BlockInfo info; + + public ContraptionTileWorld(World world, TileEntity te, BlockInfo info) { + super(world); + this.te = te; + this.info = info; + } + + @Override + public BlockState getBlockState(BlockPos pos) { + if (!pos.equals(te.getPos())) + return Blocks.AIR.getDefaultState(); + return info.state; + } + + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/AnchoredLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/AnchoredLighter.java new file mode 100644 index 000000000..09cfa2a39 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/AnchoredLighter.java @@ -0,0 +1,19 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.bearing; + +import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; +import com.simibubi.create.foundation.render.backend.light.GridAlignedBB; + +public class AnchoredLighter extends ContraptionLighter { + + public AnchoredLighter(Contraption contraption) { + super(contraption); + } + + @Override + public GridAlignedBB getContraptionBounds() { + GridAlignedBB bb = GridAlignedBB.fromAABB(contraption.bounds); + bb.translate(contraption.anchor); + return bb; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingContraption.java index 3c2edd2d2..8e1e60aa6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingContraption.java @@ -97,6 +97,6 @@ public class BearingContraption extends Contraption { @OnlyIn(Dist.CLIENT) @Override public ContraptionLighter makeLighter() { - return new BearingLighter(this); + return new AnchoredLighter(this); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingLighter.java deleted file mode 100644 index ef4ab3bf4..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingLighter.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; - -import java.util.Set; - -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; -import com.simibubi.create.foundation.render.backend.light.GridAlignedBB; - -import net.minecraft.util.Direction; -import net.minecraft.util.math.BlockPos; - -public class BearingLighter extends ContraptionLighter { - - public BearingLighter(BearingContraption contraption) { - super(contraption); - } - - @Override - public GridAlignedBB getContraptionBounds() { - Set blocks = contraption.getBlocks().keySet(); - - Direction orientation = contraption.facing; - Direction.Axis axis = orientation.getAxis(); - - int radius = (int) (Math.ceil(Math.sqrt(getRadius(blocks, axis)))); - - GridAlignedBB betterBounds = GridAlignedBB.ofRadius(radius); - - GridAlignedBB contraptionBounds = GridAlignedBB.fromAABB(contraption.bounds); - if (axis == Direction.Axis.X) { - betterBounds.maxX = contraptionBounds.maxX; - betterBounds.minX = contraptionBounds.minX; - } else if (axis == Direction.Axis.Y) { - betterBounds.maxY = contraptionBounds.maxY; - betterBounds.minY = contraptionBounds.minY; - } else if (axis == Direction.Axis.Z) { - betterBounds.maxZ = contraptionBounds.maxZ; - betterBounds.minZ = contraptionBounds.minZ; - } - - betterBounds.translate(contraption.anchor); - return betterBounds; - } - - private static float getRadius(Set blocks, Direction.Axis axis) { - switch (axis) { - case X: - return getMaxDistSqr(blocks, BlockPos::getY, BlockPos::getZ); - case Y: - return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getZ); - case Z: - return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getY); - } - - throw new IllegalStateException("Impossible axis"); - } - - private static float getMaxDistSqr(Set blocks, Coordinate one, Coordinate other) { - float maxDistSq = -1; - for (BlockPos pos : blocks) { - float a = one.get(pos); - float b = other.get(pos); - - float distSq = a * a + b * b; - - - if (distSq > maxDistSq) maxDistSq = distSq; - } - - return maxDistSq; - } - - private interface Coordinate { - float get(BlockPos from); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingTileEntity.java index 49cba252a..197637276 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingTileEntity.java @@ -28,7 +28,8 @@ import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; -public class ClockworkBearingTileEntity extends KineticTileEntity implements IBearingTileEntity, IDisplayAssemblyExceptions { +public class ClockworkBearingTileEntity extends KineticTileEntity + implements IBearingTileEntity, IDisplayAssemblyExceptions { protected ControlledContraptionEntity hourHand; protected ControlledContraptionEntity minuteHand; @@ -40,9 +41,10 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe protected boolean running; protected boolean assembleNextTick; protected AssemblyException lastException; - protected ScrollOptionBehaviour operationMode; + private float prevForcedAngle; + public ClockworkBearingTileEntity(TileEntityType type) { super(type); setLazyTickRate(3); @@ -67,6 +69,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe super.tick(); if (world.isRemote) { + prevForcedAngle = hourAngle; clientMinuteAngleDiff /= 2; clientHourAngleDiff /= 2; } @@ -341,6 +344,8 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe @Override public float getInterpolatedAngle(float partialTicks) { + if (isVirtual()) + return MathHelper.lerp(partialTicks, prevForcedAngle, hourAngle); if (hourHand == null || hourHand.isStalled()) partialTicks = 0; return MathHelper.lerp(partialTicks, hourAngle, hourAngle + getHourArmSpeed()); @@ -414,4 +419,8 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe public boolean shouldRenderAsTE() { return true; } + + public void setAngle(float forcedAngle) { + hourAngle = forcedAngle; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkContraption.java index 1dea812eb..c32679a34 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkContraption.java @@ -4,6 +4,7 @@ import java.util.HashSet; import java.util.Queue; import java.util.Set; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; @@ -129,4 +130,8 @@ public class ClockworkContraption extends Contraption { HOUR, MINUTE } + @Override + public ContraptionLighter makeLighter() { + return new AnchoredLighter(this); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/IBearingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/IBearingTileEntity.java index f2f9a475d..e729feae4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/IBearingTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/IBearingTileEntity.java @@ -20,5 +20,7 @@ public interface IBearingTileEntity extends IControlContraption { return bearingAxis != axis; }); } + + void setAngle(float forcedAngle); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerInstance.java index 60c9e199d..4f5becd7c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerInstance.java @@ -4,12 +4,11 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.foundation.render.backend.RenderMaterials; import com.simibubi.create.foundation.render.backend.instancing.*; -import com.simibubi.create.foundation.render.backend.instancing.impl.TransformData; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.LightTexture; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; import net.minecraft.world.LightType; @@ -24,7 +23,7 @@ public class StickerInstance extends TileEntityInstance imple float lastOffset = Float.NaN; - private InstanceKey head; + private InstanceKey head; public StickerInstance(InstancedTileRenderer modelManager, StickerTileEntity tile) { super(modelManager, tile); @@ -61,7 +60,7 @@ public class StickerInstance extends TileEntityInstance imple .translate(0, (offset * offset) * 4 / 16f, 0); head.getInstance() - .setTransform(stack); + .setTransformNoCopy(stack); lastOffset = offset; } @@ -69,8 +68,8 @@ public class StickerInstance extends TileEntityInstance imple @Override public void updateLight() { head.getInstance() - .setBlockLight((byte) (world.getLightLevel(LightType.BLOCK, pos) << 4)) - .setSkyLight((byte) (world.getLightLevel(LightType.SKY, pos) << 4)); + .setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) + .setSkyLight(world.getLightLevel(LightType.SKY, pos)); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java index 3a94fccb8..c6d2b13a3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java @@ -10,7 +10,7 @@ import com.simibubi.create.foundation.render.backend.instancing.ITickableInstanc import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.impl.TransformData; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.MatrixStacker; @@ -28,7 +28,7 @@ public class GantryCarriageInstance extends ShaftInstance implements ITickableIn InstancedTileRenderRegistry.instance.register(type, GantryCarriageInstance::new)); } - private InstanceKey gantryCogs; + private InstanceKey gantryCogs; public GantryCarriageInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { super(dispatcher, tile); @@ -47,7 +47,7 @@ public class GantryCarriageInstance extends ShaftInstance implements ITickableIn @Override public void tick() { - lastState = world.getBlockState(pos); + lastState = tile.getBlockState(); Direction facing = lastState.get(GantryCarriageBlock.FACING); Boolean alongFirst = lastState.get(GantryCarriageBlock.AXIS_ALONG_FIRST_COORDINATE); Direction.Axis rotationAxis = KineticTileEntityRenderer.getRotationAxisOf(tile); @@ -80,14 +80,14 @@ public class GantryCarriageInstance extends ShaftInstance implements ITickableIn .translate(0, 9 / 16f, 0) .unCentre(); - gantryCogs.getInstance().setTransform(ms); + gantryCogs.getInstance().setTransformNoCopy(ms); } @Override public void updateLight() { gantryCogs.getInstance() - .setBlockLight((byte) (world.getLightLevel(LightType.BLOCK, pos) << 4)) - .setSkyLight((byte) (world.getLightLevel(LightType.SKY, pos) << 4)); + .setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) + .setSkyLight(world.getLightLevel(LightType.SKY, pos)); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageRenderer.java index 0010a4755..271992288 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageRenderer.java @@ -72,7 +72,7 @@ public class GantryCarriageRenderer extends KineticTileEntityRenderer { } public static float getAngleForTe(KineticTileEntity te, final BlockPos pos, Axis axis) { - float time = AnimationTickHolder.getRenderTime(); + float time = AnimationTickHolder.getRenderTime(te.getWorld()); float offset = getRotationOffsetForPosition(te, pos, axis); return ((time * te.getSpeed() * 3f / 20 + offset) % 360) / 180 * (float) Math.PI; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java index 182e063bb..00d708294 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java @@ -41,9 +41,7 @@ public class PulleyRenderer extends AbstractPulleyRenderer { @Override protected float getOffset(KineticTileEntity te, float partialTicks) { PulleyTileEntity pulley = (PulleyTileEntity) te; - boolean running = pulley.running; - boolean moving = running && (pulley.movedContraption == null || !pulley.movedContraption.isStalled()); - float offset = pulley.getInterpolatedOffset(moving ? partialTicks : 0.5f); + float offset = pulley.getInterpolatedOffset(partialTicks); if (pulley.movedContraption != null) { AbstractContraptionEntity e = pulley.movedContraption; @@ -57,7 +55,7 @@ public class PulleyRenderer extends AbstractPulleyRenderer { @Override protected boolean isRunning(KineticTileEntity te) { - return ((PulleyTileEntity) te).running; + return ((PulleyTileEntity) te).running || te.isVirtual(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java index 5fde955e9..f6dbbb33c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java @@ -27,6 +27,7 @@ import net.minecraft.util.math.Vec3d; public class PulleyTileEntity extends LinearActuatorTileEntity { protected int initialOffset; + private float prevAnimatedOffset; public PulleyTileEntity(TileEntityType type) { super(type); @@ -41,6 +42,13 @@ public class PulleyTileEntity extends LinearActuatorTileEntity { public double getMaxRenderDistanceSquared() { return super.getMaxRenderDistanceSquared() + offset * offset; } + + @Override + public void tick() { + super.tick(); + if (isVirtual()) + prevAnimatedOffset = offset; + } @Override protected void assemble() throws AssemblyException { @@ -219,4 +227,16 @@ public class PulleyTileEntity extends LinearActuatorTileEntity { return new CenteredSideValueBoxTransform((state, d) -> d == Direction.UP); } + @Override + public float getInterpolatedOffset(float partialTicks) { + if (isVirtual()) + return MathHelper.lerp(partialTicks, prevAnimatedOffset, offset); + boolean moving = running && (movedContraption == null || !movedContraption.isStalled()); + return super.getInterpolatedOffset(moving ? partialTicks : 0.5f); + } + + public void animateOffset(float forcedOffset) { + offset = forcedOffset; + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionKineticRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionKineticRenderer.java index 6cd01e76b..8413118f7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionKineticRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionKineticRenderer.java @@ -10,14 +10,14 @@ import com.simibubi.create.foundation.render.backend.RenderMaterials; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; -import com.simibubi.create.foundation.render.backend.instancing.impl.TransformedInstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.impl.BasicInstancedModel; import net.minecraft.util.math.BlockPos; public class ContraptionKineticRenderer extends InstancedTileRenderer { @Override public void registerMaterials() { - materials.put(RenderMaterials.MODELS, new RenderMaterial<>(this, AllProgramSpecs.C_MODEL, TransformedInstancedModel::new)); + materials.put(RenderMaterials.MODELS, new RenderMaterial<>(this, AllProgramSpecs.C_MODEL, BasicInstancedModel::new)); materials.put(KineticRenderMaterials.BELTS, new RenderMaterial<>(this, AllProgramSpecs.C_BELT, BeltInstancedModel::new)); materials.put(KineticRenderMaterials.ROTATING, new RenderMaterial<>(this, AllProgramSpecs.C_ROTATING, RotatingInstancedModel::new)); diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticle.java b/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticle.java index f9b754484..43e871aa2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticle.java +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticle.java @@ -67,7 +67,7 @@ public class RotationIndicatorParticle extends SimpleAnimatedParticle { } public void move(double x, double y, double z) { - float time = AnimationTickHolder.getTicks(); + float time = AnimationTickHolder.getTicks(world); float angle = (float) ((time * speed) % 360) - (speed / 2 * age * (((float) age) / maxAge)); if (speed < 0 && axis.isVertical()) angle += 180; diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinRenderer.java index 618816da2..72d80ad6b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinRenderer.java @@ -72,8 +72,9 @@ public class BasinRenderer extends SmartTileEntityRenderer { if (fluidLevel > 0) { ms.translate(0, - (MathHelper.sin(AnimationTickHolder.getRenderTime() / 12f + anglePartition * itemCount) + 1.5f) * 1 - / 32f, + (MathHelper.sin( + AnimationTickHolder.getRenderTime(basin.getWorld()) / 12f + anglePartition * itemCount) + 1.5f) + * 1 / 32f, 0); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerRenderer.java index 458035ec9..df11ef484 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerRenderer.java @@ -27,7 +27,7 @@ public class BlazeBurnerRenderer extends SafeTileEntityRenderer { MatrixStack localTransforms = new MatrixStack(); MatrixStacker msr = MatrixStacker.of(localTransforms); IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); - float renderTick = AnimationTickHolder.getRenderTime(); + float renderTick = AnimationTickHolder.getRenderTime(te.getWorld()); msr.centre(); msr.rotateY(AngleHelper.horizontalAngle(facing) + (upward ? 180 : 0) + (sideways ? 270 : 0)); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftRenderer.java index 1d4531a36..a1cf575af 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftRenderer.java @@ -32,7 +32,7 @@ public class SplitShaftRenderer extends KineticTileEntityRenderer { Block block = te.getBlockState().getBlock(); final Axis boxAxis = ((IRotate) block).getRotationAxis(te.getBlockState()); final BlockPos pos = te.getPos(); - float time = AnimationTickHolder.getRenderTime(); + float time = AnimationTickHolder.getRenderTime(te.getWorld()); for (Direction direction : Iterate.directions) { Axis axis = direction.getAxis(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxRenderer.java index 601aedc49..45463f007 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxRenderer.java @@ -30,7 +30,7 @@ public class GearboxRenderer extends KineticTileEntityRenderer { final Axis boxAxis = te.getBlockState().get(BlockStateProperties.AXIS); final BlockPos pos = te.getPos(); - float time = AnimationTickHolder.getRenderTime(); + float time = AnimationTickHolder.getRenderTime(te.getWorld()); for (Direction direction : Iterate.directions) { final Axis axis = direction.getAxis(); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java index 6432569f0..e4e00e69c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java @@ -1,29 +1,178 @@ package com.simibubi.create.content.logistics.block.mechanicalArm; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.RotatingData; import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.gui.widgets.InterpolatedValue; +import com.simibubi.create.foundation.render.backend.RenderMaterials; +import com.simibubi.create.foundation.render.backend.instancing.*; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.MatrixStacker; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ItemRenderer; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.LightType; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.fml.DistExecutor; -public class ArmInstance extends SingleRotatingInstance { +import java.util.ArrayList; +import java.util.stream.Stream; + +public class ArmInstance extends SingleRotatingInstance implements ITickableInstance { public static void register(TileEntityType type) { DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedTileRenderRegistry.instance.register(type, ArmInstance::new)); } + private InstanceKey base; + private InstanceKey lowerBody; + private InstanceKey upperBody; + private InstanceKey head; + private InstanceKey claw; + private ArrayList> clawGrips; + + private ArrayList> models; + + private boolean firstTick = true; public ArmInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { super(modelManager, tile); } + @Override + protected void init() { + super.init(); + + RenderMaterial> mat = modelManager.getMaterial(RenderMaterials.MODELS); + + base = mat.getModel(AllBlockPartials.ARM_BASE, lastState).createInstance(); + lowerBody = mat.getModel(AllBlockPartials.ARM_LOWER_BODY, lastState).createInstance(); + upperBody = mat.getModel(AllBlockPartials.ARM_UPPER_BODY, lastState).createInstance(); + head = mat.getModel(AllBlockPartials.ARM_HEAD, lastState).createInstance(); + claw = mat.getModel(AllBlockPartials.ARM_CLAW_BASE, lastState).createInstance(); + + InstancedModel clawHalfModel = mat.getModel(AllBlockPartials.ARM_CLAW_GRIP, lastState); + InstanceKey clawGrip1 = clawHalfModel.createInstance(); + InstanceKey clawGrip2 = clawHalfModel.createInstance(); + + clawGrips = Lists.newArrayList(clawGrip1, clawGrip2); + models = Lists.newArrayList(base, lowerBody, upperBody, head, claw, clawGrip1, clawGrip2); + + tick(); + updateLight(); + } + + @Override + public void tick() { + ArmTileEntity arm = (ArmTileEntity) tile; + + boolean settled = Stream.of(arm.baseAngle, arm.lowerArmAngle, arm.upperArmAngle, arm.headAngle).allMatch(InterpolatedValue::settled); + boolean rave = arm.phase == ArmTileEntity.Phase.DANCING; + + if (!settled || rave || firstTick) + transformModels(arm, rave); + + if (settled) + firstTick = false; + } + + private void transformModels(ArmTileEntity arm, boolean rave) { + float pt = AnimationTickHolder.getPartialTicks(); + int color = 0xFFFFFF; + + float baseAngle = arm.baseAngle.get(pt); + float lowerArmAngle = arm.lowerArmAngle.get(pt) - 135; + float upperArmAngle = arm.upperArmAngle.get(pt) - 90; + float headAngle = arm.headAngle.get(pt); + + if (rave) { + float renderTick = AnimationTickHolder.getRenderTime(arm.getWorld()) + (tile.hashCode() % 64); + baseAngle = (renderTick * 10) % 360; + lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15); + upperArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 8) + 1) / 4, -45, 95); + headAngle = -lowerArmAngle; + color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100); + } + + + MatrixStack msLocal = new MatrixStack(); + MatrixStacker msr = MatrixStacker.of(msLocal); + msr.translate(getFloatingPos()); + msr.centre(); + + if (lastState.get(ArmBlock.CEILING)) + msr.rotateX(180); + + ArmRenderer.transformBase(msr, baseAngle); + base.getInstance() + .setTransform(msLocal); + + ArmRenderer.transformLowerArm(msr, lowerArmAngle); + lowerBody.getInstance() + .setColor(color) + .setTransform(msLocal); + + ArmRenderer.transformUpperArm(msr, upperArmAngle); + upperBody.getInstance() + .setColor(color) + .setTransform(msLocal); + + ArmRenderer.transformHead(msr, headAngle); + head.getInstance() + .setTransform(msLocal); + + ArmRenderer.transformClaw(msr); + claw.getInstance() + .setTransform(msLocal); + + ItemStack item = arm.heldItem; + ItemRenderer itemRenderer = Minecraft.getInstance() + .getItemRenderer(); + boolean hasItem = !item.isEmpty(); + boolean isBlockItem = hasItem && (item.getItem() instanceof BlockItem) + && itemRenderer.getItemModelWithOverrides(item, Minecraft.getInstance().world, null) + .isGui3d(); + + for (int index : Iterate.zeroAndOne) { + msLocal.push(); + int flip = index * 2 - 1; + ArmRenderer.transformClawHalf(msr, hasItem, isBlockItem, flip); + clawGrips.get(index) + .getInstance() + .setTransform(msLocal); + msLocal.pop(); + } + } + + @Override + public void updateLight() { + super.updateLight(); + int block = world.getLightLevel(LightType.BLOCK, pos); + int sky = world.getLightLevel(LightType.SKY, pos); + + + models.stream() + .map(InstanceKey::getInstance) + .forEach(data -> data.setSkyLight(sky).setBlockLight(block)); + } + @Override protected InstancedModel getModel() { return AllBlockPartials.ARM_COG.renderOnRotating(modelManager, tile.getBlockState()); } + + @Override + public void remove() { + super.remove(); + models.forEach(InstanceKey::delete); + } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java index a15fca209..9f4c6224e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java @@ -7,6 +7,8 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.logistics.block.mechanicalArm.ArmTileEntity.Phase; import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.Backend; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.Iterate; @@ -39,6 +41,21 @@ public class ArmRenderer extends KineticTileEntityRenderer { int overlay) { super.renderSafe(te, pt, ms, buffer, light, overlay); ArmTileEntity arm = (ArmTileEntity) te; + + boolean usingFlywheel = FastRenderDispatcher.available(te.getWorld()); + + ItemStack item = arm.heldItem; + boolean hasItem = !item.isEmpty(); + + if (usingFlywheel && !hasItem) return; + + ItemRenderer itemRenderer = Minecraft.getInstance() + .getItemRenderer(); + + boolean isBlockItem = hasItem && (item.getItem() instanceof BlockItem) + && itemRenderer.getItemModelWithOverrides(item, Minecraft.getInstance().world, null) + .isGui3d(); + IVertexBuilder builder = buffer.getBuffer(RenderType.getSolid()); BlockState blockState = te.getBlockState(); @@ -52,7 +69,7 @@ public class ArmRenderer extends KineticTileEntityRenderer { float headAngle = arm.headAngle.get(pt); boolean rave = arm.phase == Phase.DANCING; - float renderTick = AnimationTickHolder.getRenderTime() + (te.hashCode() % 64); + float renderTick = AnimationTickHolder.getRenderTime(te.getWorld()) + (te.hashCode() % 64); if (rave) { baseAngle = (renderTick * 10) % 360; lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15); @@ -61,59 +78,15 @@ public class ArmRenderer extends KineticTileEntityRenderer { color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100); } - SuperByteBuffer base = AllBlockPartials.ARM_BASE.renderOn(blockState).light(light); - SuperByteBuffer lowerBody = AllBlockPartials.ARM_LOWER_BODY.renderOn(blockState).light(light); - SuperByteBuffer upperBody = AllBlockPartials.ARM_UPPER_BODY.renderOn(blockState).light(light); - SuperByteBuffer head = AllBlockPartials.ARM_HEAD.renderOn(blockState).light(light); - SuperByteBuffer claw = AllBlockPartials.ARM_CLAW_BASE.renderOn(blockState).light(light); - SuperByteBuffer clawGrip = AllBlockPartials.ARM_CLAW_GRIP.renderOn(blockState); - msr.centre(); - + if (blockState.get(ArmBlock.CEILING)) msr.rotateX(180); - msLocal.translate(0, 4 / 16d, 0); - msr.rotateY(baseAngle); - base.transform(msLocal) - .renderInto(ms, builder); - - msLocal.translate(0, 1 / 16d, -2 / 16d); - msr.rotateX(lowerArmAngle); - msLocal.translate(0, -1 / 16d, 0); - lowerBody.color(color) - .transform(msLocal) - .renderInto(ms, builder); - - msLocal.translate(0, 12 / 16d, 12 / 16d); - msr.rotateX(upperArmAngle); - upperBody.color(color) - .transform(msLocal) - .renderInto(ms, builder); - - msLocal.translate(0, 11 / 16d, -11 / 16d); - msr.rotateX(headAngle); - head.transform(msLocal) - .renderInto(ms, builder); - - msLocal.translate(0, 0, -4 / 16d); - claw.transform(msLocal) - .renderInto(ms, builder); - ItemStack item = arm.heldItem; - ItemRenderer itemRenderer = Minecraft.getInstance() - .getItemRenderer(); - boolean hasItem = !item.isEmpty(); - boolean isBlockItem = hasItem && (item.getItem() instanceof BlockItem) - && itemRenderer.getItemModelWithOverrides(item, Minecraft.getInstance().world, null) - .isGui3d(); - - for (int flip : Iterate.positiveAndNegative) { - msLocal.push(); - msLocal.translate(0, flip * 3 / 16d, -1 / 16d); - msr.rotateX(flip * (hasItem ? isBlockItem ? 0 : -35 : 0)); - clawGrip.light(light).transform(msLocal).renderInto(ms, builder); - msLocal.pop(); - } + if (usingFlywheel) + doItemTransforms(msr, baseAngle, lowerArmAngle, upperArmAngle, headAngle); + else + renderArm(builder, ms, msLocal, msr, blockState, color, baseAngle, lowerArmAngle, upperArmAngle, headAngle, hasItem, isBlockItem, light); if (hasItem) { ms.push(); @@ -131,6 +104,83 @@ public class ArmRenderer extends KineticTileEntityRenderer { } + private void renderArm(IVertexBuilder builder, MatrixStack ms, MatrixStack msLocal, MatrixStacker msr, BlockState blockState, int color, float baseAngle, float lowerArmAngle, float upperArmAngle, float headAngle, boolean hasItem, boolean isBlockItem, int light) { + SuperByteBuffer base = AllBlockPartials.ARM_BASE.renderOn(blockState).light(light); + SuperByteBuffer lowerBody = AllBlockPartials.ARM_LOWER_BODY.renderOn(blockState).light(light); + SuperByteBuffer upperBody = AllBlockPartials.ARM_UPPER_BODY.renderOn(blockState).light(light); + SuperByteBuffer head = AllBlockPartials.ARM_HEAD.renderOn(blockState).light(light); + SuperByteBuffer claw = AllBlockPartials.ARM_CLAW_BASE.renderOn(blockState).light(light); + SuperByteBuffer clawGrip = AllBlockPartials.ARM_CLAW_GRIP.renderOn(blockState); + + transformBase(msr, baseAngle); + base.transform(msLocal) + .renderInto(ms, builder); + + transformLowerArm(msr, lowerArmAngle); + lowerBody.color(color) + .transform(msLocal) + .renderInto(ms, builder); + + transformUpperArm(msr, upperArmAngle); + upperBody.color(color) + .transform(msLocal) + .renderInto(ms, builder); + + transformHead(msr, headAngle); + head.transform(msLocal) + .renderInto(ms, builder); + + transformClaw(msr); + claw.transform(msLocal) + .renderInto(ms, builder); + + for (int flip : Iterate.positiveAndNegative) { + msLocal.push(); + transformClawHalf(msr, hasItem, isBlockItem, flip); + clawGrip.light(light).transform(msLocal).renderInto(ms, builder); + msLocal.pop(); + } + } + + private void doItemTransforms(MatrixStacker msr, float baseAngle, float lowerArmAngle, float upperArmAngle, float headAngle) { + + transformBase(msr, baseAngle); + transformLowerArm(msr, lowerArmAngle); + transformUpperArm(msr, upperArmAngle); + transformHead(msr, headAngle); + transformClaw(msr); + } + + public static void transformClawHalf(MatrixStacker msr, boolean hasItem, boolean isBlockItem, int flip) { + msr.translate(0, flip * 3 / 16d, -1 / 16d); + msr.rotateX(flip * (hasItem ? isBlockItem ? 0 : -35 : 0)); + } + + public static void transformClaw(MatrixStacker msr) { + msr.translate(0, 0, -4 / 16d); + } + + public static void transformHead(MatrixStacker msr, float headAngle) { + msr.translate(0, 11 / 16d, -11 / 16d); + msr.rotateX(headAngle); + } + + public static void transformUpperArm(MatrixStacker msr, float upperArmAngle) { + msr.translate(0, 12 / 16d, 12 / 16d); + msr.rotateX(upperArmAngle); + } + + public static void transformLowerArm(MatrixStacker msr, float lowerArmAngle) { + msr.translate(0, 1 / 16d, -2 / 16d); + msr.rotateX(lowerArmAngle); + msr.translate(0, -1 / 16d, 0); + } + + public static void transformBase(MatrixStacker msr, float baseAngle) { + msr.translate(0, 4 / 16d, 0); + msr.rotateY(baseAngle); + } + @Override protected SuperByteBuffer getRotatedModel(KineticTileEntity te) { return AllBlockPartials.ARM_COG.renderOn(te.getBlockState()); diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInstance.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInstance.java new file mode 100644 index 000000000..47ddbaf4c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInstance.java @@ -0,0 +1,99 @@ +package com.simibubi.create.content.schematics.block; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelInstance; +import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelTileEntity; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.RenderMaterials; +import com.simibubi.create.foundation.render.backend.instancing.*; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.MatrixStacker; +import net.minecraft.block.BlockState; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.LightType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class SchematicannonInstance extends TileEntityInstance implements ITickableInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, SchematicannonInstance::new)); + } + + private InstanceKey connector; + private InstanceKey pipe; + + public SchematicannonInstance(InstancedTileRenderer modelManager, SchematicannonTileEntity tile) { + super(modelManager, tile); + } + + @Override + protected void init() { + + RenderMaterial> mat = modelManager.getMaterial(RenderMaterials.MODELS); + + connector = mat.getModel(AllBlockPartials.SCHEMATICANNON_CONNECTOR, lastState).createInstance(); + pipe = mat.getModel(AllBlockPartials.SCHEMATICANNON_PIPE, lastState).createInstance(); + + updateLight(); + } + + @Override + public void tick() { + float partialTicks = AnimationTickHolder.getPartialTicks(); + + double[] cannonAngles = SchematicannonRenderer.getCannonAngles(tile, pos, partialTicks); + + double pitch = cannonAngles[0]; + double yaw = cannonAngles[1]; + + double recoil = SchematicannonRenderer.getRecoil(tile, partialTicks); + + MatrixStack ms = new MatrixStack(); + MatrixStacker msr = MatrixStacker.of(ms); + + msr.translate(getFloatingPos()); + + ms.push(); + msr.centre(); + msr.rotate(Direction.UP, (float) ((yaw + 90) / 180 * Math.PI)); + msr.unCentre(); + connector.getInstance().setTransform(ms); + ms.pop(); + + msr.translate(.5f, 15 / 16f, .5f); + msr.rotate(Direction.UP, (float) ((yaw + 90) / 180 * Math.PI)); + msr.rotate(Direction.SOUTH, (float) (pitch / 180 * Math.PI)); + msr.translate(-.5f, -15 / 16f, -.5f); + msr.translate(0, -recoil / 100, 0); + + pipe.getInstance().setTransformNoCopy(ms); + } + + @Override + public void remove() { + connector.delete(); + pipe.delete(); + } + + @Override + public void updateLight() { + int block = world.getLightLevel(LightType.BLOCK, pos); + int sky = world.getLightLevel(LightType.SKY, pos); + + connector.getInstance() + .setBlockLight(block) + .setSkyLight(sky); + + pipe.getInstance() + .setBlockLight(block) + .setSkyLight(sky); + } +} diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonRenderer.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonRenderer.java index 6163c07fc..32856a392 100644 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonRenderer.java +++ b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonRenderer.java @@ -8,6 +8,7 @@ import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.schematics.block.LaunchedItem.ForBlockState; import com.simibubi.create.content.schematics.block.LaunchedItem.ForEntity; import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import net.minecraft.block.BlockState; @@ -40,33 +41,20 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer launched.totalTicks - 10) + recoil = Math.max(recoil, (launched.ticksRemaining + 1 - partialTicks) - launched.totalTicks + 10); + } + + return recoil; + } + + private static void renderLaunchedBlocks(SchematicannonTileEntity tileEntityIn, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { for (LaunchedItem launched : tileEntityIn.flyingBlocks) { if (launched.ticksRemaining == 0) @@ -141,10 +171,6 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer launched.totalTicks - 10) - recoil = Math.max(recoil, (launched.ticksRemaining + 1 - partialTicks) - launched.totalTicks + 10); - // Render particles for launch if (launched.ticksRemaining == launched.totalTicks && tileEntityIn.firstRenderTick) { tileEntityIn.firstRenderTick = false; @@ -162,8 +188,6 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer () -> CreateClient.kineticRenderer.add(this)); + } + + @Override + public void onChunkLightUpdate() { + CreateClient.kineticRenderer.onLightUpdate(this); + } + + @Override + public boolean shouldRenderAsTE() { + return true; + } } diff --git a/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java b/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java index 17806fb70..577ea8028 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java @@ -122,7 +122,8 @@ public class AllIcons implements IScreenRenderable { I_MTD_CLOSE = next(), I_MTD_RIGHT = next(), I_MTD_SCAN = next(), - I_MTD_REPLAY = next(); + I_MTD_REPLAY = next(), + I_MTD_USER_MODE = next(); public AllIcons(int x, int y) { iconX = x * 16; diff --git a/src/main/java/com/simibubi/create/foundation/gui/widgets/InterpolatedValue.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/InterpolatedValue.java index 6739f39af..ebc1e712f 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widgets/InterpolatedValue.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/InterpolatedValue.java @@ -16,5 +16,9 @@ public class InterpolatedValue { public float get(float partialTicks) { return MathHelper.lerp(partialTicks, lastValue, value); } + + public boolean settled() { + return Math.abs(value - lastValue) < 1e-3; + } } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java index 1eee89b34..3f56194e9 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java @@ -76,10 +76,13 @@ public class PonderScene { WorldSectionElement baseWorldSection; Entity renderViewEntity; - int offsetX; - int offsetZ; - int size; + int basePlateOffsetX; + int basePlateOffsetZ; + int basePlateSize; + float scaleFactor; + float yOffset; + boolean stoppedCounting; int totalTime; int currentTime; @@ -97,10 +100,12 @@ public class PonderScene { schedule = new ArrayList<>(); activeSchedule = new ArrayList<>(); transform = new SceneTransform(); - size = getBounds().getXSize(); + basePlateSize = getBounds().getXSize(); info = new SceneRenderInfo(); baseWorldSection = new WorldSectionElement(); renderViewEntity = new ArmorStandEntity(world, 0, 0, 0); + scaleFactor = 1; + yOffset = 0; setPointOfInterest(new Vec3d(0, 4, 0)); } @@ -135,11 +140,12 @@ public class PonderScene { BlockPos selectedPos = nearestHit.getValue() .getSecond(); - BlockPos origin = new BlockPos(offsetX, 0, offsetZ); + BlockPos origin = new BlockPos(basePlateOffsetX, 0, basePlateOffsetZ); if (!world.getBounds() .isVecInside(selectedPos)) return Pair.of(ItemStack.EMPTY, null); - if (new MutableBoundingBox(origin, origin.add(new Vec3i(size - 1, 0, size - 1))).isVecInside(selectedPos)) { + if (new MutableBoundingBox(origin, origin.add(new Vec3i(basePlateSize - 1, 0, basePlateSize - 1))) + .isVecInside(selectedPos)) { if (PonderIndex.EDITOR_MODE) nearestHit.getValue() .getFirst() @@ -189,6 +195,7 @@ public class PonderScene { elements.add(baseWorldSection); totalTime = 0; + stoppedCounting = false; activeSchedule.addAll(schedule); activeSchedule.forEach(i -> i.onScheduled(this)); } @@ -269,7 +276,12 @@ public class PonderScene { } public void addToSceneTime(int time) { - totalTime += time; + if (!stoppedCounting) + totalTime += time; + } + + public void stopCounting() { + stoppedCounting = true; } public void addElement(PonderElement e) { @@ -376,11 +388,11 @@ public class PonderScene { } public MatrixStack apply(MatrixStack ms) { - return apply(ms, AnimationTickHolder.getPartialTicks()); + return apply(ms, AnimationTickHolder.getPartialTicks(world)); } public MatrixStack apply(MatrixStack ms, float pt) { - ms.translate(width / 2, height / 2, 200); + ms.translate(width / 2, height / 2, 200 + offset); MatrixStacker.of(ms) .rotateX(-35) @@ -389,12 +401,15 @@ public class PonderScene { MatrixStacker.of(ms) .rotateY(-55) .rotateX(35); - MatrixStacker.of(ms) .rotateX(xRotation.getValue(pt)) .rotateY(yRotation.getValue(pt)); - ms.scale(30, -30, 30); - ms.translate((size + offsetX) / -2f, -1f, (size + offsetZ) / -2f); + + float f = 30 * scaleFactor; + + ms.scale(f, -f, f); + ms.translate((basePlateSize + basePlateOffsetX) / -2f, -1f + yOffset, + (basePlateSize + basePlateOffsetZ) / -2f); return ms; } @@ -409,7 +424,7 @@ public class PonderScene { float pt = AnimationTickHolder.getPartialTicks(); Vec3d vec = new Vec3d(x, y, depth); - vec = vec.subtract(width / 2, height / 2, 200); + vec = vec.subtract(width / 2, height / 2, 200 + offset); vec = VecHelper.rotate(vec, 35, Axis.X); vec = VecHelper.rotate(vec, -55, Axis.Y); vec = vec.subtract(offset, 0, 0); @@ -417,8 +432,12 @@ public class PonderScene { vec = VecHelper.rotate(vec, -35, Axis.X); vec = VecHelper.rotate(vec, -xRotation.getValue(pt), Axis.X); vec = VecHelper.rotate(vec, -yRotation.getValue(pt), Axis.Y); - vec = vec.mul(1f / 30, 1f / -30, 1f / 30); - vec = vec.subtract((size + offsetX) / -2f, -1f, (size + offsetZ) / -2f); + + float f = 1f / (30 * scaleFactor); + + vec = vec.mul(f, -f, f); + vec = vec.subtract((basePlateSize + basePlateOffsetX) / -2f, -1f + yOffset, + (basePlateSize + basePlateOffsetZ) / -2f); return vec; } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderTooltipHandler.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderTooltipHandler.java index 6209624bc..2f1abec45 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderTooltipHandler.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderTooltipHandler.java @@ -95,7 +95,8 @@ public class PonderTooltipHandler { } public static void addToTooltip(List toolTip, ItemStack stack) { - float renderPartialTicks = AnimationTickHolder.getPartialTicks(); + float renderPartialTicks = Minecraft.getInstance() + .getRenderPartialTicks(); if (lastHoveredStack != stack) return; ITextComponent component = subject ? Lang.createTranslationTextComponent(SUBJECT) diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java index 29f877017..c39d48077 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java @@ -24,7 +24,6 @@ import com.simibubi.create.foundation.ponder.content.PonderTag; import com.simibubi.create.foundation.ponder.content.PonderTagScreen; import com.simibubi.create.foundation.ponder.ui.PonderButton; import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; @@ -38,6 +37,7 @@ import net.minecraft.client.GameSettings; import net.minecraft.client.MainWindow; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.widget.Widget; import net.minecraft.client.settings.KeyBinding; import net.minecraft.item.ItemStack; import net.minecraft.util.Direction; @@ -55,6 +55,9 @@ import net.minecraftforge.registries.ForgeRegistries; public class PonderUI extends AbstractSimiScreen { + public static int ponderTicks; + public static float ponderPartialTicksPaused; + public static final String PONDERING = PonderLocalization.LANG_PREFIX + "pondering"; public static final String IDENTIFY_MODE = PonderLocalization.LANG_PREFIX + "identify_mode"; public static final String IN_CHAPTER = PonderLocalization.LANG_PREFIX + "in_chapter"; @@ -68,6 +71,7 @@ public class PonderUI extends AbstractSimiScreen { ItemStack stack; PonderChapter chapter = null; + private boolean userViewMode; private boolean identifyMode; private ItemStack hoveredTooltipItem; private BlockPos hoveredBlockPos; @@ -79,7 +83,7 @@ public class PonderUI extends AbstractSimiScreen { private int index = 0; private PonderTag referredToByTag; - private PonderButton left, right, scan, chap; + private PonderButton left, right, scan, chap, userMode; public static PonderUI of(ItemStack item) { return new PonderUI(PonderRegistry.compile(item.getItem() @@ -134,7 +138,7 @@ public class PonderUI extends AbstractSimiScreen { tags.forEach(t -> { int i = tagButtons.size(); int x = 31; - int y = 71 + i * 30; + int y = 81 + i * 30; PonderButton b = new PonderButton(x, y, (mouseX, mouseY) -> { centerScalingOn(mouseX, mouseY); ScreenOpener.transitionTo(new PonderTagScreen(t)); @@ -165,10 +169,19 @@ public class PonderUI extends AbstractSimiScreen { if (!identifyMode) scenes.get(index) .deselect(); + else + ponderPartialTicksPaused = minecraft.getRenderPartialTicks(); }).showing(AllIcons.I_MTD_SCAN) .shortcut(bindings.keyBindDrop) .fade(0, -1)); + if (PonderIndex.EDITOR_MODE) { + widgets.add(userMode = new PonderButton(31, bY, () -> { + userViewMode = !userViewMode; + }).showing(AllIcons.I_MTD_USER_MODE) + .fade(0, -1)); + } + bX += 50 + spacing; widgets.add(left = new PonderButton(bX, bY, () -> this.scroll(false)).showing(AllIcons.I_MTD_LEFT) .shortcut(bindings.keyBindLeft) @@ -215,8 +228,10 @@ public class PonderUI extends AbstractSimiScreen { } PonderScene activeScene = scenes.get(index); - if (!identifyMode) + if (!identifyMode) { + ponderTicks++; activeScene.tick(); + } sceneProgress.chase(activeScene.getSceneProgress(), .5f, Chaser.EXP); lazyIndex.tickChaser(); fadeIn.tickChaser(); @@ -295,8 +310,13 @@ public class PonderUI extends AbstractSimiScreen { @Override protected void renderWindow(int mouseX, int mouseY, float partialTicks) { RenderSystem.enableBlend(); - renderVisibleScenes(mouseX, mouseY, identifyMode ? 0 : partialTicks); - renderWidgets(mouseX, mouseY, identifyMode ? 0 : partialTicks); + renderVisibleScenes(mouseX, mouseY, identifyMode ? ponderPartialTicksPaused : partialTicks); + renderWidgets(mouseX, mouseY, identifyMode ? ponderPartialTicksPaused : partialTicks); + } + + @Override + public void renderBackground() { + super.renderBackground(); } protected void renderVisibleScenes(int mouseX, int mouseY, float partialTicks) { @@ -310,7 +330,7 @@ public class PonderUI extends AbstractSimiScreen { SuperRenderTypeBuffer buffer = SuperRenderTypeBuffer.getInstance(); PonderScene story = scenes.get(i); MatrixStack ms = new MatrixStack(); - double value = lazyIndex.getValue(AnimationTickHolder.getPartialTicks()); + double value = lazyIndex.getValue(minecraft.getRenderPartialTicks()); double diff = i - value; double slide = MathHelper.lerp(diff * diff, 200, 600) * diff; @@ -325,15 +345,36 @@ public class PonderUI extends AbstractSimiScreen { story.renderScene(buffer, ms, partialTicks); buffer.draw(); - // coords for debug - if (PonderIndex.EDITOR_MODE) { - MutableBoundingBox bounds = story.getBounds(); + MutableBoundingBox bounds = story.getBounds(); + RenderSystem.pushMatrix(); + RenderSystem.multMatrix(ms.peek() + .getModel()); + // kool shadow fx + { + RenderSystem.enableCull(); + RenderSystem.enableDepthTest(); RenderSystem.pushMatrix(); - RenderSystem.multMatrix(ms.peek() - .getModel()); + RenderSystem.translated(story.basePlateOffsetX, 0, story.basePlateOffsetZ); + RenderSystem.scaled(1, -1, 1); + for (int f = 0; f < 4; f++) { + RenderSystem.translated(story.basePlateSize, 0, 0); + RenderSystem.pushMatrix(); + RenderSystem.translated(0, 0, 1/1024f); + GuiUtils.drawGradientRect(0, 0, 0, -story.basePlateSize, 4, 0x66_000000, 0x00_000000); + RenderSystem.popMatrix(); + RenderSystem.rotatef(-90, 0, 1, 0); + } + RenderSystem.popMatrix(); + RenderSystem.disableCull(); + RenderSystem.disableDepthTest(); + } - RenderSystem.scaled(-1 / 16d, -1 / 16d, 1 / 16d); + // coords for debug + if (PonderIndex.EDITOR_MODE && !userViewMode) { + + RenderSystem.scaled(-1, -1, 1); + RenderSystem.scaled(1 / 16d, 1 / 16d, 1 / 16d); RenderSystem.translated(1, -8, -1 / 64f); // X AXIS @@ -373,11 +414,11 @@ public class PonderUI extends AbstractSimiScreen { RenderSystem.popMatrix(); } RenderSystem.popMatrix(); - buffer.draw(); - RenderSystem.popMatrix(); } + RenderSystem.popMatrix(); + ms.pop(); } @@ -388,6 +429,10 @@ public class PonderUI extends AbstractSimiScreen { PonderScene activeScene = scenes.get(index); int textColor = 0xeeeeee; + boolean noWidgetsHovered = true; + for (Widget widget : widgets) + noWidgetsHovered &= !widget.isMouseOver(mouseX, mouseY); + { // Chapter title RenderSystem.pushMatrix(); @@ -396,7 +441,7 @@ public class PonderUI extends AbstractSimiScreen { int y = 31; String title = activeScene.getTitle(); - int wordWrappedHeight = font.getWordWrappedHeight(title, left.x); + int wordWrappedHeight = font.getWordWrappedHeight(title, left.x - 51); int streakHeight = 35 - 9 + wordWrappedHeight; UIRenderHelper.streak(0, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (150 * fade), 0x101010); @@ -415,7 +460,7 @@ public class PonderUI extends AbstractSimiScreen { RenderSystem.translated(x, y, 0); RenderSystem.rotatef(indexDiff * -75, 1, 0, 0); RenderSystem.translated(0, 0, 5); - font.drawSplitString(title, 0, 0, left.x, ColorHelper.applyAlpha(textColor, 1 - indexDiff)); + font.drawSplitString(title, 0, 0, left.x - 51, ColorHelper.applyAlpha(textColor, 1 - indexDiff)); RenderSystem.popMatrix(); if (chapter != null) { @@ -433,34 +478,42 @@ public class PonderUI extends AbstractSimiScreen { } if (identifyMode) { - RenderSystem.pushMatrix(); - RenderSystem.translated(mouseX, mouseY, 100); - if (hoveredTooltipItem.isEmpty()) { - String tooltip = Lang - .createTranslationTextComponent(IDENTIFY_MODE, - new StringTextComponent(minecraft.gameSettings.keyBindDrop.getKeyBinding() - .getLocalizedName()).applyTextStyle(TextFormatting.WHITE)) - .applyTextStyle(TextFormatting.GRAY) - .getFormattedText(); - renderTooltip(font.listFormattedStringToWidth(tooltip, width / 3), 0, 0); - } else - renderTooltip(hoveredTooltipItem, 0, 0); - if (hoveredBlockPos != null && PonderIndex.EDITOR_MODE) { - RenderSystem.translated(0, -15, 0); - boolean copied = copiedBlockPos != null && hoveredBlockPos.equals(copiedBlockPos); - String coords = new StringTextComponent( - hoveredBlockPos.getX() + ", " + hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ()) - .applyTextStyles(copied ? TextFormatting.GREEN : TextFormatting.GOLD) + if (noWidgetsHovered) { + RenderSystem.pushMatrix(); + RenderSystem.translated(mouseX, mouseY, 100); + if (hoveredTooltipItem.isEmpty()) { + String tooltip = Lang + .createTranslationTextComponent(IDENTIFY_MODE, + new StringTextComponent(minecraft.gameSettings.keyBindDrop.getKeyBinding() + .getLocalizedName()).applyTextStyle(TextFormatting.WHITE)) + .applyTextStyle(TextFormatting.GRAY) .getFormattedText(); - renderTooltip(coords, 0, 0); + renderTooltip(font.listFormattedStringToWidth(tooltip, width / 3), 0, 0); + } else + renderTooltip(hoveredTooltipItem, 0, 0); + if (hoveredBlockPos != null && PonderIndex.EDITOR_MODE && !userViewMode) { + RenderSystem.translated(0, -15, 0); + boolean copied = copiedBlockPos != null && hoveredBlockPos.equals(copiedBlockPos); + String coords = new StringTextComponent( + hoveredBlockPos.getX() + ", " + hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ()) + .applyTextStyles(copied ? TextFormatting.GREEN : TextFormatting.GOLD) + .getFormattedText(); + renderTooltip(coords, 0, 0); + } + RenderSystem.popMatrix(); } - RenderSystem.popMatrix(); - scan.flash(); } else { scan.dim(); } + if (PonderIndex.EDITOR_MODE) { + if (userViewMode) + userMode.flash(); + else + userMode.dim(); + } + { // Scene overlay RenderSystem.pushMatrix(); @@ -494,11 +547,16 @@ public class PonderUI extends AbstractSimiScreen { int x = (width / 2) - 110; int y = right.y + right.getHeight() + 4; int w = width - 2 * x; + + RenderSystem.pushMatrix(); + RenderSystem.translated(0, 0, 400); renderBox(x, y, w, 1, false); + RenderSystem.popMatrix(); + RenderSystem.pushMatrix(); RenderSystem.translated(x - 2, y - 2, 0); RenderSystem.scaled((w + 4) * sceneProgress.getValue(partialTicks), 1, 1); - GuiUtils.drawGradientRect(200, 0, 3, 1, 4, 0x60ffeedd, 0x60ffeedd); + GuiUtils.drawGradientRect(500, 0, 3, 1, 4, 0x60ffeedd, 0x60ffeedd); RenderSystem.popMatrix(); } @@ -602,8 +660,12 @@ public class PonderUI extends AbstractSimiScreen { return true; } - clipboardHelper.setClipboardString(handle, "util.grid.at(" + hoveredBlockPos.getX() + ", " - + hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ() + ")"); + if (hasShiftDown()) + clipboardHelper.setClipboardString(handle, "util.select.position(" + hoveredBlockPos.getX() + ", " + + hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ() + ")"); + else + clipboardHelper.setClipboardString(handle, "util.grid.at(" + hoveredBlockPos.getX() + ", " + + hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ() + ")"); copiedBlockPos = hoveredBlockPos; return true; } @@ -773,8 +835,25 @@ public class PonderUI extends AbstractSimiScreen { @Override public void shareContextWith(AbstractSimiScreen other) { - if (other instanceof PonderUI) - ((PonderUI) other).referredToByTag = referredToByTag; + if (other instanceof PonderUI) { + PonderUI ponderUI = (PonderUI) other; + ponderUI.referredToByTag = referredToByTag; + } + } + + public static float getPartialTicks() { + if (Minecraft.getInstance().currentScreen instanceof PonderUI) { + PonderUI ui = (PonderUI) Minecraft.getInstance().currentScreen; + if (ui.identifyMode) + return ponderPartialTicksPaused; + } + return Minecraft.getInstance() + .getRenderPartialTicks(); + } + + @Override + public boolean isPauseScreen() { + return true; } } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java b/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java index 17ea8d9a0..2529ea352 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java @@ -34,6 +34,7 @@ import com.simibubi.create.foundation.ponder.instructions.DisplayWorldSectionIns import com.simibubi.create.foundation.ponder.instructions.EmitParticlesInstruction; import com.simibubi.create.foundation.ponder.instructions.EmitParticlesInstruction.Emitter; import com.simibubi.create.foundation.ponder.instructions.FadeOutOfSceneInstruction; +import com.simibubi.create.foundation.ponder.instructions.HighlightValueBoxInstruction; import com.simibubi.create.foundation.ponder.instructions.LineInstruction; import com.simibubi.create.foundation.ponder.instructions.MarkAsFinishedInstruction; import com.simibubi.create.foundation.ponder.instructions.MovePoiInstruction; @@ -140,9 +141,29 @@ public class SceneBuilder { * assumes it to be square */ public void configureBasePlate(int xOffset, int zOffset, int basePlateSize) { - scene.offsetX = xOffset; - scene.offsetZ = zOffset; - scene.size = basePlateSize; + scene.basePlateOffsetX = xOffset; + scene.basePlateOffsetZ = zOffset; + scene.basePlateSize = basePlateSize; + } + + /** + * Use this in case you are not happy with the scale of the scene relative to + * the overlay + * + * @param factor >1 will make the scene appear larger, smaller otherwise + */ + public void scaleSceneView(float factor) { + scene.scaleFactor = factor; + } + + /** + * Use this in case you are not happy with the vertical alignment of the scene + * relative to the overlay + * + * @param yOffset >0 moves the scene up, down otherwise + */ + public void setSceneOffsetY(float yOffset) { + scene.yOffset = yOffset; } /** @@ -150,8 +171,10 @@ public class SceneBuilder { * of the schematic's structure. Makes for a nice opener */ public void showBasePlate() { - world.showSection(scene.getSceneBuildingUtil().select.cuboid(new BlockPos(scene.offsetX, 0, scene.offsetZ), - new Vec3i(scene.size, 0, scene.size)), Direction.UP); + world.showSection( + scene.getSceneBuildingUtil().select.cuboid(new BlockPos(scene.basePlateOffsetX, 0, scene.basePlateOffsetZ), + new Vec3i(scene.basePlateSize, 0, scene.basePlateSize)), + Direction.UP); } /** @@ -284,6 +307,15 @@ public class SceneBuilder { addInstruction(new ChaseAABBInstruction(color, slot, boundingBox, duration)); } + public void showCenteredScrollInput(BlockPos pos, Direction side, int duration) { + Axis axis = side.getAxis(); + float s = 1 / 16f; + float q = 1 / 4f; + Vec3d expands = new Vec3d(axis == Axis.X ? s : q, axis == Axis.Y ? s : q, axis == Axis.Z ? s : q); + addInstruction(new HighlightValueBoxInstruction(scene.getSceneBuildingUtil().vector.blockSurface(pos, side), + expands, duration)); + } + public void showLine(PonderPalette color, Vec3d start, Vec3d end, int duration) { addInstruction(new LineInstruction(color, start, end, duration)); } @@ -350,6 +382,12 @@ public class SceneBuilder { Optional.of(() -> scene.resolve(link)))); } + public void glueBlockOnto(BlockPos position, Direction fadeInDirection, ElementLink link) { + addInstruction(new DisplayWorldSectionInstruction(15, fadeInDirection, + scene.getSceneBuildingUtil().select.position(position), Optional.of(() -> scene.resolve(link)), + position)); + } + public ElementLink showIndependentSection(Selection selection, Direction fadeInDirection) { DisplayWorldSectionInstruction instruction = new DisplayWorldSectionInstruction(15, fadeInDirection, selection, Optional.empty()); @@ -405,6 +443,11 @@ public class SceneBuilder { .setCenterOfRotation(anchor)); } + public void configureStabilization(ElementLink link, Vec3d anchor) { + addInstruction(scene -> scene.resolve(link) + .stabilizeRotation(anchor)); + } + public void moveSection(ElementLink link, Vec3d offset, int duration) { addInstruction(AnimateWorldSectionInstruction.move(link, offset, duration)); } @@ -504,7 +547,7 @@ public class SceneBuilder { return; behaviour.handleInsertion(stack, insertionSide.getOpposite(), false); }); - flapFunnels(scene.getSceneBuildingUtil().select.position(location.up()), true); + flapFunnel(location.up(), true); } public ElementLink createItemOnBelt(BlockPos beltLocation, Direction insertionSide, @@ -532,9 +575,8 @@ public class SceneBuilder { scene.linkElement(tracker, link); return TransportedResult.doNothing(); }); - }); - flapFunnels(scene.getSceneBuildingUtil().select.position(beltLocation.up()), true); + flapFunnel(beltLocation.up(), true); return link; } @@ -596,8 +638,7 @@ public class SceneBuilder { modifyTileNBT(selection, teType, consumer, false); } - public void modifyTileEntity(BlockPos position, Class teType, - Consumer consumer) { + public void modifyTileEntity(BlockPos position, Class teType, Consumer consumer) { addInstruction(scene -> { TileEntity tileEntity = scene.world.getTileEntity(position); if (teType.isInstance(tileEntity)) @@ -613,11 +654,8 @@ public class SceneBuilder { }, reDrawBlocks)); } - public void flapFunnels(Selection selection, boolean outward) { - addInstruction(new TileEntityDataInstruction(selection, FunnelTileEntity.class, nbt -> { - nbt.putInt("Flap", outward ? -1 : 1); - return nbt; - }, false)); + public void flapFunnel(BlockPos position, boolean outward) { + modifyTileEntity(position, FunnelTileEntity.class, funnel -> funnel.flap(!outward)); } } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/BearingScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/BearingScenes.java index 6358cf7ab..01ac69c20 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/BearingScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/BearingScenes.java @@ -14,7 +14,6 @@ import com.simibubi.create.foundation.utility.Pointing; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; -import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; @@ -22,6 +21,9 @@ public class BearingScenes { public static void windmillsAsSource(SceneBuilder scene, SceneBuildingUtil util) { scene.title("windmill_source", "Generating Rotational Force using Windmill Bearings"); + scene.configureBasePlate(1, 1, 5); + scene.setSceneOffsetY(-1); + scene.world.showSection(util.select.fromTo(1, 0, 1, 5, 0, 5), Direction.UP); scene.world.setBlock(util.grid.at(2, -1, 0), AllBlocks.SAIL.getDefaultState() .with(SailBlock.FACING, Direction.NORTH), false); @@ -102,7 +104,7 @@ public class BearingScenes { scene.overlay.showText(60) .pointAt(util.vector.topOf(windmill)) .placeNearTarget() - .text("Once Activated, the Windmill Bearing will start providing Rotational Force"); + .text("Activated with Right-Click, the Windmill Bearing will start providing Rotational Force"); scene.idle(70); scene.overlay.showText(60) @@ -113,19 +115,14 @@ public class BearingScenes { scene.idle(90); Vec3d surface = util.vector.blockSurface(windmill, Direction.WEST); - AxisAlignedBB point = new AxisAlignedBB(surface, surface); - AxisAlignedBB expanded = point.grow(1 / 16f, 1 / 4f, 1 / 4f); - scene.overlay.showControls(new InputWindowElement(surface, Pointing.DOWN).scroll() .withWrench(), 60); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.WHITE, point, point, 1); - scene.idle(1); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.WHITE, point, expanded, 50); + scene.overlay.showCenteredScrollInput(windmill, Direction.WEST, 50); scene.overlay.showText(60) .pointAt(surface) .placeNearTarget() .text("Use a Wrench to configure its rotation direction"); - scene.idle(35); + scene.idle(36); scene.world.rotateBearing(windmill, -90 - 45, 75); scene.world.rotateSection(structure, 0, 0, -90 - 45, 75); @@ -150,6 +147,8 @@ public class BearingScenes { public static void windmillsAnyStructure(SceneBuilder scene, SceneBuildingUtil util) { scene.title("windmill_structure", "Windmill Contraptions"); + scene.configureBasePlate(1, 1, 5); + scene.setSceneOffsetY(-1); scene.world.showSection(util.select.layer(0), Direction.UP); scene.idle(5); @@ -186,13 +185,380 @@ public class BearingScenes { new InputWindowElement(util.vector.blockSurface(bearingPos, Direction.WEST), Pointing.LEFT).rightClick(), 40); scene.idle(7); + scene.markAsFinished(); scene.world.rotateBearing(bearingPos, -720, 400); scene.world.rotateSection(contraption, 0, -720, 0, 400); scene.world.modifyTileEntity(util.grid.at(2, 1, 5), HarvesterTileEntity.class, hte -> hte.setAnimatedSpeed(-150)); - scene.markAsFinished(); scene.idle(400); scene.world.modifyTileEntity(util.grid.at(2, 1, 5), HarvesterTileEntity.class, hte -> hte.setAnimatedSpeed(0)); } + public static void mechanicalBearing(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_bearing", "Movings Structures using the Mechanical Bearing"); + scene.configureBasePlate(1, 1, 5); + scene.setSceneOffsetY(-1); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layer(1), Direction.DOWN); + scene.idle(10); + scene.world.showSection(util.select.layer(2), Direction.DOWN); + scene.idle(10); + + Selection cog1 = util.select.position(6, 0, 4); + Selection cog2 = util.select.position(5, 1, 4); + Selection cog3 = util.select.position(4, 1, 3); + Selection cog4 = util.select.position(3, 1, 3); + Selection all = cog1.copy() + .add(cog2) + .add(cog3) + .add(cog4); + + BlockPos bearingPos = util.grid.at(3, 2, 3); + scene.overlay.showSelectionWithText(util.select.position(bearingPos.up()), 60) + .colored(PonderPalette.GREEN) + .pointAt(util.vector.blockSurface(bearingPos, Direction.WEST)) + .placeNearTarget() + .text("Mechanical Bearings attach to the block in front of them"); + scene.idle(50); + + ElementLink plank = scene.world.showIndependentSection(util.select.position(bearingPos.up() + .east() + .north()), Direction.DOWN); + scene.world.moveSection(plank, util.vector.of(-1, 0, 1), 0); + scene.idle(20); + + scene.world.setKineticSpeed(cog1, -8); + scene.world.setKineticSpeed(cog2, 8); + scene.world.setKineticSpeed(cog3, -16); + scene.world.setKineticSpeed(cog4, 16); + scene.effects.rotationSpeedIndicator(bearingPos.down()); + scene.world.rotateBearing(bearingPos, 360, 37 * 2); + scene.world.rotateSection(plank, 0, 360, 0, 37 * 2); + + scene.overlay.showText(80) + .pointAt(util.vector.topOf(bearingPos.up())) + .placeNearTarget() + .text("Upon receiving Rotational Force, it will assemble it into a Rotating Contraption"); + scene.idle(37 * 2); + scene.world.setKineticSpeed(all, 0); + scene.idle(20); + + scene.world.hideIndependentSection(plank, Direction.UP); + scene.idle(15); + Selection plank2 = util.select.position(4, 3, 2); + ElementLink contraption = scene.world.showIndependentSection(util.select.layersFrom(3) + .substract(plank2), Direction.DOWN); + scene.idle(10); + scene.world.showSectionAndMerge(plank2, Direction.SOUTH, contraption); + scene.idle(15); + scene.effects.superGlue(util.grid.at(4, 3, 2), Direction.SOUTH, true); + scene.idle(5); + + scene.world.configureCenterOfRotation(contraption, util.vector.topOf(bearingPos)); + scene.world.setKineticSpeed(cog1, -8); + scene.world.setKineticSpeed(cog2, 8); + scene.world.setKineticSpeed(cog3, -16); + scene.world.setKineticSpeed(cog4, 16); + scene.effects.rotationSpeedIndicator(bearingPos.down()); + scene.world.rotateBearing(bearingPos, 360 * 2, 37 * 4); + scene.world.rotateSection(contraption, 0, 360 * 2, 0, 37 * 4); + + scene.overlay.showText(120) + .pointAt(util.vector.topOf(bearingPos.up())) + .placeNearTarget() + .sharedText("movement_anchors"); + + scene.idle(37 * 4); + scene.world.setKineticSpeed(all, 0); + } + + public static void bearingModes(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("bearing_modes", "Movement Modes of the Mechanical Bearing"); + scene.configureBasePlate(1, 1, 6); + scene.setSceneOffsetY(-1); + + Selection sideCog = util.select.position(util.grid.at(7, 0, 3)); + Selection cogColumn = util.select.fromTo(6, 1, 3, 6, 4, 3); + Selection cogAndClutch = util.select.fromTo(5, 3, 1, 5, 4, 2); + BlockPos leverPos = util.grid.at(5, 3, 1); + + scene.world.setKineticSpeed(sideCog, 4); + scene.world.setKineticSpeed(cogColumn, -4); + scene.world.setKineticSpeed(cogAndClutch, 8); + scene.world.toggleRedstonePower(cogAndClutch); + + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(cogColumn, Direction.DOWN); + scene.idle(5); + scene.world.showSection(cogAndClutch, Direction.DOWN); + scene.idle(10); + + BlockPos bearingPos = util.grid.at(5, 2, 2); + scene.world.showSection(util.select.position(bearingPos), Direction.UP); + scene.idle(10); + + ElementLink contraption = + scene.world.showIndependentSection(util.select.fromTo(5, 1, 2, 2, 1, 2), Direction.EAST); + scene.world.configureCenterOfRotation(contraption, util.vector.centerOf(bearingPos)); + scene.idle(20); + + scene.world.toggleRedstonePower(cogAndClutch); + scene.effects.indicateRedstone(leverPos); + scene.world.rotateSection(contraption, 0, 55, 0, 23); + scene.world.rotateBearing(bearingPos, 55, 23); + scene.idle(24); + + scene.world.toggleRedstonePower(cogAndClutch); + scene.effects.indicateRedstone(leverPos); + scene.world.rotateSection(contraption, 0, 35, 0, 0); + scene.world.rotateBearing(bearingPos, 35, 0); + + Vec3d target = util.vector.topOf(bearingPos.down()); + scene.overlay.showLine(PonderPalette.RED, target.add(-2.5, 0, 3.5), target, 50); + scene.overlay.showLine(PonderPalette.GREEN, target.add(0, 0, 4.5), target, 50); + + scene.idle(50); + + scene.overlay.showText(100) + .pointAt(util.vector.blockSurface(bearingPos, Direction.WEST)) + .placeNearTarget() + .colored(PonderPalette.RED) + .text("When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle"); + scene.idle(110); + + scene.overlay.showCenteredScrollInput(bearingPos, Direction.NORTH, 60); + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(bearingPos, Direction.NORTH), Pointing.DOWN).scroll() + .withWrench(), + 60); + scene.idle(10); + scene.overlay.showText(60) + .pointAt(util.vector.blockSurface(bearingPos, Direction.WEST)) + .placeNearTarget() + .sharedText("behaviour_modify_wrench"); + scene.idle(70); + + scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -f); + scene.world.toggleRedstonePower(cogAndClutch); + scene.effects.indicateRedstone(leverPos); + scene.world.rotateSection(contraption, 0, -55, 0, 23); + scene.world.rotateBearing(bearingPos, -55, 23); + scene.idle(24); + + scene.world.toggleRedstonePower(cogAndClutch); + scene.effects.indicateRedstone(leverPos); + scene.idle(40); + + scene.overlay.showText(120) + .colored(PonderPalette.GREEN) + .pointAt(util.vector.blockSurface(util.grid.at(3, 1, 3), Direction.UP)) + .text("It can be configured never to revert to solid blocks, or only near the angle it started at"); + + } + + public static void stabilizedBearings(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("stabilized_bearings", "Stabilized Contraptions"); + scene.configureBasePlate(1, 1, 5); + scene.setSceneOffsetY(-1); + + Selection beltAndBearing = util.select.fromTo(3, 3, 4, 3, 1, 6); + Selection largeCog = util.select.position(2, 0, 6); + BlockPos parentBearingPos = util.grid.at(3, 3, 4); + BlockPos bearingPos = util.grid.at(3, 4, 2); + + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(beltAndBearing, Direction.DOWN); + scene.idle(10); + + ElementLink contraption = + scene.world.showIndependentSection(util.select.fromTo(3, 3, 3, 3, 4, 3), Direction.SOUTH); + scene.world.configureCenterOfRotation(contraption, util.vector.centerOf(parentBearingPos)); + scene.idle(20); + scene.world.glueBlockOnto(bearingPos, Direction.SOUTH, contraption); + + scene.idle(15); + + scene.overlay.showSelectionWithText(util.select.position(bearingPos), 60) + .text("Whenever Mechanical Bearings are themselves part of a moving Structure..") + .placeNearTarget(); + scene.idle(70); + + scene.world.setKineticSpeed(largeCog, -8); + scene.world.setKineticSpeed(beltAndBearing, 16); + scene.world.rotateBearing(parentBearingPos, 360, 74); + scene.world.rotateSection(contraption, 0, 0, 360, 74); + scene.world.rotateBearing(bearingPos, -360, 74); + scene.idle(74); + + scene.world.setKineticSpeed(largeCog, 0); + scene.world.setKineticSpeed(beltAndBearing, 0); + scene.overlay.showText(60) + .text("..they will attempt to keep themselves upright") + .pointAt(util.vector.blockSurface(bearingPos, Direction.NORTH)) + .placeNearTarget(); + scene.idle(70); + + scene.overlay.showSelectionWithText(util.select.position(bearingPos.north()), 60) + .colored(PonderPalette.GREEN) + .text("Once again, the bearing will attach to the block in front of it") + .placeNearTarget(); + scene.idle(70); + + ElementLink subContraption = + scene.world.showIndependentSection(util.select.fromTo(4, 4, 1, 2, 4, 1), Direction.SOUTH); + scene.world.configureCenterOfRotation(subContraption, util.vector.centerOf(parentBearingPos)); + scene.world.configureStabilization(subContraption, util.vector.centerOf(bearingPos)); + scene.idle(20); + + scene.overlay.showText(80) + .text("As a result, the entire sub-Contraption will stay upright"); + + scene.world.setKineticSpeed(largeCog, -8); + scene.world.setKineticSpeed(beltAndBearing, 16); + scene.world.rotateBearing(parentBearingPos, 360 * 2, 74 * 2); + scene.world.rotateSection(contraption, 0, 0, 360 * 2, 74 * 2); + scene.world.rotateBearing(bearingPos, -360 * 2, 74 * 2); + scene.world.rotateSection(subContraption, 0, 0, 360 * 2, 74 * 2); + + scene.markAsFinished(); + scene.idle(74 * 2); + scene.world.setKineticSpeed(largeCog, 0); + scene.world.setKineticSpeed(beltAndBearing, 0); + } + + public static void clockwork(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("clockwork_bearing", "Animating Structures using Clockwork Bearings"); + + Selection kinetics = util.select.fromTo(3, 3, 4, 3, 1, 6); + Selection largeCog = util.select.position(2, 0, 6); + BlockPos bearingPos = util.grid.at(3, 3, 3); + + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(kinetics, Direction.DOWN); + scene.idle(10); + scene.world.showSection(util.select.position(bearingPos), Direction.DOWN); + scene.idle(10); + + scene.overlay.showSelectionWithText(util.select.position(bearingPos.north()), 60) + .colored(PonderPalette.GREEN) + .pointAt(util.vector.blockSurface(bearingPos, Direction.WEST)) + .placeNearTarget() + .text("Clockwork Bearings attach to blocks in front of them"); + scene.idle(50); + + ElementLink plank = + scene.world.showIndependentSection(util.select.position(2, 3, 2), Direction.SOUTH); + scene.world.moveSection(plank, util.vector.of(1, 0, 0), 0); + scene.idle(20); + + scene.world.rotateSection(plank, 0, 0, 60, 25); + scene.world.rotateBearing(bearingPos, 60, 25); + scene.world.setKineticSpeed(kinetics, 8); + scene.world.setKineticSpeed(largeCog, -4); + + scene.idle(25); + scene.overlay.showText(80) + .pointAt(util.vector.blockSurface(bearingPos.north(), Direction.NORTH)) + .placeNearTarget() + .text("Upon receiving Rotational Force, the structure will be rotated according to the hour of the day"); + scene.idle(90); + + scene.overlay.showText(30) + .pointAt(util.vector.blockSurface(bearingPos.north(), Direction.NORTH)) + .placeNearTarget() + .text("3:00"); + scene.world.rotateSection(plank, 0, 0, 30, 12); + scene.world.rotateBearing(bearingPos, 30, 12); + scene.idle(42); + scene.overlay.showText(30) + .pointAt(util.vector.blockSurface(bearingPos.north(), Direction.NORTH)) + .placeNearTarget() + .text("4:00"); + scene.world.rotateSection(plank, 0, 0, 30, 12); + scene.world.rotateBearing(bearingPos, 30, 12); + scene.idle(42); + + InputWindowElement clickTheBearing = new InputWindowElement(util.vector.topOf(bearingPos), Pointing.DOWN); + InputWindowElement clickTheBearingSide = + new InputWindowElement(util.vector.blockSurface(bearingPos, Direction.WEST), Pointing.LEFT); + + scene.overlay.showControls(clickTheBearing.rightClick(), 60); + scene.idle(7); + scene.world.rotateSection(plank, 0, 0, -120, 0); + scene.world.rotateBearing(bearingPos, -120, 0); + scene.overlay.showText(60) + .pointAt(util.vector.blockSurface(bearingPos, Direction.WEST)) + .placeNearTarget() + .text("Right-Click the bearing to start or stop animating the structure"); + scene.idle(70); + + scene.world.hideIndependentSection(plank, Direction.NORTH); + scene.idle(15); + + ElementLink hourHand = + scene.world.showIndependentSection(util.select.fromTo(3, 3, 1, 3, 5, 2), Direction.SOUTH); + scene.world.configureCenterOfRotation(hourHand, util.vector.centerOf(bearingPos)); + scene.idle(15); + scene.overlay.showSelectionWithText(util.select.fromTo(3, 3, 1, 3, 4, 2), 80) + .placeNearTarget() + .sharedText("movement_anchors"); + scene.idle(90); + + scene.overlay.showControls(clickTheBearingSide.rightClick(), 20); + scene.idle(7); + scene.world.rotateSection(hourHand, 0, 0, 120, 50); + scene.world.rotateBearing(bearingPos, 120, 50); + scene.idle(60); + + scene.overlay.showSelectionWithText(util.select.position(bearingPos.north(3)), 80) + .placeNearTarget() + .colored(PonderPalette.BLUE) + .text("In front of the Hour Hand, a second structure can be added"); + scene.idle(90); + scene.overlay.showControls(clickTheBearingSide.rightClick(), 20); + scene.idle(7); + scene.world.rotateSection(hourHand, 0, 0, -120, 0); + scene.world.rotateBearing(bearingPos, -120, 0); + scene.idle(10); + + ElementLink minuteHand = + scene.world.showIndependentSection(util.select.fromTo(3, 3, 0, 3, 6, 0), Direction.SOUTH); + scene.world.configureCenterOfRotation(minuteHand, util.vector.centerOf(bearingPos)); + scene.idle(30); + + scene.overlay.showOutline(PonderPalette.BLUE, minuteHand, util.select.fromTo(3, 3, 0, 3, 6, 0), 85); + scene.overlay.showSelectionWithText(util.select.fromTo(3, 3, 1, 3, 4, 2), 80) + .placeNearTarget() + .colored(PonderPalette.GREEN) + .text("Ensure the two Structures are not attached to each other through super glue or similar"); + scene.idle(90); + + scene.overlay.showControls(clickTheBearingSide.rightClick(), 20); + scene.idle(7); + + scene.world.rotateSection(hourHand, 0, 0, 120, 50); + scene.world.rotateSection(minuteHand, 0, 0, 180, 75); + scene.world.rotateBearing(bearingPos, 120, 50); + scene.idle(90); + scene.world.rotateSection(minuteHand, 0, 0, 6, 3); + + scene.overlay.showText(80) + .placeNearTarget() + .pointAt(util.vector.blockSurface(bearingPos.north(3), Direction.NORTH)) + .colored(PonderPalette.GREEN) + .text("The Second Structure will now rotate as the Minute Hand"); + scene.markAsFinished(); + + for (int i = 0; i < 40; i++) { + scene.idle(23); + scene.world.rotateSection(minuteHand, 0, 0, 6, 3); + if (i == 29) + scene.world.rotateSection(hourHand, 0, 0, 30, 20); + } + } + } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/BeltScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/BeltScenes.java index 547a8c348..ed9604071 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/BeltScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/BeltScenes.java @@ -161,6 +161,7 @@ public class BeltScenes { public static void directions(SceneBuilder scene, SceneBuildingUtil util) { scene.title("belt_directions", "Valid Orientations for Mechanical Belts"); scene.configureBasePlate(0, 0, 5); + scene.setSceneOffsetY(-1); scene.showBasePlate(); scene.idle(5); @@ -305,6 +306,7 @@ public class BeltScenes { public static void transport(SceneBuilder scene, SceneBuildingUtil util) { scene.title("belt_transport", "Using Mechanical Belts for Logistics"); scene.configureBasePlate(0, 0, 5); + scene.setSceneOffsetY(-1); scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -.6f * f); scene.showBasePlate(); scene.idle(5); @@ -379,6 +381,7 @@ public class BeltScenes { public static void beltsCanBeEncased(SceneBuilder scene, SceneBuildingUtil util) { scene.title("belt_casing", "Encasing Belts"); scene.configureBasePlate(0, 0, 5); + scene.setSceneOffsetY(-1); scene.showBasePlate(); scene.idle(5); scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/ChainDriveScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/ChainDriveScenes.java index 841646d57..168e171c2 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/ChainDriveScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/ChainDriveScenes.java @@ -92,7 +92,8 @@ public class ChainDriveScenes { public static void adjustableChainGearshift(SceneBuilder scene, SceneBuildingUtil util) { scene.title("chain_gearshift", "Controlling rotational speed with Chain Gearshifts"); - scene.configureBasePlate(0, 0, 7); + scene.configureBasePlate(0, 0, 5); + scene.setSceneOffsetY(-1); scene.world.showSection(util.select.layer(0), Direction.UP); BlockPos leverPos = util.grid.at(3, 1, 0); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/FunnelScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/FunnelScenes.java index f6fee510c..c8f9c6c44 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/FunnelScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/FunnelScenes.java @@ -52,12 +52,11 @@ public class FunnelScenes { BlockPos entryBeltPos = util.grid.at(3, 1, 2); BlockPos exitBeltPos = util.grid.at(1, 1, 2); ItemStack itemStack = AllBlocks.BRASS_BLOCK.asStack(); - Selection exitFunnel = util.select.position(exitBeltPos.up()); for (int i = 0; i < 8; i++) { scene.idle(8); scene.world.removeItemsFromBelt(exitBeltPos); - scene.world.flapFunnels(exitFunnel, false); + scene.world.flapFunnel(exitBeltPos.up(), false); if (i == 2) scene.rotateCameraY(70); if (i < 6) @@ -94,7 +93,7 @@ public class FunnelScenes { for (int i = 0; i < 3; i++) { scene.idle(8); - scene.world.flapFunnels(outputFunnel, false); + scene.world.flapFunnel(util.grid.at(1, 2, 4), false); scene.world.createItemEntity(sideItemSpawn, util.vector.of(-.05, 0, 0), itemStack); } @@ -198,7 +197,7 @@ public class FunnelScenes { scene.idle(20); - scene.world.flapFunnels(sideFunnelSelection, true); + scene.world.flapFunnel(sideFunnel, true); itemLink = scene.world.createItemEntity(sideCenter.subtract(0, .45, 0), util.vector.of(0, 0, -0.1), itemStack); scene.idle(60); scene.world.hideSection(sideFunnelSelection, Direction.UP); @@ -233,7 +232,7 @@ public class FunnelScenes { scene.idle(35); scene.world.removeItemsFromBelt(beltPos); - scene.world.flapFunnels(beltFunnelSetup, false); + scene.world.flapFunnel(util.grid.at(2, 2, 2), false); if (i == 0) { scene.idle(50); @@ -374,7 +373,7 @@ public class FunnelScenes { scene.idle(10); scene.world.createItemOnBeltLike(andesiteFunnel.down() .north(), Direction.SOUTH, itemStack); - scene.world.flapFunnels(util.select.position(andesiteFunnel), true); + scene.world.flapFunnel(andesiteFunnel, true); scene.idle(60); scene.overlay.showText(60) @@ -384,7 +383,7 @@ public class FunnelScenes { scene.idle(10); scene.world.createItemOnBeltLike(brassFunnel.down() .north(), Direction.SOUTH, ItemHandlerHelper.copyStackWithSize(itemStack, 64)); - scene.world.flapFunnels(util.select.position(brassFunnel), true); + scene.world.flapFunnel(brassFunnel, true); scene.idle(60); AxisAlignedBB filterSlot = new AxisAlignedBB(brassFunnel).grow(-.35, -.35, -.35) @@ -421,7 +420,7 @@ public class FunnelScenes { if (i > 0 && (i < 3 || i % 3 == 0)) { scene.world.removeItemsFromBelt(brassFunnel.down()); - scene.world.flapFunnels(util.select.position(brassFunnel), false); + scene.world.flapFunnel(brassFunnel, false); } scene.world.modifyEntities(ItemEntity.class, e -> { diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/GantryScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/GantryScenes.java index 152d7c781..7ce74ee04 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/GantryScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/GantryScenes.java @@ -241,6 +241,7 @@ public class GantryScenes { public static void subgantry(SceneBuilder scene, SceneBuildingUtil util) { scene.title("gantry_cascaded", "Cascaded Gantries"); scene.configureBasePlate(0, 0, 5); + scene.setSceneOffsetY(-1); scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -2 * f); scene.world.showSection(util.select.layer(0) .add(util.select.column(5, 3)) diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/KineticsScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/KineticsScenes.java index 28ff3e051..03ab44c64 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/KineticsScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/KineticsScenes.java @@ -279,6 +279,8 @@ public class KineticsScenes { public static void gearbox(SceneBuilder scene, SceneBuildingUtil util) { scene.title("gearbox", "Relaying rotational force using Gearboxes"); scene.configureBasePlate(1, 1, 5); + scene.setSceneOffsetY(-1); + scene.world.showSection(util.select.layer(0), Direction.UP); scene.world.showSection(util.select.fromTo(4, 1, 6, 3, 2, 5), Direction.UP); scene.idle(10); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/MovementActorScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/MovementActorScenes.java index 5203f0756..8c262ceca 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/MovementActorScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/MovementActorScenes.java @@ -22,7 +22,9 @@ public class MovementActorScenes { public static void psiTransfer(SceneBuilder scene, SceneBuildingUtil util) { scene.title("portable_storage_interface", "Contraption Storage Exchange"); - scene.configureBasePlate(0, 0, 8); + scene.configureBasePlate(0, 0, 6); + scene.scaleSceneView(0.95f); + scene.setSceneOffsetY(-1); scene.world.showSection(util.select.layer(0), Direction.UP); scene.idle(5); @@ -112,7 +114,7 @@ public class MovementActorScenes { scene.world.modifyEntity(entity2, Entity::remove); scene.overlay - .showControls(new InputWindowElement(util.vector.topOf(6, 3, 2), Pointing.DOWN).withItem(itemStack), 40); + .showControls(new InputWindowElement(util.vector.topOf(5, 3, 2), Pointing.DOWN).withItem(itemStack), 40); scene.idle(30); scene.world.hideSection(util.select.position(hopper), Direction.UP); @@ -148,7 +150,8 @@ public class MovementActorScenes { public static void psiRedstone(SceneBuilder scene, SceneBuildingUtil util) { scene.title("portable_storage_interface_redstone", "Redstone Control"); - scene.configureBasePlate(0, 0, 6); + scene.configureBasePlate(0, 0, 5); + scene.setSceneOffsetY(-1); Class psiClass = PortableItemInterfaceTileEntity.class; Selection psis = util.select.fromTo(1, 1, 3, 1, 3, 3); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PistonScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PistonScenes.java new file mode 100644 index 000000000..28706d1fa --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PistonScenes.java @@ -0,0 +1,279 @@ +package com.simibubi.create.foundation.ponder.content; + +import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonHeadBlock; +import com.simibubi.create.foundation.ponder.ElementLink; +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; +import com.simibubi.create.foundation.ponder.Selection; +import com.simibubi.create.foundation.ponder.elements.InputWindowElement; +import com.simibubi.create.foundation.ponder.elements.ParrotElement; +import com.simibubi.create.foundation.ponder.elements.ParrotElement.FaceCursorPose; +import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; +import com.simibubi.create.foundation.utility.Pointing; + +import net.minecraft.block.Blocks; +import net.minecraft.block.DoublePlantBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.state.properties.DoubleBlockHalf; +import net.minecraft.state.properties.PistonType; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; + +public class PistonScenes { + + public static void movement(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_piston", "Moving Structures using Mechanical Pistons"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0) + .add(util.select.position(0, 1, 2)), Direction.UP); + + Selection kinetics = util.select.fromTo(3, 1, 3, 3, 1, 2); + BlockPos piston = util.grid.at(3, 1, 2); + BlockPos leverPos = util.grid.at(3, 2, 4); + BlockPos shaft = util.grid.at(3, 1, 3); + + scene.idle(5); + scene.world.showSection(util.select.fromTo(3, 1, 3, 3, 2, 5), Direction.DOWN); + scene.idle(10); + scene.world.showSection(util.select.position(piston), Direction.DOWN); + ElementLink contraption = + scene.world.showIndependentSection(util.select.position(3, 1, 1), Direction.DOWN); + scene.world.moveSection(contraption, util.vector.of(0, 0, 1), 0); + scene.idle(20); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .east()), Direction.DOWN, contraption); + scene.idle(5); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .east(2)), Direction.DOWN, contraption); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .west()), Direction.DOWN, contraption); + scene.idle(15); + + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.modifyKineticSpeed(kinetics, f -> -f); + scene.effects.rotationDirectionIndicator(shaft); + scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); + scene.overlay.showText(55) + .pointAt(util.vector.topOf(piston)) + .placeNearTarget() + .text("Mechanical Pistons can move blocks in front of them"); + scene.idle(65); + + scene.overlay.showText(45) + .pointAt(util.vector.blockSurface(shaft, Direction.SOUTH)) + .placeNearTarget() + .text("Speed and direction of movement depend on the Rotational Input"); + scene.world.setBlock(util.grid.at(2, 1, 1), Blocks.AIR.getDefaultState(), false); + scene.world.setBlock(util.grid.at(0, 1, 2), Blocks.OAK_PLANKS.getDefaultState(), false); + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.modifyKineticSpeed(kinetics, f -> -f); + scene.effects.rotationDirectionIndicator(shaft); + scene.world.moveSection(contraption, util.vector.of(2, 0, 0), 40); + scene.idle(60); + + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(piston, Direction.WEST), Pointing.DOWN).rightClick() + .withItem(new ItemStack(Items.SLIME_BALL)), + 30); + scene.idle(7); + scene.world.modifyBlock(piston.north(), s -> s.with(MechanicalPistonHeadBlock.TYPE, PistonType.STICKY), false); + scene.effects.superGlue(piston, Direction.WEST, true); + + scene.idle(33); + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.modifyKineticSpeed(kinetics, f -> -f); + scene.effects.rotationDirectionIndicator(shaft); + scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); + + scene.idle(25); + scene.overlay.showText(60) + .pointAt(util.vector.topOf(piston)) + .placeNearTarget() + .text("Sticky Mechanical Pistons can pull the attached blocks back"); + scene.idle(20); + scene.world.setBlock(util.grid.at(2, 1, 1), Blocks.OAK_PLANKS.getDefaultState(), false); + scene.world.setBlock(util.grid.at(0, 1, 2), Blocks.AIR.getDefaultState(), false); + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.modifyKineticSpeed(kinetics, f -> -f); + scene.effects.rotationDirectionIndicator(shaft); + scene.world.moveSection(contraption, util.vector.of(2, 0, 0), 40); + + scene.idle(50); + scene.world.setBlock(util.grid.at(2, 1, 1), Blocks.AIR.getDefaultState(), false); + ElementLink chassis = + scene.world.showIndependentSection(util.select.fromTo(2, 2, 0, 2, 3, 2), Direction.DOWN); + scene.world.moveSection(chassis, util.vector.of(0, -1, 1), 0); + scene.idle(5); + scene.world.showSectionAndMerge(util.select.position(1, 2, 0), Direction.EAST, chassis); + scene.idle(15); + scene.effects.superGlue(piston.west() + .north(), Direction.WEST, true); + scene.overlay.showText(80) + .pointAt(util.vector.topOf(piston.west())) + .placeNearTarget() + .sharedText("movement_anchors"); + + scene.idle(90); + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.modifyKineticSpeed(kinetics, f -> -f); + scene.effects.rotationDirectionIndicator(shaft); + scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); + scene.world.moveSection(chassis, util.vector.of(-2, 0, 0), 40); + } + + public static void poles(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("piston_pole", "Piston Extension Poles"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -f); + + Selection kinetics = util.select.fromTo(3, 1, 3, 3, 1, 2); + BlockPos piston = util.grid.at(3, 1, 2); + + scene.idle(5); + scene.world.showSection(util.select.fromTo(3, 1, 3, 3, 2, 5), Direction.DOWN); + scene.idle(10); + scene.world.showSection(util.select.position(piston), Direction.DOWN); + ElementLink contraption = + scene.world.showIndependentSection(util.select.position(3, 1, 1), Direction.DOWN); + scene.world.moveSection(contraption, util.vector.of(0, 0, 1), 0); + scene.idle(20); + + BlockPos leverPos = util.grid.at(3, 2, 4); + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.setKineticSpeed(kinetics, 16); + scene.idle(10); + + scene.overlay.showSelectionWithText(util.select.position(piston), 50) + .colored(PonderPalette.RED) + .placeNearTarget() + .text("Without attached Poles, a Mechanical Piston cannot move"); + scene.idle(60); + + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.setKineticSpeed(kinetics, 0); + scene.idle(5); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .east()), Direction.DOWN, contraption); + scene.idle(5); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .east(2)), Direction.DOWN, contraption); + scene.idle(10); + + scene.overlay.showOutline(PonderPalette.RED, new Object(), util.select.fromTo(piston.east(), piston.east(2)), + 100); + scene.overlay.showSelectionWithText(util.select.fromTo(piston.west(), piston.west(2)), 100) + .text("The Length of pole added at its back determines the Extension Range") + .placeNearTarget() + .colored(PonderPalette.GREEN); + scene.idle(110); + + scene.world.showSectionAndMerge(util.select.position(piston.north() + .west()), Direction.EAST, contraption); + scene.idle(10); + ElementLink birb = + scene.special.createBirb(util.vector.topOf(piston.west()), FaceCursorPose::new); + scene.idle(15); + + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.setKineticSpeed(kinetics, 16); + scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); + scene.special.moveParrot(birb, util.vector.of(-2, 0, 0), 40); + + } + + public static void movementModes(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_piston_modes", "Movement Modes of the Mechanical Piston"); + scene.configureBasePlate(0, 0, 5); + Selection rose = util.select.fromTo(0, 2, 2, 0, 1, 2); + scene.world.showSection(util.select.layer(0) + .add(rose), Direction.UP); + + Selection kinetics = util.select.fromTo(3, 1, 3, 3, 1, 2); + BlockPos piston = util.grid.at(3, 1, 2); + BlockPos leverPos = util.grid.at(3, 2, 4); + BlockPos shaft = util.grid.at(3, 1, 3); + + scene.idle(5); + scene.world.showSection(util.select.fromTo(3, 1, 3, 3, 2, 5), Direction.DOWN); + scene.idle(10); + scene.world.showSection(util.select.position(piston), Direction.DOWN); + ElementLink contraption = + scene.world.showIndependentSection(util.select.position(3, 1, 1), Direction.DOWN); + scene.world.moveSection(contraption, util.vector.of(0, 0, 1), 0); + scene.idle(20); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .east()), Direction.DOWN, contraption); + scene.idle(5); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .east(2)), Direction.DOWN, contraption); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .west()), Direction.DOWN, contraption); + scene.idle(5); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .west() + .up()), Direction.DOWN, contraption); + scene.idle(15); + scene.effects.superGlue(piston.west(), Direction.UP, true); + scene.idle(10); + + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.modifyKineticSpeed(kinetics, f -> -f); + scene.effects.rotationDirectionIndicator(shaft); + scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); + scene.idle(40); + + scene.world.destroyBlock(util.grid.at(0, 1, 2)); + scene.world.destroyBlock(util.grid.at(0, 2, 2)); + scene.idle(10); + scene.overlay.showSelectionWithText(rose, 70) + .text("Whenever Pistons stop moving, the moved structure reverts to blocks") + .colored(PonderPalette.RED); + scene.idle(80); + + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.modifyKineticSpeed(kinetics, f -> -f); + scene.effects.rotationDirectionIndicator(shaft); + scene.world.moveSection(contraption, util.vector.of(2, 0, 0), 40); + scene.world.hideSection(rose, Direction.UP); + scene.idle(50); + + scene.world.setBlock(util.grid.at(0, 1, 2), Blocks.ROSE_BUSH.getDefaultState(), false); + scene.world.setBlock(util.grid.at(0, 2, 2), Blocks.ROSE_BUSH.getDefaultState() + .with(DoublePlantBlock.HALF, DoubleBlockHalf.UPPER), false); + scene.world.showIndependentSection(rose, Direction.DOWN); + scene.overlay.showCenteredScrollInput(piston, Direction.UP, 60); + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(piston), Pointing.DOWN).scroll() + .withWrench(), 60); + scene.overlay.showText(70) + .pointAt(util.vector.topOf(piston)) + .placeNearTarget() + .sharedText("behaviour_modify_wrench"); + scene.idle(80); + + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.modifyKineticSpeed(kinetics, f -> -f); + scene.effects.rotationDirectionIndicator(shaft); + scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); + scene.idle(50); + scene.overlay.showText(120) + .colored(PonderPalette.GREEN) + .pointAt(util.vector.blockSurface(util.grid.at(0, 1, 2), Direction.WEST)) + .placeNearTarget() + .text("It can be configured never to revert to solid blocks, or only at the location it started at"); + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java index 63438e8ec..67b6c5e68 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java @@ -77,12 +77,42 @@ public class PonderIndex { .addStoryBoard("funnels/transposer", FunnelScenes::transposer); PonderRegistry.addStoryBoard(AllBlocks.ANDESITE_FUNNEL, "funnels/brass", FunnelScenes::brass); + // Mechanical Piston + PonderRegistry.forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON) + .addStoryBoard("mechanical_piston/anchor", PistonScenes::movement, PonderTag.KINETIC_APPLIANCES, + PonderTag.MOVEMENT_ANCHOR); + PonderRegistry + .forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON, + AllBlocks.PISTON_EXTENSION_POLE) + .addStoryBoard("mechanical_piston/piston_pole", PistonScenes::poles); + PonderRegistry.forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON) + .addStoryBoard("mechanical_piston/modes", PistonScenes::movementModes); + + // Windmill Bearing + PonderRegistry.forComponents(AllBlocks.ROPE_PULLEY) + .addStoryBoard("rope_pulley/anchor", PulleyScenes::movement, PonderTag.KINETIC_APPLIANCES, + PonderTag.MOVEMENT_ANCHOR) + .addStoryBoard("rope_pulley/modes", PulleyScenes::movementModes) + .addStoryBoard("rope_pulley/attachment", PulleyScenes::attachment); + // Windmill Bearing PonderRegistry.forComponents(AllBlocks.WINDMILL_BEARING) .addStoryBoard("windmill_bearing/source", BearingScenes::windmillsAsSource, PonderTag.KINETIC_SOURCES) .addStoryBoard("windmill_bearing/structure", BearingScenes::windmillsAnyStructure, PonderTag.MOVEMENT_ANCHOR); + // Mechanical Bearing + PonderRegistry.forComponents(AllBlocks.MECHANICAL_BEARING) + .addStoryBoard("mechanical_bearing/anchor", BearingScenes::mechanicalBearing, PonderTag.KINETIC_APPLIANCES, + PonderTag.MOVEMENT_ANCHOR) + .addStoryBoard("mechanical_bearing/modes", BearingScenes::bearingModes) + .addStoryBoard("mechanical_bearing/stabilized", BearingScenes::stabilizedBearings, + PonderTag.CONTRAPTION_ACTOR); + + // Clockwork Bearing + PonderRegistry.addStoryBoard(AllBlocks.CLOCKWORK_BEARING, "clockwork_bearing", BearingScenes::clockwork, + PonderTag.KINETIC_APPLIANCES, PonderTag.MOVEMENT_ANCHOR); + // Gantries PonderRegistry.addStoryBoard(AllBlocks.GANTRY_SHAFT, "gantry/intro", GantryScenes::introForShaft, PonderTag.KINETIC_APPLIANCES, PonderTag.MOVEMENT_ANCHOR); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndexScreen.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndexScreen.java index 364ce0797..15f3e70f8 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndexScreen.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndexScreen.java @@ -49,43 +49,39 @@ public class PonderIndexScreen extends AbstractSimiScreen { protected void init() { super.init(); - //populate lists + // populate lists widgets.clear(); chapters.clear(); - //chapters.addAll(PonderRegistry.chapters.getAllChapters()); + // chapters.addAll(PonderRegistry.chapters.getAllChapters()); items.clear(); PonderRegistry.all.keySet() - .stream() - .map(key -> { - Item item = ForgeRegistries.ITEMS.getValue(key); - if (item == null) { - Block b = ForgeRegistries.BLOCKS.getValue(key); - if (b != null) - item = b.asItem(); - } - return item; - }) - .filter(Objects::nonNull) - .filter(PonderIndexScreen::exclusions) - .forEach(items::add); + .stream() + .map(key -> { + Item item = ForgeRegistries.ITEMS.getValue(key); + if (item == null) { + Block b = ForgeRegistries.BLOCKS.getValue(key); + if (b != null) + item = b.asItem(); + } + return item; + }) + .filter(Objects::nonNull) + .filter(PonderIndexScreen::exclusions) + .forEach(items::add); boolean hasChapters = !chapters.isEmpty(); - //setup chapters - LayoutHelper layout = LayoutHelper.centeredHorizontal( - chapters.size(), - MathHelper.clamp((int) Math.ceil(chapters.size() / 4f), 1, 4), - 200, - 38, - 16 - ); + // setup chapters + LayoutHelper layout = LayoutHelper.centeredHorizontal(chapters.size(), + MathHelper.clamp((int) Math.ceil(chapters.size() / 4f), 1, 4), 200, 38, 16); chapterArea = layout.getArea(); int chapterCenterX = (int) (width * chapterXmult); int chapterCenterY = (int) (height * chapterYmult); - //todo at some point pagination or horizontal scrolling may be needed for chapters/items + // todo at some point pagination or horizontal scrolling may be needed for + // chapters/items for (PonderChapter chapter : chapters) { ChapterLabel label = new ChapterLabel(chapter, chapterCenterX + layout.getX(), chapterCenterY + layout.getY(), (mouseX, mouseY) -> { @@ -97,44 +93,40 @@ public class PonderIndexScreen extends AbstractSimiScreen { layout.next(); } - //setup items + // setup items if (!hasChapters) { itemYmult = 0.5; } int maxItemRows = hasChapters ? 4 : 7; - layout = LayoutHelper.centeredHorizontal( - items.size(), - MathHelper.clamp((int) Math.ceil(items.size() / 11f), 1, maxItemRows), - 28, - 28, - 8 - ); + layout = LayoutHelper.centeredHorizontal(items.size(), + MathHelper.clamp((int) Math.ceil(items.size() / 11f), 1, maxItemRows), 28, 28, 8); itemArea = layout.getArea(); int itemCenterX = (int) (width * itemXmult); int itemCenterY = (int) (height * itemYmult); for (Item item : items) { - PonderButton button = new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4, (x, y) -> { - if (!PonderRegistry.all.containsKey(item.getRegistryName())) - return; + PonderButton button = + new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4, (x, y) -> { + if (!PonderRegistry.all.containsKey(item.getRegistryName())) + return; - centerScalingOn(x, y); - ScreenOpener.transitionTo(PonderUI.of(new ItemStack(item))); - }).showing(new ItemStack(item)); + centerScalingOn(x, y); + ScreenOpener.transitionTo(PonderUI.of(new ItemStack(item))); + }).showing(new ItemStack(item)); button.fade(1); widgets.add(button); layout.next(); } - } private static boolean exclusions(Item item) { if (item instanceof BlockItem) { Block block = ((BlockItem) item).getBlock(); - if (block instanceof ValveHandleBlock && !AllBlocks.COPPER_VALVE_HANDLE.is(item)) return false; + if (block instanceof ValveHandleBlock && !AllBlocks.COPPER_VALVE_HANDLE.is(item)) + return false; } return true; @@ -143,6 +135,7 @@ public class PonderIndexScreen extends AbstractSimiScreen { @Override public void tick() { super.tick(); + PonderUI.ponderTicks++; hoveredItem = ItemStack.EMPTY; MainWindow w = minecraft.getWindow(); @@ -224,4 +217,9 @@ public class PonderIndexScreen extends AbstractSimiScreen { public ItemStack getHoveredTooltipItem() { return hoveredItem; } + + @Override + public boolean isPauseScreen() { + return true; + } } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagScreen.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagScreen.java index 8c03321c9..a443af1f2 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagScreen.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagScreen.java @@ -77,13 +77,16 @@ public class PonderTagScreen extends AbstractSimiScreen { int itemCenterY = getItemsY(); for (Item i : items) { + final boolean canClick = PonderRegistry.all.containsKey(i.getRegistryName()); PonderButton button = new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4, (mouseX, mouseY) -> { - if (!PonderRegistry.all.containsKey(i.getRegistryName())) + if (!canClick) return; centerScalingOn(mouseX, mouseY); ScreenOpener.transitionTo(PonderUI.of(new ItemStack(i), tag)); }).showing(new ItemStack(i)); + if (!canClick) + button.noClickEvent(); button.fade(1); widgets.add(button); @@ -92,18 +95,20 @@ public class PonderTagScreen extends AbstractSimiScreen { if (!tag.getMainItem() .isEmpty()) { + final boolean canClick = PonderRegistry.all.containsKey(tag.getMainItem() + .getItem() + .getRegistryName()); PonderButton button = new PonderButton(itemCenterX - layout.getTotalWidth() / 2 - 42, itemCenterY - 10, (mouseX, mouseY) -> { - if (!PonderRegistry.all.containsKey(tag.getMainItem() - .getItem() - .getRegistryName())) + if (!canClick) return; centerScalingOn(mouseX, mouseY); ScreenOpener.transitionTo(PonderUI.of(tag.getMainItem(), tag)); }).showing(tag.getMainItem()); + if (!canClick) + button.noClickEvent(); button.fade(1); -// button.flash(); widgets.add(button); } @@ -133,6 +138,7 @@ public class PonderTagScreen extends AbstractSimiScreen { @Override public void tick() { super.tick(); + PonderUI.ponderTicks++; hoveredItem = ItemStack.EMPTY; MainWindow w = minecraft.getWindow(); @@ -291,5 +297,10 @@ public class PonderTagScreen extends AbstractSimiScreen { return tag == ((PonderTagScreen) other).tag; return super.isEquivalentTo(other); } + + @Override + public boolean isPauseScreen() { + return true; + } } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PulleyScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PulleyScenes.java new file mode 100644 index 000000000..8b11d693e --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PulleyScenes.java @@ -0,0 +1,227 @@ +package com.simibubi.create.foundation.ponder.content; + +import com.simibubi.create.foundation.ponder.ElementLink; +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; +import com.simibubi.create.foundation.ponder.Selection; +import com.simibubi.create.foundation.ponder.elements.InputWindowElement; +import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; +import com.simibubi.create.foundation.utility.Pointing; + +import net.minecraft.block.Blocks; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; + +public class PulleyScenes { + + public static void movement(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("rope_pulley", "Moving Structures using Rope Pulleys"); + scene.configureBasePlate(0, 0, 5); + scene.scaleSceneView(0.95f); + scene.setSceneOffsetY(-1); + + Selection reversable = util.select.fromTo(2, 3, 4, 2, 4, 2); + BlockPos leverPos = util.grid.at(1, 2, 4); + BlockPos pulleyPos = util.grid.at(2, 4, 2); + Selection redstoneStuff = util.select.fromTo(leverPos, leverPos.east()); + + scene.world.showSection(util.select.layer(0), Direction.UP); + ElementLink plank = + scene.world.showIndependentSection(util.select.position(2, 1, 2), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.fromTo(1, 4, 3, 2, 1, 4), Direction.DOWN); + scene.idle(10); + + scene.world.showSection(util.select.position(pulleyPos), Direction.SOUTH); + scene.idle(20); + + scene.world.toggleRedstonePower(redstoneStuff); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reversable, f -> -f); + scene.effects.rotationDirectionIndicator(pulleyPos.south()); + scene.world.movePulley(pulleyPos, 2, 40); + + scene.idle(45); + scene.overlay.showText(60) + .pointAt(util.vector.blockSurface(pulleyPos, Direction.WEST)) + .text("Rope Pulleys can move blocks vertically when given Rotational Force") + .placeNearTarget(); + scene.idle(70); + + scene.world.toggleRedstonePower(redstoneStuff); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reversable, f -> -f); + scene.effects.rotationDirectionIndicator(pulleyPos.south()); + scene.world.movePulley(pulleyPos, -2, 40); + scene.world.moveSection(plank, util.vector.of(0, 2, 0), 40); + scene.idle(60); + + scene.overlay.showText(60) + .pointAt(util.vector.blockSurface(pulleyPos, Direction.SOUTH)) + .text("Direction and Speed of movement depend on the Rotational Input") + .placeNearTarget(); + + scene.world.toggleRedstonePower(redstoneStuff); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reversable, f -> -f); + scene.effects.rotationDirectionIndicator(pulleyPos.south()); + scene.world.movePulley(pulleyPos, 2, 40); + scene.world.moveSection(plank, util.vector.of(0, -2, 0), 40); + scene.idle(50); + + scene.world.hideIndependentSection(plank, Direction.NORTH); + scene.idle(15); + ElementLink chassis = + scene.world.showIndependentSection(util.select.fromTo(2, 1, 1, 0, 2, 1), Direction.SOUTH); + scene.world.moveSection(chassis, util.vector.of(1, 0, 1), 0); + scene.idle(5); + scene.world.showSectionAndMerge(util.select.position(2, 1, 0), Direction.SOUTH, chassis); + scene.idle(15); + scene.effects.superGlue(util.grid.at(3, 1, 1), Direction.SOUTH, true); + scene.overlay.showText(80) + .pointAt(util.vector.blockSurface(util.grid.at(1, 2, 2), Direction.NORTH)) + .placeNearTarget() + .sharedText("movement_anchors"); + scene.idle(90); + + scene.world.toggleRedstonePower(redstoneStuff); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reversable, f -> -f); + scene.effects.rotationDirectionIndicator(pulleyPos.south()); + scene.world.movePulley(pulleyPos, -2, 40); + scene.world.moveSection(chassis, util.vector.of(0, 2, 0), 40); + scene.idle(50); + + scene.world.toggleRedstonePower(redstoneStuff); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reversable, f -> -f); + scene.effects.rotationDirectionIndicator(pulleyPos.south()); + scene.world.movePulley(pulleyPos, 2, 40); + scene.world.moveSection(chassis, util.vector.of(0, -2, 0), 40); + scene.idle(50); + } + + public static void movementModes(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("rope_pulley_modes", "Movement Modes of the Rope Pulley"); + scene.configureBasePlate(0, 0, 5); + scene.scaleSceneView(0.95f); + scene.setSceneOffsetY(-1); + + Selection reversable = util.select.fromTo(2, 3, 4, 2, 4, 2); + BlockPos leverPos = util.grid.at(1, 2, 4); + BlockPos pulleyPos = util.grid.at(2, 4, 2); + Selection redstoneStuff = util.select.fromTo(leverPos, leverPos.east()); + BlockPos flowerPos = util.grid.at(2, 1, 2); + + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.world.showSection(util.select.position(flowerPos), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.fromTo(1, 4, 3, 2, 1, 4), Direction.DOWN); + scene.idle(10); + + scene.world.showSection(util.select.position(pulleyPos), Direction.SOUTH); + ElementLink glass = + scene.world.showIndependentSection(util.select.position(pulleyPos.down()), Direction.UP); + scene.idle(20); + + scene.world.toggleRedstonePower(redstoneStuff); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reversable, f -> -f); + scene.effects.rotationDirectionIndicator(pulleyPos.south()); + scene.world.movePulley(pulleyPos, 2, 40); + scene.world.moveSection(glass, util.vector.of(0, -2, 0), 40); + scene.idle(40); + + scene.world.destroyBlock(flowerPos); + scene.idle(10); + scene.overlay.showSelectionWithText(util.select.position(flowerPos), 70) + .text("Whenever Pulleys stop moving, the moved structure reverts to blocks") + .placeNearTarget() + .colored(PonderPalette.RED); + scene.idle(80); + + scene.world.toggleRedstonePower(redstoneStuff); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reversable, f -> -f); + scene.effects.rotationDirectionIndicator(pulleyPos.south()); + scene.world.movePulley(pulleyPos, -2, 40); + scene.world.moveSection(glass, util.vector.of(0, 2, 0), 40); + scene.world.hideSection(util.select.position(flowerPos), Direction.DOWN); + scene.idle(40); + + scene.world.setBlock(flowerPos, Blocks.BLUE_ORCHID.getDefaultState(), false); + scene.world.showSection(util.select.position(flowerPos), Direction.DOWN); + scene.overlay.showCenteredScrollInput(pulleyPos, Direction.UP, 60); + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(pulleyPos), Pointing.DOWN).scroll() + .withWrench(), 60); + scene.overlay.showText(70) + .pointAt(util.vector.topOf(pulleyPos)) + .placeNearTarget() + .sharedText("behaviour_modify_wrench"); + scene.idle(80); + + scene.world.toggleRedstonePower(redstoneStuff); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reversable, f -> -f); + scene.effects.rotationDirectionIndicator(pulleyPos.south()); + scene.world.movePulley(pulleyPos, 2, 40); + scene.world.moveSection(glass, util.vector.of(0, -2, 0), 40); + scene.idle(50); + scene.overlay.showText(120) + .colored(PonderPalette.GREEN) + .pointAt(util.vector.blockSurface(flowerPos, Direction.WEST)) + .placeNearTarget() + .text("It can be configured never to revert to solid blocks, or only at the location it started at"); + } + + public static void attachment(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("rope_pulley_attachment", "Moving Pulleys as part of a Contraption"); + scene.configureBasePlate(0, 0, 5); + scene.scaleSceneView(0.95f); + scene.setSceneOffsetY(-1); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + + Selection kinetics = util.select.fromTo(4, 3, 2, 4, 1, 5); + Selection largeCog = util.select.position(3, 0, 5); + + scene.world.showSection(kinetics, Direction.DOWN); + ElementLink poles = + scene.world.showIndependentSection(util.select.fromTo(4, 4, 2, 6, 4, 2), Direction.DOWN); + scene.world.moveSection(poles, util.vector.of(0, -1, 0), 0); + scene.idle(10); + + BlockPos pulleyPos = util.grid.at(3, 3, 2); + ElementLink pulley = + scene.world.showIndependentSection(util.select.position(pulleyPos), Direction.EAST); + scene.idle(10); + scene.world.showSectionAndMerge(util.select.fromTo(3, 1, 1, 3, 1, 2) + .add(util.select.position(3, 2, 1)), Direction.SOUTH, pulley); + + scene.idle(10); + scene.overlay.showText(50) + .pointAt(util.vector.blockSurface(pulleyPos, Direction.WEST)) + .placeNearTarget() + .text("Whenever Pulleys are themselves being moved by a Contraption..."); + scene.idle(60); + + scene.world.setKineticSpeed(largeCog, -16); + scene.world.setKineticSpeed(kinetics, 32); + scene.effects.rotationDirectionIndicator(util.grid.at(4, 1, 5)); + scene.world.moveSection(poles, util.vector.of(-2, 0, 0), 40); + scene.world.moveSection(pulley, util.vector.of(-2, 0, 0), 40); + scene.idle(40); + + scene.overlay.showSelectionWithText(util.select.fromTo(1, 1, 1, 1, 1, 2), 50) + .colored(PonderPalette.GREEN) + .placeNearTarget() + .text("...its attached structure will be dragged with it"); + scene.idle(60); + scene.overlay.showText(80) + .colored(PonderPalette.RED) + .pointAt(util.vector.topOf(pulleyPos.west(2))) + .placeNearTarget() + .text("Mind that pulleys are only movable while stopped"); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/SharedText.java b/src/main/java/com/simibubi/create/foundation/ponder/content/SharedText.java index c7e2ed679..73d233ba2 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/SharedText.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/SharedText.java @@ -16,6 +16,7 @@ public class SharedText { add("rpm32", "32 RPM"); add("movement_anchors", "With the help of Chassis or Super Glue, larger structures can be moved."); + add("behaviour_modify_wrench", "This behaviour can be modified using a Wrench"); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/elements/ParrotElement.java b/src/main/java/com/simibubi/create/foundation/ponder/elements/ParrotElement.java index cd7043524..c2ea78695 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/elements/ParrotElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/elements/ParrotElement.java @@ -6,9 +6,9 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.foundation.ponder.PonderScene; +import com.simibubi.create.foundation.ponder.PonderUI; import com.simibubi.create.foundation.ponder.PonderWorld; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.client.MainWindow; @@ -170,7 +170,7 @@ public class ParrotElement extends AnimatedSceneElement { .length(); entity.onGround = false; double phase = Math.min(length * 15, 8); - float f = (float) ((AnimationTickHolder.getTicks() % 100) * phase); + float f = (float) ((PonderUI.ponderTicks % 100) * phase); entity.flapSpeed = MathHelper.sin(f) + 1; if (length == 0) entity.flapSpeed = 0; diff --git a/src/main/java/com/simibubi/create/foundation/ponder/elements/WorldSectionElement.java b/src/main/java/com/simibubi/create/foundation/ponder/elements/WorldSectionElement.java index aa53b9f60..f1e05c489 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/elements/WorldSectionElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/elements/WorldSectionElement.java @@ -64,6 +64,7 @@ public class WorldSectionElement extends AnimatedSceneElement { Vec3d prevAnimatedRotation = Vec3d.ZERO; Vec3d animatedRotation = Vec3d.ZERO; Vec3d centerOfRotation = Vec3d.ZERO; + Vec3d stabilizationAnchor = null; BlockPos selectedBlock; @@ -103,6 +104,10 @@ public class WorldSectionElement extends AnimatedSceneElement { centerOfRotation = center; } + public void stabilizeRotation(Vec3d anchor) { + stabilizationAnchor = anchor; + } + @Override public void reset(PonderScene scene) { super.reset(scene); @@ -194,11 +199,21 @@ public class WorldSectionElement extends AnimatedSceneElement { if (!animatedRotation.equals(Vec3d.ZERO) || !prevAnimatedRotation.equals(Vec3d.ZERO)) { if (centerOfRotation == null) centerOfRotation = section.getCenter(); + double rotX = MathHelper.lerp(pt, prevAnimatedRotation.x, animatedRotation.x); + double rotZ = MathHelper.lerp(pt, prevAnimatedRotation.z, animatedRotation.z); + double rotY = MathHelper.lerp(pt, prevAnimatedRotation.y, animatedRotation.y); in = in.subtract(centerOfRotation); - in = VecHelper.rotate(in, -MathHelper.lerp(pt, prevAnimatedRotation.x, animatedRotation.x), Axis.X); - in = VecHelper.rotate(in, -MathHelper.lerp(pt, prevAnimatedRotation.z, animatedRotation.z), Axis.Z); - in = VecHelper.rotate(in, -MathHelper.lerp(pt, prevAnimatedRotation.y, animatedRotation.y), Axis.Y); + in = VecHelper.rotate(in, -rotX, Axis.X); + in = VecHelper.rotate(in, -rotZ, Axis.Z); + in = VecHelper.rotate(in, -rotY, Axis.Y); in = in.add(centerOfRotation); + if (stabilizationAnchor != null) { + in = in.subtract(stabilizationAnchor); + in = VecHelper.rotate(in, rotX, Axis.X); + in = VecHelper.rotate(in, rotZ, Axis.Z); + in = VecHelper.rotate(in, rotY, Axis.Y); + in = in.add(stabilizationAnchor); + } } return in; } @@ -209,12 +224,23 @@ public class WorldSectionElement extends AnimatedSceneElement { if (!animatedRotation.equals(Vec3d.ZERO) || !prevAnimatedRotation.equals(Vec3d.ZERO)) { if (centerOfRotation == null) centerOfRotation = section.getCenter(); + double rotX = MathHelper.lerp(pt, prevAnimatedRotation.x, animatedRotation.x); + double rotZ = MathHelper.lerp(pt, prevAnimatedRotation.z, animatedRotation.z); + double rotY = MathHelper.lerp(pt, prevAnimatedRotation.y, animatedRotation.y); MatrixStacker.of(ms) .translate(centerOfRotation) - .rotateX(MathHelper.lerp(pt, prevAnimatedRotation.x, animatedRotation.x)) - .rotateZ(MathHelper.lerp(pt, prevAnimatedRotation.z, animatedRotation.z)) - .rotateY(MathHelper.lerp(pt, prevAnimatedRotation.y, animatedRotation.y)) + .rotateX(rotX) + .rotateZ(rotZ) + .rotateY(rotY) .translateBack(centerOfRotation); + if (stabilizationAnchor != null) { + MatrixStacker.of(ms) + .translate(stabilizationAnchor) + .rotateX(-rotX) + .rotateZ(-rotZ) + .rotateY(-rotY) + .translateBack(stabilizationAnchor); + } } } @@ -287,10 +313,9 @@ public class WorldSectionElement extends AnimatedSceneElement { transformMS(ms, pt); RenderSystem.disableTexture(); WorldRenderer.drawBox(ms, buffer.getBuffer(RenderType.getLines()), shape.getBoundingBox() - .offset(selectedBlock), 1, 1, 1, 1); - if (buffer instanceof SuperRenderTypeBuffer) - ((SuperRenderTypeBuffer) buffer).draw(RenderType.getLines()); - RenderSystem.enableTexture(); + .offset(selectedBlock), 1, 1, 1, 0.6f); +// if (buffer instanceof SuperRenderTypeBuffer) +// ((SuperRenderTypeBuffer) buffer).draw(RenderType.getLines()); ms.pop(); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/AnimateTileEntityInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/AnimateTileEntityInstruction.java index 99e1e8f2b..fd788e53d 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/AnimateTileEntityInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/AnimateTileEntityInstruction.java @@ -4,7 +4,7 @@ import java.util.Optional; import java.util.function.BiConsumer; import java.util.function.Function; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingTileEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.bearing.IBearingTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity; import com.simibubi.create.foundation.ponder.PonderScene; import com.simibubi.create.foundation.ponder.PonderWorld; @@ -24,14 +24,14 @@ public class AnimateTileEntityInstruction extends TickingInstruction { public static AnimateTileEntityInstruction bearing(BlockPos location, float totalDelta, int ticks) { return new AnimateTileEntityInstruction(location, totalDelta, ticks, - (w, f) -> castIfPresent(w, location, MechanicalBearingTileEntity.class).ifPresent(bte -> bte.setAngle(f)), - (w) -> castIfPresent(w, location, MechanicalBearingTileEntity.class).map(bte -> bte.getInterpolatedAngle(0)) + (w, f) -> castIfPresent(w, location, IBearingTileEntity.class).ifPresent(bte -> bte.setAngle(f)), + (w) -> castIfPresent(w, location, IBearingTileEntity.class).map(bte -> bte.getInterpolatedAngle(0)) .orElse(0f)); } public static AnimateTileEntityInstruction pulley(BlockPos location, float totalDelta, int ticks) { return new AnimateTileEntityInstruction(location, totalDelta, ticks, - (w, f) -> castIfPresent(w, location, PulleyTileEntity.class).ifPresent(pulley -> pulley.offset = f), + (w, f) -> castIfPresent(w, location, PulleyTileEntity.class).ifPresent(pulley -> pulley.animateOffset(f)), (w) -> castIfPresent(w, location, PulleyTileEntity.class).map(pulley -> pulley.offset) .orElse(0f)); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/DisplayWorldSectionInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/DisplayWorldSectionInstruction.java index e180ac92a..d9f5c70fc 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/DisplayWorldSectionInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/DisplayWorldSectionInstruction.java @@ -3,27 +3,40 @@ package com.simibubi.create.foundation.ponder.instructions; import java.util.Optional; import java.util.function.Supplier; +import javax.annotation.Nullable; + +import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueItem; import com.simibubi.create.foundation.ponder.PonderScene; import com.simibubi.create.foundation.ponder.Selection; import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; public class DisplayWorldSectionInstruction extends FadeIntoSceneInstruction { private Selection initialSelection; private Optional> mergeOnto; + private BlockPos glue; public DisplayWorldSectionInstruction(int fadeInTicks, Direction fadeInFrom, Selection selection, Optional> mergeOnto) { + this(fadeInTicks, fadeInFrom, selection, mergeOnto, null); + } + + public DisplayWorldSectionInstruction(int fadeInTicks, Direction fadeInFrom, Selection selection, + Optional> mergeOnto, @Nullable BlockPos glue) { super(fadeInTicks, fadeInFrom, new WorldSectionElement(selection)); initialSelection = selection; this.mergeOnto = mergeOnto; + this.glue = glue; } @Override protected void firstTick(PonderScene scene) { super.firstTick(scene); + mergeOnto.ifPresent(wse -> element.setAnimatedOffset(wse.get() + .getAnimatedOffset(), true)); element.set(initialSelection); element.setVisible(true); } @@ -34,6 +47,8 @@ public class DisplayWorldSectionInstruction extends FadeIntoSceneInstruction 0) return; mergeOnto.ifPresent(c -> element.mergeOnto(c.get())); + if (glue != null) + SuperGlueItem.spawnParticles(scene.getWorld(), glue, fadeInFrom, true); } @Override diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/FadeIntoSceneInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/FadeIntoSceneInstruction.java index a45b1d967..bad0f79b9 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/FadeIntoSceneInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/FadeIntoSceneInstruction.java @@ -9,7 +9,7 @@ import net.minecraft.util.math.Vec3d; public abstract class FadeIntoSceneInstruction extends TickingInstruction { - private Direction fadeInFrom; + protected Direction fadeInFrom; protected T element; private ElementLink elementLink; diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/HighlightValueBoxInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/HighlightValueBoxInstruction.java new file mode 100644 index 000000000..aee65a54e --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/HighlightValueBoxInstruction.java @@ -0,0 +1,31 @@ +package com.simibubi.create.foundation.ponder.instructions; + +import com.simibubi.create.foundation.ponder.PonderScene; +import com.simibubi.create.foundation.ponder.content.PonderPalette; + +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.Vec3d; + +public class HighlightValueBoxInstruction extends TickingInstruction { + + private Vec3d vec; + private Vec3d expands; + + public HighlightValueBoxInstruction(Vec3d vec, Vec3d expands, int duration) { + super(false, duration); + this.vec = vec; + this.expands = expands; + } + + @Override + public void tick(PonderScene scene) { + super.tick(scene); + AxisAlignedBB point = new AxisAlignedBB(vec, vec); + AxisAlignedBB expanded = point.grow(expands.x, expands.y, expands.z); + scene.getOutliner() + .chaseAABB(vec, remainingTicks == totalTicks ? point : expanded) + .lineWidth(1 / 32f) + .colored(PonderPalette.WHITE.getColor()); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/MarkAsFinishedInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/MarkAsFinishedInstruction.java index a7f2e15b2..ef15e46dd 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/MarkAsFinishedInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/MarkAsFinishedInstruction.java @@ -14,5 +14,10 @@ public class MarkAsFinishedInstruction extends PonderInstruction { public void tick(PonderScene scene) { scene.setFinished(true); } + + @Override + public void onScheduled(PonderScene scene) { + scene.stopCounting(); + } } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java b/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java index c5ff15c2a..defd97deb 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java @@ -7,7 +7,6 @@ import com.simibubi.create.foundation.gui.GuiGameElement; import com.simibubi.create.foundation.gui.IScreenRenderable; import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget; import com.simibubi.create.foundation.ponder.PonderUI; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.LerpedFloat; @@ -26,6 +25,7 @@ public class PonderButton extends AbstractSimiWidget { private float fade; private KeyBinding shortcut; private LerpedFloat flash; + private boolean noClickEvent; public static final int SIZE = 20; @@ -54,6 +54,11 @@ public class PonderButton extends AbstractSimiWidget { return this; } + public PonderButton noClickEvent() { + this.noClickEvent = true; + return this; + } + public PonderButton shortcut(KeyBinding key) { this.shortcut = key; return this; @@ -86,7 +91,7 @@ public class PonderButton extends AbstractSimiWidget { if (fade < .1f) return; - isHovered = mouseX >= x && mouseY >= y && mouseX < x + width && mouseY < y + height && fade > .75f; + isHovered = isMouseOver(mouseX, mouseY) && fade > .75f; RenderSystem.pushMatrix(); RenderSystem.disableDepthTest(); @@ -95,11 +100,13 @@ public class PonderButton extends AbstractSimiWidget { float flashValue = flash.getValue(partialTicks); if (flashValue > .1f) - fade *= 3 * flashValue + Math.sin((AnimationTickHolder.getTicks() + partialTicks) / 6); + fade *= 3 * flashValue + Math.sin((PonderUI.ponderTicks + partialTicks) / 6); int backgroundColor = ColorHelper.applyAlpha(0xdd000000, fade); - int borderColorStart = ColorHelper.applyAlpha(isHovered ? 0x70ffffff : 0x40aa9999, fade); - int borderColorEnd = ColorHelper.applyAlpha(isHovered ? 0x30ffffff : 0x20aa9999, fade); + int borderColorStart = + ColorHelper.applyAlpha(noClickEvent ? 0x70984500 : isHovered ? 0x70ffffff : 0x40aa9999, fade); + int borderColorEnd = + ColorHelper.applyAlpha(noClickEvent ? 0x70692400 : isHovered ? 0x30ffffff : 0x20aa9999, fade); PonderUI.renderBox(x, y, width, height, backgroundColor, borderColorStart, borderColorEnd); RenderSystem.translated(0, 0, 800); @@ -153,4 +160,13 @@ public class PonderButton extends AbstractSimiWidget { public ItemStack getItem() { return item; } + + @Override + public boolean isMouseOver(double x, double y) { + double m = 4; + x = Math.floor(x); + y = Math.floor(y); + return active && visible + && !(x < this.x - m || x > this.x + width + m - 1 || y < this.y - m || y > this.y + height + m - 1); + } } diff --git a/src/main/java/com/simibubi/create/foundation/render/KineticRenderer.java b/src/main/java/com/simibubi/create/foundation/render/KineticRenderer.java index 7446f86ff..d9c8f74d6 100644 --- a/src/main/java/com/simibubi/create/foundation/render/KineticRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/render/KineticRenderer.java @@ -12,7 +12,7 @@ import com.simibubi.create.foundation.render.backend.gl.shader.ShaderCallback; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; -import com.simibubi.create.foundation.render.backend.instancing.impl.TransformedInstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.impl.BasicInstancedModel; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.Matrix4f; import net.minecraft.client.renderer.RenderType; @@ -27,7 +27,7 @@ public class KineticRenderer extends InstancedTileRenderer { @Override public void registerMaterials() { - materials.put(RenderMaterials.MODELS, new RenderMaterial<>(this, AllProgramSpecs.MODEL, TransformedInstancedModel::new)); + materials.put(RenderMaterials.MODELS, new RenderMaterial<>(this, AllProgramSpecs.MODEL, BasicInstancedModel::new)); materials.put(KineticRenderMaterials.BELTS, new RenderMaterial<>(this, AllProgramSpecs.BELT, BeltInstancedModel::new)); materials.put(KineticRenderMaterials.ROTATING, new RenderMaterial<>(this, AllProgramSpecs.ROTATING, RotatingInstancedModel::new)); diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java b/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java index 159122f24..b2a50382f 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java @@ -13,6 +13,8 @@ import com.simibubi.create.foundation.render.backend.gl.GlFog; import com.simibubi.create.foundation.render.backend.gl.GlFogMode; import com.simibubi.create.foundation.render.backend.gl.shader.*; import com.simibubi.create.foundation.render.backend.gl.versioned.GlFeatureCompat; +import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld; +import net.minecraft.world.World; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.lwjgl.opengl.GL; @@ -65,6 +67,10 @@ public class Backend { return (P) programs.get(spec).get(GlFog.getFogMode()); } + public static boolean isFlywheelWorld(World world) { + return world == Minecraft.getInstance().world || (world instanceof IFlywheelWorld && ((IFlywheelWorld) world).supportsFlywheel()); + } + public static boolean available() { return canUseVBOs(); } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/FastRenderDispatcher.java b/src/main/java/com/simibubi/create/foundation/render/backend/FastRenderDispatcher.java index 7038c4a78..6f096d888 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/FastRenderDispatcher.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/FastRenderDispatcher.java @@ -57,7 +57,7 @@ public class FastRenderDispatcher { } public static boolean available(World world) { - return Backend.canUseInstancing() && !(world instanceof SchematicWorld); + return Backend.canUseInstancing() && Backend.isFlywheelWorld(world); } public static int getDebugMode() { diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/RenderMaterials.java b/src/main/java/com/simibubi/create/foundation/render/backend/RenderMaterials.java index 7cc06e520..b1a09fc0a 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/RenderMaterials.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/RenderMaterials.java @@ -1,10 +1,9 @@ package com.simibubi.create.foundation.render.backend; -import com.simibubi.create.content.contraptions.components.actors.ContraptionActorData; import com.simibubi.create.foundation.render.backend.instancing.MaterialType; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.impl.TransformData; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; public class RenderMaterials { - public static final MaterialType> MODELS = new MaterialType<>(); + public static final MaterialType> MODELS = new MaterialType<>(); } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/InstanceVertexAttributes.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/InstanceVertexAttributes.java index cf1702532..dacecf161 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/InstanceVertexAttributes.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/InstanceVertexAttributes.java @@ -4,6 +4,7 @@ public enum InstanceVertexAttributes implements IVertexAttrib { TRANSFORM("aTransform", MatrixAttributes.MAT4), NORMAL_MAT("aNormalMat", MatrixAttributes.MAT3), LIGHT("aLight", CommonAttributes.LIGHT), + COLOR("aColor", CommonAttributes.RGBA), ; private final String name; diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/TransformedInstancedModel.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/BasicInstancedModel.java similarity index 74% rename from src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/TransformedInstancedModel.java rename to src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/BasicInstancedModel.java index 2335a386f..cd67de720 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/TransformedInstancedModel.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/BasicInstancedModel.java @@ -6,16 +6,16 @@ import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import net.minecraft.client.renderer.BufferBuilder; -public class TransformedInstancedModel extends InstancedModel { +public class BasicInstancedModel extends InstancedModel { public static final VertexFormat INSTANCE_FORMAT = VertexFormat.builder().addAttributes(InstanceVertexAttributes.class).build(); - public TransformedInstancedModel(InstancedTileRenderer renderer, BufferBuilder buf) { + public BasicInstancedModel(InstancedTileRenderer renderer, BufferBuilder buf) { super(renderer, buf); } @Override - protected TransformData newInstance() { - return new TransformData(this); + protected ModelData newInstance() { + return new ModelData(this); } @Override diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelData.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelData.java new file mode 100644 index 000000000..350c8e4ad --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelData.java @@ -0,0 +1,100 @@ +package com.simibubi.create.foundation.render.backend.instancing.impl; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.foundation.render.backend.RenderUtil; +import com.simibubi.create.foundation.render.backend.instancing.InstanceData; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import net.minecraft.client.renderer.Matrix3f; +import net.minecraft.client.renderer.Matrix4f; + +import java.nio.ByteBuffer; + +public class ModelData extends InstanceData { + private static final Matrix4f IDENT4 = new Matrix4f(); + private static final Matrix3f IDENT3 = new Matrix3f(); + static { + IDENT4.loadIdentity(); + IDENT3.loadIdentity(); + } + + private Matrix4f modelMat = IDENT4; + private Matrix3f normalMat = IDENT3; + + private byte blockLight; + private byte skyLight; + + private byte r = (byte) 0xFF; + private byte g = (byte) 0xFF; + private byte b = (byte) 0xFF; + private byte a = (byte) 0xFF; + + public ModelData(InstancedModel owner) { + super(owner); + } + + public ModelData setModelMat(Matrix4f modelMat) { + this.modelMat = modelMat; + return this; + } + + public ModelData setNormalMat(Matrix3f normalMat) { + this.normalMat = normalMat; + return this; + } + + public ModelData setTransform(MatrixStack stack) { + this.modelMat = stack.peek().getModel().copy(); + this.normalMat = stack.peek().getNormal().copy(); + return this; + } + + public ModelData setTransformNoCopy(MatrixStack stack) { + this.modelMat = stack.peek().getModel(); + this.normalMat = stack.peek().getNormal(); + return this; + } + + public ModelData setBlockLight(int blockLight) { + this.blockLight = (byte) (blockLight << 4); + return this; + } + + public ModelData setSkyLight(int skyLight) { + this.skyLight = (byte) (skyLight << 4); + return this; + } + + public ModelData setColor(int color) { + byte a = (byte) ((color >> 24) & 0xFF); + byte r = (byte) ((color >> 16) & 0xFF); + byte g = (byte) ((color >> 8) & 0xFF); + byte b = (byte) (color & 0xFF); + return setColor(r, g, b); + } + + public ModelData setColor(int r, int g, int b) { + return setColor((byte) r, (byte) g, (byte) b); + } + + public ModelData setColor(byte r, byte g, byte b) { + this.r = r; + this.g = g; + this.b = b; + return this; + } + + public ModelData setColor(byte r, byte g, byte b, byte a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + return this; + } + + @Override + public void write(ByteBuffer buf) { + RenderUtil.writeMat4(buf, modelMat); + RenderUtil.writeMat3(buf, normalMat); + buf.put(new byte[] { blockLight, skyLight, r, g, b, a }); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/TransformData.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/TransformData.java deleted file mode 100644 index 115463df7..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/TransformData.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.simibubi.create.foundation.render.backend.instancing.impl; - -import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.render.backend.RenderUtil; -import com.simibubi.create.foundation.render.backend.instancing.InstanceData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import net.minecraft.client.renderer.Matrix3f; -import net.minecraft.client.renderer.Matrix4f; - -import java.nio.ByteBuffer; - -public class TransformData extends InstanceData { - - private Matrix4f modelMat; - private Matrix3f normalMat; - - private byte blockLight; - private byte skyLight; - - public TransformData(InstancedModel owner) { - super(owner); - } - - public TransformData setModelMat(Matrix4f modelMat) { - this.modelMat = modelMat; - return this; - } - - public TransformData setNormalMat(Matrix3f normalMat) { - this.normalMat = normalMat; - return this; - } - - public TransformData setTransform(MatrixStack stack) { - this.modelMat = stack.peek().getModel(); - this.normalMat = stack.peek().getNormal(); - return this; - } - - public TransformData setBlockLight(byte blockLight) { - this.blockLight = blockLight; - return this; - } - - public TransformData setSkyLight(byte skyLight) { - this.skyLight = skyLight; - return this; - } - - @Override - public void write(ByteBuffer buf) { - RenderUtil.writeMat4(buf, modelMat); - RenderUtil.writeMat3(buf, normalMat); - buf.put(new byte[] { blockLight, skyLight }); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/light/GridAlignedBB.java b/src/main/java/com/simibubi/create/foundation/render/backend/light/GridAlignedBB.java index f711ab41f..5ee051229 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/light/GridAlignedBB.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/light/GridAlignedBB.java @@ -269,6 +269,10 @@ public class GridAlignedBB { } } + public AxisAlignedBB toAABB() { + return toAABB(this); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/com/simibubi/create/foundation/utility/AnimationTickHolder.java b/src/main/java/com/simibubi/create/foundation/utility/AnimationTickHolder.java index b86ac025a..1da015fd6 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/AnimationTickHolder.java +++ b/src/main/java/com/simibubi/create/foundation/utility/AnimationTickHolder.java @@ -1,6 +1,10 @@ package com.simibubi.create.foundation.utility; +import com.simibubi.create.foundation.ponder.PonderUI; +import com.simibubi.create.foundation.ponder.PonderWorld; + import net.minecraft.client.Minecraft; +import net.minecraft.world.IWorld; public class AnimationTickHolder { @@ -15,6 +19,10 @@ public class AnimationTickHolder { ticks = (ticks + 1) % 1_728_000; // wrap around every 24 hours so we maintain enough floating point precision } } + + public static int getTicks() { + return ticks; + } public static float getRenderTime() { return getTicks() + getPartialTicks(); @@ -24,8 +32,16 @@ public class AnimationTickHolder { Minecraft mc = Minecraft.getInstance(); return (mc.isGamePaused() ? mc.renderPartialTicksPaused : mc.getRenderPartialTicks()); } - - public static int getTicks() { - return ticks; + + public static int getTicks(IWorld world) { + return world instanceof PonderWorld ? PonderUI.ponderTicks : getTicks(); + } + + public static float getRenderTime(IWorld world) { + return getTicks(world) + getPartialTicks(world); + } + + public static float getPartialTicks(IWorld world) { + return world instanceof PonderWorld ? PonderUI.getPartialTicks() : getPartialTicks(); } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/Coordinate.java b/src/main/java/com/simibubi/create/foundation/utility/Coordinate.java new file mode 100644 index 000000000..adb419c3e --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/Coordinate.java @@ -0,0 +1,8 @@ +package com.simibubi.create.foundation.utility; + +import net.minecraft.util.math.BlockPos; + +@FunctionalInterface +public interface Coordinate { + float get(BlockPos from); +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/MatrixStacker.java b/src/main/java/com/simibubi/create/foundation/utility/MatrixStacker.java index c56938d49..0323a1ebb 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/MatrixStacker.java +++ b/src/main/java/com/simibubi/create/foundation/utility/MatrixStacker.java @@ -4,6 +4,7 @@ import com.mojang.blaze3d.matrix.MatrixStack; import net.minecraft.client.renderer.Quaternion; import net.minecraft.client.renderer.Vector3f; +import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; @@ -23,6 +24,14 @@ public class MatrixStacker { return instance; } + public MatrixStacker rotate(Direction axis, float radians) { + if (radians == 0) + return this; + ms.multiply(axis.getUnitVector() + .getRadialQuaternion(radians)); + return this; + } + public MatrixStacker rotate(double angle, Axis axis) { Vector3f vec = axis == Axis.X ? Vector3f.POSITIVE_X : axis == Axis.Y ? Vector3f.POSITIVE_Y : Vector3f.POSITIVE_Z; @@ -75,7 +84,7 @@ public class MatrixStacker { } public MatrixStacker nudge(int id) { - long randomBits = (long) id * 493286711L; + long randomBits = (long) id * 31L * 493286711L; randomBits = randomBits * randomBits * 4392167121L + randomBits * 98761L; float xNudge = (((float) (randomBits >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; float yNudge = (((float) (randomBits >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; @@ -84,7 +93,7 @@ public class MatrixStacker { return this; } - private MatrixStacker multiply(Vector3f axis, double angle) { + public MatrixStacker multiply(Vector3f axis, double angle) { if (angle == 0) return this; ms.multiply(axis.getDegreesQuaternion((float) angle)); diff --git a/src/main/resources/assets/create/shader/model.vert b/src/main/resources/assets/create/shader/model.vert index 916cc7bcb..54bf4ba4b 100644 --- a/src/main/resources/assets/create/shader/model.vert +++ b/src/main/resources/assets/create/shader/model.vert @@ -7,6 +7,7 @@ attribute vec2 aTexCoords; attribute mat4 aTransform; attribute mat3 aNormalMat; attribute vec2 aLight; +attribute vec4 aColor; varying vec2 TexCoords; varying vec4 Color; @@ -72,5 +73,5 @@ void main() { Light = aLight; gl_Position = uViewProjection * worldPos; - Color = vec4(1.); + Color = aColor; } \ No newline at end of file diff --git a/src/main/resources/assets/create/textures/gui/icons.png b/src/main/resources/assets/create/textures/gui/icons.png index 000090faf..c9d661aee 100644 Binary files a/src/main/resources/assets/create/textures/gui/icons.png and b/src/main/resources/assets/create/textures/gui/icons.png differ diff --git a/src/main/resources/ponder/clockwork_bearing.nbt b/src/main/resources/ponder/clockwork_bearing.nbt new file mode 100644 index 000000000..43b4c4f93 Binary files /dev/null and b/src/main/resources/ponder/clockwork_bearing.nbt differ diff --git a/src/main/resources/ponder/mechanical_bearing/anchor.nbt b/src/main/resources/ponder/mechanical_bearing/anchor.nbt new file mode 100644 index 000000000..3ae522be0 Binary files /dev/null and b/src/main/resources/ponder/mechanical_bearing/anchor.nbt differ diff --git a/src/main/resources/ponder/mechanical_bearing/modes.nbt b/src/main/resources/ponder/mechanical_bearing/modes.nbt new file mode 100644 index 000000000..a3e80f13f Binary files /dev/null and b/src/main/resources/ponder/mechanical_bearing/modes.nbt differ diff --git a/src/main/resources/ponder/mechanical_bearing/stabilized.nbt b/src/main/resources/ponder/mechanical_bearing/stabilized.nbt new file mode 100644 index 000000000..59ac0501c Binary files /dev/null and b/src/main/resources/ponder/mechanical_bearing/stabilized.nbt differ diff --git a/src/main/resources/ponder/mechanical_piston/anchor.nbt b/src/main/resources/ponder/mechanical_piston/anchor.nbt new file mode 100644 index 000000000..7bbee5cc9 Binary files /dev/null and b/src/main/resources/ponder/mechanical_piston/anchor.nbt differ diff --git a/src/main/resources/ponder/mechanical_piston/modes.nbt b/src/main/resources/ponder/mechanical_piston/modes.nbt new file mode 100644 index 000000000..f9755f1ed Binary files /dev/null and b/src/main/resources/ponder/mechanical_piston/modes.nbt differ diff --git a/src/main/resources/ponder/mechanical_piston/piston_pole.nbt b/src/main/resources/ponder/mechanical_piston/piston_pole.nbt new file mode 100644 index 000000000..710f5930a Binary files /dev/null and b/src/main/resources/ponder/mechanical_piston/piston_pole.nbt differ diff --git a/src/main/resources/ponder/rope_pulley/anchor.nbt b/src/main/resources/ponder/rope_pulley/anchor.nbt new file mode 100644 index 000000000..2aa175277 Binary files /dev/null and b/src/main/resources/ponder/rope_pulley/anchor.nbt differ diff --git a/src/main/resources/ponder/rope_pulley/attachment.nbt b/src/main/resources/ponder/rope_pulley/attachment.nbt new file mode 100644 index 000000000..e61952ab2 Binary files /dev/null and b/src/main/resources/ponder/rope_pulley/attachment.nbt differ diff --git a/src/main/resources/ponder/rope_pulley/modes.nbt b/src/main/resources/ponder/rope_pulley/modes.nbt new file mode 100644 index 000000000..6da97dd80 Binary files /dev/null and b/src/main/resources/ponder/rope_pulley/modes.nbt differ