132 lines
5.2 KiB
Java
132 lines
5.2 KiB
Java
package com.hypixel.hytale.server.worldgen.loader.biome;
|
|
|
|
import com.google.gson.JsonElement;
|
|
import com.google.gson.JsonObject;
|
|
import com.hypixel.hytale.procedurallib.condition.IIntCondition;
|
|
import com.hypixel.hytale.procedurallib.json.JsonLoader;
|
|
import com.hypixel.hytale.procedurallib.json.SeedString;
|
|
import com.hypixel.hytale.server.worldgen.SeedStringResource;
|
|
import com.hypixel.hytale.server.worldgen.biome.BiomeInterpolation;
|
|
import com.hypixel.hytale.server.worldgen.loader.context.ZoneFileContext;
|
|
import com.hypixel.hytale.server.worldgen.util.condition.HashSetIntCondition;
|
|
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
|
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
|
import it.unimi.dsi.fastutil.ints.IntIterator;
|
|
import it.unimi.dsi.fastutil.ints.IntSet;
|
|
import java.nio.file.Path;
|
|
import javax.annotation.Nonnull;
|
|
import javax.annotation.Nullable;
|
|
|
|
public class BiomeInterpolationJsonLoader extends JsonLoader<SeedStringResource, BiomeInterpolation> {
|
|
protected final ZoneFileContext zoneFileContext;
|
|
|
|
public BiomeInterpolationJsonLoader(SeedString<SeedStringResource> seed, Path dataFolder, JsonElement json, ZoneFileContext zoneFileContext) {
|
|
super(seed, dataFolder, json);
|
|
this.zoneFileContext = zoneFileContext;
|
|
}
|
|
|
|
public BiomeInterpolation load() {
|
|
int defaultRadius = this.loadDefaultRadius();
|
|
Int2IntMap biomeRadii = this.loadBiomeRadii(defaultRadius);
|
|
return BiomeInterpolation.create(defaultRadius, biomeRadii);
|
|
}
|
|
|
|
protected int loadDefaultRadius() {
|
|
if (!this.has("DefaultRadius")) {
|
|
return 5;
|
|
} else {
|
|
int radius = this.get("DefaultRadius").getAsInt();
|
|
if (radius >= 0 && radius <= 5) {
|
|
return radius;
|
|
} else {
|
|
throw new Error(String.format("Default biome interpolation radius %s lies outside the range 0-5", radius));
|
|
}
|
|
}
|
|
}
|
|
|
|
@Nonnull
|
|
protected Int2IntMap loadBiomeRadii(int maxRadius) {
|
|
if (!this.has("Biomes")) {
|
|
return BiomeInterpolation.EMPTY_MAP;
|
|
} else {
|
|
JsonElement biomes = this.get("Biomes");
|
|
if (!biomes.isJsonArray()) {
|
|
throw new Error("Invalid json-type for Biomes property. Must be an array!");
|
|
} else {
|
|
Int2IntOpenHashMap biomeRadii = new Int2IntOpenHashMap();
|
|
|
|
for (JsonElement entry : biomes.getAsJsonArray()) {
|
|
this.loadBiomeEntry(entry, maxRadius, biomeRadii);
|
|
}
|
|
|
|
return biomeRadii;
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void loadBiomeEntry(@Nonnull JsonElement entry, int defaultRadius, @Nonnull Int2IntMap biomeRadii) {
|
|
if (!entry.isJsonObject()) {
|
|
throw new Error("Invalid json-type for biome entry. Must be an object!");
|
|
} else {
|
|
int radius = loadBiomeRadius(entry.getAsJsonObject(), defaultRadius);
|
|
if (radius != defaultRadius) {
|
|
IIntCondition mask = this.loadBiomeMask(entry.getAsJsonObject());
|
|
addBiomes(mask, radius, biomeRadii);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Nullable
|
|
protected IIntCondition loadBiomeMask(@Nonnull JsonObject entry) {
|
|
if (!entry.has("Mask")) {
|
|
throw new Error(String.format("Missing property %s", "Mask"));
|
|
} else {
|
|
return new BiomeMaskJsonLoader(this.seed, this.dataFolder, entry.get("Mask"), "InterpolationMask", this.zoneFileContext).load();
|
|
}
|
|
}
|
|
|
|
protected static int loadBiomeRadius(@Nonnull JsonObject entry, int maxRadius) {
|
|
if (!entry.has("Radius")) {
|
|
throw new Error(String.format("Missing property %s", "Radius"));
|
|
} else {
|
|
int radius = entry.get("Radius").getAsInt();
|
|
if (radius >= 0 && radius <= maxRadius) {
|
|
return radius;
|
|
} else {
|
|
throw new Error(String.format("Biome interpolation radius %s is outside the range 0-%s", radius, maxRadius));
|
|
}
|
|
}
|
|
}
|
|
|
|
protected static void addBiomes(IIntCondition mask, int radius, @Nonnull Int2IntMap biomeRadii) {
|
|
if (mask instanceof HashSetIntCondition) {
|
|
int radius2 = radius * radius;
|
|
IntSet biomes = ((HashSetIntCondition)mask).getSet();
|
|
IntIterator var5 = biomes.iterator();
|
|
|
|
while (var5.hasNext()) {
|
|
int biome = (Integer)var5.next();
|
|
if (biomeRadii.containsKey(biome)) {
|
|
throw new Error("Duplicate biome detected in interpolation rules");
|
|
}
|
|
|
|
biomeRadii.put(biome, radius2);
|
|
}
|
|
}
|
|
}
|
|
|
|
public interface Constants {
|
|
String KEY_DEFAULT_RADIUS = "DefaultRadius";
|
|
String KEY_RADIUS = "Radius";
|
|
String KEY_BIOMES = "Biomes";
|
|
String KEY_MASK = "Mask";
|
|
String SEED_OFFSET_MASK = "InterpolationMask";
|
|
String ERROR_MISSING_PROPERTY = "Missing property %s";
|
|
String ERROR_INVALID_BIOME_LIST = "Invalid json-type for Biomes property. Must be an array!";
|
|
String ERROR_INVALID_BIOME_ENTRY = "Invalid json-type for biome entry. Must be an object!";
|
|
String ERROR_DUPLICATE_BIOME = "Duplicate biome detected in interpolation rules";
|
|
String ERROR_BIOME_RADIUS = "Biome interpolation radius %s is outside the range 0-%s";
|
|
String ERROR_DEFAULT_RADIUS = "Default biome interpolation radius %s lies outside the range 0-5";
|
|
}
|
|
}
|