Skip to content

Commit 7dcaa6b

Browse files
committed
Merge remote-tracking branch 'origin/1.20' into 1.21.1
2 parents 6f3f754 + c3086e5 commit 7dcaa6b

File tree

11 files changed

+335
-90
lines changed

11 files changed

+335
-90
lines changed

common/src/main/java/org/embeddedt/modernfix/common/mixin/feature/disable_unihex_font/UnihexProviderDefinitionMixin.java

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.embeddedt.modernfix.common.mixin.perf.compress_unihex_font;
2+
3+
import com.llamalad7.mixinextras.sugar.Local;
4+
import it.unimi.dsi.fastutil.bytes.ByteList;
5+
import net.minecraft.client.gui.font.providers.UnihexProvider;
6+
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
7+
import org.embeddedt.modernfix.render.font.CompactUnihexContents;
8+
import org.spongepowered.asm.mixin.Mixin;
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+
@Mixin(targets = {"net/minecraft/client/gui/font/providers/UnihexProvider$ByteContents"})
14+
@ClientOnlyMixin
15+
public class UnihexProviderByteContentsMixin {
16+
@Inject(method = "read", at = @At(value = "NEW", target = "([B)Lnet/minecraft/client/gui/font/providers/UnihexProvider$ByteContents;"), cancellable = true)
17+
private static void useCompactIfPossible(int index, ByteList byteList, CallbackInfoReturnable<UnihexProvider.LineData> cir, @Local(ordinal = 0) byte[] contents) {
18+
if (contents.length == 16) {
19+
cir.setReturnValue(new CompactUnihexContents.Bytes(contents));
20+
}
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.embeddedt.modernfix.common.mixin.perf.compress_unihex_font;
2+
3+
import com.llamalad7.mixinextras.sugar.Local;
4+
import it.unimi.dsi.fastutil.bytes.ByteList;
5+
import net.minecraft.client.gui.font.providers.UnihexProvider;
6+
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
7+
import org.embeddedt.modernfix.render.font.CompactUnihexContents;
8+
import org.spongepowered.asm.mixin.Mixin;
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+
@Mixin(targets = {"net/minecraft/client/gui/font/providers/UnihexProvider$ShortContents"})
14+
@ClientOnlyMixin
15+
public class UnihexProviderShortContentsMixin {
16+
@Inject(method = "read", at = @At(value = "NEW", target = "([S)Lnet/minecraft/client/gui/font/providers/UnihexProvider$ShortContents;"), cancellable = true)
17+
private static void useCompactIfPossible(int index, ByteList byteList, CallbackInfoReturnable<UnihexProvider.LineData> cir, @Local(ordinal = 0) short[] contents) {
18+
if (contents.length == 16) {
19+
cir.setReturnValue(new CompactUnihexContents.Shorts(contents));
20+
}
21+
}
22+
}

common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/fix_loop_spin_waiting/BlockableEventLoopMixin.java

Lines changed: 0 additions & 23 deletions
This file was deleted.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package org.embeddedt.modernfix.common.mixin.perf.fix_loop_spin_waiting;
2+
3+
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
4+
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
5+
import net.minecraft.Util;
6+
import net.minecraft.server.MinecraftServer;
7+
import net.minecraft.util.thread.BlockableEventLoop;
8+
import org.spongepowered.asm.mixin.Mixin;
9+
import org.spongepowered.asm.mixin.Shadow;
10+
import org.spongepowered.asm.mixin.Unique;
11+
import org.spongepowered.asm.mixin.injection.At;
12+
13+
import java.util.concurrent.locks.LockSupport;
14+
import java.util.function.BooleanSupplier;
15+
16+
@Mixin(value = MinecraftServer.class, priority = 500)
17+
public abstract class MinecraftServerMixin extends BlockableEventLoop<Runnable> {
18+
@Shadow private long nextTickTimeNanos;
19+
20+
protected MinecraftServerMixin(String name) {
21+
super(name);
22+
}
23+
24+
@Unique
25+
private boolean mfix$isWaitingForNextTick = false;
26+
27+
@WrapOperation(
28+
method = "waitUntilNextTick",
29+
at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;managedBlock(Ljava/util/function/BooleanSupplier;)V")
30+
)
31+
private void managedBlock(MinecraftServer instance, BooleanSupplier isDone, Operation<Void> original) {
32+
try {
33+
this.mfix$isWaitingForNextTick = true;
34+
original.call(instance, isDone);
35+
} finally {
36+
this.mfix$isWaitingForNextTick = false;
37+
}
38+
}
39+
40+
@Override
41+
public void waitForTasks() {
42+
if (this.mfix$isWaitingForNextTick) {
43+
LockSupport.parkNanos("waiting for tasks", this.nextTickTimeNanos - Util.getNanos());
44+
} else {
45+
super.waitForTasks();
46+
}
47+
}
48+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package org.embeddedt.modernfix.render.font;
2+
3+
import net.minecraft.client.gui.font.providers.UnihexProvider;
4+
5+
/**
6+
* Implements more compact storage for LineData contents.
7+
*
8+
* Credit for the idea of using flattened fields rather than a backing array goes to @AnAwesomGuy.
9+
*/
10+
public class CompactUnihexContents {
11+
private static long extract8Bytes(byte[] arr, int off) {
12+
long l = 0;
13+
for (int i = 0; i < 8; i++) {
14+
l |= ((long)arr[off + i] << (i * 8));
15+
}
16+
return l;
17+
}
18+
19+
private static byte extractByte(long compressed, int off) {
20+
return (byte)((compressed >> (off * 8)) & 0xFF);
21+
}
22+
23+
private static long extract4Shorts(short[] arr, int off) {
24+
long l = 0;
25+
for (int i = 0; i < 4; i++) {
26+
l |= ((long)arr[off + i] << (i * 16));
27+
}
28+
return l;
29+
}
30+
31+
private static short extractShort(long compressed, int off) {
32+
return (short)((compressed >> (off * 16)) & 0xFFFF);
33+
}
34+
35+
public static class Bytes implements UnihexProvider.LineData {
36+
private final long b0;
37+
private final long b8;
38+
39+
public Bytes(byte[] contents) {
40+
this.b0 = extract8Bytes(contents, 0);
41+
this.b8 = extract8Bytes(contents, 8);
42+
}
43+
44+
@Override
45+
public int line(int index) {
46+
if (index < 0 || index >= 16) {
47+
throw new ArrayIndexOutOfBoundsException();
48+
}
49+
if (index < 8) {
50+
return extractByte(b0, index) << 24;
51+
} else {
52+
return extractByte(b8, index - 8) << 24;
53+
}
54+
}
55+
56+
@Override
57+
public int bitWidth() {
58+
return 8;
59+
}
60+
}
61+
62+
public static class Shorts implements UnihexProvider.LineData {
63+
private final long b0;
64+
private final long b4;
65+
private final long b8;
66+
private final long b12;
67+
68+
public Shorts(short[] contents) {
69+
this.b0 = extract4Shorts(contents, 0);
70+
this.b4 = extract4Shorts(contents, 4);
71+
this.b8 = extract4Shorts(contents, 8);
72+
this.b12 = extract4Shorts(contents, 12);
73+
}
74+
75+
@Override
76+
public int line(int index) {
77+
if (index < 0 || index >= 16) {
78+
throw new ArrayIndexOutOfBoundsException();
79+
}
80+
if (index < 4) {
81+
return extractShort(b0, index) << 16;
82+
} else if (index < 8) {
83+
return extractShort(b4, index - 4) << 16;
84+
} else if (index < 12) {
85+
return extractShort(b8, index - 8) << 16;
86+
} else {
87+
return extractShort(b12, index - 12) << 16;
88+
}
89+
}
90+
91+
@Override
92+
public int bitWidth() {
93+
return 16;
94+
}
95+
}
96+
}

common/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.nio.file.Files;
1717
import java.nio.file.Path;
1818
import java.util.*;
19+
import java.util.concurrent.ConcurrentHashMap;
1920
import java.util.function.Function;
2021
import java.util.stream.Stream;
2122

@@ -24,6 +25,8 @@
2425
*/
2526
public class PackResourcesCacheEngine {
2627
private static final Joiner SLASH_JOINER = Joiner.on('/');
28+
private static final ConcurrentHashMap<String, String> PATH_COMPONENT_INTERNER = new ConcurrentHashMap<>();
29+
private static final ConcurrentHashMap<String, String[]> CACHED_SPLIT_PATHS = new ConcurrentHashMap<>();
2730

2831
static class Node {
2932
Map<String, Node> children;
@@ -100,7 +103,6 @@ public PackResourcesCacheEngine(Function<PackType, Path> basePathRetriever) {
100103
// used for log message
101104
this.debugPath = basePathRetriever.apply(PackType.CLIENT_RESOURCES).toAbsolutePath();
102105
this.root.children = new Object2ObjectOpenHashMap<>();
103-
ObjectOpenHashSet<String> pathKeys = new ObjectOpenHashSet<>();
104106
for(PackType type : PackType.values()) {
105107
var typeRoot = new Node();
106108
this.root.children.put(type.getDirectory(), typeRoot);
@@ -114,8 +116,12 @@ public PackResourcesCacheEngine(Function<PackType, Path> basePathRetriever) {
114116
.filter(PackResourcesCacheEngine::isValidCachedResourcePath)
115117
.forEach(path -> {
116118
var node = typeRoot;
117-
for (Path component : path) {
118-
String key = pathKeys.addOrGet(component.toString());
119+
int nameCount = path.getNameCount();
120+
for (int i = 0; i < nameCount; i++) {
121+
String key = path.getName(i).toString();
122+
if (i < (nameCount - 1)) {
123+
key = PATH_COMPONENT_INTERNER.computeIfAbsent(key, Function.identity());
124+
}
119125
if (node.children == null) {
120126
node.children = new Object2ObjectOpenHashMap<>();
121127
}
@@ -147,9 +153,17 @@ private static boolean isValidCachedResourcePath(Path path) {
147153

148154
public Set<String> getNamespaces(PackType type) {
149155
awaitLoad();
150-
if(PackTypeHelper.isVanillaPackType(type))
151-
return this.root.getChild(type.getDirectory()).children.keySet();
152-
else
156+
if(PackTypeHelper.isVanillaPackType(type)) {
157+
var namespaceToNodeMap = this.root.getChild(type.getDirectory()).children;
158+
var results = new ObjectOpenHashSet<String>();
159+
for (var entry : namespaceToNodeMap.entrySet()) {
160+
// Entries without children are files, not folders
161+
if (!entry.getValue().children.isEmpty()) {
162+
results.add(entry.getKey());
163+
}
164+
}
165+
return results;
166+
} else
153167
return null;
154168
}
155169

@@ -205,4 +219,16 @@ public void collectResources(PackType type, String resourceNamespace, String[] c
205219
}
206220
node.collectResources(resourceNamespace, this.rootPathsByType.get(type).resolve(resourceNamespace), components, 0, maxDepth, output);
207221
}
222+
223+
private static String[] decompose(String path) {
224+
String[] components = path.split("/");
225+
for (int i = 0; i < components.length; i++) {
226+
components[i] = PATH_COMPONENT_INTERNER.computeIfAbsent(components[i], Function.identity());
227+
}
228+
return components;
229+
}
230+
231+
public static String[] decomposeCached(String path) {
232+
return CACHED_SPLIT_PATHS.computeIfAbsent(path, PackResourcesCacheEngine::decompose);
233+
}
208234
}

common/src/main/resources/assets/modernfix/lang/en_us.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
"modernfix.option.mixin.perf.twilightforest.structure_spawn_fix": "Fixes lag caused by Twilight Forest worldgen checking structures very inefficiently",
118118
"modernfix.option.mixin.perf.fast_forge_dummies": "Speeds up Forge registry freezing during launch by using a faster code path",
119119
"modernfix.option.mixin.perf.tag_id_caching": "Speeds up uses of tag entries by caching the location object instead of recreating it every time",
120-
"modernfix.option.mixin.feature.disable_unihex_font": "Remove the Unicode font, saves 10MB but causes special characters to no longer render",
120+
"modernfix.option.mixin.perf.compress_unihex_font": "Stores the glyphs for the Unicode font more efficiently. Kudos to @AnAwesomGuy for the trick.",
121121
"modernfix.option.mixin.bugfix.world_leaks": "Reduces the memory usage of old client-side worlds that aren't needed after switching dimensions. These are normally garbage collected in vanilla, but mods sometimes retain references to them.",
122122
"modernfix.option.mixin.perf.compact_mojang_registries": "(Fabric) Experimental option that reduces the memory usage of registries by roughly 50%. Not useful in most modpacks unless they contain millions of blocks and items.",
123123
"modernfix.option.mixin.perf.dynamic_block_codecs": "Avoids storing a codec for every block(state) and instead generates and caches it on the fly when needed. Generally not worth enabling unless you have a million blocks/items.",

0 commit comments

Comments
 (0)