Flying the wheel away

This commit is contained in:
IThundxr 2024-07-18 19:08:25 -04:00 committed by Jozufozu
parent 02dca46855
commit 05c2cbaf73
59 changed files with 948 additions and 334 deletions

View file

@ -104,10 +104,11 @@ repositories {
name = "ModMaven"
url = "https://modmaven.dev"
}*/
maven {
// location of the maven for Dynamic Trees
url = 'https://harleyoconnor.com/maven'
}
// Expired SSL cert, prevents building
// maven {
// // location of the maven for Dynamic Trees
// url = 'https://harleyoconnor.com/maven'
// }
maven {
// location of the maven for Curios API
url = "https://maven.theillusivec4.top/"
@ -145,7 +146,7 @@ dependencies {
jarJar("com.tterrag.registrate:Registrate:${registrate_version}") {
jarJar.ranged(it, '[MC1.19.3-1.1.10,)')
}
jarJar("com.jozufozu.flywheel:flywheel-forge-${flywheel_minecraft_version}:${flywheel_version}") {
jarJar("dev.engine_room.flywheel:flywheel-forge-${flywheel_minecraft_version}:${flywheel_version}") {
jarJar.ranged(it, '[1.0,2.0)')
}

View file

@ -23,7 +23,7 @@ use_parchment = true
# dependency versions
registrate_version = MC1.20-1.3.3
flywheel_minecraft_version = 1.20.1
flywheel_version = 1.0.0-beta-89
flywheel_version = 1.0.0-beta-97
jei_minecraft_version = 1.20.1
jei_version = 15.2.0.22
curios_minecraft_version = 1.20.1

View file

@ -102,9 +102,4 @@ public class HarvesterActorVisual extends ActorVisual {
protected double getRotation() {
return AngleHelper.angleLerp(AnimationTickHolder.getPartialTicks(), previousRotation, rotation);
}
@Override
public void init(float partialTick) {
}
}

View file

@ -32,9 +32,4 @@ public class PSIActorVisual extends ActorVisual {
protected void _delete() {
instance.remove();
}
@Override
public void init(float partialTick) {
}
}

View file

@ -14,16 +14,12 @@ public class PSIVisual extends AbstractBlockEntityVisual<PortableStorageInterfac
private final PIInstance instance;
public PSIVisual(VisualizationContext visualizationContext, PortableStorageInterfaceBlockEntity blockEntity) {
super(visualizationContext, blockEntity);
public PSIVisual(VisualizationContext visualizationContext, PortableStorageInterfaceBlockEntity blockEntity, float partialTick) {
super(visualizationContext, blockEntity, partialTick);
instance = new PIInstance(visualizationContext.instancerProvider(), blockState, getVisualPosition());
}
@Override
public void init(float pt) {
instance.init(isLit());
super.init(pt);
}
@Override
@ -37,7 +33,7 @@ public class PSIVisual extends AbstractBlockEntityVisual<PortableStorageInterfac
}
@Override
public void updateLight() {
public void updateLight(float partialTick) {
relight(pos, instance.middle, instance.top);
}

View file

@ -27,8 +27,8 @@ public class BearingVisual<B extends KineticBlockEntity & IBearingBlockEntity> e
final Axis rotationAxis;
final Quaternionf blockOrientation;
public BearingVisual(VisualizationContext context, B blockEntity) {
super(context, blockEntity);
public BearingVisual(VisualizationContext context, B blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
Direction facing = blockState.getValue(BlockStateProperties.FACING);
rotationAxis = Axis.of(Direction.get(Direction.AxisDirection.POSITIVE, axis).step());
@ -58,8 +58,8 @@ public class BearingVisual<B extends KineticBlockEntity & IBearingBlockEntity> e
}
@Override
public void updateLight() {
super.updateLight();
public void updateLight(float partialTick) {
super.updateLight(partialTick);
relight(pos, topInstance);
}

View file

@ -70,9 +70,4 @@ public class StabilizedBearingVisual extends ActorVisual {
topInstance.delete();
shaft.delete();
}
@Override
public void init(float partialTick) {
}
}

View file

@ -26,8 +26,8 @@ public class StickerVisual extends AbstractBlockEntityVisual<StickerBlockEntity>
private final TransformedInstance head;
public StickerVisual(VisualizationContext context, StickerBlockEntity blockEntity) {
super(context, blockEntity);
public StickerVisual(VisualizationContext context, StickerBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
head = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.STICKER_HEAD)).createInstance();
@ -66,7 +66,7 @@ public class StickerVisual extends AbstractBlockEntityVisual<StickerBlockEntity>
}
@Override
public void updateLight() {
public void updateLight(float partialTick) {
relight(pos, head);
}

View file

@ -8,8 +8,8 @@ import com.simibubi.create.content.kinetics.base.ShaftVisual;
// TODO
public class ElevatorPulleyVisual extends ShaftVisual<ElevatorPulleyBlockEntity> implements SimpleDynamicVisual {
public ElevatorPulleyVisual(VisualizationContext context, ElevatorPulleyBlockEntity blockEntity) {
super(context, blockEntity);
public ElevatorPulleyVisual(VisualizationContext context, ElevatorPulleyBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
}
@Override

View file

@ -31,8 +31,8 @@ public class GantryCarriageVisual extends ShaftVisual<GantryCarriageBlockEntity>
private float lastAngle = Float.NaN;
public GantryCarriageVisual(VisualizationContext context, GantryCarriageBlockEntity blockEntity) {
super(context, blockEntity);
public GantryCarriageVisual(VisualizationContext context, GantryCarriageBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
gantryCogs = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.GANTRY_COGS))
.createInstance();
@ -98,7 +98,7 @@ public class GantryCarriageVisual extends ShaftVisual<GantryCarriageBlockEntity>
}
@Override
public void updateLight() {
public void updateLight(float partialTick) {
relight(pos, gantryCogs, rotatingModel);
}

View file

@ -2,13 +2,14 @@ package com.simibubi.create.content.contraptions.pulley;
import java.util.function.Consumer;
import com.simibubi.create.foundation.utility.flywheel.box.MutableBox;
import com.simibubi.create.foundation.utility.flywheel.light.LightVolume;
import dev.engine_room.flywheel.api.instance.Instance;
import dev.engine_room.flywheel.api.instance.Instancer;
import dev.engine_room.flywheel.api.visual.DynamicVisual;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.lib.box.MutableBox;
import dev.engine_room.flywheel.lib.instance.OrientedInstance;
import dev.engine_room.flywheel.lib.light.LightVolume;
import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual;
import com.mojang.math.Axis;
import com.simibubi.create.content.kinetics.base.KineticBlockEntity;
@ -34,8 +35,8 @@ public abstract class AbstractPulleyVisual<T extends KineticBlockEntity> extends
private final MutableBox volume = new MutableBox();
private final LightVolume light;
public AbstractPulleyVisual(VisualizationContext dispatcher, T blockEntity) {
super(dispatcher, blockEntity);
public AbstractPulleyVisual(VisualizationContext dispatcher, T blockEntity, float partialTick) {
super(dispatcher, blockEntity, partialTick);
rotatingAbout = Direction.get(Direction.AxisDirection.POSITIVE, axis);
rotationAxis = Axis.of(rotatingAbout.step());
@ -109,8 +110,8 @@ public abstract class AbstractPulleyVisual<T extends KineticBlockEntity> extends
}
@Override
public void updateLight() {
super.updateLight();
public void updateLight(float partialTick) {
super.updateLight(partialTick);
light.copyLight(volume);
relight(pos, coil);
}

View file

@ -10,8 +10,8 @@ import com.simibubi.create.content.fluids.hosePulley.HosePulleyBlockEntity;
public class HosePulleyVisual extends AbstractPulleyVisual<HosePulleyBlockEntity> {
public HosePulleyVisual(VisualizationContext dispatcher, HosePulleyBlockEntity blockEntity) {
super(dispatcher, blockEntity);
public HosePulleyVisual(VisualizationContext dispatcher, HosePulleyBlockEntity blockEntity, float partialTick) {
super(dispatcher, blockEntity, partialTick);
}
protected Instancer<OrientedInstance> getRopeModel() {

View file

@ -11,8 +11,8 @@ import com.simibubi.create.AllPartialModels;
import com.simibubi.create.foundation.render.VirtualRenderHelper;
public class RopePulleyVisual extends AbstractPulleyVisual<PulleyBlockEntity> {
public RopePulleyVisual(VisualizationContext context, PulleyBlockEntity blockEntity) {
super(context, blockEntity);
public RopePulleyVisual(VisualizationContext context, PulleyBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
}
protected Instancer<OrientedInstance> getRopeModel() {

View file

@ -2,7 +2,12 @@ package com.simibubi.create.content.contraptions.render;
import java.util.ArrayList;
import java.util.List;
import java.util.function.LongConsumer;
import dev.engine_room.flywheel.api.visual.LightUpdatedVisual;
import dev.engine_room.flywheel.api.visual.ShaderLightVisual;
import it.unimi.dsi.fastutil.longs.LongArraySet;
import it.unimi.dsi.fastutil.longs.LongSet;
import org.apache.commons.lang3.tuple.MutablePair;
@ -10,7 +15,6 @@ import dev.engine_room.flywheel.api.model.Model;
import dev.engine_room.flywheel.api.task.Plan;
import dev.engine_room.flywheel.api.visual.BlockEntityVisual;
import dev.engine_room.flywheel.api.visual.DynamicVisual;
import dev.engine_room.flywheel.api.visual.LitVisual;
import dev.engine_room.flywheel.api.visual.TickableVisual;
import dev.engine_room.flywheel.api.visualization.BlockEntityVisualizer;
import dev.engine_room.flywheel.api.visualization.VisualEmbedding;
@ -44,7 +48,7 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import net.minecraftforge.client.model.data.ModelData;
public class ContraptionVisual<E extends AbstractContraptionEntity> extends AbstractEntityVisual<E> implements DynamicVisual, TickableVisual, LitVisual {
public class ContraptionVisual<E extends AbstractContraptionEntity> extends AbstractEntityVisual<E> implements DynamicVisual, TickableVisual, LightUpdatedVisual, ShaderLightVisual {
protected static final int LIGHT_PADDING = 1;
protected final VisualEmbedding embedding;
@ -55,18 +59,19 @@ public class ContraptionVisual<E extends AbstractContraptionEntity> extends Abst
protected VirtualRenderWorld virtualRenderWorld;
protected Model model;
protected TransformedInstance structure;
protected Notifier notifier;
protected SectionCollector sectionCollector;
protected long minSection, maxSection;
protected long minBlock, maxBlock;
private final PoseStack contraptionMatrix = new PoseStack();
public ContraptionVisual(VisualizationContext ctx, E entity) {
super(ctx, entity);
public ContraptionVisual(VisualizationContext ctx, E entity, float partialTick) {
super(ctx, entity, partialTick);
embedding = ctx.createEmbedding();
init(partialTick);
}
@Override
public void init(float partialTick) {
setEmbeddingMatrices(partialTick);
@ -97,7 +102,7 @@ public class ContraptionVisual<E extends AbstractContraptionEntity> extends Abst
setupActor(actor, partialTick);
}
updateLight();
updateLight(partialTick);
}
@SuppressWarnings("unchecked")
@ -107,11 +112,9 @@ public class ContraptionVisual<E extends AbstractContraptionEntity> extends Abst
return;
}
Level world = be.getLevel();
Level level = be.getLevel();
be.setLevel(virtualRenderWorld);
BlockEntityVisual<? super T> visual = visualizer.createVisual(this.embedding, be);
visual.init(partialTicks);
BlockEntityVisual<? super T> visual = visualizer.createVisual(this.embedding, be, partialTicks);
children.add(visual);
@ -123,7 +126,7 @@ public class ContraptionVisual<E extends AbstractContraptionEntity> extends Abst
tickableVisuals.add(tickable, tickable.planTick());
}
be.setLevel(world);
be.setLevel(level);
}
private void setupActor(MutablePair<StructureTemplate.StructureBlockInfo, MovementContext> actor, float partialTick) {
@ -147,8 +150,6 @@ public class ContraptionVisual<E extends AbstractContraptionEntity> extends Abst
return;
}
visual.init(partialTick);
actors.add(visual);
}
@ -174,14 +175,14 @@ public class ContraptionVisual<E extends AbstractContraptionEntity> extends Abst
setEmbeddingMatrices(partialTick);
if (hasMovedSections()) {
notifier.notifySectionsChanged();
sectionCollector.sections(collectLightSections());
}
if (hasMovedBlocks()) {
// TODO: incremental light collection
// TODO: optimize light collection for very large contraptions
// by only collecting cuboids that contain faces
updateLight();
updateLight(partialTick);
}
}
@ -198,27 +199,11 @@ public class ContraptionVisual<E extends AbstractContraptionEntity> extends Abst
}
@Override
public void updateLight() {
embedding.invalidateLight();
// FIXME: Some blocks (e.g. large waterwheels) extend well beyond their actual block
// and might have lighting issues here
var boundingBox = entity.getBoundingBox();
int minX = minLight(boundingBox.minX);
int minY = minLight(boundingBox.minY);
int minZ = minLight(boundingBox.minZ);
int maxX = maxLight(boundingBox.maxX);
int maxY = maxLight(boundingBox.maxY);
int maxZ = maxLight(boundingBox.maxZ);
minBlock = BlockPos.asLong(minX, minY, minZ);
maxBlock = BlockPos.asLong(maxX, maxY, maxZ);
embedding.collectLight(level, minX, minY, minZ, maxX - minX, maxY - minY, maxZ - minZ);
public void updateLight(float partialTick) {
super.update(partialTick);
}
@Override
public void collectLightSections(LongConsumer consumer) {
public LongSet collectLightSections() {
var boundingBox = entity.getBoundingBox();
var minSectionX = minLightSection(boundingBox.minX);
@ -231,13 +216,17 @@ public class ContraptionVisual<E extends AbstractContraptionEntity> extends Abst
minSection = SectionPos.asLong(minSectionX, minSectionY, minSectionZ);
maxSection = SectionPos.asLong(maxSectionX, maxSectionY, maxSectionZ);
LongSet longSet = new LongArraySet();
for (int x = 0; x <= maxSectionX - minSectionX; x++) {
for (int y = 0; y <= maxSectionY - minSectionY; y++) {
for (int z = 0; z <= maxSectionZ - minSectionZ; z++) {
consumer.accept(SectionPos.offset(minSection, x, y, z));
longSet.add(SectionPos.offset(minSection, x, y, z));
}
}
}
return longSet;
}
protected boolean hasMovedBlocks() {
@ -267,8 +256,8 @@ public class ContraptionVisual<E extends AbstractContraptionEntity> extends Abst
}
@Override
public void initLightSectionNotifier(Notifier notifier) {
this.notifier = notifier;
public void setSectionCollector(SectionCollector collector) {
this.sectionCollector = collector;
}
@Override

View file

@ -7,8 +7,8 @@ import com.simibubi.create.content.kinetics.base.SingleRotatingVisual;
public class BacktankVisual extends SingleRotatingVisual<BacktankBlockEntity> {
public BacktankVisual(VisualizationContext context, BacktankBlockEntity blockEntity) {
super(context, blockEntity);
public BacktankVisual(VisualizationContext context, BacktankBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
}
@Override

View file

@ -19,25 +19,20 @@ import net.minecraft.core.Direction;
public class ToolBoxVisual extends AbstractBlockEntityVisual<ToolboxBlockEntity> implements SimpleDynamicVisual {
private final Direction facing;
private TransformedInstance lid;
private TransformedInstance[] drawers;
private final TransformedInstance lid;
private final TransformedInstance[] drawers;
public ToolBoxVisual(VisualizationContext context, ToolboxBlockEntity blockEntity) {
super(context, blockEntity);
public ToolBoxVisual(VisualizationContext context, ToolboxBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
facing = blockState.getValue(ToolboxBlock.FACING)
.getOpposite();
}
@Override
public void init(float pt) {
Instancer<TransformedInstance> drawerModel = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.TOOLBOX_DRAWER));
drawers = new TransformedInstance[]{drawerModel.createInstance(), drawerModel.createInstance()};
lid = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.TOOLBOX_LIDS.get(blockEntity.getColor())))
.createInstance();
super.init(pt);
}
@Override
@ -78,7 +73,7 @@ public class ToolBoxVisual extends AbstractBlockEntityVisual<ToolboxBlockEntity>
}
@Override
public void updateLight() {
public void updateLight(float partialTick) {
relight(pos, drawers);
relight(pos, lid);
}

View file

@ -26,8 +26,8 @@ public class FluidValveVisual extends ShaftVisual<FluidValveBlockEntity> impleme
protected final double yRot;
protected final int pointerRotationOffset;
public FluidValveVisual(VisualizationContext dispatcher, FluidValveBlockEntity blockEntity) {
super(dispatcher, blockEntity);
public FluidValveVisual(VisualizationContext dispatcher, FluidValveBlockEntity blockEntity, float partialTick) {
super(dispatcher, blockEntity, partialTick);
Direction facing = blockState.getValue(FluidValveBlock.FACING);
@ -75,8 +75,8 @@ public class FluidValveVisual extends ShaftVisual<FluidValveBlockEntity> impleme
}
@Override
public void updateLight() {
super.updateLight();
public void updateLight(float partialTick) {
super.updateLight(partialTick);
relight(pos, pointer);
}

View file

@ -12,8 +12,8 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties;
public class PumpCogVisual extends SingleRotatingVisual<PumpBlockEntity> {
public PumpCogVisual(VisualizationContext context, PumpBlockEntity blockEntity) {
super(context, blockEntity);
public PumpCogVisual(VisualizationContext context, PumpBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
}
@Override

View file

@ -6,8 +6,8 @@ import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
public class BackHalfShaftVisual<T extends KineticBlockEntity> extends HalfShaftVisual<T> {
public BackHalfShaftVisual(VisualizationContext context, T blockEntity) {
super(context, blockEntity);
public BackHalfShaftVisual(VisualizationContext context, T blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
}
@Override

View file

@ -9,8 +9,8 @@ import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
public class HalfShaftVisual<T extends KineticBlockEntity> extends SingleRotatingVisual<T> {
public HalfShaftVisual(VisualizationContext context, T blockEntity) {
super(context, blockEntity);
public HalfShaftVisual(VisualizationContext context, T blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
}
@Override

View file

@ -7,8 +7,8 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties;
public class HorizontalHalfShaftVisual<T extends KineticBlockEntity> extends HalfShaftVisual<T> {
public HorizontalHalfShaftVisual(VisualizationContext context, T blockEntity) {
super(context, blockEntity);
public HorizontalHalfShaftVisual(VisualizationContext context, T blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
}
@Override

View file

@ -14,8 +14,8 @@ public abstract class KineticBlockEntityVisual<T extends KineticBlockEntity> ext
protected final Direction.Axis axis;
public KineticBlockEntityVisual(VisualizationContext context, T blockEntity) {
super(context, blockEntity);
public KineticBlockEntityVisual(VisualizationContext context, T blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
axis = (blockState.getBlock() instanceof IRotate irotate) ? irotate.getRotationAxis(blockState) : Axis.Y;
}

View file

@ -46,13 +46,13 @@ public class KineticInstance extends ColoredLitInstance {
if (blockEntity.hasNetwork()) {
setColor(Color.generateFromLong(blockEntity.network));
}else {
setColor(0xFF, 0xFF, 0xFF);
color(0xFF, 0xFF, 0xFF);
}
return this;
}
public KineticInstance setColor(Color c) {
setColor(c.getRed(), c.getGreen(), c.getBlue());
color(c.getRed(), c.getGreen(), c.getBlue());
return this;
}

View file

@ -6,8 +6,8 @@ import com.simibubi.create.foundation.render.VirtualRenderHelper;
public class ShaftVisual<T extends KineticBlockEntity> extends SingleRotatingVisual<T> {
public ShaftVisual(VisualizationContext context, T blockEntity) {
super(context, blockEntity);
public ShaftVisual(VisualizationContext context, T blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
}
@Override

View file

@ -13,16 +13,14 @@ public class SingleRotatingVisual<T extends KineticBlockEntity> extends KineticB
protected RotatingInstance rotatingModel;
public SingleRotatingVisual(VisualizationContext context, T blockEntity) {
super(context, blockEntity);
public SingleRotatingVisual(VisualizationContext context, T blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
}
@Override
public void init(float pt) {
rotatingModel = instancerProvider.instancer(AllInstanceTypes.ROTATING, model())
.createInstance();
setup(rotatingModel);
super.init(pt);
}
@Override
@ -31,7 +29,7 @@ public class SingleRotatingVisual<T extends KineticBlockEntity> extends KineticB
}
@Override
public void updateLight() {
public void updateLight(float partialTick) {
relight(pos, rotatingModel);
}

View file

@ -12,8 +12,6 @@ import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import dev.engine_room.flywheel.lib.box.Box;
import dev.engine_room.flywheel.lib.box.MutableBox;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.kinetics.base.IRotate;
import com.simibubi.create.content.kinetics.base.KineticBlockEntity;
@ -30,6 +28,9 @@ import com.simibubi.create.content.logistics.tunnel.BrassTunnelBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.flywheel.box.Box;
import com.simibubi.create.foundation.utility.flywheel.box.MutableBox;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockPos.MutableBlockPos;

View file

@ -3,6 +3,8 @@ package com.simibubi.create.content.kinetics.belt;
import java.util.ArrayList;
import java.util.function.Consumer;
import dev.engine_room.flywheel.lib.instance.FlatLit;
import org.joml.Quaternionf;
import dev.engine_room.flywheel.api.instance.Instance;
@ -38,8 +40,8 @@ public class BeltVisual extends KineticBlockEntityVisual<BeltBlockEntity> {
protected ArrayList<BeltInstance> keys;
protected RotatingInstance pulleyKey;
public BeltVisual(VisualizationContext context, BeltBlockEntity blockEntity) {
super(context, blockEntity);
public BeltVisual(VisualizationContext context, BeltBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
if (!AllBlocks.BELT.has(blockState))
return;
@ -99,8 +101,8 @@ public class BeltVisual extends KineticBlockEntityVisual<BeltBlockEntity> {
}
@Override
public void updateLight() {
relight(pos, keys.stream());
public void updateLight(float partialTick) {
relight(pos, keys.toArray(FlatLit[]::new));
if (pulleyKey != null) relight(pos, pulleyKey);
}

View file

@ -13,8 +13,8 @@ import net.minecraft.core.Direction;
public class ShaftlessCogwheelVisual extends SingleRotatingVisual<KineticBlockEntity> {
public ShaftlessCogwheelVisual(VisualizationContext context, KineticBlockEntity blockEntity) {
super(context, blockEntity);
public ShaftlessCogwheelVisual(VisualizationContext context, KineticBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
}
@Override

View file

@ -16,15 +16,22 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties;
public class HandCrankVisual extends SingleRotatingVisual<HandCrankBlockEntity> implements SimpleDynamicVisual {
private TransformedInstance crank;
private Direction facing;
private final TransformedInstance crank;
private final Direction facing;
public HandCrankVisual(VisualizationContext modelManager, HandCrankBlockEntity blockEntity) {
super(modelManager, blockEntity);
public HandCrankVisual(VisualizationContext modelManager, HandCrankBlockEntity blockEntity, float partialTick) {
super(modelManager, blockEntity, partialTick);
facing = blockState.getValue(BlockStateProperties.FACING);
Model model = blockEntity.getRenderedHandleInstance();
crank = instancerProvider.instancer(InstanceTypes.TRANSFORMED, model)
.createInstance();
rotateCrank(partialTick);
if (blockEntity.shouldRenderShaft())
setup(rotatingModel);
updateLight(partialTick);
}
@Override
@ -47,17 +54,6 @@ public class HandCrankVisual extends SingleRotatingVisual<HandCrankBlockEntity>
.setChanged();
}
@Override
public void init(float pt) {
rotateCrank(pt);
// FIXME: need to call super.super.init here
if (blockEntity.shouldRenderShaft())
super.init(pt);
updateLight();
}
@Override
protected void _delete() {
if (blockEntity.shouldRenderShaft())
@ -73,9 +69,9 @@ public class HandCrankVisual extends SingleRotatingVisual<HandCrankBlockEntity>
}
@Override
public void updateLight() {
public void updateLight(float partialTick) {
if (blockEntity.shouldRenderShaft())
super.updateLight();
super.updateLight(partialTick);
if (crank != null)
relight(pos, crank);
}

View file

@ -124,9 +124,4 @@ public class DeployerActorVisual extends ActorVisual {
hand.delete();
shaft.delete();
}
@Override
public void init(float partialTick) {
}
}

View file

@ -41,8 +41,8 @@ public class DeployerVisual extends ShaftVisual<DeployerBlockEntity> implements
PartialModel currentHand;
float progress;
public DeployerVisual(VisualizationContext context, DeployerBlockEntity blockEntity) {
super(context, blockEntity);
public DeployerVisual(VisualizationContext context, DeployerBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
facing = blockState.getValue(FACING);
@ -57,16 +57,11 @@ public class DeployerVisual extends ShaftVisual<DeployerBlockEntity> implements
currentHand = this.blockEntity.getHandPose();
hand = instancerProvider.instancer(InstanceTypes.ORIENTED, Models.partial(currentHand)).createInstance();
}
@Override
public void init(float pt) {
progress = getProgress(pt);
progress = getProgress(partialTick);
updateRotation(pole, hand, yRot, xRot, zRot);
updatePosition();
super.init(pt);
}
}
@Override
public void tick(TickableVisual.Context context) {
@ -91,8 +86,8 @@ public class DeployerVisual extends ShaftVisual<DeployerBlockEntity> implements
}
@Override
public void updateLight() {
super.updateLight();
public void updateLight(float partialTick) {
super.updateLight(partialTick);
relight(pos, hand, pole);
}

View file

@ -66,9 +66,4 @@ public class DrillActorVisual extends ActorVisual {
protected void _delete() {
drillHead.delete();
}
@Override
public void init(float partialTick) {
}
}

View file

@ -11,8 +11,8 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties;
public class DrillVisual extends SingleRotatingVisual<DrillBlockEntity> {
public DrillVisual(VisualizationContext context, DrillBlockEntity blockEntity) {
super(context, blockEntity);
public DrillVisual(VisualizationContext context, DrillBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
}
@Override

View file

@ -23,8 +23,8 @@ public class FanVisual extends KineticBlockEntityVisual<EncasedFanBlockEntity> {
final Direction direction;
private final Direction opposite;
public FanVisual(VisualizationContext context, EncasedFanBlockEntity blockEntity) {
super(context, blockEntity);
public FanVisual(VisualizationContext context, EncasedFanBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
direction = blockState.getValue(FACING);
@ -53,7 +53,7 @@ public class FanVisual extends KineticBlockEntityVisual<EncasedFanBlockEntity> {
}
@Override
public void updateLight() {
public void updateLight(float partialTick) {
BlockPos behind = pos.relative(opposite);
relight(behind, shaft);

View file

@ -24,8 +24,8 @@ public class FlywheelVisual extends KineticBlockEntityVisual<FlywheelBlockEntity
protected final TransformedInstance wheel;
protected float lastAngle = Float.NaN;
public FlywheelVisual(VisualizationContext context, FlywheelBlockEntity blockEntity) {
super(context, blockEntity);
public FlywheelVisual(VisualizationContext context, FlywheelBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
shaft = setup(instancerProvider.instancer(AllInstanceTypes.ROTATING, VirtualRenderHelper.blockModel(shaft()))
.createInstance());
@ -70,7 +70,7 @@ public class FlywheelVisual extends KineticBlockEntityVisual<FlywheelBlockEntity
}
@Override
public void updateLight() {
public void updateLight(float partialTick) {
relight(pos, shaft, wheel);
}

View file

@ -7,6 +7,7 @@ import dev.engine_room.flywheel.api.instance.Instance;
import dev.engine_room.flywheel.api.instance.Instancer;
import dev.engine_room.flywheel.api.visual.DynamicVisual;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.lib.instance.FlatLit;
import dev.engine_room.flywheel.lib.instance.InstanceTypes;
import dev.engine_room.flywheel.lib.instance.TransformedInstance;
import dev.engine_room.flywheel.lib.model.Models;
@ -28,12 +29,13 @@ public abstract class GaugeVisual extends ShaftVisual<GaugeBlockEntity> implemen
protected final PoseStack ms = new PoseStack();
protected GaugeVisual(VisualizationContext context, GaugeBlockEntity blockEntity) {
super(context, blockEntity);
protected GaugeVisual(VisualizationContext context, GaugeBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
init(partialTick);
}
@Override
public void init(float pt) {
public void init(float partialTick) {
GaugeBlock gaugeBlock = (GaugeBlock) blockState.getBlock();
Instancer<TransformedInstance> dialModel = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.GAUGE_DIAL));
@ -54,8 +56,6 @@ public abstract class GaugeVisual extends ShaftVisual<GaugeBlockEntity> implemen
face.setupTransform(msr, progress);
}
super.init(pt);
}
private DialFace makeFace(Direction face, Instancer<TransformedInstance> dialModel, Instancer<TransformedInstance> headModel) {
@ -77,11 +77,11 @@ public abstract class GaugeVisual extends ShaftVisual<GaugeBlockEntity> implemen
}
@Override
public void updateLight() {
super.updateLight();
public void updateLight(float partialTick) {
super.updateLight(partialTick);
relight(pos, faces.stream()
.flatMap(Couple::stream));
.flatMap(Couple::stream).toArray(FlatLit[]::new));
}
@Override
@ -155,8 +155,8 @@ public abstract class GaugeVisual extends ShaftVisual<GaugeBlockEntity> implemen
}
public static class Speed extends GaugeVisual {
public Speed(VisualizationContext context, GaugeBlockEntity blockEntity) {
super(context, blockEntity);
public Speed(VisualizationContext context, GaugeBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
}
@Override
@ -166,8 +166,8 @@ public abstract class GaugeVisual extends ShaftVisual<GaugeBlockEntity> implemen
}
public static class Stress extends GaugeVisual {
public Stress(VisualizationContext context, GaugeBlockEntity blockEntity) {
super(context, blockEntity);
public Stress(VisualizationContext context, GaugeBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
}
@Override

View file

@ -7,6 +7,7 @@ import java.util.function.Consumer;
import dev.engine_room.flywheel.api.instance.Instance;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.lib.instance.AbstractInstance;
import dev.engine_room.flywheel.lib.instance.FlatLit;
import dev.engine_room.flywheel.lib.model.Models;
import com.simibubi.create.AllPartialModels;
import com.simibubi.create.content.kinetics.base.KineticBlockEntityVisual;
@ -24,8 +25,8 @@ public class GearboxVisual extends KineticBlockEntityVisual<GearboxBlockEntity>
protected final EnumMap<Direction, RotatingInstance> keys;
protected Direction sourceFacing;
public GearboxVisual(VisualizationContext context, GearboxBlockEntity blockEntity) {
super(context, blockEntity);
public GearboxVisual(VisualizationContext context, GearboxBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
keys = new EnumMap<>(Direction.class);
@ -87,8 +88,8 @@ public class GearboxVisual extends KineticBlockEntityVisual<GearboxBlockEntity>
}
@Override
public void updateLight() {
relight(pos, keys.values().stream());
public void updateLight(float partialTick) {
relight(pos, keys.values().toArray(FlatLit[]::new));
}
@Override

View file

@ -9,6 +9,7 @@ import dev.engine_room.flywheel.api.model.Model;
import dev.engine_room.flywheel.api.visual.DynamicVisual;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.lib.instance.AbstractInstance;
import dev.engine_room.flywheel.lib.instance.FlatLit;
import dev.engine_room.flywheel.lib.instance.InstanceTypes;
import dev.engine_room.flywheel.lib.instance.TransformedInstance;
import dev.engine_room.flywheel.lib.model.Models;
@ -45,8 +46,8 @@ public class ArmVisual extends SingleRotatingVisual<ArmBlockEntity> implements S
private float upperArmAngle = Float.NaN;
private float headAngle = Float.NaN;
public ArmVisual(VisualizationContext context, ArmBlockEntity blockEntity) {
super(context, blockEntity);
public ArmVisual(VisualizationContext context, ArmBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
base = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.ARM_BASE))
.createInstance();
@ -131,12 +132,12 @@ public class ArmVisual extends SingleRotatingVisual<ArmBlockEntity> implements S
ArmRenderer.transformLowerArm(msr, lowerArmAngle);
lowerBody.setTransform(msLocal)
.setColor(color)
.color(color)
.setChanged();
ArmRenderer.transformUpperArm(msr, upperArmAngle);
upperBody.setTransform(msLocal)
.setColor(color)
.color(color)
.setChanged();
ArmRenderer.transformHead(msr, headAngle);
@ -177,15 +178,15 @@ public class ArmVisual extends SingleRotatingVisual<ArmBlockEntity> implements S
claw = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(blockEntity.goggles ? AllPartialModels.ARM_CLAW_BASE_GOGGLES : AllPartialModels.ARM_CLAW_BASE))
.createInstance();
models.add(claw);
updateLight();
updateLight(pt);
animateArm();
}
@Override
public void updateLight() {
super.updateLight();
public void updateLight(float partialTick) {
super.updateLight(partialTick);
relight(pos, models.stream());
relight(pos, models.toArray(FlatLit[]::new));
}
@Override

View file

@ -8,8 +8,8 @@ import com.simibubi.create.content.kinetics.base.SingleRotatingVisual;
public class MillstoneCogVisual extends SingleRotatingVisual<MillstoneBlockEntity> {
public MillstoneCogVisual(VisualizationContext context, MillstoneBlockEntity blockEntity) {
super(context, blockEntity);
public MillstoneCogVisual(VisualizationContext context, MillstoneBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
}
@Override

View file

@ -23,8 +23,8 @@ public class MixerVisual extends EncasedCogVisual implements SimpleDynamicVisual
private final OrientedInstance mixerPole;
private final MechanicalMixerBlockEntity mixer;
public MixerVisual(VisualizationContext context, MechanicalMixerBlockEntity blockEntity) {
super(context, blockEntity, false);
public MixerVisual(VisualizationContext context, MechanicalMixerBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, false, partialTick);
this.mixer = blockEntity;
mixerHead = instancerProvider.instancer(AllInstanceTypes.ROTATING, Models.partial(AllPartialModels.MECHANICAL_MIXER_HEAD))
@ -34,13 +34,8 @@ public class MixerVisual extends EncasedCogVisual implements SimpleDynamicVisual
mixerPole = instancerProvider.instancer(InstanceTypes.ORIENTED, Models.partial(AllPartialModels.MECHANICAL_MIXER_POLE))
.createInstance();
}
@Override
public void init(float pt) {
super.init(pt);
animate(pt);
animate(partialTick);
}
@Override
@ -76,8 +71,8 @@ public class MixerVisual extends EncasedCogVisual implements SimpleDynamicVisual
}
@Override
public void updateLight() {
super.updateLight();
public void updateLight(float partialTick) {
super.updateLight(partialTick);
relight(pos.below(), mixerHead);
relight(pos, mixerPole);

View file

@ -20,8 +20,8 @@ public class PressVisual extends ShaftVisual<MechanicalPressBlockEntity> impleme
private final OrientedInstance pressHead;
public PressVisual(VisualizationContext context, MechanicalPressBlockEntity blockEntity) {
super(context, blockEntity);
public PressVisual(VisualizationContext context, MechanicalPressBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
pressHead = instancerProvider.instancer(InstanceTypes.ORIENTED, Models.partial(AllPartialModels.MECHANICAL_PRESS_HEAD))
.createInstance();
@ -30,13 +30,8 @@ public class PressVisual extends ShaftVisual<MechanicalPressBlockEntity> impleme
.rotationDegrees(AngleHelper.horizontalAngle(blockState.getValue(MechanicalPressBlock.HORIZONTAL_FACING)));
pressHead.setRotation(q);
}
@Override
public void init(float pt) {
super.init(pt);
transformModels(pt);
transformModels(partialTick);
}
@Override
@ -59,8 +54,8 @@ public class PressVisual extends ShaftVisual<MechanicalPressBlockEntity> impleme
}
@Override
public void updateLight() {
super.updateLight();
public void updateLight(float partialTick) {
super.updateLight(partialTick);
relight(pos, pressHead);
}

View file

@ -14,8 +14,8 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties;
public class SawVisual extends SingleRotatingVisual<SawBlockEntity> {
public SawVisual(VisualizationContext context, SawBlockEntity blockEntity) {
super(context, blockEntity);
public SawVisual(VisualizationContext context, SawBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
}
@Override

View file

@ -24,12 +24,13 @@ public class BracketedKineticBlockEntityVisual extends SingleRotatingVisual<Brac
protected RotatingInstance additionalShaft;
public BracketedKineticBlockEntityVisual(VisualizationContext context, BracketedKineticBlockEntity blockEntity) {
super(context, blockEntity);
public BracketedKineticBlockEntityVisual(VisualizationContext context, BracketedKineticBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
init(partialTick);
}
@Override
public void init(float pt) {
public void init(float partialTick) {
if (ICogWheel.isLargeCog(blockEntity.getBlockState())) {
// Large cogs sometimes have to offset their teeth by 11.25 degrees in order to
// mesh properly
@ -45,7 +46,6 @@ public class BracketedKineticBlockEntityVisual extends SingleRotatingVisual<Brac
additionalShaft.setRotationOffset(offset)
.setChanged();
}
super.init(pt);
}
@Override
@ -77,8 +77,8 @@ public class BracketedKineticBlockEntityVisual extends SingleRotatingVisual<Brac
}
@Override
public void updateLight() {
super.updateLight();
public void updateLight(float partialTick) {
super.updateLight(partialTick);
if (additionalShaft != null)
relight(pos, additionalShaft);
}

View file

@ -29,27 +29,28 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties;
public class EncasedCogVisual extends KineticBlockEntityVisual<KineticBlockEntity> {
private boolean large;
private final boolean large;
protected RotatingInstance rotatingModel;
protected Optional<RotatingInstance> rotatingTopShaft;
protected Optional<RotatingInstance> rotatingBottomShaft;
public static EncasedCogVisual small(VisualizationContext modelManager, KineticBlockEntity blockEntity) {
return new EncasedCogVisual(modelManager, blockEntity, false);
public static EncasedCogVisual small(VisualizationContext modelManager, KineticBlockEntity blockEntity, float partialTick) {
return new EncasedCogVisual(modelManager, blockEntity, false, partialTick);
}
public static EncasedCogVisual large(VisualizationContext modelManager, KineticBlockEntity blockEntity) {
return new EncasedCogVisual(modelManager, blockEntity, true);
public static EncasedCogVisual large(VisualizationContext modelManager, KineticBlockEntity blockEntity, float partialTick) {
return new EncasedCogVisual(modelManager, blockEntity, true, partialTick);
}
public EncasedCogVisual(VisualizationContext modelManager, KineticBlockEntity blockEntity, boolean large) {
super(modelManager, blockEntity);
public EncasedCogVisual(VisualizationContext modelManager, KineticBlockEntity blockEntity, boolean large, float partialTick) {
super(modelManager, blockEntity, partialTick);
this.large = large;
init(partialTick);
}
@Override
public void init(float pt) {
public void init(float partialTick) {
var instancer = instancerProvider.instancer(AllInstanceTypes.ROTATING, getCogModel());
rotatingModel = setup(instancer.createInstance());
@ -72,8 +73,6 @@ public class EncasedCogVisual extends KineticBlockEntityVisual<KineticBlockEntit
else
rotatingBottomShaft = Optional.of(data);
}
super.init(pt);
}
@Override
@ -84,7 +83,7 @@ public class EncasedCogVisual extends KineticBlockEntityVisual<KineticBlockEntit
}
@Override
public void updateLight() {
public void updateLight(float partialTick) {
relight(pos, rotatingModel);
rotatingTopShaft.ifPresent(d -> relight(pos, d));
rotatingBottomShaft.ifPresent(d -> relight(pos, d));

View file

@ -24,8 +24,8 @@ public class SteamEngineVisual extends AbstractBlockEntityVisual<SteamEngineBloc
protected final TransformedInstance linkage;
protected final TransformedInstance connector;
public SteamEngineVisual(VisualizationContext context, SteamEngineBlockEntity blockEntity) {
super(context, blockEntity);
public SteamEngineVisual(VisualizationContext context, SteamEngineBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
piston = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.ENGINE_PISTON))
.createInstance();
@ -91,7 +91,7 @@ public class SteamEngineVisual extends AbstractBlockEntityVisual<SteamEngineBloc
}
@Override
public void updateLight() {
public void updateLight(float partialTick) {
relight(pos, piston, linkage, connector);
}

View file

@ -6,6 +6,7 @@ import java.util.function.Consumer;
import dev.engine_room.flywheel.api.instance.Instance;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.lib.instance.AbstractInstance;
import dev.engine_room.flywheel.lib.instance.FlatLit;
import dev.engine_room.flywheel.lib.model.Models;
import com.simibubi.create.AllPartialModels;
import com.simibubi.create.content.kinetics.base.IRotate;
@ -21,8 +22,8 @@ public class SplitShaftVisual extends KineticBlockEntityVisual<SplitShaftBlockEn
protected final ArrayList<RotatingInstance> keys;
public SplitShaftVisual(VisualizationContext modelManager, SplitShaftBlockEntity blockEntity) {
super(modelManager, blockEntity);
public SplitShaftVisual(VisualizationContext modelManager, SplitShaftBlockEntity blockEntity, float partialTick) {
super(modelManager, blockEntity, partialTick);
keys = new ArrayList<>(2);
@ -52,8 +53,8 @@ public class SplitShaftVisual extends KineticBlockEntityVisual<SplitShaftBlockEn
}
@Override
public void updateLight() {
relight(pos, keys.stream());
public void updateLight(float partialTick) {
relight(pos, keys.toArray(FlatLit[]::new));
}
@Override

View file

@ -25,23 +25,19 @@ public class WaterWheelVisual<T extends WaterWheelBlockEntity> extends KineticBl
protected BlockState lastMaterial;
protected RotatingInstance rotatingModel;
public WaterWheelVisual(VisualizationContext context, T blockEntity, boolean large) {
super(context, blockEntity);
public WaterWheelVisual(VisualizationContext context, T blockEntity, boolean large, float partialTick) {
super(context, blockEntity, partialTick);
this.large = large;
}
public static <T extends WaterWheelBlockEntity> WaterWheelVisual<T> standard(VisualizationContext context, T blockEntity) {
return new WaterWheelVisual<>(context, blockEntity, false);
}
public static <T extends WaterWheelBlockEntity> WaterWheelVisual<T> large(VisualizationContext context, T blockEntity) {
return new WaterWheelVisual<>(context, blockEntity, true);
}
@Override
public void init(float pt) {
setupInstance();
super.init(pt);
}
public static <T extends WaterWheelBlockEntity> WaterWheelVisual<T> standard(VisualizationContext context, T blockEntity, float partialTick) {
return new WaterWheelVisual<>(context, blockEntity, false, partialTick);
}
public static <T extends WaterWheelBlockEntity> WaterWheelVisual<T> large(VisualizationContext context, T blockEntity, float partialTick) {
return new WaterWheelVisual<>(context, blockEntity, true, partialTick);
}
private void setupInstance() {
@ -62,7 +58,7 @@ public class WaterWheelVisual<T extends WaterWheelBlockEntity> extends KineticBl
}
@Override
public void updateLight() {
public void updateLight(float partialTick) {
relight(pos, rotatingModel);
}

View file

@ -18,17 +18,12 @@ public class EjectorVisual extends ShaftVisual<EjectorBlockEntity> implements Si
private float lastProgress = Float.NaN;
public EjectorVisual(VisualizationContext dispatcher, EjectorBlockEntity blockEntity) {
super(dispatcher, blockEntity);
public EjectorVisual(VisualizationContext dispatcher, EjectorBlockEntity blockEntity, float partialTick) {
super(dispatcher, blockEntity, partialTick);
plate = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.EJECTOR_TOP)).createInstance();
}
@Override
public void init(float pt) {
pivotPlate(getLidProgress(pt));
super.init(pt);
pivotPlate(getLidProgress(partialTick));
}
@Override
@ -44,8 +39,8 @@ public class EjectorVisual extends ShaftVisual<EjectorBlockEntity> implements Si
}
@Override
public void updateLight() {
super.updateLight();
public void updateLight(float partialTick) {
super.updateLight(partialTick);
relight(pos, plate);
}

View file

@ -8,6 +8,7 @@ import dev.engine_room.flywheel.api.instance.Instancer;
import dev.engine_room.flywheel.api.visual.DynamicVisual;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.lib.instance.AbstractInstance;
import dev.engine_room.flywheel.lib.instance.FlatLit;
import dev.engine_room.flywheel.lib.model.Models;
import dev.engine_room.flywheel.lib.model.baked.PartialModel;
import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual;
@ -24,8 +25,8 @@ public class FunnelVisual extends AbstractBlockEntityVisual<FunnelBlockEntity> i
private final ArrayList<FlapInstance> flaps;
public FunnelVisual(VisualizationContext context, FunnelBlockEntity blockEntity) {
super(context, blockEntity);
public FunnelVisual(VisualizationContext context, FunnelBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
flaps = new ArrayList<>(4);
@ -76,9 +77,9 @@ public class FunnelVisual extends AbstractBlockEntityVisual<FunnelBlockEntity> i
}
@Override
public void updateLight() {
public void updateLight(float partialTick) {
if (flaps != null)
relight(pos, flaps.stream());
relight(pos, flaps.toArray(FlatLit[]::new));
}
@Override

View file

@ -11,6 +11,7 @@ import dev.engine_room.flywheel.api.instance.Instancer;
import dev.engine_room.flywheel.api.visual.DynamicVisual;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.lib.instance.AbstractInstance;
import dev.engine_room.flywheel.lib.instance.FlatLit;
import dev.engine_room.flywheel.lib.model.Models;
import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual;
import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual;
@ -26,8 +27,10 @@ public class BeltTunnelVisual extends AbstractBlockEntityVisual<BeltTunnelBlockE
private final Map<Direction, ArrayList<FlapInstance>> tunnelFlaps = new EnumMap<>(Direction.class);
public BeltTunnelVisual(VisualizationContext context, BeltTunnelBlockEntity blockEntity) {
super(context, blockEntity);
public BeltTunnelVisual(VisualizationContext context, BeltTunnelBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
setupFlaps(partialTick);
}
private void setupFlaps(float partialTick) {
@ -69,13 +72,6 @@ public class BeltTunnelVisual extends AbstractBlockEntityVisual<BeltTunnelBlockE
});
}
@Override
public void init(float partialTick) {
setupFlaps(partialTick);
super.init(partialTick);
}
@Override
public void update(float partialTick) {
super.update(partialTick);
@ -100,8 +96,8 @@ public class BeltTunnelVisual extends AbstractBlockEntityVisual<BeltTunnelBlockE
}
@Override
public void updateLight() {
relight(pos, tunnelFlaps.values().stream().flatMap(Collection::stream));
public void updateLight(float partialTick) {
relight(pos, tunnelFlaps.values().stream().flatMap(Collection::stream).toArray(FlatLit[]::new));
}
@Override

View file

@ -27,8 +27,8 @@ public class AnalogLeverVisual extends AbstractBlockEntityVisual<AnalogLeverBloc
final float rX;
final float rY;
public AnalogLeverVisual(VisualizationContext context, AnalogLeverBlockEntity blockEntity) {
super(context, blockEntity);
public AnalogLeverVisual(VisualizationContext context, AnalogLeverBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
handle = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.ANALOG_LEVER_HANDLE))
.createInstance();
@ -38,11 +38,6 @@ public class AnalogLeverVisual extends AbstractBlockEntityVisual<AnalogLeverBloc
AttachFace face = blockState.getValue(AnalogLeverBlock.FACE);
rX = face == AttachFace.FLOOR ? 0 : face == AttachFace.WALL ? 90 : 180;
rY = AngleHelper.horizontalAngle(blockState.getValue(AnalogLeverBlock.FACING));
}
@Override
public void init(float partialTick) {
super.init(partialTick);
transform(indicator.loadIdentity());
@ -58,7 +53,7 @@ public class AnalogLeverVisual extends AbstractBlockEntityVisual<AnalogLeverBloc
protected void animateLever(float pt) {
float state = blockEntity.clientState.getValue(pt);
indicator.setColor(Color.mixColors(0x2C0300, 0xCD0000, state / 15f));
indicator.color(Color.mixColors(0x2C0300, 0xCD0000, state / 15f));
indicator.setChanged();
float angle = (float) ((state / 15) * 90 / 180 * Math.PI);
@ -76,7 +71,7 @@ public class AnalogLeverVisual extends AbstractBlockEntityVisual<AnalogLeverBloc
}
@Override
public void updateLight() {
public void updateLight(float partialTick) {
relight(pos, handle, indicator);
}

View file

@ -19,14 +19,14 @@ public class BrassDiodeVisual extends AbstractBlockEntityVisual<BrassDiodeBlockE
protected int previousState;
public BrassDiodeVisual(VisualizationContext context, BrassDiodeBlockEntity blockEntity) {
super(context, blockEntity);
public BrassDiodeVisual(VisualizationContext context, BrassDiodeBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
indicator = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.FLEXPEATER_INDICATOR)).createInstance();
indicator.loadIdentity()
.translate(getVisualPosition())
.setColor(getColor())
.color(getColor())
.setChanged();
previousState = blockEntity.state;
@ -36,14 +36,14 @@ public class BrassDiodeVisual extends AbstractBlockEntityVisual<BrassDiodeBlockE
public void tick(TickableVisual.Context context) {
if (previousState == blockEntity.state) return;
indicator.setColor(getColor());
indicator.color(getColor());
indicator.setChanged();
previousState = blockEntity.state;
}
@Override
public void updateLight() {
public void updateLight(float partialTick) {
relight(pos, indicator);
}

View file

@ -21,8 +21,8 @@ public class SchematicannonVisual extends AbstractBlockEntityVisual<Schematicann
private final TransformedInstance connector;
private final TransformedInstance pipe;
public SchematicannonVisual(VisualizationContext context, SchematicannonBlockEntity blockEntity) {
super(context, blockEntity);
public SchematicannonVisual(VisualizationContext context, SchematicannonBlockEntity blockEntity, float partialTick) {
super(context, blockEntity, partialTick);
connector = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.SCHEMATICANNON_CONNECTOR)).createInstance();
pipe = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.SCHEMATICANNON_PIPE)).createInstance();
@ -70,7 +70,7 @@ public class SchematicannonVisual extends AbstractBlockEntityVisual<Schematicann
}
@Override
public void updateLight() {
public void updateLight(float partialTick) {
relight(pos, connector, pipe);
}

View file

@ -20,8 +20,8 @@ public class CarriageContraptionVisual extends ContraptionVisual<CarriageContrap
private Couple<BogeyVisual> bogeys;
private Couple<Boolean> bogeyHidden;
public CarriageContraptionVisual(VisualizationContext context, CarriageContraptionEntity entity) {
super(context, entity);
public CarriageContraptionVisual(VisualizationContext context, CarriageContraptionEntity entity, float partialTick) {
super(context, entity, partialTick);
bogeyHidden = Couple.create(() -> false);
entity.bindInstance(this);
}
@ -33,7 +33,7 @@ public class CarriageContraptionVisual extends ContraptionVisual<CarriageContrap
if (carriage != null) {
bogeys = carriage.bogeys.mapNotNullWithParam((bogey, manager) -> bogey.getStyle()
.createVisual(bogey, bogey.type.getSize(), manager), visualizationContext);
updateLight();
updateLight(pt);
}
super.init(pt);
@ -86,8 +86,8 @@ public class CarriageContraptionVisual extends ContraptionVisual<CarriageContrap
ms.popPose();
}
public void updateLight() {
super.updateLight();
public void updateLight(float partialTick) {
super.updateLight(partialTick);
if (bogeys == null)
return;

View file

@ -23,6 +23,9 @@ import com.simibubi.create.content.trains.track.BezierConnection.SegmentAngles;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Iterate;
import it.unimi.dsi.fastutil.longs.LongArraySet;
import it.unimi.dsi.fastutil.longs.LongSet;
import it.unimi.dsi.fastutil.longs.LongSets;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.Level;
@ -30,21 +33,16 @@ import net.minecraft.world.level.LightLayer;
public class TrackVisual extends AbstractBlockEntityVisual<TrackBlockEntity> {
private List<BezierTrackVisual> visuals;
private final List<BezierTrackVisual> visuals;
public TrackVisual(VisualizationContext context, TrackBlockEntity track) {
super(context, track);
}
public TrackVisual(VisualizationContext context, TrackBlockEntity track, float partialTick) {
super(context, track, partialTick);
@Override
public void init(float partialTick) {
visuals = blockEntity.connections.values()
.stream()
.map(this::createInstance)
.filter(Objects::nonNull)
.toList();
super.init(partialTick);
}
@Override
@ -53,12 +51,11 @@ public class TrackVisual extends AbstractBlockEntityVisual<TrackBlockEntity> {
return;
_delete();
init(pt);
notifier.notifySectionsChanged();
lightSections.sections(collectLightSections());
}
@Override
public void updateLight() {
public void updateLight(float partialTick) {
if (visuals == null)
return;
visuals.forEach(BezierTrackVisual::updateLight);
@ -78,10 +75,11 @@ public class TrackVisual extends AbstractBlockEntityVisual<TrackBlockEntity> {
visuals.forEach(BezierTrackVisual::delete);
}
@Override
public void collectLightSections(LongConsumer consumer) {
public LongSet collectLightSections() {
LongSet longSet = new LongArraySet();
if (blockEntity.connections.isEmpty()) {
return;
return LongSet.of();
}
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
@ -99,7 +97,9 @@ public class TrackVisual extends AbstractBlockEntityVisual<TrackBlockEntity> {
}
SectionPos.betweenClosedStream(SectionPos.blockToSectionCoord(minX), SectionPos.blockToSectionCoord(minY), SectionPos.blockToSectionCoord(minZ), SectionPos.blockToSectionCoord(maxX), SectionPos.blockToSectionCoord(maxY), SectionPos.blockToSectionCoord(maxZ))
.mapToLong(SectionPos::asLong)
.forEach(consumer);
.forEach(longSet::add);
return longSet;
}
@Override

View file

@ -36,8 +36,8 @@ public class AllInstanceTypes {
MemoryUtil.memPutByte(ptr + 1, instance.g);
MemoryUtil.memPutByte(ptr + 2, instance.b);
MemoryUtil.memPutByte(ptr + 3, instance.a);
MemoryUtil.memPutShort(ptr + 4, (short) (instance.packedLight & 0xFFFF));
MemoryUtil.memPutShort(ptr + 6, (short) (instance.packedLight >> 16 & 0xFFFF));
MemoryUtil.memPutShort(ptr + 4, (short) (instance.light & 0xFFFF));
MemoryUtil.memPutShort(ptr + 6, (short) (instance.light >> 16 & 0xFFFF));
MemoryUtil.memPutInt(ptr + 8, instance.overlay);
MemoryUtil.memPutFloat(ptr + 12, instance.x);
MemoryUtil.memPutFloat(ptr + 16, instance.y);
@ -70,8 +70,8 @@ public class AllInstanceTypes {
MemoryUtil.memPutByte(ptr + 1, instance.g);
MemoryUtil.memPutByte(ptr + 2, instance.b);
MemoryUtil.memPutByte(ptr + 3, instance.a);
MemoryUtil.memPutShort(ptr + 4, (short) (instance.packedLight & 0xFFFF));
MemoryUtil.memPutShort(ptr + 6, (short) (instance.packedLight >> 16 & 0xFFFF));
MemoryUtil.memPutShort(ptr + 4, (short) (instance.light & 0xFFFF));
MemoryUtil.memPutShort(ptr + 6, (short) (instance.light >> 16 & 0xFFFF));
MemoryUtil.memPutInt(ptr + 8, instance.overlay);
MemoryUtil.memPutFloat(ptr + 12, instance.x);
MemoryUtil.memPutFloat(ptr + 16, instance.y);

View file

@ -0,0 +1,142 @@
package com.simibubi.create.foundation.utility.flywheel.box;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.AABB;
public interface Box {
int getMinX();
int getMinY();
int getMinZ();
int getMaxX();
int getMaxY();
int getMaxZ();
default int sizeX() {
return getMaxX() - getMinX();
}
default int sizeY() {
return getMaxY() - getMinY();
}
default int sizeZ() {
return getMaxZ() - getMinZ();
}
default int volume() {
return sizeX() * sizeY() * sizeZ();
}
default boolean isEmpty() {
// if any dimension has side length 0 this box contains no volume
return getMinX() == getMaxX() || getMinY() == getMaxY() || getMinZ() == getMaxZ();
}
default boolean sameAs(Box other) {
return getMinX() == other.getMinX() && getMinY() == other.getMinY() && getMinZ() == other.getMinZ() && getMaxX() == other.getMaxX() && getMaxY() == other.getMaxY() && getMaxZ() == other.getMaxZ();
}
default boolean sameAs(Box other, int margin) {
return getMinX() == other.getMinX() - margin &&
getMinY() == other.getMinY() - margin &&
getMinZ() == other.getMinZ() - margin &&
getMaxX() == other.getMaxX() + margin &&
getMaxY() == other.getMaxY() + margin &&
getMaxZ() == other.getMaxZ() + margin;
}
default boolean sameAs(AABB other) {
return getMinX() == Math.floor(other.minX)
&& getMinY() == Math.floor(other.minY)
&& getMinZ() == Math.floor(other.minZ)
&& getMaxX() == Math.ceil(other.maxX)
&& getMaxY() == Math.ceil(other.maxY)
&& getMaxZ() == Math.ceil(other.maxZ);
}
default boolean intersects(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
return this.getMinX() < maxX && this.getMaxX() > minX && this.getMinY() < maxY && this.getMaxY() > minY && this.getMinZ() < maxZ && this.getMaxZ() > minZ;
}
default boolean intersects(Box other) {
return this.intersects(other.getMinX(), other.getMinY(), other.getMinZ(), other.getMaxX(), other.getMaxY(), other.getMaxZ());
}
default boolean contains(int x, int y, int z) {
return x >= getMinX()
&& x <= getMaxX()
&& y >= getMinY()
&& y <= getMaxY()
&& z >= getMinZ()
&& z <= getMaxZ();
}
default boolean contains(Box other) {
return other.getMinX() >= this.getMinX()
&& other.getMaxX() <= this.getMaxX()
&& other.getMinY() >= this.getMinY()
&& other.getMaxY() <= this.getMaxY()
&& other.getMinZ() >= this.getMinZ()
&& other.getMaxZ() <= this.getMaxZ();
}
default void forEachContained(CoordinateConsumer func) {
int minX = getMinX();
int minY = getMinY();
int minZ = getMinZ();
int maxX = getMaxX();
int maxY = getMaxY();
int maxZ = getMaxZ();
for (int x = minX; x < maxX; x++) {
for (int y = minY; y < maxY; y++) {
for (int z = minZ; z < maxZ; z++) {
func.accept(x, y, z);
}
}
}
}
default boolean hasPowerOf2Sides() {
// this is only true if all individual side lengths are powers of 2
return Mth.isPowerOfTwo(volume());
}
default MutableBox union(Box other) {
int minX = Math.min(this.getMinX(), other.getMinX());
int minY = Math.min(this.getMinY(), other.getMinY());
int minZ = Math.min(this.getMinZ(), other.getMinZ());
int maxX = Math.max(this.getMaxX(), other.getMaxX());
int maxY = Math.max(this.getMaxY(), other.getMaxY());
int maxZ = Math.max(this.getMaxZ(), other.getMaxZ());
return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
}
default MutableBox intersect(Box other) {
int minX = Math.max(this.getMinX(), other.getMinX());
int minY = Math.max(this.getMinY(), other.getMinY());
int minZ = Math.max(this.getMinZ(), other.getMinZ());
int maxX = Math.min(this.getMaxX(), other.getMaxX());
int maxY = Math.min(this.getMaxY(), other.getMaxY());
int maxZ = Math.min(this.getMaxZ(), other.getMaxZ());
return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
}
default AABB toAABB() {
return new AABB(getMinX(), getMinY(), getMinZ(), getMaxX(), getMaxY(), getMaxZ());
}
default MutableBox copy() {
return new MutableBox(getMinX(), getMinY(), getMinZ(), getMaxX(), getMaxY(), getMaxZ());
}
@FunctionalInterface
interface CoordinateConsumer {
void accept(int x, int y, int z);
}
}

View file

@ -0,0 +1,329 @@
package com.simibubi.create.foundation.utility.flywheel.box;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.SectionPos;
import net.minecraft.core.Vec3i;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.AABB;
import java.util.Collection;
public class MutableBox implements Box {
protected int minX;
protected int minY;
protected int minZ;
protected int maxX;
protected int maxY;
protected int maxZ;
public MutableBox() {
}
public MutableBox(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
this.minX = minX;
this.minY = minY;
this.minZ = minZ;
this.maxX = maxX;
this.maxY = maxY;
this.maxZ = maxZ;
}
public static MutableBox from(AABB aabb) {
int minX = (int) Math.floor(aabb.minX);
int minY = (int) Math.floor(aabb.minY);
int minZ = (int) Math.floor(aabb.minZ);
int maxX = (int) Math.ceil(aabb.maxX);
int maxY = (int) Math.ceil(aabb.maxY);
int maxZ = (int) Math.ceil(aabb.maxZ);
return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
}
public static MutableBox from(Vec3i pos) {
return new MutableBox(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1);
}
public static MutableBox from(SectionPos pos) {
return new MutableBox(pos.minBlockX(), pos.minBlockY(), pos.minBlockZ(), pos.maxBlockX() + 1, pos.maxBlockY() + 1, pos.maxBlockZ() + 1);
}
public static MutableBox from(Vec3i start, Vec3i end) {
return new MutableBox(start.getX(), start.getY(), start.getZ(), end.getX() + 1, end.getY() + 1, end.getZ() + 1);
}
public static MutableBox ofRadius(int radius) {
return new MutableBox(-radius, -radius, -radius, radius + 1, radius + 1, radius + 1);
}
public static Box containingAll(Collection<BlockPos> positions) {
if (positions.isEmpty()) {
return new MutableBox();
}
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int minZ = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int maxY = Integer.MIN_VALUE;
int maxZ = Integer.MIN_VALUE;
for (BlockPos pos : positions) {
minX = Math.min(minX, pos.getX());
minY = Math.min(minY, pos.getY());
minZ = Math.min(minZ, pos.getZ());
maxX = Math.max(maxX, pos.getX());
maxY = Math.max(maxY, pos.getY());
maxZ = Math.max(maxZ, pos.getZ());
}
return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ);
}
@Override
public int getMinX() {
return minX;
}
@Override
public int getMinY() {
return minY;
}
@Override
public int getMinZ() {
return minZ;
}
@Override
public int getMaxX() {
return maxX;
}
@Override
public int getMaxY() {
return maxY;
}
@Override
public int getMaxZ() {
return maxZ;
}
public void setMinX(int minX) {
this.minX = minX;
}
public void setMinY(int minY) {
this.minY = minY;
}
public MutableBox setMinZ(int minZ) {
this.minZ = minZ;
return this;
}
public void setMaxX(int maxX) {
this.maxX = maxX;
}
public void setMaxY(int maxY) {
this.maxY = maxY;
}
public void setMaxZ(int maxZ) {
this.maxZ = maxZ;
}
public void setMin(int x, int y, int z) {
minX = x;
minY = y;
minZ = z;
}
public void setMax(int x, int y, int z) {
maxX = x;
maxY = y;
maxZ = z;
}
public void setMin(Vec3i v) {
setMin(v.getX(), v.getY(), v.getZ());
}
public void setMax(Vec3i v) {
setMax(v.getX(), v.getY(), v.getZ());
}
public void assign(Box other) {
minX = other.getMinX();
minY = other.getMinY();
minZ = other.getMinZ();
maxX = other.getMaxX();
maxY = other.getMaxY();
maxZ = other.getMaxZ();
}
public void assign(AABB other) {
minX = (int) Math.floor(other.minX);
minY = (int) Math.floor(other.minY);
minZ = (int) Math.floor(other.minZ);
maxX = (int) Math.ceil(other.maxX);
maxY = (int) Math.ceil(other.maxY);
maxZ = (int) Math.ceil(other.maxZ);
}
public void assign(Vec3i start, Vec3i end) {
minX = start.getX();
minY = start.getY();
minZ = start.getZ();
maxX = end.getX() + 1;
maxY = end.getY() + 1;
maxZ = end.getZ() + 1;
}
public void unionAssign(Box other) {
minX = Math.min(this.minX, other.getMinX());
minY = Math.min(this.minY, other.getMinY());
minZ = Math.min(this.minZ, other.getMinZ());
maxX = Math.max(this.maxX, other.getMaxX());
maxY = Math.max(this.maxY, other.getMaxY());
maxZ = Math.max(this.maxZ, other.getMaxZ());
}
public void unionAssign(AABB other) {
minX = Math.min(this.minX, (int) Math.floor(other.minX));
minY = Math.min(this.minY, (int) Math.floor(other.minY));
minZ = Math.min(this.minZ, (int) Math.floor(other.minZ));
maxX = Math.max(this.maxX, (int) Math.ceil(other.maxX));
maxY = Math.max(this.maxY, (int) Math.ceil(other.maxY));
maxZ = Math.max(this.maxZ, (int) Math.ceil(other.maxZ));
}
public void intersectAssign(Box other) {
minX = Math.max(this.minX, other.getMinX());
minY = Math.max(this.minY, other.getMinY());
minZ = Math.max(this.minZ, other.getMinZ());
maxX = Math.min(this.maxX, other.getMaxX());
maxY = Math.min(this.maxY, other.getMaxY());
maxZ = Math.min(this.maxZ, other.getMaxZ());
}
public void fixMinMax() {
int minX = Math.min(this.minX, this.maxX);
int minY = Math.min(this.minY, this.maxY);
int minZ = Math.min(this.minZ, this.maxZ);
int maxX = Math.max(this.minX, this.maxX);
int maxY = Math.max(this.minY, this.maxY);
int maxZ = Math.max(this.minZ, this.maxZ);
this.minX = minX;
this.minY = minY;
this.minZ = minZ;
this.maxX = maxX;
this.maxY = maxY;
this.maxZ = maxZ;
}
public void translate(int x, int y, int z) {
minX = minX + x;
maxX = maxX + x;
minY = minY + y;
maxY = maxY + y;
minZ = minZ + z;
maxZ = maxZ + z;
}
public void translate(Vec3i by) {
translate(by.getX(), by.getY(), by.getZ());
}
public void grow(int x, int y, int z) {
minX = minX - x;
minY = minY - y;
minZ = minZ - z;
maxX = maxX + x;
maxY = maxY + y;
maxZ = maxZ + z;
}
public void grow(int s) {
this.grow(s, s, s);
}
/**
* Grow this box to have power of 2 side lengths, scaling from the minimum coords.
*/
public void nextPowerOf2() {
int sizeX = Mth.smallestEncompassingPowerOfTwo(sizeX());
int sizeY = Mth.smallestEncompassingPowerOfTwo(sizeY());
int sizeZ = Mth.smallestEncompassingPowerOfTwo(sizeZ());
maxX = minX + sizeX;
maxY = minY + sizeY;
maxZ = minZ + sizeZ;
}
/**
* Grow this box to have power of 2 side length, scaling from the center.
*/
public void nextPowerOf2Centered() {
int sizeX = sizeX();
int sizeY = sizeY();
int sizeZ = sizeZ();
int newSizeX = Mth.smallestEncompassingPowerOfTwo(sizeX);
int newSizeY = Mth.smallestEncompassingPowerOfTwo(sizeY);
int newSizeZ = Mth.smallestEncompassingPowerOfTwo(sizeZ);
int diffX = newSizeX - sizeX;
int diffY = newSizeY - sizeY;
int diffZ = newSizeZ - sizeZ;
minX = minX - diffX / 2; // floor division for the minimums
minY = minY - diffY / 2;
minZ = minZ - diffZ / 2;
maxX = maxX + (diffX + 1) / 2; // ceiling divison for the maximums
maxY = maxY + (diffY + 1) / 2;
maxZ = maxZ + (diffZ + 1) / 2;
}
public void mirrorAbout(Direction.Axis axis) {
Vec3i axisVec = Direction.get(Direction.AxisDirection.POSITIVE, axis)
.getNormal();
int flipX = axisVec.getX() - 1;
int flipY = axisVec.getY() - 1;
int flipZ = axisVec.getZ() - 1;
int maxX = this.maxX * flipX;
int maxY = this.maxY * flipY;
int maxZ = this.maxZ * flipZ;
this.maxX = this.minX * flipX;
this.maxY = this.minY * flipY;
this.maxZ = this.minZ * flipZ;
this.minX = maxX;
this.minY = maxY;
this.minZ = maxZ;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (!(o instanceof Box that)) return false;
return this.sameAs(that);
}
@Override
public int hashCode() {
int result = minX;
result = 31 * result + minY;
result = 31 * result + minZ;
result = 31 * result + maxX;
result = 31 * result + maxY;
result = 31 * result + maxZ;
return result;
}
@Override
public String toString() {
return "(" + minX + ", " + minY + ", " + minZ + ")->(" + maxX + ", " + maxY + ", " + maxZ + ')';
}
}

View file

@ -0,0 +1,219 @@
package com.simibubi.create.foundation.utility.flywheel.light;
import com.simibubi.create.foundation.utility.flywheel.box.Box;
import com.simibubi.create.foundation.utility.flywheel.box.MutableBox;
import dev.engine_room.flywheel.lib.memory.MemoryBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.LightLayer;
import org.lwjgl.system.MemoryUtil;
public class LightVolume implements Box {
protected final BlockAndTintGetter level;
protected final MutableBox box = new MutableBox();
protected MemoryBlock lightData;
public LightVolume(BlockAndTintGetter level, Box sampleVolume) {
this.level = level;
this.setBox(sampleVolume);
this.lightData = MemoryBlock.malloc(this.box.volume() * 2);
}
public Box getVolume() {
return box;
}
@Override
public int getMinX() {
return box.getMinX();
}
@Override
public int getMinY() {
return box.getMinY();
}
@Override
public int getMinZ() {
return box.getMinZ();
}
@Override
public int getMaxX() {
return box.getMaxX();
}
@Override
public int getMaxY() {
return box.getMaxY();
}
@Override
public int getMaxZ() {
return box.getMaxZ();
}
public boolean isInvalid() {
return lightData == null;
}
protected void setBox(Box box) {
this.box.assign(box);
}
public short getPackedLight(int x, int y, int z) {
if (box.contains(x, y, z)) {
return MemoryUtil.memGetShort(levelPosToPtr(x, y, z));
} else {
return 0;
}
}
public void move(Box newSampleVolume) {
if (lightData == null) return;
setBox(newSampleVolume);
int neededCapacity = box.volume() * 2;
if (neededCapacity > lightData.size()) {
lightData = lightData.realloc(neededCapacity);
}
initialize();
}
/**
* Completely (re)populate this volume with block and sky lighting data.
* This is expensive and should be avoided.
*/
public void initialize() {
if (lightData == null) return;
copyLight(getVolume());
markDirty();
}
protected void markDirty() {
// noop
}
public void delete() {
lightData.free();
lightData = null;
}
/**
* Copy all light from the level into this volume.
*
* @param levelVolume the region in the level to copy data from.
*/
public void copyLight(Box levelVolume) {
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
int xShift = box.getMinX();
int yShift = box.getMinY();
int zShift = box.getMinZ();
levelVolume.forEachContained((x, y, z) -> {
pos.set(x, y, z);
int block = this.level.getBrightness(LightLayer.BLOCK, pos);
int sky = this.level.getBrightness(LightLayer.SKY, pos);
writeLight(x - xShift, y - yShift, z - zShift, block, sky);
});
}
protected void writeLight(int x, int y, int z, int block, int sky) {
byte b = (byte) ((block & 0xF) << 4);
byte s = (byte) ((sky & 0xF) << 4);
long ptr = boxPosToPtr(x, y, z);
MemoryUtil.memPutByte(ptr, b);
MemoryUtil.memPutByte(ptr + 1, s);
}
/**
* Copy block light from the level into this volume.
*
* @param levelVolume the region in the level to copy data from.
*/
public void copyBlock(Box levelVolume) {
var pos = new BlockPos.MutableBlockPos();
int xShift = box.getMinX();
int yShift = box.getMinY();
int zShift = box.getMinZ();
levelVolume.forEachContained((x, y, z) -> {
int light = this.level.getBrightness(LightLayer.BLOCK, pos.set(x, y, z));
writeBlock(x - xShift, y - yShift, z - zShift, light);
});
}
protected void writeBlock(int x, int y, int z, int block) {
byte b = (byte) ((block & 0xF) << 4);
MemoryUtil.memPutByte(boxPosToPtr(x, y, z), b);
}
/**
* Copy sky light from the level into this volume.
*
* @param levelVolume the region in the level to copy data from.
*/
public void copySky(Box levelVolume) {
var pos = new BlockPos.MutableBlockPos();
int xShift = box.getMinX();
int yShift = box.getMinY();
int zShift = box.getMinZ();
levelVolume.forEachContained((x, y, z) -> {
int light = this.level.getBrightness(LightLayer.SKY, pos.set(x, y, z));
writeSky(x - xShift, y - yShift, z - zShift, light);
});
}
protected void writeSky(int x, int y, int z, int sky) {
byte s = (byte) ((sky & 0xF) << 4);
MemoryUtil.memPutByte(boxPosToPtr(x, y, z) + 1, s);
}
protected long levelPosToPtr(int x, int y, int z) {
return lightData.ptr() + levelPosToPtrOffset(x, y, z);
}
protected long boxPosToPtr(int x, int y, int z) {
return lightData.ptr() + boxPosToPtrOffset(x, y, z);
}
protected int levelPosToPtrOffset(int x, int y, int z) {
x -= box.getMinX();
y -= box.getMinY();
z -= box.getMinZ();
return boxPosToPtrOffset(x, y, z);
}
protected int boxPosToPtrOffset(int x, int y, int z) {
return (x + box.sizeX() * (y + z * box.sizeY())) * 2;
}
public void onLightUpdate(LightLayer type, SectionPos pos) {
if (lightData == null) return;
MutableBox vol = MutableBox.from(pos);
if (!vol.intersects(getVolume())) return;
vol.intersectAssign(getVolume()); // compute the region contained by us that has dirty lighting data.
if (type == LightLayer.BLOCK) copyBlock(vol);
else if (type == LightLayer.SKY) copySky(vol);
markDirty();
}
}