Skip to content

Commit a25e37b

Browse files
committed
Merge remote-tracking branch 'origin/1.20' into 1.21.1
2 parents d9fb13a + c64ca2e commit a25e37b

8 files changed

Lines changed: 75 additions & 29 deletions

File tree

.github/workflows/gradle.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ jobs:
4444
run: ./scripts/tagcleaner.sh
4545
- name: Build ModernFix using Gradle
4646
run: ./gradlew build
47+
- name: Run mixin audit
48+
run: timeout 60 xvfb-run ./gradlew runAuditClient
4749
- name: Publish mod to CurseForge & Modrinth
4850
if: steps.check_branch.outputs.is_release == 'true'
4951
run: ./gradlew publishMods copyJarToBin

build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ neoForge {
3838
create("server") {
3939
server()
4040
}
41+
create("auditClient") {
42+
client()
43+
jvmArguments.addAll("-Dmodernfix.auditAndExit=true", "-Djava.awt.headless=true")
44+
}
4145
}
4246

4347
mods {

src/main/java/org/embeddedt/modernfix/ModernFix.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
1313
import org.embeddedt.modernfix.resources.ReloadExecutor;
1414
import org.embeddedt.modernfix.util.ClassInfoManager;
15+
import org.spongepowered.asm.mixin.MixinEnvironment;
1516

1617
import java.lang.management.ManagementFactory;
1718
import java.util.concurrent.ExecutorService;
@@ -45,6 +46,15 @@ public static ExecutorService resourceReloadExecutor() {
4546
return resourceReloadService;
4647
}
4748

49+
public static void runAuditIfRequested() {
50+
boolean auditAndExit = Boolean.getBoolean("modernfix.auditAndExit");
51+
if (auditAndExit || Boolean.getBoolean("modernfix.auditMixinsAtStart")) {
52+
MixinEnvironment.getCurrentEnvironment().audit();
53+
if (auditAndExit) {
54+
System.exit(0);
55+
}
56+
}
57+
}
4858

4959
public ModernFix() {
5060
INSTANCE = this;

src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_languages/ClientLanguageMixin.java

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
44
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
5-
import com.llamalad7.mixinextras.sugar.Local;
5+
import com.llamalad7.mixinextras.sugar.Share;
6+
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
67
import net.minecraft.client.resources.language.ClientLanguage;
78
import net.minecraft.server.packs.resources.Resource;
89
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
@@ -11,47 +12,42 @@
1112
import org.spongepowered.asm.mixin.injection.At;
1213
import org.spongepowered.asm.mixin.injection.ModifyArg;
1314

15+
import java.util.ArrayList;
1416
import java.util.List;
1517
import java.util.Map;
16-
import java.util.function.BiConsumer;
18+
import java.util.Objects;
1719

1820
/**
1921
* Modifies the language system to load/unload the contents of language entries based on GC pressure.
2022
*/
21-
@Mixin(ClientLanguage.class)
23+
@Mixin(value = ClientLanguage.class, priority = 2000)
2224
@ClientOnlyMixin
2325
public class ClientLanguageMixin {
24-
private static final ThreadLocal<Boolean> MFIX_MODIFY_APPEND_SEMANTICS = ThreadLocal.withInitial(() -> Boolean.FALSE);
25-
26-
/**
27-
* @author embeddedt
28-
* @reason modify the semantics of appendFrom so that it's used to do a prepass
29-
*/
30-
@ModifyArg(method = "appendFrom", at = @At(value = "INVOKE", target = "Lnet/minecraft/locale/Language;loadFromJson(Ljava/io/InputStream;Ljava/util/function/BiConsumer;)V"), index = 1)
31-
private static BiConsumer<String, ?> changeSemanticsOfConsumer(BiConsumer<String, ?> consumer, @Local(ordinal = 0, argsOnly = true) Map<String, Object> destinationMap, @Local(ordinal = 0) Resource resource) {
32-
return MFIX_MODIFY_APPEND_SEMANTICS.get() ? ((k, v) -> destinationMap.put(k, resource)) : consumer;
33-
}
34-
3526
/**
3627
* @author embeddedt
37-
* @reason collect resources that own keys with a prepass
28+
* @reason collect the list of all known language resources
3829
*/
39-
@WrapOperation(method = "loadFrom", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/language/ClientLanguage;appendFrom(Ljava/lang/String;Ljava/util/List;Ljava/util/Map;)V"))
40-
private static void trackEntrySource(String languageName, List<Resource> resources, Map<String, String> destinationMap, Operation<Void> original) {
41-
MFIX_MODIFY_APPEND_SEMANTICS.set(true);
42-
try {
43-
original.call(languageName, resources, destinationMap);
44-
} finally {
45-
MFIX_MODIFY_APPEND_SEMANTICS.remove();
30+
@WrapOperation(method = "loadFrom", at = @At(value = "INVOKE",
31+
target = "Lnet/minecraft/client/resources/language/ClientLanguage;appendFrom(Ljava/lang/String;Ljava/util/List;Ljava/util/Map;)V"))
32+
private static void collectResources(String languageName, List<Resource> resources,
33+
Map<String, String> destinationMap, Operation<Void> original,
34+
@Share("usedResources") LocalRef<List<Resource>> usedResources) {
35+
List<Resource> collected = usedResources.get();
36+
if (collected == null) {
37+
collected = new ArrayList<>();
38+
usedResources.set(collected);
4639
}
40+
collected.addAll(resources);
41+
original.call(languageName, resources, destinationMap);
4742
}
4843

4944
/**
5045
* @author embeddedt
5146
* @reason figure out which keys are dynamically loaded and which are injected by mixins
5247
*/
5348
@ModifyArg(method = "loadFrom", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/language/ClientLanguage;<init>(Ljava/util/Map;Z)V"), index = 0)
54-
private static Map<String, String> modifyLanguageMap(Map<String, ?> storage) {
55-
return DynamicLanguageMap.forStorage(Map.copyOf(storage));
49+
private static Map<String, String> modifyLanguageMap(Map<String, String> storage, @Share("usedResources") LocalRef<List<Resource>> usedResources) {
50+
List<Resource> collected = Objects.requireNonNullElse(usedResources.get(), List.of());
51+
return DynamicLanguageMap.forVanillaData(storage, collected);
5652
}
5753
}

src/main/java/org/embeddedt/modernfix/common/mixin/perf/optimize_surface_rules/SurfaceSystemMixin.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
import java.util.function.Function;
2828

29-
@Mixin(SurfaceSystem.class)
29+
@Mixin(value = SurfaceSystem.class, priority = 2000)
3030
public class SurfaceSystemMixin {
3131
private static final ThreadLocal<ChunkBiomeLookup> MFIX_LOOKUP_CACHE = ThreadLocal.withInitial(ChunkBiomeLookup::new);
3232
private static final ThreadLocal<PrefetchingBlockColumn> MFIX_BLOCK_COLUMN = new ThreadLocal<>();
@@ -43,7 +43,7 @@ private Function<BlockPos, Holder<Biome>> useFasterLookup(Function<BlockPos, Hol
4343
return lookup;
4444
}
4545

46-
@Inject(method = "buildSurface", at = @At("RETURN"))
46+
@Inject(method = "buildSurface", at = @At("TAIL"))
4747
private void finishAndDisposeLookups(RandomState randomState, BiomeManager biomeManager, Registry<Biome> biomes, boolean p_224652_, WorldGenerationContext context, ChunkAccess chunk, NoiseChunk noiseChunk, SurfaceRules.RuleSource ruleSource, CallbackInfo ci) {
4848
MFIX_LOOKUP_CACHE.get().dispose();
4949
var column = MFIX_BLOCK_COLUMN.get();

src/main/java/org/embeddedt/modernfix/common/mixin/perf/suspend_integrated_server_during_load/IntegratedServerMixin.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import org.spongepowered.asm.mixin.Mixin;
1818
import org.spongepowered.asm.mixin.Shadow;
1919
import org.spongepowered.asm.mixin.injection.At;
20+
import org.spongepowered.asm.mixin.injection.Inject;
21+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
2022

2123
import java.net.Proxy;
2224
import java.util.concurrent.atomic.AtomicBoolean;
@@ -28,6 +30,7 @@ public abstract class IntegratedServerMixin extends MinecraftServer implements I
2830
@Shadow
2931
private boolean paused;
3032

33+
private int mfix$numTickServerCalls = 0;
3134
private final AtomicBoolean mfix$hasPrimaryClientJoined = new AtomicBoolean(false);
3235

3336
public IntegratedServerMixin(Thread serverThread, LevelStorageSource.LevelStorageAccess storageSource, PackRepository packRepository, WorldStem worldStem, Proxy proxy, DataFixer fixerUpper, Services services, ChunkProgressListenerFactory progressListenerFactory) {
@@ -44,14 +47,26 @@ private boolean preventTicks(Minecraft instance, Operation<Boolean> original) {
4447
return !mfix$hasPrimaryClientJoined.get() || original.call(instance);
4548
}
4649

50+
/**
51+
* @author embeddedt
52+
* @reason Keep our own tick count for the integrated server specifically, rather than relying on super
53+
* to increment.
54+
*/
55+
@Inject(method = "tickServer", at = @At("HEAD"))
56+
private void mfix$countTicks(CallbackInfo ci) {
57+
this.mfix$numTickServerCalls++;
58+
}
59+
4760
/**
4861
* @author embeddedt
4962
* @reason If waiting for a client connection to exist, we only need to tick the server connection,
50-
* not the whole server as vanilla does.
63+
* not the whole server as vanilla does. However, we must tick the whole server once to accommodate mods
64+
* that rely on the first tick to initialize state as a side effect. Not doing this causes issues like
65+
* <a href="https://github.com/embeddedt/ModernFix/issues/639">#639</a>.
5166
*/
5267
@WrapWithCondition(method = "tickServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;tickServer(Ljava/util/function/BooleanSupplier;)V", ordinal = 0))
5368
private boolean preventRunningFullServerTick(MinecraftServer server, BooleanSupplier hasTimeLeft) {
54-
if (this.paused && !mfix$hasPrimaryClientJoined.get()) {
69+
if (this.mfix$numTickServerCalls >= 2 && this.paused && !mfix$hasPrimaryClientJoined.get()) {
5570
var conn = this.getConnection();
5671
if (conn != null) {
5772
conn.tick();

src/main/java/org/embeddedt/modernfix/dynamiclanguages/DynamicLanguageMap.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,28 @@
1010
import org.embeddedt.modernfix.ModernFix;
1111

1212
import java.io.IOException;
13+
import java.util.HashMap;
14+
import java.util.List;
1315
import java.util.Map;
1416

1517
public class DynamicLanguageMap {
16-
public static Map<String, String> forStorage(Map<String, ?> storage) {
18+
private static Map<String, Object> createStorage(Map<String, String> rawLanguageContents, List<Resource> languageResources) {
19+
Map<String, Object> storage = new HashMap<>(rawLanguageContents);
20+
for (var resource : languageResources) {
21+
try (var stream = resource.open()) {
22+
Language.loadFromJson(stream, (key, value) -> {
23+
if (value != null && value.equals(storage.get(key))) {
24+
storage.put(key, resource);
25+
}
26+
});
27+
} catch (Exception ignored) {
28+
}
29+
}
30+
return Map.copyOf(storage);
31+
}
32+
33+
public static Map<String, String> forVanillaData(Map<String, String> rawLanguageContents, List<Resource> languageResources) {
34+
Map<String, Object> storage = createStorage(rawLanguageContents, languageResources);
1735
LoadingCache<Resource, Map<String, String>> languageFileContents = CacheBuilder.newBuilder()
1836
.softValues()
1937
.build(new CacheLoader<>() {

src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixForge.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public void commonSetup(FMLCommonSetupEvent event) {
8181
ModLoader.addLoadingIssue(ModLoadingIssue.warning("modernfix.perf_mod_warning"));
8282
});
8383
}
84+
event.enqueueWork(ModernFix::runAuditIfRequested);
8485
}
8586

8687
private void registerNetworkChannel(final RegisterPayloadHandlersEvent event) {

0 commit comments

Comments
 (0)