mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-29 08:26:37 +01:00
Fix chunk caching race condition add toggle
- /flywheel chunkCaching on|off - synchronized ftw
This commit is contained in:
parent
a5850a46c8
commit
b530ea1be5
5 changed files with 69 additions and 12 deletions
|
@ -43,6 +43,7 @@ public class Backend {
|
||||||
private Matrix4f projectionMatrix = new Matrix4f();
|
private Matrix4f projectionMatrix = new Matrix4f();
|
||||||
private boolean instancedArrays;
|
private boolean instancedArrays;
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
|
public boolean chunkCachingEnabled;
|
||||||
|
|
||||||
private final List<IShaderContext<?>> contexts = new ArrayList<>();
|
private final List<IShaderContext<?>> contexts = new ArrayList<>();
|
||||||
private final Map<ResourceLocation, MaterialSpec<?>> materialRegistry = new HashMap<>();
|
private final Map<ResourceLocation, MaterialSpec<?>> materialRegistry = new HashMap<>();
|
||||||
|
@ -153,6 +154,8 @@ public class Backend {
|
||||||
|
|
||||||
enabled = FlwConfig.get()
|
enabled = FlwConfig.get()
|
||||||
.enabled() && !OptifineHandler.usingShaders();
|
.enabled() && !OptifineHandler.usingShaders();
|
||||||
|
chunkCachingEnabled = FlwConfig.get()
|
||||||
|
.chunkCaching();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canUseInstancing(@Nullable World world) {
|
public boolean canUseInstancing(@Nullable World world) {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
public enum BooleanConfig {
|
public enum BooleanConfig {
|
||||||
ENGINE(() -> BooleanConfig::enabled),
|
ENGINE(() -> BooleanConfig::enabled),
|
||||||
NORMAL_OVERLAY(() -> BooleanConfig::normalOverlay),
|
NORMAL_OVERLAY(() -> BooleanConfig::normalOverlay),
|
||||||
|
CHUNK_CACHING(() -> BooleanConfig::chunkCaching),
|
||||||
;
|
;
|
||||||
|
|
||||||
final Supplier<Consumer<BooleanDirective>> receiver;
|
final Supplier<Consumer<BooleanDirective>> receiver;
|
||||||
|
@ -71,6 +72,25 @@ public enum BooleanConfig {
|
||||||
player.displayClientMessage(text, false);
|
player.displayClientMessage(text, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
private static void chunkCaching(BooleanDirective state) {
|
||||||
|
ClientPlayerEntity player = Minecraft.getInstance().player;
|
||||||
|
if (player == null || state == null) return;
|
||||||
|
|
||||||
|
if (state == BooleanDirective.DISPLAY) {
|
||||||
|
ITextComponent text = new StringTextComponent("Chunk caching is currently: ").append(boolToText(FlwConfig.get().client.debugNormals.get()));
|
||||||
|
player.displayClientMessage(text, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlwConfig.get().client.chunkCaching.set(state.get());
|
||||||
|
|
||||||
|
ITextComponent text = boolToText(FlwConfig.get().client.chunkCaching.get()).append(new StringTextComponent(" chunk caching").withStyle(TextFormatting.WHITE));
|
||||||
|
|
||||||
|
player.displayClientMessage(text, false);
|
||||||
|
Backend.reloadWorldRenderers();
|
||||||
|
}
|
||||||
|
|
||||||
private static IFormattableTextComponent boolToText(boolean b) {
|
private static IFormattableTextComponent boolToText(boolean b) {
|
||||||
return b ? new StringTextComponent("enabled").withStyle(TextFormatting.DARK_GREEN) : new StringTextComponent("disabled").withStyle(TextFormatting.RED);
|
return b ? new StringTextComponent("enabled").withStyle(TextFormatting.DARK_GREEN) : new StringTextComponent("disabled").withStyle(TextFormatting.RED);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ public class FlwCommands {
|
||||||
|
|
||||||
dispatcher.register(Commands.literal("flywheel")
|
dispatcher.register(Commands.literal("flywheel")
|
||||||
.then(new BooleanConfigCommand("backend", BooleanConfig.ENGINE).register())
|
.then(new BooleanConfigCommand("backend", BooleanConfig.ENGINE).register())
|
||||||
.then(new BooleanConfigCommand("debugNormals", BooleanConfig.NORMAL_OVERLAY).register()));
|
.then(new BooleanConfigCommand("debugNormals", BooleanConfig.NORMAL_OVERLAY).register())
|
||||||
|
.then(new BooleanConfigCommand("chunkCaching", BooleanConfig.CHUNK_CACHING).register())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,12 +34,17 @@ public class FlwConfig {
|
||||||
return client.debugNormals.get();
|
return client.debugNormals.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean chunkCaching() {
|
||||||
|
return client.chunkCaching.get();
|
||||||
|
}
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ClientConfig {
|
public static class ClientConfig {
|
||||||
public final BooleanValue enabled;
|
public final BooleanValue enabled;
|
||||||
public final BooleanValue debugNormals;
|
public final BooleanValue debugNormals;
|
||||||
|
public final BooleanValue chunkCaching;
|
||||||
|
|
||||||
public ClientConfig(ForgeConfigSpec.Builder builder) {
|
public ClientConfig(ForgeConfigSpec.Builder builder) {
|
||||||
|
|
||||||
|
@ -48,6 +53,9 @@ public class FlwConfig {
|
||||||
|
|
||||||
debugNormals = builder.comment("Enable or disable a debug overlay that colors pixels by their normal")
|
debugNormals = builder.comment("Enable or disable a debug overlay that colors pixels by their normal")
|
||||||
.define("debugNormals", false);
|
.define("debugNormals", false);
|
||||||
|
|
||||||
|
chunkCaching = builder.comment("Cache chunk lookups to improve performance.")
|
||||||
|
.define("chunkCaching", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package com.jozufozu.flywheel.mixin;
|
package com.jozufozu.flywheel.mixin;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
@ -8,7 +10,10 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
|
|
||||||
import net.minecraft.client.multiplayer.ClientChunkProvider;
|
import net.minecraft.client.multiplayer.ClientChunkProvider;
|
||||||
|
import net.minecraft.client.world.ClientWorld;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.network.PacketBuffer;
|
import net.minecraft.network.PacketBuffer;
|
||||||
import net.minecraft.world.biome.BiomeContainer;
|
import net.minecraft.world.biome.BiomeContainer;
|
||||||
|
@ -20,6 +25,9 @@ import net.minecraft.world.chunk.IChunk;
|
||||||
@Mixin(ClientChunkProvider.class)
|
@Mixin(ClientChunkProvider.class)
|
||||||
public abstract class FastChunkProviderMixin extends AbstractChunkProvider {
|
public abstract class FastChunkProviderMixin extends AbstractChunkProvider {
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private ClientWorld level;
|
||||||
@Unique
|
@Unique
|
||||||
private int lastX;
|
private int lastX;
|
||||||
@Unique
|
@Unique
|
||||||
|
@ -32,36 +40,52 @@ public abstract class FastChunkProviderMixin extends AbstractChunkProvider {
|
||||||
at = @At("HEAD"),
|
at = @At("HEAD"),
|
||||||
cancellable = true)
|
cancellable = true)
|
||||||
public void returnCachedChunk(int x, int z, ChunkStatus status, boolean create, CallbackInfoReturnable<IChunk> cir) {
|
public void returnCachedChunk(int x, int z, ChunkStatus status, boolean create, CallbackInfoReturnable<IChunk> cir) {
|
||||||
if (status.isOrAfter(ChunkStatus.FULL) && lastChunk != null && x == lastX && z == lastZ) {
|
if (Backend.getInstance().chunkCachingEnabled && status.isOrAfter(ChunkStatus.FULL)) {
|
||||||
cir.setReturnValue(lastChunk);
|
synchronized (level) {
|
||||||
|
if (lastChunk != null && x == lastX && z == lastZ) {
|
||||||
|
cir.setReturnValue(lastChunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "getChunk",
|
@Inject(method = "getChunk",
|
||||||
at = @At("RETURN"))
|
at = @At("RETURN"))
|
||||||
public void cacheChunk(int x, int z, ChunkStatus status, boolean create, CallbackInfoReturnable<IChunk> cir) {
|
public void cacheChunk(int x, int z, ChunkStatus status, boolean create, CallbackInfoReturnable<IChunk> cir) {
|
||||||
if (status.isOrAfter(ChunkStatus.FULL)) {
|
if (Backend.getInstance().chunkCachingEnabled && status.isOrAfter(ChunkStatus.FULL)) {
|
||||||
lastChunk = cir.getReturnValue();
|
synchronized (level) {
|
||||||
lastX = x;
|
lastChunk = cir.getReturnValue();
|
||||||
lastZ = z;
|
lastX = x;
|
||||||
|
lastZ = z;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "drop", at = @At("HEAD"))
|
@Inject(method = "drop", at = @At("HEAD"))
|
||||||
public void invalidateOnDrop(int x, int z, CallbackInfo ci) {
|
public void invalidateOnDrop(int x, int z, CallbackInfo ci) {
|
||||||
if (x == lastX && z == lastZ)
|
if (Backend.getInstance().chunkCachingEnabled) {
|
||||||
lastChunk = null;
|
synchronized (level) {
|
||||||
|
if (x == lastX && z == lastZ) lastChunk = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "replaceWithPacketData", at = @At("HEAD"))
|
@Inject(method = "replaceWithPacketData", at = @At("HEAD"))
|
||||||
public void invalidateOnPacket(int x, int z, BiomeContainer p_228313_3_, PacketBuffer p_228313_4_, CompoundNBT p_228313_5_, int p_228313_6_, boolean p_228313_7_, CallbackInfoReturnable<Chunk> cir) {
|
public void invalidateOnPacket(int x, int z, BiomeContainer p_228313_3_, PacketBuffer p_228313_4_, CompoundNBT p_228313_5_, int p_228313_6_, boolean p_228313_7_, CallbackInfoReturnable<Chunk> cir) {
|
||||||
if (x == lastX && z == lastZ)
|
if (Backend.getInstance().chunkCachingEnabled) {
|
||||||
lastChunk = null;
|
synchronized (level) {
|
||||||
|
if (x == lastX && z == lastZ) lastChunk = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Redirect(method = "isTickingChunk", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientChunkProvider;hasChunk(II)Z"))
|
@Redirect(method = "isTickingChunk", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientChunkProvider;hasChunk(II)Z"))
|
||||||
public boolean redirectTicking(ClientChunkProvider clientChunkProvider, int x, int z) {
|
public boolean redirectTicking(ClientChunkProvider clientChunkProvider, int x, int z) {
|
||||||
if (lastChunk != null && x == lastX && z == lastZ) return true;
|
if (Backend.getInstance().chunkCachingEnabled) {
|
||||||
|
synchronized (level) {
|
||||||
|
if (lastChunk != null && x == lastX && z == lastZ) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return clientChunkProvider.hasChunk(x, z);
|
return clientChunkProvider.hasChunk(x, z);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue