mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-23 21:46:25 +01:00
Implicitly initiated
- Pass partial tick to visualizers and Effect#visualize - Pass partial tick to LitVisual#updateLight - Remove Visual#init - Rename LitVisual#initLightSectionNotifier to setLightSectionNotifier - Add static utility methods to FlatLit - Remove relight methods from AbstractVisual and add specialized relight methods to AbstractBlockEntityVisual and AbstractEntityVisual to match how vanilla retrieves lightmaps - Rename AtomicBitset to AtomicBitSet
This commit is contained in:
parent
6017228f4a
commit
06a2788f9c
29 changed files with 212 additions and 227 deletions
|
@ -31,5 +31,6 @@ gradlePlugin {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation("dev.architectury.loom:dev.architectury.loom.gradle.plugin:1.6-SNAPSHOT")
|
||||
// FIXME: This should not hard-code the Loom version.
|
||||
implementation("dev.architectury.loom:dev.architectury.loom.gradle.plugin:1.6.397")
|
||||
}
|
||||
|
|
|
@ -16,5 +16,5 @@ public interface Effect {
|
|||
* @param ctx The visualization context.
|
||||
* @return An arbitrary EffectVisual.
|
||||
*/
|
||||
List<EffectVisual<?>> visualize(VisualizationContext ctx);
|
||||
List<EffectVisual<?>> visualize(VisualizationContext ctx, float partialTick);
|
||||
}
|
||||
|
|
|
@ -13,16 +13,14 @@ import net.minecraft.core.SectionPos;
|
|||
*/
|
||||
public interface LitVisual extends Visual {
|
||||
/**
|
||||
* Called when a section this visual is contained in receives a light update.
|
||||
* Set the notifier object.
|
||||
*
|
||||
* <p>Even if multiple sections are updated at the same time, this method will only be called once.</p>
|
||||
* <p>This method is only called once right after the visual
|
||||
* is created and before {@link #collectLightSections}.</p>
|
||||
*
|
||||
* <p>The implementation is free to parallelize calls to this method, as well as execute the plan
|
||||
* returned by {@link DynamicVisual#planFrame} simultaneously. It is safe to query/update light here,
|
||||
* but you must ensure proper synchronization if you want to mutate anything outside this visual or
|
||||
* anything that is also mutated within {@link DynamicVisual#planFrame}.</p>
|
||||
* @param notifier The notifier.
|
||||
*/
|
||||
void updateLight();
|
||||
void setLightSectionNotifier(Notifier notifier);
|
||||
|
||||
/**
|
||||
* Collect the sections that this visual is contained in.
|
||||
|
@ -36,14 +34,18 @@ public interface LitVisual extends Visual {
|
|||
void collectLightSections(LongConsumer consumer);
|
||||
|
||||
/**
|
||||
* Set the notifier object.
|
||||
* Called when a section this visual is contained in receives a light update.
|
||||
*
|
||||
* <p>This method is only called once, upon visual creation,
|
||||
* after {@link #init} and before {@link #collectLightSections}.</p>
|
||||
* <p>Even if multiple sections are updated at the same time, this method will only be called once.</p>
|
||||
*
|
||||
* @param notifier The notifier.
|
||||
* <p>The implementation is free to parallelize calls to this method, as well as execute the plan
|
||||
* returned by {@link DynamicVisual#planFrame} simultaneously. It is safe to query/update light here,
|
||||
* but you must ensure proper synchronization if you want to mutate anything outside this visual or
|
||||
* anything that is also mutated within {@link DynamicVisual#planFrame}.</p>
|
||||
*
|
||||
* <p>This method not is invoked automatically after visual creation.</p>
|
||||
*/
|
||||
void initLightSectionNotifier(Notifier notifier);
|
||||
void updateLight(float partialTick);
|
||||
|
||||
/**
|
||||
* A notifier object that can be used to indicate to the impl
|
||||
|
|
|
@ -8,13 +8,6 @@ package dev.engine_room.flywheel.api.visual;
|
|||
* @see LitVisual
|
||||
*/
|
||||
public interface Visual {
|
||||
/**
|
||||
* Initialize instances here.
|
||||
*
|
||||
* <p>This method will be called exactly once upon visual creation.</p>
|
||||
*/
|
||||
void init(float partialTick);
|
||||
|
||||
/**
|
||||
* Update instances here.
|
||||
*
|
||||
|
|
|
@ -18,7 +18,7 @@ public interface BlockEntityVisualizer<T extends BlockEntity> {
|
|||
* @param blockEntity The block entity to construct a visual for.
|
||||
* @return The visual.
|
||||
*/
|
||||
List<BlockEntityVisual<? super T>> createVisual(VisualizationContext ctx, T blockEntity);
|
||||
List<BlockEntityVisual<? super T>> createVisual(VisualizationContext ctx, T blockEntity, float partialTick);
|
||||
|
||||
/**
|
||||
* Checks if the given block entity should not be rendered with the vanilla {@link BlockEntityRenderer}.
|
||||
|
|
|
@ -18,7 +18,7 @@ public interface EntityVisualizer<T extends Entity> {
|
|||
* @param entity The entity to construct a visual for.
|
||||
* @return The visual.
|
||||
*/
|
||||
List<EntityVisual<? super T>> createVisual(VisualizationContext ctx, T entity);
|
||||
List<EntityVisual<? super T>> createVisual(VisualizationContext ctx, T entity, float partialTick);
|
||||
|
||||
/**
|
||||
* Checks if the given entity should not render with the vanilla {@link EntityRenderer}.
|
||||
|
|
|
@ -8,7 +8,7 @@ import dev.engine_room.flywheel.api.instance.Instance;
|
|||
import dev.engine_room.flywheel.api.instance.InstanceType;
|
||||
import dev.engine_room.flywheel.api.instance.Instancer;
|
||||
import dev.engine_room.flywheel.backend.engine.embed.Environment;
|
||||
import dev.engine_room.flywheel.lib.util.AtomicBitset;
|
||||
import dev.engine_room.flywheel.lib.util.AtomicBitSet;
|
||||
|
||||
public abstract class AbstractInstancer<I extends Instance> implements Instancer<I> {
|
||||
public final InstanceType<I> type;
|
||||
|
@ -19,8 +19,8 @@ public abstract class AbstractInstancer<I extends Instance> implements Instancer
|
|||
protected final ArrayList<I> instances = new ArrayList<>();
|
||||
protected final ArrayList<InstanceHandleImpl> handles = new ArrayList<>();
|
||||
|
||||
protected final AtomicBitset changed = new AtomicBitset();
|
||||
protected final AtomicBitset deleted = new AtomicBitset();
|
||||
protected final AtomicBitSet changed = new AtomicBitSet();
|
||||
protected final AtomicBitSet deleted = new AtomicBitSet();
|
||||
|
||||
protected AbstractInstancer(InstanceType<I> type, Environment environment) {
|
||||
this.type = type;
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
package dev.engine_room.flywheel.lib.instance;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import dev.engine_room.flywheel.api.instance.Instance;
|
||||
import dev.engine_room.flywheel.lib.visual.AbstractVisual;
|
||||
import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual;
|
||||
import dev.engine_room.flywheel.lib.visual.AbstractEntityVisual;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
|
||||
/**
|
||||
* An interface that implementors of {@link Instance} should also implement
|
||||
* if they wish to make use of the relighting utilities in {@link AbstractVisual}.
|
||||
* An interface that implementors of {@link Instance} should also implement if they wish to make use of
|
||||
* {@link #relight} and the relighting utilities in {@link AbstractBlockEntityVisual} and {@link AbstractEntityVisual}.
|
||||
*/
|
||||
public interface FlatLit extends Instance {
|
||||
/**
|
||||
|
@ -25,4 +31,34 @@ public interface FlatLit extends Instance {
|
|||
default FlatLit light(int blockLight, int skyLight) {
|
||||
return light(LightTexture.pack(blockLight, skyLight));
|
||||
}
|
||||
|
||||
static void relight(int packedLight, @Nullable FlatLit... instances) {
|
||||
for (FlatLit instance : instances) {
|
||||
if (instance != null) {
|
||||
instance.light(packedLight)
|
||||
.handle()
|
||||
.setChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void relight(int packedLight, Iterator<@Nullable FlatLit> instances) {
|
||||
while (instances.hasNext()) {
|
||||
FlatLit instance = instances.next();
|
||||
|
||||
if (instance != null) {
|
||||
instance.light(packedLight)
|
||||
.handle()
|
||||
.setChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void relight(int packedLight, Iterable<@Nullable FlatLit> instances) {
|
||||
relight(packedLight, instances.iterator());
|
||||
}
|
||||
|
||||
static void relight(int packedLight, Stream<@Nullable FlatLit> instances) {
|
||||
relight(packedLight, instances.iterator());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
|
|||
|
||||
// https://github.com/Netflix/hollow/blob/master/hollow/src/main/java/com/netflix/hollow/core/memory/ThreadSafeBitSet.java
|
||||
// Refactored to remove unused methods, deduplicate some code segments, and add extra functionality with #forEachSetSpan
|
||||
public class AtomicBitset {
|
||||
public class AtomicBitSet {
|
||||
// 1024 bits, 128 bytes, 16 longs per segment
|
||||
public static final int DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS = 10;
|
||||
|
||||
|
@ -18,17 +18,17 @@ public class AtomicBitset {
|
|||
private final int numLongsPerSegment;
|
||||
private final int log2SegmentSize;
|
||||
private final int segmentMask;
|
||||
private final AtomicReference<AtomicBitsetSegments> segments;
|
||||
private final AtomicReference<AtomicBitSetSegments> segments;
|
||||
|
||||
public AtomicBitset() {
|
||||
public AtomicBitSet() {
|
||||
this(DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS);
|
||||
}
|
||||
|
||||
public AtomicBitset(int log2SegmentSizeInBits) {
|
||||
public AtomicBitSet(int log2SegmentSizeInBits) {
|
||||
this(log2SegmentSizeInBits, 0);
|
||||
}
|
||||
|
||||
public AtomicBitset(int log2SegmentSizeInBits, int numBitsToPreallocate) {
|
||||
public AtomicBitSet(int log2SegmentSizeInBits, int numBitsToPreallocate) {
|
||||
if (log2SegmentSizeInBits < 6) {
|
||||
throw new IllegalArgumentException("Cannot specify fewer than 64 bits in each segment!");
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public class AtomicBitset {
|
|||
long numBitsPerSegment = numLongsPerSegment * 64L;
|
||||
int numSegmentsToPreallocate = numBitsToPreallocate == 0 ? 1 : (int) (((numBitsToPreallocate - 1) / numBitsPerSegment) + 1);
|
||||
|
||||
segments = new AtomicReference<>(new AtomicBitsetSegments(numSegmentsToPreallocate, numLongsPerSegment));
|
||||
segments = new AtomicReference<>(new AtomicBitSetSegments(numSegmentsToPreallocate, numLongsPerSegment));
|
||||
}
|
||||
|
||||
public void set(int position) {
|
||||
|
@ -251,7 +251,7 @@ public class AtomicBitset {
|
|||
}
|
||||
|
||||
public long maxSetBit() {
|
||||
AtomicBitsetSegments segments = this.segments.get();
|
||||
AtomicBitSetSegments segments = this.segments.get();
|
||||
|
||||
int segmentIdx = segments.numSegments() - 1;
|
||||
|
||||
|
@ -273,7 +273,7 @@ public class AtomicBitset {
|
|||
throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
|
||||
}
|
||||
|
||||
AtomicBitsetSegments segments = this.segments.get();
|
||||
AtomicBitSetSegments segments = this.segments.get();
|
||||
|
||||
int segmentPosition = segmentIndexForPosition(fromIndex);
|
||||
if (segmentPosition >= segments.numSegments()) {
|
||||
|
@ -309,7 +309,7 @@ public class AtomicBitset {
|
|||
|
||||
int segmentPosition = segmentIndexForPosition(fromIndex);
|
||||
|
||||
AtomicBitsetSegments segments = this.segments.get();
|
||||
AtomicBitSetSegments segments = this.segments.get();
|
||||
|
||||
if (segmentPosition >= segments.numSegments()) {
|
||||
return fromIndex;
|
||||
|
@ -352,7 +352,7 @@ public class AtomicBitset {
|
|||
* @param consumer The consumer to accept each span.
|
||||
*/
|
||||
public void forEachSetSpan(BitSpanConsumer consumer) {
|
||||
AtomicBitsetSegments segments = this.segments.get();
|
||||
AtomicBitSetSegments segments = this.segments.get();
|
||||
|
||||
if (segments.cardinality() == 0) {
|
||||
return;
|
||||
|
@ -415,7 +415,7 @@ public class AtomicBitset {
|
|||
* Clear all bits to 0.
|
||||
*/
|
||||
public void clear() {
|
||||
AtomicBitsetSegments segments = this.segments.get();
|
||||
AtomicBitSetSegments segments = this.segments.get();
|
||||
|
||||
for (int i = 0; i < segments.numSegments(); i++) {
|
||||
AtomicLongArray segment = segments.getSegment(i);
|
||||
|
@ -478,13 +478,13 @@ public class AtomicBitset {
|
|||
}
|
||||
|
||||
@NotNull
|
||||
private AtomicBitsetSegments expandToFit(int segmentIndex) {
|
||||
AtomicBitsetSegments visibleSegments = segments.get();
|
||||
private AtomicBitSet.AtomicBitSetSegments expandToFit(int segmentIndex) {
|
||||
AtomicBitSetSegments visibleSegments = segments.get();
|
||||
|
||||
while (visibleSegments.numSegments() <= segmentIndex) {
|
||||
// Thread safety: newVisibleSegments contains all of the segments from the currently visible segments, plus extra.
|
||||
// all of the segments in the currently visible segments are canonical and will not change.
|
||||
AtomicBitsetSegments newVisibleSegments = new AtomicBitsetSegments(visibleSegments, segmentIndex + 1, numLongsPerSegment);
|
||||
AtomicBitSetSegments newVisibleSegments = new AtomicBitSetSegments(visibleSegments, segmentIndex + 1, numLongsPerSegment);
|
||||
|
||||
// because we are using a compareAndSet, if this thread "wins the race" and successfully sets this variable, then the segments
|
||||
// which are newly defined in newVisibleSegments become canonical.
|
||||
|
@ -500,10 +500,10 @@ public class AtomicBitset {
|
|||
return visibleSegments;
|
||||
}
|
||||
|
||||
private static class AtomicBitsetSegments {
|
||||
private static class AtomicBitSetSegments {
|
||||
private final AtomicLongArray[] segments;
|
||||
|
||||
private AtomicBitsetSegments(int numSegments, int segmentLength) {
|
||||
private AtomicBitSetSegments(int numSegments, int segmentLength) {
|
||||
AtomicLongArray[] segments = new AtomicLongArray[numSegments];
|
||||
|
||||
for (int i = 0; i < numSegments; i++) {
|
||||
|
@ -515,7 +515,7 @@ public class AtomicBitset {
|
|||
this.segments = segments;
|
||||
}
|
||||
|
||||
private AtomicBitsetSegments(AtomicBitsetSegments copyFrom, int numSegments, int segmentLength) {
|
||||
private AtomicBitSetSegments(AtomicBitSetSegments copyFrom, int numSegments, int segmentLength) {
|
||||
AtomicLongArray[] segments = new AtomicLongArray[numSegments];
|
||||
|
||||
for (int i = 0; i < numSegments; i++) {
|
||||
|
@ -550,7 +550,7 @@ public class AtomicBitset {
|
|||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof AtomicBitset other)) {
|
||||
if (!(obj instanceof AtomicBitSet other)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -558,8 +558,8 @@ public class AtomicBitset {
|
|||
throw new IllegalArgumentException("Segment sizes must be the same");
|
||||
}
|
||||
|
||||
AtomicBitsetSegments thisSegments = this.segments.get();
|
||||
AtomicBitsetSegments otherSegments = other.segments.get();
|
||||
AtomicBitSetSegments thisSegments = this.segments.get();
|
||||
AtomicBitSetSegments otherSegments = other.segments.get();
|
||||
|
||||
for (int i = 0; i < thisSegments.numSegments(); i++) {
|
||||
AtomicLongArray thisArray = thisSegments.getSegment(i);
|
|
@ -11,7 +11,9 @@ import dev.engine_room.flywheel.api.visual.LitVisual;
|
|||
import dev.engine_room.flywheel.api.visual.TickableVisual;
|
||||
import dev.engine_room.flywheel.api.visualization.VisualManager;
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
import dev.engine_room.flywheel.lib.instance.FlatLit;
|
||||
import dev.engine_room.flywheel.lib.math.MoreMath;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
@ -40,8 +42,8 @@ public abstract class AbstractBlockEntityVisual<T extends BlockEntity> extends A
|
|||
@Nullable
|
||||
protected LitVisual.Notifier notifier;
|
||||
|
||||
public AbstractBlockEntityVisual(VisualizationContext ctx, T blockEntity) {
|
||||
super(ctx, blockEntity.getLevel());
|
||||
public AbstractBlockEntityVisual(VisualizationContext ctx, T blockEntity, float partialTick) {
|
||||
super(ctx, blockEntity.getLevel(), partialTick);
|
||||
this.blockEntity = blockEntity;
|
||||
this.pos = blockEntity.getBlockPos();
|
||||
this.blockState = blockEntity.getBlockState();
|
||||
|
@ -49,8 +51,8 @@ public abstract class AbstractBlockEntityVisual<T extends BlockEntity> extends A
|
|||
}
|
||||
|
||||
@Override
|
||||
public void init(float partialTick) {
|
||||
updateLight();
|
||||
public void setLightSectionNotifier(Notifier notifier) {
|
||||
this.notifier = notifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,11 +60,6 @@ public abstract class AbstractBlockEntityVisual<T extends BlockEntity> extends A
|
|||
consumer.accept(SectionPos.asLong(pos));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initLightSectionNotifier(Notifier notifier) {
|
||||
this.notifier = notifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* In order to accommodate for floating point precision errors at high coordinates,
|
||||
* {@link VisualManager}s are allowed to arbitrarily adjust the origin, and
|
||||
|
@ -100,4 +97,12 @@ public abstract class AbstractBlockEntityVisual<T extends BlockEntity> extends A
|
|||
return !context.limiter()
|
||||
.shouldUpdate(pos.distToCenterSqr(context.camera().getPosition()));
|
||||
}
|
||||
|
||||
protected void relight(BlockPos pos, @Nullable FlatLit... instances) {
|
||||
FlatLit.relight(LevelRenderer.getLightColor(level, pos), instances);
|
||||
}
|
||||
|
||||
protected void relight(@Nullable FlatLit... instances) {
|
||||
relight(pos, instances);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,12 @@ import dev.engine_room.flywheel.api.visual.EntityVisual;
|
|||
import dev.engine_room.flywheel.api.visual.TickableVisual;
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationManager;
|
||||
import dev.engine_room.flywheel.lib.instance.FlatLit;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.LightLayer;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
/**
|
||||
|
@ -31,16 +35,12 @@ public abstract class AbstractEntityVisual<T extends Entity> extends AbstractVis
|
|||
protected final T entity;
|
||||
protected final EntityVisibilityTester visibilityTester;
|
||||
|
||||
public AbstractEntityVisual(VisualizationContext ctx, T entity) {
|
||||
super(ctx, entity.level());
|
||||
public AbstractEntityVisual(VisualizationContext ctx, T entity, float partialTick) {
|
||||
super(ctx, entity.level(), partialTick);
|
||||
this.entity = entity;
|
||||
visibilityTester = new EntityVisibilityTester(entity, ctx.renderOrigin(), 1.5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(float partialTick) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the distance squared between this visual and the given <em>level</em> position.
|
||||
*
|
||||
|
@ -84,4 +84,12 @@ public abstract class AbstractEntityVisual<T extends Entity> extends AbstractVis
|
|||
public boolean isVisible(FrustumIntersection frustum) {
|
||||
return entity.noCulling || visibilityTester.check(frustum);
|
||||
}
|
||||
|
||||
protected void relight(float partialTick, FlatLit... instances) {
|
||||
BlockPos pos = BlockPos.containing(entity.getLightProbePosition(partialTick));
|
||||
int blockLight = entity.isOnFire() ? 15 : level.getBrightness(LightLayer.BLOCK, pos);
|
||||
int skyLight = level.getBrightness(LightLayer.SKY, pos);
|
||||
int light = LightTexture.pack(blockLight, skyLight);
|
||||
FlatLit.relight(light, instances);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,10 @@
|
|||
package dev.engine_room.flywheel.lib.visual;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import dev.engine_room.flywheel.api.instance.InstancerProvider;
|
||||
import dev.engine_room.flywheel.api.visual.Visual;
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
import dev.engine_room.flywheel.lib.instance.FlatLit;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LightLayer;
|
||||
|
||||
public abstract class AbstractVisual implements Visual {
|
||||
/**
|
||||
|
@ -27,7 +19,7 @@ public abstract class AbstractVisual implements Visual {
|
|||
|
||||
protected boolean deleted = false;
|
||||
|
||||
public AbstractVisual(VisualizationContext ctx, Level level) {
|
||||
public AbstractVisual(VisualizationContext ctx, Level level, float partialTick) {
|
||||
this.visualizationContext = ctx;
|
||||
this.instancerProvider = ctx.instancerProvider();
|
||||
this.renderOrigin = ctx.renderOrigin();
|
||||
|
@ -49,46 +41,4 @@ public abstract class AbstractVisual implements Visual {
|
|||
_delete();
|
||||
deleted = true;
|
||||
}
|
||||
|
||||
protected void relight(BlockPos pos, @Nullable FlatLit... instances) {
|
||||
relight(level.getBrightness(LightLayer.BLOCK, pos), level.getBrightness(LightLayer.SKY, pos), instances);
|
||||
}
|
||||
|
||||
protected void relight(int block, int sky, @Nullable FlatLit... instances) {
|
||||
for (FlatLit instance : instances) {
|
||||
if (instance == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
instance.light(block, sky)
|
||||
.handle()
|
||||
.setChanged();
|
||||
}
|
||||
}
|
||||
|
||||
protected void relight(BlockPos pos, Stream<? extends @Nullable FlatLit> instances) {
|
||||
relight(level.getBrightness(LightLayer.BLOCK, pos), level.getBrightness(LightLayer.SKY, pos), instances);
|
||||
}
|
||||
|
||||
protected void relight(int block, int sky, Stream<? extends @Nullable FlatLit> instances) {
|
||||
instances.filter(Objects::nonNull)
|
||||
.forEach(instance -> instance.light(block, sky)
|
||||
.handle()
|
||||
.setChanged());
|
||||
}
|
||||
|
||||
protected void relight(BlockPos pos, Iterable<? extends @Nullable FlatLit> instances) {
|
||||
relight(level.getBrightness(LightLayer.BLOCK, pos), level.getBrightness(LightLayer.SKY, pos), instances);
|
||||
}
|
||||
|
||||
protected void relight(int block, int sky, Iterable<? extends @Nullable FlatLit> instances) {
|
||||
for (FlatLit instance : instances) {
|
||||
if (instance == null) {
|
||||
continue;
|
||||
}
|
||||
instance.light(block, sky)
|
||||
.handle()
|
||||
.setChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@ public class SimpleBlockEntityVisualizer<T extends BlockEntity> implements Block
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<BlockEntityVisual<? super T>> createVisual(VisualizationContext ctx, T blockEntity) {
|
||||
return List.of(visualFactory.create(ctx, blockEntity));
|
||||
public List<BlockEntityVisual<? super T>> createVisual(VisualizationContext ctx, T blockEntity, float partialTick) {
|
||||
return List.of(visualFactory.create(ctx, blockEntity, partialTick));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,7 +46,7 @@ public class SimpleBlockEntityVisualizer<T extends BlockEntity> implements Block
|
|||
|
||||
@FunctionalInterface
|
||||
public interface Factory<T extends BlockEntity> {
|
||||
BlockEntityVisual<? super T> create(VisualizationContext ctx, T blockEntity);
|
||||
BlockEntityVisual<? super T> create(VisualizationContext ctx, T blockEntity, float partialTick);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,8 +9,8 @@ import net.minecraft.world.entity.Entity;
|
|||
public class SimpleEntityVisual<T extends Entity> extends AbstractEntityVisual<T> implements SimpleDynamicVisual {
|
||||
protected final List<EntityComponent> components = new ArrayList<>();
|
||||
|
||||
public SimpleEntityVisual(VisualizationContext ctx, T entity) {
|
||||
super(ctx, entity);
|
||||
public SimpleEntityVisual(VisualizationContext ctx, T entity, float partialTick) {
|
||||
super(ctx, entity, partialTick);
|
||||
}
|
||||
|
||||
public void addComponent(EntityComponent component) {
|
||||
|
|
|
@ -24,8 +24,8 @@ public class SimpleEntityVisualizer<T extends Entity> implements EntityVisualize
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<EntityVisual<? super T>> createVisual(VisualizationContext ctx, T entity) {
|
||||
return List.of(visualFactory.create(ctx, entity));
|
||||
public List<EntityVisual<? super T>> createVisual(VisualizationContext ctx, T entity, float partialTick) {
|
||||
return List.of(visualFactory.create(ctx, entity, partialTick));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,7 +46,7 @@ public class SimpleEntityVisualizer<T extends Entity> implements EntityVisualize
|
|||
|
||||
@FunctionalInterface
|
||||
public interface Factory<T extends Entity> {
|
||||
EntityVisual<? super T> create(VisualizationContext ctx, T entity);
|
||||
EntityVisual<? super T> create(VisualizationContext ctx, T entity, float partialTick);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -53,13 +53,13 @@ public class BlockEntityStorage extends Storage<BlockEntity> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected List<? extends BlockEntityVisual<?>> createRaw(BlockEntity obj) {
|
||||
protected List<? extends BlockEntityVisual<?>> createRaw(BlockEntity obj, float partialTick) {
|
||||
var visualizer = VisualizationHelper.getVisualizer(obj);
|
||||
if (visualizer == null) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
var visualList = visualizer.createVisual(visualizationContextSupplier.get(), obj);
|
||||
var visualList = visualizer.createVisual(visualizationContextSupplier.get(), obj, partialTick);
|
||||
|
||||
BlockPos blockPos = obj.getBlockPos();
|
||||
posLookup.put(blockPos.asLong(), visualList);
|
||||
|
|
|
@ -14,8 +14,8 @@ public class EffectStorage extends Storage<Effect> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected List<? extends EffectVisual<?>> createRaw(Effect obj) {
|
||||
return obj.visualize(visualizationContextSupplier.get());
|
||||
protected List<? extends EffectVisual<?>> createRaw(Effect obj, float partialTick) {
|
||||
return obj.visualize(visualizationContextSupplier.get(), partialTick);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,13 +16,13 @@ public class EntityStorage extends Storage<Entity> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected List<? extends EntityVisual<?>> createRaw(Entity obj) {
|
||||
protected List<? extends EntityVisual<?>> createRaw(Entity obj, float partialTick) {
|
||||
var visualizer = VisualizationHelper.getVisualizer(obj);
|
||||
if (visualizer == null) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
return visualizer.createVisual(visualizationContextSupplier.get(), obj);
|
||||
return visualizer.createVisual(visualizationContextSupplier.get(), obj, partialTick);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -51,11 +51,12 @@ public class LitVisualStorage {
|
|||
});
|
||||
|
||||
long updateId = getNextUpdateId();
|
||||
Updater.Context updaterContext = new Updater.Context(updateId, context.partialTick());
|
||||
|
||||
for (long section : sectionsUpdatedThisFrame) {
|
||||
var visuals = sections2Visuals.get(section);
|
||||
if (visuals != null && !visuals.isEmpty()) {
|
||||
taskExecutor.execute(() -> Distribute.tasks(taskExecutor, updateId, sync, visuals, Updater::updateLight));
|
||||
taskExecutor.execute(() -> Distribute.tasks(taskExecutor, updaterContext, sync, visuals, Updater::updateLight));
|
||||
} else {
|
||||
sync.decrementAndEventuallyRun();
|
||||
}
|
||||
|
@ -89,8 +90,8 @@ public class LitVisualStorage {
|
|||
return visuals2Sections.isEmpty();
|
||||
}
|
||||
|
||||
public void addAndInitNotifier(LitVisual visual) {
|
||||
visual.initLightSectionNotifier(new LitVisualNotifierImpl(visual));
|
||||
public void setNotifierAndAdd(LitVisual visual) {
|
||||
visual.setLightSectionNotifier(new LitVisualNotifierImpl(visual));
|
||||
add(visual);
|
||||
}
|
||||
|
||||
|
@ -168,15 +169,15 @@ public class LitVisualStorage {
|
|||
|
||||
// Breaking this into 2 separate cases allows us to avoid the overhead of atomics in the common case.
|
||||
sealed interface Updater {
|
||||
void updateLight(long updateId);
|
||||
void updateLight(Context ctx);
|
||||
|
||||
LitVisual visual();
|
||||
|
||||
// The visual is only in one section. In this case, we can just update the visual directly.
|
||||
record Simple(LitVisual visual) implements Updater {
|
||||
@Override
|
||||
public void updateLight(long updateId) {
|
||||
visual.updateLight();
|
||||
public void updateLight(Context ctx) {
|
||||
visual.updateLight(ctx.partialTick);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,14 +185,17 @@ public class LitVisualStorage {
|
|||
// even when multiple sections it was contained in are updated at the same time.
|
||||
record Synced(LitVisual visual, AtomicLong updateId) implements Updater {
|
||||
@Override
|
||||
public void updateLight(long updateId) {
|
||||
public void updateLight(Context ctx) {
|
||||
// Different update ID means we won, so we can update the visual.
|
||||
// Same update ID means another thread beat us to the update.
|
||||
if (this.updateId.getAndSet(updateId) != updateId) {
|
||||
visual.updateLight();
|
||||
if (this.updateId.getAndSet(ctx.updateId) != ctx.updateId) {
|
||||
visual.updateLight(ctx.partialTick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
record Context(long updateId, float partialTick) {
|
||||
}
|
||||
}
|
||||
|
||||
private final class LitVisualNotifierImpl implements LitVisual.Notifier {
|
||||
|
|
|
@ -81,14 +81,14 @@ public abstract class Storage<T> {
|
|||
visuals.replaceAll((obj, visuals) -> {
|
||||
visuals.forEach(Visual::delete);
|
||||
|
||||
var out = createRaw(obj);
|
||||
var out = createRaw(obj, partialTick);
|
||||
|
||||
if (out.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Visual visual : out) {
|
||||
setup(visual, partialTick);
|
||||
setup(visual);
|
||||
}
|
||||
|
||||
return out;
|
||||
|
@ -108,7 +108,7 @@ public abstract class Storage<T> {
|
|||
}
|
||||
|
||||
private void create(T obj, float partialTick) {
|
||||
var visuals = createRaw(obj);
|
||||
var visuals = createRaw(obj, partialTick);
|
||||
|
||||
if (visuals.isEmpty()) {
|
||||
return;
|
||||
|
@ -116,11 +116,11 @@ public abstract class Storage<T> {
|
|||
this.visuals.put(obj, visuals);
|
||||
|
||||
for (Visual visual : visuals) {
|
||||
setup(visual, partialTick);
|
||||
setup(visual);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract List<? extends Visual> createRaw(T obj);
|
||||
protected abstract List<? extends Visual> createRaw(T obj, float partialTick);
|
||||
|
||||
public Plan<DynamicVisual.Context> framePlan() {
|
||||
return NestedPlan.of(dynamicVisuals, litVisuals.plan(), ForEachPlan.of(() -> simpleDynamicVisuals, SimpleDynamicVisual::beginFrame));
|
||||
|
@ -134,9 +134,7 @@ public abstract class Storage<T> {
|
|||
litVisuals.enqueueLightUpdateSection(section);
|
||||
}
|
||||
|
||||
private void setup(Visual visual, float partialTick) {
|
||||
visual.init(partialTick);
|
||||
|
||||
private void setup(Visual visual) {
|
||||
if (visual instanceof TickableVisual tickable) {
|
||||
if (visual instanceof SimpleTickableVisual simpleTickable) {
|
||||
simpleTickableVisuals.add(simpleTickable);
|
||||
|
@ -154,7 +152,7 @@ public abstract class Storage<T> {
|
|||
}
|
||||
|
||||
if (visual instanceof LitVisual lit) {
|
||||
litVisuals.addAndInitNotifier(lit);
|
||||
litVisuals.setNotifierAndAdd(lit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,24 +26,19 @@ public class BellVisual extends AbstractBlockEntityVisual<BellBlockEntity> imple
|
|||
return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.BELL, BellRenderer.BELL_RESOURCE_LOCATION.sprite(), "bell_body"), Materials.BELL);
|
||||
});
|
||||
|
||||
private OrientedInstance bell;
|
||||
private final OrientedInstance bell;
|
||||
|
||||
private boolean wasShaking = false;
|
||||
|
||||
public BellVisual(VisualizationContext ctx, BellBlockEntity blockEntity) {
|
||||
super(ctx, blockEntity);
|
||||
}
|
||||
public BellVisual(VisualizationContext ctx, BellBlockEntity blockEntity, float partialTick) {
|
||||
super(ctx, blockEntity, partialTick);
|
||||
|
||||
@Override
|
||||
public void init(float partialTick) {
|
||||
bell = createBellInstance().setPivot(0.5f, 0.75f, 0.5f)
|
||||
.setPosition(getVisualPosition());
|
||||
|
||||
bell.setChanged();
|
||||
|
||||
updateRotation(partialTick);
|
||||
|
||||
super.init(partialTick);
|
||||
updateLight(partialTick);
|
||||
}
|
||||
|
||||
private OrientedInstance createBellInstance() {
|
||||
|
@ -81,8 +76,8 @@ public class BellVisual extends AbstractBlockEntityVisual<BellBlockEntity> imple
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
relight(pos, bell);
|
||||
public void updateLight(float partialTick) {
|
||||
relight(bell);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -51,22 +51,20 @@ public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends Abstrac
|
|||
return new SingleMeshModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "lock"), Materials.CHEST);
|
||||
});
|
||||
|
||||
private OrientedInstance bottom;
|
||||
private TransformedInstance lid;
|
||||
private TransformedInstance lock;
|
||||
private final OrientedInstance bottom;
|
||||
private final TransformedInstance lid;
|
||||
private final TransformedInstance lock;
|
||||
|
||||
private final ChestType chestType;
|
||||
private final Float2FloatFunction lidProgress;
|
||||
|
||||
private ChestType chestType;
|
||||
private final Quaternionf baseRotation = new Quaternionf();
|
||||
private Float2FloatFunction lidProgress;
|
||||
|
||||
private float lastProgress = Float.NaN;
|
||||
|
||||
public ChestVisual(VisualizationContext ctx, T blockEntity) {
|
||||
super(ctx, blockEntity);
|
||||
}
|
||||
public ChestVisual(VisualizationContext ctx, T blockEntity, float partialTick) {
|
||||
super(ctx, blockEntity, partialTick);
|
||||
|
||||
@Override
|
||||
public void init(float partialTick) {
|
||||
chestType = blockState.hasProperty(ChestBlock.TYPE) ? blockState.getValue(ChestBlock.TYPE) : ChestType.SINGLE;
|
||||
Material texture = Sheets.chooseMaterial(blockEntity, chestType, isChristmas());
|
||||
|
||||
|
@ -90,8 +88,7 @@ public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends Abstrac
|
|||
bottom.setChanged();
|
||||
|
||||
applyLidTransform(lidProgress.get(partialTick));
|
||||
|
||||
super.init(partialTick);
|
||||
updateLight(partialTick);
|
||||
}
|
||||
|
||||
private OrientedInstance createBottomInstance(Material texture) {
|
||||
|
@ -153,8 +150,8 @@ public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends Abstrac
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
relight(pos, bottom, lid, lock);
|
||||
public void updateLight(float partialTick) {
|
||||
relight(bottom, lid, lock);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -38,19 +38,32 @@ public class MinecartVisual<T extends AbstractMinecart> extends SimpleEntityVisu
|
|||
public static final ModelHolder SPAWNER_BODY_MODEL = createBodyModelHolder(ModelLayers.SPAWNER_MINECART);
|
||||
public static final ModelHolder TNT_BODY_MODEL = createBodyModelHolder(ModelLayers.TNT_MINECART);
|
||||
|
||||
private final ModelHolder bodyModel;
|
||||
|
||||
private TransformedInstance body;
|
||||
private final TransformedInstance body;
|
||||
@Nullable
|
||||
private TransformedInstance contents;
|
||||
private BlockState blockState;
|
||||
private boolean active;
|
||||
|
||||
private final ModelHolder bodyModel;
|
||||
|
||||
private final PoseStack stack = new PoseStack();
|
||||
|
||||
public MinecartVisual(VisualizationContext ctx, T entity, ModelHolder bodyModel) {
|
||||
super(ctx, entity);
|
||||
private BlockState blockState;
|
||||
private boolean active;
|
||||
|
||||
public MinecartVisual(VisualizationContext ctx, T entity, float partialTick, ModelHolder bodyModel) {
|
||||
super(ctx, entity, partialTick);
|
||||
|
||||
this.bodyModel = bodyModel;
|
||||
|
||||
body = createBodyInstance();
|
||||
blockState = entity.getDisplayBlockState();
|
||||
contents = createContentsInstance();
|
||||
|
||||
addComponent(new ShadowComponent(visualizationContext, entity).radius(0.7f));
|
||||
addComponent(new FireComponent(visualizationContext, entity));
|
||||
addComponent(new HitboxComponent(visualizationContext, entity));
|
||||
|
||||
updateInstances(partialTick);
|
||||
updateLight(partialTick);
|
||||
}
|
||||
|
||||
private static ModelHolder createBodyModelHolder(ModelLayerLocation layer) {
|
||||
|
@ -59,22 +72,6 @@ public class MinecartVisual<T extends AbstractMinecart> extends SimpleEntityVisu
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(float partialTick) {
|
||||
addComponent(new ShadowComponent(visualizationContext, entity).radius(0.7f));
|
||||
addComponent(new FireComponent(visualizationContext, entity));
|
||||
addComponent(new HitboxComponent(visualizationContext, entity));
|
||||
|
||||
body = createBodyInstance();
|
||||
blockState = entity.getDisplayBlockState();
|
||||
contents = createContentsInstance();
|
||||
|
||||
updateInstances(partialTick);
|
||||
updateLight();
|
||||
|
||||
super.init(partialTick);
|
||||
}
|
||||
|
||||
private TransformedInstance createBodyInstance() {
|
||||
return instancerProvider.instancer(InstanceTypes.TRANSFORMED, bodyModel.get())
|
||||
.createInstance();
|
||||
|
@ -110,8 +107,6 @@ public class MinecartVisual<T extends AbstractMinecart> extends SimpleEntityVisu
|
|||
}
|
||||
contents = createContentsInstance();
|
||||
}
|
||||
|
||||
updateLight();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -198,6 +193,9 @@ public class MinecartVisual<T extends AbstractMinecart> extends SimpleEntityVisu
|
|||
stack.scale(-1.0F, -1.0F, 1.0F);
|
||||
body.setTransform(stack)
|
||||
.setChanged();
|
||||
|
||||
// TODO: Use LitVisual if possible.
|
||||
updateLight(partialTick);
|
||||
}
|
||||
|
||||
protected void updateContents(TransformedInstance contents, PoseStack stack, float partialTick) {
|
||||
|
@ -205,8 +203,8 @@ public class MinecartVisual<T extends AbstractMinecart> extends SimpleEntityVisu
|
|||
.setChanged();
|
||||
}
|
||||
|
||||
public void updateLight() {
|
||||
relight(entity.blockPosition(), body, contents);
|
||||
public void updateLight(float partialTick) {
|
||||
relight(partialTick, body, contents);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -34,19 +34,16 @@ public class ShulkerBoxVisual extends AbstractBlockEntityVisual<ShulkerBoxBlockE
|
|||
return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.SHULKER, texture.sprite(), "lid"), Materials.SHULKER);
|
||||
});
|
||||
|
||||
private TransformedInstance base;
|
||||
private TransformedInstance lid;
|
||||
private final TransformedInstance base;
|
||||
private final TransformedInstance lid;
|
||||
|
||||
private final PoseStack stack = new PoseStack();
|
||||
|
||||
private float lastProgress = Float.NaN;
|
||||
|
||||
public ShulkerBoxVisual(VisualizationContext ctx, ShulkerBoxBlockEntity blockEntity) {
|
||||
super(ctx, blockEntity);
|
||||
}
|
||||
public ShulkerBoxVisual(VisualizationContext ctx, ShulkerBoxBlockEntity blockEntity, float partialTick) {
|
||||
super(ctx, blockEntity, partialTick);
|
||||
|
||||
@Override
|
||||
public void init(float partialTick) {
|
||||
DyeColor color = blockEntity.getColor();
|
||||
Material texture;
|
||||
if (color == null) {
|
||||
|
@ -67,12 +64,11 @@ public class ShulkerBoxVisual extends AbstractBlockEntityVisual<ShulkerBoxBlockE
|
|||
.translateY(-1);
|
||||
|
||||
base = createBaseInstance(texture).setTransform(stack);
|
||||
lid = createLidInstance(texture).setTransform(stack);
|
||||
|
||||
base.setChanged();
|
||||
lid = createLidInstance(texture).setTransform(stack);
|
||||
lid.setChanged();
|
||||
|
||||
super.init(partialTick);
|
||||
updateLight(partialTick);
|
||||
}
|
||||
|
||||
private TransformedInstance createBaseInstance(Material texture) {
|
||||
|
@ -119,8 +115,8 @@ public class ShulkerBoxVisual extends AbstractBlockEntityVisual<ShulkerBoxBlockE
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
relight(pos, base, lid);
|
||||
public void updateLight(float partialTick) {
|
||||
relight(base, lid);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,8 +11,8 @@ import net.minecraft.world.entity.vehicle.MinecartTNT;
|
|||
public class TntMinecartVisual<T extends MinecartTNT> extends MinecartVisual<T> {
|
||||
private static final int WHITE_OVERLAY = OverlayTexture.pack(OverlayTexture.u(1.0F), 10);
|
||||
|
||||
public TntMinecartVisual(VisualizationContext ctx, T entity) {
|
||||
super(ctx, entity, TNT_BODY_MODEL);
|
||||
public TntMinecartVisual(VisualizationContext ctx, T entity, float partialTick) {
|
||||
super(ctx, entity, partialTick, TNT_BODY_MODEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -47,27 +47,27 @@ public class VanillaVisuals {
|
|||
.apply();
|
||||
|
||||
builder(EntityType.CHEST_MINECART)
|
||||
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.CHEST_BODY_MODEL))
|
||||
.factory((ctx, entity, partialTick) -> new MinecartVisual<>(ctx, entity, partialTick, MinecartVisual.CHEST_BODY_MODEL))
|
||||
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
||||
.apply();
|
||||
builder(EntityType.COMMAND_BLOCK_MINECART)
|
||||
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.COMMAND_BLOCK_BODY_MODEL))
|
||||
.factory((ctx, entity, partialTick) -> new MinecartVisual<>(ctx, entity, partialTick, MinecartVisual.COMMAND_BLOCK_BODY_MODEL))
|
||||
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
||||
.apply();
|
||||
builder(EntityType.FURNACE_MINECART)
|
||||
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.FURNACE_BODY_MODEL))
|
||||
.factory((ctx, entity, partialTick) -> new MinecartVisual<>(ctx, entity, partialTick, MinecartVisual.FURNACE_BODY_MODEL))
|
||||
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
||||
.apply();
|
||||
builder(EntityType.HOPPER_MINECART)
|
||||
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.HOPPER_BODY_MODEL))
|
||||
.factory((ctx, entity, partialTick) -> new MinecartVisual<>(ctx, entity, partialTick, MinecartVisual.HOPPER_BODY_MODEL))
|
||||
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
||||
.apply();
|
||||
builder(EntityType.MINECART)
|
||||
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.STANDARD_BODY_MODEL))
|
||||
.factory((ctx, entity, partialTick) -> new MinecartVisual<>(ctx, entity, partialTick, MinecartVisual.STANDARD_BODY_MODEL))
|
||||
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
||||
.apply();
|
||||
builder(EntityType.SPAWNER_MINECART)
|
||||
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.SPAWNER_BODY_MODEL))
|
||||
.factory((ctx, entity, partialTick) -> new MinecartVisual<>(ctx, entity, partialTick, MinecartVisual.SPAWNER_BODY_MODEL))
|
||||
.skipVanillaRender(MinecartVisual::shouldSkipRender)
|
||||
.apply();
|
||||
builder(EntityType.TNT_MINECART)
|
||||
|
|
|
@ -7,9 +7,9 @@ public class TestAtomicBitset {
|
|||
|
||||
@Test
|
||||
void testNextClearBit() {
|
||||
var segmentLength = 1 << AtomicBitset.DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS;
|
||||
var bitLength = 2 << AtomicBitset.DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS;
|
||||
var bs = new AtomicBitset(AtomicBitset.DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS, bitLength);
|
||||
var segmentLength = 1 << AtomicBitSet.DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS;
|
||||
var bitLength = 2 << AtomicBitSet.DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS;
|
||||
var bs = new AtomicBitSet(AtomicBitSet.DEFAULT_LOG2_SEGMENT_SIZE_IN_BITS, bitLength);
|
||||
|
||||
Assertions.assertEquals(0, bs.nextClearBit(0));
|
||||
Assertions.assertEquals(1, bs.nextClearBit(1));
|
||||
|
|
|
@ -19,7 +19,8 @@ forge_version_range = [47.0.0,)
|
|||
|
||||
# General build dependency versions
|
||||
java_version = 17
|
||||
arch_loom_version = 1.6-SNAPSHOT
|
||||
# FIXME: This doesn't do anything.
|
||||
# arch_loom_version = 1.6-SNAPSHOT
|
||||
cursegradle_version = 1.4.0
|
||||
parchment_version = 2023.09.03
|
||||
|
||||
|
|
|
@ -12,10 +12,11 @@ pluginManagement {
|
|||
maven("https://maven.parchmentmc.org")
|
||||
}
|
||||
|
||||
plugins {
|
||||
val arch_loom_version: String by settings
|
||||
id("dev.architectury.loom") version arch_loom_version
|
||||
}
|
||||
// FIXME: This doesn't do anything. The actual version is always the one defined in buildSrc/build.gradle.kts.
|
||||
// plugins {
|
||||
// val arch_loom_version: String by settings
|
||||
// id("dev.architectury.loom") version arch_loom_version
|
||||
// }
|
||||
}
|
||||
|
||||
rootProject.name = "Flywheel"
|
||||
|
|
Loading…
Reference in a new issue