Remove obsolete biome profile files

Also used to rename unedited "Minetest Game.mt" files to "Minetest Game v.4.mt"
master
Treer 2018-10-14 19:40:32 +11:00
parent 0ff2f22eaf
commit 64e796c8a8
7 changed files with 125 additions and 7 deletions

View File

@ -41,6 +41,7 @@ public class AmidstSettings {
public final Setting<String> lastProfile;
public final Setting<String> lastBiomeProfile;
public final Setting<Long> lastBiomeProfilePurge;
public final Setting<String> worldType;
/**
@ -78,6 +79,7 @@ public class AmidstSettings {
lastProfile = Settings.createString( preferences, "profile", "");
lastBiomeProfile = Settings.createString( preferences, "biomeProfile", "");
lastBiomeProfilePurge = Settings.createLong( preferences, "biomePurgeDate", 0);
worldType = Settings.createString( preferences, "worldType", WorldType.PROMPT_EACH_TIME);
biomeProfileSelection = new BiomeProfileSelection(BiomeProfileImpl.getDefaultProfiles().iterator().next());
// @formatter:on

View File

@ -164,7 +164,7 @@ public class BiomeProfileMenuFactory implements BiomeProfileUpdateListener {
private void initParentMenu() {
parentMenu.removeAll();
biomeProfileDirectory.saveDefaultProfilesIfNecessary();
biomeProfileDirectory.saveDefaultProfilesIfNecessary(settings);
BiomeProfileVisitorImpl visitor = new BiomeProfileVisitorImpl(parentMenu, actions, settings);
biomeProfileDirectory.visitProfiles(visitor);
parentMenu.addSeparator();

View File

@ -1,7 +1,13 @@
package amidst.minetest.world.mapgen;
import java.time.LocalDate;
import java.time.Month;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import amidst.mojangapi.world.biome.BiomeColor;
@ -10,11 +16,39 @@ public class DefaultBiomes {
private static Map<String, MinetestBiome[]> biomeLists = null;
public static final String BIOMEPROFILENAME_V6 = "v6";
public static final String BIOMEPROFILENAME_MINETEST_GAME = "Minetest Game";
public static final String BIOMEPROFILENAME_MINETEST_GAME = "Minetest Game v.4";
public static final short FLOATLAND_SHADOW_LIMIT = 1024;
public static final short FLOATLAND_LEVEL = 1280;
/**
* List of biome profile files that were created by older versions of Admist
* and can now be deleted.
* @see getObsoleteBiomeProfilesDate()
*/
public static List<Entry<String, String>> getObsoleteBiomeProfiles() {
List<Entry<String, String>> result = new ArrayList<Entry<String, String>>();
result.add(new AbstractMap.SimpleEntry<String, String>("Minetest Game", "c0f90f045b4111bab064f669958196fd73bad894"));
result.add(new AbstractMap.SimpleEntry<String, String>("Minetest default", "b9535c9299fd0ee92067c8c6b38a46c43d22be71")); // v1.1
result.add(new AbstractMap.SimpleEntry<String, String>("V6 biomes", "2c74eaf3c805c9f05797bfed906b70dd18772587")); // v1.1
result.add(new AbstractMap.SimpleEntry<String, String>("VoxelGarden", "8ab488cbbe5c3cbfc1aa3bae8c717104e98e00ca")); // v1.1
return result;
}
/**
* Returns the date of the data provided by getObsoleteBiomeProfiles().
* If the returned date is younger than the last time obsolete biomes were removed, then
* no further checks are necessary.
* @see getObsoleteBiomeProfiles()
*/
public static LocalDate getObsoleteBiomeProfilesDate() {
return LocalDate.of(2018, Month.OCTOBER, 20);
}
/**
* The first item in the list will be considered the definitive biome list
*/

View File

@ -147,7 +147,7 @@ public class BiomeDataOracleV7 extends MinetestBiomeDataOracle {
if (lastHeight != Short.MIN_VALUE) {
// Perhaps the height hasn't changed and we can save some tests with this information: We can check if
// height is the same with only two tests (and only 1 will be needed if lastHeight was sea level).
// height is the same with only two tests (and only 1 will be needed if lastHeight was highestGround).
int lastAirHeight = lastHeight + 1;
float density_gradient = -((float)(lastAirHeight - mount_zero_level) / mnt_h_n);

View File

@ -28,6 +28,13 @@ public enum Settings {
value -> preferences.putBoolean(key, value));
}
public static Setting<Long> createLong(Preferences preferences, String key, long defaultValue) {
return new SettingBase<>(
defaultValue,
value -> preferences.getLong(key, value),
value -> preferences.putLong(key, value));
}
public static Setting<Dimension> createDimension(Preferences preferences, String key, Dimension defaultValue) {
return new SettingBase<>(
defaultValue,

View File

@ -104,8 +104,8 @@ public class BiomeAuthority implements BiomeProfileUpdateListener {
);
// Makes sure the default biomeprofiles for this game engine are added to the biomes
// directory so the user can edit them.
biomeProfileDirectory.saveDefaultProfilesIfNecessary();
// directory so the user can edit them.
biomeProfileDirectory.saveDefaultProfilesIfNecessary(settings);
// Makes sure biomeProfileSelection is set to a profile that's suitable for the
// current game engine.

View File

@ -1,15 +1,20 @@
package amidst.settings.biomeprofile;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.time.LocalDate;
import java.util.Collection;
import java.util.Map.Entry;
import amidst.AmidstSettings;
import amidst.AmidstVersion;
import amidst.documentation.Immutable;
import amidst.logging.AmidstLogger;
import amidst.minetest.world.mapgen.DefaultBiomes;
import amidst.parsing.FormatException;
import amidst.parsing.json.JsonReader;
import amidst.util.OperatingSystemDetector;
@ -139,11 +144,14 @@ public class BiomeProfileDirectory {
this.biomeProfileImpl = biome_profile_impl;
}
public void saveDefaultProfilesIfNecessary() {
public void saveDefaultProfilesIfNecessary(AmidstSettings settings) {
if (!isValid()) {
AmidstLogger.info("Unable to find biome profile directory.");
} else {
AmidstLogger.info("Found biome profile directory.");
removeObsoleteBiomeProfileFiles(settings);
for(BiomeProfile profile : createDefaultProfiles()) {
File profileFile = new File(root, profile.getName() + "." + profileFileExtension);
@ -158,6 +166,73 @@ public class BiomeProfileDirectory {
}
}
/**
* Delete any old biome profile files that are out of date, or have had their name changed.
* This only deletes known files, to prevent removal of anything user-created or user-edited.
*/
private void removeObsoleteBiomeProfileFiles(AmidstSettings settings) {
long obsoleteLastRemoved_epochDay = settings.lastBiomeProfilePurge.get();
if ((obsoleteLastRemoved_epochDay == 0) || (LocalDate.now().toEpochDay() < obsoleteLastRemoved_epochDay)) {
// The data we have about obsolete biome profiles is more recent than the
// last time we removed obsolete biome profiles, so do so again.
try {
MessageDigest shaDigest = MessageDigest.getInstance("SHA-1");
// Realistically it's only the Minetest biome profiles that will need older files removed
for(Entry<String, String> entry : DefaultBiomes.getObsoleteBiomeProfiles()) {
File obsoleteFile = new File(root, entry.getKey() + "." + profileFileExtension);
if (obsoleteFile.isFile()) {
// check the file content matches the obsolete content, i.e. hasn't been edited by the user
if (entry.getValue().equals(getFileChecksum(shaDigest, obsoleteFile))) {
AmidstLogger.info("Removing obsolete biome profile \"" + obsoleteFile.getName() + "\"");
obsoleteFile.delete();
}
}
}
// Save the date the cleanup was performed
settings.lastBiomeProfilePurge.set(LocalDate.now().toEpochDay());
} catch(Exception ex) {
// cleaning up obsolete files is not critical
AmidstLogger.error("Exception removing old biome profiles: " + ex.getMessage());
}
}
}
private static String getFileChecksum(MessageDigest digest, File file) throws IOException
{
//Get file input stream for reading the file content
FileInputStream fis = new FileInputStream(file);
//Create byte array to read data in chunks
byte[] byteArray = new byte[1024];
int bytesCount = 0;
//Read file data and update in message digest
while ((bytesCount = fis.read(byteArray)) != -1) {
digest.update(byteArray, 0, bytesCount);
};
//close the stream; We don't need it now.
fis.close();
//Get the hash's bytes
byte[] bytes = digest.digest();
//This bytes[] has bytes in decimal format;
//Convert it to hexadecimal format
StringBuilder sb = new StringBuilder();
for(int i=0; i< bytes.length ;i++)
{
sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
}
//return complete hash
return sb.toString();
}
public void visitProfiles(BiomeProfileVisitor visitor) {
visitProfiles(root, visitor);
}