mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-29 08:27:03 +01:00
Keep everything up to date
This commit is contained in:
commit
9bc25db615
25 changed files with 308 additions and 132 deletions
|
@ -17,11 +17,13 @@ import net.minecraft.util.Direction;
|
||||||
|
|
||||||
public class HandCrankInstance extends SingleRotatingInstance implements IDynamicInstance {
|
public class HandCrankInstance extends SingleRotatingInstance implements IDynamicInstance {
|
||||||
|
|
||||||
|
private final HandCrankTileEntity tile;
|
||||||
private InstanceKey<ModelData> crank;
|
private InstanceKey<ModelData> crank;
|
||||||
private Direction facing;
|
private Direction facing;
|
||||||
|
|
||||||
public HandCrankInstance(InstancedTileRenderer<?> modelManager, KineticTileEntity tile) {
|
public HandCrankInstance(InstancedTileRenderer<?> modelManager, HandCrankTileEntity tile) {
|
||||||
super(modelManager, tile);
|
super(modelManager, tile);
|
||||||
|
this.tile = tile;
|
||||||
|
|
||||||
Block block = blockState.getBlock();
|
Block block = blockState.getBlock();
|
||||||
AllBlockPartials renderedHandle = null;
|
AllBlockPartials renderedHandle = null;
|
||||||
|
@ -33,16 +35,20 @@ public class HandCrankInstance extends SingleRotatingInstance implements IDynami
|
||||||
facing = blockState.get(BlockStateProperties.FACING);
|
facing = blockState.get(BlockStateProperties.FACING);
|
||||||
InstancedModel<ModelData> model = renderedHandle.renderOnDirectionalSouthModel(modelManager, blockState, facing.getOpposite());
|
InstancedModel<ModelData> model = renderedHandle.renderOnDirectionalSouthModel(modelManager, blockState, facing.getOpposite());
|
||||||
crank = model.createInstance();
|
crank = model.createInstance();
|
||||||
|
|
||||||
|
rotateCrank();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beginFrame() {
|
public void beginFrame() {
|
||||||
if (crank == null) return;
|
if (crank == null) return;
|
||||||
|
|
||||||
HandCrankTileEntity crankTile = (HandCrankTileEntity) tile;
|
rotateCrank();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rotateCrank() {
|
||||||
Direction.Axis axis = facing.getAxis();
|
Direction.Axis axis = facing.getAxis();
|
||||||
float angle = (crankTile.independentAngle + AnimationTickHolder.getPartialTicks() * crankTile.chasingVelocity) / 360;
|
float angle = (tile.independentAngle + AnimationTickHolder.getPartialTicks() * tile.chasingVelocity) / 360;
|
||||||
|
|
||||||
MatrixStack ms = new MatrixStack();
|
MatrixStack ms = new MatrixStack();
|
||||||
MatrixStacker.of(ms)
|
MatrixStacker.of(ms)
|
||||||
|
|
|
@ -54,6 +54,8 @@ public class DeployerInstance extends ShaftInstance implements IDynamicInstance,
|
||||||
relight(pos, pole.getInstance());
|
relight(pos, pole.getInstance());
|
||||||
|
|
||||||
updateRotation(pole, hand, yRot, zRot, zRotPole);
|
updateRotation(pole, hand, yRot, zRot, zRotPole);
|
||||||
|
|
||||||
|
beginFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -36,11 +36,8 @@ public class FlyWheelInstance extends KineticTileInstance<FlywheelTileEntity> im
|
||||||
protected InstanceKey<ModelData> upperSliding;
|
protected InstanceKey<ModelData> upperSliding;
|
||||||
protected InstanceKey<ModelData> lowerSliding;
|
protected InstanceKey<ModelData> lowerSliding;
|
||||||
|
|
||||||
|
|
||||||
protected float lastAngle = Float.NaN;
|
protected float lastAngle = Float.NaN;
|
||||||
|
|
||||||
protected boolean firstFrame = true;
|
|
||||||
|
|
||||||
public FlyWheelInstance(InstancedTileRenderer<?> modelManager, FlywheelTileEntity tile) {
|
public FlyWheelInstance(InstancedTileRenderer<?> modelManager, FlywheelTileEntity tile) {
|
||||||
super(modelManager, tile);
|
super(modelManager, tile);
|
||||||
|
|
||||||
|
@ -69,6 +66,8 @@ public class FlyWheelInstance extends KineticTileInstance<FlywheelTileEntity> im
|
||||||
} else {
|
} else {
|
||||||
connectors = Collections.emptyList();
|
connectors = Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
animate(tile.angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -79,8 +78,14 @@ public class FlyWheelInstance extends KineticTileInstance<FlywheelTileEntity> im
|
||||||
float speed = tile.visualSpeed.get(partialTicks) * 3 / 10f;
|
float speed = tile.visualSpeed.get(partialTicks) * 3 / 10f;
|
||||||
float angle = tile.angle + speed * partialTicks;
|
float angle = tile.angle + speed * partialTicks;
|
||||||
|
|
||||||
if (!firstFrame && Math.abs(angle - lastAngle) < 0.001) return;
|
if (Math.abs(angle - lastAngle) < 0.001) return;
|
||||||
|
|
||||||
|
animate(angle);
|
||||||
|
|
||||||
|
lastAngle = angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void animate(float angle) {
|
||||||
MatrixStack ms = new MatrixStack();
|
MatrixStack ms = new MatrixStack();
|
||||||
MatrixStacker msr = MatrixStacker.of(ms);
|
MatrixStacker msr = MatrixStacker.of(ms);
|
||||||
|
|
||||||
|
@ -120,9 +125,6 @@ public class FlyWheelInstance extends KineticTileInstance<FlywheelTileEntity> im
|
||||||
.unCentre();
|
.unCentre();
|
||||||
|
|
||||||
wheel.getInstance().setTransform(ms);
|
wheel.getInstance().setTransform(ms);
|
||||||
|
|
||||||
lastAngle = angle;
|
|
||||||
firstFrame = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -14,25 +14,25 @@ import com.simibubi.create.foundation.utility.MatrixStacker;
|
||||||
public class PressInstance extends ShaftInstance implements IDynamicInstance {
|
public class PressInstance extends ShaftInstance implements IDynamicInstance {
|
||||||
|
|
||||||
private final InstanceKey<ModelData> pressHead;
|
private final InstanceKey<ModelData> pressHead;
|
||||||
|
private final MechanicalPressTileEntity press;
|
||||||
|
|
||||||
public PressInstance(InstancedTileRenderer<?> dispatcher, KineticTileEntity tile) {
|
public PressInstance(InstancedTileRenderer<?> dispatcher, MechanicalPressTileEntity tile) {
|
||||||
super(dispatcher, tile);
|
super(dispatcher, tile);
|
||||||
|
press = tile;
|
||||||
|
|
||||||
pressHead = AllBlockPartials.MECHANICAL_PRESS_HEAD.renderOnHorizontalModel(dispatcher, blockState).createInstance();
|
pressHead = AllBlockPartials.MECHANICAL_PRESS_HEAD.renderOnHorizontalModel(dispatcher, blockState).createInstance();
|
||||||
|
transformModels();
|
||||||
transformModels((MechanicalPressTileEntity) tile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beginFrame() {
|
public void beginFrame() {
|
||||||
MechanicalPressTileEntity press = (MechanicalPressTileEntity) tile;
|
|
||||||
if (!press.running)
|
if (!press.running)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
transformModels(press);
|
transformModels();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void transformModels(MechanicalPressTileEntity press) {
|
private void transformModels() {
|
||||||
float renderedHeadOffset = getRenderedHeadOffset(press);
|
float renderedHeadOffset = getRenderedHeadOffset(press);
|
||||||
|
|
||||||
MatrixStack ms = new MatrixStack();
|
MatrixStack ms = new MatrixStack();
|
||||||
|
|
|
@ -31,6 +31,8 @@ public class StickerInstance extends TileEntityInstance<StickerTileEntity> imple
|
||||||
fakeWorld = tile.getWorld() != Minecraft.getInstance().world;
|
fakeWorld = tile.getWorld() != Minecraft.getInstance().world;
|
||||||
facing = blockState.get(StickerBlock.FACING);
|
facing = blockState.get(StickerBlock.FACING);
|
||||||
offset = blockState.get(StickerBlock.EXTENDED) ? 1 : 0;
|
offset = blockState.get(StickerBlock.EXTENDED) ? 1 : 0;
|
||||||
|
|
||||||
|
animateHead(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -43,6 +45,12 @@ public class StickerInstance extends TileEntityInstance<StickerTileEntity> imple
|
||||||
if (MathHelper.epsilonEquals(offset, lastOffset))
|
if (MathHelper.epsilonEquals(offset, lastOffset))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
animateHead(offset);
|
||||||
|
|
||||||
|
lastOffset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void animateHead(float offset) {
|
||||||
MatrixStack stack = new MatrixStack();
|
MatrixStack stack = new MatrixStack();
|
||||||
MatrixStacker.of(stack)
|
MatrixStacker.of(stack)
|
||||||
.translate(getInstancePosition())
|
.translate(getInstancePosition())
|
||||||
|
@ -55,8 +63,6 @@ public class StickerInstance extends TileEntityInstance<StickerTileEntity> imple
|
||||||
|
|
||||||
head.getInstance()
|
head.getInstance()
|
||||||
.setTransform(stack);
|
.setTransform(stack);
|
||||||
|
|
||||||
lastOffset = offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,6 +15,7 @@ import com.simibubi.create.foundation.utility.MatrixStacker;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.vector.Vector3f;
|
import net.minecraft.util.math.vector.Vector3f;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
public class GantryCarriageInstance extends ShaftInstance implements IDynamicInstance {
|
public class GantryCarriageInstance extends ShaftInstance implements IDynamicInstance {
|
||||||
|
|
||||||
|
@ -23,8 +24,11 @@ public class GantryCarriageInstance extends ShaftInstance implements IDynamicIns
|
||||||
final Direction facing;
|
final Direction facing;
|
||||||
final Boolean alongFirst;
|
final Boolean alongFirst;
|
||||||
final Direction.Axis rotationAxis;
|
final Direction.Axis rotationAxis;
|
||||||
|
final float rotationMult;
|
||||||
final BlockPos visualPos;
|
final BlockPos visualPos;
|
||||||
|
|
||||||
|
private float lastAngle = Float.NaN;
|
||||||
|
|
||||||
public GantryCarriageInstance(InstancedTileRenderer<?> dispatcher, KineticTileEntity tile) {
|
public GantryCarriageInstance(InstancedTileRenderer<?> dispatcher, KineticTileEntity tile) {
|
||||||
super(dispatcher, tile);
|
super(dispatcher, tile);
|
||||||
|
|
||||||
|
@ -36,27 +40,29 @@ public class GantryCarriageInstance extends ShaftInstance implements IDynamicIns
|
||||||
alongFirst = blockState.get(GantryCarriageBlock.AXIS_ALONG_FIRST_COORDINATE);
|
alongFirst = blockState.get(GantryCarriageBlock.AXIS_ALONG_FIRST_COORDINATE);
|
||||||
rotationAxis = KineticTileEntityRenderer.getRotationAxisOf(tile);
|
rotationAxis = KineticTileEntityRenderer.getRotationAxisOf(tile);
|
||||||
|
|
||||||
|
rotationMult = getRotationMultiplier(getGantryAxis(), facing);
|
||||||
|
|
||||||
visualPos = facing.getAxisDirection() == Direction.AxisDirection.POSITIVE ? tile.getPos()
|
visualPos = facing.getAxisDirection() == Direction.AxisDirection.POSITIVE ? tile.getPos()
|
||||||
: tile.getPos()
|
: tile.getPos()
|
||||||
.offset(facing.getOpposite());
|
.offset(facing.getOpposite());
|
||||||
|
|
||||||
|
animateCogs(getCogAngle());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beginFrame() {
|
public void beginFrame() {
|
||||||
float angleForTe = GantryCarriageRenderer.getAngleForTe(tile, visualPos, rotationAxis);
|
float cogAngle = getCogAngle();
|
||||||
|
|
||||||
Direction.Axis gantryAxis = Direction.Axis.X;
|
if (MathHelper.epsilonEquals(cogAngle, lastAngle)) return;
|
||||||
for (Direction.Axis axis : Iterate.axes)
|
|
||||||
if (axis != rotationAxis && axis != facing.getAxis())
|
|
||||||
gantryAxis = axis;
|
|
||||||
|
|
||||||
if (gantryAxis == Direction.Axis.Z)
|
animateCogs(cogAngle);
|
||||||
if (facing == Direction.DOWN)
|
}
|
||||||
angleForTe *= -1;
|
|
||||||
if (gantryAxis == Direction.Axis.Y)
|
|
||||||
if (facing == Direction.NORTH || facing == Direction.EAST)
|
|
||||||
angleForTe *= -1;
|
|
||||||
|
|
||||||
|
private float getCogAngle() {
|
||||||
|
return GantryCarriageRenderer.getAngleForTe(tile, visualPos, rotationAxis) * rotationMult;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void animateCogs(float cogAngle) {
|
||||||
MatrixStack ms = new MatrixStack();
|
MatrixStack ms = new MatrixStack();
|
||||||
MatrixStacker.of(ms)
|
MatrixStacker.of(ms)
|
||||||
.translate(getInstancePosition())
|
.translate(getInstancePosition())
|
||||||
|
@ -65,13 +71,33 @@ public class GantryCarriageInstance extends ShaftInstance implements IDynamicIns
|
||||||
.rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90)
|
.rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90)
|
||||||
.rotateY(alongFirst ^ facing.getAxis() == Direction.Axis.Z ? 90 : 0)
|
.rotateY(alongFirst ^ facing.getAxis() == Direction.Axis.Z ? 90 : 0)
|
||||||
.translate(0, -9 / 16f, 0)
|
.translate(0, -9 / 16f, 0)
|
||||||
.multiply(Vector3f.POSITIVE_X.getRadialQuaternion(-angleForTe))
|
.multiply(Vector3f.POSITIVE_X.getRadialQuaternion(-cogAngle))
|
||||||
.translate(0, 9 / 16f, 0)
|
.translate(0, 9 / 16f, 0)
|
||||||
.unCentre();
|
.unCentre();
|
||||||
|
|
||||||
gantryCogs.getInstance().setTransform(ms);
|
gantryCogs.getInstance().setTransform(ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static float getRotationMultiplier(Direction.Axis gantryAxis, Direction facing) {
|
||||||
|
float multiplier = 1;
|
||||||
|
if (gantryAxis == Direction.Axis.Z)
|
||||||
|
if (facing == Direction.DOWN)
|
||||||
|
multiplier *= -1;
|
||||||
|
if (gantryAxis == Direction.Axis.Y)
|
||||||
|
if (facing == Direction.NORTH || facing == Direction.EAST)
|
||||||
|
multiplier *= -1;
|
||||||
|
|
||||||
|
return multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Direction.Axis getGantryAxis() {
|
||||||
|
Direction.Axis gantryAxis = Direction.Axis.X;
|
||||||
|
for (Direction.Axis axis : Iterate.axes)
|
||||||
|
if (axis != rotationAxis && axis != facing.getAxis())
|
||||||
|
gantryAxis = axis;
|
||||||
|
return gantryAxis;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLight() {
|
public void updateLight() {
|
||||||
relight(pos, gantryCogs.getInstance(), rotatingModel.getInstance());
|
relight(pos, gantryCogs.getInstance(), rotatingModel.getInstance());
|
||||||
|
|
|
@ -17,6 +17,8 @@ import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.render.backend.instancing.impl.OrientedModel;
|
import com.simibubi.create.foundation.render.backend.instancing.impl.OrientedModel;
|
||||||
import com.simibubi.create.foundation.render.backend.instancing.impl.TransformedModel;
|
import com.simibubi.create.foundation.render.backend.instancing.impl.TransformedModel;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.gen.feature.template.Template;
|
import net.minecraft.world.gen.feature.template.Template;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
@ -46,14 +48,13 @@ public class ContraptionKineticRenderer extends InstancedTileRenderer<Contraptio
|
||||||
materials.put(KineticRenderMaterials.ACTORS, new RenderMaterial<>(this, AllProgramSpecs.C_ACTOR, ActorModel::new));
|
materials.put(KineticRenderMaterials.ACTORS, new RenderMaterial<>(this, AllProgramSpecs.C_ACTOR, ActorModel::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tick() {
|
public void tick() {
|
||||||
actors.forEach(ActorInstance::tick);
|
actors.forEach(ActorInstance::tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beginFrame(double cameraX, double cameraY, double cameraZ) {
|
public void beginFrame(ActiveRenderInfo info, double cameraX, double cameraY, double cameraZ) {
|
||||||
super.beginFrame(cameraX, cameraY, cameraZ);
|
super.beginFrame(info, cameraX, cameraY, cameraZ);
|
||||||
|
|
||||||
actors.forEach(ActorInstance::beginFrame);
|
actors.forEach(ActorInstance::beginFrame);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ import net.minecraft.client.renderer.LightTexture;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.client.renderer.RenderTypeLookup;
|
import net.minecraft.client.renderer.RenderTypeLookup;
|
||||||
import net.minecraft.client.renderer.WorldRenderer;
|
import net.minecraft.client.renderer.WorldRenderer;
|
||||||
|
import net.minecraft.client.renderer.*;
|
||||||
import net.minecraft.client.renderer.model.IBakedModel;
|
import net.minecraft.client.renderer.model.IBakedModel;
|
||||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||||
|
@ -93,9 +94,9 @@ public class ContraptionRenderDispatcher {
|
||||||
return contraption;
|
return contraption;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void beginFrame(double camX, double camY, double camZ) {
|
public static void beginFrame(ActiveRenderInfo info, double camX, double camY, double camZ) {
|
||||||
for (RenderedContraption renderer : renderers.values()) {
|
for (RenderedContraption renderer : renderers.values()) {
|
||||||
renderer.beginFrame(camX, camY, camZ);
|
renderer.beginFrame(info, camX, camY, camZ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,8 +88,8 @@ public class RenderedContraption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void beginFrame(double camX, double camY, double camZ) {
|
public void beginFrame(ActiveRenderInfo info, double camX, double camY, double camZ) {
|
||||||
kinetics.beginFrame(camX, camY, camZ);
|
kinetics.beginFrame(info, camX, camY, camZ);
|
||||||
|
|
||||||
AbstractContraptionEntity entity = contraption.entity;
|
AbstractContraptionEntity entity = contraption.entity;
|
||||||
float pt = AnimationTickHolder.getPartialTicks();
|
float pt = AnimationTickHolder.getPartialTicks();
|
||||||
|
|
|
@ -1,15 +1,5 @@
|
||||||
package com.simibubi.create.content.contraptions.relays.advanced;
|
package com.simibubi.create.content.contraptions.relays.advanced;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
|
||||||
import com.simibubi.create.AllShapes;
|
|
||||||
import com.simibubi.create.AllTileEntities;
|
|
||||||
import com.simibubi.create.content.contraptions.base.HorizontalAxisKineticBlock;
|
|
||||||
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
|
|
||||||
import com.simibubi.create.content.contraptions.relays.elementary.CogwheelBlockItem;
|
|
||||||
import com.simibubi.create.foundation.block.ITE;
|
|
||||||
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
|
|
||||||
import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
|
|
||||||
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
|
|
||||||
import mcp.MethodsReturnNonnullByDefault;
|
import mcp.MethodsReturnNonnullByDefault;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
@ -29,6 +19,16 @@ import net.minecraft.world.IBlockReader;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.AllShapes;
|
||||||
|
import com.simibubi.create.AllTileEntities;
|
||||||
|
import com.simibubi.create.content.contraptions.base.HorizontalAxisKineticBlock;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.elementary.CogwheelBlockItem;
|
||||||
|
import com.simibubi.create.foundation.block.ITE;
|
||||||
|
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
|
||||||
|
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
|
||||||
|
|
||||||
public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements ITE<SpeedControllerTileEntity> {
|
public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements ITE<SpeedControllerTileEntity> {
|
||||||
|
|
||||||
|
@ -100,8 +100,8 @@ public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements
|
||||||
|
|
||||||
Axis newAxis = state.get(HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X;
|
Axis newAxis = state.get(HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X;
|
||||||
|
|
||||||
if (CogwheelBlockItem.DiagonalCogHelper.hasLargeCogwheelNeighbor(world, newPos, newAxis)
|
if (CogwheelBlockItem.hasLargeCogwheelNeighbor(world, newPos, newAxis)
|
||||||
|| CogwheelBlockItem.DiagonalCogHelper.hasSmallCogwheelNeighbor(world, newPos, newAxis))
|
|| CogwheelBlockItem.hasSmallCogwheelNeighbor(world, newPos, newAxis))
|
||||||
return PlacementOffset.fail();
|
return PlacementOffset.fail();
|
||||||
|
|
||||||
return PlacementOffset.success(newPos, s -> s.with(CogWheelBlock.AXIS, newAxis));
|
return PlacementOffset.success(newPos, s -> s.with(CogWheelBlock.AXIS, newAxis));
|
||||||
|
|
|
@ -1,15 +1,5 @@
|
||||||
package com.simibubi.create.content.contraptions.relays.elementary;
|
package com.simibubi.create.content.contraptions.relays.elementary;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
|
||||||
import com.simibubi.create.AllShapes;
|
|
||||||
import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock;
|
|
||||||
import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock;
|
|
||||||
import com.simibubi.create.content.contraptions.base.IRotate;
|
|
||||||
import com.simibubi.create.foundation.advancement.AllTriggers;
|
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
|
||||||
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
|
|
||||||
import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
|
|
||||||
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
|
|
||||||
import mcp.MethodsReturnNonnullByDefault;
|
import mcp.MethodsReturnNonnullByDefault;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
@ -27,6 +17,16 @@ import net.minecraft.world.World;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.AllShapes;
|
||||||
|
import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock;
|
||||||
|
import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock;
|
||||||
|
import com.simibubi.create.content.contraptions.base.IRotate;
|
||||||
|
import com.simibubi.create.foundation.advancement.AllTriggers;
|
||||||
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
|
||||||
|
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
|
||||||
|
|
||||||
import static com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock.AXIS;
|
import static com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock.AXIS;
|
||||||
|
|
||||||
|
@ -169,6 +169,10 @@ public class CogwheelBlockItem extends BlockItem {
|
||||||
for (Direction dir : directions) {
|
for (Direction dir : directions) {
|
||||||
BlockPos newPos = pos.offset(dir)
|
BlockPos newPos = pos.offset(dir)
|
||||||
.offset(side);
|
.offset(side);
|
||||||
|
|
||||||
|
if (hasLargeCogwheelNeighbor(world, newPos, dir.getAxis()) || hasSmallCogwheelNeighbor(world, newPos, dir.getAxis()))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!world.getBlockState(newPos)
|
if (!world.getBlockState(newPos)
|
||||||
.getMaterial()
|
.getMaterial()
|
||||||
.isReplaceable())
|
.isReplaceable())
|
||||||
|
@ -225,30 +229,6 @@ public class CogwheelBlockItem extends BlockItem {
|
||||||
.subtract(ray.getHitVec()
|
.subtract(ray.getHitVec()
|
||||||
.align(Iterate.axisSet)));
|
.align(Iterate.axisSet)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static public boolean hasLargeCogwheelNeighbor(World world, BlockPos pos, Direction.Axis axis) {
|
|
||||||
for (Direction dir : Iterate.directions) {
|
|
||||||
if (dir.getAxis() == axis)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (AllBlocks.LARGE_COGWHEEL.has(world.getBlockState(pos.offset(dir))))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static public boolean hasSmallCogwheelNeighbor(World world, BlockPos pos, Direction.Axis axis) {
|
|
||||||
for (Direction dir : Iterate.directions) {
|
|
||||||
if (dir.getAxis() == axis)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (AllBlocks.COGWHEEL.has(world.getBlockState(pos.offset(dir))))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@MethodsReturnNonnullByDefault
|
@MethodsReturnNonnullByDefault
|
||||||
|
@ -294,8 +274,8 @@ public class CogwheelBlockItem extends BlockItem {
|
||||||
.isReplaceable())
|
.isReplaceable())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (DiagonalCogHelper.hasLargeCogwheelNeighbor(world, newPos, newAxis)
|
if (hasLargeCogwheelNeighbor(world, newPos, newAxis)
|
||||||
|| DiagonalCogHelper.hasSmallCogwheelNeighbor(world, newPos, newAxis))
|
|| hasSmallCogwheelNeighbor(world, newPos, newAxis))
|
||||||
return PlacementOffset.fail();
|
return PlacementOffset.fail();
|
||||||
|
|
||||||
return PlacementOffset.success(newPos, s -> s.with(CogWheelBlock.AXIS, newAxis));
|
return PlacementOffset.success(newPos, s -> s.with(CogWheelBlock.AXIS, newAxis));
|
||||||
|
@ -303,5 +283,29 @@ public class CogwheelBlockItem extends BlockItem {
|
||||||
|
|
||||||
return PlacementOffset.fail();
|
return PlacementOffset.fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
static public boolean hasLargeCogwheelNeighbor(World world, BlockPos pos, Axis axis) {
|
||||||
|
for (Direction dir : Iterate.directions) {
|
||||||
|
if (dir.getAxis() == axis)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (AllBlocks.LARGE_COGWHEEL.has(world.getBlockState(pos.offset(dir))))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public boolean hasSmallCogwheelNeighbor(World world, BlockPos pos, Axis axis) {
|
||||||
|
for (Direction dir : Iterate.directions) {
|
||||||
|
if (dir.getAxis() == axis)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (AllBlocks.COGWHEEL.has(world.getBlockState(pos.offset(dir))))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,6 @@ public class SplitShaftInstance extends KineticTileInstance<SplitShaftTileEntity
|
||||||
|
|
||||||
keys.add(setup(half.createInstance(), splitSpeed));
|
keys.add(setup(half.createInstance(), splitSpeed));
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLight();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -28,7 +28,6 @@ public class EjectorInstance extends ShaftInstance implements IDynamicInstance {
|
||||||
plate = getTransformMaterial().getModel(AllBlockPartials.EJECTOR_TOP, blockState).createInstance();
|
plate = getTransformMaterial().getModel(AllBlockPartials.EJECTOR_TOP, blockState).createInstance();
|
||||||
|
|
||||||
pivotPlate();
|
pivotPlate();
|
||||||
updateLight();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -3,7 +3,6 @@ package com.simibubi.create.content.logistics.block.mechanicalArm;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
import com.simibubi.create.AllBlockPartials;
|
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.RotatingData;
|
||||||
import com.simibubi.create.content.contraptions.base.SingleRotatingInstance;
|
import com.simibubi.create.content.contraptions.base.SingleRotatingInstance;
|
||||||
import com.simibubi.create.foundation.render.backend.instancing.*;
|
import com.simibubi.create.foundation.render.backend.instancing.*;
|
||||||
|
@ -30,10 +29,11 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta
|
||||||
private final ArrayList<InstanceKey<ModelData>> clawGrips;
|
private final ArrayList<InstanceKey<ModelData>> clawGrips;
|
||||||
|
|
||||||
private final ArrayList<InstanceKey<ModelData>> models;
|
private final ArrayList<InstanceKey<ModelData>> models;
|
||||||
|
private final ArmTileEntity arm;
|
||||||
|
|
||||||
private boolean firstTick = true;
|
private boolean firstTick = true;
|
||||||
|
|
||||||
public ArmInstance(InstancedTileRenderer<?> modelManager, KineticTileEntity tile) {
|
public ArmInstance(InstancedTileRenderer<?> modelManager, ArmTileEntity tile) {
|
||||||
super(modelManager, tile);
|
super(modelManager, tile);
|
||||||
|
|
||||||
RenderMaterial<?, InstancedModel<ModelData>> mat = getTransformMaterial();
|
RenderMaterial<?, InstancedModel<ModelData>> mat = getTransformMaterial();
|
||||||
|
@ -50,33 +50,35 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta
|
||||||
|
|
||||||
clawGrips = Lists.newArrayList(clawGrip1, clawGrip2);
|
clawGrips = Lists.newArrayList(clawGrip1, clawGrip2);
|
||||||
models = Lists.newArrayList(base, lowerBody, upperBody, head, claw, clawGrip1, clawGrip2);
|
models = Lists.newArrayList(base, lowerBody, upperBody, head, claw, clawGrip1, clawGrip2);
|
||||||
|
arm = tile;
|
||||||
|
|
||||||
|
animateArm(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beginFrame() {
|
public void beginFrame() {
|
||||||
ArmTileEntity arm = (ArmTileEntity) tile;
|
|
||||||
|
|
||||||
boolean settled = arm.baseAngle.settled() && arm.lowerArmAngle.settled() && arm.upperArmAngle.settled() && arm.headAngle.settled();
|
boolean settled = arm.baseAngle.settled() && arm.lowerArmAngle.settled() && arm.upperArmAngle.settled() && arm.headAngle.settled();
|
||||||
boolean rave = arm.phase == ArmTileEntity.Phase.DANCING;
|
boolean rave = arm.phase == ArmTileEntity.Phase.DANCING;
|
||||||
|
|
||||||
if (!settled || rave || firstTick)
|
if (!settled || rave || firstTick)
|
||||||
transformModels(arm, rave);
|
animateArm(rave);
|
||||||
|
|
||||||
if (settled)
|
if (settled)
|
||||||
firstTick = false;
|
firstTick = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void transformModels(ArmTileEntity arm, boolean rave) {
|
private void animateArm(boolean rave) {
|
||||||
float pt = AnimationTickHolder.getPartialTicks();
|
float pt = AnimationTickHolder.getPartialTicks();
|
||||||
int color = 0xFFFFFF;
|
int color = 0xFFFFFF;
|
||||||
|
|
||||||
float baseAngle = arm.baseAngle.get(pt);
|
float baseAngle = this.arm.baseAngle.get(pt);
|
||||||
float lowerArmAngle = arm.lowerArmAngle.get(pt) - 135;
|
float lowerArmAngle = this.arm.lowerArmAngle.get(pt) - 135;
|
||||||
float upperArmAngle = arm.upperArmAngle.get(pt) - 90;
|
float upperArmAngle = this.arm.upperArmAngle.get(pt) - 90;
|
||||||
float headAngle = arm.headAngle.get(pt);
|
float headAngle = this.arm.headAngle.get(pt);
|
||||||
|
|
||||||
if (rave) {
|
if (rave) {
|
||||||
float renderTick = AnimationTickHolder.getRenderTime(arm.getWorld()) + (tile.hashCode() % 64);
|
float renderTick = AnimationTickHolder.getRenderTime(this.arm.getWorld()) + (tile.hashCode() % 64);
|
||||||
baseAngle = (renderTick * 10) % 360;
|
baseAngle = (renderTick * 10) % 360;
|
||||||
lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15);
|
lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15);
|
||||||
upperArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 8) + 1) / 4, -45, 95);
|
upperArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 8) + 1) / 4, -45, 95);
|
||||||
|
@ -84,7 +86,6 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta
|
||||||
color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100);
|
color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MatrixStack msLocal = new MatrixStack();
|
MatrixStack msLocal = new MatrixStack();
|
||||||
MatrixStacker msr = MatrixStacker.of(msLocal);
|
MatrixStacker msr = MatrixStacker.of(msLocal);
|
||||||
msr.translate(getInstancePosition());
|
msr.translate(getInstancePosition());
|
||||||
|
@ -115,7 +116,7 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta
|
||||||
claw.getInstance()
|
claw.getInstance()
|
||||||
.setTransform(msLocal);
|
.setTransform(msLocal);
|
||||||
|
|
||||||
ItemStack item = arm.heldItem;
|
ItemStack item = this.arm.heldItem;
|
||||||
ItemRenderer itemRenderer = Minecraft.getInstance()
|
ItemRenderer itemRenderer = Minecraft.getInstance()
|
||||||
.getItemRenderer();
|
.getItemRenderer();
|
||||||
boolean hasItem = !item.isEmpty();
|
boolean hasItem = !item.isEmpty();
|
||||||
|
|
|
@ -31,16 +31,16 @@ public class AnalogLeverInstance extends TileEntityInstance<AnalogLeverTileEntit
|
||||||
rX = face == AttachFace.FLOOR ? 0 : face == AttachFace.WALL ? 90 : 180;
|
rX = face == AttachFace.FLOOR ? 0 : face == AttachFace.WALL ? 90 : 180;
|
||||||
rY = AngleHelper.horizontalAngle(blockState.get(AnalogLeverBlock.HORIZONTAL_FACING));
|
rY = AngleHelper.horizontalAngle(blockState.get(AnalogLeverBlock.HORIZONTAL_FACING));
|
||||||
|
|
||||||
setupModel();
|
animateLever();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beginFrame() {
|
public void beginFrame() {
|
||||||
if (!tile.clientState.settled())
|
if (!tile.clientState.settled())
|
||||||
setupModel();
|
animateLever();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setupModel() {
|
protected void animateLever() {
|
||||||
MatrixStack ms = new MatrixStack();
|
MatrixStack ms = new MatrixStack();
|
||||||
MatrixStacker msr = MatrixStacker.of(ms);
|
MatrixStacker msr = MatrixStacker.of(ms);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@ public class SchematicannonInstance extends TileEntityInstance<SchematicannonTil
|
||||||
|
|
||||||
connector = mat.getModel(AllBlockPartials.SCHEMATICANNON_CONNECTOR, blockState).createInstance();
|
connector = mat.getModel(AllBlockPartials.SCHEMATICANNON_CONNECTOR, blockState).createInstance();
|
||||||
pipe = mat.getModel(AllBlockPartials.SCHEMATICANNON_PIPE, blockState).createInstance();
|
pipe = mat.getModel(AllBlockPartials.SCHEMATICANNON_PIPE, blockState).createInstance();
|
||||||
|
|
||||||
|
beginFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -59,8 +59,8 @@ public class RenderHooksMixin {
|
||||||
double camY = cameraPos.getY();
|
double camY = cameraPos.getY();
|
||||||
double camZ = cameraPos.getZ();
|
double camZ = cameraPos.getZ();
|
||||||
|
|
||||||
CreateClient.kineticRenderer.get(world).beginFrame(camX, camY, camZ);
|
CreateClient.kineticRenderer.get(world).beginFrame(info, camX, camY, camZ);
|
||||||
ContraptionRenderDispatcher.beginFrame(camX, camY, camZ);
|
ContraptionRenderDispatcher.beginFrame(info, camX, camY, camZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(at = @At("TAIL"), method = "scheduleBlockRerenderIfNeeded")
|
@Inject(at = @At("TAIL"), method = "scheduleBlockRerenderIfNeeded")
|
||||||
|
|
|
@ -15,6 +15,7 @@ import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial;
|
||||||
import com.simibubi.create.foundation.render.backend.instancing.impl.OrientedModel;
|
import com.simibubi.create.foundation.render.backend.instancing.impl.OrientedModel;
|
||||||
import com.simibubi.create.foundation.render.backend.instancing.impl.TransformedModel;
|
import com.simibubi.create.foundation.render.backend.instancing.impl.TransformedModel;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
@ -42,7 +43,7 @@ public class KineticRenderer extends InstancedTileRenderer<BasicProgram> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beginFrame(double cameraX, double cameraY, double cameraZ) {
|
public void beginFrame(ActiveRenderInfo info, double cameraX, double cameraY, double cameraZ) {
|
||||||
int cX = MathHelper.floor(cameraX);
|
int cX = MathHelper.floor(cameraX);
|
||||||
int cY = MathHelper.floor(cameraY);
|
int cY = MathHelper.floor(cameraY);
|
||||||
int cZ = MathHelper.floor(cameraZ);
|
int cZ = MathHelper.floor(cameraZ);
|
||||||
|
@ -62,7 +63,7 @@ public class KineticRenderer extends InstancedTileRenderer<BasicProgram> {
|
||||||
instancedTiles.forEach(this::add);
|
instancedTiles.forEach(this::add);
|
||||||
}
|
}
|
||||||
|
|
||||||
super.beginFrame(cameraX, cameraY, cameraZ);
|
super.beginFrame(info, cameraX, cameraY, cameraZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,6 +15,7 @@ import net.minecraft.client.entity.player.ClientPlayerEntity;
|
||||||
import net.minecraft.client.renderer.GameRenderer;
|
import net.minecraft.client.renderer.GameRenderer;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.potion.Effects;
|
import net.minecraft.potion.Effects;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
@ -37,10 +38,13 @@ public class FastRenderDispatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tick() {
|
public static void tick() {
|
||||||
ClientWorld world = Minecraft.getInstance().world;
|
Minecraft mc = Minecraft.getInstance();
|
||||||
|
ClientWorld world = mc.world;
|
||||||
|
|
||||||
KineticRenderer kineticRenderer = CreateClient.kineticRenderer.get(world);
|
KineticRenderer kineticRenderer = CreateClient.kineticRenderer.get(world);
|
||||||
kineticRenderer.tick();
|
|
||||||
|
Entity renderViewEntity = mc.renderViewEntity;
|
||||||
|
kineticRenderer.tick(renderViewEntity.getX(), renderViewEntity.getY(), renderViewEntity.getZ());
|
||||||
|
|
||||||
ConcurrentHashMap.KeySetView<TileEntity, Boolean> map = queuedUpdates.get(world);
|
ConcurrentHashMap.KeySetView<TileEntity, Boolean> map = queuedUpdates.get(world);
|
||||||
map
|
map
|
||||||
|
|
|
@ -9,9 +9,22 @@ package com.simibubi.create.foundation.render.backend.instancing;
|
||||||
* <br><br> If your goal is offloading work to shaders, but you're unsure exactly how you need
|
* <br><br> If your goal is offloading work to shaders, but you're unsure exactly how you need
|
||||||
* to parameterize the instances, you're encouraged to implement this for prototyping.
|
* to parameterize the instances, you're encouraged to implement this for prototyping.
|
||||||
*/
|
*/
|
||||||
public interface IDynamicInstance {
|
public interface IDynamicInstance extends IInstance {
|
||||||
/**
|
/**
|
||||||
* Called every frame.
|
* Called every frame.
|
||||||
*/
|
*/
|
||||||
void beginFrame();
|
void beginFrame();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* As a further optimization, dynamic instances that are far away are ticked less often.
|
||||||
|
* This behavior can be disabled by returning false.
|
||||||
|
*
|
||||||
|
* <br> You might want to opt out of this if you want your animations to remain smooth
|
||||||
|
* even when far away from the camera. It is recommended to keep this as is, however.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if your instance should be slow ticked.
|
||||||
|
*/
|
||||||
|
default boolean decreaseFramerateWithDistance() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.simibubi.create.foundation.render.backend.instancing;
|
||||||
|
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A general interface providing information about any type of thing that could use
|
||||||
|
* Flywheel's instanced rendering. Right now, that's only {@link InstancedTileRenderer},
|
||||||
|
* but there could be an entity equivalent in the future.
|
||||||
|
*/
|
||||||
|
public interface IInstance {
|
||||||
|
|
||||||
|
BlockPos getWorldPosition();
|
||||||
|
}
|
|
@ -16,10 +16,23 @@ package com.simibubi.create.foundation.render.backend.instancing;
|
||||||
* </li>
|
* </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public interface ITickableInstance {
|
public interface ITickableInstance extends IInstance {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called every tick.
|
* Called every tick.
|
||||||
*/
|
*/
|
||||||
void tick();
|
void tick();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* As a further optimization, tickable instances that are far away are ticked less often.
|
||||||
|
* This behavior can be disabled by returning false.
|
||||||
|
*
|
||||||
|
* <br> You might want to opt out of this if you want your animations to remain smooth
|
||||||
|
* even when far away from the camera. It is recommended to keep this as is, however.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if your instance should be slow ticked.
|
||||||
|
*/
|
||||||
|
default boolean decreaseTickRateWithDistance() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,13 +10,14 @@ import com.simibubi.create.foundation.render.backend.gl.BasicProgram;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.shader.ShaderCallback;
|
import com.simibubi.create.foundation.render.backend.gl.shader.ShaderCallback;
|
||||||
import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData;
|
import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData;
|
||||||
import com.simibubi.create.foundation.render.backend.instancing.impl.OrientedData;
|
import com.simibubi.create.foundation.render.backend.instancing.impl.OrientedData;
|
||||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.client.renderer.*;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.vector.Matrix4f;
|
import net.minecraft.util.math.vector.Matrix4f;
|
||||||
|
import net.minecraft.util.math.vector.Vector3f;
|
||||||
import net.minecraft.world.IBlockReader;
|
import net.minecraft.world.IBlockReader;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
@ -30,6 +31,8 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
||||||
|
|
||||||
protected Map<MaterialType<?>, RenderMaterial<P, ?>> materials = new HashMap<>();
|
protected Map<MaterialType<?>, RenderMaterial<P, ?>> materials = new HashMap<>();
|
||||||
|
|
||||||
|
protected int frame;
|
||||||
|
|
||||||
protected InstancedTileRenderer() {
|
protected InstancedTileRenderer() {
|
||||||
registerMaterials();
|
registerMaterials();
|
||||||
}
|
}
|
||||||
|
@ -38,15 +41,74 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
||||||
|
|
||||||
public abstract void registerMaterials();
|
public abstract void registerMaterials();
|
||||||
|
|
||||||
public void tick() {
|
public void tick(double cameraX, double cameraY, double cameraZ) {
|
||||||
if (tickableInstances.size() > 0)
|
// integer camera pos
|
||||||
tickableInstances.values().forEach(ITickableInstance::tick);
|
int cX = (int) cameraX;
|
||||||
|
int cY = (int) cameraY;
|
||||||
|
int cZ = (int) cameraZ;
|
||||||
|
|
||||||
|
if (tickableInstances.size() > 0) {
|
||||||
|
for (ITickableInstance instance : tickableInstances.values()) {
|
||||||
|
if (!instance.decreaseTickRateWithDistance()) {
|
||||||
|
instance.tick();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void beginFrame(double cameraX, double cameraY, double cameraZ) {
|
BlockPos pos = instance.getWorldPosition();
|
||||||
|
|
||||||
|
int dX = pos.getX() - cX;
|
||||||
|
int dY = pos.getY() - cY;
|
||||||
|
int dZ = pos.getZ() - cZ;
|
||||||
|
|
||||||
|
int dSq = dX * dX + dY * dY + dZ * dZ;
|
||||||
|
|
||||||
|
int divisor = (dSq / 1024) + 1;
|
||||||
|
|
||||||
|
if (frame % divisor == 0)
|
||||||
|
instance.tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void beginFrame(ActiveRenderInfo info, double cameraX, double cameraY, double cameraZ) {
|
||||||
|
frame++;
|
||||||
processQueuedAdditions();
|
processQueuedAdditions();
|
||||||
if (dynamicInstances.size() > 0)
|
|
||||||
dynamicInstances.values().forEach(IDynamicInstance::beginFrame);
|
Vector3f look = info.getHorizontalPlane();
|
||||||
|
float lookX = look.getX();
|
||||||
|
float lookY = look.getY();
|
||||||
|
float lookZ = look.getZ();
|
||||||
|
|
||||||
|
// integer camera pos
|
||||||
|
int cX = (int) cameraX;
|
||||||
|
int cY = (int) cameraY;
|
||||||
|
int cZ = (int) cameraZ;
|
||||||
|
|
||||||
|
if (dynamicInstances.size() > 0) {
|
||||||
|
for (IDynamicInstance dyn : dynamicInstances.values()) {
|
||||||
|
if (!dyn.decreaseFramerateWithDistance()) {
|
||||||
|
dyn.beginFrame();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockPos pos = dyn.getWorldPosition();
|
||||||
|
|
||||||
|
int dX = pos.getX() - cX;
|
||||||
|
int dY = pos.getY() - cY;
|
||||||
|
int dZ = pos.getZ() - cZ;
|
||||||
|
|
||||||
|
float dot = dX * lookX + dY * lookY + dZ * lookZ;
|
||||||
|
|
||||||
|
if (dot < 0) continue; // is it behind the camera?
|
||||||
|
|
||||||
|
int dSq = dX * dX + dY * dY + dZ * dZ;
|
||||||
|
|
||||||
|
int divisor = (dSq / 1024) + 1; // https://www.desmos.com/calculator/aaycpludsy
|
||||||
|
|
||||||
|
if (frame % divisor == 0)
|
||||||
|
dyn.beginFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ) {
|
public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ) {
|
||||||
|
|
|
@ -30,12 +30,13 @@ import java.util.stream.Stream;
|
||||||
*
|
*
|
||||||
* @param <T> The type of {@link TileEntity} your class is an instance of.
|
* @param <T> The type of {@link TileEntity} your class is an instance of.
|
||||||
*/
|
*/
|
||||||
public abstract class TileEntityInstance<T extends TileEntity> {
|
public abstract class TileEntityInstance<T extends TileEntity> implements IInstance {
|
||||||
|
|
||||||
protected final InstancedTileRenderer<?> renderer;
|
protected final InstancedTileRenderer<?> renderer;
|
||||||
protected final T tile;
|
protected final T tile;
|
||||||
protected final World world;
|
protected final World world;
|
||||||
protected final BlockPos pos;
|
protected final BlockPos pos;
|
||||||
|
protected final BlockPos instancePos;
|
||||||
protected final BlockState blockState;
|
protected final BlockState blockState;
|
||||||
|
|
||||||
public TileEntityInstance(InstancedTileRenderer<?> renderer, T tile) {
|
public TileEntityInstance(InstancedTileRenderer<?> renderer, T tile) {
|
||||||
|
@ -44,6 +45,7 @@ public abstract class TileEntityInstance<T extends TileEntity> {
|
||||||
this.world = tile.getWorld();
|
this.world = tile.getWorld();
|
||||||
this.pos = tile.getPos();
|
this.pos = tile.getPos();
|
||||||
this.blockState = tile.getBlockState();
|
this.blockState = tile.getBlockState();
|
||||||
|
this.instancePos = pos.subtract(renderer.getOriginCoordinate());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -89,7 +91,12 @@ public abstract class TileEntityInstance<T extends TileEntity> {
|
||||||
* represents should be rendered at to appear in the correct location.
|
* represents should be rendered at to appear in the correct location.
|
||||||
*/
|
*/
|
||||||
public BlockPos getInstancePosition() {
|
public BlockPos getInstancePosition() {
|
||||||
return pos.subtract(renderer.getOriginCoordinate());
|
return instancePos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockPos getWorldPosition() {
|
||||||
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void relight(BlockPos pos, IFlatLight<?>... models) {
|
protected void relight(BlockPos pos, IFlatLight<?>... models) {
|
||||||
|
|
|
@ -18,7 +18,9 @@ import net.minecraftforge.items.CapabilityItemHandler;
|
||||||
|
|
||||||
public abstract class SmartTileEntity extends SyncedTileEntity implements ITickableTileEntity {
|
public abstract class SmartTileEntity extends SyncedTileEntity implements ITickableTileEntity {
|
||||||
|
|
||||||
private Map<BehaviourType<?>, TileEntityBehaviour> behaviours;
|
private final Map<BehaviourType<?>, TileEntityBehaviour> behaviours;
|
||||||
|
// Internally maintained to be identical to behaviorMap.values() in order to improve iteration performance.
|
||||||
|
private final List<TileEntityBehaviour> behaviourList;
|
||||||
private boolean initialized;
|
private boolean initialized;
|
||||||
private boolean firstNbtRead;
|
private boolean firstNbtRead;
|
||||||
private int lazyTickRate;
|
private int lazyTickRate;
|
||||||
|
@ -37,6 +39,9 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka
|
||||||
ArrayList<TileEntityBehaviour> list = new ArrayList<>();
|
ArrayList<TileEntityBehaviour> list = new ArrayList<>();
|
||||||
addBehaviours(list);
|
addBehaviours(list);
|
||||||
list.forEach(b -> behaviours.put(b.getType(), b));
|
list.forEach(b -> behaviours.put(b.getType(), b));
|
||||||
|
|
||||||
|
behaviourList = new ArrayList<>(list.size());
|
||||||
|
updateBehaviorList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void addBehaviours(List<TileEntityBehaviour> behaviours);
|
public abstract void addBehaviours(List<TileEntityBehaviour> behaviours);
|
||||||
|
@ -59,13 +64,11 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka
|
||||||
lazyTick();
|
lazyTick();
|
||||||
}
|
}
|
||||||
|
|
||||||
behaviours.values()
|
behaviourList.forEach(TileEntityBehaviour::tick);
|
||||||
.forEach(TileEntityBehaviour::tick);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
behaviours.values()
|
behaviourList.forEach(TileEntityBehaviour::initialize);
|
||||||
.forEach(TileEntityBehaviour::initialize);
|
|
||||||
lazyTick();
|
lazyTick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,10 +103,11 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka
|
||||||
ArrayList<TileEntityBehaviour> list = new ArrayList<>();
|
ArrayList<TileEntityBehaviour> list = new ArrayList<>();
|
||||||
addBehavioursDeferred(list);
|
addBehavioursDeferred(list);
|
||||||
list.forEach(b -> behaviours.put(b.getType(), b));
|
list.forEach(b -> behaviours.put(b.getType(), b));
|
||||||
|
|
||||||
|
updateBehaviorList();
|
||||||
}
|
}
|
||||||
super.fromTag(state, compound);
|
super.fromTag(state, compound);
|
||||||
behaviours.values()
|
behaviourList.forEach(tb -> tb.read(compound, clientPacket));
|
||||||
.forEach(tb -> tb.read(compound, clientPacket));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -111,8 +115,7 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka
|
||||||
*/
|
*/
|
||||||
protected void write(CompoundNBT compound, boolean clientPacket) {
|
protected void write(CompoundNBT compound, boolean clientPacket) {
|
||||||
super.write(compound);
|
super.write(compound);
|
||||||
behaviours.values()
|
behaviourList.forEach(tb -> tb.write(compound, clientPacket));
|
||||||
.forEach(tb -> tb.write(compound, clientPacket));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -131,19 +134,31 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void forEachBehaviour(Consumer<TileEntityBehaviour> action) {
|
protected void forEachBehaviour(Consumer<TileEntityBehaviour> action) {
|
||||||
behaviours.values()
|
behaviourList.forEach(action);
|
||||||
.forEach(action);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void attachBehaviourLate(TileEntityBehaviour behaviour) {
|
protected void attachBehaviourLate(TileEntityBehaviour behaviour) {
|
||||||
behaviours.put(behaviour.getType(), behaviour);
|
behaviours.put(behaviour.getType(), behaviour);
|
||||||
behaviour.initialize();
|
behaviour.initialize();
|
||||||
|
|
||||||
|
updateBehaviorList();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void removeBehaviour(BehaviourType<?> type) {
|
protected void removeBehaviour(BehaviourType<?> type) {
|
||||||
TileEntityBehaviour remove = behaviours.remove(type);
|
TileEntityBehaviour remove = behaviours.remove(type);
|
||||||
if (remove != null)
|
if (remove != null) {
|
||||||
remove.remove();
|
remove.remove();
|
||||||
|
updateBehaviorList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't trust the input to the API will be sane, so we
|
||||||
|
// update all the contents whenever something changes. It's
|
||||||
|
// simpler than trying to manipulate the list one element at
|
||||||
|
// a time.
|
||||||
|
private void updateBehaviorList() {
|
||||||
|
behaviourList.clear();
|
||||||
|
behaviourList.addAll(behaviours.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|
Loading…
Reference in a new issue