Skip to content

Commit 317413b

Browse files
committed
Merge branch 'dev/1.21.5' into dev/1.21.6
2 parents 422d79f + 0432c59 commit 317413b

File tree

10 files changed

+330
-9
lines changed

10 files changed

+330
-9
lines changed

c2me-base/src/main/java/com/ishland/c2me/base/ModuleEntryPoint.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ public class ModuleEntryPoint {
5858
.incompatibleMod("textile_backup", "*")
5959
.getBoolean(true, false);
6060

61+
public static final boolean preventEarlyClientMovementTicks = new ConfigSystem.ConfigAccessor()
62+
.key("fixes.preventEarlyClientMovementTicks")
63+
.comment("""
64+
Whether to prevent early client ticks.
65+
66+
This avoids the player from falling through the world.
67+
Mitigates https://github.com/CaffeineMC/sodium/issues/3065
68+
""")
69+
.getBoolean(true, false);
70+
6171
public static final int defaultParallelism;
6272

6373
private static int tryEvaluateExpression(String expression) {

c2me-base/src/main/java/com/ishland/c2me/base/TheMixinPlugin.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
1616
if (mixinClassName.startsWith("com.ishland.c2me.base.mixin.util.log4j2shutdownhookisnomore."))
1717
return ModuleEntryPoint.disableLoggingShutdownHook;
1818

19+
if (mixinClassName.startsWith("com.ishland.c2me.base.mixin.client_movement."))
20+
return ModuleEntryPoint.preventEarlyClientMovementTicks;
21+
1922
return true;
2023
}
2124
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.ishland.c2me.base.mixin.access;
2+
3+
import net.minecraft.block.BlockState;
4+
import net.minecraft.fluid.FlowableFluid;
5+
import net.minecraft.fluid.Fluid;
6+
import net.minecraft.fluid.FluidState;
7+
import net.minecraft.util.math.BlockPos;
8+
import net.minecraft.util.math.Direction;
9+
import net.minecraft.world.BlockView;
10+
import net.minecraft.world.WorldView;
11+
import org.spongepowered.asm.mixin.Mixin;
12+
import org.spongepowered.asm.mixin.gen.Invoker;
13+
14+
@Mixin(FlowableFluid.class)
15+
public interface IFlowableFluid {
16+
17+
@Invoker
18+
boolean invokeCanFlowThrough(BlockView world, BlockPos pos, BlockState state, Direction face, BlockPos fromPos, BlockState fromState, FluidState fluidState);
19+
20+
@Invoker
21+
int invokeGetLevelDecreasePerBlock(WorldView world);
22+
23+
@Invoker
24+
boolean invokeCanFlowDownTo(BlockView world, BlockPos pos, BlockState state, BlockPos fromPos, BlockState fromState);
25+
26+
@Invoker
27+
public static boolean invokeCanFillWithFluid(BlockView world, BlockPos pos, BlockState state, Fluid fluid) {
28+
throw new AbstractMethodError();
29+
}
30+
31+
@Invoker
32+
public static boolean invokeReceivesFlow(Direction face, BlockView world, BlockPos pos, BlockState state, BlockPos fromPos, BlockState fromState) {
33+
throw new AbstractMethodError();
34+
}
35+
36+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.ishland.c2me.base.mixin.access;
2+
3+
import net.minecraft.entity.player.PlayerEntity;
4+
import org.spongepowered.asm.mixin.Mixin;
5+
import org.spongepowered.asm.mixin.gen.Accessor;
6+
7+
@Mixin(PlayerEntity.class)
8+
public interface IPlayerEntity {
9+
10+
@Accessor
11+
boolean getLoaded();
12+
13+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.ishland.c2me.base.mixin.client_movement;
2+
3+
import com.ishland.c2me.base.mixin.access.IPlayerEntity;
4+
import com.mojang.authlib.GameProfile;
5+
import net.minecraft.client.network.AbstractClientPlayerEntity;
6+
import net.minecraft.client.network.ClientPlayerEntity;
7+
import net.minecraft.client.world.ClientWorld;
8+
import org.spongepowered.asm.mixin.Mixin;
9+
10+
@Mixin(ClientPlayerEntity.class)
11+
public abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity {
12+
13+
public MixinClientPlayerEntity(ClientWorld world, GameProfile profile) {
14+
super(world, profile);
15+
}
16+
17+
@Override
18+
public boolean isLoaded() {
19+
return ((IPlayerEntity) this).getLoaded();
20+
}
21+
22+
}

c2me-base/src/main/resources/c2me-base.mixins.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@
2121
"access.IChunkTickScheduler",
2222
"access.IDensityFunctionsCaveScaler",
2323
"access.IDensityFunctionTypesWeirdScaledSamplerRarityValueMapper",
24+
"access.IFlowableFluid",
2425
"access.IInterpolatedNoiseSampler",
2526
"access.IMultiNoiseBiomeSource",
2627
"access.INbtCompound",
2728
"access.INbtList",
2829
"access.IOctavePerlinNoiseSampler",
2930
"access.IPerlinNoiseSampler",
31+
"access.IPlayerEntity",
3032
"access.IRegionBasedStorage",
3133
"access.IRegionFile",
3234
"access.ISerializingRegionBasedStorage",
@@ -59,5 +61,8 @@
5961
"theinterface.MixinStorageIoWorker",
6062
"util.log4j2shutdownhookisnomore.MixinMain",
6163
"util.log4j2shutdownhookisnomore.MixinMinecraftDedicatedServer"
64+
],
65+
"client": [
66+
"client_movement.MixinClientPlayerEntity"
6267
]
6368
}

c2me-opts-allocs/src/main/java/com/ishland/c2me/opts/allocs/mixin/MixinUtil.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import java.util.List;
99
import java.util.concurrent.CompletableFuture;
10+
import java.util.function.BiConsumer;
1011
import java.util.stream.Collectors;
1112

1213
@Mixin(Util.class)
@@ -28,10 +29,14 @@ public static <V> CompletableFuture<List<V>> combineSafe(List<CompletableFuture<
2829
@Overwrite
2930
public static <V> CompletableFuture<List<V>> combine(List<CompletableFuture<V>> futures) {
3031
final CompletableFuture<List<V>> future = Combinators.collect(futures, Collectors.toList()).toCompletableFuture();
31-
CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)).exceptionally(e -> {
32-
future.completeExceptionally(e);
33-
return null;
34-
});
32+
BiConsumer<V, Throwable> action = (v, throwable) -> {
33+
if (throwable != null) {
34+
future.completeExceptionally(throwable);
35+
}
36+
};
37+
for (CompletableFuture<V> completableFuture : futures) {
38+
completableFuture.whenComplete(action);
39+
}
3540
return future;
3641
}
3742

