mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2025-07-18 10:32:30 +00:00
Implement multiple failover types
This commit is contained in:
parent
3ca1c5980c
commit
1a7d49ab1e
@ -22,8 +22,10 @@ public class TerraWorld {
|
||||
private final BiomeZone zone;
|
||||
private final ConfigPack config;
|
||||
private final WorldConfig worldConfig;
|
||||
private boolean safe;
|
||||
|
||||
private TerraWorld(World w) {
|
||||
safe = true;
|
||||
worldConfig = new WorldConfig(w, Terra.getInstance());
|
||||
config = worldConfig.getConfig();
|
||||
UserDefinedGrid[] definedGrids = new UserDefinedGrid[config.biomeList.size()];
|
||||
@ -42,6 +44,7 @@ public class TerraWorld {
|
||||
definedGrids[i] = g.getGrid(w, worldConfig);
|
||||
}
|
||||
} catch(NullPointerException e) {
|
||||
safe = false;
|
||||
Debug.stack(e);
|
||||
Bukkit.getLogger().severe("No such BiomeGrid " + partName);
|
||||
Bukkit.getLogger().severe("Please check configuration files for errors. Configuration errors will have been reported during initialization.");
|
||||
@ -64,6 +67,7 @@ public class TerraWorld {
|
||||
erosion = g.getGrid(w, worldConfig);
|
||||
}
|
||||
} catch(NullPointerException e) {
|
||||
safe = false;
|
||||
Debug.stack(e);
|
||||
Bukkit.getLogger().severe("No such BiomeGrid (erosion): " + config.erosionName);
|
||||
Bukkit.getLogger().severe("Please check configuration files for errors. Configuration errors will have been reported during initialization.");
|
||||
@ -73,6 +77,7 @@ public class TerraWorld {
|
||||
}
|
||||
zone = new BiomeZone(w, worldConfig, definedGrids);
|
||||
grid = new TerraBiomeGrid(w, config.freq1, config.freq2, zone, config, erosion);
|
||||
|
||||
}
|
||||
|
||||
public static synchronized TerraWorld getWorld(World w) {
|
||||
@ -102,4 +107,8 @@ public class TerraWorld {
|
||||
public static int numWorlds() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
public boolean isSafe() {
|
||||
return safe;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.dfsek.terra.biome;
|
||||
|
||||
import com.dfsek.terra.biome.failsafe.FailoverBiome;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.base.ConfigUtil;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
@ -10,6 +11,7 @@ import org.bukkit.World;
|
||||
import org.polydev.gaea.biome.Biome;
|
||||
import org.polydev.gaea.biome.BiomeGrid;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
import org.polydev.gaea.math.parsii.tokenizer.ParseException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -52,7 +54,7 @@ public class TerraBiomeGrid extends BiomeGrid {
|
||||
if(ConfigUtil.debug) e.printStackTrace();
|
||||
if(failNum % 256 == 0) LangUtil.log("error.severe-config", Level.SEVERE, String.valueOf(x), String.valueOf(z));
|
||||
failNum++;
|
||||
return null;
|
||||
return ConfigUtil.failType.fail();
|
||||
}
|
||||
if(erode != null && b.isErodible() && erode.isEroded(xp, zp)) {
|
||||
return erosionGrid.getBiome(xp, zp, phase);
|
||||
|
59
src/main/java/com/dfsek/terra/biome/failsafe/FailType.java
Normal file
59
src/main/java/com/dfsek/terra/biome/failsafe/FailType.java
Normal file
@ -0,0 +1,59 @@
|
||||
package com.dfsek.terra.biome.failsafe;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.polydev.gaea.biome.Biome;
|
||||
import org.polydev.gaea.math.parsii.tokenizer.ParseException;
|
||||
|
||||
/**
|
||||
* What happens if terrain generation is attempted with an unrecoverable config error.
|
||||
*/
|
||||
public enum FailType {
|
||||
/**
|
||||
* Return failover biome, then shut down server to minimize damage.
|
||||
* Generally the safest option.
|
||||
*/
|
||||
SHUTDOWN {
|
||||
@Override
|
||||
public Biome fail() {
|
||||
Bukkit.getServer().shutdown();
|
||||
try {
|
||||
return new FailoverBiome();
|
||||
} catch(ParseException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Returns null, hard crashing the server, but not generating any corrupted terrain.<br>
|
||||
* This option is <br>NOT</br> stable, but it has the least risk of blank chunks being generated.
|
||||
* However, it has the highest risk of corruption!
|
||||
*/
|
||||
CRASH {
|
||||
@Override
|
||||
public Biome fail() {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Returns a failover biome, which generates completely blank chunks.
|
||||
* Recommended for debugging.
|
||||
*/
|
||||
FAILOVER {
|
||||
@Override
|
||||
public Biome fail() {
|
||||
try {
|
||||
return new FailoverBiome();
|
||||
} catch(ParseException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs the action specified by the enum type to occur on failure of terrain generation.
|
||||
* @return Failover biome, if specified, null if not.
|
||||
*/
|
||||
public abstract Biome fail();
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.dfsek.terra.biome.failsafe;
|
||||
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import org.polydev.gaea.math.parsii.tokenizer.ParseException;
|
||||
|
||||
/**
|
||||
* Blank biome to generate in case of a severe config error
|
||||
*/
|
||||
public final class FailoverBiome extends UserDefinedBiome {
|
||||
public FailoverBiome() throws ParseException {
|
||||
super(org.bukkit.block.Biome.PLAINS, new FailoverDecorator(), new FailoverGenerator(), false, "FAILSAFE");
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.dfsek.terra.biome.failsafe;
|
||||
|
||||
import com.dfsek.terra.generation.UserDefinedDecorator;
|
||||
import org.polydev.gaea.math.ProbabilityCollection;
|
||||
import org.polydev.gaea.tree.Tree;
|
||||
import org.polydev.gaea.world.Flora;
|
||||
|
||||
public final class FailoverDecorator extends UserDefinedDecorator {
|
||||
public FailoverDecorator() {
|
||||
super(new ProbabilityCollection<>(), new ProbabilityCollection<>(), 0, 0, 0);
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.dfsek.terra.biome.failsafe;
|
||||
|
||||
import com.dfsek.terra.generation.UserDefinedGenerator;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.polydev.gaea.math.parsii.eval.Variable;
|
||||
import org.polydev.gaea.math.parsii.tokenizer.ParseException;
|
||||
import org.polydev.gaea.world.palette.Palette;
|
||||
import org.polydev.gaea.world.palette.RandomPalette;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public final class FailoverGenerator extends UserDefinedGenerator {
|
||||
private static final TreeMap<Integer, Palette<BlockData>> palette = new TreeMap<>();
|
||||
static {
|
||||
palette.put(255, new RandomPalette<BlockData>(new Random(2403)).add(Material.STONE.createBlockData(), 1));
|
||||
}
|
||||
public FailoverGenerator() throws ParseException {
|
||||
super("0", Collections.emptyList(), palette);
|
||||
}
|
||||
}
|
@ -19,7 +19,13 @@ public class LoadCommand extends PlayerCommand implements DebugCommand {
|
||||
@Override
|
||||
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
try {
|
||||
GaeaStructure.Rotation r = GaeaStructure.Rotation.fromDegrees(Integer.parseInt(args[1]));
|
||||
GaeaStructure.Rotation r;
|
||||
try {
|
||||
r =GaeaStructure.Rotation.fromDegrees(Integer.parseInt(args[1]));
|
||||
} catch(NumberFormatException e) {
|
||||
LangUtil.send("command.structure.invalid-rotation", sender, args[1]);
|
||||
return true;
|
||||
}
|
||||
GaeaStructure struc = GaeaStructure.load(new File(Terra.getInstance().getDataFolder() + File.separator + "export" + File.separator + "structures", args[0] + ".tstructure"));
|
||||
if("true".equals(args[2])) struc.paste(sender.getLocation(), r);
|
||||
else struc.paste(sender.getLocation(), sender.getLocation().getChunk(), r);
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.dfsek.terra.config.base;
|
||||
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.biome.failsafe.FailType;
|
||||
import com.dfsek.terra.config.exception.ConfigException;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -14,12 +15,14 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public final class ConfigUtil {
|
||||
public static boolean debug;
|
||||
public static long dataSave; // Period of population data saving, in ticks.
|
||||
public static boolean masterDisableCaves;
|
||||
public static FailType failType;
|
||||
public static void loadConfig(JavaPlugin main) {
|
||||
main.saveDefaultConfig();
|
||||
main.reloadConfig();
|
||||
@ -30,6 +33,13 @@ public final class ConfigUtil {
|
||||
dataSave = Duration.parse(Objects.requireNonNull(config.getString("data-save", "PT6M"))).toMillis()/20L;
|
||||
masterDisableCaves = config.getBoolean("master-disable.caves", false);
|
||||
|
||||
String fail = config.getString("fail-type", "SHUTDOWN");
|
||||
try {
|
||||
failType = FailType.valueOf(fail);
|
||||
} catch(IllegalArgumentException e) {
|
||||
LangUtil.log("config.invalid-failover", Level.SEVERE, fail);
|
||||
}
|
||||
|
||||
Logger logger = main.getLogger();
|
||||
logger.info("Loading config values");
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
package com.dfsek.terra.image;
|
||||
package com.dfsek.terra.debug.gui;
|
||||
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.generation.TerraChunkGenerator;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.image.ImageLoader;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
@ -1,4 +1,4 @@
|
||||
package com.dfsek.terra.image;
|
||||
package com.dfsek.terra.debug.gui;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
@ -62,10 +62,12 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
|
||||
|
||||
@Override
|
||||
public ChunkData generateBase(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, FastNoise fastNoise) {
|
||||
if(needsLoad) load(world);
|
||||
if(needsLoad) load(world); // Load population data for world.
|
||||
StructureSpawnRequirement.putNoise(world, fastNoise); // Assign noise to world to be used for structures.
|
||||
ChunkData chunk = createChunkData(world);
|
||||
ConfigPack config = TerraWorld.getWorld(world).getConfig();
|
||||
TerraWorld tw = TerraWorld.getWorld(world);
|
||||
if(!tw.isSafe()) return chunk;
|
||||
ConfigPack config = tw.getConfig();
|
||||
int xOrig = (chunkX << 4);
|
||||
int zOrig = (chunkZ << 4);
|
||||
for(byte x = 0; x < 16; x++) {
|
||||
|
@ -4,7 +4,7 @@ import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.biome.BiomeZone;
|
||||
import com.dfsek.terra.biome.TerraBiomeGrid;
|
||||
import com.dfsek.terra.config.base.ConfigUtil;
|
||||
import com.dfsek.terra.config.base.WorldConfig;
|
||||
import com.dfsek.terra.debug.gui.DebugGUI;
|
||||
import org.bukkit.World;
|
||||
import org.polydev.gaea.biome.NormalizationUtil;
|
||||
|
||||
|
@ -31,7 +31,9 @@ public class CavePopulator extends BlockPopulator {
|
||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
||||
if(ConfigUtil.masterDisableCaves) return;
|
||||
try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("CaveTime")) {
|
||||
ConfigPack config = TerraWorld.getWorld(world).getConfig();
|
||||
TerraWorld tw = TerraWorld.getWorld(world);
|
||||
if(!tw.isSafe()) return;
|
||||
ConfigPack config = tw.getConfig();
|
||||
|
||||
for(CarverConfig c : config.getCarvers().values()) {
|
||||
Map<Location, Material> shiftCandidate = new HashMap<>();
|
||||
|
@ -23,6 +23,7 @@ public class FloraPopulator extends GaeaBlockPopulator {
|
||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
||||
try (ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("FloraTime")) {
|
||||
TerraWorld tw = TerraWorld.getWorld(world);
|
||||
if(!tw.isSafe()) return;
|
||||
TerraBiomeGrid grid = tw.getGrid();
|
||||
ConfigPack config = tw.getConfig();
|
||||
for(int x = 0; x < 16; x++) {
|
||||
|
@ -21,7 +21,9 @@ public class OrePopulator extends GaeaBlockPopulator {
|
||||
@Override
|
||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
||||
try (ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("OreTime")) {
|
||||
ConfigPack config = TerraWorld.getWorld(world).getConfig();
|
||||
TerraWorld tw = TerraWorld.getWorld(world);
|
||||
if(!tw.isSafe()) return;
|
||||
ConfigPack config = tw.getConfig();
|
||||
Biome b = TerraWorld.getWorld(world).getGrid().getBiome((chunk.getX() << 4)+8, (chunk.getZ() << 4) + 8, GenerationPhase.POPULATE);
|
||||
for(Map.Entry<OreConfig, Range> e : config.getBiome((UserDefinedBiome) b).getOres().getOres().entrySet()) {
|
||||
int num = e.getValue().get(random);
|
||||
|
@ -3,6 +3,7 @@ package com.dfsek.terra.population;
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.biome.TerraBiomeGrid;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.base.ConfigUtil;
|
||||
import com.dfsek.terra.util.DataUtil;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -45,6 +46,7 @@ public class SnowPopulator extends GaeaBlockPopulator {
|
||||
int origX = chunk.getX() << 4;
|
||||
int origZ = chunk.getZ() << 4;
|
||||
TerraWorld w = TerraWorld.getWorld(world);
|
||||
if(!w.isSafe()) return;
|
||||
TerraBiomeGrid g = w.getGrid();
|
||||
for(int x = 0; x < 16; x++) {
|
||||
for(int z = 0; z < 16; z++) {
|
||||
|
@ -27,6 +27,7 @@ public class StructurePopulator extends BlockPopulator {
|
||||
int cx = (chunk.getX() << 4);
|
||||
int cz = (chunk.getZ() << 4);
|
||||
TerraWorld tw = TerraWorld.getWorld(world);
|
||||
if(!tw.isSafe()) return;
|
||||
TerraBiomeGrid grid = tw.getGrid();
|
||||
ConfigPack config = tw.getConfig();
|
||||
UserDefinedBiome b = (UserDefinedBiome) grid.getBiome(cx+ 8, cz + 8, GenerationPhase.POPULATE);
|
||||
|
@ -5,6 +5,7 @@ import com.dfsek.terra.TerraProfiler;
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.biome.TerraBiomeGrid;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.base.WorldConfig;
|
||||
import com.dfsek.terra.generation.UserDefinedDecorator;
|
||||
import org.bukkit.Chunk;
|
||||
@ -29,6 +30,7 @@ public class TreePopulator extends GaeaBlockPopulator {
|
||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
||||
try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("TreeGenTime")) {
|
||||
TerraWorld tw = TerraWorld.getWorld(world);
|
||||
if(!tw.isSafe()) return;
|
||||
TerraBiomeGrid grid = tw.getGrid();;
|
||||
int x = random.nextInt(16);
|
||||
int z = random.nextInt(16);
|
||||
|
@ -1,5 +1,6 @@
|
||||
debug: false
|
||||
data-save: PT6M
|
||||
language: "en_us"
|
||||
fail-type: SHUTDOWN
|
||||
master-disable:
|
||||
caves: false
|
@ -78,6 +78,7 @@ command:
|
||||
- "export - Export your current WorldEdit selection as a Terra structure."
|
||||
- "load - Load a Terra structure"
|
||||
invalid-radius: "Invalid radius: \"%s\""
|
||||
invalid-rotation: "Invalid rotation: \"%s\""
|
||||
invalid: "Invalid Structure ID: \"%s\""
|
||||
export: "Saved structure to \"%s\""
|
||||
world-config:
|
||||
@ -92,6 +93,7 @@ config:
|
||||
loaded: "Loaded %1$s from file %2$s"
|
||||
loaded-all: "Loaded %1$s %2$s(s) in %3$sms."
|
||||
error:
|
||||
invalid-failover: "Invalid failover type: \"%s\""
|
||||
duplicate: "Duplicate ID found in file: %s"
|
||||
file:
|
||||
- "Configuration error for Terra object. File: %1$s"
|
||||
|
Loading…
x
Reference in New Issue
Block a user