Autopopulate configs with discovered blockids and biomes

This commit is contained in:
Blue (Lukas Rieger) 2019-12-31 12:23:41 +01:00
parent f6be5dd30f
commit 22c2772c70
8 changed files with 159 additions and 49 deletions

View File

@ -24,18 +24,28 @@
*/
package de.bluecolored.bluemap.core.config;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map.Entry;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.mca.mapping.BiomeMapper;
import de.bluecolored.bluemap.core.world.Biome;
import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.loader.ConfigurationLoader;
public class BiomeConfig implements BiomeMapper {
private ConfigurationLoader<? extends ConfigurationNode> autopoulationConfigLoader;
private HashMap<Integer, Biome> biomes;
public BiomeConfig(ConfigurationNode node) {
this(node, null);
}
public BiomeConfig(ConfigurationNode node, ConfigurationLoader<? extends ConfigurationNode> autopoulationConfigLoader) {
this.autopoulationConfigLoader = autopoulationConfigLoader;
biomes = new HashMap<>();
for (Entry<Object, ? extends ConfigurationNode> e : node.getChildrenMap().entrySet()){
@ -48,7 +58,27 @@ public BiomeConfig(ConfigurationNode node) {
@Override
public Biome get(int id) {
return biomes.getOrDefault(id, Biome.DEFAULT);
Biome biome = biomes.get(id);
if (biome == null) {
if (autopoulationConfigLoader != null) {
biomes.put(id, Biome.DEFAULT);
synchronized (autopoulationConfigLoader) {
try {
ConfigurationNode node = autopoulationConfigLoader.load();
node.getNode("unknown:" + id).getNode("id").setValue(id);
autopoulationConfigLoader.save(node);
} catch (IOException ex) {
Logger.global.noFloodError("biomeconf-autopopulate-ioex", "Failed to auto-populate BiomeConfig!", ex);
}
}
}
return Biome.DEFAULT;
}
return biome;
}
}

View File

@ -24,6 +24,7 @@
*/
package de.bluecolored.bluemap.core.config;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
@ -32,12 +33,20 @@
import de.bluecolored.bluemap.core.mca.mapping.BlockIdMapper;
import de.bluecolored.bluemap.core.world.BlockState;
import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.loader.ConfigurationLoader;
public class BlockIdConfig implements BlockIdMapper {
private ConfigurationLoader<? extends ConfigurationNode> autopoulationConfigLoader;
private Map<BlockIDMeta, BlockState> mappings;
public BlockIdConfig(ConfigurationNode node) {
this(node, null);
}
public BlockIdConfig(ConfigurationNode node, ConfigurationLoader<? extends ConfigurationNode> autopoulationConfigLoader) {
this.autopoulationConfigLoader = autopoulationConfigLoader;
mappings = new HashMap<>();
for (Entry<Object, ? extends ConfigurationNode> e : node.getChildrenMap().entrySet()){
@ -69,10 +78,27 @@ public BlockIdConfig(ConfigurationNode node) {
@Override
public BlockState get(int id, int meta) {
BlockState state = mappings.get(new BlockIDMeta(id, meta));
if (id == 0) return BlockState.AIR;
BlockIDMeta idmeta = new BlockIDMeta(id, meta);
BlockState state = mappings.get(idmeta);
if (state == null) {
state = mappings.getOrDefault(new BlockIDMeta(id, 0), BlockState.AIR); //meta-fallback
if (autopoulationConfigLoader != null) {
mappings.put(idmeta, state);
synchronized (autopoulationConfigLoader) {
try {
ConfigurationNode node = autopoulationConfigLoader.load();
node.getNode(id + ":" + meta).setValue(state.toString());
autopoulationConfigLoader.save(node);
} catch (IOException ex) {
Logger.global.noFloodError("blockidconf-autopopulate-ioex", "Failed to auto-populate BlockIdConfig!", ex);
}
}
}
}
return state;

View File

@ -33,20 +33,28 @@
import com.google.common.cache.LoadingCache;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.mca.mapping.BlockPropertiesMapper;
import de.bluecolored.bluemap.core.world.BlockProperties;
import de.bluecolored.bluemap.core.world.BlockState;
import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.loader.ConfigurationLoader;
public class BlockPropertiesConfig implements BlockPropertiesMapper {
private ConfigurationLoader<? extends ConfigurationNode> autopoulationConfigLoader;
private Multimap<String, BlockStateMapping<BlockProperties>> mappings;
private LoadingCache<BlockState, BlockProperties> mappingCache;
public BlockPropertiesConfig(ConfigurationNode node) throws IOException {
this(node, null);
}
public BlockPropertiesConfig(ConfigurationNode node, ConfigurationLoader<? extends ConfigurationNode> autopoulationConfigLoader) throws IOException {
this.autopoulationConfigLoader = autopoulationConfigLoader;
mappings = HashMultimap.create();
for (Entry<Object, ? extends ConfigurationNode> e : node.getChildrenMap().entrySet()){
@ -65,8 +73,6 @@ public BlockPropertiesConfig(ConfigurationNode node) throws IOException {
}
}
mappings = Multimaps.unmodifiableMultimap(mappings);
mappingCache = CacheBuilder.newBuilder()
.concurrencyLevel(8)
.maximumSize(10000)
@ -92,6 +98,23 @@ private BlockProperties mapNoCache(BlockState bs){
}
}
if (autopoulationConfigLoader != null) {
mappings.put(bs.getFullId(), new BlockStateMapping<BlockProperties>(new BlockState(bs.getFullId()), BlockProperties.DEFAULT));
synchronized (autopoulationConfigLoader) {
try {
ConfigurationNode node = autopoulationConfigLoader.load();
ConfigurationNode bpNode = node.getNode(bs.getFullId());
bpNode.getNode("culling").setValue(false);
bpNode.getNode("occluding").setValue(false);
bpNode.getNode("flammable").setValue(false);
autopoulationConfigLoader.save(node);
} catch (IOException ex) {
Logger.global.noFloodError("blockpropsconf-autopopulate-ioex", "Failed to auto-populate BlockPropertiesConfig!", ex);
}
}
}
return BlockProperties.DEFAULT;
}

View File

@ -113,38 +113,52 @@ public void loadOrCreateConfigs() throws IOException {
mainConfig = new MainConfig(loadOrCreate(getMainConfigFile(), defaultMainConfig, mainConfigDefaultValues, true));
URL blockIdsConfigUrl = BlueMap.class.getResource("/blockIds.json");
blockIdConfig = new BlockIdConfig(loadOrCreate(getBlockIdConfigFile(), blockIdsConfigUrl, blockIdsConfigUrl, false));
blockIdConfig = new BlockIdConfig(loadOrCreate(getBlockIdConfigFile(), null, blockIdsConfigUrl, false), getLoader(makeAutogen(getBlockIdConfigFile())));
URL blockPropertiesConfigUrl = BlueMap.class.getResource("/blockProperties.json");
blockPropertiesConfig = new BlockPropertiesConfig(loadOrCreate(getBlockPropertiesConfigFile(), blockPropertiesConfigUrl, blockPropertiesConfigUrl, false));
blockPropertiesConfig = new BlockPropertiesConfig(loadOrCreate(getBlockPropertiesConfigFile(), null, blockPropertiesConfigUrl, false), getLoader(makeAutogen(getBlockPropertiesConfigFile())));
URL biomeConfigUrl = BlueMap.class.getResource("/biomes.json");
biomeConfig = new BiomeConfig(loadOrCreate(getBiomeConfigFile(), biomeConfigUrl, biomeConfigUrl, false));
biomeConfig = new BiomeConfig(loadOrCreate(getBiomeConfigFile(), null, biomeConfigUrl, false), getLoader(makeAutogen(getBiomeConfigFile())));
}
private ConfigurationNode loadOrCreate(File configFile, URL defaultConfig, URL defaultValues, boolean usePlaceholders) throws IOException {
ConfigurationNode configNode;
if (!configFile.exists()) {
configFile.getParentFile().mkdirs();
//load content of default config
String content;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(defaultConfig.openStream(), StandardCharsets.UTF_8))){
content = reader.lines().collect(Collectors.joining("\n"));
}
//replace placeholders if enabled
if (usePlaceholders) {
for (Placeholder placeholder : CONFIG_PLACEHOLDERS) {
content = placeholder.apply(content);
if (defaultConfig != null) {
//load content of default config
String content;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(defaultConfig.openStream(), StandardCharsets.UTF_8))){
content = reader.lines().collect(Collectors.joining("\n"));
}
//replace placeholders if enabled
if (usePlaceholders) {
for (Placeholder placeholder : CONFIG_PLACEHOLDERS) {
content = placeholder.apply(content);
}
}
//create the config file
Files.write(configFile.toPath(), content.getBytes(StandardCharsets.UTF_8));
//load
configNode = getLoader(configFile).load();
} else {
//create empty config
ConfigurationLoader<? extends ConfigurationNode> loader = getLoader(configFile);
configNode = loader.createEmptyNode();
//save to create file
loader.save(configNode);
}
//create the config file
Files.write(configFile.toPath(), content.getBytes(StandardCharsets.UTF_8));
} else {
//load config
configNode = getLoader(configFile).load();
}
ConfigurationNode configNode = getLoader(configFile).load();
//populate missing values with default values
if (defaultValues != null) {
@ -155,6 +169,12 @@ private ConfigurationNode loadOrCreate(File configFile, URL defaultConfig, URL d
return configNode;
}
private File makeAutogen(File file) throws IOException {
File autogenFile = file.getCanonicalFile().toPath().getParent().resolve("generated").resolve(file.getName()).toFile();
autogenFile.getParentFile().mkdirs();
return autogenFile;
}
private ConfigurationLoader<? extends ConfigurationNode> getLoader(URL url){
if (url.getFile().endsWith(".json")) return GsonConfigurationLoader.builder().setURL(url).build();
if (url.getFile().endsWith(".yaml") || url.getFile().endsWith(".yml")) return YAMLConfigurationLoader.builder().setURL(url).build();

View File

@ -136,30 +136,38 @@ public BlockStateResource build(String blockstateFile) throws IOException {
//create variants
for (Entry<Object, ? extends ConfigurationNode> entry : config.getNode("variants").getChildrenMap().entrySet()) {
String conditionString = entry.getKey().toString();
ConfigurationNode transformedModelNode = entry.getValue();
Variant variant = blockState.new Variant();
variant.condition = parseConditionString(conditionString);
variant.models = loadModels(transformedModelNode, blockstateFile);
variant.updateTotalWeight();
blockState.variants.add(variant);
try {
String conditionString = entry.getKey().toString();
ConfigurationNode transformedModelNode = entry.getValue();
Variant variant = blockState.new Variant();
variant.condition = parseConditionString(conditionString);
variant.models = loadModels(transformedModelNode, blockstateFile);
variant.updateTotalWeight();
blockState.variants.add(variant);
} catch (Exception ex) {
Logger.global.logWarning("Failed to parse a variant of " + blockstateFile + ": " + ex);
}
}
//create multipart
for (ConfigurationNode partNode : config.getNode("multipart").getChildrenList()) {
Variant variant = blockState.new Variant();
ConfigurationNode whenNode = partNode.getNode("when");
if (!whenNode.isVirtual()) {
variant.condition = parseCondition(whenNode);
try {
Variant variant = blockState.new Variant();
ConfigurationNode whenNode = partNode.getNode("when");
if (!whenNode.isVirtual()) {
variant.condition = parseCondition(whenNode);
}
variant.models = loadModels(partNode.getNode("apply"), blockstateFile);
variant.updateTotalWeight();
blockState.multipart.add(variant);
} catch (Exception ex) {
Logger.global.logWarning("Failed to parse a multipart-part of " + blockstateFile + ": " + ex);
}
variant.models = loadModels(partNode.getNode("apply"), blockstateFile);
variant.updateTotalWeight();
blockState.multipart.add(variant);
}
return blockState;
@ -233,12 +241,13 @@ private PropertyCondition parseCondition(ConfigurationNode conditionNode) {
return PropertyCondition.and(andConditions.toArray(new PropertyCondition[andConditions.size()]));
}
private PropertyCondition parseConditionString(String conditionString) {
private PropertyCondition parseConditionString(String conditionString) throws IllegalArgumentException {
List<PropertyCondition> conditions = new ArrayList<>();
if (!conditionString.isEmpty() && !conditionString.equals("default")) {
if (!conditionString.isEmpty() && !conditionString.equals("default") && !conditionString.equals("normal")) {
String[] conditionSplit = StringUtils.split(conditionString, ',');
for (String element : conditionSplit) {
String[] keyval = StringUtils.split(element, "=", 2); //TODO what if it is wrong formatted?
String[] keyval = StringUtils.split(element, "=", 2);
if (keyval.length < 2) throw new IllegalArgumentException("Condition-String '" + conditionString + "' is invalid!");
conditions.add(PropertyCondition.property(keyval[0], keyval[1]));
}
}

View File

@ -155,7 +155,7 @@ public final boolean checkVariantCondition(String condition){
public boolean equals(Object obj) {
if (!(obj instanceof BlockState)) return false;
BlockState b = (BlockState) obj;
if (!Objects.equals(getId(), b.getId())) return false;
if (!Objects.equals(getFullId(), b.getFullId())) return false;
if (!Objects.equals(getProperties(), b.getProperties())) return false;
return true;
}
@ -163,7 +163,7 @@ public boolean equals(Object obj) {
@Override
public int hashCode() {
if (!hashed){
hash = Objects.hash( getId(), getProperties() );
hash = Objects.hash( getFullId(), getProperties() );
hashed = true;
}
@ -177,7 +177,7 @@ public String toString() {
sj.add(e.getKey() + "=" + e.getValue());
}
return getId() + "[" + sj.toString() + "]";
return getFullId() + "[" + sj.toString() + "]";
}
public static BlockState fromString(String serializedBlockState) throws IllegalArgumentException {

View File

@ -1,4 +1,5 @@
{
"0:0": "minecraft:air",
"1:0": "minecraft:stone",
"1:1": "minecraft:granite",
"1:2": "minecraft:polished_granite",

View File

@ -135,6 +135,7 @@ public synchronized void load() throws ExecutionException, IOException, Interrup
URL defaultSpongeConfig = SpongePlugin.class.getResource("/bluemap-sponge.conf");
URL spongeConfigDefaults = SpongePlugin.class.getResource("/bluemap-sponge-defaults.conf");
ConfigManager configManager = new ConfigManager(getConfigPath().toFile(), defaultSpongeConfig, spongeConfigDefaults);
configManager.loadOrCreateConfigs();
config = configManager.getMainConfig();
File blockColorsConfigFile = getConfigPath().resolve("blockColors.json").toFile();