Package com.khorn.terraincontrol.configuration

Source Code of com.khorn.terraincontrol.configuration.WorldSettings

package com.khorn.terraincontrol.configuration;

import com.khorn.terraincontrol.BiomeIds;
import com.khorn.terraincontrol.LocalBiome;
import com.khorn.terraincontrol.LocalWorld;
import com.khorn.terraincontrol.TerrainControl;
import com.khorn.terraincontrol.configuration.io.FileSettingsReader;
import com.khorn.terraincontrol.configuration.io.FileSettingsWriter;
import com.khorn.terraincontrol.configuration.io.MemorySettingsReader;
import com.khorn.terraincontrol.configuration.io.SettingsReader;
import com.khorn.terraincontrol.configuration.standard.BiomeStandardValues;
import com.khorn.terraincontrol.configuration.standard.PluginStandardValues;
import com.khorn.terraincontrol.configuration.standard.StandardBiomeTemplate;
import com.khorn.terraincontrol.configuration.standard.WorldStandardValues;
import com.khorn.terraincontrol.customobjects.CustomObjectLoader;
import com.khorn.terraincontrol.customobjects.CustomObjectCollection;
import com.khorn.terraincontrol.logging.LogMarker;
import com.khorn.terraincontrol.util.helpers.FileHelper;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;

/**
* Holds the WorldConfig and all BiomeConfigs.
*
* <p>Note: this is an internal class that is pending a rename. For backwards
* compatibility it is still here as a public class with this name.
*/
public class WorldSettings implements ConfigProvider
{

    private static final int MAX_INHERITANCE_DEPTH = 15;
    private LocalWorld world;
    private File settingsDir;
    private CustomObjectCollection customObjects;
    public WorldConfig worldConfig;

    /**
     * Holds all biome configs. Generation Id => BiomeConfig
     *
     * Must be simple array for fast access. Warning: some ids may contain
     * null values, always check.
     */
    public LocalBiome[] biomes;

    /**
     * Holds all biomes that aren't virtual. These need to be sent to all
     * players on the server that have Terrain Control installed.
     */
    private final Collection<LocalBiome> savedBiomes = new HashSet<LocalBiome>();

    /**
     * Set this to true to skip indexing of settings and avoiding tampering
     * with the array in Minecraft's BiomeBase class.
     */
    private final boolean checkOnly;

    /**
     * The number of loaded biomes.
     */
    private int biomesCount;

    public WorldSettings(File settingsDir, LocalWorld world, boolean checkOnly)
    {
        this.settingsDir = settingsDir;
        this.world = world;
        this.checkOnly = checkOnly;

        loadCustomObjects();
        loadWorldConfig();

        this.biomes = new LocalBiome[world.getMaxBiomesCount()];
        loadBiomes();
    }

    private void loadCustomObjects()
    {
        File worldObjectsDir = new File(settingsDir, WorldStandardValues.WORLD_OBJECTS_DIRECTORY_NAME);

        // Migrate folders
        File oldWorldObjectsDir = new File(settingsDir, "BOBPlugins");
        if (!FileHelper.migrateFolder(oldWorldObjectsDir, worldObjectsDir))
        {
            TerrainControl.log(LogMarker.WARN, "Failed to move old world"
                    + " custom objects from {} to {} in world {}."
                    + " Please move the old objects manually.",
                    oldWorldObjectsDir.getName(), worldObjectsDir.getName(), world.getName());
        }

        Map<String, CustomObjectLoader> objectLoaders =
                TerrainControl.getCustomObjectManager().getObjectLoaders();

        customObjects = new CustomObjectCollection(objectLoaders, worldObjectsDir);
        customObjects.setFallback(TerrainControl.getCustomObjectManager().getGlobalObjects());
        TerrainControl.log(LogMarker.INFO, "{} world custom objects loaded.", customObjects.getAll().size());
    }

    private void loadWorldConfig()
    {
        File worldConfigFile = new File(settingsDir, WorldStandardValues.WORLD_CONFIG_FILE_NAME);
        this.worldConfig = new WorldConfig(new FileSettingsReader(world.getName(), worldConfigFile), world, customObjects);
        FileSettingsWriter.writeToFile(worldConfig, worldConfig.SettingsMode);
    }

