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 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<>();
@ -138,8 +137,6 @@ public class Backend {
enabled = FlwConfig.get() enabled = FlwConfig.get()
.enabled() && !OptifineHandler.usingShaders(); .enabled() && !OptifineHandler.usingShaders();
chunkCachingEnabled = FlwConfig.get()
.chunkCaching();
} }
public boolean canUseInstancing(@Nullable Level world) { 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. * @param te The tile whose instance you want to update.
*/ */
public static void enqueueUpdate(BlockEntity te) { 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.ChatFormatting;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
@ -18,7 +19,6 @@ 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;
@ -31,6 +31,27 @@ public enum BooleanConfig {
return new SConfigureBooleanPacket(this, directive); 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) @OnlyIn(Dist.CLIENT)
private static void enabled(BooleanDirective state) { private static void enabled(BooleanDirective state) {
LocalPlayer player = Minecraft.getInstance().player; LocalPlayer player = Minecraft.getInstance().player;
@ -72,25 +93,6 @@ public enum BooleanConfig {
player.displayClientMessage(text, false); 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) { private static MutableComponent boolToText(boolean b) {
return b ? new TextComponent("enabled").withStyle(ChatFormatting.DARK_GREEN) : new TextComponent("disabled").withStyle(ChatFormatting.RED); 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; package com.jozufozu.flywheel.config;
import net.minecraft.network.FriendlyByteBuf;
public enum BooleanDirective { public enum BooleanDirective {
TRUE(true), TRUE(true),
FALSE(false), FALSE(false),
@ -16,7 +18,21 @@ public enum BooleanDirective {
} }
public boolean get() { 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; 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") 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())
); );
} }
} }

View file

@ -34,17 +34,12 @@ 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) {
@ -53,9 +48,6 @@ 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);
} }
} }
} }

View file

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

View file

@ -4,6 +4,7 @@ import java.util.ArrayList;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.util.WorldAttached;
import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.light.LightUpdater;
import com.jozufozu.flywheel.util.ChunkIter; import com.jozufozu.flywheel.util.ChunkIter;
@ -52,6 +53,7 @@ public class ForgeEvents {
public static void unloadWorld(WorldEvent.Unload event) { public static void unloadWorld(WorldEvent.Unload event) {
LevelAccessor world = event.getWorld(); LevelAccessor world = event.getWorld();
ChunkIter._unload(world); ChunkIter._unload(world);
WorldAttached.invalidateWorld(world);
} }
@SubscribeEvent @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) { public static void _putStorageReference(BlockGetter level, AtomicReferenceArray<LevelChunk> storage) {
storages.put(level, storage); storages.put(level, storage);

View file

@ -1,6 +1,10 @@
package com.jozufozu.flywheel.util; package com.jozufozu.flywheel.util;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -12,12 +16,30 @@ import net.minecraft.world.level.LevelAccessor;
public class WorldAttached<T> { 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 Map<LevelAccessor, T> attached;
private final Function<LevelAccessor, T> factory; private final Function<LevelAccessor, T> factory;
public WorldAttached(Function<LevelAccessor, T> factory) { public WorldAttached(Function<LevelAccessor, T> factory) {
this.factory = factory; this.factory = factory;
attached = new HashMap<>(); 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 @Nonnull