Skip to content

Commit 17f930e

Browse files
committed
WIP chunk saving optimization
1 parent f23348c commit 17f930e

5 files changed

Lines changed: 102 additions & 0 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package org.embeddedt.modernfix.common.mixin.bugfix.skip_redundant_saves;
2+
3+
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
4+
import net.minecraft.server.level.ChunkHolder;
5+
import net.minecraft.world.level.chunk.ChunkAccess;
6+
import net.minecraft.world.level.chunk.LevelChunk;
7+
import org.spongepowered.asm.mixin.Mixin;
8+
import org.spongepowered.asm.mixin.Shadow;
9+
import org.spongepowered.asm.mixin.injection.At;
10+
11+
import javax.annotation.Nullable;
12+
13+
@Mixin(ChunkHolder.class)
14+
public abstract class ChunkHolderMixin {
15+
@Shadow
16+
@Nullable
17+
public abstract LevelChunk getTickingChunk();
18+
19+
/**
20+
* @author embeddedt
21+
* @reason prevent chunks from being flagged for saving when light engine is loading data from disk
22+
*/
23+
@WrapWithCondition(method = "sectionLightChanged", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/ChunkAccess;setUnsaved(Z)V"))
24+
private boolean onlyMarkUnsavedIfAlreadyTicking(ChunkAccess instance, boolean unsaved) {
25+
return this.getTickingChunk() != null;
26+
}
27+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.embeddedt.modernfix.common.mixin.bugfix.skip_redundant_saves;
2+
3+
import net.minecraft.server.level.ChunkMap;
4+
import net.minecraft.world.level.ChunkPos;
5+
import org.spongepowered.asm.mixin.Mixin;
6+
import org.spongepowered.asm.mixin.gen.Invoker;
7+
8+
@Mixin(ChunkMap.class)
9+
public interface ChunkMapAccessor {
10+
@Invoker("releaseLightTicket")
11+
void mfix$invokeReleaseLightTicket(ChunkPos pos);
12+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.embeddedt.modernfix.common.mixin.bugfix.skip_redundant_saves;
2+
3+
import com.llamalad7.mixinextras.sugar.Local;
4+
import net.minecraft.nbt.CompoundTag;
5+
import net.minecraft.server.level.ServerLevel;
6+
import net.minecraft.world.entity.ai.village.poi.PoiManager;
7+
import net.minecraft.world.level.ChunkPos;
8+
import net.minecraft.world.level.chunk.ChunkAccess;
9+
import net.minecraft.world.level.chunk.ProtoChunk;
10+
import net.minecraft.world.level.chunk.storage.ChunkSerializer;
11+
import org.spongepowered.asm.mixin.Mixin;
12+
import org.spongepowered.asm.mixin.injection.At;
13+
import org.spongepowered.asm.mixin.injection.Inject;
14+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
15+
16+
@Mixin(ChunkSerializer.class)
17+
public class ChunkSerializerMixin {
18+
/**
19+
* @author embeddedt
20+
* @reason When reloading chunks from disk, they by definition normally don't need saving unless they've changed.
21+
*/
22+
@Inject(method = "read", at = @At(value = "CONSTANT", args = "stringValue=PostProcessing", ordinal = 0))
23+
private static void updateUnsavedFlag(ServerLevel level, PoiManager poiManager, ChunkPos pos, CompoundTag tag, CallbackInfoReturnable<ProtoChunk> cir, @Local(ordinal = 0) ChunkAccess chunkaccess) {
24+
chunkaccess.setUnsaved(tag.getBoolean("shouldSave"));
25+
}
26+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.embeddedt.modernfix.common.mixin.bugfix.skip_redundant_saves;
2+
3+
import net.minecraft.server.level.ChunkMap;
4+
import net.minecraft.server.level.ThreadedLevelLightEngine;
5+
import net.minecraft.world.level.chunk.ChunkAccess;
6+
import org.spongepowered.asm.mixin.Final;
7+
import org.spongepowered.asm.mixin.Mixin;
8+
import org.spongepowered.asm.mixin.Shadow;
9+
import org.spongepowered.asm.mixin.injection.At;
10+
import org.spongepowered.asm.mixin.injection.Inject;
11+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
12+
13+
import java.util.concurrent.CompletableFuture;
14+
15+
@Mixin(ThreadedLevelLightEngine.class)
16+
public class ThreadedLevelLightEngineMixin {
17+
@Shadow
18+
@Final
19+
private ChunkMap chunkMap;
20+
21+
/**
22+
* @author embeddedt
23+
* @reason avoid toggling the lightCorrect flag when chunk is already lit, because it triggers saving
24+
*/
25+
@Inject(method = "lightChunk", at = @At("HEAD"), cancellable = true)
26+
private void skipLightCorrectFlagChange(ChunkAccess chunk, boolean isAlreadyLit, CallbackInfoReturnable<CompletableFuture<ChunkAccess>> cir) {
27+
if (isAlreadyLit) {
28+
((ChunkMapAccessor)this.chunkMap).mfix$invokeReleaseLightTicket(chunk.getPos());
29+
// Defensively ensure the lightCorrect flag is set properly on exit from this method
30+
if (!chunk.isLightCorrect()) {
31+
chunk.setLightCorrect(true);
32+
}
33+
cir.setReturnValue(CompletableFuture.completedFuture(chunk));
34+
}
35+
}
36+
}

src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ public DefaultSettingMapBuilder put(String key, Boolean value) {
184184
.put("mixin.feature.spam_thread_dump", false)
185185
.put("mixin.feature.disable_unihex_font", false)
186186
.put("mixin.feature.remove_chat_signing", false)
187+
.put("mixin.bugfix.skip_redundant_saves", false)
187188
.put("mixin.feature.snapshot_easter_egg", true)
188189
.put("mixin.feature.warn_missing_perf_mods", true)
189190
.put("mixin.feature.spark_profile_launch", false)

0 commit comments

Comments
 (0)