    private void loadBiomes()
    {
        // Establish folders
        List<File> biomeDirs = new ArrayList<File>(2);
        // TerrainControl/worlds/<WorldName>/<WorldBiomes/
        biomeDirs.add(new File(settingsDir, correctOldBiomeConfigFolder(settingsDir)));
        // TerrainControl/GlobalBiomes/
        biomeDirs.add(new File(TerrainControl.getEngine().getTCDataFolder(), PluginStandardValues.BiomeConfigDirectoryName));

        FileHelper.makeFolders(biomeDirs);

        // Build a set of all biomes to load
        Collection<BiomeLoadInstruction> biomesToLoad = new HashSet<BiomeLoadInstruction>();
        biomesToLoad.addAll(world.getDefaultBiomes());

        // This adds all custombiomes that have been listed in WorldConfig to
        // the arrayList
        for (Entry<String, Integer> entry : worldConfig.customBiomeGenerationIds.entrySet())
        {
            String biomeName = entry.getKey();
            int generationId = entry.getValue();
            biomesToLoad.add(new BiomeLoadInstruction(biomeName, generationId, new StandardBiomeTemplate(
                    worldConfig.worldHeightScale)));
        }

        // Load all files
        BiomeConfigFinder biomeConfigFinder = new BiomeConfigFinder(worldConfig, TerrainControl.getPluginConfig().biomeConfigExtension);
        Map<String, BiomeConfig> biomeConfigs = biomeConfigFinder.loadBiomesFromDirectories(biomeDirs, biomesToLoad);

        // Read all settings
        String loadedBiomeNames = readSettings(biomeConfigs);

        // Save all settings
        saveSettings();

        TerrainControl.log(LogMarker.INFO, "{} biomes Loaded", new Object[] {biomesCount});
        TerrainControl.log(LogMarker.DEBUG, "{}", new Object[] {loadedBiomeNames});
    }

    @Override
    public WorldConfig getWorldConfig()
    {
        return worldConfig;
    }

    @Override
    public LocalBiome getBiomeByIdOrNull(int id)
    {
        if (id < 0 || id > biomes.length)
        {
            return null;
        }
        return biomes[id];
    }

    @Override
    public void reload()
    {
        // Clear biome collections
        Arrays.fill(this.biomes, null);
        this.savedBiomes.clear();
        this.biomesCount = 0;

        // Load again
        loadCustomObjects();
        loadWorldConfig();
        loadBiomes();
    }

    private String readSettings(Map<String, BiomeConfig> biomeConfigs)
    {
        StringBuilder loadedBiomeNames = new StringBuilder();
        for (BiomeConfig biomeConfig : biomeConfigs.values())
        {
            if (biomeConfig == null)
            {
                continue;
            }

            // Statistics of the loaded biomes
            this.biomesCount++;
            loadedBiomeNames.append(biomeConfig.getName());
            loadedBiomeNames.append(", ");

            // Inheritance
            processInheritance(biomeConfigs, biomeConfig, 0);

            // Settings reading
            biomeConfig.process();

            // Skip indexing when only checking
            if (this.checkOnly)
            {
                continue;
            }

            // Check generation id range
            int generationId = biomeConfig.generationId;
            if (generationId < 0 || generationId >= world.getMaxBiomesCount())
            {
                TerrainControl.log(LogMarker.ERROR,
                        "The biome id of the {} biome, {}, is too high. It must be between 0 and {}, inclusive.",
                        biomeConfig.getName(), generationId, world.getMaxBiomesCount() - 1);
                TerrainControl.log(LogMarker.ERROR, "The biome has been prevented from loading.");
                continue;
            }

            // Check for id conflicts
            if (biomes[generationId] != null)
            {
                TerrainControl.log(LogMarker.FATAL, "Duplicate biome id {} ({} and {})!", generationId, biomes[generationId].getName(),
                        biomeConfig.getName());
                TerrainControl.log(LogMarker.FATAL, "The biome {} has been prevented from loading.", new Object[] {biomeConfig.getName()});
                TerrainControl.log(LogMarker.INFO, "If you are updating an old pre-Minecraft 1.7 world, please read this wiki page:");
                TerrainControl.log(LogMarker.INFO, "https://github.com/Wickth/TerrainControl/wiki/Upgrading-an-old-map-to-Minecraft-1.7");
                continue;
            }

            // Get correct saved id (defaults to generation id, but can be set
            // to use the generation id of another biome)
            int savedId = biomeConfig.generationId;
            if (!biomeConfig.replaceToBiomeName.isEmpty())
            {
                BiomeConfig replaceToConfig = biomeConfigs.get(biomeConfig.replaceToBiomeName);
                if (replaceToConfig == null)
                {
                    biomeConfig.replaceToBiomeName = "";
                    TerrainControl.log(LogMarker.WARN, "Invalid ReplaceToBiomeName in biome {}: biome {} doesn't exist", biomeConfig.getName(),
                            biomeConfig.replaceToBiomeName);
                } else
                {
                    savedId = replaceToConfig.generationId;
                }
            }

            // Check saved id range
            if (savedId >= world.getMaxSavedBiomesCount())
            {
                TerrainControl.log(LogMarker.ERROR,
                        "Biomes with an id between {} and {} (inclusive) must have a valid ReplaceToBiomeName setting:",
                        world.getMaxBiomesCount(), world.getMaxSavedBiomesCount() - 1);
                TerrainControl.log(LogMarker.ERROR, "Minecraft can only save biomes with an id between 0 and {}, inclusive.",
                        world.getMaxBiomesCount() - 1);
                TerrainControl.log(LogMarker.ERROR, "This means that the biome {} with map file id {} had to be prevented from loading.",
                        biomeConfig.getName(), savedId);
                continue;
            }

            // Create biome
            LocalBiome biome = world.createBiomeFor(biomeConfig, new BiomeIds(generationId, savedId));
            this.biomes[biome.getIds().getGenerationId()] = biome;

            // If not virtual, add to saved biomes set
            if (!biome.getIds().isVirtual())
            {
                savedBiomes.add(biome);
            }

            // Indexing ReplacedBlocks
            if (!this.worldConfig.BiomeConfigsHaveReplacement)
            {
                this.worldConfig.BiomeConfigsHaveReplacement = biomeConfig.replacedBlocks.hasReplaceSettings();
            }

            // Indexing BiomeRarity
            if (this.worldConfig.NormalBiomes.contains(biomeConfig.getName()))
            {
                this.worldConfig.normalBiomesRarity += biomeConfig.biomeRarity;
            }
            if (this.worldConfig.IceBiomes.contains(biomeConfig.getName()))
            {
                this.worldConfig.iceBiomesRarity += biomeConfig.biomeRarity;
            }

            // Indexing MaxSmoothRadius
            if (this.worldConfig.maxSmoothRadius < biomeConfig.smoothRadius)
            {
                this.worldConfig.maxSmoothRadius = biomeConfig.smoothRadius;
            }

            // Indexing BiomeColor
            if (this.worldConfig.biomeMode == TerrainControl.getBiomeModeManager().FROM_IMAGE)
            {
                if (this.worldConfig.biomeColorMap == null)
                {
                    this.worldConfig.biomeColorMap = new HashMap<Integer, Integer>();
                }

                int color = biomeConfig.biomeColor;
                this.worldConfig.biomeColorMap.put(color, biome.getIds().getGenerationId());
            }

            // Setting effects
            biome.setEffects();
        }

        if (this.biomesCount > 0)
        {
            // Remove last ", "
            loadedBiomeNames.delete(loadedBiomeNames.length() - 2, loadedBiomeNames.length());
        }
        return loadedBiomeNames.toString();
    }

