Merge remote-tracking branch 'origin/1.16/dev' into 1.17/dev

# Conflicts:
#	changelog.txt
#	gradle.properties
#	src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java
#	src/main/java/com/jozufozu/flywheel/config/BooleanConfig.java
#	src/main/java/com/jozufozu/flywheel/config/SConfigureBooleanPacket.java
#	src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java
#	src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java
#	src/main/java/com/jozufozu/flywheel/util/WorldAttached.java
#	src/main/resources/flywheel.mixins.json
This commit is contained in:
Jozufozu 2021-11-23 16:21:37 -08:00
commit 881ce3639d
10 changed files with 74 additions and 41 deletions

View file

@ -40,7 +40,6 @@ public class Backend {
private boolean instancedArrays;
private boolean enabled;
public boolean chunkCachingEnabled;
private final List<IShaderContext<?>> contexts = new ArrayList<>();
private final Map<ResourceLocation, MaterialSpec<?>> materialRegistry = new HashMap<>();
@ -138,8 +137,6 @@ public class Backend {
enabled = FlwConfig.get()
.enabled() && !OptifineHandler.usingShaders();
chunkCachingEnabled = FlwConfig.get()
.chunkCaching();
}
public boolean canUseInstancing(@Nullable Level world) {

View file

@ -29,7 +29,8 @@ public class InstancedRenderDispatcher {
* @param te The tile whose instance you want to update.
*/
public static void enqueueUpdate(BlockEntity te) {
getTiles(te.getLevel()).queueUpdate(te);
if (te.hasLevel() && te.getLevel() instanceof ClientLevel)
getTiles(te.getLevel()).queueUpdate(te);
}
/**

View file

@ -9,6 +9,7 @@ import com.jozufozu.flywheel.backend.OptifineHandler;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.TextComponent;
@ -18,7 +19,6 @@ import net.minecraftforge.api.distmarker.OnlyIn;
public enum BooleanConfig {
ENGINE(() -> BooleanConfig::enabled),
NORMAL_OVERLAY(() -> BooleanConfig::normalOverlay),
CHUNK_CACHING(() -> BooleanConfig::chunkCaching),
;
final Supplier<Consumer<BooleanDirective>> receiver;
@ -31,6 +31,27 @@ public enum BooleanConfig {
return new SConfigureBooleanPacket(this, directive);
}
/**
* Encode a variant of BooleanConfig. Symmetrical function to {@link #decode}
*/
public void encode(FriendlyByteBuf buffer) {
buffer.writeByte(this.ordinal());
}
/**
* Safely decode a variant of BooleanConfig. Symmetrical function to {@link #encode}
*/
public static BooleanConfig decode(FriendlyByteBuf buffer) {
byte t = buffer.readByte();
BooleanConfig[] values = values();
// Protects against version differences.
// Shouldn't ever happen but do a sanity check for safety.
if (t >= 0 && t < values.length)
return values[t];
else
return null;
}
@OnlyIn(Dist.CLIENT)
private static void enabled(BooleanDirective state) {
LocalPlayer player = Minecraft.getInstance().player;
@ -72,25 +93,6 @@ public enum BooleanConfig {
player.displayClientMessage(text, false);
}
@OnlyIn(Dist.CLIENT)
private static void chunkCaching(BooleanDirective state) {
LocalPlayer player = Minecraft.getInstance().player;
if (player == null || state == null) return;
if (state == BooleanDirective.DISPLAY) {
Component text = new TextComponent("Chunk caching is currently: ").append(boolToText(FlwConfig.get().chunkCaching()));
player.displayClientMessage(text, false);
return;
}
FlwConfig.get().client.chunkCaching.set(state.get());
Component text = boolToText(FlwConfig.get().chunkCaching()).append(new TextComponent(" chunk caching").withStyle(ChatFormatting.WHITE));
player.displayClientMessage(text, false);
Backend.reloadWorldRenderers();
}
private static MutableComponent boolToText(boolean b) {
return b ? new TextComponent("enabled").withStyle(ChatFormatting.DARK_GREEN) : new TextComponent("disabled").withStyle(ChatFormatting.RED);
}

View file

@ -1,5 +1,7 @@
package com.jozufozu.flywheel.config;
import net.minecraft.network.FriendlyByteBuf;
public enum BooleanDirective {
TRUE(true),
FALSE(false),
@ -16,7 +18,21 @@ public enum BooleanDirective {
}
public boolean get() {
if (this == DISPLAY) throw new IllegalStateException("Cannot get value from DISPLAY directive");
if (this == DISPLAY) throw new IllegalStateException("DISPLAY directive has no value");
return b;
}
/**
* Encode a variant of BooleanDirective. Symmetrical function to {@link #decode}
*/
public void encode(FriendlyByteBuf buffer) {
buffer.writeByte(this.ordinal());
}
/**
* Safely decode a variant of BooleanDirective. Symmetrical function to {@link #encode}
*/
public static BooleanDirective decode(FriendlyByteBuf buffer) {
return values()[buffer.readByte()];
}
}

View file

@ -17,7 +17,6 @@ public class FlwCommands {
dispatcher.register(Commands.literal("flywheel")
.then(new BooleanConfigCommand("backend", BooleanConfig.ENGINE).register())
.then(new BooleanConfigCommand("debugNormals", BooleanConfig.NORMAL_OVERLAY).register())
.then(new BooleanConfigCommand("chunkCaching", BooleanConfig.CHUNK_CACHING).register())
);
}
}

View file

@ -34,17 +34,12 @@ public class FlwConfig {
return client.debugNormals.get();
}
public boolean chunkCaching() {
return client.chunkCaching.get();
}
public static void init() {
}
public static class ClientConfig {
public final BooleanValue enabled;
public final BooleanValue debugNormals;
public final BooleanValue chunkCaching;
public ClientConfig(ForgeConfigSpec.Builder builder) {
@ -53,9 +48,6 @@ public class FlwConfig {
debugNormals = builder.comment("Enable or disable a debug overlay that colors pixels by their normal")
.define("debugNormals", false);
chunkCaching = builder.comment("Cache chunk lookups to improve performance.")
.define("chunkCaching", true);
}
}
}

View file

@ -20,18 +20,20 @@ public class SConfigureBooleanPacket {
}
public SConfigureBooleanPacket(FriendlyByteBuf buffer) {
target = BooleanConfig.values()[buffer.readByte()];
directive = BooleanDirective.values()[buffer.readByte()];
target = BooleanConfig.decode(buffer);
directive = BooleanDirective.decode(buffer);
}
public void encode(FriendlyByteBuf buffer) {
buffer.writeByte(target.ordinal());
buffer.writeByte(directive.ordinal());
target.encode(buffer);
directive.encode(buffer);
}
public void execute(Supplier<NetworkEvent.Context> ctx) {
target.receiver.get()
.accept(directive);
if (directive != null) {
target.receiver.get()
.accept(directive);
}
ctx.get()
.setPacketHandled(true);
}

View file

@ -4,6 +4,7 @@ import java.util.ArrayList;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.util.WorldAttached;
import com.jozufozu.flywheel.light.LightUpdater;
import com.jozufozu.flywheel.util.ChunkIter;
@ -52,6 +53,7 @@ public class ForgeEvents {
public static void unloadWorld(WorldEvent.Unload event) {
LevelAccessor world = event.getWorld();
ChunkIter._unload(world);
WorldAttached.invalidateWorld(world);
}
@SubscribeEvent

View file

@ -34,7 +34,7 @@ public class ChunkIter {
}
}
// INTERNAL MAINTENENCE METHODS BELOW
// INTERNAL MAINTENANCE METHODS BELOW
public static void _putStorageReference(BlockGetter level, AtomicReferenceArray<LevelChunk> storage) {
storages.put(level, storage);

View file

@ -1,6 +1,10 @@
package com.jozufozu.flywheel.util;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
@ -12,12 +16,30 @@ import net.minecraft.world.level.LevelAccessor;
public class WorldAttached<T> {
// weak references to prevent leaking hashmaps when a WorldAttached is GC'd during runtime
static List<WeakReference<Map<LevelAccessor, ?>>> allMaps = new ArrayList<>();
private final Map<LevelAccessor, T> attached;
private final Function<LevelAccessor, T> factory;
public WorldAttached(Function<LevelAccessor, T> factory) {
this.factory = factory;
attached = new HashMap<>();
allMaps.add(new WeakReference<>(attached));
}
public static void invalidateWorld(LevelAccessor world) {
Iterator<WeakReference<Map<LevelAccessor, ?>>> i = allMaps.iterator();
while (i.hasNext()) {
Map<LevelAccessor, ?> map = i.next()
.get();
if (map == null) {
// If the map has been GC'd, remove the weak reference
i.remove();
} else {
// Prevent leaks
map.remove(world);
}
}
}
@Nonnull