2019-02-10 22:51:25 +00:00
/ *
* Minecraft Forge
2019-02-10 22:57:03 +00:00
* Copyright ( c ) 2016 - 2019 .
2019-02-10 22:51:25 +00:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2 . 1
* of the License .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
* /
2019-01-29 03:42:37 +00:00
package net.minecraftforge.fml.config ;
2019-02-17 21:07:47 +00:00
import com.electronwill.nightconfig.core.CommentedConfig ;
2019-01-29 03:42:37 +00:00
import com.electronwill.nightconfig.core.file.CommentedFileConfig ;
2019-02-16 02:45:28 +00:00
import com.electronwill.nightconfig.toml.TomlFormat ;
2019-07-29 01:09:15 +00:00
import it.unimi.dsi.fastutil.bytes.Byte2ByteOpenCustomHashMap ;
2019-02-16 02:45:28 +00:00
import net.minecraft.client.Minecraft ;
import net.minecraftforge.fml.network.FMLHandshakeMessages ;
import net.minecraftforge.fml.network.NetworkEvent ;
import org.apache.commons.lang3.tuple.Pair ;
2019-01-29 03:42:37 +00:00
import org.apache.logging.log4j.LogManager ;
import org.apache.logging.log4j.Logger ;
import org.apache.logging.log4j.Marker ;
import org.apache.logging.log4j.MarkerManager ;
2019-02-16 02:45:28 +00:00
import java.io.ByteArrayInputStream ;
2019-02-21 12:24:39 +00:00
import java.io.IOException ;
2019-02-16 02:45:28 +00:00
import java.nio.file.Files ;
2019-01-29 03:42:37 +00:00
import java.nio.file.Path ;
2019-01-29 20:42:56 +00:00
import java.util.Collections ;
2019-01-29 03:42:37 +00:00
import java.util.EnumMap ;
2019-01-29 20:42:56 +00:00
import java.util.LinkedHashSet ;
2019-02-16 02:45:28 +00:00
import java.util.List ;
import java.util.Map ;
import java.util.Optional ;
2019-01-29 03:42:37 +00:00
import java.util.Set ;
import java.util.concurrent.ConcurrentHashMap ;
2019-02-16 02:45:28 +00:00
import java.util.function.Supplier ;
import java.util.stream.Collectors ;
import static cpw.mods.modlauncher.api.LamdbaExceptionUtils.rethrowFunction ;
2019-01-29 03:42:37 +00:00
public class ConfigTracker {
private static final Logger LOGGER = LogManager . getLogger ( ) ;
static final Marker CONFIG = MarkerManager . getMarker ( " CONFIG " ) ;
public static final ConfigTracker INSTANCE = new ConfigTracker ( ) ;
private final ConcurrentHashMap < String , ModConfig > fileMap ;
private final EnumMap < ModConfig . Type , Set < ModConfig > > configSets ;
2019-07-29 01:09:15 +00:00
private ConcurrentHashMap < String , Map < ModConfig . Type , ModConfig > > configsByMod ;
2019-01-29 03:42:37 +00:00
private ConfigTracker ( ) {
this . fileMap = new ConcurrentHashMap < > ( ) ;
this . configSets = new EnumMap < > ( ModConfig . Type . class ) ;
2019-07-29 01:09:15 +00:00
this . configsByMod = new ConcurrentHashMap < > ( ) ;
2019-01-29 20:42:56 +00:00
this . configSets . put ( ModConfig . Type . CLIENT , Collections . synchronizedSet ( new LinkedHashSet < > ( ) ) ) ;
2019-02-16 02:45:28 +00:00
this . configSets . put ( ModConfig . Type . COMMON , Collections . synchronizedSet ( new LinkedHashSet < > ( ) ) ) ;
2019-01-29 03:42:37 +00:00
// this.configSets.put(ModConfig.Type.PLAYER, new ConcurrentSkipListSet<>());
2019-01-29 20:42:56 +00:00
this . configSets . put ( ModConfig . Type . SERVER , Collections . synchronizedSet ( new LinkedHashSet < > ( ) ) ) ;
2019-01-29 03:42:37 +00:00
}
void trackConfig ( final ModConfig config ) {
if ( this . fileMap . containsKey ( config . getFileName ( ) ) ) {
LOGGER . error ( CONFIG , " Detected config file conflict {} between {} and {} " , config . getFileName ( ) , this . fileMap . get ( config . getFileName ( ) ) . getModId ( ) , config . getModId ( ) ) ;
throw new RuntimeException ( " Config conflict detected! " ) ;
}
this . fileMap . put ( config . getFileName ( ) , config ) ;
this . configSets . get ( config . getType ( ) ) . add ( config ) ;
2019-07-29 01:09:15 +00:00
this . configsByMod . computeIfAbsent ( config . getModId ( ) , ( k ) - > new EnumMap < > ( ModConfig . Type . class ) ) . put ( config . getType ( ) , config ) ;
2019-01-29 03:42:37 +00:00
LOGGER . debug ( CONFIG , " Config file {} for {} tracking " , config . getFileName ( ) , config . getModId ( ) ) ;
}
public void loadConfigs ( ModConfig . Type type , Path configBasePath ) {
LOGGER . debug ( CONFIG , " Loading configs type {} " , type ) ;
this . configSets . get ( type ) . forEach ( config - > openConfig ( config , configBasePath ) ) ;
}
2019-03-16 03:19:28 +00:00
public List < Pair < String , FMLHandshakeMessages . S2CConfigData > > syncConfigs ( boolean isLocal ) {
2019-02-21 12:24:39 +00:00
final Map < String , byte [ ] > configData = configSets . get ( ModConfig . Type . SERVER ) . stream ( ) . collect ( Collectors . toMap ( ModConfig : : getFileName , mc - > { //TODO: Test cpw's LambdaExceptionUtils on Oracle javac.
try {
return Files . readAllBytes ( mc . getFullPath ( ) ) ;
} catch ( IOException e ) {
throw new RuntimeException ( e ) ;
}
} ) ) ;
2019-02-16 02:45:28 +00:00
return configData . entrySet ( ) . stream ( ) . map ( e - > Pair . of ( " Config " + e . getKey ( ) , new FMLHandshakeMessages . S2CConfigData ( e . getKey ( ) , e . getValue ( ) ) ) ) . collect ( Collectors . toList ( ) ) ;
}
2019-01-29 03:42:37 +00:00
private void openConfig ( final ModConfig config , final Path configBasePath ) {
LOGGER . debug ( CONFIG , " Loading config file type {} at {} for {} " , config . getType ( ) , config . getFileName ( ) , config . getModId ( ) ) ;
final CommentedFileConfig configData = config . getHandler ( ) . reader ( configBasePath ) . apply ( config ) ;
config . setConfigData ( configData ) ;
config . fireEvent ( new ModConfig . Loading ( config ) ) ;
2019-02-16 02:45:28 +00:00
config . save ( ) ;
}
public void receiveSyncedConfig ( final FMLHandshakeMessages . S2CConfigData s2CConfigData , final Supplier < NetworkEvent . Context > contextSupplier ) {
if ( ! Minecraft . getInstance ( ) . isIntegratedServerRunning ( ) ) {
Optional . ofNullable ( fileMap . get ( s2CConfigData . getFileName ( ) ) ) . ifPresent ( mc - > {
mc . setConfigData ( TomlFormat . instance ( ) . createParser ( ) . parse ( new ByteArrayInputStream ( s2CConfigData . getBytes ( ) ) ) ) ;
2020-01-22 21:09:58 +00:00
mc . fireEvent ( new ModConfig . Reloading ( mc ) ) ;
2019-02-16 02:45:28 +00:00
} ) ;
}
2019-01-29 03:42:37 +00:00
}
2019-02-17 21:07:47 +00:00
public void loadDefaultServerConfigs ( ) {
configSets . get ( ModConfig . Type . SERVER ) . forEach ( modConfig - > {
final CommentedConfig commentedConfig = CommentedConfig . inMemory ( ) ;
modConfig . getSpec ( ) . correct ( commentedConfig ) ;
modConfig . setConfigData ( commentedConfig ) ;
2019-07-09 02:49:47 +00:00
modConfig . fireEvent ( new ModConfig . Loading ( modConfig ) ) ;
2019-02-17 21:07:47 +00:00
} ) ;
}
2019-07-29 01:09:15 +00:00
public String getConfigFileName ( String modId , ModConfig . Type type ) {
return Optional . ofNullable ( configsByMod . getOrDefault ( modId , Collections . emptyMap ( ) ) . getOrDefault ( type , null ) ) .
map ( ModConfig : : getFullPath ) . map ( Object : : toString ) . orElse ( null ) ;
}
2019-01-29 03:42:37 +00:00
}