    private void saveSettings()
    {
        for (LocalBiome biome : this.biomes)
        {
            if (biome != null)
            {
                biome.getBiomeConfig().outputToFile();
            }
        }
    }

    private void processInheritance(Map<String, BiomeConfig> allBiomeConfigs, BiomeConfig biomeConfig, int currentDepth)
    {
        if (biomeConfig.biomeExtendsProcessed)
        {
            // Already processed earlier
            return;
        }

        String extendedBiomeName = biomeConfig.biomeExtends;
        if (extendedBiomeName == null || extendedBiomeName.length() == 0)
        {
            // Not extending anything
            biomeConfig.biomeExtendsProcessed = true;
            return;
        }

        // This biome extends another biome
        BiomeConfig extendedBiomeConfig = allBiomeConfigs.get(extendedBiomeName);
        if (extendedBiomeConfig == null)
        {
            TerrainControl.log(LogMarker.WARN, "The biome {} tried to extend the biome {}, but that biome doesn't exist.", new Object[] {
                    biomeConfig.getName(), extendedBiomeName});
            return;
        }

        // Check for too much recursion
        if (currentDepth > MAX_INHERITANCE_DEPTH)
        {
            TerrainControl.log(LogMarker.FATAL,
                    "The biome {} cannot extend the biome {} - too much configs processed already! Cyclical inheritance?", new Object[] {
                            biomeConfig.getName(), extendedBiomeConfig.getName()});
        }

        if (!extendedBiomeConfig.biomeExtendsProcessed)
        {
            // This biome has not been processed yet, do that first
            processInheritance(allBiomeConfigs, extendedBiomeConfig, currentDepth + 1);
        }

        // Merge the two
        biomeConfig.merge(extendedBiomeConfig);

        // Done
        biomeConfig.biomeExtendsProcessed = true;
    }

