1212import java .lang .reflect .Field ;
1313import java .nio .file .Path ;
1414import java .util .Collections ;
15+ import java .util .HashMap ;
16+ import java .util .Map ;
1517import java .util .Set ;
1618import java .util .concurrent .ConcurrentHashMap ;
1719import java .util .function .Function ;
@@ -34,17 +36,32 @@ public static void monitorFileWatcher() {
3436 }
3537
3638 private static final Class <?> WATCHED_FILE = LamdbaExceptionUtils .uncheck (() -> Class .forName ("com.electronwill.nightconfig.core.file.FileWatcher$WatchedFile" ));
37- private static final Class <?> CONFIG_WATCHER = LamdbaExceptionUtils .uncheck (() -> Class .forName ("net.minecraftforge.fml.config.ConfigFileTypeHandler$ConfigWatcher" ));
3839 private static final Field CHANGE_HANDLER = ObfuscationReflectionHelper .findField (WATCHED_FILE , "changeHandler" );
3940
40- private static final Field COMMENTED_FILE_CONFIG = ObfuscationReflectionHelper .findField (CONFIG_WATCHER , "commentedFileConfig" );
41-
4241 private static final Class <?> WRITE_SYNC_CONFIG = LamdbaExceptionUtils .uncheck (() -> Class .forName ("com.electronwill.nightconfig.core.file.WriteSyncFileConfig" ));
4342 private static final Class <?> AUTOSAVE_CONFIG = LamdbaExceptionUtils .uncheck (() -> Class .forName ("com.electronwill.nightconfig.core.file.AutosaveCommentedFileConfig" ));
4443 private static final Field AUTOSAVE_FILECONFIG = ObfuscationReflectionHelper .findField (AUTOSAVE_CONFIG , "fileConfig" );
4544
4645 private static final Field CURRENTLY_WRITING = ObfuscationReflectionHelper .findField (WRITE_SYNC_CONFIG , "currentlyWriting" );
4746
47+ private static final Map <Class <?>, Field > CONFIG_WATCHER_TO_CONFIG_FIELD = Collections .synchronizedMap (new HashMap <>());
48+
49+ private static Field getCurrentlyWritingFieldOnWatcher (Object watcher ) {
50+ return CONFIG_WATCHER_TO_CONFIG_FIELD .computeIfAbsent (watcher .getClass (), clz -> {
51+ while (clz != null && clz != Object .class ) {
52+ for (Field f : clz .getDeclaredFields ()) {
53+ if (CommentedFileConfig .class .isAssignableFrom (f .getType ())) {
54+ f .setAccessible (true );
55+ ModernFixMixinPlugin .instance .logger .debug ("Found CommentedFileConfig: field '{}' on {}" , f .getName (), clz .getName ());
56+ return f ;
57+ }
58+ }
59+ clz = clz .getSuperclass ();
60+ }
61+ return null ;
62+ });
63+ }
64+
4865 static class MonitoringMap extends ConcurrentHashMap <Path , Object > {
4966 public MonitoringMap (ConcurrentHashMap <Path , ?> oldMap ) {
5067 super (oldMap );
@@ -56,11 +73,7 @@ public Object computeIfAbsent(Path key, Function<? super Path, ?> mappingFunctio
5673 Object watchedFile = mappingFunction .apply (path );
5774 try {
5875 Runnable changeHandler = (Runnable )CHANGE_HANDLER .get (watchedFile );
59- // replace Forge's config tracker with our own
60- if (CONFIG_WATCHER .isAssignableFrom (changeHandler .getClass ()))
61- CHANGE_HANDLER .set (watchedFile , new MonitoringConfigTracker (changeHandler ));
62- else
63- ModernFixMixinPlugin .instance .logger .warn ("Unexpected Forge config tracker class: {}" , changeHandler .getClass ().getName ());
76+ CHANGE_HANDLER .set (watchedFile , new MonitoringConfigTracker (changeHandler ));
6477 } catch (ReflectiveOperationException e ) {
6578 e .printStackTrace ();
6679 }
@@ -99,15 +112,18 @@ private boolean isSaving(FileConfig config) throws ReflectiveOperationException
99112 @ Override
100113 public void run () {
101114 try {
102- CommentedFileConfig cfg = (CommentedFileConfig )COMMENTED_FILE_CONFIG .get (this .configTracker );
103- while (isSaving (cfg )) {
104- // block until the config is no longer marked as saving
105- // Forge shouldn't save the config twice in a row under normal conditions so this should fix the
106- // original bug
107- try {
108- Thread .sleep (500 );
109- } catch (InterruptedException e ) {
110- return ;
115+ Field theField = getCurrentlyWritingFieldOnWatcher (this .configTracker );
116+ if (theField != null ) {
117+ CommentedFileConfig cfg = (CommentedFileConfig )theField .get (this .configTracker );
118+ while (isSaving (cfg )) {
119+ // block until the config is no longer marked as saving
120+ // Forge shouldn't save the config twice in a row under normal conditions so this should fix the
121+ // original bug
122+ try {
123+ Thread .sleep (500 );
124+ } catch (InterruptedException e ) {
125+ return ;
126+ }
111127 }
112128 }
113129 } catch (ReflectiveOperationException e ) {
0 commit comments