Added config for biomes

This commit is contained in:
Aleksey 2020-09-22 17:10:04 +03:00
parent 41e0d1e42a
commit d382a965e9
10 changed files with 322 additions and 267 deletions

View file

@ -1,37 +0,0 @@
package ru.betterend.config;
import com.google.gson.JsonObject;
public class ClientConfig extends Config {
private static ClientConfig instance;
public static ClientConfig get() {
if (instance == null) {
instance = new ClientConfig();
}
return instance;
}
private ClientConfig() {
JsonObject config = ConfigWriter.load();
if (config.size() > 0) {
KEEPER.fromJson(config);
} else {
ConfigWriter.save(KEEPER.toJson());
}
}
public void reloadFromDisk() {
JsonObject config = ConfigWriter.load();
if (config.size() > 0) {
KEEPER.fromJson(config);
}
}
@Override
public void saveChanges() {
ConfigWriter.save(KEEPER.toJson());
}
}

View file

@ -5,29 +5,29 @@ import ru.betterend.config.ConfigKeeper.*;
public abstract class Config { public abstract class Config {
protected final static ConfigKeeper KEEPER = ConfigKeeper.getInstance(); protected final ConfigKeeper configKeeper = new ConfigKeeper();
public abstract void saveChanges(); public abstract void saveChanges();
public <E extends Entry<?>> E getEntry(String key) { public <E extends Entry<?>> E getEntry(String key) {
return KEEPER.getEntry(key); return this.configKeeper.getEntry(key);
} }
public <T> T getDefault(String key) { public <T> T getDefault(String key) {
Entry<T> entry = KEEPER.getEntry(key); Entry<T> entry = configKeeper.getEntry(key);
return entry != null ? entry.getDefault() : null; return entry != null ? entry.getDefault() : null;
} }
public String getString(String key) { public String getString(String key) {
String str = KEEPER.getValue(key); String str = configKeeper.getValue(key);
return str != null ? str : ""; return str != null ? str : "";
} }
public boolean setString(String key, String value) { public boolean setString(String key, String value) {
try { try {
StringEntry entry = KEEPER.getEntry(key); StringEntry entry = configKeeper.getEntry(key);
entry.setValue(value); entry.setValue(value);
KEEPER.set(key, entry); this.configKeeper.set(key, entry);
return true; return true;
} catch (NullPointerException ex) { } catch (NullPointerException ex) {
@ -38,15 +38,15 @@ public abstract class Config {
} }
public int getInt(String key) { public int getInt(String key) {
Integer val = KEEPER.getValue(key); Integer val = configKeeper.getValue(key);
return val != null ? val : 0; return val != null ? val : 0;
} }
public boolean setInt(String key, int value) { public boolean setInt(String key, int value) {
try { try {
IntegerEntry entry = KEEPER.getEntry(key); IntegerEntry entry = configKeeper.getEntry(key);
entry.setValue(value); entry.setValue(value);
KEEPER.set(key, entry); this.configKeeper.set(key, entry);
return true; return true;
} catch (NullPointerException ex) { } catch (NullPointerException ex) {
@ -58,9 +58,9 @@ public abstract class Config {
public <T extends Comparable<T>> boolean setRanged(String key, T value) { public <T extends Comparable<T>> boolean setRanged(String key, T value) {
try { try {
RangeEntry<T> entry = KEEPER.getEntry(key); RangeEntry<T> entry = configKeeper.getEntry(key);
entry.setValue(value); entry.setValue(value);
KEEPER.set(key, entry); this.configKeeper.set(key, entry);
return true; return true;
} catch (NullPointerException | ClassCastException ex) { } catch (NullPointerException | ClassCastException ex) {
@ -71,15 +71,15 @@ public abstract class Config {
} }
public float getFloat(String key) { public float getFloat(String key) {
Float val = KEEPER.getValue(key); Float val = configKeeper.getValue(key);
return val != null ? val : 0.0F; return val != null ? val : 0.0F;
} }
public boolean setFloat(String key, float value) { public boolean setFloat(String key, float value) {
try { try {
FloatEntry entry = KEEPER.getEntry(key); FloatEntry entry = configKeeper.getEntry(key);
entry.setValue(value); entry.setValue(value);
KEEPER.set(key, entry); this.configKeeper.set(key, entry);
return true; return true;
} catch (NullPointerException ex) { } catch (NullPointerException ex) {
@ -90,15 +90,15 @@ public abstract class Config {
} }
public boolean getBoolean(String key) { public boolean getBoolean(String key) {
Boolean val = KEEPER.getValue(key); Boolean val = configKeeper.getValue(key);
return val != null ? val : false; return val != null ? val : false;
} }
public boolean setBoolean(String key, boolean value) { public boolean setBoolean(String key, boolean value) {
try { try {
BooleanEntry entry = KEEPER.getEntry(key); BooleanEntry entry = configKeeper.getEntry(key);
entry.setValue(value); entry.setValue(value);
KEEPER.set(key, entry); this.configKeeper.set(key, entry);
return true; return true;
} catch (NullPointerException ex) { } catch (NullPointerException ex) {

View file

@ -13,48 +13,9 @@ import ru.betterend.BetterEnd;
public final class ConfigKeeper { public final class ConfigKeeper {
private static ConfigKeeper instance;
public static ConfigKeeper getInstance() {
if (instance == null) {
instance = new ConfigKeeper();
}
return instance;
}
private Map<String, Entry<?>> configEntries = new HashMap<>(); private Map<String, Entry<?>> configEntries = new HashMap<>();
private ConfigKeeper() {} public JsonElement toJson(JsonObject jsonObject) {
@SuppressWarnings("unchecked")
public <E extends Entry<?>> E getEntry(String key) {
Entry<?> entry = this.configEntries.get(key);
if (entry == null) {
BetterEnd.LOGGER.warning(String.format("Entry '%s' doesn't exists.", key));
return null;
}
return (E) entry;
}
public <T> T getValue(String key) {
Entry<T> entry = this.getEntry(key);
if (entry == null) {
BetterEnd.LOGGER.warning(String.format("Empty value will be returned.", key));
return null;
}
return entry.getValue();
}
public void set(String key, Entry<?> entry) {
configEntries.put(key, entry);
}
public <T extends Entry<?>> void registerEntry(String key, T entry) {
configEntries.put(key, entry);
}
public JsonElement toJson() {
JsonObject jsonObject = new JsonObject();
for (String param : configEntries.keySet()) { for (String param : configEntries.keySet()) {
jsonObject.addProperty(param, configEntries.get(param).asString()); jsonObject.addProperty(param, configEntries.get(param).asString());
} }
@ -71,6 +32,33 @@ public final class ConfigKeeper {
} }
} }
@SuppressWarnings("unchecked")
public <E extends Entry<?>> E getEntry(String key) {
Entry<?> entry = this.configEntries.get(key);
if (entry == null) {
BetterEnd.LOGGER.warning(String.format("Entry '%s' doesn't exists.", key));
return null;
}
return (E) entry;
}
public <T> T getValue(String key) {
Entry<T> entry = this.getEntry(key);
if (entry == null) {
BetterEnd.LOGGER.warning("Empty value will be returned.");
return null;
}
return entry.getValue();
}
public void set(String key, Entry<?> entry) {
configEntries.put(key, entry);
}
public <T extends Entry<?>> void registerEntry(String key, T entry) {
configEntries.put(key, entry);
}
public static class BooleanEntry extends Entry<Boolean> { public static class BooleanEntry extends Entry<Boolean> {
public BooleanEntry(Boolean defaultValue, Consumer<Boolean> consumer, Supplier<Boolean> supplier) { public BooleanEntry(Boolean defaultValue, Consumer<Boolean> consumer, Supplier<Boolean> supplier) {
@ -94,12 +82,12 @@ public final class ConfigKeeper {
@Override @Override
public String asString() { public String asString() {
return getValue() ? "true" : "false"; return this.getValue() ? "true" : "false";
} }
@Override @Override
public void fromString(String value) { public void fromString(String value) {
setValue(value.equals("true") ? true : false); this.setValue(value.equals("true") ? true : false);
} }
} }
@ -132,7 +120,7 @@ public final class ConfigKeeper {
@Override @Override
public void fromString(String value) { public void fromString(String value) {
setValue(Float.valueOf(value)); this.setValue(Float.valueOf(value));
} }
} }
@ -155,7 +143,7 @@ public final class ConfigKeeper {
@Override @Override
public void fromString(String value) { public void fromString(String value) {
setValue(Float.valueOf(value)); this.setValue(Float.valueOf(value));
} }
@Override @Override
@ -193,7 +181,7 @@ public final class ConfigKeeper {
@Override @Override
public void fromString(String value) { public void fromString(String value) {
setValue(Integer.valueOf(value)); this.setValue(Integer.valueOf(value));
} }
} }
@ -216,7 +204,7 @@ public final class ConfigKeeper {
@Override @Override
public void fromString(String value) { public void fromString(String value) {
setValue(Integer.valueOf(value)); this.setValue(Integer.valueOf(value));
} }
@Override @Override
@ -254,7 +242,7 @@ public final class ConfigKeeper {
@Override @Override
public void fromString(String value) { public void fromString(String value) {
setValue(value); this.setValue(value);
} }
} }

View file

@ -13,24 +13,51 @@ import ru.betterend.util.JsonFactory;
public class ConfigWriter { public class ConfigWriter {
private final static FabricLoader fabricLoader = FabricLoader.getInstance(); private final static Path GAME_CONFIG_DIR = FabricLoader.getInstance().getConfigDir();
private final static Path GAME_CONFIG_DIR = fabricLoader.getConfigDir(); public final static File MOD_CONFIG_DIR = new File(GAME_CONFIG_DIR.toFile(), BetterEnd.MOD_ID);
private final static File MOD_CONFIG_DIR = new File(GAME_CONFIG_DIR.toFile(), BetterEnd.MOD_ID); private final static File MAIN_CONFIG_FILE = new File(MOD_CONFIG_DIR, "settings.json");
private final static File CONFIG_FILE = new File(MOD_CONFIG_DIR, "settings.json");
private static JsonObject configObject; private static JsonObject mainConfig;
private ConfigWriter() {} private JsonObject configObject;
private File configFile;
public static JsonObject load() { public JsonObject loadConfig(File configFile) {
this.configFile = configFile;
if (configObject == null) { if (configObject == null) {
configObject = JsonFactory.getJsonObject(CONFIG_FILE); configObject = load(configFile);
} }
return configObject; return configObject;
} }
public void saveConfig() {
if (configFile == null || configObject == null) {
return;
}
save(configFile, configObject);
}
public static JsonObject load() {
if (mainConfig == null) {
mainConfig = load(MAIN_CONFIG_FILE);
}
return mainConfig;
}
public static JsonObject load(File configFile) {
return JsonFactory.getJsonObject(configFile);
}
public static void save() {
save(MAIN_CONFIG_FILE, mainConfig);
}
public static void save(JsonElement config) { public static void save(JsonElement config) {
JsonFactory.storeJson(CONFIG_FILE, config); save(MAIN_CONFIG_FILE, config);
}
public static void save(File configFile, JsonElement config) {
JsonFactory.storeJson(configFile, config);
} }
} }

View file

@ -0,0 +1,34 @@
package ru.betterend.config;
import com.google.gson.JsonObject;
public class MainConfig extends Config {
private static MainConfig instance;
public static MainConfig getInstance() {
if (instance == null) {
instance = new MainConfig();
}
return instance;
}
private MainConfig() {
//TODO: Need to register config params in the Keeper
JsonObject config = ConfigWriter.load();
if (config.size() > 0) {
this.configKeeper.fromJson(config);
} else {
this.configKeeper.toJson(config);
ConfigWriter.save();
}
}
@Override
public void saveChanges() {
this.configKeeper.toJson(ConfigWriter.load());
ConfigWriter.save();
}
}

View file

@ -1,104 +1,104 @@
package ru.betterend; package ru.betterend.util;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Random; import java.util.Random;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.state.property.Property; import net.minecraft.state.property.Property;
import net.minecraft.util.BlockMirror; import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation; import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3i; import net.minecraft.util.math.Vec3i;
import net.minecraft.world.WorldAccess; import net.minecraft.world.WorldAccess;
public class BlocksHelper { public class BlocksHelper {
public static final int FLAG_UPDATE_BLOCK = 1; public static final int FLAG_UPDATE_BLOCK = 1;
public static final int FLAG_SEND_CLIENT_CHANGES = 2; public static final int FLAG_SEND_CLIENT_CHANGES = 2;
public static final int FLAG_NO_RERENDER = 4; public static final int FLAG_NO_RERENDER = 4;
public static final int FORSE_RERENDER = 8; public static final int FORSE_RERENDER = 8;
public static final int FLAG_IGNORE_OBSERVERS = 16; public static final int FLAG_IGNORE_OBSERVERS = 16;
public static final int SET_SILENT = FLAG_UPDATE_BLOCK | FLAG_IGNORE_OBSERVERS | FLAG_SEND_CLIENT_CHANGES; public static final int SET_SILENT = FLAG_UPDATE_BLOCK | FLAG_IGNORE_OBSERVERS | FLAG_SEND_CLIENT_CHANGES;
public static final Direction[] HORIZONTAL = new Direction[] { Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST }; public static final Direction[] HORIZONTAL = new Direction[] { Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST };
private static final Vec3i[] OFFSETS = new Vec3i[] { private static final Vec3i[] OFFSETS = new Vec3i[] {
new Vec3i(-1, -1, -1), new Vec3i(-1, -1, 0), new Vec3i(-1, -1, 1), new Vec3i(-1, -1, -1), new Vec3i(-1, -1, 0), new Vec3i(-1, -1, 1),
new Vec3i(-1, 0, -1), new Vec3i(-1, 0, 0), new Vec3i(-1, 0, 1), new Vec3i(-1, 0, -1), new Vec3i(-1, 0, 0), new Vec3i(-1, 0, 1),
new Vec3i(-1, 1, -1), new Vec3i(-1, 1, 0), new Vec3i(-1, 1, 1), new Vec3i(-1, 1, -1), new Vec3i(-1, 1, 0), new Vec3i(-1, 1, 1),
new Vec3i(0, -1, -1), new Vec3i(0, -1, 0), new Vec3i(0, -1, 1), new Vec3i(0, -1, -1), new Vec3i(0, -1, 0), new Vec3i(0, -1, 1),
new Vec3i(0, 0, -1), new Vec3i(0, 0, 0), new Vec3i(0, 0, 1), new Vec3i(0, 0, -1), new Vec3i(0, 0, 0), new Vec3i(0, 0, 1),
new Vec3i(0, 1, -1), new Vec3i(0, 1, 0), new Vec3i(0, 1, 1), new Vec3i(0, 1, -1), new Vec3i(0, 1, 0), new Vec3i(0, 1, 1),
new Vec3i(1, -1, -1), new Vec3i(1, -1, 0), new Vec3i(1, -1, 1), new Vec3i(1, -1, -1), new Vec3i(1, -1, 0), new Vec3i(1, -1, 1),
new Vec3i(1, 0, -1), new Vec3i(1, 0, 0), new Vec3i(1, 0, 1), new Vec3i(1, 0, -1), new Vec3i(1, 0, 0), new Vec3i(1, 0, 1),
new Vec3i(1, 1, -1), new Vec3i(1, 1, 0), new Vec3i(1, 1, 1) new Vec3i(1, 1, -1), new Vec3i(1, 1, 0), new Vec3i(1, 1, 1)
}; };
public static void setWithoutUpdate(WorldAccess world, BlockPos pos, BlockState state) { public static void setWithoutUpdate(WorldAccess world, BlockPos pos, BlockState state) {
world.setBlockState(pos, state, SET_SILENT); world.setBlockState(pos, state, SET_SILENT);
} }
public static int upRay(WorldAccess world, BlockPos pos, int maxDist) { public static int upRay(WorldAccess world, BlockPos pos, int maxDist) {
int length = 0; int length = 0;
for (int j = 1; j < maxDist && (world.isAir(pos.up(j))); j++) for (int j = 1; j < maxDist && (world.isAir(pos.up(j))); j++)
length++; length++;
return length; return length;
} }
public static int downRay(WorldAccess world, BlockPos pos, int maxDist) { public static int downRay(WorldAccess world, BlockPos pos, int maxDist) {
int length = 0; int length = 0;
for (int j = 1; j < maxDist && (world.isAir(pos.down(j))); j++) for (int j = 1; j < maxDist && (world.isAir(pos.down(j))); j++)
length++; length++;
return length; return length;
} }
public static BlockState rotateHorizontal(BlockState state, BlockRotation rotation, Property<Direction> facing) { public static BlockState rotateHorizontal(BlockState state, BlockRotation rotation, Property<Direction> facing) {
return (BlockState) state.with(facing, rotation.rotate((Direction) state.get(facing))); return (BlockState) state.with(facing, rotation.rotate((Direction) state.get(facing)));
} }
public static BlockState mirrorHorizontal(BlockState state, BlockMirror mirror, Property<Direction> facing) { public static BlockState mirrorHorizontal(BlockState state, BlockMirror mirror, Property<Direction> facing) {
return state.rotate(mirror.getRotation((Direction) state.get(facing))); return state.rotate(mirror.getRotation((Direction) state.get(facing)));
} }
public static int getLengthDown(ServerWorld world, BlockPos pos, Block block) { public static int getLengthDown(ServerWorld world, BlockPos pos, Block block) {
int count = 1; int count = 1;
while (world.getBlockState(pos.down(count)).getBlock() == block) while (world.getBlockState(pos.down(count)).getBlock() == block)
count++; count++;
return count; return count;
} }
public static void cover(WorldAccess world, BlockPos center, Block ground, BlockState cover, int radius, Random random) { public static void cover(WorldAccess world, BlockPos center, Block ground, BlockState cover, int radius, Random random) {
HashSet<BlockPos> points = new HashSet<BlockPos>(); HashSet<BlockPos> points = new HashSet<BlockPos>();
HashSet<BlockPos> points2 = new HashSet<BlockPos>(); HashSet<BlockPos> points2 = new HashSet<BlockPos>();
if (world.getBlockState(center).getBlock() == ground) { if (world.getBlockState(center).getBlock() == ground) {
points.add(center); points.add(center);
points2.add(center); points2.add(center);
for (int i = 0; i < radius; i++) { for (int i = 0; i < radius; i++) {
Iterator<BlockPos> iterator = points.iterator(); Iterator<BlockPos> iterator = points.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
BlockPos pos = iterator.next(); BlockPos pos = iterator.next();
for (Vec3i offset : OFFSETS) { for (Vec3i offset : OFFSETS) {
if (random.nextBoolean()) { if (random.nextBoolean()) {
BlockPos pos2 = pos.add(offset); BlockPos pos2 = pos.add(offset);
if (random.nextBoolean() && world.getBlockState(pos2).getBlock() == ground if (random.nextBoolean() && world.getBlockState(pos2).getBlock() == ground
&& !points.contains(pos2)) && !points.contains(pos2))
points2.add(pos2); points2.add(pos2);
} }
} }
} }
points.addAll(points2); points.addAll(points2);
points2.clear(); points2.clear();
} }
Iterator<BlockPos> iterator = points.iterator(); Iterator<BlockPos> iterator = points.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
BlockPos pos = iterator.next(); BlockPos pos = iterator.next();
BlocksHelper.setWithoutUpdate(world, pos, cover); BlocksHelper.setWithoutUpdate(world, pos, cover);
} }
} }
} }
} }

View file

@ -1,51 +1,51 @@
package ru.betterend; package ru.betterend.util;
import java.util.Random; import java.util.Random;
public class MHelper { public class MHelper {
public static final float PI2 = (float) (Math.PI * 2); public static final float PI2 = (float) (Math.PI * 2);
private static final int ALPHA = 255 << 24; private static final int ALPHA = 255 << 24;
public static final Random RANDOM = new Random(); public static final Random RANDOM = new Random();
public static int color(int r, int g, int b) { public static int color(int r, int g, int b) {
return ALPHA | (r << 16) | (g << 8) | b; return ALPHA | (r << 16) | (g << 8) | b;
} }
public static int randRange(int min, int max, Random random) { public static int randRange(int min, int max, Random random) {
return min + random.nextInt(max - min + 1); return min + random.nextInt(max - min + 1);
} }
public static float randRange(float min, float max, Random random) { public static float randRange(float min, float max, Random random) {
return min + random.nextFloat() * (max - min); return min + random.nextFloat() * (max - min);
} }
public static byte setBit(byte source, int pos, boolean value) { public static byte setBit(byte source, int pos, boolean value) {
return value ? setBitTrue(source, pos) : setBitFalse(source, pos); return value ? setBitTrue(source, pos) : setBitFalse(source, pos);
} }
public static byte setBitTrue(byte source, int pos) { public static byte setBitTrue(byte source, int pos) {
source |= 1 << pos; source |= 1 << pos;
return source; return source;
} }
public static byte setBitFalse(byte source, int pos) { public static byte setBitFalse(byte source, int pos) {
source &= ~(1 << pos); source &= ~(1 << pos);
return source; return source;
} }
public static boolean getBit(byte source, int pos) { public static boolean getBit(byte source, int pos) {
return ((source >> pos) & 1) == 1; return ((source >> pos) & 1) == 1;
} }
public static int floor(float x) { public static int floor(float x) {
return x < 0 ? (int) (x - 1) : (int) x; return x < 0 ? (int) (x - 1) : (int) x;
} }
public static float wrap(float x, float side) { public static float wrap(float x, float side) {
return x - floor(x / side) * side; return x - floor(x / side) * side;
} }
public static int floor(double x) { public static int floor(double x) {
return x < 0 ? (int) (x - 1) : (int) x; return x < 0 ? (int) (x - 1) : (int) x;
} }
} }

View file

@ -0,0 +1,43 @@
package ru.betterend.world.biome;
import java.io.File;
import java.nio.file.Path;
import com.google.gson.JsonObject;
import net.minecraft.util.Identifier;
import ru.betterend.config.Config;
import ru.betterend.config.ConfigWriter;
public class BiomeConfig extends Config {
private final static Path BIOME_CONFIG_DIR = ConfigWriter.MOD_CONFIG_DIR.toPath().resolve("biomes");
private EndBiome biome;
private ConfigWriter configWriter;
private File configFile;
public BiomeConfig(EndBiome biome) {
this.biome = biome;
Identifier biomeId = biome.getID();
this.configFile = new File(BIOME_CONFIG_DIR.toFile(), biomeId.getPath());
this.configWriter = new ConfigWriter();
this.registerEntries();
JsonObject config = configWriter.loadConfig(configFile);
if (config.size() > 0) {
this.configKeeper.fromJson(config);
} else {
this.configKeeper.toJson(config);
this.configWriter.saveConfig();
}
}
private void registerEntries() {
//TODO: Need to register config params in the Keeper
}
@Override
public void saveChanges() {
this.configWriter.saveConfig();
}
}

View file

@ -26,7 +26,7 @@ import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.ConfiguredStructureFeature; import net.minecraft.world.gen.feature.ConfiguredStructureFeature;
import net.minecraft.world.gen.surfacebuilder.ConfiguredSurfaceBuilders; import net.minecraft.world.gen.surfacebuilder.ConfiguredSurfaceBuilders;
import ru.betterend.BetterEnd; import ru.betterend.BetterEnd;
import ru.betterend.MHelper; import ru.betterend.util.MHelper;
public class BiomeDefinition public class BiomeDefinition
{ {

View file

@ -4,8 +4,8 @@ import java.util.HashMap;
import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.gen.ChunkRandom; import net.minecraft.world.gen.ChunkRandom;
import ru.betterend.MHelper;
import ru.betterend.noise.OpenSimplexNoise; import ru.betterend.noise.OpenSimplexNoise;
import ru.betterend.util.MHelper;
import ru.betterend.world.biome.EndBiome; import ru.betterend.world.biome.EndBiome;
public class BiomeMap public class BiomeMap