    // Read settings from the network
    public WorldSettings(DataInputStream stream, LocalWorld world) throws IOException
    {
        this.checkOnly = false;
        // We need a valid CustomObjects object with things like the trees in
        // it, so that the configs can load without errors
        // An empty CustomObjects instance with the global objects as fallback
        // would work just as well
        this.customObjects = TerrainControl.getCustomObjectManager().getGlobalObjects();

        // Create WorldConfig
        SettingsReader worldSettingsReader = new MemorySettingsReader(world.getName());
        worldSettingsReader.putSetting(WorldStandardValues.WORLD_FOG, stream.readInt());
        worldSettingsReader.putSetting(WorldStandardValues.WORLD_NIGHT_FOG, stream.readInt());
        worldConfig = new WorldConfig(worldSettingsReader, world, customObjects);

        // Custom biomes + ids
        int count = stream.readInt();
        while (count-- > 0)
        {
            String biomeName = ConfigFile.readStringFromStream(stream);
            int id = stream.readInt();
            worldConfig.customBiomeGenerationIds.put(biomeName, id);
        }

        // BiomeConfigs
        StandardBiomeTemplate defaultSettings = new StandardBiomeTemplate(worldConfig.worldHeightCap);
        biomes = new LocalBiome[world.getMaxBiomesCount()];

        count = stream.readInt();
        while (count-- > 0)
        {
            int id = stream.readInt();
            String biomeName = ConfigFile.readStringFromStream(stream);
            SettingsReader biomeReader = new MemorySettingsReader(biomeName);
            biomeReader.putSetting(BiomeStandardValues.BIOME_TEMPERATURE, stream.readFloat());
            biomeReader.putSetting(BiomeStandardValues.BIOME_WETNESS, stream.readFloat());
            biomeReader.putSetting(BiomeStandardValues.SKY_COLOR, stream.readInt());
            biomeReader.putSetting(BiomeStandardValues.WATER_COLOR, stream.readInt());
            biomeReader.putSetting(BiomeStandardValues.GRASS_COLOR, stream.readInt());
            biomeReader.putSetting(BiomeStandardValues.GRASS_COLOR_IS_MULTIPLIER, stream.readBoolean());
            biomeReader.putSetting(BiomeStandardValues.FOLIAGE_COLOR, stream.readInt());
            biomeReader.putSetting(BiomeStandardValues.FOLIAGE_COLOR_IS_MULTIPLIER, stream.readBoolean());

            BiomeLoadInstruction instruction = new BiomeLoadInstruction(biomeName, id, defaultSettings);
            BiomeConfig config = new BiomeConfig(biomeReader, instruction, worldConfig);
            config.process();
            LocalBiome biome = world.createBiomeFor(config, new BiomeIds(id));

            biomes[id] = biome;
            biome.setEffects();
        }

        savedBiomes.addAll(Arrays.asList(biomes));
    }

    private String correctOldBiomeConfigFolder(File settingsDir)
    {
        // Rename the old folder
        String biomeFolderName = WorldStandardValues.WORLD_BIOMES_DIRECTORY_NAME;
        File oldBiomeConfigs = new File(settingsDir, "BiomeConfigs");
        if (oldBiomeConfigs.exists())
        {
            if (!oldBiomeConfigs.renameTo(new File(settingsDir, biomeFolderName)))
            {
                TerrainControl.log(LogMarker.WARN, "========================");
                TerrainControl.log(LogMarker.WARN, "Fould old `BiomeConfigs` folder, but it could not be renamed to `", biomeFolderName,
                        "`!");
                TerrainControl.log(LogMarker.WARN, "Please rename the folder manually.");
                TerrainControl.log(LogMarker.WARN, "========================");
                biomeFolderName = "BiomeConfigs";
            }
        }
        return biomeFolderName;
    }

    @Override
    public void writeToStream(DataOutputStream stream) throws IOException
    {
        // General information
        ConfigFile.writeStringToStream(stream, worldConfig.getName());

        stream.writeInt(worldConfig.WorldFog);
        stream.writeInt(worldConfig.WorldNightFog);

        // Fetch all non-virtual custom biomes
        Collection<LocalBiome> nonVirtualCustomBiomes = new ArrayList<LocalBiome>(worldConfig.customBiomeGenerationIds.size());
        for (Integer generationId : worldConfig.customBiomeGenerationIds.values())
        {
            LocalBiome biome = biomes[generationId];
            if (!biome.getIds().isVirtual()) {
                nonVirtualCustomBiomes.add(biome);
            }
        }

        // Write them to the stream
        stream.writeInt(nonVirtualCustomBiomes.size());
        for (LocalBiome biome : nonVirtualCustomBiomes)
        {
            ConfigFile.writeStringToStream(stream, biome.getName());
            stream.writeInt(biome.getIds().getSavedId());
        }

        // BiomeConfigs
        stream.writeInt(savedBiomes.size());
        for (LocalBiome biome : savedBiomes)
        {
            if (biome == null)
            {
                continue;
            }
            stream.writeInt(biome.getIds().getSavedId());
            biome.getBiomeConfig().writeToStream(stream);
        }
    }

    @Override
    public LocalBiome[] getBiomeArray()
    {
        return this.biomes;
    }

    @Override
    public CustomObjectCollection getCustomObjects()
    {
        return customObjects;
    }

}
TOP

Related Classes of com.khorn.terraincontrol.configuration.WorldSettings

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.