mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-19 15:09:25 +00:00
306 lines
15 KiB
Diff
306 lines
15 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|
Date: Thu, 24 Oct 2024 08:20:45 -0700
|
|
Subject: [PATCH] Moonrise: fluid method optimisations
|
|
|
|
Removed since Leaf 1.21.3, Paper 1.21.3 included it
|
|
|
|
Original license: GPLv3
|
|
Original project:
|
|
- https://github.com/Tuinity/Moonrise
|
|
- https://github.com/PaperMC/Paper
|
|
|
|
This patch is based on the following mixin:
|
|
"ca/spottedleaf/moonrise/mixin/fluid/FlowingFluidMixin.java"
|
|
"ca/spottedleaf/moonrise/mixin/fluid/FluidStateMixin.java"
|
|
"ca/spottedleaf/moonrise/mixin/fluid/MappedRegistryMixin.java"
|
|
|
|
Use cached result to avoid indirection
|
|
|
|
For FlowingFluid#canPassThroughWall, try to avoid going to the cache for simple cases; additionally use better caching strategy
|
|
|
|
diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/fluid/FluidFluidState.java b/src/main/java/ca/spottedleaf/moonrise/patches/fluid/FluidFluidState.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..107c97089354edd35f330582f5e0c8a18e792a6e
|
|
--- /dev/null
|
|
+++ b/src/main/java/ca/spottedleaf/moonrise/patches/fluid/FluidFluidState.java
|
|
@@ -0,0 +1,5 @@
|
|
+package ca.spottedleaf.moonrise.patches.fluid;
|
|
+
|
|
+public interface FluidFluidState {
|
|
+ public void moonrise$initCaches();
|
|
+}
|
|
diff --git a/src/main/java/net/minecraft/core/MappedRegistry.java b/src/main/java/net/minecraft/core/MappedRegistry.java
|
|
index f22d22ebcedcc9c20225677844c86a1ad27c4211..92c2c37363fe31147f94f645c49e54ac626951cd 100644
|
|
--- a/src/main/java/net/minecraft/core/MappedRegistry.java
|
|
+++ b/src/main/java/net/minecraft/core/MappedRegistry.java
|
|
@@ -78,6 +78,19 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
|
|
};
|
|
private final Object tagAdditionLock = new Object();
|
|
|
|
+ // Moonrise start - fluid method optimisations
|
|
+ private void injectFluidRegister(
|
|
+ final ResourceKey<?> resourceKey,
|
|
+ final T object
|
|
+ ) {
|
|
+ if (resourceKey.registryKey() == (Object) net.minecraft.core.registries.Registries.FLUID) {
|
|
+ for (final net.minecraft.world.level.material.FluidState possibleState : ((net.minecraft.world.level.material.Fluid) object).getStateDefinition().getPossibleStates()) {
|
|
+ ((ca.spottedleaf.moonrise.patches.fluid.FluidFluidState) (Object) possibleState).moonrise$initCaches();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // Moonrise end - fluid method optimisations
|
|
+
|
|
public MappedRegistry(ResourceKey<? extends Registry<T>> key, Lifecycle lifecycle) {
|
|
this(key, lifecycle, false);
|
|
}
|
|
@@ -145,6 +158,7 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
|
|
this.toId.put(value, i);
|
|
this.registrationInfos.put(key, info);
|
|
this.registryLifecycle = this.registryLifecycle.add(info.lifecycle());
|
|
+ this.injectFluidRegister(key, value); // Moonrise - fluid method optimisations
|
|
return reference;
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
|
|
index 3b197331f51b12b55a40f2abb6ce99ef0fb65f17..bf9c228a19fe34221686f1d002feda7f40e8272c 100644
|
|
--- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
|
|
+++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
|
|
@@ -55,6 +55,48 @@ public abstract class FlowingFluid extends Fluid {
|
|
});
|
|
private final Map<FluidState, VoxelShape> shapes = Maps.newIdentityHashMap();
|
|
|
|
+ // Moonrise start - fluid method optimisations
|
|
+ private FluidState sourceFalling;
|
|
+ private FluidState sourceNotFalling;
|
|
+
|
|
+ private static final int TOTAL_FLOWING_STATES = FALLING.getPossibleValues().size() * LEVEL.getPossibleValues().size();
|
|
+ private static final int MIN_LEVEL = LEVEL.getPossibleValues().stream().sorted().findFirst().get().intValue();
|
|
+
|
|
+ // index = (falling ? 1 : 0) + level*2
|
|
+ private FluidState[] flowingLookUp;
|
|
+ private volatile boolean init;
|
|
+
|
|
+ private static final int COLLISION_OCCLUSION_CACHE_SIZE = 2048;
|
|
+ private static final ThreadLocal<ca.spottedleaf.moonrise.patches.collisions.util.FluidOcclusionCacheKey[]> COLLISION_OCCLUSION_CACHE = ThreadLocal.withInitial(() -> new ca.spottedleaf.moonrise.patches.collisions.util.FluidOcclusionCacheKey[COLLISION_OCCLUSION_CACHE_SIZE]);
|
|
+
|
|
+
|
|
+ /**
|
|
+ * Due to init order, we need to use callbacks to initialise our state
|
|
+ */
|
|
+ private void init() {
|
|
+ synchronized (this) {
|
|
+ if (this.init) {
|
|
+ return;
|
|
+ }
|
|
+ this.flowingLookUp = new FluidState[TOTAL_FLOWING_STATES];
|
|
+ final FluidState defaultFlowState = this.getFlowing().defaultFluidState();
|
|
+ for (int i = 0; i < TOTAL_FLOWING_STATES; ++i) {
|
|
+ final int falling = i & 1;
|
|
+ final int level = (i >>> 1) + MIN_LEVEL;
|
|
+
|
|
+ this.flowingLookUp[i] = defaultFlowState.setValue(FALLING, falling == 1 ? Boolean.TRUE : Boolean.FALSE)
|
|
+ .setValue(LEVEL, Integer.valueOf(level));
|
|
+ }
|
|
+
|
|
+ final FluidState defaultFallState = this.getSource().defaultFluidState();
|
|
+ this.sourceFalling = defaultFallState.setValue(FALLING, Boolean.TRUE);
|
|
+ this.sourceNotFalling = defaultFallState.setValue(FALLING, Boolean.FALSE);
|
|
+
|
|
+ this.init = true;
|
|
+ }
|
|
+ }
|
|
+ // Moonrise end - fluid method optimisations
|
|
+
|
|
public FlowingFluid() {}
|
|
|
|
@Override
|
|
@@ -239,53 +281,70 @@ public abstract class FlowingFluid extends Fluid {
|
|
}
|
|
}
|
|
|
|
- private boolean canPassThroughWall(Direction face, BlockGetter world, BlockPos pos, BlockState state, BlockPos fromPos, BlockState fromState) {
|
|
- Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap;
|
|
+ // Moonrise start - fluid method optimisations
|
|
+ private static boolean canPassThroughWall(final Direction direction, final BlockGetter level,
|
|
+ final BlockPos fromPos, final BlockState fromState,
|
|
+ final BlockPos toPos, final BlockState toState) {
|
|
+ if (((ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState) fromState).moonrise$emptyCollisionShape() & ((ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState) toState).moonrise$emptyCollisionShape()) {
|
|
+ // don't even try to cache simple cases
|
|
+ return true;
|
|
+ }
|
|
|
|
- if (!state.getBlock().hasDynamicShape() && !fromState.getBlock().hasDynamicShape()) {
|
|
- object2bytelinkedopenhashmap = (Object2ByteLinkedOpenHashMap) FlowingFluid.OCCLUSION_CACHE.get();
|
|
- } else {
|
|
- object2bytelinkedopenhashmap = null;
|
|
+ if (((ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState) fromState).moonrise$occludesFullBlock() | ((ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState) toState).moonrise$occludesFullBlock()) {
|
|
+ // don't even try to cache simple cases
|
|
+ return false;
|
|
}
|
|
|
|
- Block.BlockStatePairKey block_a;
|
|
+ final ca.spottedleaf.moonrise.patches.collisions.util.FluidOcclusionCacheKey[] cache = ((ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState) fromState).moonrise$hasCache() & ((ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState) toState).moonrise$hasCache() ?
|
|
+ COLLISION_OCCLUSION_CACHE.get() : null;
|
|
|
|
- if (object2bytelinkedopenhashmap != null) {
|
|
- block_a = new Block.BlockStatePairKey(state, fromState, face);
|
|
- byte b0 = object2bytelinkedopenhashmap.getAndMoveToFirst(block_a);
|
|
+ final int keyIndex
|
|
+ = (((ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState) fromState).moonrise$uniqueId1() ^ ((ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState) toState).moonrise$uniqueId2() ^ ((ca.spottedleaf.moonrise.patches.collisions.util.CollisionDirection) (Object) direction).moonrise$uniqueId())
|
|
+ & (COLLISION_OCCLUSION_CACHE_SIZE - 1);
|
|
|
|
- if (b0 != 127) {
|
|
- return b0 != 0;
|
|
+ if (cache != null) {
|
|
+ final ca.spottedleaf.moonrise.patches.collisions.util.FluidOcclusionCacheKey cached = cache[keyIndex];
|
|
+ if (cached != null && cached.first() == fromState && cached.second() == toState && cached.direction() == direction) {
|
|
+ return cached.result();
|
|
}
|
|
- } else {
|
|
- block_a = null;
|
|
}
|
|
|
|
- VoxelShape voxelshape = state.getCollisionShape(world, pos);
|
|
- VoxelShape voxelshape1 = fromState.getCollisionShape(world, fromPos);
|
|
- boolean flag = !Shapes.mergedFaceOccludes(voxelshape, voxelshape1, face);
|
|
+ final VoxelShape shape1 = fromState.getCollisionShape(level, fromPos);
|
|
+ final VoxelShape shape2 = toState.getCollisionShape(level, toPos);
|
|
|
|
- if (object2bytelinkedopenhashmap != null) {
|
|
- if (object2bytelinkedopenhashmap.size() == 200) {
|
|
- object2bytelinkedopenhashmap.removeLastByte();
|
|
- }
|
|
+ final boolean result = !Shapes.mergedFaceOccludes(shape1, shape2, direction);
|
|
|
|
- object2bytelinkedopenhashmap.putAndMoveToFirst(block_a, (byte) (flag ? 1 : 0));
|
|
+ if (cache != null) {
|
|
+ // we can afford to replace in-use keys more often due to the excessive caching the collision patch does in mergedFaceOccludes
|
|
+ cache[keyIndex] = new ca.spottedleaf.moonrise.patches.collisions.util.FluidOcclusionCacheKey(fromState, toState, direction, result);
|
|
}
|
|
|
|
- return flag;
|
|
+ return result;
|
|
}
|
|
+ // Moonrise end - fluid method optimisations
|
|
|
|
public abstract Fluid getFlowing();
|
|
|
|
public FluidState getFlowing(int level, boolean falling) {
|
|
- return (FluidState) ((FluidState) this.getFlowing().defaultFluidState().setValue(FlowingFluid.LEVEL, level)).setValue(FlowingFluid.FALLING, falling);
|
|
+ // Moonrise start - fluid method optimisations
|
|
+ final int amount = level;
|
|
+ if (!this.init) {
|
|
+ this.init();
|
|
+ }
|
|
+ final int index = (falling ? 1 : 0) | ((amount - MIN_LEVEL) << 1);
|
|
+ return this.flowingLookUp[index];
|
|
+ // Moonrise end - fluid method optimisations
|
|
}
|
|
|
|
public abstract Fluid getSource();
|
|
|
|
public FluidState getSource(boolean falling) {
|
|
- return (FluidState) this.getSource().defaultFluidState().setValue(FlowingFluid.FALLING, falling);
|
|
+ // Moonrise start - fluid method optimisations
|
|
+ if (!this.init) {
|
|
+ this.init();
|
|
+ }
|
|
+ return falling ? this.sourceFalling : this.sourceNotFalling;
|
|
+ // Moonrise end - fluid method optimisations
|
|
}
|
|
|
|
protected abstract boolean canConvertToSource(Level world);
|
|
diff --git a/src/main/java/net/minecraft/world/level/material/FluidState.java b/src/main/java/net/minecraft/world/level/material/FluidState.java
|
|
index 14bb12d2a0066e8b020f2e0e670a7a5c74633623..49e07b51e7a516d71abc1976069be2d8b523c83c 100644
|
|
--- a/src/main/java/net/minecraft/world/level/material/FluidState.java
|
|
+++ b/src/main/java/net/minecraft/world/level/material/FluidState.java
|
|
@@ -21,7 +21,7 @@ import net.minecraft.world.level.block.state.properties.Property;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
|
|
|
-public final class FluidState extends StateHolder<Fluid, FluidState> {
|
|
+public final class FluidState extends StateHolder<Fluid, FluidState> implements ca.spottedleaf.moonrise.patches.fluid.FluidFluidState { // Moonrise - fluid method optimisations
|
|
public static final Codec<FluidState> CODEC = codec(BuiltInRegistries.FLUID.byNameCodec(), Fluid::defaultFluidState).stable();
|
|
public static final int AMOUNT_MAX = 9;
|
|
public static final int AMOUNT_FULL = 8;
|
|
@@ -32,20 +32,38 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
|
|
this.isEmpty = fluid.isEmpty(); // Paper - Perf: moved from isEmpty()
|
|
}
|
|
|
|
+ // Moonrise start - fluid method optimisations
|
|
+ private int amount;
|
|
+ //private boolean isEmpty;
|
|
+ private boolean isSource;
|
|
+ private float ownHeight;
|
|
+ private boolean isRandomlyTicking;
|
|
+ private BlockState legacyBlock;
|
|
+
|
|
+ @Override
|
|
+ public final void moonrise$initCaches() {
|
|
+ this.amount = this.getType().getAmount((FluidState) (Object) this);
|
|
+ //this.isEmpty = this.getType().isEmpty();
|
|
+ this.isSource = this.getType().isSource((FluidState) (Object) this);
|
|
+ this.ownHeight = this.getType().getOwnHeight((FluidState) (Object) this);
|
|
+ this.isRandomlyTicking = this.getType().isRandomlyTicking();
|
|
+ }
|
|
+ // Moonrise end - fluid method optimisations
|
|
+
|
|
public Fluid getType() {
|
|
return this.owner;
|
|
}
|
|
|
|
public boolean isSource() {
|
|
- return this.getType().isSource(this);
|
|
+ return this.isSource; // Moonrise - fluid method optimisations
|
|
}
|
|
|
|
public boolean isSourceOfType(Fluid fluid) {
|
|
- return this.owner == fluid && this.owner.isSource(this);
|
|
+ return this.isSource && this.owner == fluid; // Moonrise - fluid method optimisations
|
|
}
|
|
|
|
public boolean isEmpty() {
|
|
- return this.isEmpty; // Paper - Perf: moved into constructor
|
|
+ return this.isEmpty; // Moonrise - Perf: moved into constructor
|
|
}
|
|
|
|
public float getHeight(BlockGetter world, BlockPos pos) {
|
|
@@ -53,11 +71,11 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
|
|
}
|
|
|
|
public float getOwnHeight() {
|
|
- return this.getType().getOwnHeight(this);
|
|
+ return this.ownHeight; // Moonrise - fluid method optimisations
|
|
}
|
|
|
|
public int getAmount() {
|
|
- return this.getType().getAmount(this);
|
|
+ return this.amount; // Moonrise - fluid method optimisations
|
|
}
|
|
|
|
public boolean shouldRenderBackwardUpFace(BlockGetter world, BlockPos pos) {
|
|
@@ -83,7 +101,7 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
|
|
}
|
|
|
|
public boolean isRandomlyTicking() {
|
|
- return this.getType().isRandomlyTicking();
|
|
+ return this.isRandomlyTicking; // Moonrise - fluid method optimisations
|
|
}
|
|
|
|
public void randomTick(Level world, BlockPos pos, RandomSource random) {
|
|
@@ -95,7 +113,12 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
|
|
}
|
|
|
|
public BlockState createLegacyBlock() {
|
|
- return this.getType().createLegacyBlock(this);
|
|
+ // Moonrise start - fluid method optimisations
|
|
+ if (this.legacyBlock != null) {
|
|
+ return this.legacyBlock;
|
|
+ }
|
|
+ return this.legacyBlock = this.getType().createLegacyBlock((FluidState) (Object) this);
|
|
+ // Moonrise end - fluid method optimisations
|
|
}
|
|
|
|
@Nullable
|