Added a new facade config. (#3706)

The whitelist is now based on manually add explicit entries instead of
automatically adding every existing block. This alone should save a few
MB of RAM depending on the modpack size.

Additionally the FacadeConfig is no longer extending the normal
Configuration provided by Forge. It will only parse the file once per
start and store the settings in an optimised collection to further
reduce memory consumption.

Any full block without a TileEntity and having a model is whitelisted
automatically and does not need an explicit entry anymore.

By default vanilla and AE2 glass is added as they are no fullblocks
technically.

The whitelist technically allows many more blocks now. E.g. stairs,
slabs or even items like saplings. But with various rendering quality.

Further there is an option to allow facades based on TileEntities, this
is completely unsupported and can work or corrupt the whole save.
This commit is contained in:
yueh
2018-09-02 13:59:18 +02:00
committed by GitHub
parent 7ba2893635
commit b1ac0adfd8
2 changed files with 133 additions and 55 deletions
+111 -37
View File
@@ -20,32 +20,124 @@ package appeng.core;
import java.io.File;
import java.lang.reflect.Field;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.config.ConfigCategory;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import net.minecraftforge.common.config.Property.Type;
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
public class FacadeConfig extends Configuration
public class FacadeConfig
{
private static final String CONFIG_VERSION = "1";
private static final String CONFIG_COMMON_KEY = "common";
private static final String CONFIG_COMMON_COMMENT = "Settings applied to all facades.\n\n" //
+ "By default full blocks with no tile entity and a model do not need whitelisting.\n"//
+ "This will only be read once during client startup.";
private static final String CONFIG_COMMON_ALLOW_TILEENTITIES_KEY = "allowTileEntityFacades";
private static final String CONFIG_COMMON_ALLOW_TILEENTITIES_COMMENT = "Unsupported: Allows whitelisting TileEntity as facades. Could work, have render issues, or corrupt your world. USE AT YOUR OWN RISK.";
private static final String CONFIG_FACADES_KEY = "facades";
private static final String CONFIG_FACADES_COMMENT = "A way to explicitly handle certain blocks as facades.\n\n" //
+ "Blocks can be added by their resource location under the following rules.\n" //
+ " - One category per domain like minecraft or appliedenergistics2\n" //
+ " - One key per id. E.g. glass in case of minecraft:glass\n" //
+ " - An integer value ranging from 0 to 16 representing the metadata 0-15 and 16 as wildcard for all" //
+ " - Multiple entries for the same id but different metadata are possible when needed";
private static FacadeConfig instance;
private final Pattern replacementPattern;
private final boolean allowTileEntityFacades;
private final Object2IntMap<ResourceLocation> whiteList;
public FacadeConfig( final File facadeFile )
private FacadeConfig( boolean allowTileEntityFacades, Object2IntMap<ResourceLocation> whiteList )
{
super( facadeFile );
this.replacementPattern = Pattern.compile( "[^a-zA-Z0-9]" );
this.allowTileEntityFacades = allowTileEntityFacades;
this.whiteList = whiteList;
}
/**
* Creates a custom confuration based on a {@link Configuration}, but ultimately throws it away after reading it
* once to save a couple MB of memory.
*
* @param configFile
*/
public static void init( final File configFile )
{
instance = new FacadeConfig( configFile );
final Configuration configurartion = migrate( new Configuration( configFile, CONFIG_VERSION ) );
final boolean allowTileEntityFacades = configurartion
.get( CONFIG_COMMON_KEY, CONFIG_COMMON_ALLOW_TILEENTITIES_KEY, false, CONFIG_COMMON_ALLOW_TILEENTITIES_COMMENT )
.setRequiresMcRestart( true )
.setShowInGui( false )
.getBoolean();
final Object2IntMap<ResourceLocation> configWhiteList = new Object2IntArrayMap<>();
final Set<ConfigCategory> whitelist = configurartion.getCategory( CONFIG_FACADES_KEY ).getChildren();
for( ConfigCategory configCategory : whitelist )
{
final String domain = configCategory.getName();
final Map<String, Property> values = configCategory.getValues();
for( Entry<String, Property> entry : values.entrySet() )
{
configWhiteList.put( new ResourceLocation( domain, entry.getKey() ), entry.getValue().getInt() );
}
}
if( configurartion.hasChanged() )
{
configurartion.save();
}
instance = new FacadeConfig( allowTileEntityFacades, configWhiteList );
}
private static Configuration migrate( Configuration configurartion )
{
// Clear pre rv6 configs.
if( configurartion.getLoadedConfigVersion() == null )
{
for( String category : configurartion.getCategoryNames() )
{
final ConfigCategory c = configurartion.getCategory( category );
configurartion.removeCategory( c );
}
}
// Create general category, if missing
if( !configurartion.hasCategory( CONFIG_COMMON_KEY ) )
{
configurartion.getCategory( CONFIG_COMMON_KEY ).setComment( CONFIG_COMMON_COMMENT );
}
// Create whitelist, if missing
if( !configurartion.hasCategory( CONFIG_FACADES_KEY ) )
{
final ConfigCategory category = configurartion.getCategory( CONFIG_FACADES_KEY );
category.setComment( CONFIG_FACADES_COMMENT );
// Whitelist some vanilla blocks like glass
final ConfigCategory minecraft = new ConfigCategory( "minecraft", category );
minecraft.put( "glass", new Property( "glass", "16", Type.INTEGER ) );
minecraft.put( "stained_glass", new Property( "stained_glass", "16", Type.INTEGER ) );
// Whitelist some AE2 blocks like quartz glass
final ConfigCategory appliedenergistics = new ConfigCategory( "appliedenergistics2", category );
appliedenergistics.put( "quartz_glass", new Property( "quartz_glass", "16", Type.INTEGER ) );
appliedenergistics.put( "quartz_vibrant_glass", new Property( "quartz_vibrant_glass", "16", Type.INTEGER ) );
}
return configurartion;
}
public static FacadeConfig instance()
@@ -53,36 +145,18 @@ public class FacadeConfig extends Configuration
return instance;
}
public boolean checkEnabled( final Block id, final int metadata, final boolean automatic )
public boolean allowTileEntityFacades()
{
if( id == null )
{
return false;
}
return this.allowTileEntityFacades;
}
final ResourceLocation blk = Item.REGISTRY.getNameForObject( Item.getItemFromBlock( id ) );
if( blk == null )
public boolean isWhiteListed( final Block block, final int metadata )
{
final Integer entry = this.whiteList.get( block.getRegistryName() );
if( entry != null )
{
for( final Field f : Block.class.getFields() )
{
try
{
if( f.get( Block.class ) == id )
{
return this.get( "minecraft", f.getName() + ( metadata == 0 ? "" : "/" + metadata ), automatic ).getBoolean( automatic );
}
}
catch( final Throwable e )
{
// :P
}
}
}
else
{
final Matcher mod = this.replacementPattern.matcher( blk.getResourceDomain() );
final Matcher name = this.replacementPattern.matcher( blk.getResourcePath() );
return this.get( mod.replaceAll( "" ), name.replaceAll( "" ) + ( metadata == 0 ? "" : "." + metadata ), automatic ).getBoolean( automatic );
return entry == metadata || entry == 16;
}
return false;