Skip to content

Commit 00e63e1

Browse files
committed
fix: Track known keys as they are loaded, as setKey is not called when it matches the original default
1 parent 86cf207 commit 00e63e1

12 files changed

Lines changed: 153 additions & 8 deletions

File tree

common/src/main/java/net/blay09/mods/defaultoptions/DefaultOptionsInitializer.java

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
import net.blay09.mods.balm.api.event.client.ClientStartedEvent;
44
import net.blay09.mods.defaultoptions.api.*;
5+
import net.minecraft.client.Options;
6+
import net.minecraft.nbt.CompoundTag;
57

8+
import java.util.HashSet;
69
import java.util.ServiceLoader;
710

811
public class DefaultOptionsInitializer {
@@ -24,12 +27,18 @@ public static void postLoad(ClientStartedEvent event) {
2427

2528
private static void loadDefaults(DefaultOptionsLoadStage stage) {
2629
for (DefaultOptionsHandler handler : DefaultOptions.getDefaultOptionsHandlers()) {
27-
if (handler.shouldLoadDefaults() && handler.getLoadStage() == stage) {
28-
try {
29-
handler.loadDefaults();
30-
DefaultOptions.logger.info("Loaded default options for {}", handler.getId());
31-
} catch (DefaultOptionsHandlerException e) {
32-
DefaultOptions.logger.error("Failed to load default options for {}", e.getHandlerId(), e);
30+
if (handler.getLoadStage() == stage) {
31+
if (handler.shouldLoadDefaults()) {
32+
try {
33+
handler.loadDefaults();
34+
DefaultOptions.logger.info("Loaded default options for {}", handler.getId());
35+
} catch (DefaultOptionsHandlerException e) {
36+
DefaultOptions.logger.error("Failed to load default options for {}", e.getHandlerId(), e);
37+
}
38+
} else if (handler.hasDefaults()) {
39+
DefaultOptions.logger.debug("Skipping default options for {}; defaults are present but should not be loaded", handler.getId());
40+
} else {
41+
DefaultOptions.logger.debug("Skipping default options for {}; no defaults available", handler.getId());
3342
}
3443
}
3544
}
@@ -40,4 +49,19 @@ public static void postSave() {
4049
handler.saveAdditional();
4150
}
4251
}
52+
53+
public static void detectAndMarkModifiedKeys(Options options, CompoundTag fields) {
54+
final var knownKeys = new HashSet<String>();
55+
for (final var option : fields.getAllKeys()) {
56+
if (option.startsWith("key_")) {
57+
final var name = option.substring("key_".length());
58+
knownKeys.add(name);
59+
}
60+
}
61+
for (final var keyMapping : options.keyMappings) {
62+
if (knownKeys.contains(keyMapping.getName())) {
63+
((DefaultOptionsKeyMapping) keyMapping).defaultoptions$setUserModified(true);
64+
}
65+
}
66+
}
4367
}

common/src/main/java/net/blay09/mods/defaultoptions/DefaultOptionsKeyMapping.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22

33
public interface DefaultOptionsKeyMapping {
44
boolean defaultoptions$wasUserModified();
5+
void defaultoptions$setUserModified(boolean modified);
56
}

common/src/main/java/net/blay09/mods/defaultoptions/mixin/KeyMappingMixin.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,18 @@ public class KeyMappingMixin implements DefaultOptionsKeyMapping {
1515

1616
@Inject(method = "setKey", at = @At("HEAD"))
1717
void setKey(InputConstants.Key key, CallbackInfo ci) {
18+
// setKey is only called when the key didn't match the default on options load, so it's not reliable.
19+
// We just track it additionally to cover all bases.
1820
defaultoptions$userModified = true;
1921
}
2022

2123
@Override
2224
public boolean defaultoptions$wasUserModified() {
2325
return defaultoptions$userModified;
2426
}
27+
28+
@Override
29+
public void defaultoptions$setUserModified(boolean modified) {
30+
defaultoptions$userModified = modified;
31+
}
2532
}

common/src/main/java/net/blay09/mods/defaultoptions/mixin/OptionsMixin.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ private void load(CallbackInfo ci) {
1818
private void save(CallbackInfo ci) {
1919
DefaultOptionsInitializer.postSave();
2020
}
21+
2122
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package net.blay09.mods.defaultoptions.fabric.mixin;
2+
3+
import net.blay09.mods.defaultoptions.DefaultOptionsInitializer;
4+
import net.minecraft.client.Options;
5+
import net.minecraft.nbt.CompoundTag;
6+
import org.spongepowered.asm.mixin.Mixin;
7+
import org.spongepowered.asm.mixin.injection.At;
8+
import org.spongepowered.asm.mixin.injection.ModifyArg;
9+
10+
@Mixin(Options.class)
11+
public class FabricOptionsMixin {
12+
@ModifyArg(method = "load()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Options;dataFix(Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/nbt/CompoundTag;"))
13+
private CompoundTag processPreDataFixedOptions(CompoundTag fields) {
14+
// This will operate on raw options data before data fixers are applied to it, but I think that's fine
15+
// considering key mapping options have been stable for a long time and even if they ever change,
16+
// it would be extremely rare to happen in a modpack environment.
17+
DefaultOptionsInitializer.detectAndMarkModifiedKeys((Options) (Object) this, fields);
18+
return fields;
19+
}
20+
21+
}

fabric/src/main/resources/defaultoptions.fabric.mixins.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"mixins": [
88
],
99
"client": [
10+
"FabricOptionsMixin"
1011
],
1112
"injectors": {
1213
"defaultRequire": 1
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package net.blay09.mods.defaultoptions.forge.mixin;
2+
3+
import com.mojang.blaze3d.platform.InputConstants;
4+
import net.blay09.mods.defaultoptions.DefaultOptionsKeyMapping;
5+
import net.minecraft.client.KeyMapping;
6+
import net.minecraftforge.client.settings.KeyModifier;
7+
import org.spongepowered.asm.mixin.Mixin;
8+
import org.spongepowered.asm.mixin.injection.At;
9+
import org.spongepowered.asm.mixin.injection.Inject;
10+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
11+
12+
@Mixin(KeyMapping.class)
13+
public class ForgeKeyMappingMixin {
14+
15+
@Inject(method = "setKeyModifierAndCode", at = @At("HEAD"), remap = false)
16+
void setKeyModifierAndCode(KeyModifier keyModifier, InputConstants.Key keyCode, CallbackInfo ci) {
17+
// setKey is only called when the key didn't match the default on options load, so it's not reliable.
18+
// We just track it additionally to cover all bases.
19+
((DefaultOptionsKeyMapping) this).defaultoptions$setUserModified(true);
20+
}
21+
22+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package net.blay09.mods.defaultoptions.mixin;
2+
3+
import net.blay09.mods.defaultoptions.DefaultOptionsInitializer;
4+
import net.minecraft.client.Options;
5+
import net.minecraft.nbt.CompoundTag;
6+
import org.spongepowered.asm.mixin.Mixin;
7+
import org.spongepowered.asm.mixin.injection.At;
8+
import org.spongepowered.asm.mixin.injection.ModifyArg;
9+
10+
@Mixin(Options.class)
11+
public class ForgeOptionsMixin {
12+
@ModifyArg(method = "load(Z)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Options;dataFix(Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/nbt/CompoundTag;"))
13+
private CompoundTag processPreDataFixedOptions(CompoundTag fields) {
14+
// This will operate on raw options data before data fixers are applied to it, but I think that's fine
15+
// considering key mapping options have been stable for a long time and even if they ever change,
16+
// it would be extremely rare to happen in a modpack environment.
17+
DefaultOptionsInitializer.detectAndMarkModifiedKeys((Options) (Object) this, fields);
18+
return fields;
19+
}
20+
21+
}

forge/src/main/resources/defaultoptions.forge.mixins.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
"mixins": [
88
],
99
"client": [
10-
"ForgeKeyMappingAccessor"
10+
"ForgeOptionsMixin",
11+
"ForgeKeyMappingAccessor",
12+
"ForgeKeyMappingMixin"
1113
],
1214
"injectors": {
1315
"defaultRequire": 1
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package net.blay09.mods.defaultoptions.neoforge.mixin;
2+
3+
import com.mojang.blaze3d.platform.InputConstants;
4+
import net.blay09.mods.defaultoptions.DefaultOptionsKeyMapping;
5+
import net.minecraft.client.KeyMapping;
6+
import net.neoforged.neoforge.client.settings.KeyModifier;
7+
import org.spongepowered.asm.mixin.Mixin;
8+
import org.spongepowered.asm.mixin.injection.At;
9+
import org.spongepowered.asm.mixin.injection.Inject;
10+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
11+
12+
@Mixin(KeyMapping.class)
13+
public class NeoForgeKeyMappingMixin {
14+
15+
@Inject(method = "setKeyModifierAndCode", at = @At("HEAD"), remap = false)
16+
void setKeyModifierAndCode(KeyModifier keyModifier, InputConstants.Key keyCode, CallbackInfo ci) {
17+
// setKey is only called when the key didn't match the default on options load, so it's not reliable.
18+
// We just track it additionally to cover all bases.
19+
((DefaultOptionsKeyMapping) this).defaultoptions$setUserModified(true);
20+
}
21+
22+
}

0 commit comments

Comments
 (0)