@@ -42,11 +47,15 @@ public static <V> CompletableFuture<List<V>> combine(List<CompletableFuture<V>>
4247
@Overwrite
4348
public static <V> CompletableFuture<List<V>> combineCancellable(List<CompletableFuture<V>> futures) {
4449
final CompletableFuture<List<V>> future = Combinators.collect(futures, Collectors.toList()).toCompletableFuture();
45-
CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)).exceptionally(e -> {
46-
future.completeExceptionally(e);
47-
futures.forEach(f -> f.cancel(false));
48-
return null;
49-
});
50+
BiConsumer<V, Throwable> action = (v, throwable) -> {
51+
if (throwable != null) {
52+
future.completeExceptionally(throwable);
53+
futures.forEach(f -> f.cancel(false));
54+
}
55+
};
56+
for (CompletableFuture<V> completableFuture : futures) {
57+
completableFuture.whenComplete(action);
58+
}
5059
return future;
5160
}
5261

c2me-rewrites-chunk-system/src/main/java/com/ishland/c2me/rewrites/chunksystem/common/Config.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@ Whether to allow POIs (Point of Interest) to be unloaded
6969
""")
7070
.getBoolean(true, false);
7171

72+
public static final boolean filterFluidPostProcessing = new ConfigSystem.ConfigAccessor()
73+
.key("chunkSystem.filterFluidPostProcessing")
74+
.comment("""
75+
Whether to filter fluid post-processing on worldgen threads
76+
77+
The worldgen processes creates a lot of unnecessary fluid post-processing tasks,
78+
which can overload the server thread and cause stutters.
79+
This applies a rough filter to filter out fluids that are definitely not going to flow
80+
""")
81+
.getBoolean(true, false);
82+
7283
public static final boolean lowMemoryMode = new ConfigSystem.ConfigAccessor()
7384
.key("chunkSystem.lowMemoryMode")
7485
.comment("""
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
package com.ishland.c2me.rewrites.chunksystem.common.quirks;
2+
3+
import com.ishland.c2me.base.mixin.access.IFlowableFluid;
4+
import it.unimi.dsi.fastutil.shorts.Short2BooleanFunction;
5+
import it.unimi.dsi.fastutil.shorts.Short2BooleanMap;
6+
import it.unimi.dsi.fastutil.shorts.Short2BooleanOpenHashMap;
7+
import it.unimi.dsi.fastutil.shorts.Short2ObjectFunction;
8+
import it.unimi.dsi.fastutil.shorts.Short2ObjectMap;
9+
import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap;
10+
import net.minecraft.block.BlockState;
11+
import net.minecraft.fluid.FlowableFluid;
12+
import net.minecraft.fluid.Fluid;
13+
import net.minecraft.fluid.FluidState;
14+
import net.minecraft.fluid.Fluids;
15+
import net.minecraft.util.math.BlockPos;
16+
import net.minecraft.util.math.Direction;
17+
import net.minecraft.world.BlockView;
18+
import net.minecraft.world.WorldView;
19+
20+
public class FlowableFluidUtils {
21+
22+
public static boolean needsPostProcessing(WorldView world, BlockPos pos, BlockState blockState, FluidState fluidState) {
23+
if (!fluidState.isStill()) {
24+
return true;
25+
}
26+
return canFlowNormally(world, pos, blockState, fluidState);
27+
}
28+
29+
private static boolean canFlowNormally(WorldView world, BlockPos pos, BlockState blockState, FluidState fluidState) {
30+
if (fluidState.isEmpty()) return false;
31+
32+
BlockPos belowPos = pos.down();
33+
BlockState belowBlockState = world.getBlockState(belowPos);
34+
FluidState belowFluidState = belowBlockState.getFluidState();
35+
// very rough filtering
36+
if (((IFlowableFluid) fluidState.getFluid()).invokeCanFlowThrough(world, pos, blockState, Direction.DOWN, belowPos, belowBlockState, belowFluidState)) {
37+
FluidState fluidState3 = getUpdatedState(((FlowableFluid) fluidState.getFluid()), world, belowPos, belowBlockState);
38+
if (fluidState3 == null) {
39+
return true; // shortcut
40+
}
41+
Fluid fluid = fluidState3.getFluid();
42+
if (belowFluidState.canBeReplacedWith(world, belowPos, fluid, Direction.DOWN) && IFlowableFluid.invokeCanFillWithFluid(world, belowPos, belowBlockState, fluid)) {
43+
return true;
44+
}
45+
}
46+
if ((fluidState.isStill() || !(((IFlowableFluid) fluidState.getFluid()).invokeCanFlowDownTo(world, pos, blockState, belowPos, belowBlockState))) &&
47+
canSpreadToSidesNormally(world, pos, blockState, fluidState)) {
48+
return true;
49+
}
50+
51+
return false;
52+
}
53+
54+
private static boolean canSpreadToSidesNormally(WorldView world, BlockPos pos, BlockState blockState, FluidState fluidState) {
55+
int nextFluidLevel = fluidState.getLevel() - ((IFlowableFluid) fluidState.getFluid()).invokeGetLevelDecreasePerBlock(world);
56+
if (fluidState.get(FlowableFluid.FALLING)) {
57+
nextFluidLevel = 7;
58+
}
59+
if (nextFluidLevel > 0) {
60+
// getSpread
61+
// int i = 1000;
62+
// Map<Direction, FluidState> map = Maps.newEnumMap(Direction.class);
63+
// SpreadCache spreadCache = null;
64+
65+
for (Direction direction : Direction.Type.HORIZONTAL) {
66+
BlockPos offsetPos = pos.offset(direction);
67+
BlockState offsetBlockState = world.getBlockState(offsetPos);
68+
FluidState offsetFluidState = offsetBlockState.getFluidState();
69+
if (((IFlowableFluid) fluidState.getFluid()).invokeCanFlowThrough(world, pos, blockState, direction, offsetPos, offsetBlockState, offsetFluidState)) {
70+
FluidState fluidState2 = getUpdatedState((FlowableFluid) fluidState.getFluid(), world, offsetPos, offsetBlockState);
71+
if (fluidState2 == null) {
72+
return true; // shortcut
73+
}
74+
if (IFlowableFluid.invokeCanFillWithFluid(world, offsetPos, offsetBlockState, fluidState2.getFluid())) {
75+
return true; // shortcut
76+
}
77+
}
78+
}
79+
}
80+
81+
return false;
82+
}
83+
84+
private static FluidState getUpdatedState(FlowableFluid receiver, WorldView world, BlockPos pos, BlockState state) {
85+
int i = 0;
86+
int j = 0;
87+
BlockPos.Mutable mutable = new BlockPos.Mutable();
88+
89+
for (Direction direction : Direction.Type.HORIZONTAL) {
90+
BlockPos blockPos = mutable.set(pos, direction);
91+
BlockState blockState = world.getBlockState(blockPos);
92+
FluidState fluidState = blockState.getFluidState();
93+
if (fluidState.getFluid().matchesType(receiver) && IFlowableFluid.invokeReceivesFlow(direction, world, pos, state, blockPos, blockState)) {
94+
if (fluidState.isStill()) {
95+
j++;
96+
}
97+
98+
i = Math.max(i, fluidState.getLevel());
99+
}
100+
}
101+
102+
// if (j >= 2 && this.isInfinite(world)) {
103+
// BlockState blockState2 = world.getBlockState(mutable.set(pos, Direction.DOWN));
104+
// FluidState fluidState2 = blockState2.getFluidState();
105+
// if (blockState2.isSolid() || receiver.isMatchingAndStill(fluidState2)) {
106+
// return receiver.getStill(false);
107+
// }
108+
// }
109+
if (j >= 2) {
110+
return null; // to not filter this
111+
}
112+
113+
BlockPos blockPos2 = mutable.set(pos, Direction.UP);
114+
BlockState blockState3 = world.getBlockState(blockPos2);
115+
FluidState fluidState3 = blockState3.getFluidState();
116+
if (!fluidState3.isEmpty() && fluidState3.getFluid().matchesType(receiver) && IFlowableFluid.invokeReceivesFlow(Direction.UP, world, pos, state, blockPos2, blockState3)) {
117+
return receiver.getFlowing(8, true);
118+
} else {
119+
int k = i - ((IFlowableFluid) receiver).invokeGetLevelDecreasePerBlock(world);
120+
return k <= 0 ? Fluids.EMPTY.getDefaultState() : receiver.getFlowing(k, false);
121+
}
122+
}
123+
124+
private static class SpreadCache {
125+
private final FlowableFluid flowableFluid;
126+
private final BlockView world;
127+
private final BlockPos startPos;
128+
private final Short2ObjectMap<BlockState> stateCache = new Short2ObjectOpenHashMap<>();
129+
private final Short2BooleanMap flowDownCache = new Short2BooleanOpenHashMap();
130+
131+
SpreadCache(final FlowableFluid flowableFluid, final BlockView world, final BlockPos startPos) {
132+
this.flowableFluid = flowableFluid;
133+
this.world = world;
134+
this.startPos = startPos;
135+
}
136+
137+
public BlockState getBlockState(BlockPos pos) {
138+
return this.getBlockState(pos, this.pack(pos));
139+
}
140+
141+
private BlockState getBlockState(BlockPos pos, short packed) {
142+
return this.stateCache.computeIfAbsent(packed, (Short2ObjectFunction<? extends BlockState>)(packedPos -> this.world.getBlockState(pos)));
143+
}
144+
145+
public boolean canFlowDownTo(BlockPos pos) {
146+
return this.flowDownCache.computeIfAbsent(this.pack(pos), (Short2BooleanFunction)(packed -> {
147+
BlockState blockState = this.getBlockState(pos, packed);
148+
BlockPos blockPos2 = pos.down();
149+
BlockState blockState2 = this.world.getBlockState(blockPos2);
150+
return ((IFlowableFluid) this.flowableFluid).invokeCanFlowDownTo(this.world, pos, blockState, blockPos2, blockState2);
151+
}));
152+
}
153+
154+
private short pack(BlockPos pos) {
155+
int i = pos.getX() - this.startPos.getX();
156+
int j = pos.getZ() - this.startPos.getZ();
157+
return (short)((i + 128 & 0xFF) << 8 | j + 128 & 0xFF);
158+
}
159+
}
160+
161+
}

0 commit comments

Comments
 (0)