Got rid of a mixin.
This commit is contained in:
@@ -1,34 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package li.cil.oc2.common.ext;
|
||||
|
||||
import li.cil.oc2.common.mixin.ChunkMapMixin;
|
||||
import li.cil.oc2.common.util.ChunkUtils;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
|
||||
/**
|
||||
* Interface injected into the {@link ChunkAccess} class.
|
||||
* <p>
|
||||
* Tracks a "lazy unsaved" flag, which is converted into the regular unsaved flag
|
||||
* before certain manual save operations.
|
||||
*
|
||||
* @see ChunkUtils
|
||||
* @see ChunkMapMixin
|
||||
*/
|
||||
public interface ChunkAccessExt {
|
||||
/**
|
||||
* Set the lazy unsaved flag for this instance.
|
||||
* <p>
|
||||
* This method is used by the utility methods in {@link ChunkUtils}.
|
||||
*/
|
||||
void setLazyUnsaved();
|
||||
|
||||
/**
|
||||
* Set the unsaved flag for this instance, if the lazy unsaved flag is set,
|
||||
* then clears the lazy unsaved flag.
|
||||
* <p>
|
||||
* This method is invoked from mixins injected into the {@link ChunkMap} class.
|
||||
*/
|
||||
void applyAndClearLazyUnsaved();
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package li.cil.oc2.common.mixin;
|
||||
|
||||
import li.cil.oc2.common.ext.ChunkAccessExt;
|
||||
import li.cil.oc2.common.util.ChunkUtils;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
/**
|
||||
* Tracks a "lazy unsaved" flag per {@link ChunkAccess} instance, to allow
|
||||
* marking chunks as needing saving just in time for "hard" saves.
|
||||
*
|
||||
* @see ChunkMapMixin <c>ChunkMapMixin</c> for more information
|
||||
* @see ChunkUtils
|
||||
*/
|
||||
@Mixin(ChunkAccess.class)
|
||||
public abstract class ChunkAccessMixin implements ChunkAccessExt {
|
||||
@Shadow
|
||||
protected volatile boolean unsaved;
|
||||
|
||||
private volatile boolean lazyUnsaved;
|
||||
|
||||
@Override
|
||||
public void setLazyUnsaved() {
|
||||
lazyUnsaved = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyAndClearLazyUnsaved() {
|
||||
if (!unsaved && lazyUnsaved) {
|
||||
unsaved = true;
|
||||
}
|
||||
lazyUnsaved = false;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package li.cil.oc2.common.mixin;
|
||||
|
||||
import com.mojang.datafixers.DataFixer;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||
import li.cil.oc2.common.ext.ChunkAccessExt;
|
||||
import li.cil.oc2.common.util.ChunkUtils;
|
||||
import net.minecraft.server.level.ChunkHolder;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.storage.ChunkStorage;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Hooks into {@link ChunkMap} saving code-paths for "hard" save operations.
|
||||
* <p>
|
||||
* Minecraft immediately serializes all chunk data, including {@link BlockEntity} NBT.
|
||||
* This is a massive performance issue for blocks with state that changes every tick,
|
||||
* such as computers and things accepting energy.
|
||||
* <p>
|
||||
* To avoid this per-frame serialization operations, we track a "lazy unsaved" flag per
|
||||
* {@link ChunkAccess} using the {@link ChunkAccessMixin}, and flush this flag into the
|
||||
* real unsaved flag during "hard" save operations, just before the flag would be
|
||||
* checked. These save operations include:
|
||||
* <ul>
|
||||
* <li>Chunk unloaded.</li>
|
||||
* <li>Game paused (singleplayer).</li>
|
||||
* <li>Save command.</li>
|
||||
* <li>Server stopped.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* The flag is set using the injected interface {@link ChunkAccessExt}, via the utility
|
||||
* methods in {@link ChunkUtils}.
|
||||
*
|
||||
* @see ChunkAccessMixin
|
||||
* @see ChunkUtils
|
||||
*/
|
||||
@Mixin(ChunkMap.class)
|
||||
public abstract class ChunkMapMixin extends ChunkStorage {
|
||||
@Shadow private volatile Long2ObjectLinkedOpenHashMap<ChunkHolder> visibleChunkMap;
|
||||
|
||||
public ChunkMapMixin(final Path path, final DataFixer dataFixer, final boolean sync) {
|
||||
super(path, dataFixer, sync);
|
||||
}
|
||||
|
||||
@Inject(method = "saveAllChunks", at = {@At(value = "HEAD")})
|
||||
private void beforeAsyncSave(final CallbackInfo ci) {
|
||||
visibleChunkMap.values().forEach(holder -> {
|
||||
if (holder.wasAccessibleSinceLastSave()) {
|
||||
final ChunkAccess chunkToSave = holder.getChunkToSave().getNow(null);
|
||||
if (chunkToSave instanceof ChunkAccessExt ext) {
|
||||
ext.applyAndClearLazyUnsaved();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package li.cil.oc2.common.mixin;
|
||||
|
||||
import li.cil.oc2.common.util.ChunkUtils;
|
||||
import net.minecraft.server.level.ServerChunkCache;
|
||||
import net.minecraft.world.level.chunk.ChunkSource;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ServerChunkCache.class)
|
||||
public abstract class ServerChunkCacheMixin extends ChunkSource {
|
||||
@Inject(method = "save", at = @At("HEAD"))
|
||||
private void applyLazyUnsavedChunks(final CallbackInfo ci) {
|
||||
ChunkUtils.applyChunkLazyUnsaved();
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
package li.cil.oc2.common.util;
|
||||
|
||||
import li.cil.oc2.api.API;
|
||||
import li.cil.oc2.common.ext.ChunkAccessExt;
|
||||
import li.cil.oc2.common.mixin.ServerChunkCacheMixin;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
@@ -13,8 +13,18 @@ import net.minecraftforge.event.world.ChunkEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = API.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
|
||||
public final class ChunkUtils {
|
||||
/**
|
||||
* All chunks marked for lazy saving. The lazy unsaved state will be applied when
|
||||
* chunks unload and when chunks get explicitly saved, via the {@link ServerChunkCacheMixin}.
|
||||
*/
|
||||
private static final Set<ChunkAccess> UNSAVED_CHUNKS = Collections.synchronizedSet(Collections.newSetFromMap(new WeakHashMap<>()));
|
||||
|
||||
/**
|
||||
* This will mark a chunk unsaved lazily, right before an attempt to save it would be made due
|
||||
* to of these events:
|
||||
@@ -36,9 +46,7 @@ public final class ChunkUtils {
|
||||
* @param chunkAccess the chunk to set the flag for.
|
||||
*/
|
||||
public static void setLazyUnsaved(final ChunkAccess chunkAccess) {
|
||||
if (chunkAccess instanceof ChunkAccessExt ext) {
|
||||
ext.setLazyUnsaved();
|
||||
}
|
||||
UNSAVED_CHUNKS.add(chunkAccess);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,10 +107,24 @@ public final class ChunkUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the specified as unsaved, if it was marked as lazy unsaved before
|
||||
* and clears the lazy unsaved flags.
|
||||
*
|
||||
* @param chunk the chunk to apply the lazy unsaved state for.
|
||||
*/
|
||||
public static void applyChunkLazyUnsaved() {
|
||||
for (final ChunkAccess chunk : UNSAVED_CHUNKS) {
|
||||
chunk.setUnsaved(true);
|
||||
}
|
||||
UNSAVED_CHUNKS.clear();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void handleChunkUnload(final ChunkEvent.Unload event) {
|
||||
if (event.getChunk() instanceof ChunkAccessExt ext) {
|
||||
ext.applyAndClearLazyUnsaved();
|
||||
final ChunkAccess chunk = event.getChunk();
|
||||
if (UNSAVED_CHUNKS.remove(chunk)) {
|
||||
chunk.setUnsaved(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
{
|
||||
"minVersion": "0.8",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"required": true,
|
||||
"package": "li.cil.oc2.common.mixin",
|
||||
"refmap": "mixins.oc2.refmap.json",
|
||||
"mixins": [
|
||||
"ChunkAccessMixin",
|
||||
"ChunkMapMixin"
|
||||
],
|
||||
"client": [
|
||||
"FrustumMixin",
|
||||
"LevelRendererMixin",
|
||||
"MinecraftMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
"minVersion": "0.8.5",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"required": true,
|
||||
"package": "li.cil.oc2.common.mixin",
|
||||
"refmap": "mixins.oc2.refmap.json",
|
||||
"mixins": [
|
||||
"ServerChunkCacheMixin"
|
||||
],
|
||||
"client": [
|
||||
"FrustumMixin",
|
||||
"LevelRendererMixin",
|
||||
"MinecraftMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user